video/pc_vga_sis: add SiS6326 VGA core

This commit is contained in:
angelosa 2024-03-14 00:03:59 +01:00
parent 28210363d0
commit c6348541e6
6 changed files with 203 additions and 128 deletions

View File

@ -65,10 +65,10 @@ void sis6326_agp_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(m_vga, FUNC(sis630_svga_device::screen_update));
screen.set_screen_update(m_vga, FUNC(sis6236_vga_device::screen_update));
// TODO: barely similar, to be changed.
SIS630_SVGA(config, m_vga, 0);
SIS6236_VGA(config, m_vga, 0);
m_vga->set_screen("screen");
// 4MB, max 8MB
m_vga->set_vram_size(4*1024*1024);
@ -155,7 +155,7 @@ void sis6326_agp_device::config_map(address_map &map)
void sis6326_agp_device::vram_aperture_map(address_map &map)
{
map(0x0000000, 0x3ffffff).rw(m_vga, FUNC(sis630_svga_device::mem_linear_r), FUNC(sis630_svga_device::mem_linear_w)).umask32(0xffffffff);
map(0x0000000, 0x3ffffff).rw(m_vga, FUNC(sis6236_vga_device::mem_linear_r), FUNC(sis6236_vga_device::mem_linear_w));
}
void sis6326_agp_device::mmio_map(address_map &map)
@ -174,17 +174,17 @@ void sis6326_agp_device::legacy_memory_map(address_map &map)
void sis6326_agp_device::legacy_io_map(address_map &map)
{
map(0, 0x02f).m(m_vga, FUNC(sis630_svga_device::io_map));
map(0, 0x02f).m(m_vga, FUNC(sis6236_vga_device::io_map));
}
uint8_t sis6326_agp_device::vram_r(offs_t offset)
{
return downcast<sis630_svga_device *>(m_vga.target())->mem_r(offset);
return downcast<sis6236_vga_device *>(m_vga.target())->mem_r(offset);
}
void sis6326_agp_device::vram_w(offs_t offset, uint8_t data)
{
downcast<sis630_svga_device *>(m_vga.target())->mem_w(offset, data);
downcast<sis6236_vga_device *>(m_vga.target())->mem_w(offset, data);
}
void sis6326_agp_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,

View File

@ -36,7 +36,7 @@ protected:
void mmio_map(address_map &map);
void vmi_map(address_map &map);
private:
required_device<sis630_svga_device> m_vga;
required_device<sis6236_vga_device> m_vga;
required_memory_region m_vga_rom;
void legacy_memory_map(address_map &map);

View File

