// 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;i<address+length;i+=4)
{
m_host_space->write_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<sort_entry> entries(data);
for(int i=0; i<data; i++) {
sort_entry &e = entries[i];
e.val = m_host_space->read_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; i<data; i++)
m_host_space->write_word(cop_sort_lookup + 2*i, entries[i].val);
}