mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
video/virge_pci.cpp: fix remapping, allow pcipc with ibm5170_hdd:win98se to boot without hacks in 256 color mode (#10804)
* video/virge_pci.cpp: fix remapping, allow pcipc with ibm5170_hdd:win98se to boot without hacks in 256 color mode * bus/isa/s3virge.cpp: implement DPna, DSna, DSno, DSPDxax and DSo ROP opcodes * video/virge_pci.cpp: hookup VGA ports to MMIO, makes HW mouse cursor usable * bus/isa/s3virge.cpp: fix device_reset inheritance, make s3d to start in idle state * bus/isa/s3virge.cpp: fix source pitch stride * bus/isa/s3virge.cpp: make bitblt_colour_step / bitblt_monosrc_step a bit less verbose * bus/isa/s3virge.cpp: stride follows up what's reading it * bus/isa/s3virge.cpp: clip against de bit * video/virge_pci.cpp: update BAR fix to catchup lower address config * bus/isa/s3virge.cpp: initialize pattern variable in mono mode * bus/isa/s3virge.cpp: fix mistake with shift << 8 in 8bpp pattern path, fixes Windows tooltips/Windows XP welcome setup screen * bus/isa/s3virge.cpp: QA notes
This commit is contained in:
parent
5a29410b26
commit
b0c64c29af
@ -9,6 +9,19 @@
|
||||
* - Working on getting VESA video modes working better - 800x600 and higher skip every other line at
|
||||
* 8-bit depth, but are fine at 15/16-bit depth.
|
||||
* - S3D is not implemented at all, so no 2D/3D acceleration yet.
|
||||
*
|
||||
* TODO:
|
||||
* - Proper FIFOs;
|
||||
* - Implement 3d commands;
|
||||
* - Implement remaining ROP commands;
|
||||
* - Secondary stream mixing;
|
||||
* - S3 Scenic Highway i/f (SAA7110 + S3 Scenic/MX2 MPEG-1);
|
||||
* - DMAs;
|
||||
* - interrupts;
|
||||
* - big endian support for non-x86 machines;
|
||||
* - DDC/I2C i/f, cfr. serial port on MMFF20
|
||||
* - win98se: doesn't show transparent layer on shut down screen;
|
||||
*
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -137,15 +150,23 @@ void s3virgedx_rev1_vga_device::device_start()
|
||||
|
||||
void s3virge_vga_device::device_reset()
|
||||
{
|
||||
vga_device::device_reset();
|
||||
s3_vga_device::device_reset();
|
||||
// Power-on strapping bits. Sampled at reset, but can be modified later.
|
||||
// These are just assumed defaults.
|
||||
s3.strapping = 0x000f0912;
|
||||
|
||||
// TODO: fix soft reset state
|
||||
// On Windows 98 shutdown message sometimes leads to an hang the next boot around
|
||||
s3virge.s3d.state = S3D_STATE_IDLE;
|
||||
s3virge.s3d.cmd_fifo_current_ptr = 0;
|
||||
s3virge.s3d.cmd_fifo_slots_free = 16;
|
||||
s3virge.s3d.busy = false;
|
||||
//m_draw_timer->adjust(attotime::never);
|
||||
}
|
||||
|
||||
void s3virgedx_vga_device::device_reset()
|
||||
{
|
||||
vga_device::device_reset();
|
||||
s3virge_vga_device::device_reset();
|
||||
// Power-on strapping bits. Sampled at reset, but can be modified later.
|
||||
// These are just assumed defaults.
|
||||
s3.strapping = 0x000f0912;
|
||||
@ -153,7 +174,7 @@ void s3virgedx_vga_device::device_reset()
|
||||
|
||||
void s3virgedx_rev1_vga_device::device_reset()
|
||||
{
|
||||
vga_device::device_reset();
|
||||
s3virgedx_vga_device::device_reset();
|
||||
// Power-on strapping bits. Sampled at reset, but can be modified later.
|
||||
// These are based on results from a Diamond Stealth 3D 2000 Pro (Virge/DX based)
|
||||
// bits 8-15 are still unknown, S3ID doesn't show config register 2 (CR37)
|
||||
@ -1035,6 +1056,12 @@ uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uin
|
||||
case 0x00: // 0
|
||||
ret = 0;
|
||||
break;
|
||||
case 0x0a: // DPna
|
||||
ret = (dst & (~pat));
|
||||
break;
|
||||
case 0x22: // DSna
|
||||
ret = (dst & (~src));
|
||||
break;
|
||||
case 0x55: // Dn
|
||||
ret = ~dst;
|
||||
break;
|
||||
@ -1049,11 +1076,19 @@ uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uin
|
||||
break;
|
||||
case 0xb8: // PSDPxax
|
||||
ret = ((dst ^ pat) & src) ^ pat;
|
||||
// machine().debug_break();
|
||||
break;
|
||||
case 0xbb: // DSno
|
||||
ret = (dst | (~src));
|
||||
break;
|
||||
case 0xcc:
|
||||
ret = src;
|
||||
break;
|
||||
case 0xe2: // DSPDxax
|
||||
ret = ((pat ^ dst) & src) ^ dst;
|
||||
break;
|
||||
case 0xee: // DSo
|
||||
ret = (dst | src);
|
||||
break;
|
||||
case 0xf0:
|
||||
ret = pat;
|
||||
break;
|
||||
@ -1061,7 +1096,7 @@ uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uin
|
||||
ret = 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
popmessage("Unimplemented ROP 0x%02x",rop);
|
||||
popmessage("bus/isa/s3virge.cpp: Unimplemented ROP 0x%02x",rop);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1147,12 +1182,17 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
// get source and destination addresses
|
||||
uint32_t src_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BASE] & 0x003ffff8;
|
||||
uint32_t dst_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_BASE] & 0x003ffff8;
|
||||
uint8_t pixel_size = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) >> 2;
|
||||
uint8_t rop = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17;
|
||||
|
||||
const u32 current_command = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND];
|
||||
const uint8_t pixel_size = (current_command & 0x0000001c) >> 2;
|
||||
const uint8_t rop = (current_command & 0x01fe0000) >> 17;
|
||||
const int align = (current_command & 0x000000c00) >> 10;
|
||||
//const bool tp = bool(BIT(current_command, 9));
|
||||
const bool de = bool(BIT(current_command, 5));
|
||||
|
||||
uint32_t src = 0;
|
||||
uint32_t dst = 0;
|
||||
uint32_t pat = 0;
|
||||
int align = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x000000c00) >> 10;
|
||||
int x;
|
||||
bool done = false;
|
||||
|
||||
@ -1161,26 +1201,31 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
case 0: // 8bpp
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = s3virge.s3d.image_xfer >> (x*8);
|
||||
else
|
||||
src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
|
||||
src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
if(current_command & 0x100)
|
||||
{
|
||||
pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
|
||||
? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
|
||||
}
|
||||
else
|
||||
pat = (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*8) + s3virge.s3d.bitblt_pat_x]) << 8;
|
||||
dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xff);
|
||||
{
|
||||
pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y * 8) + s3virge.s3d.bitblt_pat_x];
|
||||
}
|
||||
dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
|
||||
if (de)
|
||||
write_pixel8(dst_base, s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, GetROP(rop, src, dst, pat) & 0xff);
|
||||
|
||||
done = advance_pixel();
|
||||
if(done)
|
||||
{
|
||||
command_finish();
|
||||
break;
|
||||
}
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
{
|
||||
if(align == 2) // doubleword aligned, end here
|
||||
break;
|
||||
@ -1195,45 +1240,48 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
}
|
||||
break;
|
||||
case 1: // 16bpp
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = s3virge.s3d.image_xfer;
|
||||
else
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
if(current_command & 0x100)
|
||||
{
|
||||
pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
|
||||
? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
|
||||
}
|
||||
else
|
||||
pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2) + 1]) << 8;
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
|
||||
|
||||
if (de)
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
|
||||
done = advance_pixel();
|
||||
if(done)
|
||||
{
|
||||
command_finish();
|
||||
break;
|
||||
}
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst && align == 2)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst && align == 2)
|
||||
break; // if a new line of an image transfer, and is dword aligned, stop here
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = s3virge.s3d.image_xfer >> 16;
|
||||
else
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
if(current_command & 0x100)
|
||||
{
|
||||
pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
|
||||
? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
|
||||
}
|
||||
else
|
||||
pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2) + 1]) << 8;
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
|
||||
if (de)
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
|
||||
if(advance_pixel())
|
||||
command_finish();
|
||||
break;
|
||||
case 2: // 24bpp
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
{
|
||||
src = s3virge.s3d.image_xfer;
|
||||
for(x=0;x<4;x++)
|
||||
@ -1243,8 +1291,8 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
if(s3virge.s3d.bitblt_pixel_pos > 2)
|
||||
{
|
||||
s3virge.s3d.bitblt_pixel_pos = 0;
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
if(current_command & 0x100)
|
||||
{
|
||||
pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
|
||||
? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
|
||||
@ -1252,10 +1300,11 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
else
|
||||
pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 1]) << 8
|
||||
| (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 2]) << 16;
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.bitblt_current_pixel, dst, pat));
|
||||
if (de)
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.bitblt_current_pixel, dst, pat));
|
||||
s3virge.s3d.bitblt_current_pixel = 0;
|
||||
done = advance_pixel();
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
{
|
||||
if(align == 2) // doubleword aligned, end here
|
||||
x = 4;
|
||||
@ -1275,9 +1324,9 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
}
|
||||
else
|
||||
{
|
||||
src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
|
||||
src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
if(current_command & 0x100)
|
||||
{
|
||||
pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
|
||||
? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
|
||||
@ -1286,7 +1335,8 @@ void s3virge_vga_device::bitblt_colour_step()
|
||||
pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 1]) << 8
|
||||
| (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 2]) << 16;
|
||||
}
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat));
|
||||
if (de)
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat));
|
||||
if(advance_pixel())
|
||||
command_finish();
|
||||
break;
|
||||
@ -1300,12 +1350,19 @@ void s3virge_vga_device::bitblt_monosrc_step()
|
||||
// progress current monochrome source BitBLT operation
|
||||
uint32_t src_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BASE] & 0x003ffff8;
|
||||
uint32_t dst_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_BASE] & 0x003ffff8;
|
||||
uint8_t pixel_size = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) >> 2;
|
||||
uint8_t rop = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17;
|
||||
|
||||
const u32 current_command = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND];
|
||||
const uint8_t pixel_size = (current_command & 0x0000001c) >> 2;
|
||||
const uint8_t rop = (current_command & 0x01fe0000) >> 17;
|
||||
//const bool tp = bool(BIT(current_command, 9));
|
||||
const bool de = bool(BIT(current_command, 5));
|
||||
const int align = (current_command & 0x000000c00) >> 10;
|
||||
|
||||
uint32_t src = 0;
|
||||
uint32_t dst = 0;
|
||||
uint32_t pat = 0;
|
||||
int align = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x000000c00) >> 10;
|
||||
// Windows 98 cares about this being initialized to non-zero for
|
||||
// greyed back/forward icons in Explorer, system icons and right click disabled Paste command.
|
||||
uint32_t pat = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR];
|
||||
int x;
|
||||
bool done = false;
|
||||
|
||||
@ -1314,19 +1371,22 @@ void s3virge_vga_device::bitblt_monosrc_step()
|
||||
case 0: // 8bpp
|
||||
for(x=31;x>=0;x--)
|
||||
{
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
|
||||
else
|
||||
src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
|
||||
if(src & (1 << x))
|
||||
write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xff);
|
||||
else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xff);
|
||||
if (de)
|
||||
{
|
||||
if(src & (1 << x))
|
||||
write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xff);
|
||||
else if(!(current_command & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xff);
|
||||
}
|
||||
//printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
|
||||
done = advance_pixel();
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
{
|
||||
switch(align)
|
||||
{
|
||||
@ -1351,19 +1411,22 @@ void s3virge_vga_device::bitblt_monosrc_step()
|
||||
case 1: // 16bpp
|
||||
for(x=31;x>=0;x--)
|
||||
{
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
|
||||
else
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
|
||||
if(src & (1 << x))
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xffff);
|
||||
else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xffff);
|
||||
if (de)
|
||||
{
|
||||
if(src & (1 << x))
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xffff);
|
||||
else if(!(current_command & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xffff);
|
||||
}
|
||||
//printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
|
||||
done = advance_pixel();
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
{
|
||||
switch(align)
|
||||
{
|
||||
@ -1388,19 +1451,22 @@ void s3virge_vga_device::bitblt_monosrc_step()
|
||||
case 2: // 24bpp
|
||||
for(x=31;x>=0;x--)
|
||||
{
|
||||
if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
|
||||
if(current_command & 0x80)
|
||||
src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
|
||||
else
|
||||
src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
|
||||
src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current, src_stride());
|
||||
dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current, dest_stride());
|
||||
|
||||
if(src & (1 << x))
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat));
|
||||
else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat));
|
||||
if (de)
|
||||
{
|
||||
if(src & (1 << x))
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat));
|
||||
else if(!(current_command & 0x200)) // only draw background colour if transparency is not set
|
||||
write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat));
|
||||
}
|
||||
//printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
|
||||
done = advance_pixel();
|
||||
if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
if((current_command & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
|
||||
{
|
||||
switch(align)
|
||||
{
|
||||
@ -1491,30 +1557,30 @@ inline void s3virge_vga_device::write_pixel8(uint32_t base, uint16_t x, uint16_t
|
||||
vga.memory[(base + x + (y*dest_stride())) % vga.svga_intf.vram_size] = val;
|
||||
}
|
||||
|
||||
inline uint32_t s3virge_vga_device::read_pixel32(uint32_t base, uint16_t x, uint16_t y)
|
||||
inline uint32_t s3virge_vga_device::read_pixel32(uint32_t base, uint16_t x, uint16_t y, u16 stride_select)
|
||||
{
|
||||
return (vga.memory[(base + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 24) |
|
||||
(vga.memory[(base + 1 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 16) |
|
||||
(vga.memory[(base + 2 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8) |
|
||||
vga.memory[(base + 3 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size];
|
||||
return (vga.memory[(base + (x * 4) + (y * stride_select)) % vga.svga_intf.vram_size] << 24) |
|
||||
(vga.memory[(base + 1 + (x * 4) + (y * stride_select)) % vga.svga_intf.vram_size] << 16) |
|
||||
(vga.memory[(base + 2 + (x * 4) + (y * stride_select)) % vga.svga_intf.vram_size] << 8) |
|
||||
vga.memory[(base + 3 + (x * 4) + (y * stride_select)) % vga.svga_intf.vram_size];
|
||||
}
|
||||
|
||||
inline uint32_t s3virge_vga_device::read_pixel24(uint32_t base, uint16_t x, uint16_t y)
|
||||
inline uint32_t s3virge_vga_device::read_pixel24(uint32_t base, uint16_t x, uint16_t y, u16 stride_select)
|
||||
{
|
||||
return (vga.memory[(base + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size]) |
|
||||
(vga.memory[(base + 1 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8) |
|
||||
(vga.memory[(base + 2 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] << 16);
|
||||
return (vga.memory[(base + (x * 3) + (y * stride_select)) % vga.svga_intf.vram_size]) |
|
||||
(vga.memory[(base + 1 + (x * 3) + (y * stride_select)) % vga.svga_intf.vram_size] << 8) |
|
||||
(vga.memory[(base + 2 + (x * 3) + (y * stride_select)) % vga.svga_intf.vram_size] << 16);
|
||||
}
|
||||
|
||||
inline uint16_t s3virge_vga_device::read_pixel16(uint32_t base, uint16_t x, uint16_t y)
|
||||
inline uint16_t s3virge_vga_device::read_pixel16(uint32_t base, uint16_t x, uint16_t y, u16 stride_select)
|
||||
{
|
||||
return (vga.memory[(base + (x*2) + (y*dest_stride()) % vga.svga_intf.vram_size)]) |
|
||||
(vga.memory[(base + 1 + (x*2) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8);
|
||||
return (vga.memory[(base + (x * 2) + (y * stride_select) % vga.svga_intf.vram_size)]) |
|
||||
(vga.memory[(base + 1 + (x * 2) + (y * stride_select)) % vga.svga_intf.vram_size] << 8);
|
||||
}
|
||||
|
||||
inline uint8_t s3virge_vga_device::read_pixel8(uint32_t base, uint16_t x, uint16_t y)
|
||||
inline uint8_t s3virge_vga_device::read_pixel8(uint32_t base, uint16_t x, uint16_t y, u16 stride_select)
|
||||
{
|
||||
return vga.memory[(base + x + (y*dest_stride())) % vga.svga_intf.vram_size];
|
||||
return vga.memory[(base + x + (y * stride_select)) % vga.svga_intf.vram_size];
|
||||
}
|
||||
|
||||
// 2D command register format - A500 (BitBLT), A900 (2D line), AD00 (2D Polygon)
|
||||
@ -1557,6 +1623,13 @@ void s3virge_vga_device::s3d_sub_control_w(uint32_t data)
|
||||
LOGMMIO("Sub control = %08x\n", data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Advanced Function Control Register (MM850C)
|
||||
* ---- --xx xx-- ---- command fifo status
|
||||
* ---- ---- ---x ---- LA ENB Linear Addressing Enable (mirror of CR58 bit 4)
|
||||
* ---- ---- ---- --x- RST DM Reset read DMA
|
||||
* ---- ---- ---- ---x ENB EHFC Enable enhanced functions (mirror of CR66 bit 0)
|
||||
*/
|
||||
uint32_t s3virge_vga_device::s3d_func_ctrl_r()
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
@ -59,6 +59,10 @@ public:
|
||||
uint32_t get_linear_address_size_full() { return s3virge.linear_address_size_full; }
|
||||
bool is_linear_address_active() { return s3virge.linear_address_enable; }
|
||||
bool is_new_mmio_active() { return s3.cr53 & 0x08; }
|
||||
uint16_t src_stride()
|
||||
{
|
||||
return (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 0) & 0xfff8;
|
||||
}
|
||||
uint16_t dest_stride()
|
||||
{
|
||||
// if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) == 0x08)
|
||||
@ -184,10 +188,10 @@ protected:
|
||||
inline void write_pixel24(uint32_t base, uint16_t x, uint16_t y, uint32_t val);
|
||||
inline void write_pixel16(uint32_t base, uint16_t x, uint16_t y, uint16_t val);
|
||||
inline void write_pixel8(uint32_t base, uint16_t x, uint16_t y, uint8_t val);
|
||||
inline uint32_t read_pixel32(uint32_t base, uint16_t x, uint16_t y);
|
||||
inline uint32_t read_pixel24(uint32_t base, uint16_t x, uint16_t y);
|
||||
inline uint16_t read_pixel16(uint32_t base, uint16_t x, uint16_t y);
|
||||
inline uint8_t read_pixel8(uint32_t base, uint16_t x, uint16_t y);
|
||||
inline uint32_t read_pixel32(uint32_t base, uint16_t x, uint16_t y, u16 stride_select);
|
||||
inline uint32_t read_pixel24(uint32_t base, uint16_t x, uint16_t y, u16 stride_select);
|
||||
inline uint16_t read_pixel16(uint32_t base, uint16_t x, uint16_t y, u16 stride_select);
|
||||
inline uint8_t read_pixel8(uint32_t base, uint16_t x, uint16_t y, u16 stride_select);
|
||||
|
||||
uint32_t GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat);
|
||||
bool advance_pixel();
|
||||
|
@ -1,6 +1,7 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Barry Rodewald
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "virge_pci.h"
|
||||
|
||||
@ -29,16 +30,28 @@ void virge_pci_device::mmio_map(address_map& map)
|
||||
// image transfer ports
|
||||
map(0x1000000,0x1007fff).w(m_vga, FUNC(s3virge_vga_device::image_xfer));
|
||||
|
||||
//map(0x1008180,0x10081ff) primary/secondary stream control
|
||||
|
||||
//map(0x1008200,0x100821f) memory port controller
|
||||
//map(0x1008220,0x1008227) DMA control
|
||||
|
||||
// MMIO address map
|
||||
map(0x10083b0,0x10083bf).rw(FUNC(virge_pci_device::vga_3b0_r), FUNC(virge_pci_device::vga_3b0_w));
|
||||
map(0x10083c0,0x10083df).rw(FUNC(virge_pci_device::vga_3c0_r), FUNC(virge_pci_device::vga_3c0_w));
|
||||
map(0x10083d0,0x10083df).rw(FUNC(virge_pci_device::vga_3d0_r), FUNC(virge_pci_device::vga_3d0_w));
|
||||
map(0x1008504,0x1008507).rw(m_vga, FUNC(s3virge_vga_device::s3d_sub_status_r), FUNC(s3virge_vga_device::s3d_sub_control_w));
|
||||
map(0x100850c,0x100850f).r(m_vga, FUNC(s3virge_vga_device::s3d_func_ctrl_r));
|
||||
|
||||
//map(0x1008580,0x100858b) video DMA
|
||||
//map(0x1008590,0x100859f) command DMA
|
||||
|
||||
// S3D engine registers
|
||||
map(0x100a000,0x100b7ff).rw(m_vga, FUNC(s3virge_vga_device::s3d_register_r), FUNC(s3virge_vga_device::s3d_register_w));
|
||||
|
||||
// alternate image transfer ports
|
||||
map(0x100d000,0x100efff).w(m_vga, FUNC(s3virge_vga_device::image_xfer));
|
||||
|
||||
//map(0x100ff00, 0x100ff43) LPB control
|
||||
}
|
||||
|
||||
void virge_pci_device::lfb_map(address_map& map)
|
||||
@ -95,7 +108,9 @@ uint32_t virge_pci_device::base_address_r()
|
||||
void virge_pci_device::base_address_w(offs_t offset, uint32_t data)
|
||||
{
|
||||
pci_device::address_base_w(offset,data);
|
||||
downcast<s3virge_vga_device *>(m_vga.target())->set_linear_address(data & 0xffff0000);
|
||||
// only bits 31-26 are changed here, cfr. page 25-4
|
||||
const u32 new_address = (data & 0xfc000000) | (base_address_r() & 0x3ffffff);
|
||||
downcast<s3virge_vga_device *>(m_vga.target())->set_linear_address(new_address);
|
||||
refresh_linear_window();
|
||||
}
|
||||
|
||||
@ -124,9 +139,16 @@ void virge_pci_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
downcast<s3_vga_device *>(m_vga.target())->port_03b0_w(offset * 4 + 1, data >> 8);
|
||||
// TODO: make this more transparent
|
||||
// it shouldn't expose the S3 CRTC regs directly and don't repeat on 0x3d0 I/O below.
|
||||
if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3b0)
|
||||
{
|
||||
if(m_current_crtc_reg == 0x58)
|
||||
if (m_current_crtc_reg == 0x53)
|
||||
{
|
||||
refresh_linear_window();
|
||||
remap_cb();
|
||||
}
|
||||
else if(m_current_crtc_reg == 0x58)
|
||||
{
|
||||
refresh_linear_window();
|
||||
remap_cb();
|
||||
@ -197,9 +219,20 @@ void virge_pci_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask
|
||||
downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(offset * 4 + 1, data >> 8);
|
||||
if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3d0)
|
||||
{
|
||||
if(m_current_crtc_reg >= 0x58 && m_current_crtc_reg <= 0x5a)
|
||||
if (m_current_crtc_reg == 0x53)
|
||||
{
|
||||
refresh_linear_window();
|
||||
remap_cb();
|
||||
}
|
||||
else if(m_current_crtc_reg == 0x58)
|
||||
{
|
||||
refresh_linear_window();
|
||||
remap_cb();
|
||||
}
|
||||
else if(m_current_crtc_reg == 0x59 || m_current_crtc_reg == 0x5a)
|
||||
{
|
||||
refresh_linear_window();
|
||||
remap_cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user