pcipc: added a slightly more usable PCI S3 Virge/DX video card.

s3virge: added PCI interface, and linear framebuffer support. [Barry Rodewald]
This commit is contained in:
mahlemiut 2019-08-09 14:55:50 +12:00
parent 1c1360617d
commit d7267c1cdd
9 changed files with 703 additions and 13 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<s3virge_vga_device *>(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<s3virge_vga_device *>(m_vga.target())->is_linear_address_active())
{
set_map_flags(0, M_MEM);
switch(downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address_size() & 0x03)
{
case LAW_64K:
set_map_address(0,downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffff0000);
logerror("Linear window set to 0x%08x\n",downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffff0000);
break;
case LAW_1MB:
set_map_address(0,downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xfff00000);
logerror("Linear window set to 0x%08x\n",downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xfff00000);
break;
case LAW_2MB:
set_map_address(0,downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffe00000);
logerror("Linear window set to 0x%08x\n",downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffe00000);
break;
case LAW_4MB:
set_map_address(0,downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffc00000);
logerror("Linear window set to 0x%08x\n",downcast<s3virge_vga_device *>(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<s3virge_vga_device *>(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<s3virge_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03b0_r(space, offset * 4 + 0, 0xff) << 0;
if (ACCESSING_BITS_8_15)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(space, offset * 4 + 1, 0xff) << 8;
if (ACCESSING_BITS_16_23)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(space, offset * 4 + 2, 0xff) << 16;
if (ACCESSING_BITS_24_31)
result |= downcast<s3_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03b0_w(space, offset * 4 + 0, data >> 0, 0xff);
if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3b0)
m_current_crtc_reg = data & 0xff;
}
if (ACCESSING_BITS_8_15)
{
downcast<s3_vga_device *>(m_vga.target())->port_03b0_w(space, offset * 4 + 1, data >> 8, 0xff);
if(offset == 1 && downcast<s3virge_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03b0_w(space, offset * 4 + 2, data >> 16, 0xff);
if (ACCESSING_BITS_24_31)
downcast<s3_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03c0_r(space, offset * 4 + 0, 0xff) << 0;
if (ACCESSING_BITS_8_15)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(space, offset * 4 + 1, 0xff) << 8;
if (ACCESSING_BITS_16_23)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(space, offset * 4 + 2, 0xff) << 16;
if (ACCESSING_BITS_24_31)
result |= downcast<s3_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03c0_w(space, offset * 4 + 0, data >> 0, 0xff);
if (ACCESSING_BITS_8_15)
downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(space, offset * 4 + 1, data >> 8, 0xff);
if (ACCESSING_BITS_16_23)
downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(space, offset * 4 + 2, data >> 16, 0xff);
if (ACCESSING_BITS_24_31)
downcast<s3_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03d0_r(space, offset * 4 + 0, 0xff) << 0;
if (ACCESSING_BITS_8_15)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(space, offset * 4 + 1, 0xff) << 8;
if (ACCESSING_BITS_16_23)
result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(space, offset * 4 + 2, 0xff) << 16;
if (ACCESSING_BITS_24_31)
result |= downcast<s3_vga_device *>(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<s3_vga_device *>(m_vga.target())->port_03d0_w(space, offset * 4 + 0, data >> 0, 0xff);
if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3d0)
m_current_crtc_reg = data & 0xff;
}
if (ACCESSING_BITS_8_15)
{
downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(space, offset * 4 + 1, data >> 8, 0xff);
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)
{
refresh_linear_window();
}
}
}
if (ACCESSING_BITS_16_23)
downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(space, offset * 4 + 2, data >> 16, 0xff);
if (ACCESSING_BITS_24_31)
downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(space, offset * 4 + 3, data >> 24, 0xff);
}
READ8_MEMBER(virge_pci_device::vram_r)
{
return downcast<s3_vga_device *>(m_vga.target())->mem_r(space, offset, 0xff);
}
WRITE8_MEMBER(virge_pci_device::vram_w)
{
downcast<s3_vga_device *>(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")

View File

@ -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 <typename T>
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<T>(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<s3virge_vga_device> m_vga;
required_memory_region m_bios;
optional_device<screen_device> m_screen;
private:
void refresh_linear_window();
uint8_t m_current_crtc_reg;
};
class virgedx_pci_device : public virge_pci_device
{
public:
template <typename T>
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<T>(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<s3virge_vga_device> m_vga;
// required_memory_region m_bios;
// optional_device<screen_device> m_screen;
};
DECLARE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device)
DECLARE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device)
#endif

View File

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