mindset: Connect the keyboard (buggy), manage palette, resolution. Add a pattern fill (buggy) [O. Galibert]

Display test is deliberatly broken to see the message in a different
graphics mode.
This commit is contained in:
Olivier Galibert 2019-06-16 17:14:47 +02:00
parent 8cf2fecbca
commit ff0ad51b55

View File

@ -28,8 +28,10 @@ protected:
memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_gcos; memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_gcos;
u32 m_palette[16];
bool m_genlock[16];
u16 m_dispctrl; u16 m_dispctrl;
u8 m_kbd_p1, m_kbd_p2; u8 m_kbd_p1, m_kbd_p2, m_borderidx;
static u16 gco_blend_0(u16, u16); static u16 gco_blend_0(u16, u16);
static u16 gco_blend_1(u16, u16); static u16 gco_blend_1(u16, u16);
@ -54,6 +56,8 @@ protected:
void gco_w(u16); void gco_w(u16);
u16 dispctrl_r(); u16 dispctrl_r();
void dispctrl_w(u16 data); void dispctrl_w(u16 data);
u16 dispreg_r();
void dispreg_w(u16 data);
int sys_t0_r(); int sys_t0_r();
int sys_t1_r(); int sys_t1_r();
@ -99,8 +103,8 @@ void mindset_state::machine_reset()
int mindset_state::sys_t0_r() int mindset_state::sys_t0_r()
{ {
logerror("SYS: read t0 (%03x)\n", m_syscpu->pc()); // logerror("SYS: %d read t0 %d (%03x)\n", m_kbdcpu->total_cycles(), (m_kbd_p2 & 0x40) != 0, m_syscpu->pc());
return true; return (m_kbd_p2 & 0x40) != 0;
} }
int mindset_state::sys_t1_r() int mindset_state::sys_t1_r()
@ -111,25 +115,25 @@ int mindset_state::sys_t1_r()
u8 mindset_state::sys_p1_r() u8 mindset_state::sys_p1_r()
{ {
logerror("SYS: read p1\n"); // logerror("SYS: read p1\n");
return 0xff; return 0xff;
} }
u8 mindset_state::sys_p2_r() u8 mindset_state::sys_p2_r()
{ {
logerror("SYS: read p2 (%03x)\n", m_syscpu->pc()); // logerror("SYS: read p2 (%03x)\n", m_syscpu->pc());
return 0xff; return 0xff;
} }
void mindset_state::sys_p1_w(u8 data) void mindset_state::sys_p1_w(u8 data)
{ {
logerror("SYS: write p1 %02x\n", data); // logerror("SYS: write p1 %02x\n", data);
} }
void mindset_state::sys_p2_w(u8 data) void mindset_state::sys_p2_w(u8 data)
{ {
m_maincpu->int3_w(data & 0x20); m_maincpu->int3_w(!(data & 0x80));
logerror("SYS: write p2 %02x\n", data); // logerror("SYS: write p2 %02x\n", data);
} }
void mindset_state::kbd_p1_w(u8 data) void mindset_state::kbd_p1_w(u8 data)
@ -139,8 +143,8 @@ void mindset_state::kbd_p1_w(u8 data)
void mindset_state::kbd_p2_w(u8 data) void mindset_state::kbd_p2_w(u8 data)
{ {
if((m_kbd_p2 ^ data) & 0x40) // if((m_kbd_p2 ^ data) & 0x40)
logerror("KBD: %d output bit %d\n", m_kbdcpu->total_cycles(), (m_kbd_p2 & 0x40) != 0); // logerror("KBD: %d output bit %d\n", m_kbdcpu->total_cycles(), (m_kbd_p2 & 0x40) != 0);
m_kbd_p2 = data; m_kbd_p2 = data;
} }
@ -176,48 +180,91 @@ void mindset_state::dispctrl_w(u16 data)
// 4000 = buffer choice (switch on int2, frame int instead of field int?) // 4000 = buffer choice (switch on int2, frame int instead of field int?)
u16 chg = m_dispctrl ^ data; u16 chg = m_dispctrl ^ data;
m_dispctrl = data; m_dispctrl = data;
if(chg & ~0x0050) if(chg & 0xff00)
logerror("display control %04x\n", m_dispctrl); logerror("display control %04x\n", m_dispctrl);
} }
u16 mindset_state::dispreg_r()
{
// a..5 needed to pass the display test
// 0080 needed to allow uploading the palette
return 0xa086;
}
void mindset_state::dispreg_w(u16 data)
{
switch(m_dispctrl & 0xf) {
case 1:
m_borderidx = data & 0xf;
break;
case 4: {
data = sw(data);
u8 r = 0x11*(((data & 0x4000) >> 11) | (data & 7));
u8 g = 0x11*(((data & 0x2000) >> 10) | ((data & 0x38) >> 3));
u8 b = 0x11*(((data & 0x1000) >> 9) | ((data & 0x1c0) >> 6));
if(!(data & 0x8000)) {
r = r * 0.75;
g = g * 0.75;
b = b * 0.75;
}
m_palette[m_borderidx] = (r << 16) | (g << 8) | b;
m_genlock[m_borderidx] = data & 0x0200;
logerror("palette[%x] = %04x -> %06x.%d\n", m_borderidx, data, m_palette[m_borderidx], m_genlock[m_borderidx]);
m_borderidx = (m_borderidx + 1) & 0xf;
break;
}
default:
logerror("display reg[%x] = %04x\n", m_dispctrl & 0xf, data);
}
}
u32 mindset_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) u32 mindset_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{ {
static const u32 pal[4] = { 0x000000, 0x555555, 0xaaaaaa, 0xffffff }; int mode_type = (m_dispctrl & 0x6000) >> 13;
bool interleave = m_dispctrl & 0x0800;
int pixels_per_byte_order = (m_dispctrl & 0x0600) >> 9;
bool large_pixels = m_dispctrl & 0x0100;
if(false) { switch(mode_type) {
case 0: // Native mode
if(large_pixels) {
if(!interleave) {
switch(pixels_per_byte_order) {
case 1: {
static int palind[4] = { 0, 1, 4, 5 };
const u16 *src = m_vram;
for(u32 y=0; y<200; y++) { for(u32 y=0; y<200; y++) {
// Interleaved
const u16 *src = m_vram + 40*(y >> 1) + 4096*(y & 1);
u32 *dest = &bitmap.pix32(y); u32 *dest = &bitmap.pix32(y);
for(u32 x=0; x<320; x+=8) { for(u32 x=0; x<320; x+=8) {
u16 sv = *src++; u16 sv = *src++;
*dest++ = pal[(sv >> 6) & 3]; *dest++ = m_palette[palind[(sv >> 6) & 3]];
*dest++ = pal[(sv >> 4) & 3]; *dest++ = m_palette[palind[(sv >> 4) & 3]];
*dest++ = pal[(sv >> 2) & 3]; *dest++ = m_palette[palind[(sv >> 2) & 3]];
*dest++ = pal[(sv >> 0) & 3]; *dest++ = m_palette[palind[(sv >> 0) & 3]];
*dest++ = pal[(sv >> 14) & 3]; *dest++ = m_palette[palind[(sv >> 14) & 3]];
*dest++ = pal[(sv >> 12) & 3]; *dest++ = m_palette[palind[(sv >> 12) & 3]];
*dest++ = pal[(sv >> 10) & 3]; *dest++ = m_palette[palind[(sv >> 10) & 3]];
*dest++ = pal[(sv >> 8) & 3]; *dest++ = m_palette[palind[(sv >> 8) & 3]];
} }
} }
} else if(false) { return 0;
for(u32 y=0; y<200; y++) {
const u16 *src = m_vram + 40*y;
u32 *dest = &bitmap.pix32(y);
for(u32 x=0; x<320; x+=8) {
u16 sv = *src++;
*dest++ = pal[(sv >> 6) & 3];
*dest++ = pal[(sv >> 4) & 3];
*dest++ = pal[(sv >> 2) & 3];
*dest++ = pal[(sv >> 0) & 3];
*dest++ = pal[(sv >> 14) & 3];
*dest++ = pal[(sv >> 12) & 3];
*dest++ = pal[(sv >> 10) & 3];
*dest++ = pal[(sv >> 8) & 3];
} }
} }
} else { }
}
logerror("Unimplemented native mode (%dx%d, ppb=%d)\n", large_pixels ? 320 : 640, interleave ? 400 : 200, 2 << pixels_per_byte_order);
break;
case 1: // IBM-compatible graphics mode
logerror("Unimplemented ibm-compatible graphics mode (%dx%d, ppb=%d)\n", large_pixels ? 320 : 640, interleave ? 400 : 200, 2 << pixels_per_byte_order);
break;
case 2: // IBM-compatible character mode
if(large_pixels) {
if(!interleave) {
for(u32 y=0; y<25; y++) { for(u32 y=0; y<25; y++) {
for(u32 x=0; x<40; x++) { for(u32 x=0; x<40; x++) {
u16 val = m_vram[y*40+x]; u16 val = m_vram[y*40+x];
@ -227,11 +274,22 @@ u32 mindset_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, co
src += 128; src += 128;
u32 *dest = &bitmap.pix32(8*y+yy, 8*x); u32 *dest = &bitmap.pix32(8*y+yy, 8*x);
for(u32 xx=0; xx<8; xx++) for(u32 xx=0; xx<8; xx++)
*dest++ = pix & (0x80 >> xx) ? 0xffffff : 0x000000; *dest++ = pix & (0x80 >> xx) ? m_palette[1] : m_palette[0];
} }
} }
} }
return 0;
} }
}
logerror("Unimplemented ibm-compatible character mode (%dx%d)\n", large_pixels ? 320/8 : 640/8, interleave ? 400/8 : 200/8);
break;
case 3: // Unknown
logerror("Unknown graphics mode type 3\n");
break;
}
bitmap.fill(0);
return 0; return 0;
} }
@ -320,9 +378,23 @@ void mindset_state::blit(u16 packet_seg, u16 packet_adr)
// x = go right to left (unimplemented) // x = go right to left (unimplemented)
// f = fast (no idea what it means) // f = fast (no idea what it means)
// n = invert collision flag (unimplemented) // n = invert collision flag (unimplemented)
// p = pattern fill (unimplemented, use by fill_dest_buffer) // p = pattern fill (unimplemented, used by fill_dest_buffer)
// i/f = increment source / don't (unimplemented, compare with p?, used by blt_copy_word) // i/f = increment source / don't (unimplemented, compare with p?, used by blt_copy_word)
if(mode & 0x200) {
u32 nw = width >> 4;
u16 src = m_gcos->read_word((src_seg << 4) + src_adr);
for(u32 y=0; y<height; y++) {
u16 dst_cadr = dst_adr;
for(u32 w = 0; w != nw; w++) {
m_gcos->write_word((dst_seg << 4) + dst_cadr, src);
dst_cadr += 2;
}
dst_adr += dy;
}
} else {
auto blend = gco_blend[(mode >> 2) & 7]; auto blend = gco_blend[(mode >> 2) & 7];
u16 awmask = ((wmask << 16) | wmask) >> (15 - dst_sft); u16 awmask = ((wmask << 16) | wmask) >> (15 - dst_sft);
@ -398,6 +470,7 @@ void mindset_state::blit(u16 packet_seg, u16 packet_adr)
dst_adr += dy; dst_adr += dy;
} }
} }
}
void mindset_state::gco_w(u16) void mindset_state::gco_w(u16)
{ {
@ -409,6 +482,7 @@ void mindset_state::gco_w(u16)
switch(global_mode) { switch(global_mode) {
case 0x0101: case 0x0101:
case 0x0005:
blit(packet_seg, packet_adr); blit(packet_seg, packet_adr);
break; break;
} }
@ -431,17 +505,19 @@ void mindset_state::maincpu_io(address_map &map)
map(0x8280, 0x8283).rw(m_syscpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff); map(0x8280, 0x8283).rw(m_syscpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff);
map(0x82a0, 0x82a3).rw(m_soundcpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff); map(0x82a0, 0x82a3).rw(m_soundcpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff);
map(0x8300, 0x8301).w(FUNC(mindset_state::gco_w)); map(0x8300, 0x8301).w(FUNC(mindset_state::gco_w));
map(0x8320, 0x8321).lr16("8320", []() -> u16 { return 0xa005; }); // To pass the display test map(0x8320, 0x8321).rw(FUNC(mindset_state::dispreg_r), FUNC(mindset_state::dispreg_w));
map(0x8322, 0x8323).rw(FUNC(mindset_state::dispctrl_r), FUNC(mindset_state::dispctrl_w)); map(0x8322, 0x8323).rw(FUNC(mindset_state::dispctrl_r), FUNC(mindset_state::dispctrl_w));
} }
void mindset_state::mindset(machine_config &config) void mindset_state::mindset(machine_config &config)
{ {
config.m_perfect_cpu_quantum = ":syscpu";
I80186(config, m_maincpu, 12_MHz_XTAL/2); I80186(config, m_maincpu, 12_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &mindset_state::maincpu_mem); m_maincpu->set_addrmap(AS_PROGRAM, &mindset_state::maincpu_mem);
m_maincpu->set_addrmap(AS_IO, &mindset_state::maincpu_io); m_maincpu->set_addrmap(AS_IO, &mindset_state::maincpu_io);
I8042(config, m_syscpu, 12_MHz_XTAL); I8042(config, m_syscpu, 14.318181_MHz_XTAL/2);
m_syscpu->p1_in_cb().set(FUNC(mindset_state::sys_p1_r)); m_syscpu->p1_in_cb().set(FUNC(mindset_state::sys_p1_r));
m_syscpu->p2_in_cb().set(FUNC(mindset_state::sys_p2_r)); m_syscpu->p2_in_cb().set(FUNC(mindset_state::sys_p2_r));
m_syscpu->p1_out_cb().set(FUNC(mindset_state::sys_p1_w)); m_syscpu->p1_out_cb().set(FUNC(mindset_state::sys_p1_w));
@ -449,7 +525,7 @@ void mindset_state::mindset(machine_config &config)
m_syscpu->t0_in_cb().set(FUNC(mindset_state::sys_t0_r)); m_syscpu->t0_in_cb().set(FUNC(mindset_state::sys_t0_r));
m_syscpu->t1_in_cb().set(FUNC(mindset_state::sys_t1_r)); m_syscpu->t1_in_cb().set(FUNC(mindset_state::sys_t1_r));
I8042(config, m_soundcpu, 12_MHz_XTAL); I8042(config, m_soundcpu, 14.318181_MHz_XTAL/2);
I8749(config, m_kbdcpu, 6_MHz_XTAL); I8749(config, m_kbdcpu, 6_MHz_XTAL);
m_kbdcpu->p1_out_cb().set(FUNC(mindset_state::kbd_p1_w)); m_kbdcpu->p1_out_cb().set(FUNC(mindset_state::kbd_p1_w));