pc_vga: made a start on the Cirrus hardware pointer, fixed reading of the lock register (bonanza works again)

This commit is contained in:
mahlemiut 2015-04-11 14:22:23 +12:00
parent ac614bf9e4
commit ac1598dfa0
2 changed files with 250 additions and 14 deletions

View File

@ -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;

View File

@ -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);