From b0c64c29afd5671b883016e7bb7663ab320cb483 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Tue, 10 Jan 2023 14:10:57 +0100 Subject: 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 --- src/devices/bus/isa/s3virge.cpp | 229 ++++++++++++++++++++++++++-------------- src/devices/bus/isa/s3virge.h | 12 ++- src/devices/video/virge_pci.cpp | 39 ++++++- 3 files changed, 195 insertions(+), 85 deletions(-) diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp index 9fb6f98d204..fddf1766b14 100644 --- a/src/devices/bus/isa/s3virge.cpp +++ b/src/devices/bus/isa/s3virge.cpp @@ -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); - - 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); + 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 (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; diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h index aec31340d7b..03281adfe19 100644 --- a/src/devices/bus/isa/s3virge.h +++ b/src/devices/bus/isa/s3virge.h @@ -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(); diff --git a/src/devices/video/virge_pci.cpp b/src/devices/video/virge_pci.cpp index a76fc33966b..08f392a8e0d 100644 --- a/src/devices/video/virge_pci.cpp +++ b/src/devices/video/virge_pci.cpp @@ -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(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(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(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(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(m_vga.target())->port_03d0_w(offset * 4 + 1, data >> 8); if(offset == 1 && downcast(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(); } } } -- cgit v1.2.3