clgd542x: added transparency support, fixed some lockup issues with colour expanded system-to-VRAM BitBLTs.

This commit is contained in:
mahlemiut 2015-05-20 18:42:15 +12:00
parent 5018b72a79
commit adc0b0b6c2
2 changed files with 93 additions and 29 deletions

View File

@ -372,31 +372,46 @@ void cirrus_gd5428_device::start_system_bitblt()
m_blt_status |= 0x09;
}
// non colour-expanded BitBLTs from system memory must be doubleword sized, extra bytes are ignored
void cirrus_gd5428_device::blit_dword()
{
// TODO: add support for reverse direction
UINT8 x,pixel;
if(m_blt_mode & 0x80) // colour expand
for(x=0;x<32;x+=8)
{
for(x=0;x<32;x++)
{
pixel = ((m_blt_system_buffer & (0x00000001 << x)) >> x) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs
if(m_blt_pixel_count <= m_blt_width)
copy_pixel(pixel,vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]);
m_blt_dest_current++;
m_blt_pixel_count++;
}
pixel = ((m_blt_system_buffer & (0x000000ff << x)) >> x);
if(m_blt_pixel_count <= m_blt_width)
copy_pixel(pixel,vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]);
m_blt_dest_current++;
m_blt_pixel_count++;
}
else
if(m_blt_pixel_count > m_blt_width)
{
for(x=0;x<32;x+=8)
{
pixel = ((m_blt_system_buffer & (0x000000ff << x)) >> x);
if(m_blt_pixel_count <= m_blt_width)
copy_pixel(pixel,vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]);
m_blt_dest_current++;
m_blt_pixel_count++;
}
m_blt_pixel_count = 0;
m_blt_scan_count++;
m_blt_dest_current = m_blt_dest + (m_blt_dest_pitch*m_blt_scan_count);
}
if(m_blt_scan_count > m_blt_height)
{
m_blt_system_transfer = false; // BitBLT complete
m_blt_status &= ~0x0b;
}
}
// colour-expanded BitBLTs from system memory are on a byte boundary, unused bits are ignored
void cirrus_gd5428_device::blit_byte()
{
// TODO: add support for reverse direction
UINT8 x,pixel;
for(x=0;x<8;x++)
{
pixel = ((m_blt_system_buffer & (0x00000001 << (7-x))) >> (7-x)) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs
if(m_blt_pixel_count <= m_blt_width - 1)
copy_pixel(pixel,vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]);
m_blt_dest_current++;
m_blt_pixel_count++;
}
if(m_blt_pixel_count > m_blt_width)
{
@ -413,26 +428,38 @@ void cirrus_gd5428_device::blit_dword()
void cirrus_gd5428_device::copy_pixel(UINT8 src, UINT8 dst)
{
UINT8 res = src;
switch(m_blt_rop)
{
case 0x00: // BLACK
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = 0x00;
res = 0x00;
break;
case 0x0b: // DSTINVERT
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = ~dst;
res = ~dst;
break;
case 0x0d: // SRC
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = src;
res = src;
break;
case 0x0e: // WHITE
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = 0xff;
res = 0xff;
break;
case 0x59: // SRCINVERT
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = src ^ dst;
res = src ^ dst;
break;
default:
popmessage("CL: Unsupported BitBLT ROP mode %02x",m_blt_rop);
}
// handle transparency compare
if(m_blt_mode & 0x08) // TODO: 16-bit compare
{
// if ROP result matches the transparency colour, don't change the pixel
if((res & (~m_blt_trans_colour_mask & 0xff)) == ((m_blt_trans_colour & 0xff) & (~m_blt_trans_colour_mask & 0xff)))
return;
}
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = res;
}
UINT8 cirrus_gd5428_device::cirrus_seq_reg_read(UINT8 index)
@ -687,6 +714,18 @@ UINT8 cirrus_gd5428_device::cirrus_gc_reg_read(UINT8 index)
case 0x32: // BitBLT ROP mode
res = m_blt_rop;
break;
case 0x34: // BitBLT Transparent Colour
res = m_blt_trans_colour & 0x00ff;
break;
case 0x35:
res = m_blt_trans_colour >> 8;
break;
case 0x36: // BitBLT Transparent Colour Mask
res = m_blt_trans_colour_mask & 0x00ff;
break;
case 0x37:
res = m_blt_trans_colour_mask >> 8;
break;
default:
res = gc_reg_read(index);
}
@ -810,6 +849,18 @@ void cirrus_gd5428_device::cirrus_gc_reg_write(UINT8 index, UINT8 data)
case 0x32: // BitBLT ROP mode
m_blt_rop = data;
break;
case 0x34: // BitBLT Transparent Colour
m_blt_trans_colour = (m_blt_trans_colour & 0xff00) | data;
break;
case 0x35:
m_blt_trans_colour = (m_blt_trans_colour & 0x00ff) | (data << 8);
break;
case 0x36: // BitBLT Transparent Colour Mask
m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0xff00) | data;
break;
case 0x37:
m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0x00ff) | (data << 8);
break;
default:
gc_reg_write(index,data);
}
@ -1224,15 +1275,25 @@ WRITE8_MEMBER(cirrus_gd5428_device::mem_w)
UINT8 cur_mode = pc_vga_choosevideomode();
if(m_blt_system_transfer)
{
m_blt_system_buffer &= ~(0x000000ff << (m_blt_system_count * 8));
m_blt_system_buffer |= (data << (m_blt_system_count * 8));
m_blt_system_count++;
if(m_blt_system_count >= 4)
{
if(m_blt_mode & 0x80) // colour expand
{
blit_dword();
m_blt_system_buffer &= ~(0x000000ff);
m_blt_system_buffer |= data;
blit_byte();
m_blt_system_count = 0;
}
else
{
m_blt_system_buffer &= ~(0x000000ff << (m_blt_system_count * 8));
m_blt_system_buffer |= (data << (m_blt_system_count * 8));
m_blt_system_count++;
if(m_blt_system_count >= 4)
{
blit_dword();
m_blt_system_count = 0;
}
}
return;
}

View File

@ -66,6 +66,8 @@ protected:
UINT16 m_blt_width;
UINT32 m_blt_source_current;
UINT32 m_blt_dest_current;
UINT16 m_blt_trans_colour;
UINT16 m_blt_trans_colour_mask;
bool m_blt_system_transfer; // blit from system memory
UINT8 m_blt_system_count;
@ -93,6 +95,7 @@ private:
void start_reverse_bitblt();
void start_system_bitblt();
void blit_dword();
void blit_byte(); // used for colour expanded system-to-vram bitblts
void copy_pixel(UINT8 src, UINT8 dst);
};