@ -63,7 +63,7 @@ DEFINE_DEVICE_TYPE(SIS630_GUI, sis630_gui_device, "sis630_gui", "SiS 630 GUI")
sis630_gui_device::sis630_gui_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pci_device(mconfig, SIS630_GUI, tag, owner, clock)
, m_svga(*this, "svga")
, m_vga(*this, "svga")
, m_gui_rom(*this, "gui_rom")
{
set_ids(0x10396300, 0x00, 0x030000, 0x00);
@ -93,13 +93,13 @@ void sis630_gui_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(m_svga, FUNC(sis630_svga_device::screen_update));
screen.set_screen_update(m_vga, FUNC(sis630_vga_device::screen_update));
SIS630_SVGA(config, m_svga, 0);
m_svga->set_screen("screen");
SIS630_VGA(config, m_vga, 0);
m_vga->set_screen("screen");
// 64MB according to POST
// documentation claims 128MB, assume being wrong
m_svga->set_vram_size(64*1024*1024);
m_vga->set_vram_size(64*1024*1024);
}
void sis630_gui_device::config_map(address_map &map)
@ -196,7 +196,7 @@ void sis630_gui_device::subvendor_w(offs_t offset, u32 data, u32 mem_mask)
void sis630_gui_device::memory_map(address_map &map)
{
map(0x0000000, 0x3ffffff).rw(m_svga, FUNC(sis630_svga_device::mem_linear_r), FUNC(sis630_svga_device::mem_linear_w)).umask32(0xffffffff);
map(0x0000000, 0x3ffffff).rw(m_vga, FUNC(sis630_vga_device::mem_linear_r), FUNC(sis630_vga_device::mem_linear_w));
}
void sis630_gui_device::io_map(address_map &map)
@ -216,7 +216,7 @@ void sis630_gui_device::space_io_map(address_map &map)
// RIO + 0x16: 301 RAMDAC
// RIO + 0x30/+0x40/+0x50: omitted, legacy '300/'630 VGA regs?
// (gamecstl definitely tries to access 0x44 index 5 for readback extension ID)
map(0x30, 0x5f).m(m_svga, FUNC(sis630_svga_device::io_map));
map(0x30, 0x5f).m(m_vga, FUNC(sis630_vga_device::io_map));
}
void sis630_gui_device::legacy_memory_map(address_map &map)
@ -226,7 +226,7 @@ void sis630_gui_device::legacy_memory_map(address_map &map)
void sis630_gui_device::legacy_io_map(address_map &map)
{
map(0x03b0, 0x03df).m(m_svga, FUNC(sis630_svga_device::io_map));
map(0x03b0, 0x03df).m(m_vga, FUNC(sis630_vga_device::io_map));
}
void sis630_gui_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
@ -264,12 +264,12 @@ void sis630_gui_device::device_reset()
// TODO: remove these trampolines
uint8_t sis630_gui_device::vram_r(offs_t offset)
{
return downcast<sis630_svga_device *>(m_svga.target())->mem_r(offset);
return downcast<sis630_vga_device *>(m_vga.target())->mem_r(offset);
}
void sis630_gui_device::vram_w(offs_t offset, uint8_t data)
{
downcast<sis630_svga_device *>(m_svga.target())->mem_w(offset, data);
downcast<sis630_vga_device *>(m_vga.target())->mem_w(offset, data);
}
/*****************************

View File

@ -36,7 +36,7 @@ protected:
void space_io_map(address_map &map);
private:
required_device<sis630_svga_device> m_svga;
required_device<sis630_vga_device> m_vga;
required_memory_region m_gui_rom;
u8 vram_r(offs_t offset);

View File

@ -34,16 +34,28 @@ TODO:
// TODO: later variant of 5598
// (definitely doesn't have dual segment mode for instance)
DEFINE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device, "sis630_svga", "SiS 630 VGA i/f")
DEFINE_DEVICE_TYPE(SIS6236_VGA, sis6236_vga_device, "sis6236_vga", "SiS 6236 VGA i/f")
DEFINE_DEVICE_TYPE(SIS630_VGA, sis630_vga_device, "sis630_vga", "SiS 630 VGA i/f")
sis630_svga_device::sis630_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: svga_device(mconfig, SIS630_SVGA, tag, owner, clock)
sis6236_vga_device::sis6236_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sis6236_vga_device(mconfig, SIS630_VGA, tag, owner, clock)
{
m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(sis630_svga_device::crtc_map), this));
m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(sis630_svga_device::sequencer_map), this));
m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(sis6236_vga_device::sequencer_map), this));
}
void sis630_svga_device::device_start()
sis6236_vga_device::sis6236_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: svga_device(mconfig, type, tag, owner, clock)
{
}
sis630_vga_device::sis630_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sis6236_vga_device(mconfig, SIS630_VGA, tag, owner, clock)
{
m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(sis630_vga_device::crtc_map), this));
m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(sis630_vga_device::sequencer_map), this));
}
void sis6236_vga_device::device_start()
{
svga_device::device_start();
zero();
@ -52,11 +64,12 @@ void sis630_svga_device::device_start()
vga.crtc.maximum_scan_line = 1;
// copy over interfaces
vga.svga_intf.vram_size = 64*1024*1024;
//vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
}
void sis630_svga_device::device_reset()
void sis6236_vga_device::device_reset()
{
svga_device::device_reset();
@ -64,7 +77,7 @@ void sis630_svga_device::device_reset()
//m_dual_seg_mode = false;
}
void sis630_svga_device::io_3cx_map(address_map &map)
void sis6236_vga_device::io_3cx_map(address_map &map)
{
svga_device::io_3cx_map(map);
// TODO: for '630 it's always with dual segment enabled?
@ -89,45 +102,7 @@ void sis630_svga_device::io_3cx_map(address_map &map)
);
}
// Page 144
void sis630_svga_device::crtc_map(address_map &map)
{
svga_device::crtc_map(map);
// CR19/CR1A Extended Signature Read-Back 0/1
// CR1B CRT horizontal counter (r/o)
// CR1C CRT vertical counter (r/o)
// CR1D CRT overflow counter (r/o)
// CR1E Extended Signature Read-Back 2
// CR26 Attribute Controller Index read-back
// TODO: is this an undocumented VGA or a SiS extension?
map(0x26, 0x26).lr8(
NAME([this] (offs_t offset) { return vga.attribute.index; })
);
// TODO: very preliminary, this section is undocumented in '630 doc
map(0x30, 0xff).lrw8(
NAME([this] (offs_t offset) {
return vga.crtc.data[offset];
}),
NAME([this] (offs_t offset, u8 data) {
// TODO: if one of these is 0xff then it enables a single port transfer to $b8000
// Older style MMIO?
vga.crtc.data[offset] = data;
})
);
// make sure '301 CRT2 is not enabled for now
// TODO: BeMAME (0.36b5) under BeOS 5.0 detects a secondary monitor by default anyway
map(0x30, 0x30).lr8(
NAME([] (offs_t offset) { return 0; })
);
map(0x31, 0x31).lr8(
NAME([] (offs_t offset) { return 0x60; })
);
map(0x32, 0x32).lr8(
NAME([] (offs_t offset) { return 0x20; })
);
}
void sis630_svga_device::sequencer_map(address_map &map)
void sis6236_vga_device::sequencer_map(address_map &map)
{
svga_device::sequencer_map(map);
// extended ID register
@ -175,15 +150,152 @@ void sis630_svga_device::sequencer_map(address_map &map)
);
map(0x07, 0x07).lrw8(
NAME([this] (offs_t offset) {
return m_ext_misc_ctrl_0;
return m_ext_misc_ctrl[0];
}),
NAME([this] (offs_t offset, u8 data) {
LOG("SR07: Extended Misc. Control 0 %02x\n", data);
m_ext_misc_ctrl_0 = data;
m_ext_misc_ctrl[0] = data;
std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
})
);
//map(0x08, 0x09) CRT threshold
map(0x0a, 0x0a).lrw8(
NAME([this] (offs_t offset) {
return m_ext_vert_overflow;
}),
NAME([this] (offs_t offset, u8 data) {
LOG("SR0A: Extended CRT Overflow %02x\n", data);
m_ext_vert_overflow = data;
vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0xf0) << 4);
vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0x03ff) | ((data & 0x08) << 7);
vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0x03ff) | ((data & 0x04) << 8);
vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0x03ff) | ((data & 0x02) << 9);
vga.crtc.vert_total = (vga.crtc.vert_total & 0x03ff) | ((data & 0x01) << 10);
recompute_params();
})
);
map(0x0b, 0x0c).lrw8(
NAME([this] (offs_t offset) {
return m_ext_misc_ctrl[offset + 1];
}),
NAME([this] (offs_t offset, u8 data) {
LOG("SR%02X: Extended Misc. Control %d %02x\n", offset + 0xb, offset + 1, data);
m_ext_misc_ctrl[offset + 1] = data;
})
);
//map(0x0e, 0x0f) Ext. Config Status (r/o)
map(0x0f, 0x10).lrw8(
NAME([this] (offs_t offset) {
return m_ext_scratch[offset];
}),
NAME([this] (offs_t offset, u8 data) {
LOG("SR%02X: Extended Scratch %d %02x\n", offset + 0xf, offset, data);
m_ext_scratch[offset] = data;
})
);
//map(0x11, 0x11) DDC register
// ...
}
std::tuple<u8, u8> sis6236_vga_device::flush_true_color_mode()
{
// punt if extended or true color is off
if ((m_ramdac_mode & 0x12) != 0x12)
return std::make_tuple(0, 0);
const u8 res = (m_ext_misc_ctrl[0] & 4) >> 2;
return std::make_tuple(res, res ^ 1);
}
void sis6236_vga_device::recompute_params()
{
u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2;
int xtal;
switch(xtal_select & 3)
{
case 0: xtal = XTAL(25'174'800).value(); break;
case 1: xtal = XTAL(28'636'363).value(); break;
// TODO: stub, barely enough to make BeOS 5 to set ~60 Hz for 640x480x16
case 2:
default:
xtal = XTAL(25'174'800).value();
break;
}
recompute_params_clock(1, xtal);
}
uint16_t sis6236_vga_device::offset()
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
return vga.crtc.offset << 3;
return svga_device::offset();
}
uint8_t sis6236_vga_device::mem_r(offs_t offset)
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
return svga_device::mem_linear_r(offset + svga.bank_r * 0x10000);
return svga_device::mem_r(offset);
}
void sis6236_vga_device::mem_w(offs_t offset, uint8_t data)
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
{
svga_device::mem_linear_w(offset + svga.bank_w * 0x10000, data);
return;
}
svga_device::mem_w(offset, data);
}
/*
* SiS630 overrides
*/
// Page 144
void sis630_vga_device::crtc_map(address_map &map)
{
sis6236_vga_device::crtc_map(map);
// CR19/CR1A Extended Signature Read-Back 0/1
// CR1B CRT horizontal counter (r/o)
// CR1C CRT vertical counter (r/o)
// CR1D CRT overflow counter (r/o)
// CR1E Extended Signature Read-Back 2
// CR26 Attribute Controller Index read-back
// TODO: is this an undocumented VGA or a SiS extension?
map(0x26, 0x26).lr8(
NAME([this] (offs_t offset) { return vga.attribute.index; })
);
// TODO: very preliminary, this section is undocumented in '630 doc
map(0x30, 0xff).lrw8(
NAME([this] (offs_t offset) {
return vga.crtc.data[offset];
}),
NAME([this] (offs_t offset, u8 data) {
// TODO: if one of these is 0xff then it enables a single port transfer to $b8000
// Older style MMIO?
vga.crtc.data[offset] = data;
})
);
// make sure '301 CRT2 is not enabled for now
// TODO: BeMAME (0.36b5) under BeOS 5.0 detects a secondary monitor by default anyway
map(0x30, 0x30).lr8(
NAME([] (offs_t offset) { return 0; })
);
map(0x31, 0x31).lr8(
NAME([] (offs_t offset) { return 0x60; })
);
map(0x32, 0x32).lr8(
NAME([] (offs_t offset) { return 0x20; })
);
}
void sis630_vga_device::sequencer_map(address_map &map)
{
sis6236_vga_device::sequencer_map(map);
map(0x0a, 0x0a).lrw8(
NAME([this] (offs_t offset) {
return m_ext_vert_overflow;
@ -336,57 +448,3 @@ void sis630_svga_device::sequencer_map(address_map &map)
//map(0x3c, 0x3c) Synchronous reset
//map(0x3d, 0x3d) Test enable
}
std::tuple<u8, u8> sis630_svga_device::flush_true_color_mode()
{
// punt if extended or true color is off
if ((m_ramdac_mode & 0x12) != 0x12)
return std::make_tuple(0, 0);
const u8 res = (m_ext_misc_ctrl_0 & 4) >> 2;
return std::make_tuple(res, res ^ 1);
}
void sis630_svga_device::recompute_params()
{
u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2;
int xtal;
switch(xtal_select & 3)
{
case 0: xtal = XTAL(25'174'800).value(); break;
case 1: xtal = XTAL(28'636'363).value(); break;
// TODO: stub, barely enough to make BeOS 5 to set ~60 Hz for 640x480x16
case 2:
default:
xtal = XTAL(25'174'800).value();
break;
}
recompute_params_clock(1, xtal);
}
uint16_t sis630_svga_device::offset()
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
return vga.crtc.offset << 3;
return svga_device::offset();
}
uint8_t sis630_svga_device::mem_r(offs_t offset)
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
return svga_device::mem_linear_r(offset + svga.bank_r * 0x10000);
return svga_device::mem_r(offset);
}
void sis630_svga_device::mem_w(offs_t offset, uint8_t data)
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
{
svga_device::mem_linear_w(offset + svga.bank_w * 0x10000, data);
return;
}
svga_device::mem_w(offset, data);
}

