// license:LGPL-2.1+ // copyright-holders:Olivier Galibert, Angelo Salese, David Haywood, Tomasz Slanina // ALL games use this - tilemap DMA (RAM -> private buffer) void raiden2cop_device::dma_tilemap_buffer() { int src = cop_dma_src[cop_dma_mode] << 6; if (src == 0xcfc0) src = 0xd000; // R2, why?? everything else sets the right pointer (it also sets up odd size / dest regs, they probably counteract this) for (int i = 0; i < 0x2800 / 2; i++) { uint16_t tileval = m_host_space->read_word(src); src += 2; m_videoramout_cb(i, tileval, 0xffff); } } // ALL games use this - palette DMA (RAM -> private buffer) void raiden2cop_device::dma_palette_buffer() { int src = cop_dma_src[cop_dma_mode] << 6; for (int i = 0; i < 0x1000 / 2; i++) // todo, use length register { uint16_t palval = m_host_space->read_word(src); src += 2; m_paletteramout_cb(i, palval); //m_palette->set_pen_color(i, pal5bit(palval >> 0), pal5bit(palval >> 5), pal5bit(palval >> 10)); } } // these are typically used to transfer palette data from one RAM buffer to another, applying fade values to it prior to the 0x15 transfer void raiden2cop_device::dma_palette_brightness() { uint32_t src, dst, size, i; /* Apparently all of those are just different DMA channels, brightness effects are done through a RAM table and the pal_brightness_val / mode 0x80 is used by Legionnaire 0x81 is used by SD Gundam and Godzilla 0x82 is used by Zero Team and X Se Dae 0x86 is used by Seibu Cup Soccer 0x87 is used by Denjin Makai TODO: - Denjin Makai mode 4 is totally guessworked. */ //if(dma_trigger != 0x87) //printf("SRC: %08x %08x DST:%08x SIZE:%08x TRIGGER: %08x %02x %02x\n",cop_dma_src[cop_dma_mode] << 6,cop_dma_adr_rel * 0x400,cop_dma_dst[cop_dma_mode] << 6,cop_dma_size[cop_dma_mode] << 5,cop_dma_mode,pal_brightness_val,pal_brightness_mode); src = (cop_dma_src[cop_dma_mode] << 6); dst = (cop_dma_dst[cop_dma_mode] << 6); size = ((cop_dma_size[cop_dma_mode] << 5) - (cop_dma_dst[cop_dma_mode] << 6) + 0x20) / 2; for (i = 0; i < size; i++) { uint16_t pal_val; int r, g, b; int rt, gt, bt; if (pal_brightness_mode == 5) { u16 paldata = m_host_space->read_word(src); if (BIT(paldata, 15)) pal_val = paldata; // fade me not else { u16 targetpaldata = m_host_space->read_word(src + (cop_dma_adr_rel * 0x400)); bt = (targetpaldata & 0x7c00) >> 5; bt = fade_table(bt | (pal_brightness_val ^ 0)); b = (paldata & 0x7c00) >> 5; b = fade_table(b | (pal_brightness_val ^ 0x1f)); pal_val = ((b + bt) & 0x1f) << 10; gt = (targetpaldata & 0x03e0); gt = fade_table(gt | (pal_brightness_val ^ 0)); g = (paldata & 0x03e0); g = fade_table(g | (pal_brightness_val ^ 0x1f)); pal_val |= ((g + gt) & 0x1f) << 5; rt = (targetpaldata & 0x001f) << 5; rt = fade_table(rt | (pal_brightness_val ^ 0)); r = (paldata & 0x001f) << 5; r = fade_table(r | (pal_brightness_val ^ 0x1f)); pal_val |= ((r + rt) & 0x1f); } } else if (pal_brightness_mode == 4) //Denjin Makai & Godzilla { // In mode 4 Denjin Makai seems to swaps endianness between two words, likely that DMA works in dword steps and bit 0. // Godzilla contradicts with this tho, so maybe it's just an address swap for the palette range ... uint16_t targetpaldata = m_host_space->read_word((src + (cop_dma_adr_rel * 0x400))); uint16_t paldata = m_host_space->read_word(src); bt = (targetpaldata & 0x7c00) >> 10; b = (paldata & 0x7c00) >> 10; gt = (targetpaldata & 0x03e0) >> 5; g = (paldata & 0x03e0) >> 5; rt = (targetpaldata & 0x001f) >> 0; r = (paldata & 0x001f) >> 0; // TODO: presumably any brightness value that isn't 0x0000-0x000f has no effect here if (pal_brightness_val == 0x10) pal_val = bt << 10 | gt << 5 | rt << 0; else if (pal_brightness_val == 0xffff) // level transitions pal_val = bt << 10 | gt << 5 | rt << 0; else { bt = fade_table(bt << 5 | ((pal_brightness_val * 2) ^ 0)); b = fade_table(b << 5 | ((pal_brightness_val * 2) ^ 0x1f)); pal_val = ((b + bt) & 0x1f) << 10; gt = fade_table(gt << 5 | ((pal_brightness_val * 2) ^ 0)); g = fade_table(g << 5 | ((pal_brightness_val * 2) ^ 0x1f)); pal_val |= ((g + gt) & 0x1f) << 5; rt = fade_table(rt << 5 | ((pal_brightness_val * 2) ^ 0)); r = fade_table(r << 5 | ((pal_brightness_val * 2) ^ 0x1f)); pal_val |= ((r + rt) & 0x1f); } } else { printf("Warning: palette DMA used with mode %02x!\n", pal_brightness_mode); pal_val = m_host_space->read_word(src); } m_host_space->write_word(dst, pal_val); src += 2; dst += 2; } } void raiden2cop_device::dma_fill() { uint32_t length, address; int i; if (cop_dma_dst[cop_dma_mode] != 0x0000) // Invalid? return; address = (cop_dma_src[cop_dma_mode] << 6); length = (cop_dma_size[cop_dma_mode] + 1) << 5; //printf("%08x %08x\n",address,length); for (i = address; i < address + length; i += 4) m_host_space->write_dword(i, (cop_dma_v1) | (cop_dma_v2 << 16)); /* uint32_t length, address; int i; if(cop_dma_dst[cop_dma_mode] != 0x0000) // Invalid? return; address = (cop_dma_src[cop_dma_mode] << 6); length = (cop_dma_size[cop_dma_mode]+1) << 5; //printf("%08x %08x\n",address,length); for (i=address;iwrite_dword(i, m_fill_val); } */ } void raiden2cop_device::dma_zsorting(uint16_t data) { struct sort_entry { int32_t sorting_key; uint16_t val; }; std::vector entries(data); for(int i=0; iread_word(cop_sort_lookup + 2*i); e.sorting_key = m_host_space->read_dword(cop_sort_ram_addr + e.val); } switch(cop_sort_param) { case 2: std::stable_sort(entries.begin(), entries.end(), [](const auto &a, const auto &b){ return a.sorting_key > b.sorting_key; }); break; case 1: std::stable_sort(entries.begin(), entries.end(), [](const auto &a, const auto &b){ return a.sorting_key < b.sorting_key; }); break; } for(int i=0; iwrite_word(cop_sort_lookup + 2*i, entries[i].val); }