summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2026-02-26 19:46:24 +0100
committer angelosa <lordkale4@gmail.com>2026-02-26 22:04:13 +0100
commit35ddefa8f160a39b8237c92b39c245d1f3d68773 (patch)
treeea0fe6d70954ea92c62d632b9bb3ed42668756b4
parentd7abdb1cfd8c5300340e1261cf3fc2de4c78a752 (diff)
bus/pci/sis6326.cpp: initial BitBlt implementation
-rw-r--r--src/devices/bus/pci/sis6326.cpp378
-rw-r--r--src/devices/bus/pci/sis6326.h34
-rw-r--r--src/devices/video/pc_vga_matrox.cpp12
-rw-r--r--src/devices/video/pc_vga_sis.cpp16
-rw-r--r--src/devices/video/pc_vga_sis.h10
5 files changed, 434 insertions, 16 deletions
diff --git a/src/devices/bus/pci/sis6326.cpp b/src/devices/bus/pci/sis6326.cpp
index 966c25f7844..6bb7dc70ec3 100644
--- a/src/devices/bus/pci/sis6326.cpp
+++ b/src/devices/bus/pci/sis6326.cpp
@@ -14,6 +14,7 @@ SiS 6326
#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_AGP)
//#define LOG_OUTPUT_FUNC osd_printf_info
+
#include "logmacro.h"
#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
@@ -113,11 +114,108 @@ void sis6326_pci_device::vram_aperture_map(address_map &map)
void sis6326_pci_device::mmio_map(address_map &map)
{
+ map(0x8280, 0x8283).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_src_start_addr);
+ m_src_start_addr &= 0x3f'ffff;
+ })
+ );
+ // TODO: bit 31 is read only for Enhanced Color Expansion busy bit
+ map(0x8284, 0x8287).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_dst_start_addr);
+ m_dst_start_addr &= 0x3f'ffff;
+ if (ACCESSING_BITS_24_31)
+ m_draw_sel = data >> 24;
+ })
+ );
+ map(0x8288, 0x8289).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_src_pitch);
+ m_src_pitch &= 0x7ff;
+ })
+ );
+ map(0x828a, 0x828b).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_dst_pitch);
+ m_dst_pitch &= 0x7ff;
+ })
+ );
+ map(0x828c, 0x828d).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_rect_width);
+ m_rect_width &= 0x7ff;
+ m_rect_width ++;
+ })
+ );
+ map(0x828e, 0x828f).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_rect_height);
+ m_rect_height &= 0x7ff;
+ m_rect_height ++;
+ })
+ );
+ map(0x8290, 0x8293).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_fg_color);
+ m_fg_color &= 0xff'ffff;
+ if (ACCESSING_BITS_24_31)
+ m_fg_rop = data >> 24;
+ })
+ );
+ map(0x8294, 0x8297).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_bg_color);
+ m_bg_color &= 0xff'ffff;
+ if (ACCESSING_BITS_24_31)
+ m_bg_rop = data >> 24;
+ })
+ );
+ map(0x8298, 0x829f).lw8(NAME([this] (offs_t offset, u8 data) { m_mask[offset] = data; }));
+ map(0x82a0, 0x82a1).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_clip_left);
+ m_clip_left &= 0x7ff;
+ })
+ );
+ map(0x82a2, 0x82a3).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_clip_top);
+ m_clip_top &= 0x7ff;
+ })
+ );
+ map(0x82a4, 0x82a5).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_clip_right);
+ m_clip_right &= 0x7ff;
+ })
+ );
+ map(0x82a6, 0x82a7).lw16(
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_clip_bottom);
+ m_clip_bottom &= 0x7ff;
+ })
+ );
+
// HACK: fake Turbo Queue so to not lockup windows
- map(0x82a8, 0x82ab).lr32(NAME([] () { return 0x8000'0100; }));
+ map(0x82a8, 0x82a9).lr16(
+ NAME([] (offs_t offset) { return 0x0100; })
+ );
+ map(0x82aa, 0x82ab).lrw16(
+ NAME([] (offs_t offset) { return 0x8000; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) {
+ COMBINE_DATA(&m_draw_command);
+ if (mem_mask == 0xffff)
+ trigger_2d_command();
+ })
+ );
+
+ map(0x82ac, 0x82eb).lw8(NAME([this] (offs_t offset, u8 data) {
+ m_pattern_data[offset] = data;
+ }));
map(0x8378, 0x837f).w(m_vga, FUNC(sis6326_vga_device::cursor_mmio_w));
- // Same deal, 3D Engine Status
+ // HACK: Same deal for 3D Engine Status
map(0x89fc, 0x89ff).lr32(NAME([] () { return (0x3ff << 16) | 3; }));
}
@@ -163,6 +261,282 @@ void sis6326_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory
}
/*
+ * 2d drawing
+ */
+
+const sis6326_pci_device::get_src_func sis6326_pci_device::get_src_table[4] =
+{
+ &sis6326_pci_device::get_src_bgcol,
+ &sis6326_pci_device::get_src_fgcol,
+ &sis6326_pci_device::get_src_mem,
+ &sis6326_pci_device::get_src_cpu
+};
+
+
+u8 sis6326_pci_device::get_src_bgcol(u32 offset_base, u32 x)
+{
+ return m_bg_color;
+}
+
+u8 sis6326_pci_device::get_src_fgcol(u32 offset_base, u32 x)
+{
+ return m_fg_color;
+}
+
+u8 sis6326_pci_device::get_src_mem(u32 offset_base, u32 x)
+{
+ return m_vga->read_memory(offset_base + x);
+}
+
+// TODO: no idea about this yet
+u8 sis6326_pci_device::get_src_cpu(u32 offset_base, u32 x)
+{
+ return x & 1 ? 0x55 : 0xaa;
+}
+
+const sis6326_pci_device::get_pat_func sis6326_pci_device::get_pat_table[4] =
+{
+ &sis6326_pci_device::get_pat_bgcol,
+ &sis6326_pci_device::get_pat_fgcol,
+ &sis6326_pci_device::get_pat_regs,
+ &sis6326_pci_device::get_pat_ddraw
+};
+
+u8 sis6326_pci_device::get_pat_bgcol(u32 y, u32 x)
+{
+ return m_bg_color;
+}
+
+u8 sis6326_pci_device::get_pat_fgcol(u32 y, u32 x)
+{
+ return m_fg_color;
+}
+
+// TODO: not yet sure about how this works either
+// testable in win98se shutdown options
+u8 sis6326_pci_device::get_pat_regs(u32 y, u32 x)
+{
+ return m_pattern_data[x & 3];
+}
+
+// TODO: this is special, uses regs in a different way
+u8 sis6326_pci_device::get_pat_ddraw(u32 y, u32 x)
+{
+ return x & 1 ? 0x55 : 0xaa;
+}
+
+// TODO: copied from s3virge, really needs moving in a common interface
+// https://learn.microsoft.com/en-us/windows/win32/gdi/ternary-raster-operations
+uint32_t sis6326_pci_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat)
+{
+ uint32_t ret = 0;
+
+ switch(rop)
+ {
+ case 0x00: // 0
+ ret = 0;
+ break;
+ case 0x0a: // DPna
+ ret = (dst & (~pat));
+ break;
+ case 0x22: // DSna
+ ret = (dst & (~src));
+ break;
+ case 0x33: // Sn
+ ret = ~src;
+ break;
+ case 0x55: // Dn
+ ret = ~dst;
+ break;
+ case 0x5a: // DPx
+ ret = dst ^ pat;
+ break;
+ case 0x66: // DSx
+ ret = dst ^ src;
+ break;
+ case 0x88: // DSa
+ ret = dst & src;
+ break;
+ case 0xaa: // D
+ ret = dst;
+ break;
+ case 0xb8: // PSDPxax
+ ret = ((dst ^ pat) & src) ^ pat;
+ break;
+ case 0xbb: // DSno
+ ret = (dst | (~src));
+ break;
+ case 0xca: // DPSDxax (moneynet install screen, no effective change?)
+ ret = ((src ^ dst) & pat) ^ dst;
+ 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;
+ case 0xff: // 1
+ ret = 0xffffffff;
+ break;
+ default:
+ popmessage("bus/pci/sis6326.cpp: Unimplemented ROP 0x%02x",rop);
+ }
+
+ return ret;
+}
+
+
+void sis6326_pci_device::trigger_2d_command()
+{
+ const u8 src_select = m_draw_command & 3;
+ const u8 pat_select = (m_draw_command >> 2) & 3;
+ const s8 x_dir = BIT(m_draw_command, 4) ? 1 : -1;
+ const s8 y_dir = BIT(m_draw_command, 5) ? 1 : -1;
+ const bool clip_enable = !!BIT(m_draw_command, 6);
+ const bool clip_external = !!BIT(m_draw_command, 7);
+ const u8 cmd_type = (m_draw_command >> 8) & 3;
+ const std::string src_types[] = { "bgcol", "fgcol", "memory", "CPU" };
+ // NOTE: pat type 3 may really select Direct Draw mode
+ const std::string pat_types[] = { "bgcol", "fgcol", "pattern", "<reserved>" };
+ LOG("Command: %04x: SRC %s, PAT %s, XY: %d|%d, clip: %d%d\n"
+ , m_draw_command, src_types[src_select], pat_types[pat_select]
+ , x_dir, y_dir, clip_enable, clip_external
+ );
+ if (clip_enable)
+ {
+ LOG("cliprange X %d %d ~ Y %d %d\n", m_clip_left, m_clip_right, m_clip_top, m_clip_bottom);
+ // (a very unlikely) sanity check
+ if (m_dst_pitch == 0)
+ {
+ LOG("\tWarning: dst pitch == 0, ignored!\n");
+ return;
+ }
+ }
+
+ // bits 15-14 are r/o
+ // TODO: currently using 256 colors only
+ // how this even acknowledge a change in color mode?
+ switch(cmd_type)
+ {
+ case 0:
+ {
+ LOG("\tBitBlt\n");
+ LOG("\tSRC Addr %06x DST Addr %06x Sel %02x\n", m_src_start_addr, m_dst_start_addr, m_draw_sel);
+ LOG("\tSRC Pitch %d DST Pitch %d Rect %dx%d\n", m_src_pitch, m_dst_pitch, m_rect_width, m_rect_height);
+ LOG("\tFG ROP %02x Color %06x | BG ROP %02x Color %06x\n", m_fg_rop, m_fg_color, m_bg_rop, m_bg_color);
+
+ for (s32 y = 0; y < m_rect_height; y++)
+ {
+ const s32 yi = y * y_dir;
+ if (clip_enable)
+ {
+ // clipping ranges are derived from the addresses (no explicit X/Y)
+ const s16 dst_y = yi + (m_dst_start_addr / m_dst_pitch);
+ if ((dst_y == std::clamp<u16>(dst_y, m_clip_top, m_clip_bottom)) ^ clip_external)
+ continue;
+ }
+
+ const u32 src_base = (yi * m_src_pitch) + m_src_start_addr;
+ const u32 dst_base = (yi * m_dst_pitch) + m_dst_start_addr;
+ for (s32 x = 0; x < m_rect_width; x++)
+ {
+ const s32 xi = x * x_dir;
+
+ if (clip_enable)
+ {
+ const u16 dst_x = xi + (m_dst_start_addr % m_dst_pitch);
+ if ((dst_x == std::clamp<u16>(dst_x, m_clip_left, m_clip_right)) ^ clip_external)
+ continue;
+ }
+
+ const u8 src = (this->*get_src_table[src_select])(src_base, xi);
+ const u8 dst = m_vga->read_memory(xi + dst_base);
+ const u8 pat = (this->*get_pat_table[pat_select])(y, x);
+ const u8 res = GetROP(m_fg_rop, src, dst, pat) & 0xff;
+ m_vga->write_memory(xi + dst_base, res);
+ }
+ }
+
+ break;
+ }
+ case 1:
+ {
+ LOG("\tBitBlt with mask\n");
+ // ...
+ break;
+ }
+ case 2:
+ {
+ const bool color_exp = !!BIT(m_draw_command, 12);
+ const bool font_exp = !!BIT(m_draw_command, 13);
+ LOG("\tColor/Font expansion: Color enhanced %d Font enhanced %d\n", color_exp, font_exp);
+ LOG("\tSRC Addr %06x DST Addr %06x Sel %02x\n", m_src_start_addr, m_dst_start_addr, m_draw_sel);
+ LOG("\tSRC Pitch %d DST Pitch %d Rect %dx%d\n", m_src_pitch, m_dst_pitch, m_rect_width, m_rect_height);
+ LOG("\tFG ROP %02x Color %06x | BG ROP %02x Color %06x\n", m_fg_rop, m_fg_color, m_bg_rop, m_bg_color);
+
+ if (m_rect_width > 8)
+ {
+ LOG("\tWarning: rect width > 8, ignored!\n");
+ return;
+ }
+
+ for (s32 y = 0; y < m_rect_height; y++)
+ {
+ const s32 yi = y * y_dir;
+
+ if (clip_enable)
+ {
+ const u16 dst_y = yi + (m_dst_start_addr / m_dst_pitch);
+ if ((dst_y == std::clamp<u16>(dst_y, m_clip_top, m_clip_bottom)) ^ clip_external)
+ continue;
+ }
+
+ const u8 pattern_base = y;
+ const u32 src_base = (y * m_src_pitch * y_dir) + m_src_start_addr;
+ const u32 dst_base = (y * m_dst_pitch * y_dir) + m_dst_start_addr;
+
+ for (s32 x = 0; x < m_rect_width; x++)
+ {
+ const s32 xi = x * x_dir;
+
+ if (clip_enable)
+ {
+ const u16 dst_x = xi + (m_dst_start_addr % m_dst_pitch);
+ if ((dst_x == std::clamp<u16>(dst_x, m_clip_left, m_clip_right)) ^ clip_external)
+ continue;
+ }
+
+ const u8 src = (this->*get_src_table[src_select])(src_base, xi);
+ const u8 dst = m_vga->read_memory(xi + dst_base);
+ const u8 dot = (m_pattern_data[pattern_base] >> (7 - x) & 1);
+ // ROP and pattern depends on pattern
+ // win98se start menu hovering depends on this
+ const u8 res = GetROP(dot ? m_fg_rop : m_bg_rop, src, dst, dot ? m_fg_color : m_bg_color) & 0xff;
+ m_vga->write_memory(xi + dst_base, res & 0xff);
+ }
+ }
+
+ break;
+ }
+ case 3:
+ {
+ const bool major_axis = !!BIT(m_draw_command, 10);
+ const bool last_pixel = !!BIT(m_draw_command, 11);
+ LOG("\tLine: major axis %s %d\n", major_axis ? "Y" : "X", !last_pixel);
+ // ...
+ break;
+ }
+ }
+
+}
+
+/*
* AGP overrides
*/
diff --git a/src/devices/bus/pci/sis6326.h b/src/devices/bus/pci/sis6326.h
index bd79771a13e..ab5db4f566b 100644
--- a/src/devices/bus/pci/sis6326.h
+++ b/src/devices/bus/pci/sis6326.h
@@ -14,7 +14,8 @@ class sis6326_pci_device : public pci_card_device
public:
sis6326_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- static constexpr feature_type unemulated_features() { return feature::GRAPHICS; }
+ // Partial working 2d graphics, no Turbo Queue, no 3d graphics, no TV Out
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
protected:
sis6326_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -42,6 +43,37 @@ private:
u8 vram_r(offs_t offset);
void vram_w(offs_t offset, uint8_t data);
+
+ // BitBlt engine
+ void trigger_2d_command();
+ u32 m_src_start_addr;
+ u32 m_dst_start_addr;
+ u8 m_draw_sel;
+ u16 m_src_pitch, m_dst_pitch;
+ u16 m_rect_width, m_rect_height;
+ u32 m_fg_color, m_bg_color;
+ u8 m_fg_rop, m_bg_rop;
+ u8 m_mask[8];
+ u16 m_clip_top, m_clip_left, m_clip_bottom, m_clip_right;
+
+ u16 m_draw_command;
+ u8 m_pattern_data[128];
+
+ typedef u8 (sis6326_pci_device::*get_src_func)(u32 offset_base, u32 x);
+ static const get_src_func get_src_table[4];
+ u8 get_src_bgcol(u32 offset_base, u32 x);
+ u8 get_src_fgcol(u32 offset_base, u32 x);
+ u8 get_src_mem(u32 offset_base, u32 x);
+ u8 get_src_cpu(u32 offset_base, u32 x);
+
+ typedef u8 (sis6326_pci_device::*get_pat_func)(u32 offset_base, u32 x);
+ static const get_pat_func get_pat_table[4];
+ u8 get_pat_bgcol(u32 y, u32 x);
+ u8 get_pat_fgcol(u32 y, u32 x);
+ u8 get_pat_regs(u32 y, u32 x);
+ u8 get_pat_ddraw(u32 y, u32 x);
+ u32 GetROP(u8 rop, u32 src, u32 dst, u32 pat);
+
};
class sis6326_agp_device : public sis6326_pci_device
diff --git a/src/devices/video/pc_vga_matrox.cpp b/src/devices/video/pc_vga_matrox.cpp
index f9551f21935..27b65ac35dc 100644
--- a/src/devices/video/pc_vga_matrox.cpp
+++ b/src/devices/video/pc_vga_matrox.cpp
@@ -732,22 +732,22 @@ uint32_t matrox_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &b
static int m_test_trigger = 1;
const int m_test_y = cliprect.max_y;
- if(machine().input().code_pressed(JOYCODE_X_RIGHT_SWITCH))
+ if(machine().input().code_pressed(JOYCODE_HAT1RIGHT))
m_test_x += 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);
- if(machine().input().code_pressed(JOYCODE_X_LEFT_SWITCH))
+ if(machine().input().code_pressed(JOYCODE_HAT1LEFT))
m_test_x -= 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);
- //if(machine().input().code_pressed(JOYCODE_Y_DOWN_SWITCH))
+ //if(machine().input().code_pressed(JOYCODE_HAT1DOWN))
// m_test_y++;
- //if(machine().input().code_pressed(JOYCODE_Y_UP_SWITCH))
+ //if(machine().input().code_pressed(JOYCODE_HAT1UP))
// m_test_y--;
- if(machine().input().code_pressed(JOYCODE_Y_DOWN_SWITCH))
+ if(machine().input().code_pressed(JOYCODE_HAT1DOWN))
m_start_offs+= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
- if(machine().input().code_pressed(JOYCODE_Y_UP_SWITCH))
+ if(machine().input().code_pressed(JOYCODE_HAT1UP))
m_start_offs-= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
m_start_offs %= vga.svga_intf.vram_size;
diff --git a/src/devices/video/pc_vga_sis.cpp b/src/devices/video/pc_vga_sis.cpp
index 6302a6d9d34..0359520ff8c 100644
--- a/src/devices/video/pc_vga_sis.cpp
+++ b/src/devices/video/pc_vga_sis.cpp
@@ -78,6 +78,7 @@ void sis6326_vga_device::device_start()
save_item(NAME(m_crtc_unlock_reg));
save_item(NAME(m_seq_unlock_reg));
+ save_item(NAME(m_ramdac_mode));
save_item(NAME(m_ext_sr07));
save_item(NAME(m_ext_sr0b));
save_item(NAME(m_ext_sr0c));
@@ -115,6 +116,7 @@ void sis6326_vga_device::device_reset()
m_crtc_unlock_reg = false;
m_seq_unlock_reg = false;
+ m_ramdac_mode = 0;
m_ext_sr07 = m_ext_sr0b = m_ext_sr0c = m_ext_sr23 = m_ext_sr33 = 0;
m_ext_sr34 = m_ext_sr35 = m_ext_sr38 = m_ext_sr39 = m_ext_sr3c = 0;
m_ext_ge26 = m_ext_ge27 = 0;
@@ -803,26 +805,26 @@ uint32_t sis6326_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &
}
#if DEBUG_VRAM_VIEWER
- static int m_test_x = 640, m_start_offs;
+ static int m_test_x = 1024, m_start_offs;
static int m_test_trigger = 1;
const int m_test_y = cliprect.max_y;
- if(machine().input().code_pressed(KEYCODE_RIGHT))
+ if(machine().input().code_pressed(JOYCODE_HAT1RIGHT))
m_test_x += 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);
- if(machine().input().code_pressed(KEYCODE_LEFT))
+ if(machine().input().code_pressed(JOYCODE_HAT1LEFT))
m_test_x -= 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);
- //if(machine().input().code_pressed(JOYCODE_Y_DOWN_SWITCH))
+ //if(machine().input().code_pressed(JOYCODE_HAT1DOWN))
// m_test_y++;
- //if(machine().input().code_pressed(JOYCODE_Y_UP_SWITCH))
+ //if(machine().input().code_pressed(JOYCODE_HAT1UP))
// m_test_y--;
- if(machine().input().code_pressed(KEYCODE_DOWN))
+ if(machine().input().code_pressed(JOYCODE_HAT1DOWN))
m_start_offs+= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
- if(machine().input().code_pressed(KEYCODE_UP))
+ if(machine().input().code_pressed(JOYCODE_HAT1UP))
m_start_offs-= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
m_start_offs %= vga.svga_intf.vram_size;
diff --git a/src/devices/video/pc_vga_sis.h b/src/devices/video/pc_vga_sis.h
index e903bc65bc7..0b771d75a90 100644
--- a/src/devices/video/pc_vga_sis.h
+++ b/src/devices/video/pc_vga_sis.h
@@ -31,6 +31,16 @@ public:
void cursor_mmio_w(offs_t offset, u16 data, u16 mem_mask);
+ u8 read_memory(u32 address)
+ {
+ return vga.memory[address % vga.svga_intf.vram_size];
+ }
+
+ void write_memory(u32 address, u8 data)
+ {
+ vga.memory[address % vga.svga_intf.vram_size] = data;
+ }
+
protected:
sis6326_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);