View File

@ -8,28 +8,31 @@
#include "video/pc_vga.h"
class sis630_svga_device : public svga_device
class sis6236_vga_device : public svga_device
{
public:
sis630_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
sis6236_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
protected:
sis6236_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
virtual void device_reset() override;
virtual void io_3cx_map(address_map &map) override;
virtual void crtc_map(address_map &map) override;
virtual void sequencer_map(address_map &map) override;
virtual uint16_t offset() override;
virtual void recompute_params() override;
u8 m_ramdac_mode = 0;
u8 m_ext_misc_ctrl_0 = 0;
u8 m_ext_misc_ctrl[3]{};
//u16 m_ext_config_status = 0;
u8 m_ext_scratch[2]{};
u8 m_ext_vert_overflow = 0;
u8 m_ext_horz_overflow[2]{};
u8 m_bus_width = 0;
@ -43,6 +46,20 @@ protected:
// bool m_dual_seg_mode = false;
};
DECLARE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device)
class sis630_vga_device : public sis6236_vga_device
{
public:
sis630_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// virtual void device_start() override;
// virtual void device_reset() override;
virtual void crtc_map(address_map &map) override;
virtual void sequencer_map(address_map &map) override;
};
DECLARE_DEVICE_TYPE(SIS6236_VGA, sis6236_vga_device)
DECLARE_DEVICE_TYPE(SIS630_VGA, sis630_vga_device)
#endif // MAME_VIDEO_PC_VGA_SIS_H