From ac1598dfa0e518e41ea44ea895f990d95a2ae54e Mon Sep 17 00:00:00 2001 From: mahlemiut Date: Sat, 11 Apr 2015 14:22:23 +1200 Subject: [PATCH] pc_vga: made a start on the Cirrus hardware pointer, fixed reading of the lock register (bonanza works again) --- src/emu/video/pc_vga.c | 245 ++++++++++++++++++++++++++++++++++++++--- src/emu/video/pc_vga.h | 19 ++++ 2 files changed, 250 insertions(+), 14 deletions(-) diff --git a/src/emu/video/pc_vga.c b/src/emu/video/pc_vga.c index 05f2e93ed87..3ead5e87442 100644 --- a/src/emu/video/pc_vga.c +++ b/src/emu/video/pc_vga.c @@ -276,7 +276,6 @@ void cirrus_vga_device::device_start() vga.svga_intf.seq_regcount = 0x1f; vga.svga_intf.crtc_regcount = 0x2d; vga.svga_intf.vram_size = 0x200000; - gc_locked = true; vga.memory.resize_and_clear(vga.svga_intf.vram_size); save_item(NAME(vga.memory)); @@ -1144,6 +1143,83 @@ UINT32 s3_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, return 0; } +UINT32 cirrus_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT8 cur_mode = 0; + int x,y,bit; + UINT32 ptr = (vga.svga_intf.vram_size - 0x4000); // cursor patterns are stored in the last 16kB of VRAM + svga_device::screen_update(screen, bitmap, cliprect); + + cur_mode = pc_vga_choosevideomode(); + + if(m_cursor_attr & 0x01) // hardware cursor enabled + { + // draw hardware graphics cursor + if(m_cursor_attr & 0x04) // 64x64 + { + ptr += ((m_cursor_addr & 0x3c) * 256); + for(y=0;y<64;y++) + { + for(x=0;x<64;x+=8) + { + for(bit=0;bit<8;bit++) + { + UINT8 pixel1 = vga.memory[ptr] >> (7-bit); + UINT8 pixel2 = vga.memory[ptr+256] >> (7-bit); + UINT8 output = ((pixel1 & 0x01) << 1) | (pixel2 & 0x01); + switch(output) + { + case 0: // transparent - do nothing + break; + case 1: // background + bitmap.pix32(y,x+bit) = (m_ext_palette[0].red << 16) | (m_ext_palette[0].green << 8) | (m_ext_palette[0].blue); + break; + case 2: // XOR + bitmap.pix32(y,x+bit) = ~bitmap.pix32(y,x+bit); + break; + case 3: // foreground + bitmap.pix32(y,x+bit) = (m_ext_palette[15].red << 16) | (m_ext_palette[15].green << 8) | (m_ext_palette[15].blue); + break; + } + } + } + } + } + else + { + ptr += ((m_cursor_addr & 0x3f) * 256); + for(y=0;y<32;y++) + { + for(x=0;x<32;x+=8) + { + for(bit=0;bit<8;bit++) + { + UINT8 pixel1 = vga.memory[ptr] >> (7-bit); + UINT8 pixel2 = vga.memory[ptr+128] >> (7-bit); + UINT8 output = ((pixel1 & 0x01) << 1) | (pixel2 & 0x01); + switch(output) + { + case 0: // transparent - do nothing + break; + case 1: // background + bitmap.pix32(y,x+bit) = (m_ext_palette[0].red << 16) | (m_ext_palette[0].green << 8) | (m_ext_palette[0].blue); + break; + case 2: // XOR + bitmap.pix32(y,x+bit) = ~bitmap.pix32(y,x+bit); + break; + case 3: // foreground + bitmap.pix32(y,x+bit) = (m_ext_palette[15].red << 16) | (m_ext_palette[15].green << 8) | (m_ext_palette[15].blue); + break; + } + } + ptr++; + } + } + } + } + return 0; +} + /***************************************************************************/ inline UINT8 vga_device::rotate_right(UINT8 val) @@ -2025,6 +2101,21 @@ void s3_vga_device::device_reset() s3.sr11 = 0x41; } +void cirrus_vga_device::device_reset() +{ + vga_device::device_reset(); + gc_locked = true; + gc_mode_ext = 0; + gc_bank_0 = gc_bank_1 = 0; + gc_blt_status = 0; + m_cursor_attr = 0x00; // disable hardware cursor and extra palette + m_cursor_x = m_cursor_y = 0; + m_cursor_addr = 0; + m_scratchpad1 = m_scratchpad2 = m_scratchpad3 = 0; + m_cr19 = m_cr1a = m_cr1b = 0; + memset(m_ext_palette, 0, sizeof(m_ext_palette)); +} + READ8_MEMBER(vga_device::mem_r) { /* TODO: check me */ @@ -5684,14 +5775,21 @@ UINT8 cirrus_vga_device::cirrus_seq_reg_read(UINT8 index) if(gc_locked) return 0x0f; else - return 0x00; + return m_lock_reg; break; - case 0x07: case 0x09: - case 0x0a: //printf("%02x\n",index); res = vga.sequencer.data[index]; break; + case 0x0a: + res = m_scratchpad1; + break; + case 0x14: + res = m_scratchpad2; + break; + case 0x15: + res = m_scratchpad3; + break; default: res = vga.sequencer.data[index]; } @@ -5712,19 +5810,65 @@ void cirrus_vga_device::cirrus_seq_reg_write(UINT8 index, UINT8 data) case 0x06: // Note: extensions are always enabled on the GD5429 if((data & 0x17) == 0x12) // bits 3,5,6,7 ignored + { gc_locked = false; + logerror("Cirrus register extensions unlocked\n"); + } else + { gc_locked = true; - case 0x09: - case 0x0a: - //printf("%02x %02x\n",index,data); - vga.sequencer.data[vga.sequencer.index] = data; + logerror("Cirrus register extensions locked\n"); + } + m_lock_reg = data & 0x17; break; case 0x07: if((data & 0xf0) != 0) - popmessage("1MB framebuffer window enabled at %iMB",data >> 4); + popmessage("1MB framebuffer window enabled at %iMB (%02x)",data >> 4,data); vga.sequencer.data[vga.sequencer.index] = data; break; + case 0x09: + //printf("%02x %02x\n",index,data); + vga.sequencer.data[vga.sequencer.index] = data; + break; + case 0x0a: + m_scratchpad1 = data; // GD5402/GD542x BIOS writes VRAM size here. + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: // bits 5-7 of the register index are the low bits of the X co-ordinate + m_cursor_x = (data << 3) | ((index & 0xe0) >> 5); + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: // bits 5-7 of the register index are the low bits of the Y co-ordinate + m_cursor_y = (data << 3) | ((index & 0xe0) >> 5); + break; + case 0x12: + // bit 0 - enable cursor + // bit 1 - enable extra palette (cursor colours are there) + // bit 2 - 64x64 cursor (32x32 if clear, GD5422+) + // bit 7 - overscan colour protect - if set, use colour 2 in the extra palette for the border (GD5424+) + m_cursor_attr = data; + break; + case 0x13: + m_cursor_addr = data; // bits 0 and 1 are ignored if using 64x64 cursor + break; + case 0x14: + m_scratchpad2 = data; + break; + case 0x15: + m_scratchpad3 = data; // GD543x BIOS writes VRAM size here + break; default: vga.sequencer.data[vga.sequencer.index] = data; seq_reg_write(vga.sequencer.index,data); @@ -5830,13 +5974,41 @@ void cirrus_vga_device::cirrus_gc_reg_write(UINT8 index, UINT8 data) READ8_MEMBER(cirrus_vga_device::port_03c0_r) { - UINT8 res; + UINT8 res = 0xff; switch(offset) { case 0x05: res = cirrus_seq_reg_read(vga.sequencer.index); break; + case 0x09: + if(!(m_cursor_attr & 0x02)) + res = vga_device::port_03c0_r(space,offset,mem_mask); + else + { + if (vga.dac.read) + { + switch (vga.dac.state++) + { + case 0: + res = m_ext_palette[vga.dac.read_index & 0x0f].red; + break; + case 1: + res = m_ext_palette[vga.dac.read_index & 0x0f].green; + break; + case 2: + res = m_ext_palette[vga.dac.read_index & 0x0f].blue; + break; + } + + if (vga.dac.state==3) + { + vga.dac.state = 0; + vga.dac.read_index++; + } + } + } + break; case 0x0f: res = cirrus_gc_reg_read(vga.gc.index); break; @@ -5855,6 +6027,31 @@ WRITE8_MEMBER(cirrus_vga_device::port_03c0_w) case 0x05: cirrus_seq_reg_write(vga.sequencer.index,data); break; + case 0x09: + if(!(m_cursor_attr & 0x02)) + vga_device::port_03c0_w(space,offset,data,mem_mask); + else + { + if (!vga.dac.read) + { + switch (vga.dac.state++) { + case 0: + m_ext_palette[vga.dac.write_index & 0x0f].red=data; + break; + case 1: + m_ext_palette[vga.dac.write_index & 0x0f].green=data; + break; + case 2: + m_ext_palette[vga.dac.write_index & 0x0f].blue=data; + break; + } + vga.dac.dirty=1; + if (vga.dac.state==3) { + vga.dac.state=0; vga.dac.write_index++; + } + } + } + break; case 0x0f: cirrus_gc_reg_write(vga.gc.index,data); break; @@ -5948,8 +6145,17 @@ UINT8 cirrus_vga_device::cirrus_crtc_reg_read(UINT8 index) switch(index) { + case 0x19: + res = m_cr19; + break; + case 0x1a: + res = m_cr1a; + break; + case 0x1b: + res = m_cr1b; + break; case 0x27: - res = 0xa0; + res = 0xa0; // Chip ID - GD5430 rev 0 break; default: logerror("CL: Unhandled extended CRTC register CR%02x read\n",index); @@ -5967,6 +6173,15 @@ void cirrus_vga_device::cirrus_crtc_reg_write(UINT8 index, UINT8 data) } switch(index) { + case 0x19: + m_cr19 = data; + break; + case 0x1a: + m_cr1a = data; + break; + case 0x1b: + m_cr1b = data; + break; case 0x27: // Do nothing, read only break; @@ -5980,8 +6195,9 @@ READ8_MEMBER(cirrus_vga_device::mem_r) { UINT32 addr; UINT8 bank; + UINT8 cur_mode = pc_vga_choosevideomode(); - if(gc_locked) + if(gc_locked || cur_mode == TEXT_MODE || cur_mode == SCREEN_OFF) return vga_device::mem_r(space,offset,mem_mask); if(offset >= 0x8000 && offset < 0x10000 && (gc_mode_ext & 0x01)) // if accessing bank 1 (if enabled) @@ -5993,7 +6209,7 @@ READ8_MEMBER(cirrus_vga_device::mem_r) addr = bank * 0x4000; else // 4kB bank granularity addr = bank * 0x1000; - // Win 3.1 GD5426/8 drivers use this in 16-colour mode also + if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) { if(gc_mode_ext & 0x01) @@ -6080,8 +6296,9 @@ WRITE8_MEMBER(cirrus_vga_device::mem_w) { UINT32 addr; UINT8 bank; + UINT8 cur_mode = pc_vga_choosevideomode(); - if(gc_locked) + if(gc_locked || cur_mode == TEXT_MODE || cur_mode == SCREEN_OFF) { vga_device::mem_w(space,offset,data,mem_mask); return; diff --git a/src/emu/video/pc_vga.h b/src/emu/video/pc_vga.h index 2eac1b024e0..8032ffd2c1a 100644 --- a/src/emu/video/pc_vga.h +++ b/src/emu/video/pc_vga.h @@ -637,9 +637,12 @@ public: virtual WRITE8_MEMBER(port_03d0_w); virtual READ8_MEMBER(mem_r); virtual WRITE8_MEMBER(mem_w); + + virtual UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); protected: // device-level overrides virtual void device_start(); + virtual void device_reset(); virtual UINT16 offset(); UINT8 gc_mode_ext; @@ -647,6 +650,22 @@ protected: UINT8 gc_bank_1; UINT8 gc_blt_status; bool gc_locked; + UINT8 m_lock_reg; + + UINT8 m_cr19; + UINT8 m_cr1a; + UINT8 m_cr1b; + + // hardware cursor + UINT16 m_cursor_x; + UINT16 m_cursor_y; + UINT16 m_cursor_addr; + UINT8 m_cursor_attr; + struct { UINT8 red, green, blue; } m_ext_palette[16]; // extra palette, colour 0 is cursor background, colour 15 is cursor foreground, colour 2 is overscan border colour + + UINT8 m_scratchpad1; + UINT8 m_scratchpad2; + UINT8 m_scratchpad3; private: void cirrus_define_video_mode(); UINT8 cirrus_seq_reg_read(UINT8 index);