mindset: Hackless graphics copro pass [O. Galibert]

This commit is contained in:
Olivier Galibert 2019-06-11 14:02:38 +02:00
parent 1f9e370b8e
commit 8a1d3ce2c7

View File

@ -26,6 +26,8 @@ protected:
memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_gcos;
u16 m_dispctrl;
static u16 gco_blend_0(u16, u16);
static u16 gco_blend_1(u16, u16);
static u16 gco_blend_2(u16, u16);
@ -43,7 +45,12 @@ protected:
void maincpu_mem(address_map &map);
void maincpu_io(address_map &map);
void display_mode();
void blit(u16 packet_seg, u16 packet_adr);
void gco_w(u16 data);
u16 dispctrl_r();
void dispctrl_w(u16 data);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
@ -71,6 +78,17 @@ void mindset_state::machine_reset()
{
}
u16 mindset_state::dispctrl_r()
{
return m_dispctrl;
}
void mindset_state::dispctrl_w(u16 data)
{
m_dispctrl = data;
// logerror("display control %04x\n", data);
}
u32 mindset_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
static const u32 pal[4] = { 0x000000, 0x555555, 0xaaaaaa, 0xffffff };
@ -179,18 +197,8 @@ u16 (*const mindset_state::gco_blend[8])(u16, u16) = {
};
static bool done = false;
void mindset_state::gco_w(u16 data)
void mindset_state::blit(u16 packet_seg, u16 packet_adr)
{
u16 packet_seg = sw(m_gcos->read_word(0xbfd7a));
u16 packet_adr = sw(m_gcos->read_word(0xbfd78));
// Low byte could be packet count, high byte mode
u16 global_mode = sw(m_gcos->read_word(0xbfd76));
logerror("GCO: start %04x:%04x mode %04x (%05x)\n", packet_seg, packet_adr, global_mode, m_maincpu->pc());
u16 mode = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 0) & 0xffff)));
u16 src_adr = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 2) & 0xffff)));
u16 src_sft = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 4) & 0xffff)));
@ -198,85 +206,131 @@ void mindset_state::gco_w(u16 data)
u16 dst_sft = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 8) & 0xffff)));
u16 width = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 10) & 0xffff)));
u16 height = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 12) & 0xffff)));
u16 sx = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 14) & 0xffff)));
u16 sy = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 16) & 0xffff)));
u16 v9 = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 18) & 0xffff)));
u16 sy = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 14) & 0xffff)));
u16 dy = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 16) & 0xffff)));
u16 rmask = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 18) & 0xffff)));
u16 src_seg = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 20) & 0xffff)));
u16 dst_seg = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 22) & 0xffff)));
u16 mask = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 24) & 0xffff)));
u16 vd = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 26) & 0xffff)));
u16 wmask = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 24) & 0xffff)));
u16 kmask = sw(m_gcos->read_word((packet_seg << 4) + ((packet_adr + 26) & 0xffff)));
logerror("GCO: p src %04x:%04x.%x dst %04x:%04x.%x sz %xx%x step %x:%x mask %04x:%04x k %x:%x mode %c%c%c%d%c%d%c%c%c\n", src_seg, src_adr, src_sft, dst_seg, dst_adr, dst_sft, width, height, sy, dy, rmask, wmask, (kmask >> 8) & 15, kmask & 15,
mode & 0x80 ? 'k' : '-',
mode & 0x40 ? 't' : 'o',
mode & 0x20 ? 'x' : '-',
(mode >> 2) & 7,
mode & 0x4000 ? 'f' : '-',
(mode >> 11) & 3,
mode & 0x400 ? 'n' : '-',
mode & 0x200 ? 'p' : '-',
mode & 0x100 ? 'i' : 'f');
logerror("GCO: p src %04x:%04x.%x dst %04x:%04x.%x sz %xx%x step %x:%x mode %04x mask %04x\n", src_seg, src_adr, src_sft, dst_seg, dst_adr, dst_sft, width, height, sx, sy, mode, mask);
// k = detect collision (unimplemented)
// t/o = transparent/opaque
// x = go right to left (unimplemented)
// f = fast (no idea what it means)
// n = invert collision flag (unimplemented)
// p = pattern fill (unimplemented, use by fill_dest_buffer)
// i/f = increment source / don't (unimplemented, compare with p?, used by blt_copy_word)
logerror("GCO: p 9:%04x d:%04x\n", v9, vd);
auto blend = gco_blend[(mode >> 2) & 7];
if(global_mode == 0x0101) {
auto blend = gco_blend[(mode >> 2) & 7];
u16 wmask = ((mask << 16) | mask) >> (15 - dst_sft);
u16 swmask, mwmask, ewmask;
if(dst_sft >= width) {
swmask = msk(dst_sft+1) & ~msk(dst_sft - width + 1) & wmask;
mwmask = 0;
ewmask = 0;
} else {
swmask = msk(dst_sft+1) & wmask;
mwmask = wmask;
ewmask = (~msk((dst_sft - width + 1) & 15)) & wmask;
}
u16 nw = ((width + (15 - dst_sft)) + 15) >> 4;
logerror("GCO: m %04x %04x %04x nw %x\n", swmask, mwmask, ewmask, nw);
if(!done)
for(u32 y=0; y<height; y++) {
u16 src_cadr = src_adr;
u16 dst_cadr = dst_adr;
u16 cmask = swmask;
u16 nw1 = nw;
u32 srcs = sw(m_gcos->read_word((src_seg << 4) + src_cadr));
src_cadr += sx;
do {
srcs = (srcs << 16) | sw(m_gcos->read_word((src_seg << 4) + src_cadr));
u16 src = srcs >> (src_sft + 1);
u16 dst = sw(m_gcos->read_word((dst_seg << 4) + dst_cadr));
u16 res = (dst & ~cmask) | (blend(src, dst) & cmask);
logerror("GCO: %04x * %04x = %04x @ %04x\n", src, dst, res, cmask);
// Gross hack number one
if(mode == 0x0140 && dst == 0xffff)
res = 0xffff;
m_gcos->write_word((dst_seg << 4) + dst_cadr, sw(res));
src_cadr += sx;
dst_cadr += sx;
nw1 --;
cmask = nw1 == 1 ? ewmask : mwmask;
} while(nw1);
src_adr += sy;
dst_adr += sy;
}
// Gross hack number two
if(!done)
if(sx == 0x50 && sy == 8) {
for(u32 i=0; i<16; i+=2)
m_gcos->write_word(0x1040 + i, m_gcos->read_word(0xf8000+0x6106 + i));
done = true;
}
u16 awmask = ((wmask << 16) | wmask) >> (15 - dst_sft);
u16 swmask, mwmask, ewmask;
if(dst_sft >= width) {
swmask = msk(dst_sft+1) & ~msk(dst_sft - width + 1);
mwmask = 0xffff;
ewmask = swmask;
} else {
swmask = msk(dst_sft+1);
mwmask = 0xffff;
ewmask = ~msk((dst_sft - width + 1) & 15);
}
// 100 = done, 400 = collision?
swmask &= awmask;
mwmask &= awmask;
ewmask &= awmask;
u16 nw = ((width + (15 - dst_sft)) + 15) >> 4;
for(u32 y=0; y<height; y++) {
u16 src_cadr = src_adr;
u16 dst_cadr = dst_adr;
u16 cmask = swmask;
u16 nw1 = nw;
u32 srcs = sw(m_gcos->read_word((src_seg << 4) + src_cadr));
src_cadr += 2;
do {
srcs = (srcs << 16) | sw(m_gcos->read_word((src_seg << 4) + src_cadr));
u16 src = (srcs >> (src_sft + 1)) & rmask;
u16 dst = sw(m_gcos->read_word((dst_seg << 4) + dst_cadr));
u16 res = blend(src, dst);
if(mode & 0x40) {
u16 tmask;
switch((mode >> 10) & 3) {
case 0:
tmask = dst;
break;
case 1:
tmask = ((dst & 0xaaaa) >> 1) | (dst & 0x5555);
tmask = tmask * 0x3;
break;
case 2:
tmask = ((dst & 0xcccc) >> 2) | (dst & 0x3333);
tmask = ((dst & 0x2222) >> 1) | (dst & 0x1111);
tmask = tmask * 0xf;
break;
case 3:
tmask = ((dst & 0xf0f0) >> 4) | (dst & 0x0f0f);
tmask = ((dst & 0x0c0c) >> 2) | (dst & 0x0303);
tmask = ((dst & 0x0202) >> 1) | (dst & 0x0101);
tmask = tmask * 0xff;
break;
}
cmask &= ~tmask;
}
res = (dst & ~cmask) | (res & cmask);
logerror("GCO: %04x * %04x = %04x @ %04x\n", src, dst, res, cmask);
m_gcos->write_word((dst_seg << 4) + dst_cadr, sw(res));
src_cadr += 2;
dst_cadr += 2;
nw1 --;
cmask = nw1 == 1 ? ewmask : mwmask;
} while(nw1);
src_adr += sy;
dst_adr += dy;
}
}
void mindset_state::gco_w(u16 data)
{
u16 packet_seg = sw(m_gcos->read_word(0xbfd7a));
u16 packet_adr = sw(m_gcos->read_word(0xbfd78));
u16 global_mode = sw(m_gcos->read_word(0xbfd76));
logerror("GCO: start %04x:%04x mode %04x (%05x)\n", packet_seg, packet_adr, global_mode, m_maincpu->pc());
switch(global_mode) {
case 0x0101:
blit(packet_seg, packet_adr);
break;
}
// 100 = done, 200 = done too???, 400 = collision?
m_gcos->write_word(0xbfd74, m_gcos->read_word(0xbfd74) | 0x0700);
// Can trigger an irq, on mode & 2 (or is it 200?) (0x40 on 8282, ack on 0x41)
}
void mindset_state::maincpu_mem(address_map &map)
{
map(0x00000, 0x07fff).ram();
map(0x00000, 0x3ffff).ram();
map(0xb8000, 0xbffff).ram().share("vram");
map(0xf8000, 0xfffff).rom().region("maincpu", 0);
}
@ -285,6 +339,7 @@ void mindset_state::maincpu_io(address_map &map)
{
map(0x8300, 0x8301).w(FUNC(mindset_state::gco_w));
map(0x8320, 0x8321).lr16("8320", []() -> u16 { return 0xa005; }); // To pass the display test
map(0x8322, 0x8323).rw(FUNC(mindset_state::dispctrl_r), FUNC(mindset_state::dispctrl_w));
}
void mindset_state::mindset(machine_config &config)