From d7267c1cdd291b7fe355cb6c4a4bd12db7acd296 Mon Sep 17 00:00:00 2001 From: mahlemiut Date: Fri, 9 Aug 2019 14:55:50 +1200 Subject: pcipc: added a slightly more usable PCI S3 Virge/DX video card. s3virge: added PCI interface, and linear framebuffer support. [Barry Rodewald] --- scripts/src/video.lua | 12 ++ scripts/target/mame/mess.lua | 1 + src/devices/bus/isa/s3virge.cpp | 228 +++++++++++++++++++++++++++-- src/devices/bus/isa/s3virge.h | 54 +++++++ src/devices/video/pc_vga.cpp | 3 + src/devices/video/pc_vga.h | 1 + src/devices/video/virge_pci.cpp | 309 ++++++++++++++++++++++++++++++++++++++++ src/devices/video/virge_pci.h | 96 +++++++++++++ src/mame/drivers/pcipc.cpp | 12 +- 9 files changed, 703 insertions(+), 13 deletions(-) create mode 100644 src/devices/video/virge_pci.cpp create mode 100644 src/devices/video/virge_pci.h diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 4af7b56d41e..ac1a02a09d7 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -685,6 +685,18 @@ if (VIDEOS["PC_VGA"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/virge_pci.h,VIDEOS["VIRGE_PCI"] = true +-------------------------------------------------- + +if (VIDEOS["VIRGE_PCI"]~=null) then + files { + MAME_DIR .. "src/devices/video/virge_pci.cpp", + MAME_DIR .. "src/devices/video/virge_pci.h", + } +end + -------------------------------------------------- -- --@src/devices/video/pcd8544.h,VIDEOS["PCD8544"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 5cb830ad7a5..df7b50aa212 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -382,6 +382,7 @@ VIDEOS["UPD7220"] = true VIDEOS["UPD7227"] = true VIDEOS["V9938"] = true VIDEOS["VIC4567"] = true +VIDEOS["VIRGE_PCI"] = true --VIDEOS["VOODOO"] = true VIDEOS["SCN2674"] = true VIDEOS["GB_LCD"] = true diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp index 2f55d51c55b..ec5ac81c8c0 100644 --- a/src/devices/bus/isa/s3virge.cpp +++ b/src/devices/bus/isa/s3virge.cpp @@ -16,9 +16,20 @@ #include "screen.h" +#define VERBOSE (LOG_REG | LOG_CMD | LOG_MMIO) + +#include "logmacro.h" + +#define LOG_REG (1U << 1) +#define LOG_CMD (1U << 2) +#define LOG_MMIO (1U << 3) + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) +#define LOGMMIO(...) LOGMASKED(LOG_MMIO, __VA_ARGS__) + #define CRTC_PORT_ADDR ((vga.miscellaneous_output & 1) ? 0x3d0 : 0x3b0) -#define LOG_REG 1 DEFINE_DEVICE_TYPE(S3VIRGE, s3virge_vga_device, "virge_vga", "S3 86C325") DEFINE_DEVICE_TYPE(S3VIRGEDX, s3virgedx_vga_device, "virgedx_vga", "S3 86C375") @@ -76,6 +87,8 @@ void s3virge_vga_device::device_start() m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this)); memset(&s3, 0, sizeof(s3)); + memset(&s3virge, 0, sizeof(s3virge)); + s3virge.linear_address = 0x70000000; // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason for(x=0;x<4;x++) { @@ -224,6 +237,30 @@ uint8_t s3virge_vga_device::s3_crtc_reg_read(uint8_t index) case 0x55: res = s3.extended_dac_ctrl; break; + case 0x58: + res = s3virge.linear_address_size & 0x03; + res |= s3virge.linear_address_enable ? 0x10 : 0x00; + break; + case 0x59: + res = (s3virge.linear_address & 0xff000000) >> 24; + break; + case 0x5a: + switch(s3virge.linear_address_size & 0x03) + { + case 0: // 64kB + res = (s3virge.linear_address & 0x00ff0000) >> 16; + break; + case 1: // 1MB + res = (s3virge.linear_address & 0x00f00000) >> 16; + break; + case 2: // 2MB + res = (s3virge.linear_address & 0x00e00000) >> 16; + break; + case 3: // 4MB + res = (s3virge.linear_address & 0x00c00000) >> 16; + break; + } + break; case 0x5c: // if VGA dot clock is set to 3 (misc reg bits 2-3), then selected dot clock is read, otherwise read VGA clock select if((vga.miscellaneous_output & 0xc) == 0x0c) @@ -327,14 +364,14 @@ void s3virge_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data) if(s3.reg_lock2 == 0xa5) { s3.strapping = (s3.strapping & 0xffffff00) | data; - logerror("CR36: Strapping data = %08x\n",s3.strapping); + LOGREG("CR36: Strapping data = %08x\n",s3.strapping); } break; case 0x37: if(s3.reg_lock2 == 0xa5) { s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8); - logerror("CR37: Strapping data = %08x\n",s3.strapping); + LOGREG("CR37: Strapping data = %08x\n",s3.strapping); } break; case 0x38: @@ -355,8 +392,11 @@ void s3virge_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data) break; case 0x43: s3.cr43 = data; // bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h. - vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6); - s3_define_video_mode(); + if((s3.cr51 & 0x30) == 0) + { + vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6); + s3_define_video_mode(); + } break; /* 3d4h index 45h (R/W): CR45 Hardware Graphics Cursor Mode @@ -482,6 +522,7 @@ bit 0-5 Pattern Display Start Y-Pixel Position. s3.cursor_pattern_y = data; break; case 0x51: + s3.cr51 = data; vga.crtc.start_addr_latch &= ~0xc0000; vga.crtc.start_addr_latch |= ((data & 0x3) << 18); svga.bank_w = (svga.bank_w & 0xcf) | ((data & 0x0c) << 2); @@ -519,6 +560,36 @@ bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the case 0x55: s3.extended_dac_ctrl = data; break; + + case 0x58: + s3virge.linear_address_size = data & 0x03; + s3virge.linear_address_enable = data & 0x10; + switch(data & 0x03) + { + case LAW_64K: + s3virge.linear_address_size_full = 0x10000; + break; + case LAW_1MB: + s3virge.linear_address_size_full = 0x100000; + break; + case LAW_2MB: + s3virge.linear_address_size_full = 0x200000; + break; + case LAW_4MB: + s3virge.linear_address_size_full = 0x400000; + break; + } + LOGREG("CR58: write %02x\n", data); + break; + case 0x59: + s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24); + LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address); + break; + case 0x5a: + s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16); + LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address); + break; + /* 3d4h index 5Dh (R/W): Extended Horizontal Overflow Register (80x +) bit 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h @@ -583,7 +654,7 @@ bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h if(s3.reg_lock2 == 0xa5) { s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16); - logerror("CR68: Strapping data = %08x\n",s3.strapping); + LOGREG("CR68: Strapping data = %08x\n",s3.strapping); } break; case 0x69: @@ -599,11 +670,11 @@ bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h if(s3.reg_lock2 == 0xa5) { s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24); - logerror("CR6F: Strapping data = %08x\n",s3.strapping); + LOGREG("CR6F: Strapping data = %08x\n",s3.strapping); } break; default: - if(LOG_REG) logerror("S3: CR%02X write %02x\n",index,data); + LOGREG("S3: CR%02X write %02x\n",index,data); break; } } @@ -778,3 +849,144 @@ WRITE8_MEMBER(s3virge_vga_device::mem_w) if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) vga_device::mem_w(space,offset,data,mem_mask); } + +READ8_MEMBER(s3virge_vga_device::fb_r) +{ + if(offset < s3virge.linear_address_size_full) + return vga.memory[offset % vga.svga_intf.vram_size]; + return 0xff; +} + +WRITE8_MEMBER(s3virge_vga_device::fb_w) +{ + if(offset < s3virge.linear_address_size_full) + vga.memory[offset % vga.svga_intf.vram_size] = data; +} + +// 2D command register format - A500 (BitBLT), A900 (2D line), AD00 (2D Polygon) +// bit 0 - Autoexecute, if set command is executed when the highest relevant register is written to (A50C / A97C / AD7C) +// bit 1 - Enable hardware clipping +// bits 2-4 - Destination colour format - (0 = 8bpp palettised, 1 = 16bpp RGB1555 or RGB565, 2 = 24bpp RGB888 +// bit 5 - Draw enable - if reset, doesn't draw anything, but is still executed +// bit 6 - Image source Mono transfer, if set source is mono, otherwise source is the same pixel depth as the destination +// bit 7 - Image data source - 0 = source is in video memory, 1 = source is from the image transfer port (CPU / system memory) +// bit 8 - Mono pattern - if set, pattern data is mono, otherwise pattern data is the same pixel depth as the destination +// Cleared to 0 if using an ROP with a colour source Must be set to 1 if doing a rectangle fill operation +// bit 9 - Transparency - if set, does not update if a background colour is selected. Effectively only if bit 7 is set, Typically used for text display. +// bits 10-11 - Image transfer alignment - Data for an image transfer is byte (0), word (1), or doubleword (2) aligned. All image transfers are doubleword in size. +// bits 12-13 - First doubleword offset - (Image transfers) - start with the given byte (+1) in a doubleword for an image transfer +// bits 17-24 - MS Windows Raster Operation +// bit 25 - X Positive - if set, BitBLT is performed from left to right, otherwise, from right to left +// bit 26 - Y Positive - if set, BitBLT is performed from top to bottom, otherwise from bottom to top +// bits 27-30 - 2D Command - 0000 = BitBLT, 0010 = Rectangle Fill, 0011 = Line Draw, 0101 = Polygon Fill, 1111 = NOP (Turns off autoexecute without executing a command) +// bit 31 - 2D / 3D Select + + +READ32_MEMBER(s3virge_vga_device::s3d_sub_status_r) +{ + return 0x00003000; // S3D engine idle, all FIFO slots free +} + +WRITE32_MEMBER(s3virge_vga_device::s3d_sub_control_w) +{ + s3virge.interrupt_enable = data & 0x00003f80; + // TODO: bits 14-15==10 - reset engine + LOGMMIO("Sub control = %08x\n", data); +} + +READ32_MEMBER(s3virge_vga_device::s3d_register_r) +{ + uint32_t res = 0; + int op_type = (((offset*4) & 0x0f00) / 4) - 1; + + switch(offset) + { + case 0x4d4/4: + case 0x8d4/4: + case 0xcd4/4: + res = s3virge.s3d.src_base[op_type]; + break; + case 0xad8/4: + case 0x8d8/4: + case 0xcd8/4: + res = s3virge.s3d.dest_base[op_type]; + break; + case 0x500/4: + case 0x900/4: + case 0xd00/4: + res = s3virge.s3d.command[op_type]; + break; + case 0x504/4: + res = s3virge.s3d.rect_height[op_type]; + res |= (s3virge.s3d.rect_width[op_type] << 16); + break; + case 0x508/4: + res = s3virge.s3d.source_y[op_type]; + res |= (s3virge.s3d.source_x[op_type] << 16); + break; + case 0x50c/4: + res = s3virge.s3d.dest_y[op_type]; + res |= (s3virge.s3d.dest_x[op_type] << 16); + break; + default: + res = 0xffffffff; + LOGMMIO("MMIO unknown/unused register read MM%04X\n", (offset*4)+0xa000); + } + + return res; +} + +WRITE32_MEMBER(s3virge_vga_device::s3d_register_w) +{ + int op_type = (((offset*4) & 0x0f00) / 4) - 1; + + switch(offset) + { + case 0x4d4/4: + case 0x8d4/4: + case 0xcd4/4: + s3virge.s3d.src_base[op_type] = data; + LOGMMIO("MM%04X: Source Base = %08x\n", (offset*4)+0xa000, data); + break; + case 0xad8/4: + case 0x8d8/4: + case 0xcd8/4: + s3virge.s3d.dest_base[op_type] = data; + LOGMMIO("MM%04X: Destination base address = %08x\n", (offset*4)+0xa000, data); + break; + case 0x500/4: + s3virge.s3d.command[OP_BITBLT] = data; + // TODO:if bit 0 is reset, then execute now + LOGMMIO("MM%04X: Command [BitBLT/FilledRect] = %08x\n", (offset*4)+0xa000, data); + break; + case 0x900/4: + s3virge.s3d.command[OP_2DLINE] = data; + // TODO:if bit 0 is reset, then execute now + LOGMMIO("MM%04X: Command [2D Line] = %08x\n", (offset*4)+0xa000, data); + break; + case 0xd00/4: + s3virge.s3d.command[OP_2DPOLY] = data; + // TODO:if bit 0 is reset, then execute now + LOGMMIO("MM%04X: Command [2D Polygon] = %08x\n", (offset*4)+0xa000, data); + break; + case 0x504/4: + s3virge.s3d.rect_height[OP_BITBLT] = data & 0x000003ff; + s3virge.s3d.rect_width[OP_BITBLT] = (data & 0x03ff0000) >> 16; + LOGMMIO("MM%04X: Rectangle Width/Height = %08x (%ix%i)\n", (offset*4)+0xa000, data, s3virge.s3d.rect_width[OP_BITBLT], s3virge.s3d.rect_height[OP_BITBLT]); + break; + case 0x508/4: + s3virge.s3d.source_y[OP_BITBLT] = data & 0x000003ff; + s3virge.s3d.source_x[OP_BITBLT] = (data & 0x03ff0000) >> 16; + LOGMMIO("MM%04X: Rectangle Source X/Y = %08x (%i, %i)\n",(offset*4)+0xa000, data, s3virge.s3d.source_x[OP_BITBLT], s3virge.s3d.source_y[OP_BITBLT]); + break; + case 0x50c/4: + s3virge.s3d.dest_y[OP_BITBLT] = data & 0x000003ff; + s3virge.s3d.dest_x[OP_BITBLT] = (data & 0x03ff0000) >> 16; + // TODO:if previous command has bit 0 set, then execute here + LOGMMIO("MM%04X: Rectangle Destination X/Y = %08x (%i, %i)\n", (offset*4)+0xa000, data, s3virge.s3d.dest_x[OP_BITBLT], s3virge.s3d.dest_y[OP_BITBLT]); + break; + default: + LOGMMIO("MMIO unknown/unused register write MM%04X = %08x\n", (offset*4)+0xa000, data); + } +} + diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h index 0ee07815092..d8cf59bdb3e 100644 --- a/src/devices/bus/isa/s3virge.h +++ b/src/devices/bus/isa/s3virge.h @@ -31,6 +31,21 @@ public: virtual READ8_MEMBER(mem_r) override; virtual WRITE8_MEMBER(mem_w) override; + DECLARE_READ8_MEMBER(fb_r); + DECLARE_WRITE8_MEMBER(fb_w); + DECLARE_READ32_MEMBER(s3d_sub_status_r); + DECLARE_WRITE32_MEMBER(s3d_sub_control_w); + + DECLARE_READ32_MEMBER(s3d_register_r); + DECLARE_WRITE32_MEMBER(s3d_register_w); + + uint16_t get_crtc_port() { return (vga.miscellaneous_output&1)?0x3d0:0x3b0; } + uint32_t get_linear_address() { return s3virge.linear_address; } + void set_linear_address(uint32_t addr) { s3virge.linear_address = addr; } + uint8_t get_linear_address_size() { return s3virge.linear_address_size; } + bool is_linear_address_active() { return s3virge.linear_address_enable; } + bool is_new_mmio_active() { return s3.cr53 & 0x08; } + ibm8514a_device* get_8514() { fatalerror("s3virge requested non-existant 8514/A device\n"); return nullptr; } protected: @@ -39,6 +54,45 @@ protected: // device-level overrides virtual void device_start() override; virtual void device_reset() override; + + enum + { + LAW_64K = 0, + LAW_1MB, + LAW_2MB, + LAW_4MB + }; + + enum + { + OP_BITBLT = 0, + OP_2DLINE, + OP_2DPOLY, + OP_3DLINE, + OP_3DTRI + }; + + struct + { + uint32_t linear_address; + uint8_t linear_address_size; + uint32_t linear_address_size_full; + bool linear_address_enable; + uint32_t interrupt_enable; + + struct + { + uint32_t src_base[5]; + uint32_t dest_base[5]; + uint32_t command[5]; + uint16_t source_x[5]; + uint16_t source_y[5]; + uint16_t dest_x[5]; + uint16_t dest_y[5]; + uint16_t rect_width[5]; + uint16_t rect_height[5]; + } s3d; + } s3virge; private: virtual uint8_t s3_crtc_reg_read(uint8_t index); diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp index 1170693a2db..7e15f1efe5e 100644 --- a/src/devices/video/pc_vga.cpp +++ b/src/devices/video/pc_vga.cpp @@ -2722,6 +2722,9 @@ uint8_t s3_vga_device::s3_crtc_reg_read(uint8_t index) res |= ((svga.bank_w & 0x30) >> 2); res |= ((vga.crtc.offset & 0x0300) >> 4); break; + case 0x53: + res = s3.cr53; + break; case 0x55: res = s3.extended_dac_ctrl; break; diff --git a/src/devices/video/pc_vga.h b/src/devices/video/pc_vga.h index bab15da5673..07823707606 100644 --- a/src/devices/video/pc_vga.h +++ b/src/devices/video/pc_vga.h @@ -620,6 +620,7 @@ protected: uint8_t cr3a; uint8_t cr42; uint8_t cr43; + uint8_t cr51; uint8_t cr53; uint8_t id_high; uint8_t id_low; diff --git a/src/devices/video/virge_pci.cpp b/src/devices/video/virge_pci.cpp new file mode 100644 index 00000000000..26badeccd6a --- /dev/null +++ b/src/devices/video/virge_pci.cpp @@ -0,0 +1,309 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#include "emu.h" +#include "virge_pci.h" + +#include "screen.h" + +virge_pci_device::virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : virge_pci_device(mconfig, VIRGE_PCI, tag, owner, clock) +{ +} + +virge_pci_device::virge_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : pci_device(mconfig, type, tag, owner, clock), + m_vga(*this, "vga"), + m_bios(*this, "bios"), + m_screen(*this, finder_base::DUMMY_TAG) +{ +} + +virgedx_pci_device::virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : virge_pci_device(mconfig, VIRGEDX_PCI, tag, owner, clock) +{ +} + +void virge_pci_device::mmio_map(address_map& map) +{ + // MMIO address map + map(0x1008504,0x1008507).rw(m_vga, FUNC(s3virge_vga_device::s3d_sub_status_r), FUNC(s3virge_vga_device::s3d_sub_control_w)); + + // S3D engine registers + map(0x100a000,0x100b7ff).rw(m_vga, FUNC(s3virge_vga_device::s3d_register_r), FUNC(s3virge_vga_device::s3d_register_w)); +} + +void virge_pci_device::lfb_map(address_map& map) +{ + map(0x0, 0x00ffffff).rw(m_vga, FUNC(s3virge_vga_device::fb_r), FUNC(s3virge_vga_device::fb_w)); + if(downcast(m_vga.target())->is_new_mmio_active()) + mmio_map(map); +} + +void virge_pci_device::config_map(address_map &map) +{ + pci_device::config_map(map); + map(0x10, 0x13).rw(FUNC(virge_pci_device::base_address_r),FUNC(virge_pci_device::base_address_w)); +} + +void virge_pci_device::refresh_linear_window() +{ + if(downcast(m_vga.target())->is_linear_address_active()) + { + set_map_flags(0, M_MEM); + switch(downcast(m_vga.target())->get_linear_address_size() & 0x03) + { + case LAW_64K: + set_map_address(0,downcast(m_vga.target())->get_linear_address() & 0xffff0000); + logerror("Linear window set to 0x%08x\n",downcast(m_vga.target())->get_linear_address() & 0xffff0000); + break; + case LAW_1MB: + set_map_address(0,downcast(m_vga.target())->get_linear_address() & 0xfff00000); + logerror("Linear window set to 0x%08x\n",downcast(m_vga.target())->get_linear_address() & 0xfff00000); + break; + case LAW_2MB: + set_map_address(0,downcast(m_vga.target())->get_linear_address() & 0xffe00000); + logerror("Linear window set to 0x%08x\n",downcast(m_vga.target())->get_linear_address() & 0xffe00000); + break; + case LAW_4MB: + set_map_address(0,downcast(m_vga.target())->get_linear_address() & 0xffc00000); + logerror("Linear window set to 0x%08x\n",downcast(m_vga.target())->get_linear_address() & 0xffc00000); + break; + } + remap_cb(); + } + else + { + set_map_flags(0, M_MEM | M_DISABLED); + remap_cb(); + } +} + +READ32_MEMBER(virge_pci_device::base_address_r) +{ + return downcast(m_vga.target())->get_linear_address(); +} + +WRITE32_MEMBER(virge_pci_device::base_address_w) +{ + pci_device::address_base_w(space,offset,data,mem_mask); + downcast(m_vga.target())->set_linear_address(data & 0xffff0000); + refresh_linear_window(); +} + +READ32_MEMBER(virge_pci_device::vga_3b0_r) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_vga.target())->port_03b0_r(space, offset * 4 + 0, 0xff) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_vga.target())->port_03b0_r(space, offset * 4 + 1, 0xff) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_vga.target())->port_03b0_r(space, offset * 4 + 2, 0xff) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_vga.target())->port_03b0_r(space, offset * 4 + 3, 0xff) << 24; + return result; +} + +WRITE32_MEMBER(virge_pci_device::vga_3b0_w) +{ + if (ACCESSING_BITS_0_7) + { + downcast(m_vga.target())->port_03b0_w(space, offset * 4 + 0, data >> 0, 0xff); + if(offset == 1 && downcast(m_vga.target())->get_crtc_port() == 0x3b0) + m_current_crtc_reg = data & 0xff; + } + if (ACCESSING_BITS_8_15) + { + downcast(m_vga.target())->port_03b0_w(space, offset * 4 + 1, data >> 8, 0xff); + if(offset == 1 && downcast(m_vga.target())->get_crtc_port() == 0x3b0) + { + 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(); + } + } + } + if (ACCESSING_BITS_16_23) + downcast(m_vga.target())->port_03b0_w(space, offset * 4 + 2, data >> 16, 0xff); + if (ACCESSING_BITS_24_31) + downcast(m_vga.target())->port_03b0_w(space, offset * 4 + 3, data >> 24, 0xff); +} + +READ32_MEMBER(virge_pci_device::vga_3c0_r) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_vga.target())->port_03c0_r(space, offset * 4 + 0, 0xff) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_vga.target())->port_03c0_r(space, offset * 4 + 1, 0xff) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_vga.target())->port_03c0_r(space, offset * 4 + 2, 0xff) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_vga.target())->port_03c0_r(space, offset * 4 + 3, 0xff) << 24; + return result; +} + +WRITE32_MEMBER(virge_pci_device::vga_3c0_w) +{ + if (ACCESSING_BITS_0_7) + downcast(m_vga.target())->port_03c0_w(space, offset * 4 + 0, data >> 0, 0xff); + if (ACCESSING_BITS_8_15) + downcast(m_vga.target())->port_03c0_w(space, offset * 4 + 1, data >> 8, 0xff); + if (ACCESSING_BITS_16_23) + downcast(m_vga.target())->port_03c0_w(space, offset * 4 + 2, data >> 16, 0xff); + if (ACCESSING_BITS_24_31) + downcast(m_vga.target())->port_03c0_w(space, offset * 4 + 3, data >> 24, 0xff); +} + +READ32_MEMBER(virge_pci_device::vga_3d0_r) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_vga.target())->port_03d0_r(space, offset * 4 + 0, 0xff) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_vga.target())->port_03d0_r(space, offset * 4 + 1, 0xff) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_vga.target())->port_03d0_r(space, offset * 4 + 2, 0xff) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_vga.target())->port_03d0_r(space, offset * 4 + 3, 0xff) << 24; + return result; +} + +WRITE32_MEMBER(virge_pci_device::vga_3d0_w) +{ + if (ACCESSING_BITS_0_7) + { + downcast(m_vga.target())->port_03d0_w(space, offset * 4 + 0, data >> 0, 0xff); + if(offset == 1 && downcast(m_vga.target())->get_crtc_port() == 0x3d0) + m_current_crtc_reg = data & 0xff; + } + if (ACCESSING_BITS_8_15) + { + downcast(m_vga.target())->port_03d0_w(space, offset * 4 + 1, data >> 8, 0xff); + if(offset == 1 && downcast(m_vga.target())->get_crtc_port() == 0x3d0) + { + if(m_current_crtc_reg >= 0x58 && m_current_crtc_reg <= 0x5a) + { + refresh_linear_window(); + } + } + } + if (ACCESSING_BITS_16_23) + downcast(m_vga.target())->port_03d0_w(space, offset * 4 + 2, data >> 16, 0xff); + if (ACCESSING_BITS_24_31) + downcast(m_vga.target())->port_03d0_w(space, offset * 4 + 3, data >> 24, 0xff); +} + +READ8_MEMBER(virge_pci_device::vram_r) +{ + return downcast(m_vga.target())->mem_r(space, offset, 0xff); +} + +WRITE8_MEMBER(virge_pci_device::vram_w) +{ + downcast(m_vga.target())->mem_w(space, offset, data, 0xff); +} + +void virge_pci_device::postload() +{ + remap_cb(); +} + +void virge_pci_device::device_start() +{ + set_ids(0x53335631, 0x00, 0x030000, 0x000000); + pci_device::device_start(); + + add_rom(m_bios->base(),0x8000); + expansion_rom_base = 0xc0000; + + add_map(32 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(virge_pci_device::lfb_map)); + set_map_address(0, 0x70000000); + set_map_size(0, 0x01100000); // Linear addressing maps to a 32MB address space + + remap_cb(); + machine().save().register_postload(save_prepost_delegate(FUNC(virge_pci_device::postload), this)); +} + +void virgedx_pci_device::device_start() +{ + set_ids(0x53338a01, 0x00, 0x030000, 0x000000); + pci_device::device_start(); + + add_rom(m_bios->base(),0x8000); + expansion_rom_base = 0xc0000; + + add_map(4 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(virge_pci_device::lfb_map)); + set_map_address(0, 0x70000000); + set_map_size(0, 0x01100000); // Linear addressing maps to a 32MB address space + + remap_cb(); + machine().save().register_postload(save_prepost_delegate(FUNC(virgedx_pci_device::postload), this)); +} + +void virge_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, + uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) +{ + memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8_delegate(FUNC(virge_pci_device::vram_r),this), write8_delegate(FUNC(virge_pci_device::vram_w),this)); + + io_space->install_readwrite_handler(0x3b0, 0x3bf, read32_delegate(FUNC(virge_pci_device::vga_3b0_r), this), write32_delegate(FUNC(virge_pci_device::vga_3b0_w), this)); + io_space->install_readwrite_handler(0x3c0, 0x3cf, read32_delegate(FUNC(virge_pci_device::vga_3c0_r), this), write32_delegate(FUNC(virge_pci_device::vga_3c0_w), this)); + io_space->install_readwrite_handler(0x3d0, 0x3df, read32_delegate(FUNC(virge_pci_device::vga_3d0_r), this), write32_delegate(FUNC(virge_pci_device::vga_3d0_w), this)); +} + +void virge_pci_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(s3virge_vga_device::screen_update)); + + S3VIRGE(config, m_vga, 0).set_screen("screen"); +} + +void virgedx_pci_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(s3virge_vga_device::screen_update)); + + S3VIRGEDX(config, m_vga, 0).set_screen("screen"); +} + + +ROM_START( virge_pci ) + ROM_REGION(0x8000,"bios", 0) + ROM_DEFAULT_BIOS("virge") + + ROM_SYSTEM_BIOS( 0, "virge", "PCI S3 ViRGE v1.00-10" ) + ROMX_LOAD("pci_m-v_virge-4s3.bin", 0x00000, 0x8000, CRC(d0a0f1de) SHA1(b7b41081974762a199610219bdeab149b7c7143d), ROM_BIOS(0) ) + + ROM_SYSTEM_BIOS( 1, "virgeo", "PCI S3 ViRGE v1.00-05" ) + ROMX_LOAD("s3virge.bin", 0x00000, 0x8000, CRC(a7983a85) SHA1(e885371816d3237f7badd57ccd602cd863c9c9f8), ROM_BIOS(1) ) + ROM_IGNORE( 0x8000 ) +ROM_END + +ROM_START( virgedx_pci ) + ROM_REGION(0x8000,"bios", 0) + ROM_LOAD("s3virgedx.bin", 0x00000, 0x8000, CRC(0da83bd3) SHA1(228a2d644e1732cb5a2eb1291608c7050cf39229) ) + //ROMX_LOAD("virgedxdiamond.bin", 0x00000, 0x8000, CRC(58b0dcda) SHA1(b13ae6b04db6fc05a76d924ddf2efe150b823029), ROM_BIOS(2) ) +ROM_END + +const tiny_rom_entry *virge_pci_device::device_rom_region() const +{ + return ROM_NAME( virge_pci ); +} + +const tiny_rom_entry *virgedx_pci_device::device_rom_region() const +{ + return ROM_NAME( virgedx_pci ); +} + +DEFINE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device, "virge_pci", "S3 86C325 ViRGE PCI") +DEFINE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device, "virgedx_pci", "S3 86C375 ViRGE/DX PCI") diff --git a/src/devices/video/virge_pci.h b/src/devices/video/virge_pci.h new file mode 100644 index 00000000000..e049ced8323 --- /dev/null +++ b/src/devices/video/virge_pci.h @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +/* + * S3 ViRGE 3D accelerator card + */ + +#ifndef MAME_VIDEO_VIRGE_PCI_H +#define MAME_VIDEO_VIRGE_PCI_H + +#pragma once + +#include "machine/pci.h" +#include "bus/isa/s3virge.h" + +class virge_pci_device : public pci_device +{ +public: + template + virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag) + : virge_pci_device(mconfig, tag, owner, clock) + { + set_screen_tag(std::forward(screen_tag)); + } + + enum + { + LAW_64K = 0, + LAW_1MB, + LAW_2MB, + LAW_4MB + }; + + virge_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void lfb_map(address_map &map); + void mmio_map(address_map& map); + + DECLARE_READ32_MEMBER(vga_3b0_r); + DECLARE_WRITE32_MEMBER(vga_3b0_w); + DECLARE_READ32_MEMBER(vga_3c0_r); + DECLARE_WRITE32_MEMBER(vga_3c0_w); + DECLARE_READ32_MEMBER(vga_3d0_r); + DECLARE_WRITE32_MEMBER(vga_3d0_w); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(vram_w); + DECLARE_READ32_MEMBER(base_address_r); + DECLARE_WRITE32_MEMBER(base_address_w); + +protected: + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, + uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; + virtual void config_map(address_map &map) override; + + void postload(void); + + required_device m_vga; + required_memory_region m_bios; + optional_device m_screen; + +private: + void refresh_linear_window(); + + uint8_t m_current_crtc_reg; +}; + +class virgedx_pci_device : public virge_pci_device +{ +public: + template + virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag) + : virgedx_pci_device(mconfig, tag, owner, clock) + { + set_screen_tag(std::forward(screen_tag)); + } + virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + +// required_device m_vga; +// required_memory_region m_bios; +// optional_device m_screen; +}; + +DECLARE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device) +DECLARE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device) + +#endif diff --git a/src/mame/drivers/pcipc.cpp b/src/mame/drivers/pcipc.cpp index 394e8bba498..8108366f3b1 100644 --- a/src/mame/drivers/pcipc.cpp +++ b/src/mame/drivers/pcipc.cpp @@ -25,6 +25,7 @@ #include "machine/i82439tx.h" #include "machine/i82371sb.h" #include "video/mga2064w.h" +#include "video/virge_pci.h" #include "bus/isa/isa_cards.h" #include "bus/rs232/hlemouse.h" #include "bus/rs232/null_modem.h" @@ -459,7 +460,7 @@ WRITE8_MEMBER(pcipc_state::boot_state_phoenix_ver40_rev6_w) break; } logerror("Boot state %02x - %s\n", data, desc); - printf("[%02X]",data); +// printf("[%02X]",data); } @@ -537,15 +538,16 @@ void pcipc_state::pcipc(machine_config &config) ide.irq_pri().set(":pci:07.0", FUNC(i82371sb_isa_device::pc_irq14_w)); ide.irq_sec().set(":pci:07.0", FUNC(i82371sb_isa_device::pc_irq15_w)); // MGA2064W(config, ":pci:12.0", 0); + VIRGEDX_PCI(config, ":pci:12.0", 0); // use VIRGEDX_PCI for its VESA 2.0 BIOS ISA16_SLOT(config, "board4", 0, "pci:07.0:isabus", isa_internal_devices, "fdc37c93x", true).set_option_machine_config("fdc37c93x", superio_config); - ISA16_SLOT(config, "isa1", 0, "pci:07.0:isabus", pc_isa16_cards, "svga_et4k", false); + ISA16_SLOT(config, "isa1", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); ISA16_SLOT(config, "isa2", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); ISA16_SLOT(config, "isa3", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); ISA16_SLOT(config, "isa4", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); ISA16_SLOT(config, "isa5", 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false); - rs232_port_device &serport0(RS232_PORT(config, "serport0", isa_com, "logitech_mouse")); + rs232_port_device &serport0(RS232_PORT(config, "serport0", isa_com, "microsoft_mouse")); serport0.rxd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::rxd1_w)); serport0.dcd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndcd1_w)); serport0.dsr_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndsr1_w)); @@ -584,8 +586,8 @@ ROM_START(pcipc) ROMX_LOAD("crisis.rom", 0x00000, 0x40000, CRC(38a1458a) SHA1(8881ac336392cca79a772b4168f63efc31f953dd), ROM_BIOS(2) ) ROM_SYSTEM_BIOS(3, "5hx29", "5hx29") ROMX_LOAD("5hx29.bin", 0x20000, 0x20000, CRC(07719a55) SHA1(b63993fd5186cdb4f28c117428a507cd069e1f68), ROM_BIOS(3) ) - ROM_REGION(0x8000,"ibm_vga", 0) - ROM_LOAD("ibm-vga.bin", 0x00000, 0x8000, BAD_DUMP CRC(74e3fadb) SHA1(dce6491424f1726203776dfae9a967a98a4ba7b5) ) +// ROM_REGION(0x8000,"ibm_vga", 0) +// ROM_LOAD("ibm-vga.bin", 0x00000, 0x8000, BAD_DUMP CRC(74e3fadb) SHA1(dce6491424f1726203776dfae9a967a98a4ba7b5) ) ROM_END ROM_START(pcipctx) -- cgit v1.2.3