summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2023-07-04 19:10:46 +0200
committer GitHub <noreply@github.com>2023-07-04 19:10:46 +0200
commit498b7a0a7ddf138e83b79acbc159597587db3804 (patch)
treef0e56fee0f4c89734d4fb3c5eef64bf4b298c38b /src/devices
parent9013ece6ee4883037265626684d7d45803959dd2 (diff)
video/pc_vga.cpp: part 2 of interface modernization (#11315)
* video/pc_vga.cpp: update QA, move SVGA related function to bottom of file * chore: rename clgd542x.cpp -> pc_vga_cirrus.cpp * chore: move SiS630 SVGA portion to pc_vga_sis.cpp * chore: intermediate step to convert crtc/seq/attribute/gc_reg_read/write to maps from violating parties * video/pc_vga_cirrus.cpp: preliminary implementation of hidden DAC mode * misc/gambl186.cpp: fix compile * pc_vga_cirrus.cpp: fix gambl186 regression * chore: convert pc_vga sequencer regs to space memory * chore: make sure that address_space_config is preserved when inheriting * trs/vis.cpp: convert VGA to sequencer_map * chore: move s3virge out of bus/isa * pc_vga.cpp: convert ATC to attribute_map * pc_vga.cpp: convert GC to gc_map * pc_vga.cpp: convert CRTC to crtc_map * fixes trs/vis.cpp refresh rate by chain reaction (40 Hz -> 61 Hz) * video/s3virge.cpp: fix regression * video/pc_vga.cpp: reorder functions * chore: modernize VGA main I/O interfaces * video/clgd546x_laguna.cpp: update to latest * konami/konmedal020.cpp: fix -validate * video/pc_vga.cpp: use yet another custom address_map_constructor in place of the non-working memory_view pattern * video/ibm8514a.cpp: address self review [skip ci]
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/bus/isa/svga_cirrus.cpp21
-rw-r--r--src/devices/bus/isa/svga_cirrus.h6
-rw-r--r--src/devices/bus/isa/svga_s3.cpp49
-rw-r--r--src/devices/bus/isa/svga_s3.h11
-rw-r--r--src/devices/bus/isa/svga_trident.cpp20
-rw-r--r--src/devices/bus/isa/svga_trident.h4
-rw-r--r--src/devices/bus/isa/svga_tseng.cpp9
-rw-r--r--src/devices/bus/isa/svga_tseng.h2
-rw-r--r--src/devices/bus/isa/vga.cpp9
-rw-r--r--src/devices/bus/isa/vga.h2
-rw-r--r--src/devices/bus/isa/vga_ati.cpp33
-rw-r--r--src/devices/bus/isa/vga_ati.h5
-rw-r--r--src/devices/machine/sis630_gui.cpp390
-rw-r--r--src/devices/machine/sis630_gui.h46
-rw-r--r--src/devices/video/clgd546x_laguna.cpp87
-rw-r--r--src/devices/video/clgd546x_laguna.h9
-rw-r--r--src/devices/video/ibm8514a.cpp16
-rw-r--r--src/devices/video/pc_vga.cpp2412
-rw-r--r--src/devices/video/pc_vga.h86
-rw-r--r--src/devices/video/pc_vga_ati.cpp17
-rw-r--r--src/devices/video/pc_vga_ati.h1
-rw-r--r--src/devices/video/pc_vga_cirrus.cpp (renamed from src/devices/video/clgd542x.cpp)1293
-rw-r--r--src/devices/video/pc_vga_cirrus.h (renamed from src/devices/video/clgd542x.h)30
-rw-r--r--src/devices/video/pc_vga_nvidia.cpp376
-rw-r--r--src/devices/video/pc_vga_nvidia.h12
-rw-r--r--src/devices/video/pc_vga_s3.cpp867
-rw-r--r--src/devices/video/pc_vga_s3.h18
-rw-r--r--src/devices/video/pc_vga_sis.cpp301
-rw-r--r--src/devices/video/pc_vga_sis.h44
-rw-r--r--src/devices/video/pc_vga_trident.cpp1137
-rw-r--r--src/devices/video/pc_vga_trident.h36
-rw-r--r--src/devices/video/pc_vga_tseng.cpp445
-rw-r--r--src/devices/video/pc_vga_tseng.h25
-rw-r--r--src/devices/video/pc_xga.cpp97
-rw-r--r--src/devices/video/pc_xga.h9
-rw-r--r--src/devices/video/riva128.cpp87
-rw-r--r--src/devices/video/riva128.h6
-rw-r--r--src/devices/video/s3virge.cpp (renamed from src/devices/bus/isa/s3virge.cpp)774
-rw-r--r--src/devices/video/s3virge.h (renamed from src/devices/bus/isa/s3virge.h)15
-rw-r--r--src/devices/video/virge_pci.cpp143
-rw-r--r--src/devices/video/virge_pci.h14
41 files changed, 4007 insertions, 4957 deletions
diff --git a/src/devices/bus/isa/svga_cirrus.cpp b/src/devices/bus/isa/svga_cirrus.cpp
index 750d0f41142..25275181781 100644
--- a/src/devices/bus/isa/svga_cirrus.cpp
+++ b/src/devices/bus/isa/svga_cirrus.cpp
@@ -65,6 +65,11 @@ isa16_svga_cirrus_device::isa16_svga_cirrus_device(const machine_config &mconfig
{
}
+void isa16_svga_cirrus_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(cirrus_gd5430_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -76,11 +81,8 @@ void isa16_svga_cirrus_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "dm_clgd5430");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03d0_w)));
-
m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_cirrus_device::io_isa_map);
}
//-------------------------------------------------
@@ -145,6 +147,11 @@ isa16_svga_cirrus_gd542x_device::isa16_svga_cirrus_gd542x_device(const machine_c
{
}
+void isa16_svga_cirrus_gd542x_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(cirrus_gd5428_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -156,11 +163,9 @@ void isa16_svga_cirrus_gd542x_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "clgd542x");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03d0_w)));
-
m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_cirrus_gd542x_device::io_isa_map);
+
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/svga_cirrus.h b/src/devices/bus/isa/svga_cirrus.h
index d2e7d75595c..0286d3d8510 100644
--- a/src/devices/bus/isa/svga_cirrus.h
+++ b/src/devices/bus/isa/svga_cirrus.h
@@ -6,7 +6,7 @@
#pragma once
#include "isa.h"
-#include "video/clgd542x.h"
+#include "video/pc_vga_cirrus.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -31,6 +31,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<cirrus_gd5430_device> m_vga;
};
@@ -54,6 +56,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<cirrus_gd5428_device> m_vga;
};
diff --git a/src/devices/bus/isa/svga_s3.cpp b/src/devices/bus/isa/svga_s3.cpp
index 1315c471679..57ad259fd99 100644
--- a/src/devices/bus/isa/svga_s3.cpp
+++ b/src/devices/bus/isa/svga_s3.cpp
@@ -1,10 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
-/***************************************************************************
+/**************************************************************************************************
ISA SVGA S3 wrapper
-***************************************************************************/
+ TODO:
+ - All these cards are really PCI and needs to be moved to video/virge_pci.cpp.
+
+**************************************************************************************************/
#include "emu.h"
#include "svga_s3.h"
@@ -86,6 +89,11 @@ isa16_svga_s3_device::isa16_svga_s3_device(const machine_config &mconfig, const
{
}
+void isa16_svga_s3_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -97,9 +105,8 @@ void isa16_svga_s3_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3_764");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_s3_device::io_isa_map);
+
m_isa->install16_device(0x82e8, 0x82eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currenty_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currenty_w)));
m_isa->install16_device(0x86e8, 0x86eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currentx_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currentx_w)));
m_isa->install16_device(0x8ae8, 0x8aeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_desty_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_desty_w)));
@@ -202,6 +209,11 @@ isa16_s3virge_device::isa16_s3virge_device(const machine_config &mconfig, const
{
}
+void isa16_s3virge_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3virge_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -213,9 +225,7 @@ void isa16_s3virge_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3virge");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_s3virge_device::io_isa_map);
m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
}
@@ -310,6 +320,12 @@ isa16_s3virgedx_device::isa16_s3virgedx_device(const machine_config &mconfig, co
{
}
+void isa16_s3virgedx_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3virgedx_vga_device::io_map));
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -321,11 +337,9 @@ void isa16_s3virgedx_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3virgedx");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_s3virgedx_device::io_isa_map);
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virgedx_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virgedx_vga_device::mem_w)));
save_item(NAME(m_lfb_enable));
save_item(NAME(m_lfb_start));
@@ -410,6 +424,11 @@ isa16_stealth3d2kpro_device::isa16_stealth3d2kpro_device(const machine_config &m
{
}
+void isa16_stealth3d2kpro_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3virgedx_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -421,11 +440,9 @@ void isa16_stealth3d2kpro_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "stealth3d");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_stealth3d2kpro_device::io_isa_map);
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virgedx_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virgedx_vga_device::mem_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/svga_s3.h b/src/devices/bus/isa/svga_s3.h
index 7009ce28167..c414c7ee6f6 100644
--- a/src/devices/bus/isa/svga_s3.h
+++ b/src/devices/bus/isa/svga_s3.h
@@ -6,9 +6,8 @@
#pragma once
#include "isa.h"
-#include "s3virge.h"
-
#include "video/pc_vga_s3.h"
+#include "video/s3virge.h"
//**************************************************************************
@@ -36,6 +35,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<s3_vga_device> m_vga;
required_device<ibm8514a_device> m_8514;
@@ -62,6 +63,8 @@ protected:
void linear_config_changed_w(int state);
+ void io_isa_map(address_map &map);
+
private:
required_device<s3virge_vga_device> m_vga;
};
@@ -87,6 +90,8 @@ protected:
void linear_config_changed_w(int state);
+ void io_isa_map(address_map &map);
+
private:
required_device<s3virgedx_vga_device> m_vga;
bool m_lfb_enable;
@@ -115,6 +120,8 @@ protected:
void linear_config_changed_w(int state);
+ void io_isa_map(address_map &map);
+
private:
required_device<s3virgedx_vga_device> m_vga;
};
diff --git a/src/devices/bus/isa/svga_trident.cpp b/src/devices/bus/isa/svga_trident.cpp
index 0c5024d08ba..790a405770e 100644
--- a/src/devices/bus/isa/svga_trident.cpp
+++ b/src/devices/bus/isa/svga_trident.cpp
@@ -52,6 +52,11 @@ isa16_svga_tvga9000_device::isa16_svga_tvga9000_device(const machine_config &mco
{
}
+void isa16_svga_tvga9000_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(tvga9000_device::io_map));
+}
+
uint8_t isa16_svga_tvga9000_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa16_svga_tvga9000_device::device_start()
@@ -60,9 +65,8 @@ void isa16_svga_tvga9000_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "tvga9000");
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_tvga9000_device::io_isa_map);
+
m_isa->install_device(0x43c4, 0x43cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_w)));
m_isa->install_device(0x83c4, 0x83cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_w)));
@@ -122,6 +126,11 @@ isa16_svga_tgui9680_device::isa16_svga_tgui9680_device(const machine_config &mco
{
}
+void isa16_svga_tgui9680_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(trident_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -133,9 +142,8 @@ void isa16_svga_tgui9680_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "tgui9680");
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_tgui9680_device::io_isa_map);
+
m_isa->install_device(0x43c4, 0x43cb, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_43c6_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_43c6_w)));
m_isa->install_device(0x83c4, 0x83cb, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_83c6_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_83c6_w)));
diff --git a/src/devices/bus/isa/svga_trident.h b/src/devices/bus/isa/svga_trident.h
index 39afd40be96..1ca7b622009 100644
--- a/src/devices/bus/isa/svga_trident.h
+++ b/src/devices/bus/isa/svga_trident.h
@@ -34,6 +34,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<tvga9000_device> m_vga;
};
@@ -56,6 +58,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<trident_vga_device> m_vga;
};
diff --git a/src/devices/bus/isa/svga_tseng.cpp b/src/devices/bus/isa/svga_tseng.cpp
index be93e3188fe..39a6533f3c7 100644
--- a/src/devices/bus/isa/svga_tseng.cpp
+++ b/src/devices/bus/isa/svga_tseng.cpp
@@ -118,11 +118,14 @@ void isa8_svga_et4k_device::remap(int space_id, offs_t start, offs_t end)
map_io();
}
+void isa8_svga_et4k_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(tseng_vga_device::io_map));
+}
+
void isa8_svga_et4k_device::map_io()
{
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_svga_et4k_device::io_isa_map);
}
void isa8_svga_et4k_device::map_ram()
diff --git a/src/devices/bus/isa/svga_tseng.h b/src/devices/bus/isa/svga_tseng.h
index f1b56423ef0..f842889e027 100644
--- a/src/devices/bus/isa/svga_tseng.h
+++ b/src/devices/bus/isa/svga_tseng.h
@@ -41,6 +41,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
void map_io();
void map_ram();
diff --git a/src/devices/bus/isa/vga.cpp b/src/devices/bus/isa/vga.cpp
index b573f4c5701..3fa8752ae91 100644
--- a/src/devices/bus/isa/vga.cpp
+++ b/src/devices/bus/isa/vga.cpp
@@ -62,6 +62,11 @@ isa8_vga_device::isa8_vga_device(const machine_config &mconfig, const char *tag,
{
}
+void isa8_vga_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -73,9 +78,7 @@ void isa8_vga_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "ibm_vga");
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_vga_device::io_isa_map);
m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(vga_device::mem_w)));
}
diff --git a/src/devices/bus/isa/vga.h b/src/devices/bus/isa/vga.h
index c1b4d7226aa..1a3a530160d 100644
--- a/src/devices/bus/isa/vga.h
+++ b/src/devices/bus/isa/vga.h
@@ -33,6 +33,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<vga_device> m_vga;
};
diff --git a/src/devices/bus/isa/vga_ati.cpp b/src/devices/bus/isa/vga_ati.cpp
index b3a7c1414bc..bee1f847c18 100644
--- a/src/devices/bus/isa/vga_ati.cpp
+++ b/src/devices/bus/isa/vga_ati.cpp
@@ -159,6 +159,21 @@ isa16_vga_mach64_device::isa16_vga_mach64_device(const machine_config &mconfig,
{
}
+void isa16_vga_gfxultra_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(ati_vga_device::io_map));
+}
+
+void isa16_vga_gfxultrapro_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(mach32_device::io_map));
+}
+
+void isa16_vga_mach64_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(mach64_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -174,9 +189,9 @@ void isa16_vga_gfxultra_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(ati_vga_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_8514, FUNC(mach8_device::ibm8514_status_r)), write8sm_delegate(*m_8514, FUNC(mach8_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_gfxultra_device::io_isa_map);
+
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vtotal_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vtotal_w)));
m_isa->install16_device(0x12ec, 0x12ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_config1_r)), write16smo_delegate(*this));
m_isa->install16_device(0x16e8, 0x16eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vdisp_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vdisp_w)));
@@ -235,9 +250,9 @@ void isa16_vga_gfxultrapro_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(mach32_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_vga, FUNC(mach32_device::mach32_status_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_gfxultrapro_device::io_isa_map);
+
m_isa->install16_device(0xaec, 0xaef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_l_w)));
m_isa->install16_device(0xeec, 0xeef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_h_w)));
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vtotal_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vtotal_w)));
@@ -304,9 +319,9 @@ void isa16_vga_mach64_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(mach64_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_vga, FUNC(mach64_device::mach32_status_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_mach64_device::io_isa_map);
+
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vtotal_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vtotal_w)));
m_isa->install16_device(0x12ec, 0x12ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_config1_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach64_config1_w)));
m_isa->install16_device(0x16e8, 0x16eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vdisp_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vdisp_w)));
diff --git a/src/devices/bus/isa/vga_ati.h b/src/devices/bus/isa/vga_ati.h
index 5ca355f590c..3b7c064bbaa 100644
--- a/src/devices/bus/isa/vga_ati.h
+++ b/src/devices/bus/isa/vga_ati.h
@@ -42,6 +42,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<ati_vga_device> m_vga;
required_device<mach8_device> m_8514;
@@ -66,6 +68,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<mach32_device> m_vga;
};
@@ -89,6 +93,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
private:
required_device<mach64_device> m_vga;
};
diff --git a/src/devices/machine/sis630_gui.cpp b/src/devices/machine/sis630_gui.cpp
index cdbd4fe9db9..8cc245cbed0 100644
--- a/src/devices/machine/sis630_gui.cpp
+++ b/src/devices/machine/sis630_gui.cpp
@@ -29,7 +29,6 @@
- 2d acceleration;
- Turbo queue stuff;
- AGP;
- - interlace (cfr. xubuntu 6.10 splash screen on 1024x768x32);
- xubuntu 6.10 splash screen is decentered (zooming?)
- xubuntu 6.10 splash screen text is unreadable or not visible depending on res selected;
- Interface with '301 bridge (a lovely can of worms);
@@ -43,10 +42,9 @@
#define LOG_TODO (1U << 2) // log unimplemented registers
#define LOG_MAP (1U << 3) // log full remaps
#define LOG_AGP (1U << 4) // log AGP
-#define LOG_SVGA (1U << 5) // log SVGA
-#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_AGP | LOG_SVGA)
-//#define LOG_OUTPUT_FUNC osd_printf_warning
+#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_AGP)
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
@@ -54,303 +52,6 @@
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
#define LOGAGP(...) LOGMASKED(LOG_AGP, __VA_ARGS__)
-#define LOGSVGA(...) LOGMASKED(LOG_SVGA, __VA_ARGS__)
-
-/**************************
- *
- * SVGA implementation
- *
- *************************/
-
-// 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 SVGA")
-
-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)
-{
-
-}
-
-void sis630_svga_device::device_start()
-{
- svga_device::device_start();
- zero();
-
- // Avoid an infinite loop when displaying. 0 is not possible anyway.
- vga.crtc.maximum_scan_line = 1;
-
- // copy over interfaces
- vga.svga_intf.seq_regcount = 0x05;
- vga.svga_intf.crtc_regcount = 0x27;
- vga.svga_intf.vram_size = 64*1024*1024;
- //vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
-}
-
-void sis630_svga_device::device_reset()
-{
- svga_device::device_reset();
-
- m_svga_bank_reg_w = m_svga_bank_reg_r = 0;
- m_unlock_reg = false;
- //m_dual_seg_mode = false;
-}
-
-// Page 144
-uint8_t sis630_svga_device::crtc_reg_read(uint8_t index)
-{
- if (index < 0x19)
- return svga_device::crtc_reg_read(index);
-
- // make sure '301 CRT2 is not enabled
- if (index == 0x30)
- return 0;
-
- if (index == 0x31)
- return 0x60;
-
- if (index == 0x32)
- return 0x20;
-
- // TODO: if one of these is 0xff then it enables a single port transfer to $b8000
- return m_crtc_ext_regs[index];
-}
-
-void sis630_svga_device::crtc_reg_write(uint8_t index, uint8_t data)
-{
- if (index < 0x19)
- svga_device::crtc_reg_write(index, data);
- else
- {
- m_crtc_ext_regs[index] = data;
- }
-}
-
-uint8_t sis630_svga_device::seq_reg_read(uint8_t index)
-{
- switch (index)
- {
- // extended id register
- case 0x05:
- return m_unlock_reg ? 0xa1 : 0x21;
- case 0x06:
- return m_ramdac_mode;
- case 0x07:
- return m_ext_misc_ctrl_0;
- case 0x0a:
- return m_ext_vert_overflow;
- case 0x0b:
- case 0x0c:
- return m_ext_horz_overflow[index - 0xb];
- case 0x0d:
- return vga.crtc.start_addr_latch >> 16;
- case 0x14:
- // sis_main.c calculates VRAM size in two ways:
- // 1. the legacy way ('300), by probing this register
- // 2. by reading '630 PCI host register $63 (as shared DRAM?)
- // Method 1 seems enough to enforce "64MB" message at POST,
- // 2 is probably more correct but unsure about how to change the shared area in BIOS
- // (shutms11 will always write a "0x41" on fresh CMOS then a "0x47"
- // on successive boots no matter what)
- const u8 bus_width = m_seq_ext_regs[index] & 0xc0;
- return (bus_width) | ((vga.svga_intf.vram_size / (1024 * 1024) - 1) & 0x3f);
- }
-
- //LOGSVGA("Unemulated index R [%02x]\n", index);
- return m_seq_ext_regs[index];
-}
-
-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()
-{
- // TODO: ext clock
- recompute_params_clock(1, XTAL(25'174'800).value());
-}
-
-
-void sis630_svga_device::seq_reg_write(uint8_t index, uint8_t data)
-{
- if (index < vga.svga_intf.seq_regcount)
- svga_device::seq_reg_write(index, data);
- else
- {
- if (index == 0x05)
- {
- m_unlock_reg = (data == 0x86);
- LOGSVGA("Unlock register write %02x (%s)\n", data, m_unlock_reg ? "unlocked" : "locked");
- }
- else
- {
- if (!m_unlock_reg)
- {
- LOGSVGA("Attempt to write to extended SVGA while locked [$%02x] -> %02x\n", index, data);
- return;
- }
-
- m_seq_ext_regs[index] = data;
-
- switch(index)
- {
- /*
- * x--- ---- GFX mode linear addressing enable
- * -x-- ---- GFX hardware cursor display
- * --x- ---- GFX mode interlace
- * ---x ---- True Color enable (ties with index 0x07 bit 2)
- * ---- x--- RGB16 enable
- * ---- -x-- RGB15 enable
- * ---- --x- enhanced GFX mode enable
- * ---- ---x enhanced text mode enable
- */
- case 0x06:
- m_ramdac_mode = data;
- LOGSVGA("RAMDAC mode %02x\n", data);
-
- if (!BIT(data, 1))
- {
- svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = svga.rgb32_en = 0;
- }
- else
- {
- if (BIT(data, 2))
- svga.rgb15_en = 1;
- if (BIT(data, 3))
- svga.rgb16_en = 1;
- std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
- }
- break;
- case 0x07:
- LOGSVGA("Extended Misc. Control register 0 (%02x) %02x\n", index, data);
- m_ext_misc_ctrl_0 = data;
- std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
- break;
- case 0x0a:
- LOGSVGA("Extended vertical Overflow register (%02x) %02x\n", index, data);
- m_ext_vert_overflow = data;
- vga.crtc.vert_retrace_end = (vga.crtc.vert_retrace_end & 0xf) | ((data & 0x20) >> 1);
- vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & 0x00ff) | ((data & 0x10) << 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();
- break;
- case 0x0b:
- //m_dual_seg_mode = bool(BIT(data, 3));
- LOGSVGA("Extended horizontal Overflow 1 (%02x) %02x\n", index, data);
- m_ext_horz_overflow[0] = data;
-
- vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0x00ff) | ((data & 0xc0) << 2);
- vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0x00ff) | ((data & 0x30) << 4);
- vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0x00ff) | ((data & 0x0c) << 6);
- vga.crtc.horz_total = (vga.crtc.horz_total & 0x00ff) | ((data & 0x03) << 8);
-
- recompute_params();
- break;
- case 0x0c:
- LOGSVGA("Extended horizontal Overflow 2 (%02x) %02x\n", index, data);
- m_ext_horz_overflow[1] = data;
-
- vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0x001f) | ((data & 0x04) << 3);
- vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0x003f) | ((data & 0x03) << 6);
- recompute_params();
- break;
- case 0x0d:
- LOGSVGA("Extended starting address register (%02x) %02x\n", index, data);
- vga.crtc.start_addr_latch &= ~0xff0000;
- vga.crtc.start_addr_latch |= data << 16;
- break;
- case 0x0e:
- LOGSVGA("Extended pitch register (%02x) %02x\n", index, data);
- // sis_main.c implicitly sets this with bits 0-3 granularity, assume being right
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x0f) << 8);
- break;
- case 0x1e:
- if (data & 0x40)
- popmessage("Warning: enable 2d engine");
- break;
- case 0x20:
- if (data & 0x81)
- popmessage("Warning: %s %s", BIT(data, 7) ? "PCI address enabled" : "", BIT(data, 0) ? "memory map I/O enable" : "");
- break;
- default:
- LOGSVGA("Extended write %02x %02x\n", index, data);
- break;
- }
- }
- }
-}
-
-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();
-}
-
-// read by gamecstl Kontron BIOS
-u8 sis630_svga_device::port_03c0_r(offs_t offset)
-{
- if (offset == 0xd)
- return m_svga_bank_reg_w;
- if (offset == 0xb)
- return m_svga_bank_reg_r;
-
- return svga_device::port_03c0_r(offset);
-}
-
-void sis630_svga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- // TODO: for '630 it's always with dual segment enabled?
-
- if (offset == 0xd)
- {
- //if (m_dual_seg_mode)
- m_svga_bank_reg_w = (data & 0x3f) * 0x10000;
- //else
- {
- // m_svga_bank_reg_w = (data >> 4) * 0x10000;
- // m_svga_bank_reg_r = (data & 0xf) * 0x10000;
- }
- return;
- }
-
- if (offset == 0xb)
- {
- //if (m_dual_seg_mode)
- m_svga_bank_reg_r = (data & 0x3f) * 0x10000;
- // otherwise ignored if dual segment mode disabled
- return;
- }
-
- svga_device::port_03c0_w(offset, data);
-}
-
-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 + m_svga_bank_reg_r);
- 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 + m_svga_bank_reg_w, data);
- return;
- }
- svga_device::mem_w(offset, data);
-}
/*****************************
*
@@ -515,9 +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, 0x3f).rw(FUNC(sis630_gui_device::vga_3b0_r), FUNC(sis630_gui_device::vga_3b0_w));
- map(0x40, 0x4f).rw(FUNC(sis630_gui_device::vga_3c0_r), FUNC(sis630_gui_device::vga_3c0_w));
- map(0x50, 0x5f).rw(FUNC(sis630_gui_device::vga_3d0_r), FUNC(sis630_gui_device::vga_3d0_w));
+ map(0x30, 0x5f).m(m_svga, FUNC(sis630_svga_device::io_map));
}
void sis630_gui_device::legacy_memory_map(address_map &map)
@@ -527,9 +226,7 @@ void sis630_gui_device::legacy_memory_map(address_map &map)
void sis630_gui_device::legacy_io_map(address_map &map)
{
- map(0x03b0, 0x03bf).rw(FUNC(sis630_gui_device::vga_3b0_r), FUNC(sis630_gui_device::vga_3b0_w));
- map(0x03c0, 0x03cf).rw(FUNC(sis630_gui_device::vga_3c0_r), FUNC(sis630_gui_device::vga_3c0_w));
- map(0x03d0, 0x03df).rw(FUNC(sis630_gui_device::vga_3d0_r), FUNC(sis630_gui_device::vga_3d0_w));
+ map(0x03b0, 0x03df).m(m_svga, FUNC(sis630_svga_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,
@@ -575,85 +272,6 @@ void sis630_gui_device::vram_w(offs_t offset, uint8_t data)
downcast<sis630_svga_device *>(m_svga.target())->mem_w(offset, data);
}
-u32 sis630_gui_device::vga_3b0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void sis630_gui_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 3, data >> 24);
-}
-
-
-u32 sis630_gui_device::vga_3c0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void sis630_gui_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 3, data >> 24);
-}
-
-u32 sis630_gui_device::vga_3d0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void sis630_gui_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 3, data >> 24);
-}
-
/*****************************
*
* 630 bridge PCI implementation
diff --git a/src/devices/machine/sis630_gui.h b/src/devices/machine/sis630_gui.h
index 460ba080eb7..600cd84d24e 100644
--- a/src/devices/machine/sis630_gui.h
+++ b/src/devices/machine/sis630_gui.h
@@ -7,45 +7,7 @@
#pragma once
#include "pci.h"
-#include "video/pc_vga.h"
-
-class sis630_svga_device : public svga_device
-{
-public:
- sis630_svga_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;
-
- virtual u8 port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual uint8_t crtc_reg_read(uint8_t index) override;
- virtual void crtc_reg_write(uint8_t index, uint8_t data) override;
- virtual uint8_t seq_reg_read(uint8_t index) override;
- virtual void seq_reg_write(uint8_t index, uint8_t data) override;
- virtual uint16_t offset() override;
- virtual void recompute_params() override;
-
- u8 m_crtc_ext_regs[0x100]{};
- u8 m_seq_ext_regs[0x100]{};
- u8 m_ramdac_mode = 0;
- u8 m_ext_misc_ctrl_0 = 0;
- u8 m_ext_vert_overflow = 0;
- u8 m_ext_horz_overflow[2]{};
- u32 m_svga_bank_reg_w = 0;
- u32 m_svga_bank_reg_r = 0;
- bool m_unlock_reg = false;
-
- std::tuple<u8, u8> flush_true_color_mode();
-// bool m_dual_seg_mode = false;
-};
-
-DECLARE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device)
-
+#include "video/pc_vga_sis.h"
class sis630_gui_device : public pci_device
{
@@ -79,12 +41,6 @@ private:
u8 vram_r(offs_t offset);
void vram_w(offs_t offset, uint8_t data);
- u32 vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
void subvendor_w(offs_t offset, u32 data, u32 mem_mask = ~0);
diff --git a/src/devices/video/clgd546x_laguna.cpp b/src/devices/video/clgd546x_laguna.cpp
index 12d684bb7e8..fd9b4621612 100644
--- a/src/devices/video/clgd546x_laguna.cpp
+++ b/src/devices/video/clgd546x_laguna.cpp
@@ -110,9 +110,7 @@ void cirrus_gd5465_laguna3d_device::legacy_memory_map(address_map &map)
void cirrus_gd5465_laguna3d_device::legacy_io_map(address_map &map)
{
- map(0x03b0, 0x03bf).rw(FUNC(cirrus_gd5465_laguna3d_device::vga_3b0_r), FUNC(cirrus_gd5465_laguna3d_device::vga_3b0_w));
- map(0x03c0, 0x03cf).rw(FUNC(cirrus_gd5465_laguna3d_device::vga_3c0_r), FUNC(cirrus_gd5465_laguna3d_device::vga_3c0_w));
- map(0x03d0, 0x03df).rw(FUNC(cirrus_gd5465_laguna3d_device::vga_3d0_r), FUNC(cirrus_gd5465_laguna3d_device::vga_3d0_w));
+ map(0, 0x02f).m(m_svga, FUNC(cirrus_gd5446_device::io_map));
}
uint8_t cirrus_gd5465_laguna3d_device::vram_r(offs_t offset)
@@ -125,85 +123,6 @@ void cirrus_gd5465_laguna3d_device::vram_w(offs_t offset, uint8_t data)
downcast<cirrus_gd5446_device *>(m_svga.target())->mem_w(offset, data);
}
-u32 cirrus_gd5465_laguna3d_device::vga_3b0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void cirrus_gd5465_laguna3d_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03b0_w(offset * 4 + 3, data >> 24);
-}
-
-
-u32 cirrus_gd5465_laguna3d_device::vga_3c0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void cirrus_gd5465_laguna3d_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03c0_w(offset * 4 + 3, data >> 24);
-}
-
-u32 cirrus_gd5465_laguna3d_device::vga_3d0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void cirrus_gd5465_laguna3d_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<cirrus_gd5446_device *>(m_svga.target())->port_03d0_w(offset * 4 + 3, data >> 24);
-}
-
void cirrus_gd5465_laguna3d_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)
{
@@ -211,9 +130,7 @@ void cirrus_gd5465_laguna3d_device::map_extra(uint64_t memory_window_start, uint
{
memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vram_r)), write8sm_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vram_w)));
- io_space->install_readwrite_handler(0x3b0, 0x3bf, read32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3b0_r)), write32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3b0_w)));
- io_space->install_readwrite_handler(0x3c0, 0x3cf, read32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3c0_r)), write32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3c0_w)));
- io_space->install_readwrite_handler(0x3d0, 0x3df, read32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3d0_r)), write32s_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vga_3d0_w)));
+ io_space->install_device(0x03b0, 0x03df, *this, &cirrus_gd5465_laguna3d_device::legacy_io_map);
//memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom);
}
}
diff --git a/src/devices/video/clgd546x_laguna.h b/src/devices/video/clgd546x_laguna.h
index 96086f94ae6..8c4faaa89f9 100644
--- a/src/devices/video/clgd546x_laguna.h
+++ b/src/devices/video/clgd546x_laguna.h
@@ -6,8 +6,7 @@
#pragma once
#include "machine/pci.h"
-//#include "video/pc_vga.h"
-#include "video/clgd542x.h"
+#include "video/pc_vga_cirrus.h"
class cirrus_gd5465_laguna3d_device : public pci_device
{
@@ -37,12 +36,6 @@ private:
u8 vram_r(offs_t offset);
void vram_w(offs_t offset, uint8_t data);
- u32 vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
// u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0);
// void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0);
diff --git a/src/devices/video/ibm8514a.cpp b/src/devices/video/ibm8514a.cpp
index 969d93d908c..5adac1dc434 100644
--- a/src/devices/video/ibm8514a.cpp
+++ b/src/devices/video/ibm8514a.cpp
@@ -1493,13 +1493,13 @@ uint8_t ibm8514a_device::ibm8514_status_r(offs_t offset)
case 0:
return m_vga->vga_vblank() << 1;
case 2:
- return m_vga->port_03c0_r(6);
+ return m_vga->ramdac_mask_r(0);
case 3:
- return m_vga->port_03c0_r(7);
+ return m_vga->ramdac_state_r(0);
case 4:
- return m_vga->port_03c0_r(8);
+ return m_vga->ramdac_write_index_r(0);
case 5:
- return m_vga->port_03c0_r(9);
+ return m_vga->ramdac_data_r(0);
}
return 0;
}
@@ -1512,16 +1512,16 @@ void ibm8514a_device::ibm8514_htotal_w(offs_t offset, uint8_t data)
ibm8514.htotal = data & 0xff;
break;
case 2:
- m_vga->port_03c0_w(6, data);
+ m_vga->ramdac_mask_w(0, data);
break;
case 3:
- m_vga->port_03c0_w(7, data);
+ m_vga->ramdac_read_index_w(0, data);
break;
case 4:
- m_vga->port_03c0_w(8, data);
+ m_vga->ramdac_write_index_w(0, data);
break;
case 5:
- m_vga->port_03c0_w(9, data);
+ m_vga->ramdac_data_w(0, data);
break;
}
//vga.crtc.horz_total = data & 0x01ff;
diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp
index db3b71fbd03..2caa993854d 100644
--- a/src/devices/video/pc_vga.cpp
+++ b/src/devices/video/pc_vga.cpp
@@ -1,31 +1,26 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods, Peter Trauner, Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
Video Graphics Adapter (VGA) section
Nathan Woods npwoods@mess.org
Peter Trauner PeT mess@utanet.at
- This code takes care of installing the various VGA memory and port
- handlers
-
- The VGA standard is compatible with MDA, CGA, Hercules, EGA
- (mda, cga, hercules not real register compatible)
- several vga cards drive also mda, cga, ega monitors
- some vga cards have register compatible mda, cga, hercules modes
-
ega/vga
64k (early ega 16k) words of 32 bit memory
TODO:
- - modernize
- - fix video update, still need to get that choosevideomode() out of it.
- - rewrite video drawing functions (they are horrible)
- - add per-gfx card VESA functions;
- - (and many more ...)
-
- per-game issues:
+ - modernize (in progress);
+ - Make RAMDAC a subclassable entity;
+ \- Clients needs to be able to swap that to SVGA extensions of the original 6bpp;
+ - Attribute from graphics to text mode in DOS doesn't restore properly, particularly if you
+ have a custom background color defined (verify);
+ - Improve debugging;
+ - Make a VGA bus slot option, already needed by 3dfx Voodoo and other similar cards;
+ - Verify how CAD ISA cards needs to r/w the VRAM space (uPD7220, HD63484, others);
+
+ per-game issues (very outdated, to be moved to SW list/to device files if necessary):
- The Incredible Machine: fix partial updates
- MAME 0.01: fix 92 Hz refresh rate bug (uses VESA register?).
- Virtual Pool: ET4k unrecognized;
@@ -33,12 +28,25 @@
- Jazz Jackrabbit: status bar is very jerky, but main screen scrolling is fine?
- Catacombs: weird resolution (untested)
- ROM declarations:
+ Notes:
+ - The VGA standard is compatible with MDA, CGA, Hercules, EGA
+ (MDA, EGA, Hercules not real register compatible)
+ - several vga cards drive also MDA, CGA, EGA monitors, some vga cards have register compatible
+ MDA, CGA, Hercules modes;
+ - SVGA is not a real interface but more like an overlay of the VGA standard that individual
+ manufacturers put together and which eventually became the VESA consortium.
+ It has incidentally a couple points in common across families but it's otherwise mostly a
+ commercial naming rather than a real physical change over the bus slot.
+
+ References:
+ - http://www.osdever.net/FreeVGA/vga/vga.htm
+
+ ROM declarations (move to pc_vga_oak):
(oti 037 chip)
ROM_LOAD("oakvga.bin", 0xc0000, 0x8000, CRC(318c5f43) SHA1(2aeb6cf737fd87dfd08c9f5b5bc421fcdbab4ce9) )
-***************************************************************************/
+***************************************************************************************************/
#include "emu.h"
#include "pc_vga.h"
@@ -99,15 +107,21 @@
***************************************************************************/
// device type definition
-DEFINE_DEVICE_TYPE(VGA, vga_device, "vga", "VGA")
+DEFINE_DEVICE_TYPE(VGA, vga_device, "vga", "VGA")
vga_device::vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_video_interface(mconfig, *this)
, device_palette_interface(mconfig, *this)
+ , device_memory_interface(mconfig, *this)
, vga(*this)
, m_input_sense(*this, "VGA_SENSE")
{
+ m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(vga_device::io_3bx_3dx_map), this));
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::crtc_map), this));
+ m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::gc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::sequencer_map), this));
+ m_atc_space_config = address_space_config("attribute_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::attribute_map), this));
}
vga_device::vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -115,16 +129,9 @@ vga_device::vga_device(const machine_config &mconfig, const char *tag, device_t
{
}
-svga_device::svga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vga_device(mconfig, type, tag, owner, clock)
-{
-}
-
// zero everything, keep vtbls
void vga_device::zero()
{
- vga.svga_intf.seq_regcount = 0;
- vga.svga_intf.crtc_regcount = 0;
memset(vga.pens, 0, sizeof(vga.pens));
vga.miscellaneous_output = 0;
vga.feature_control = 0;
@@ -136,18 +143,15 @@ void vga_device::zero()
memset(&vga.oak, 0, sizeof(vga.oak));
}
-void svga_device::zero()
+device_memory_interface::space_config_vector vga_device::memory_space_config() const
{
- vga_device::zero();
- memset(&svga, 0, sizeof(svga));
-}
-
-/* VBLANK callback, start address definitely updates AT vblank, not before. */
-TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb)
-{
- vga.crtc.start_addr = vga.crtc.start_addr_latch;
- vga.attribute.pel_shift = vga.attribute.pel_shift_latch;
- m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) );
+ return space_config_vector {
+ std::make_pair(MAIN_IF_REG, &m_main_if_space_config),
+ std::make_pair(CRTC_REG, &m_crtc_space_config),
+ std::make_pair(GC_REG, &m_gc_space_config),
+ std::make_pair(SEQ_REG, &m_seq_space_config),
+ std::make_pair(ATC_REG, &m_atc_space_config)
+ };
}
void vga_device::device_start()
@@ -160,11 +164,7 @@ void vga_device::device_start()
// Avoid an infinite loop when displaying. 0 is not possible anyway.
vga.crtc.maximum_scan_line = 1;
-
// copy over interfaces
- vga.svga_intf.seq_regcount = 0x05;
- vga.svga_intf.crtc_regcount = 0x19;
-
vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
save_pointer(NAME(vga.memory), vga.svga_intf.vram_size);
@@ -261,21 +261,908 @@ void vga_device::device_start()
m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
}
-void svga_device::device_start()
+void vga_device::device_reset()
{
- vga_device::device_start();
- memset(&svga, 0, sizeof(svga));
+ /* clear out the VGA structure */
+ memset(vga.pens, 0, sizeof(vga.pens));
+ vga.miscellaneous_output = 0;
+ m_ioas = false;
+ vga.feature_control = 0;
+ vga.sequencer.index = 0;
+ memset(vga.sequencer.data, 0, sizeof(vga.sequencer.data));
+ vga.crtc.index = 0;
+ memset(vga.crtc.data, 0, sizeof(vga.crtc.data));
+ vga.gc.index = 0;
+ memset(vga.gc.latch, 0, sizeof(vga.gc.latch));
+ memset(&vga.attribute, 0, sizeof(vga.attribute));
+ memset(&vga.dac, 0, sizeof(vga.dac));
+ memset(&vga.cursor, 0, sizeof(vga.cursor));
+ memset(&vga.oak, 0, sizeof(vga.oak));
- save_item(NAME(svga.bank_r));
- save_item(NAME(svga.bank_w));
- save_item(NAME(svga.rgb8_en));
- save_item(NAME(svga.rgb15_en));
- save_item(NAME(svga.rgb16_en));
- save_item(NAME(svga.rgb24_en));
- save_item(NAME(svga.rgb32_en));
- save_item(NAME(svga.id));
+ vga.gc.memory_map_sel = 0x3; /* prevent xtbios excepting vga ram as system ram */
+/* amstrad pc1640 bios relies on the position of
+ the video memory area,
+ so I introduced the reset to switch to b8000 area */
+ vga.sequencer.data[4] = 0;
+
+ /* TODO: real defaults */
+ vga.crtc.line_compare = 0x3ff;
+ /* skeleton/indiana.cpp boot PROM doesn't set this and assumes it's 0xff */
+ vga.dac.mask = 0xff;
+}
+
+/**************************************
+ *
+ * Main I/O space
+ *
+ *************************************/
+
+// A bare minimum VGA installs 3 main I/O areas, a fixed one at $3c0 and a moveable one at $3b0-$3bb
+// (for MDA compatibility) and $3d0-$3df. $3bc-$3bf is canonically assigned to LPT3 in an IBM machine.
+void vga_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+// map(0x00, 0x0b).view(m_ioas_3bx_view);
+// m_ioas_3bx_view[0](0x00, 0x0b).m(FUNC(vga_device::io_3bx_3dx_map));
+// m_ioas_3bx_view[1](0x00, 0x0b).unmaprw();
+ map(0x00, 0x0b).lrw8(
+ NAME([this] (offs_t offset) {
+ if (m_ioas == false)
+ return space(MAIN_IF_REG).read_byte(offset);
+ return (u8)space().unmap();
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if (m_ioas == false)
+ {
+ space(MAIN_IF_REG).write_byte(offset, data);
+ }
+ })
+ );
+
+ map(0x10, 0x1f).m(FUNC(vga_device::io_3cx_map));
+
+// map(0x20, 0x2f).view(m_ioas_3dx_view);
+// m_ioas_3dx_view[0](0x20, 0x2f).unmaprw();
+// m_ioas_3dx_view[1](0x20, 0x2f).m(FUNC(vga_device::io_3bx_3dx_map));
+ map(0x20, 0x2f).lrw8(
+ NAME([this] (offs_t offset) {
+ if (m_ioas == true)
+ return space(MAIN_IF_REG).read_byte(offset);
+ return (u8)space().unmap();
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if (m_ioas == true)
+ {
+ space(MAIN_IF_REG).write_byte(offset, data);
+ }
+ })
+ );
+}
+
+void vga_device::io_3bx_3dx_map(address_map &map)
+{
+ map(0x04, 0x04).rw(FUNC(vga_device::crtc_address_r), FUNC(vga_device::crtc_address_w));
+ map(0x05, 0x05).rw(FUNC(vga_device::crtc_data_r), FUNC(vga_device::crtc_data_w));
+ map(0x0a, 0x0a).rw(FUNC(vga_device::input_status_1_r), FUNC(vga_device::feature_control_w));
+ // TODO: move these to indicated subclasses
+ map(0x08, 0x08).lr8(
+ NAME([this] (offs_t offset) {
+ LOG("VGA: 0x3d8 read %s\n", machine().describe_context());
+ // TODO: PC-200 reads back CGA register here, everything else returns open bus OR CGA emulation of register 0x3d8
+ return 0;
+ })
+ );
+ map(0x0f, 0x0f).lr8(
+ NAME([this] (offs_t offset) {
+ LOG("VGA: 0x3df \"oak test\" read %s\n", machine().describe_context());
+ /* oak test */
+ //return 0;
+ /* pega bios on/off */
+ return 0x80;
+ })
+ );
+}
+
+void vga_device::io_3cx_map(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(vga_device::atc_address_r), FUNC(vga_device::atc_address_data_w));
+ map(0x01, 0x01).r(FUNC(vga_device::atc_data_r));
+ map(0x02, 0x02).rw(FUNC(vga_device::input_status_0_r), FUNC(vga_device::miscellaneous_output_w));
+ map(0x04, 0x04).rw(FUNC(vga_device::sequencer_address_r), FUNC(vga_device::sequencer_address_w));
+ map(0x05, 0x05).rw(FUNC(vga_device::sequencer_data_r), FUNC(vga_device::sequencer_data_w));
+ map(0x06, 0x06).rw(FUNC(vga_device::ramdac_mask_r), FUNC(vga_device::ramdac_mask_w));
+ map(0x07, 0x07).rw(FUNC(vga_device::ramdac_state_r), FUNC(vga_device::ramdac_read_index_w));
+ map(0x08, 0x08).rw(FUNC(vga_device::ramdac_write_index_r), FUNC(vga_device::ramdac_write_index_w));
+ map(0x09, 0x09).rw(FUNC(vga_device::ramdac_data_r), FUNC(vga_device::ramdac_data_w));
+ map(0x0a, 0x0a).r(FUNC(vga_device::feature_control_r));
+ map(0x0c, 0x0c).r(FUNC(vga_device::miscellaneous_output_r));
+ map(0x0e, 0x0e).rw(FUNC(vga_device::gc_address_r), FUNC(vga_device::gc_address_w));
+ map(0x0f, 0x0f).rw(FUNC(vga_device::gc_data_r), FUNC(vga_device::gc_data_w));
+ // TODO: doesn't belong here
+ map(0x03, 0x03).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.oak.reg;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.oak.reg = data;
+ })
+ );
+}
+
+/**************************************
+ *
+ * 3bx/3dx implementation
+ *
+ *************************************/
+
+u8 vga_device::crtc_address_r(offs_t offset)
+{
+ return vga.crtc.index;
+}
+
+void vga_device::crtc_address_w(offs_t offset, u8 data)
+{
+ vga.crtc.index = data;
+}
+
+u8 vga_device::crtc_data_r(offs_t offset)
+{
+ return space(CRTC_REG).read_byte(vga.crtc.index);
+}
+
+void vga_device::crtc_data_w(offs_t offset, u8 data)
+{
+ vga.crtc.data[vga.crtc.index] = data;
+ space(CRTC_REG).write_byte(vga.crtc.index, data);
+}
+
+u8 vga_device::input_status_1_r(offs_t offset)
+{
+ u8 res = 0;
+ u8 hsync, vsync;
+ vga.attribute.state = 0;
+
+ hsync = screen().hblank() & 1;
+ vsync = vga_vblank(); //screen().vblank() & 1;
+
+ res |= (hsync | vsync) & 1; // DD - display disable register
+ res |= (vsync & 1) << 3; // VRetrace register
+
+ /* ega diagnostic readback enough for oak bios */
+ // TODO: move to OAK
+ switch (vga.attribute.data[0x12]&0x30) {
+ case 0:
+ if (vga.attribute.data[0x11]&1)
+ res |= 0x10;
+ if (vga.attribute.data[0x11]&4)
+ res |= 0x20;
+ break;
+ case 0x10:
+ res |= (vga.attribute.data[0x11]&0x30);
+ break;
+ case 0x20:
+ if (vga.attribute.data[0x11]&2)
+ res |= 0x10;
+ if (vga.attribute.data[0x11]&8)
+ res |= 0x20;
+ break;
+ case 0x30:
+ res |= (vga.attribute.data[0x11]&0xc0)>>2;
+ break;
+ }
+
+ return res;
+}
+
+void vga_device::feature_control_w(offs_t offset, u8 data)
+{
+ vga.feature_control = data;
+}
+
+/**************************************
+ *
+ * 3cx implementation
+ *
+ *************************************/
+
+u8 vga_device::atc_address_r(offs_t offset)
+{
+ return vga.attribute.index;
+}
+
+u8 vga_device::atc_data_r(offs_t offset)
+{
+ return space(ATC_REG).read_byte(vga.attribute.index);
+}
+
+void vga_device::atc_address_data_w(offs_t offset, u8 data)
+{
+ if (vga.attribute.state == 0)
+ {
+ vga.attribute.index = data;
+ }
+ else
+ {
+ space(ATC_REG).write_byte(vga.attribute.index, data);
+ }
+
+ vga.attribute.state = !vga.attribute.state;
+}
+
+u8 vga_device::input_status_0_r(offs_t offset)
+{
+ u8 res = 0x60; // is VGA
+ const u8 sense_bit = (3 - (vga.miscellaneous_output >> 2)) & 3;
+ LOGDSW("Reading sense bit %d\n", sense_bit);
+ if(BIT(m_input_sense->read(), sense_bit))
+ res |= 0x10;
+ return res;
+}
+
+void vga_device::miscellaneous_output_w(offs_t offset, u8 data)
+{
+ vga.miscellaneous_output = data;
+ recompute_params();
+ m_ioas = bool(BIT(data, 0));
+}
+
+u8 vga_device::sequencer_address_r(offs_t offset)
+{
+ return vga.sequencer.index;
+}
+
+u8 vga_device::sequencer_data_r(offs_t offset)
+{
+ return space(SEQ_REG).read_byte(vga.sequencer.index);
+}
+
+void vga_device::sequencer_address_w(offs_t offset, u8 data)
+{
+ vga.sequencer.index = data;
+}
+
+void vga_device::sequencer_data_w(offs_t offset, u8 data)
+{
+ // TODO: temporary cheat for read-back
+ vga.sequencer.data[vga.sequencer.index] = data;
+ space(SEQ_REG).write_byte(vga.sequencer.index, data);
+ recompute_params();
+}
+
+u8 vga_device::ramdac_mask_r(offs_t offset)
+{
+ return vga.dac.mask;
+}
+
+u8 vga_device::ramdac_state_r(offs_t offset)
+{
+ return (vga.dac.read) ? 3 : 0;
+}
+
+u8 vga_device::ramdac_write_index_r(offs_t offset)
+{
+ return vga.dac.write_index;
+}
+
+u8 vga_device::ramdac_data_r(offs_t offset)
+{
+ u8 res = space().unmap();
+ if (vga.dac.read)
+ {
+ switch (vga.dac.state++)
+ {
+ case 0:
+ res = vga.dac.color[3*vga.dac.read_index];
+ break;
+ case 1:
+ res = vga.dac.color[3*vga.dac.read_index + 1];
+ break;
+ case 2:
+ res = vga.dac.color[3*vga.dac.read_index + 2];
+ break;
+ }
+
+ if (vga.dac.state == 3)
+ {
+ vga.dac.state = 0;
+ vga.dac.read_index++;
+ }
+ }
+ return res;
+}
+
+u8 vga_device::feature_control_r(offs_t offset)
+{
+ return vga.feature_control;
+}
+
+u8 vga_device::miscellaneous_output_r(offs_t offset)
+{
+ return vga.miscellaneous_output;
+}
+
+u8 vga_device::gc_address_r(offs_t offset)
+{
+ return vga.gc.index;
}
+u8 vga_device::gc_data_r(offs_t offset)
+{
+ return space(GC_REG).read_byte(vga.gc.index);
+}
+
+
+void vga_device::ramdac_mask_w(offs_t offset, u8 data)
+{
+ vga.dac.mask = data;
+ vga.dac.dirty = 1;
+}
+
+void vga_device::ramdac_read_index_w(offs_t offset, u8 data)
+{
+ vga.dac.read_index = data;
+ vga.dac.state = 0;
+ vga.dac.read = 1;
+}
+
+void vga_device::ramdac_write_index_w(offs_t offset, u8 data)
+{
+ vga.dac.write_index = data;
+ vga.dac.state = 0;
+ vga.dac.read = 0;
+}
+
+void vga_device::ramdac_data_w(offs_t offset, u8 data)
+{
+ if (!vga.dac.read)
+ {
+ switch (vga.dac.state++)
+ {
+ case 0:
+ vga.dac.color[3*vga.dac.write_index]=data;
+ break;
+ case 1:
+ vga.dac.color[3*vga.dac.write_index + 1]=data;
+ break;
+ case 2:
+ vga.dac.color[3*vga.dac.write_index + 2]=data;
+ break;
+ }
+
+ vga.dac.dirty=1;
+ if (vga.dac.state==3)
+ {
+ vga.dac.state = 0;
+ vga.dac.write_index++;
+ }
+ }
+}
+
+void vga_device::gc_address_w(offs_t offset, u8 data)
+{
+ vga.gc.index=data;
+}
+
+void vga_device::gc_data_w(offs_t offset, u8 data)
+{
+ space(GC_REG).write_byte(vga.gc.index, data);
+}
+
+
+/**************************************
+ *
+ * CRTC
+ *
+ *************************************/
+
+void vga_device::crtc_map(address_map &map)
+{
+ map(0x00, 0x00).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.horz_total & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ // doom (DOS) tries to write to protected regs
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_total = (vga.crtc.horz_total & ~0xff) | (data & 0xff);
+ recompute_params();
+ })
+ );
+ map(0x01, 0x01).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.horz_disp_end & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_disp_end = (data & 0xff);
+ recompute_params();
+ })
+ );
+ map(0x02, 0x02).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.horz_blank_start & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_blank_start = (data & 0xff);
+ })
+ );
+ map(0x03, 0x03).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = vga.crtc.horz_blank_end & 0x1f;
+ res |= (vga.crtc.disp_enable_skew & 3) << 5;
+ res |= (vga.crtc.evra & 1) << 7;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_blank_end &= ~0x1f;
+ vga.crtc.horz_blank_end |= data & 0x1f;
+ vga.crtc.disp_enable_skew = (data & 0x60) >> 5;
+ vga.crtc.evra = BIT(data, 7);
+ })
+ );
+ map(0x04, 0x04).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.horz_retrace_start & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_retrace_start = data & 0xff;
+ })
+ );
+ map(0x05, 0x05).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.horz_blank_end & 0x20) << 2;
+ res |= (vga.crtc.horz_retrace_skew & 3) << 5;
+ res |= (vga.crtc.horz_retrace_end & 0x1f);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.horz_blank_end &= ~0x20;
+ vga.crtc.horz_blank_end |= ((data & 0x80) >> 2);
+ vga.crtc.horz_retrace_skew = ((data & 0x60) >> 5);
+ vga.crtc.horz_retrace_end = data & 0x1f;
+ })
+ );
+ map(0x06, 0x06).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.vert_total & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.vert_total &= ~0xff;
+ vga.crtc.vert_total |= data & 0xff;
+ recompute_params();
+ })
+ );
+ // Overflow Register
+ map(0x07, 0x07).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.line_compare & 0x100) >> 4;
+ res |= (vga.crtc.vert_retrace_start & 0x200) >> 2;
+ res |= (vga.crtc.vert_disp_end & 0x200) >> 3;
+ res |= (vga.crtc.vert_total & 0x200) >> 4;
+ res |= (vga.crtc.vert_blank_start & 0x100) >> 5;
+ res |= (vga.crtc.vert_retrace_start & 0x100) >> 6;
+ res |= (vga.crtc.vert_disp_end & 0x100) >> 7;
+ res |= (vga.crtc.vert_total & 0x100) >> 8;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.line_compare &= ~0x100;
+ vga.crtc.line_compare |= ((data & 0x10) << (8-4));
+ if(vga.crtc.protect_enable)
+ return;
+ vga.crtc.vert_total &= ~0x300;
+ vga.crtc.vert_retrace_start &= ~0x300;
+ vga.crtc.vert_disp_end &= ~0x300;
+ vga.crtc.vert_blank_start &= ~0x100;
+ vga.crtc.vert_retrace_start |= ((data & 0x80) << (9-7));
+ vga.crtc.vert_disp_end |= ((data & 0x40) << (9-6));
+ vga.crtc.vert_total |= ((data & 0x20) << (9-5));
+ vga.crtc.vert_blank_start |= ((data & 0x08) << (8-3));
+ vga.crtc.vert_retrace_start |= ((data & 0x04) << (8-2));
+ vga.crtc.vert_disp_end |= ((data & 0x02) << (8-1));
+ vga.crtc.vert_total |= ((data & 0x01) << (8-0));
+ recompute_params();
+ })
+ );
+ // Preset Row Scan Register
+ map(0x08, 0x08).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.byte_panning & 3) << 5;
+ res |= (vga.crtc.preset_row_scan & 0x1f);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.byte_panning = (data & 0x60) >> 5;
+ vga.crtc.preset_row_scan = (data & 0x1f);
+ })
+ );
+ // Maximum Scan Line Register
+ map(0x09, 0x09).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.maximum_scan_line - 1) & 0x1f;
+ res |= (vga.crtc.scan_doubling & 1) << 7;
+ res |= (vga.crtc.line_compare & 0x200) >> 3;
+ res |= (vga.crtc.vert_blank_start & 0x200) >> 4;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.line_compare &= ~0x200;
+ vga.crtc.vert_blank_start &= ~0x200;
+ vga.crtc.scan_doubling = ((data & 0x80) >> 7);
+ vga.crtc.line_compare |= ((data & 0x40) << (9-6));
+ vga.crtc.vert_blank_start |= ((data & 0x20) << (9-5));
+ vga.crtc.maximum_scan_line = (data & 0x1f) + 1;
+ })
+ );
+ map(0x0a, 0x0a).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.cursor_scan_start & 0x1f);
+ res |= ((vga.crtc.cursor_enable & 1) ^ 1) << 5;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.cursor_enable = ((data & 0x20) ^ 0x20) >> 5;
+ vga.crtc.cursor_scan_start = data & 0x1f;
+ })
+ );
+ map(0x0b, 0x0b).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.cursor_skew & 3) << 5;
+ res |= (vga.crtc.cursor_scan_end & 0x1f);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.cursor_skew = (data & 0x60) >> 5;
+ vga.crtc.cursor_scan_end = data & 0x1f;
+ })
+ );
+ map(0x0c, 0x0d).lrw8(
+ NAME([this](offs_t offset) {
+ return (vga.crtc.start_addr_latch >> ((offset & 1) ^ 1) * 8) & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.start_addr_latch &= ~(0xff << (((offset & 1) ^ 1) * 8));
+ vga.crtc.start_addr_latch |= (data << (((offset & 1) ^ 1) * 8));
+ })
+ );
+ map(0x0e, 0x0f).lrw8(
+ NAME([this](offs_t offset) {
+ return (vga.crtc.cursor_addr >> ((offset & 1) ^ 1)*8) & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.cursor_addr &= ~(0xff << (((offset & 1) ^ 1) * 8));
+ vga.crtc.cursor_addr |= (data << (((offset & 1) ^ 1) * 8));
+ })
+ );
+ map(0x10, 0x10).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.vert_retrace_start & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.vert_retrace_start &= ~0xff;
+ vga.crtc.vert_retrace_start |= data & 0xff;
+ })
+ );
+ map(0x11, 0x11).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.protect_enable & 1) << 7;
+ res |= (vga.crtc.bandwidth & 1) << 6;
+ res |= (vga.crtc.vert_retrace_end & 0xf);
+ res |= (vga.crtc.irq_clear & 1) << 4;
+ res |= (vga.crtc.irq_disable & 1) << 5;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.protect_enable = (data & 0x80) >> 7;
+ vga.crtc.bandwidth = (data & 0x40) >> 6;
+ vga.crtc.vert_retrace_end = data & 0x0f;
+ vga.crtc.irq_clear = (data & 0x10) >> 4;
+ vga.crtc.irq_disable = (data & 0x20) >> 5;
+ })
+ );
+ map(0x12, 0x12).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.vert_disp_end & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.vert_disp_end &= ~0xff;
+ vga.crtc.vert_disp_end |= data & 0xff;
+ recompute_params();
+ })
+ );
+ map(0x13, 0x13).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.offset & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.offset &= ~0xff;
+ vga.crtc.offset |= data & 0xff;
+ })
+ );
+ map(0x14, 0x14).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.dw & 1) << 6;
+ res |= (vga.crtc.div4 & 1) << 5;
+ res |= (vga.crtc.underline_loc & 0x1f);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.dw = (data & 0x40) >> 6;
+ vga.crtc.div4 = (data & 0x20) >> 5;
+ vga.crtc.underline_loc = (data & 0x1f);
+ })
+ );
+ map(0x15, 0x15).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.vert_blank_start & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.vert_blank_start &= ~0xff;
+ vga.crtc.vert_blank_start |= data & 0xff;
+ })
+ );
+ map(0x16, 0x16).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.vert_blank_end & 0x7f;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.vert_blank_end = data & 0x7f;
+ })
+ );
+ map(0x17, 0x17).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.crtc.sync_en & 1) << 7;
+ res |= (vga.crtc.word_mode & 1) << 6;
+ res |= (vga.crtc.aw & 1) << 5;
+ res |= (vga.crtc.div2 & 1) << 3;
+ res |= (vga.crtc.sldiv & 1) << 2;
+ res |= (vga.crtc.map14 & 1) << 1;
+ res |= (vga.crtc.map13 & 1) << 0;
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.sync_en = BIT(data, 7);
+ vga.crtc.word_mode = BIT(data, 6);
+ vga.crtc.aw = BIT(data, 5);
+ vga.crtc.div2 = BIT(data, 3);
+ vga.crtc.sldiv = BIT(data, 2);
+ vga.crtc.map14 = BIT(data, 1);
+ vga.crtc.map13 = BIT(data, 0);
+ })
+ );
+ map(0x18, 0x18).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.crtc.line_compare & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.crtc.line_compare &= ~0xff;
+ vga.crtc.line_compare |= data & 0xff;
+ })
+ );
+ // TODO: (undocumented) CR22 Memory Data Latch Register (read only)
+ // map(0x22, 0x22).lr8(
+ // (undocumented) CR24 Attribute Controller Toggle Register (read only)
+ // 0--- ---- index
+ // 1--- ---- data
+ map(0x24, 0x24).lr8(
+ NAME([this](offs_t offset) {
+ LOG("CR24 read undocumented Attribute reg\n");
+ return vga.attribute.state << 7;
+ })
+ );
+}
+
+/**************************************
+ *
+ * GC
+ *
+ *************************************/
+
+void vga_device::gc_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00, 0x00).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.set_reset & 0xf;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.set_reset = data & 0xf;
+ })
+ );
+ map(0x01, 0x01).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.enable_set_reset & 0xf;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.enable_set_reset = data & 0xf;
+ })
+ );
+ map(0x02, 0x02).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.color_compare & 0xf;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.color_compare = data & 0xf;
+ })
+ );
+ map(0x03, 0x03).lrw8(
+ NAME([this](offs_t offset) {
+ return ((vga.gc.logical_op & 3) << 3) | (vga.gc.rotate_count & 7);
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.logical_op = (data & 0x18) >> 3;
+ vga.gc.rotate_count = data & 7;
+ })
+ );
+ map(0x04, 0x04).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.read_map_sel & 3;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.read_map_sel = data & 3;
+ })
+ );
+ map(0x05, 0x05).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.gc.shift256 & 1) << 6;
+ res |= (vga.gc.shift_reg & 1) << 5;
+ res |= (vga.gc.host_oe & 1) << 4;
+ res |= (vga.gc.read_mode & 1) << 3;
+ res |= (vga.gc.write_mode & 3);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.shift256 = BIT(data, 6);
+ vga.gc.shift_reg = BIT(data, 5);
+ vga.gc.host_oe = BIT(data, 4);
+ vga.gc.read_mode = BIT(data, 3);
+ vga.gc.write_mode = data & 3;
+ //if(data & 0x10 && vga.gc.alpha_dis)
+ // popmessage("Host O/E enabled, contact MAMEdev");
+ })
+ );
+ map(0x06, 0x06).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.gc.memory_map_sel & 3) << 2;
+ res |= (vga.gc.chain_oe & 1) << 1;
+ res |= (vga.gc.alpha_dis & 1);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.memory_map_sel = (data & 0xc) >> 2;
+ vga.gc.chain_oe = BIT(data, 1);
+ vga.gc.alpha_dis = BIT(data, 0);
+ //if(data & 2 && vga.gc.alpha_dis)
+ // popmessage("Chain O/E enabled, contact MAMEdev");
+ })
+ );
+ map(0x07, 0x07).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.color_dont_care & 0xf;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.color_dont_care = data & 0xf;
+ })
+ );
+ map(0x08, 0x08).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.bit_mask & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.bit_mask = data & 0xff;
+ })
+ );
+}
+
+/**************************************
+ *
+ * Sequencer
+ *
+ *************************************/
+
+void vga_device::sequencer_map(address_map &map)
+{
+ // TODO: legacy fallback trick
+ map(0x00, 0xff).lr8(
+ NAME([this] (offs_t offset) {
+ const u8 res = vga.sequencer.data[offset];
+ if (!machine().side_effects_disabled())
+ LOG("Reading unmapped sequencer read register [%02x] -> %02x (SVGA?)\n", offset, res);
+ return res;
+ })
+ );
+// map(0x00, 0x00) Reset Register
+// map(0x01, 0x01) Clocking Mode Register
+ map(0x02, 0x02).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ vga.sequencer.map_mask = data & 0xf;
+ })
+ );
+ map(0x03, 0x03).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ /* --2- 84-- character select A
+ ---2 --84 character select B */
+ vga.sequencer.char_sel.A = (((data & 0xc) >> 2)<<1) | ((data & 0x20) >> 5);
+ vga.sequencer.char_sel.B = (((data & 0x3) >> 0)<<1) | ((data & 0x10) >> 4);
+ if(data)
+ popmessage("Char SEL checker, contact MAMEdev (%02x %02x)\n",vga.sequencer.char_sel.A,vga.sequencer.char_sel.B);
+ })
+ );
+ // Sequencer Memory Mode Register
+// map(0x04, 0x04)
+ // (undocumented) Sequencer Horizontal Character Counter Reset
+ // Any write strobe to this register will lock the character generator until another write to other regs happens.
+// map(0x07, 0x07)
+}
+
+/**************************************
+ *
+ * Attribute (ATC)
+ *
+ *************************************/
+
+/*
+ * xx-- ---- <reserved>
+ * --x- ---- Palette RAM address source (0) CPU access (1) ATC access
+ * \- NB: leaving to '0' will disable video output from the ATC,
+ * and cause overscan drawing in canvas instead.
+ * ---x xxxx index register
+ *
+ */
+void vga_device::attribute_map(address_map &map)
+{
+ map.global_mask(0x3f);
+ map.unmap_value_high();
+ map(0x00, 0x0f).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ offset & 0x1f]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.data[offset & 0x1f] = data & 0x3f; })
+ );
+ map(0x20, 0x2f).noprw();
+ // Mode Control
+ map(0x10, 0x10).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ 0x10 ]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x10 ] = data & 0x3f; })
+ );
+ // Overscan Color
+ map(0x11, 0x11).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ 0x11 ]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x11 ] = data & 0x3f; })
+ );
+ // Color Plane Enable
+ map(0x12, 0x12).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ 0x12 ]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x12 ] = data & 0x3f; })
+ );
+ // Horizontal PEL shift
+ map(0x13, 0x13).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ 0x13 ]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.pel_shift_latch = vga.attribute.data[ 0x13 ] = data & 0xf; })
+ );
+ // Color Select
+ map(0x14, 0x14).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return vga.attribute.data[ 0x14 ]; }),
+ NAME([this] (offs_t offset, u8 data) { vga.attribute.pel_shift_latch = vga.attribute.data[ 0x14 ] = data & 0xf; })
+ );
+}
+
+/**************************************
+ *
+ * Drawing routines
+ *
+ *************************************/
+
uint16_t vga_device::offset()
{
// popmessage("Offset: %04x %s %s **",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD");
@@ -298,6 +1185,33 @@ uint32_t vga_device::start_addr()
return vga.crtc.start_addr << 1;
}
+uint8_t vga_device::vga_latch_write(int offs, uint8_t data)
+{
+ uint8_t res = 0;
+
+ switch (vga.gc.write_mode & 3) {
+ case 0:
+ data = rotate_right(data);
+ if(vga.gc.enable_set_reset & 1<<offs)
+ res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? vga.gc.bit_mask : 0, offs,vga.gc.bit_mask);
+ else
+ res = vga_logical_op(data, offs, vga.gc.bit_mask);
+ break;
+ case 1:
+ res = vga.gc.latch[offs];
+ break;
+ case 2:
+ res = vga_logical_op((data & 1<<offs) ? 0xff : 0x00,offs,vga.gc.bit_mask);
+ break;
+ case 3:
+ data = rotate_right(data);
+ res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? 0xff : 0x00,offs,data&vga.gc.bit_mask);
+ break;
+ }
+
+ return res;
+}
+
void vga_device::vga_vh_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int width=VGA_CH_WIDTH, height = (vga.crtc.maximum_scan_line) * (vga.crtc.scan_doubling + 1);
@@ -375,9 +1289,6 @@ void vga_device::vga_vh_ega(bitmap_rgb32 &bitmap, const rectangle &cliprect)
int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1);
int pel_shift = (vga.attribute.pel_shift & 7);
-// popmessage("%08x %02x",EGA_START_ADDRESS,pel_shift);
-
- /**/
for (int addr=EGA_START_ADDRESS, line=0; line<LINES; line += height, addr += offset())
{
for (int yi=0;yi<height;yi++)
@@ -547,6 +1458,346 @@ void vga_device::vga_vh_mono(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
+uint8_t vga_device::pc_vga_choosevideomode()
+{
+ if (vga.crtc.sync_en)
+ {
+ if (vga.dac.dirty)
+ {
+ for (int i=0; i<256;i++)
+ {
+ /* TODO: color shifters? */
+ set_pen_color(i, (vga.dac.color[3*(i & vga.dac.mask)] & 0x3f) << 2,
+ (vga.dac.color[3*(i & vga.dac.mask) + 1] & 0x3f) << 2,
+ (vga.dac.color[3*(i & vga.dac.mask) + 2] & 0x3f) << 2);
+ }
+ vga.dac.dirty = 0;
+ }
+
+ if (vga.attribute.data[0x10] & 0x80)
+ {
+ for (int i=0; i<16;i++)
+ {
+ vga.pens[i] = pen((vga.attribute.data[i]&0x0f)
+ |((vga.attribute.data[0x14]&0xf)<<4));
+ }
+ }
+ else
+ {
+ for (int i=0; i<16;i++)
+ {
+ vga.pens[i] = pen((vga.attribute.data[i]&0x3f)
+ |((vga.attribute.data[0x14]&0xc)<<4));
+ }
+ }
+
+ if (!GRAPHIC_MODE)
+ {
+ return TEXT_MODE;
+ }
+ else if (vga.gc.shift256)
+ {
+ return VGA_MODE;
+ }
+ else if (vga.gc.shift_reg)
+ {
+ return CGA_MODE;
+ }
+ else if (vga.gc.memory_map_sel == 0x03)
+ {
+ return MONO_MODE;
+ }
+ else
+ {
+ return EGA_MODE;
+ }
+ }
+
+ return SCREEN_OFF;
+}
+
+uint32_t vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ uint8_t cur_mode = pc_vga_choosevideomode();
+
+ switch(cur_mode)
+ {
+ case SCREEN_OFF: bitmap.fill (black_pen(), cliprect);break;
+ case TEXT_MODE: vga_vh_text (bitmap, cliprect); break;
+ case VGA_MODE: vga_vh_vga (bitmap, cliprect); break;
+ case EGA_MODE: vga_vh_ega (bitmap, cliprect); break;
+ case CGA_MODE: vga_vh_cga (bitmap, cliprect); break;
+ case MONO_MODE: vga_vh_mono (bitmap, cliprect); break;
+ }
+
+ return 0;
+}
+
+/**************************************
+ *
+ * CRTC setups
+ *
+ *************************************/
+
+void vga_device::recompute_params_clock(int divisor, int xtal)
+{
+ int vblank_period,hblank_period;
+ attoseconds_t refresh;
+ uint8_t hclock_m = (!GRAPHIC_MODE) ? VGA_CH_WIDTH : 8;
+ int pixel_clock;
+
+ /* safety check */
+ if(!vga.crtc.horz_disp_end || !vga.crtc.vert_disp_end || !vga.crtc.horz_total || !vga.crtc.vert_total)
+ return;
+
+ rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end);
+
+ vblank_period = (vga.crtc.vert_total + 2);
+ hblank_period = ((vga.crtc.horz_total + 5) * ((float)(hclock_m)/divisor));
+
+ /* TODO: 10b and 11b settings aren't known */
+ pixel_clock = xtal / (((vga.sequencer.data[1]&8) >> 3) + 1);
+
+ refresh = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period;
+ screen().configure((hblank_period), (vblank_period), visarea, refresh );
+ //popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total);
+ m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) );
+}
+
+// TODO: rename me
+void vga_device::recompute_params()
+{
+ if(vga.miscellaneous_output & 8)
+ LOGWARN("Warning: VGA external clock latch selected\n");
+ else
+ recompute_params_clock(1, ((vga.miscellaneous_output & 0xc) ? XTAL(28'636'363) : XTAL(25'174'800)).value());
+}
+
+uint8_t vga_device::vga_vblank()
+{
+ uint8_t res;
+ uint16_t vblank_start,vblank_end,vpos;
+
+ /* calculate vblank start / end positions */
+ res = 0;
+ vblank_start = vga.crtc.vert_blank_start;
+ vblank_end = vga.crtc.vert_blank_start + vga.crtc.vert_blank_end;
+ vpos = screen().vpos();
+
+ /* check if we are under vblank period */
+ if(vblank_end > vga.crtc.vert_total)
+ {
+ vblank_end -= vga.crtc.vert_total;
+ if(vpos >= vblank_start || vpos <= vblank_end)
+ res = 1;
+ }
+ else
+ {
+ if(vpos >= vblank_start && vpos <= vblank_end)
+ res = 1;
+ }
+
+ //popmessage("%d %d %d - SR1=%02x",vblank_start,vblank_end,vga.crtc.vert_total,vga.sequencer.data[1]);
+
+ return res;
+}
+
+/*
+ 4 additional dipswitches
+ seems to have emulation modes at register level
+ (mda/hgc lines bit 8 not identical to ega/vga)
+
+ standard ega/vga dipswitches
+ 00000000 320x200
+ 00000001 640x200 hanging
+ 00000010 640x200 hanging
+ 00000011 640x200 hanging
+
+ 00000100 640x350 hanging
+ 00000101 640x350 hanging EGA mono
+ 00000110 320x200
+ 00000111 640x200
+
+ 00001000 640x200
+ 00001001 640x200
+ 00001010 720x350 partial visible
+ 00001011 720x350 partial visible
+
+ 00001100 320x200
+ 00001101 320x200
+ 00001110 320x200
+ 00001111 320x200
+*/
+static INPUT_PORTS_START(vga_sense)
+ PORT_START("VGA_SENSE")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+ioport_constructor vga_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(vga_sense);
+}
+
+// TODO: convert to mapped space
+uint8_t vga_device::mem_r(offs_t offset)
+{
+ switch(vga.gc.memory_map_sel & 0x03)
+ {
+ case 0: break;
+ case 1: offset &= 0x0ffff; break;
+ case 2: offset -= 0x10000; offset &= 0x07fff; break;
+ case 3: offset -= 0x18000; offset &= 0x07fff; break;
+ }
+
+ if(vga.sequencer.data[4] & 4)
+ {
+ int data;
+ if (!machine().side_effects_disabled())
+ {
+ vga.gc.latch[0]=vga.memory[(offset)];
+ vga.gc.latch[1]=vga.memory[(offset)+0x10000];
+ vga.gc.latch[2]=vga.memory[(offset)+0x20000];
+ vga.gc.latch[3]=vga.memory[(offset)+0x30000];
+ }
+
+ if (vga.gc.read_mode)
+ {
+ // In Read Mode 1 latch is checked against this
+ // cfr. lombrall & intsocch where they RMW sprite-like objects
+ // and anything outside this formula goes transparent.
+ const u8 target_color = (vga.gc.color_compare & vga.gc.color_dont_care);
+ data = 0;
+
+ for(u8 byte = 0; byte < 8; byte++)
+ {
+ u8 fill_latch = 0;
+ for(u8 layer = 0; layer < 4; layer++)
+ {
+ if(vga.gc.latch[layer] & 1 << byte)
+ fill_latch |= 1 << layer;
+ }
+ fill_latch &= vga.gc.color_dont_care;
+ if(fill_latch == target_color)
+ data |= 1 << byte;
+ }
+ }
+ else
+ data=vga.gc.latch[vga.gc.read_map_sel];
+
+ return data;
+ }
+ else
+ {
+ uint8_t i,data;
+
+ data = 0;
+ //printf("%08x\n",offset);
+
+ for(i=0;i<4;i++)
+ {
+ if(vga.sequencer.map_mask & 1 << i)
+ data |= vga.memory[offset+i*0x10000];
+ }
+
+ return data;
+ }
+
+ // never executed
+ //return 0;
+}
+
+void vga_device::mem_w(offs_t offset, uint8_t data)
+{
+ //Inside each case must prevent writes to non-mapped VGA memory regions, not only mask the offset.
+ switch(vga.gc.memory_map_sel & 0x03)
+ {
+ case 0: break;
+ case 1:
+ if(offset & 0x10000)
+ return;
+
+ offset &= 0x0ffff;
+ break;
+ case 2:
+ if((offset & 0x18000) != 0x10000)
+ return;
+
+ offset &= 0x07fff;
+ break;
+ case 3:
+ if((offset & 0x18000) != 0x18000)
+ return;
+
+ offset &= 0x07fff;
+ break;
+ }
+
+ {
+ uint8_t i;
+
+ for(i=0;i<4;i++)
+ {
+ if(vga.sequencer.map_mask & 1 << i)
+ vga.memory[offset+i*0x10000] = (vga.sequencer.data[4] & 4) ? vga_latch_write(i,data) : data;
+ }
+ return;
+ }
+}
+
+// TODO: is there any non-SVGA capable board capable of linear access?
+uint8_t vga_device::mem_linear_r(offs_t offset)
+{
+ return vga.memory[offset % vga.svga_intf.vram_size];
+}
+
+void vga_device::mem_linear_w(offs_t offset, uint8_t data)
+{
+ vga.memory[offset % vga.svga_intf.vram_size] = data;
+}
+
+/* VBLANK callback, start address definitely updates AT vblank, not before. */
+TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb)
+{
+ vga.crtc.start_addr = vga.crtc.start_addr_latch;
+ vga.attribute.pel_shift = vga.attribute.pel_shift_latch;
+ m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) );
+}
+
+/**************************************
+ *
+ * SVGA overrides
+ *
+ *************************************/
+
+svga_device::svga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vga_device(mconfig, type, tag, owner, clock)
+{
+}
+
+void svga_device::zero()
+{
+ vga_device::zero();
+ memset(&svga, 0, sizeof(svga));
+}
+
+void svga_device::device_start()
+{
+ vga_device::device_start();
+ memset(&svga, 0, sizeof(svga));
+
+ save_item(NAME(svga.bank_r));
+ save_item(NAME(svga.bank_w));
+ save_item(NAME(svga.rgb8_en));
+ save_item(NAME(svga.rgb15_en));
+ save_item(NAME(svga.rgb16_en));
+ save_item(NAME(svga.rgb24_en));
+ save_item(NAME(svga.rgb32_en));
+ save_item(NAME(svga.id));
+}
+
void svga_device::svga_vh_rgb8(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1);
@@ -725,65 +1976,7 @@ void svga_device::svga_vh_rgb32(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
-uint8_t vga_device::pc_vga_choosevideomode()
-{
- if (vga.crtc.sync_en)
- {
- if (vga.dac.dirty)
- {
- for (int i=0; i<256;i++)
- {
- /* TODO: color shifters? */
- set_pen_color(i, (vga.dac.color[3*(i & vga.dac.mask)] & 0x3f) << 2,
- (vga.dac.color[3*(i & vga.dac.mask) + 1] & 0x3f) << 2,
- (vga.dac.color[3*(i & vga.dac.mask) + 2] & 0x3f) << 2);
- }
- vga.dac.dirty = 0;
- }
-
- if (vga.attribute.data[0x10] & 0x80)
- {
- for (int i=0; i<16;i++)
- {
- vga.pens[i] = pen((vga.attribute.data[i]&0x0f)
- |((vga.attribute.data[0x14]&0xf)<<4));
- }
- }
- else
- {
- for (int i=0; i<16;i++)
- {
- vga.pens[i] = pen((vga.attribute.data[i]&0x3f)
- |((vga.attribute.data[0x14]&0xc)<<4));
- }
- }
-
- if (!GRAPHIC_MODE)
- {
- return TEXT_MODE;
- }
- else if (vga.gc.shift256)
- {
- return VGA_MODE;
- }
- else if (vga.gc.shift_reg)
- {
- return CGA_MODE;
- }
- else if (vga.gc.memory_map_sel == 0x03)
- {
- return MONO_MODE;
- }
- else
- {
- return EGA_MODE;
- }
- }
-
- return SCREEN_OFF;
-}
-
-
+// TODO: inherit from base class
uint8_t svga_device::pc_vga_choosevideomode()
{
if (vga.crtc.sync_en)
@@ -879,23 +2072,7 @@ uint8_t svga_device::get_video_depth()
return 0;
}
-uint32_t vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- uint8_t cur_mode = pc_vga_choosevideomode();
-
- switch(cur_mode)
- {
- case SCREEN_OFF: bitmap.fill (black_pen(), cliprect);break;
- case TEXT_MODE: vga_vh_text (bitmap, cliprect); break;
- case VGA_MODE: vga_vh_vga (bitmap, cliprect); break;
- case EGA_MODE: vga_vh_ega (bitmap, cliprect); break;
- case CGA_MODE: vga_vh_cga (bitmap, cliprect); break;
- case MONO_MODE: vga_vh_mono (bitmap, cliprect); break;
- }
-
- return 0;
-}
-
+// TODO: inherit from base class
uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint8_t cur_mode = pc_vga_choosevideomode();
@@ -917,976 +2094,3 @@ uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
return 0;
}
-
-/***************************************************************************/
-
-uint8_t vga_device::vga_latch_write(int offs, uint8_t data)
-{
- uint8_t res = 0;
-
- switch (vga.gc.write_mode & 3) {
- case 0:
- data = rotate_right(data);
- if(vga.gc.enable_set_reset & 1<<offs)
- res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? vga.gc.bit_mask : 0, offs,vga.gc.bit_mask);
- else
- res = vga_logical_op(data, offs, vga.gc.bit_mask);
- break;
- case 1:
- res = vga.gc.latch[offs];
- break;
- case 2:
- res = vga_logical_op((data & 1<<offs) ? 0xff : 0x00,offs,vga.gc.bit_mask);
- break;
- case 3:
- data = rotate_right(data);
- res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? 0xff : 0x00,offs,data&vga.gc.bit_mask);
- break;
- }
-
- return res;
-}
-
-uint8_t vga_device::crtc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- res = 0xff;
-
- switch(index)
- {
- case 0x00:
- res = vga.crtc.horz_total & 0xff;
- break;
- case 0x01:
- res = vga.crtc.horz_disp_end & 0xff;
- break;
- case 0x02:
- res = vga.crtc.horz_blank_start & 0xff;
- break;
- case 0x03:
- res = vga.crtc.horz_blank_end & 0x1f;
- res |= (vga.crtc.disp_enable_skew & 3) << 5;
- res |= (vga.crtc.evra & 1) << 7;
- break;
- case 0x04:
- res = vga.crtc.horz_retrace_start & 0xff;
- break;
- case 0x05:
- res = (vga.crtc.horz_blank_end & 0x20) << 2;
- res |= (vga.crtc.horz_retrace_skew & 3) << 5;
- res |= (vga.crtc.horz_retrace_end & 0x1f);
- break;
- case 0x06:
- res = vga.crtc.vert_total & 0xff;
- break;
- case 0x07: // Overflow Register
- res = (vga.crtc.line_compare & 0x100) >> 4;
- res |= (vga.crtc.vert_retrace_start & 0x200) >> 2;
- res |= (vga.crtc.vert_disp_end & 0x200) >> 3;
- res |= (vga.crtc.vert_total & 0x200) >> 4;
- res |= (vga.crtc.vert_blank_start & 0x100) >> 5;
- res |= (vga.crtc.vert_retrace_start & 0x100) >> 6;
- res |= (vga.crtc.vert_disp_end & 0x100) >> 7;
- res |= (vga.crtc.vert_total & 0x100) >> 8;
- break;
- case 0x08: // Preset Row Scan Register
- res = (vga.crtc.byte_panning & 3) << 5;
- res |= (vga.crtc.preset_row_scan & 0x1f);
- break;
- case 0x09: // Maximum Scan Line Register
- res = (vga.crtc.maximum_scan_line - 1) & 0x1f;
- res |= (vga.crtc.scan_doubling & 1) << 7;
- res |= (vga.crtc.line_compare & 0x200) >> 3;
- res |= (vga.crtc.vert_blank_start & 0x200) >> 4;
- break;
- case 0x0a:
- res = (vga.crtc.cursor_scan_start & 0x1f);
- res |= ((vga.crtc.cursor_enable & 1) ^ 1) << 5;
- break;
- case 0x0b:
- res = (vga.crtc.cursor_skew & 3) << 5;
- res |= (vga.crtc.cursor_scan_end & 0x1f);
- break;
- case 0x0c:
- case 0x0d:
- res = (vga.crtc.start_addr_latch >> ((index & 1) ^ 1)*8) & 0xff;
- break;
- case 0x0e:
- case 0x0f:
- res = (vga.crtc.cursor_addr >> ((index & 1) ^ 1)*8) & 0xff;
- break;
- case 0x10:
- res = vga.crtc.vert_retrace_start & 0xff;
- break;
- case 0x11:
- res = (vga.crtc.protect_enable & 1) << 7;
- res |= (vga.crtc.bandwidth & 1) << 6;
- res |= (vga.crtc.vert_retrace_end & 0xf);
- res |= (vga.crtc.irq_clear & 1) << 4;
- res |= (vga.crtc.irq_disable & 1) << 5;
- break;
- case 0x12:
- res = vga.crtc.vert_disp_end & 0xff;
- break;
- case 0x13:
- res = vga.crtc.offset & 0xff;
- break;
- case 0x14:
- res = (vga.crtc.dw & 1) << 6;
- res |= (vga.crtc.div4 & 1) << 5;
- res |= (vga.crtc.underline_loc & 0x1f);
- break;
- case 0x15:
- res = vga.crtc.vert_blank_start & 0xff;
- break;
- case 0x16:
- res = vga.crtc.vert_blank_end & 0x7f;
- break;
- case 0x17:
- res = (vga.crtc.sync_en & 1) << 7;
- res |= (vga.crtc.word_mode & 1) << 6;
- res |= (vga.crtc.aw & 1) << 5;
- res |= (vga.crtc.div2 & 1) << 3;
- res |= (vga.crtc.sldiv & 1) << 2;
- res |= (vga.crtc.map14 & 1) << 1;
- res |= (vga.crtc.map13 & 1) << 0;
- break;
- case 0x18:
- res = vga.crtc.line_compare & 0xff;
- break;
- default:
- printf("Unhandled CRTC reg r %02x\n",index);
- break;
- }
- return res;
-}
-
-void vga_device::recompute_params_clock(int divisor, int xtal)
-{
- int vblank_period,hblank_period;
- attoseconds_t refresh;
- uint8_t hclock_m = (!GRAPHIC_MODE) ? VGA_CH_WIDTH : 8;
- int pixel_clock;
-
- /* safety check */
- if(!vga.crtc.horz_disp_end || !vga.crtc.vert_disp_end || !vga.crtc.horz_total || !vga.crtc.vert_total)
- return;
-
- rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end);
-
- vblank_period = (vga.crtc.vert_total + 2);
- hblank_period = ((vga.crtc.horz_total + 5) * ((float)(hclock_m)/divisor));
-
- /* TODO: 10b and 11b settings aren't known */
- pixel_clock = xtal / (((vga.sequencer.data[1]&8) >> 3) + 1);
-
- refresh = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period;
- screen().configure((hblank_period), (vblank_period), visarea, refresh );
- //popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total);
- m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) );
-}
-
-void vga_device::recompute_params()
-{
- if(vga.miscellaneous_output & 8)
- LOGWARN("Warning: VGA external clock latch selected\n");
- else
- recompute_params_clock(1, ((vga.miscellaneous_output & 0xc) ? XTAL(28'636'363) : XTAL(25'174'800)).value());
-}
-
-void vga_device::crtc_reg_write(uint8_t index, uint8_t data)
-{
- /* Doom does this */
-// if(vga.crtc.protect_enable && index <= 0x07)
-// printf("write to protected address %02x\n",index);
- switch(index)
- {
- case 0x00:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_total = (vga.crtc.horz_total & ~0xff) | (data & 0xff);
- recompute_params();
- break;
- case 0x01:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_disp_end = (data & 0xff);
- recompute_params();
- break;
- case 0x02:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_blank_start = (data & 0xff);
- break;
- case 0x03:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_blank_end &= ~0x1f;
- vga.crtc.horz_blank_end |= data & 0x1f;
- vga.crtc.disp_enable_skew = (data & 0x60) >> 5;
- vga.crtc.evra = (data & 0x80) >> 7;
- break;
- case 0x04:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_retrace_start = data & 0xff;
- break;
- case 0x05:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.horz_blank_end &= ~0x20;
- vga.crtc.horz_blank_end |= ((data & 0x80) >> 2);
- vga.crtc.horz_retrace_skew = ((data & 0x60) >> 5);
- vga.crtc.horz_retrace_end = data & 0x1f;
- break;
- case 0x06:
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.vert_total &= ~0xff;
- vga.crtc.vert_total |= data & 0xff;
- recompute_params();
- break;
- case 0x07: // Overflow Register
- vga.crtc.line_compare &= ~0x100;
- vga.crtc.line_compare |= ((data & 0x10) << (8-4));
- if(vga.crtc.protect_enable)
- break;
- vga.crtc.vert_total &= ~0x300;
- vga.crtc.vert_retrace_start &= ~0x300;
- vga.crtc.vert_disp_end &= ~0x300;
- vga.crtc.vert_blank_start &= ~0x100;
- vga.crtc.vert_retrace_start |= ((data & 0x80) << (9-7));
- vga.crtc.vert_disp_end |= ((data & 0x40) << (9-6));
- vga.crtc.vert_total |= ((data & 0x20) << (9-5));
- vga.crtc.vert_blank_start |= ((data & 0x08) << (8-3));
- vga.crtc.vert_retrace_start |= ((data & 0x04) << (8-2));
- vga.crtc.vert_disp_end |= ((data & 0x02) << (8-1));
- vga.crtc.vert_total |= ((data & 0x01) << (8-0));
- recompute_params();
- break;
- case 0x08: // Preset Row Scan Register
- vga.crtc.byte_panning = (data & 0x60) >> 5;
- vga.crtc.preset_row_scan = (data & 0x1f);
- break;
- case 0x09: // Maximum Scan Line Register
- vga.crtc.line_compare &= ~0x200;
- vga.crtc.vert_blank_start &= ~0x200;
- vga.crtc.scan_doubling = ((data & 0x80) >> 7);
- vga.crtc.line_compare |= ((data & 0x40) << (9-6));
- vga.crtc.vert_blank_start |= ((data & 0x20) << (9-5));
- vga.crtc.maximum_scan_line = (data & 0x1f) + 1;
- break;
- case 0x0a:
- vga.crtc.cursor_enable = ((data & 0x20) ^ 0x20) >> 5;
- vga.crtc.cursor_scan_start = data & 0x1f;
- break;
- case 0x0b:
- vga.crtc.cursor_skew = (data & 0x60) >> 5;
- vga.crtc.cursor_scan_end = data & 0x1f;
- break;
- case 0x0c:
- case 0x0d:
- vga.crtc.start_addr_latch &= ~(0xff << (((index & 1)^1) * 8));
- vga.crtc.start_addr_latch |= (data << (((index & 1)^1) * 8));
- break;
- case 0x0e:
- case 0x0f:
- vga.crtc.cursor_addr &= ~(0xff << (((index & 1)^1) * 8));
- vga.crtc.cursor_addr |= (data << (((index & 1)^1) * 8));
- break;
- case 0x10:
- vga.crtc.vert_retrace_start &= ~0xff;
- vga.crtc.vert_retrace_start |= data & 0xff;
- break;
- case 0x11:
- vga.crtc.protect_enable = (data & 0x80) >> 7;
- vga.crtc.bandwidth = (data & 0x40) >> 6;
- vga.crtc.vert_retrace_end = data & 0x0f;
- vga.crtc.irq_clear = (data & 0x10) >> 4;
- vga.crtc.irq_disable = (data & 0x20) >> 5;
- break;
- case 0x12:
- vga.crtc.vert_disp_end &= ~0xff;
- vga.crtc.vert_disp_end |= data & 0xff;
- recompute_params();
- break;
- case 0x13:
- vga.crtc.offset &= ~0xff;
- vga.crtc.offset |= data & 0xff;
- break;
- case 0x14:
- vga.crtc.dw = (data & 0x40) >> 6;
- vga.crtc.div4 = (data & 0x20) >> 5;
- vga.crtc.underline_loc = (data & 0x1f);
- break;
- case 0x15:
- vga.crtc.vert_blank_start &= ~0xff;
- vga.crtc.vert_blank_start |= data & 0xff;
- break;
- case 0x16:
- vga.crtc.vert_blank_end = data & 0x7f;
- break;
- case 0x17:
- vga.crtc.sync_en = (data & 0x80) >> 7;
- vga.crtc.word_mode = (data & 0x40) >> 6;
- vga.crtc.aw = (data & 0x20) >> 5;
- vga.crtc.div2 = (data & 0x08) >> 3;
- vga.crtc.sldiv = (data & 0x04) >> 2;
- vga.crtc.map14 = (data & 0x02) >> 1;
- vga.crtc.map13 = (data & 0x01) >> 0;
- break;
- case 0x18:
- vga.crtc.line_compare &= ~0xff;
- vga.crtc.line_compare |= data & 0xff;
- break;
- default:
- LOG( "Unhandled CRTC reg w %02x %02x\n",index,data);
- break;
- }
-}
-
-void vga_device::seq_reg_write(uint8_t index, uint8_t data)
-{
- switch(index)
- {
- case 0x02:
- vga.sequencer.map_mask = data & 0xf;
- break;
- case 0x03:
- /* --2- 84-- character select A
- ---2 --84 character select B */
- vga.sequencer.char_sel.A = (((data & 0xc) >> 2)<<1) | ((data & 0x20) >> 5);
- vga.sequencer.char_sel.B = (((data & 0x3) >> 0)<<1) | ((data & 0x10) >> 4);
- if(data)
- popmessage("Char SEL checker, contact MAMEdev (%02x %02x)\n",vga.sequencer.char_sel.A,vga.sequencer.char_sel.B);
- break;
- }
-}
-
-uint8_t vga_device::vga_vblank()
-{
- uint8_t res;
- uint16_t vblank_start,vblank_end,vpos;
-
- /* calculate vblank start / end positions */
- res = 0;
- vblank_start = vga.crtc.vert_blank_start;
- vblank_end = vga.crtc.vert_blank_start + vga.crtc.vert_blank_end;
- vpos = screen().vpos();
-
- /* check if we are under vblank period */
- if(vblank_end > vga.crtc.vert_total)
- {
- vblank_end -= vga.crtc.vert_total;
- if(vpos >= vblank_start || vpos <= vblank_end)
- res = 1;
- }
- else
- {
- if(vpos >= vblank_start && vpos <= vblank_end)
- res = 1;
- }
-
- //popmessage("%d %d %d - SR1=%02x",vblank_start,vblank_end,vga.crtc.vert_total,vga.sequencer.data[1]);
-
- return res;
-}
-
-uint8_t vga_device::vga_crtc_r(offs_t offset)
-{
- uint8_t data = 0xff;
-
- switch (offset) {
- case 4:
- data = vga.crtc.index;
- break;
- case 5:
- data = crtc_reg_read(vga.crtc.index);
- break;
- case 0xa:
- uint8_t hsync,vsync;
- vga.attribute.state = 0;
- data = 0;
-
- hsync = screen().hblank() & 1;
- vsync = vga_vblank(); //screen().vblank() & 1;
-
- data |= (hsync | vsync) & 1; // DD - display disable register
- data |= (vsync & 1) << 3; // VRetrace register
-
- /* ega diagnostic readback enough for oak bios */
- switch (vga.attribute.data[0x12]&0x30) {
- case 0:
- if (vga.attribute.data[0x11]&1) data|=0x10;
- if (vga.attribute.data[0x11]&4) data|=0x20;
- break;
- case 0x10:
- data|=(vga.attribute.data[0x11]&0x30);
- break;
- case 0x20:
- if (vga.attribute.data[0x11]&2) data|=0x10;
- if (vga.attribute.data[0x11]&8) data|=0x20;
- break;
- case 0x30:
- data|=(vga.attribute.data[0x11]&0xc0)>>2;
- break;
- }
- break;
- case 0xf:
- /* oak test */
- //data=0;
- /* pega bios on/off */
- data=0x80;
- break;
- }
- return data;
-}
-
-void vga_device::vga_crtc_w(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 4:
- vga.crtc.index = data;
- break;
-
- case 5:
- LOGREGS("vga_crtc_w(): CRTC[0x%02X%s] = 0x%02X\n",
- vga.crtc.index,
- (vga.crtc.index < vga.svga_intf.crtc_regcount) ? "" : "?",
- data);
-
- crtc_reg_write(vga.crtc.index,data);
- //screen().update_partial(screen().vpos());
- #if 0
- if((vga.crtc.index & 0xfe) != 0x0e)
- printf("%02x %02x %d\n",vga.crtc.index,data,screen().vpos());
- #endif
- break;
-
- case 0xa:
- vga.feature_control = data;
- break;
- }
-}
-
-
-
-uint8_t vga_device::port_03b0_r(offs_t offset)
-{
- uint8_t data = 0xff;
- if (get_crtc_port() == 0x3b0)
- data = vga_crtc_r(offset);
- return data;
-}
-
-uint8_t vga_device::gc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- switch(index)
- {
- case 0x00:
- res = vga.gc.set_reset & 0xf;
- break;
- case 0x01:
- res = vga.gc.enable_set_reset & 0xf;
- break;
- case 0x02:
- res = vga.gc.color_compare & 0xf;
- break;
- case 0x03:
- res = (vga.gc.logical_op & 3) << 3;
- res |= (vga.gc.rotate_count & 7);
- break;
- case 0x04:
- res = vga.gc.read_map_sel & 3;
- break;
- case 0x05:
- res = (vga.gc.shift256 & 1) << 6;
- res |= (vga.gc.shift_reg & 1) << 5;
- res |= (vga.gc.host_oe & 1) << 4;
- res |= (vga.gc.read_mode & 1) << 3;
- res |= (vga.gc.write_mode & 3);
- break;
- case 0x06:
- res = (vga.gc.memory_map_sel & 3) << 2;
- res |= (vga.gc.chain_oe & 1) << 1;
- res |= (vga.gc.alpha_dis & 1);
- break;
- case 0x07:
- res = vga.gc.color_dont_care & 0xf;
- break;
- case 0x08:
- res = vga.gc.bit_mask & 0xff;
- break;
- default:
- res = 0xff;
- break;
- }
-
- return res;
-}
-
-uint8_t vga_device::seq_reg_read(uint8_t index)
-{
- LOG( "Reading unmapped sequencer read register %02x (SVGA?)\n", index);
- return 0;
-}
-
-/*
- 4 additional dipswitches
- seems to have emulation modes at register level
- (mda/hgc lines bit 8 not identical to ega/vga)
-
- standard ega/vga dipswitches
- 00000000 320x200
- 00000001 640x200 hanging
- 00000010 640x200 hanging
- 00000011 640x200 hanging
-
- 00000100 640x350 hanging
- 00000101 640x350 hanging EGA mono
- 00000110 320x200
- 00000111 640x200
-
- 00001000 640x200
- 00001001 640x200
- 00001010 720x350 partial visible
- 00001011 720x350 partial visible
-
- 00001100 320x200
- 00001101 320x200
- 00001110 320x200
- 00001111 320x200
-*/
-static INPUT_PORTS_START(vga_sense)
- PORT_START("VGA_SENSE")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
-INPUT_PORTS_END
-
-ioport_constructor vga_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(vga_sense);
-}
-
-uint8_t vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t data = 0xff;
-
- switch (offset)
- {
- case 0:
- data = vga.attribute.index;
- break;
- case 1:
- if((vga.attribute.index&0x20)
- && ((vga.attribute.index&0x1f)<0x10))
- data = 0; // palette access is disabled in this mode
- else if ((vga.attribute.index&0x1f)<sizeof(vga.attribute.data))
- data=vga.attribute.data[vga.attribute.index&0x1f];
- break;
-
- case 2:
- {
- data = 0x60; // is VGA
- const u8 sense_bit = (3 - (vga.miscellaneous_output >> 2)) & 3;
- LOGDSW("Reading sense bit %d\n", sense_bit);
- if(BIT(m_input_sense->read(), sense_bit))
- data |= 0x10;
- break;
- }
-
- case 3:
- data = vga.oak.reg;
- break;
-
- case 4:
- data = vga.sequencer.index;
- break;
-
- case 5:
- if (vga.sequencer.index < vga.svga_intf.seq_regcount)
- data = vga.sequencer.data[vga.sequencer.index];
- else
- data = seq_reg_read(vga.sequencer.index);
- break;
-
- case 6:
- data = vga.dac.mask;
- break;
-
- case 7:
- data = (vga.dac.read) ? 3 : 0;
- break;
-
- case 8:
- data = vga.dac.write_index;
- break;
-
- case 9:
- if (vga.dac.read)
- {
- switch (vga.dac.state++)
- {
- case 0:
- data = vga.dac.color[3*vga.dac.read_index];
- break;
- case 1:
- data = vga.dac.color[3*vga.dac.read_index + 1];
- break;
- case 2:
- data = vga.dac.color[3*vga.dac.read_index + 2];
- break;
- }
-
- if (vga.dac.state==3)
- {
- vga.dac.state = 0;
- vga.dac.read_index++;
- }
- }
- break;
-
- case 0xa:
- data = vga.feature_control;
- break;
-
- case 0xc:
- data = vga.miscellaneous_output;
- break;
-
- case 0xe:
- data = vga.gc.index;
- break;
-
- case 0xf:
- data = gc_reg_read(vga.gc.index);
- break;
- }
- return data;
-}
-
-uint8_t vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t data = 0xff;
- if (get_crtc_port() == 0x3d0)
- data = vga_crtc_r(offset);
- if(offset == 8)
- {
- LOG("VGA: 0x3d8 read %s\n", machine().describe_context());
- data = 0; // TODO: PC-200 reads back CGA register here, everything else returns open bus OR CGA emulation of register 0x3d8
- }
-
- return data;
-}
-
-void vga_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3b0)
- vga_crtc_w(offset, data);
-}
-
-void vga_device::attribute_reg_write(uint8_t index, uint8_t data)
-{
- if((index & 0x30) == 0)
- {
- //if(vga.sequencer.data[1]&0x20) // ok?
- vga.attribute.data[index & 0x1f] = data & 0x3f;
- }
- else
- {
- switch(index & 0x1f)
- {
- /* TODO: intentional dirtiness, variable names to be properly changed */
- case 0x10: vga.attribute.data[0x10] = data; break;
- case 0x11: vga.attribute.data[0x11] = data; break;
- case 0x12: vga.attribute.data[0x12] = data; break;
- case 0x13: vga.attribute.pel_shift_latch = vga.attribute.data[0x13] = data; break;
- case 0x14: vga.attribute.data[0x14] = data; break;
- }
- }
-}
-
-void vga_device::gc_reg_write(uint8_t index,uint8_t data)
-{
- switch(index)
- {
- case 0x00:
- vga.gc.set_reset = data & 0xf;
- break;
- case 0x01:
- vga.gc.enable_set_reset = data & 0xf;
- break;
- case 0x02:
- vga.gc.color_compare = data & 0xf;
- break;
- case 0x03:
- vga.gc.logical_op = (data & 0x18) >> 3;
- vga.gc.rotate_count = data & 7;
- break;
- case 0x04:
- vga.gc.read_map_sel = data & 3;
- break;
- case 0x05:
- vga.gc.shift256 = (data & 0x40) >> 6;
- vga.gc.shift_reg = (data & 0x20) >> 5;
- vga.gc.host_oe = (data & 0x10) >> 4;
- vga.gc.read_mode = (data & 8) >> 3;
- vga.gc.write_mode = data & 3;
- //if(data & 0x10 && vga.gc.alpha_dis)
- // popmessage("Host O/E enabled, contact MAMEdev");
- break;
- case 0x06:
- vga.gc.memory_map_sel = (data & 0xc) >> 2;
- vga.gc.chain_oe = (data & 2) >> 1;
- vga.gc.alpha_dis = (data & 1);
- //if(data & 2 && vga.gc.alpha_dis)
- // popmessage("Chain O/E enabled, contact MAMEdev");
- break;
- case 0x07:
- vga.gc.color_dont_care = data & 0xf;
- break;
- case 0x08:
- vga.gc.bit_mask = data & 0xff;
- break;
- }
-}
-
-void vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch (offset) {
- case 0:
- if (vga.attribute.state==0)
- {
- vga.attribute.index=data;
- }
- else
- {
- attribute_reg_write(vga.attribute.index,data);
- }
- vga.attribute.state=!vga.attribute.state;
- break;
- case 2:
- vga.miscellaneous_output=data;
- recompute_params();
- break;
- case 3:
- vga.oak.reg = data;
- break;
- case 4:
- vga.sequencer.index = data;
- break;
- case 5:
- LOGREGS("vga_port_03c0_w(): SEQ[0x%02X%s] = 0x%02X\n",
- vga.sequencer.index,
- (vga.sequencer.index < vga.svga_intf.seq_regcount) ? "" : "?",
- data);
- if (vga.sequencer.index < vga.svga_intf.seq_regcount)
- {
- vga.sequencer.data[vga.sequencer.index] = data;
- }
-
- seq_reg_write(vga.sequencer.index,data);
- recompute_params();
- break;
- case 6:
- vga.dac.mask=data;
- vga.dac.dirty=1;
- break;
- case 7:
- vga.dac.read_index=data;
- vga.dac.state=0;
- vga.dac.read=1;
- break;
- case 8:
- vga.dac.write_index=data;
- vga.dac.state=0;
- vga.dac.read=0;
- break;
- case 9:
- if (!vga.dac.read)
- {
- switch (vga.dac.state++) {
- case 0:
- vga.dac.color[3*vga.dac.write_index]=data;
- break;
- case 1:
- vga.dac.color[3*vga.dac.write_index + 1]=data;
- break;
- case 2:
- vga.dac.color[3*vga.dac.write_index + 2]=data;
- break;
- }
- vga.dac.dirty=1;
- if (vga.dac.state==3) {
- vga.dac.state=0; vga.dac.write_index++;
- }
- }
- break;
- case 0xe:
- vga.gc.index=data;
- break;
- case 0xf:
- gc_reg_write(vga.gc.index,data);
- break;
- }
-}
-
-
-
-void vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- vga_crtc_w(offset, data);
-}
-
-void vga_device::device_reset()
-{
- /* clear out the VGA structure */
- memset(vga.pens, 0, sizeof(vga.pens));
- vga.miscellaneous_output = 0;
- vga.feature_control = 0;
- vga.sequencer.index = 0;
- memset(vga.sequencer.data, 0, sizeof(vga.sequencer.data));
- vga.crtc.index = 0;
- memset(vga.crtc.data, 0, sizeof(vga.crtc.data));
- vga.gc.index = 0;
- memset(vga.gc.latch, 0, sizeof(vga.gc.latch));
- memset(&vga.attribute, 0, sizeof(vga.attribute));
- memset(&vga.dac, 0, sizeof(vga.dac));
- memset(&vga.cursor, 0, sizeof(vga.cursor));
- memset(&vga.oak, 0, sizeof(vga.oak));
-
- vga.gc.memory_map_sel = 0x3; /* prevent xtbios excepting vga ram as system ram */
-/* amstrad pc1640 bios relies on the position of
- the video memory area,
- so I introduced the reset to switch to b8000 area */
- vga.sequencer.data[4] = 0;
-
- /* TODO: real defaults */
- vga.crtc.line_compare = 0x3ff;
- /* skeleton/indiana.cpp boot PROM doesn't set this and assumes it's 0xff */
- vga.dac.mask = 0xff;
-}
-
-uint8_t vga_device::mem_r(offs_t offset)
-{
- /* TODO: check me */
- switch(vga.gc.memory_map_sel & 0x03)
- {
- case 0: break;
- case 1: offset &= 0x0ffff; break;
- case 2: offset -= 0x10000; offset &= 0x07fff; break;
- case 3: offset -= 0x18000; offset &= 0x07fff; break;
- }
-
- if(vga.sequencer.data[4] & 4)
- {
- int data;
- if (!machine().side_effects_disabled())
- {
- vga.gc.latch[0]=vga.memory[(offset)];
- vga.gc.latch[1]=vga.memory[(offset)+0x10000];
- vga.gc.latch[2]=vga.memory[(offset)+0x20000];
- vga.gc.latch[3]=vga.memory[(offset)+0x30000];
- }
-
- if (vga.gc.read_mode)
- {
- // In Read Mode 1 latch is checked against this
- // cfr. lombrall & intsocch where they RMW sprite-like objects
- // and anything outside this formula goes transparent.
- const u8 target_color = (vga.gc.color_compare & vga.gc.color_dont_care);
- data = 0;
-
- for(u8 byte = 0; byte < 8; byte++)
- {
- u8 fill_latch = 0;
- for(u8 layer = 0; layer < 4; layer++)
- {
- if(vga.gc.latch[layer] & 1 << byte)
- fill_latch |= 1 << layer;
- }
- fill_latch &= vga.gc.color_dont_care;
- if(fill_latch == target_color)
- data |= 1 << byte;
- }
- }
- else
- data=vga.gc.latch[vga.gc.read_map_sel];
-
- return data;
- }
- else
- {
- // TODO: Guesswork, probably not right
- uint8_t i,data;
-
- data = 0;
- //printf("%08x\n",offset);
-
- for(i=0;i<4;i++)
- {
- if(vga.sequencer.map_mask & 1 << i)
- data |= vga.memory[offset+i*0x10000];
- }
-
- return data;
- }
-
- // never executed
- //return 0;
-}
-
-void vga_device::mem_w(offs_t offset, uint8_t data)
-{
- //Inside each case must prevent writes to non-mapped VGA memory regions, not only mask the offset.
- switch(vga.gc.memory_map_sel & 0x03)
- {
- case 0: break;
- case 1:
- if(offset & 0x10000)
- return;
-
- offset &= 0x0ffff;
- break;
- case 2:
- if((offset & 0x18000) != 0x10000)
- return;
-
- offset &= 0x07fff;
- break;
- case 3:
- if((offset & 0x18000) != 0x18000)
- return;
-
- offset &= 0x07fff;
- break;
- }
-
- {
- uint8_t i;
-
- for(i=0;i<4;i++)
- {
- if(vga.sequencer.map_mask & 1 << i)
- vga.memory[offset+i*0x10000] = (vga.sequencer.data[4] & 4) ? vga_latch_write(i,data) : data;
- }
- return;
- }
-}
-
-uint8_t vga_device::mem_linear_r(offs_t offset)
-{
- return vga.memory[offset % vga.svga_intf.vram_size];
-}
-
-void vga_device::mem_linear_w(offs_t offset, uint8_t data)
-{
- vga.memory[offset % vga.svga_intf.vram_size] = data;
-}
diff --git a/src/devices/video/pc_vga.h b/src/devices/video/pc_vga.h
index 54f2ef168ae..64715853808 100644
--- a/src/devices/video/pc_vga.h
+++ b/src/devices/video/pc_vga.h
@@ -20,7 +20,10 @@
// ======================> vga_device
-class vga_device : public device_t, public device_video_interface, public device_palette_interface
+class vga_device : public device_t
+ , public device_video_interface
+ , public device_palette_interface
+ , public device_memory_interface
{
friend class ibm8514a_device;
@@ -31,12 +34,8 @@ public:
virtual void zero();
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- virtual uint8_t port_03b0_r(offs_t offset);
- virtual void port_03b0_w(offs_t offset, uint8_t data);
- virtual uint8_t port_03c0_r(offs_t offset);
- virtual void port_03c0_w(offs_t offset, uint8_t data);
- virtual uint8_t port_03d0_r(offs_t offset);
- virtual void port_03d0_w(offs_t offset, uint8_t data);
+ void io_map(address_map &map);
+
virtual uint8_t mem_r(offs_t offset);
virtual void mem_w(offs_t offset, uint8_t data);
virtual uint8_t mem_linear_r(offs_t offset);
@@ -81,17 +80,51 @@ protected:
void vga_vh_mono(bitmap_rgb32 &bitmap, const rectangle &cliprect);
virtual uint8_t pc_vga_choosevideomode();
void recompute_params_clock(int divisor, int xtal);
- virtual uint8_t crtc_reg_read(uint8_t index);
virtual void recompute_params();
- virtual void crtc_reg_write(uint8_t index, uint8_t data);
- virtual uint8_t seq_reg_read(uint8_t index);
- virtual void seq_reg_write(uint8_t index, uint8_t data);
uint8_t vga_vblank();
- uint8_t vga_crtc_r(offs_t offset);
- void vga_crtc_w(offs_t offset, uint8_t data);
- uint8_t gc_reg_read(uint8_t index);
- void attribute_reg_write(uint8_t index, uint8_t data);
- void gc_reg_write(uint8_t index,uint8_t data);
+
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual void io_3bx_3dx_map(address_map &map);
+
+ u8 crtc_address_r(offs_t offset);
+ void crtc_address_w(offs_t offset, u8 data);
+ virtual u8 crtc_data_r(offs_t offset);
+ virtual void crtc_data_w(offs_t offset, u8 data);
+ u8 input_status_1_r(offs_t offset);
+ void feature_control_w(offs_t offset, u8 data);
+
+ virtual void io_3cx_map(address_map &map);
+
+ u8 atc_address_r(offs_t offset);
+ void atc_address_data_w(offs_t offset, u8 data);
+ u8 atc_data_r(offs_t offset);
+ u8 input_status_0_r(offs_t offset);
+ void miscellaneous_output_w(offs_t offset, u8 data);
+ u8 sequencer_address_r(offs_t offset);
+ void sequencer_address_w(offs_t offset, u8 data);
+ virtual u8 sequencer_data_r(offs_t offset);
+ virtual void sequencer_data_w(offs_t offset, u8 data);
+ u8 ramdac_mask_r(offs_t offset);
+ void ramdac_mask_w(offs_t offset, u8 data);
+ u8 ramdac_state_r(offs_t offset);
+ void ramdac_read_index_w(offs_t offset, u8 data);
+ u8 ramdac_write_index_r(offs_t offset);
+ void ramdac_write_index_w(offs_t offset, u8 data);
+ u8 ramdac_data_r(offs_t offset);
+ void ramdac_data_w(offs_t offset, u8 data);
+ u8 feature_control_r(offs_t offset);
+ u8 miscellaneous_output_r(offs_t offset);
+ virtual u8 gc_address_r(offs_t offset);
+ virtual void gc_address_w(offs_t offset, u8 data);
+ virtual u8 gc_data_r(offs_t offset);
+ virtual void gc_data_w(offs_t offset, u8 data);
+
+ virtual void crtc_map(address_map &map);
+ virtual void sequencer_map(address_map &map);
+ virtual void gc_map(address_map &map);
+ virtual void attribute_map(address_map &map);
+
virtual uint16_t offset();
virtual uint32_t start_addr();
virtual uint8_t vga_latch_write(int offs, uint8_t data);
@@ -125,8 +158,6 @@ protected:
struct
{
size_t vram_size;
- int seq_regcount;
- int crtc_regcount;
} svga_intf;
std::unique_ptr<uint8_t []> memory;
@@ -245,6 +276,23 @@ protected:
required_ioport m_input_sense;
emu_timer *m_vblank_timer;
+
+ enum {
+ MAIN_IF_REG = 0,
+ CRTC_REG,
+ GC_REG,
+ SEQ_REG,
+ ATC_REG
+ };
+
+ address_space_config m_main_if_space_config;
+ address_space_config m_crtc_space_config;
+ address_space_config m_gc_space_config;
+ address_space_config m_seq_space_config;
+ address_space_config m_atc_space_config;
+
+private:
+ bool m_ioas = false;
};
@@ -273,7 +321,7 @@ protected:
virtual void device_start() override;
struct
{
- uint8_t bank_r,bank_w;
+ uint8_t bank_r, bank_w;
uint8_t rgb8_en;
uint8_t rgb15_en;
uint8_t rgb16_en;
diff --git a/src/devices/video/pc_vga_ati.cpp b/src/devices/video/pc_vga_ati.cpp
index b50d7b562ff..171ab494a37 100644
--- a/src/devices/video/pc_vga_ati.cpp
+++ b/src/devices/video/pc_vga_ati.cpp
@@ -43,23 +43,6 @@ void ati_vga_device::device_add_mconfig(machine_config &config)
EEPROM_93C46_16BIT(config, "ati_eeprom");
}
-uint8_t ati_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t data = 0xff;
-
- switch(offset)
- {
- case 1:
- if ((vga.attribute.index&0x1f) < sizeof(vga.attribute.data))
- data = vga.attribute.data[vga.attribute.index&0x1f];
- break;
- default:
- data = vga_device::port_03c0_r(offset);
- break;
- }
- return data;
-}
-
uint16_t ati_vga_device::offset()
{
//popmessage("Offset: %04x %s %s %s %s",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD",(ati.ext_reg[0x33] & 0x40) ? "PEL" : "---",(ati.ext_reg[0x30] & 0x20) ? "256" : "---");
diff --git a/src/devices/video/pc_vga_ati.h b/src/devices/video/pc_vga_ati.h
index 70c83f50e11..beeae3c3053 100644
--- a/src/devices/video/pc_vga_ati.h
+++ b/src/devices/video/pc_vga_ati.h
@@ -23,7 +23,6 @@ public:
virtual void mem_w(offs_t offset, uint8_t data) override;
// VGA registers
- virtual uint8_t port_03c0_r(offs_t offset) override;
uint8_t ati_port_ext_r(offs_t offset);
void ati_port_ext_w(offs_t offset, uint8_t data);
diff --git a/src/devices/video/clgd542x.cpp b/src/devices/video/pc_vga_cirrus.cpp
index e3429d03e2b..d1a0df36379 100644
--- a/src/devices/video/clgd542x.cpp
+++ b/src/devices/video/pc_vga_cirrus.cpp
@@ -1,22 +1,32 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
-
- Cirrus Logic GD542x/3x video chipsets
-
-*/
+ *
+ * Cirrus Logic CL-GD542x/3x video chipsets
+ *
+ * TODO:
+ * - Original Acumos AVGA1/2 chipsets (Cirrus Logic eventually bought Acumos and rebranded);
+ * - Fix or implement hidden DAC modes (15bpp + mixed, true color, others);
+ * - bebox: logo at startup is squashed;
+ * - Merge with trs/vis.cpp implementation (CL-GD5200 RAMDAC with custom VGA controller)
+ *
+ */
#include "emu.h"
-#include "clgd542x.h"
+#include "pc_vga_cirrus.h"
#include "screen.h"
#define LOG_REG (1U << 1)
#define LOG_BLIT (1U << 2)
-#define VERBOSE (0)
+#define LOG_HDAC (1U << 3) // log hidden DAC
+
+#define VERBOSE (LOG_GENERAL | LOG_HDAC)
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
+// TODO: remove these macros
//#define TEXT_LINES (LINES_HELPER)
#define LINES (vga.crtc.vert_disp_end+1)
#define TEXT_LINES (vga.crtc.vert_disp_end+1)
@@ -49,6 +59,9 @@ DEFINE_DEVICE_TYPE(CIRRUS_GD5446, cirrus_gd5446_device, "clgd5446", "Cirrus Logi
cirrus_gd5428_device::cirrus_gd5428_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cirrus_gd5428_device(mconfig, CIRRUS_GD5428, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5428_device::crtc_map), this));
+ m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5428_device::gc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5428_device::sequencer_map), this));
}
cirrus_gd5428_device::cirrus_gd5428_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -59,11 +72,574 @@ cirrus_gd5428_device::cirrus_gd5428_device(const machine_config &mconfig, device
cirrus_gd5430_device::cirrus_gd5430_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cirrus_gd5428_device(mconfig, CIRRUS_GD5430, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5430_device::crtc_map), this));
+ m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5430_device::gc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5430_device::sequencer_map), this));
}
cirrus_gd5446_device::cirrus_gd5446_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cirrus_gd5428_device(mconfig, CIRRUS_GD5446, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5446_device::crtc_map), this));
+ m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5446_device::gc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(cirrus_gd5446_device::sequencer_map), this));
+}
+
+void cirrus_gd5428_device::io_3cx_map(address_map &map)
+{
+ svga_device::io_3cx_map(map);
+ map(0x06, 0x06).rw(FUNC(cirrus_gd5428_device::ramdac_hidden_mask_r), FUNC(cirrus_gd5428_device::ramdac_hidden_mask_w));
+ map(0x09, 0x09).rw(FUNC(cirrus_gd5428_device::ramdac_overlay_r), FUNC(cirrus_gd5428_device::ramdac_overlay_w));
+}
+
+u8 cirrus_gd5428_device::ramdac_hidden_mask_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_hidden_dac_phase ++;
+ if (m_hidden_dac_phase >= 4)
+ {
+ u8 res;
+ // TODO: '5420 doesn't have this
+ // TODO: '5428 reads do not lock the Hidden DAC
+ res = m_hidden_dac_mode;
+ //m_hidden_dac_phase = 0;
+ LOGMASKED(LOG_HDAC, "CL: Hidden DAC read (%02x)\n", res);
+ return res;
+ }
+
+ return vga_device::ramdac_mask_r(0);
+}
+
+void cirrus_gd5428_device::ramdac_hidden_mask_w(offs_t offset, u8 data)
+{
+ if (m_hidden_dac_phase >= 4)
+ {
+ // TODO: '5420 doesn't have this
+ // TODO: '5428 reads do not lock the Hidden DAC
+ m_hidden_dac_mode = data;
+ m_hidden_dac_phase = 0;
+ LOGMASKED(LOG_HDAC, "CL: Hidden DAC write %02x\n", data);
+ return;
+ }
+
+ vga_device::ramdac_mask_w(0, data);
+}
+
+u8 cirrus_gd5428_device::ramdac_overlay_r(offs_t offset)
+{
+ if(!m_ext_palette_enabled)
+ return vga_device::ramdac_data_r(0);
+
+ u8 res = 0xff;
+ if (vga.dac.read && !machine().side_effects_disabled())
+ {
+ switch (vga.dac.state++)
+ {
+ case 0:
+ res = m_ext_palette[vga.dac.read_index & 0x0f].red;
+ break;
+ case 1:
+ res = m_ext_palette[vga.dac.read_index & 0x0f].green;
+ break;
+ case 2:
+ res = m_ext_palette[vga.dac.read_index & 0x0f].blue;
+ break;
+ }
+
+ if (vga.dac.state == 3)
+ {
+ vga.dac.state = 0;
+ vga.dac.read_index++;
+ }
+ }
+
+ return res;
+}
+
+void cirrus_gd5428_device::ramdac_overlay_w(offs_t offset, u8 data)
+{
+ if(!m_ext_palette_enabled)
+ {
+ vga_device::ramdac_data_w(0, data);
+ return;
+ }
+
+ if (!vga.dac.read)
+ {
+ switch (vga.dac.state++) {
+ case 0:
+ m_ext_palette[vga.dac.write_index & 0x0f].red=data;
+ break;
+ case 1:
+ m_ext_palette[vga.dac.write_index & 0x0f].green=data;
+ break;
+ case 2:
+ m_ext_palette[vga.dac.write_index & 0x0f].blue=data;
+ break;
+ }
+ vga.dac.dirty=1;
+ if (vga.dac.state==3)
+ {
+ vga.dac.state=0;
+ vga.dac.write_index++;
+ }
+ }
+}
+
+void cirrus_gd5428_device::crtc_map(address_map &map)
+{
+ svga_device::crtc_map(map);
+ // VGA Vertical Blank end
+ // some SVGA chipsets use all 8 bits, and this is one of them (according to MFGTST CRTC tests)
+ map(0x16, 0x16).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.crtc.vert_blank_end & 0x00ff;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.vert_blank_end &= ~0x00ff;
+ vga.crtc.vert_blank_end |= data;
+ cirrus_define_video_mode();
+ })
+ );
+ map(0x19, 0x19).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_cr19;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_cr19 = data;
+ })
+ );
+ map(0x1a, 0x1a).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_cr1a;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_cr1a = data;
+ vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xff3f) | ((data & 0x30) << 2);
+ vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & 0xfcff) | ((data & 0xc0) << 2);
+ cirrus_define_video_mode();
+ })
+ );
+ map(0x1b, 0x1b).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_cr1b;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_cr1b = data;
+ vga.crtc.start_addr_latch &= ~0x070000;
+ vga.crtc.start_addr_latch |= ((data & 0x01) << 16);
+ vga.crtc.start_addr_latch |= ((data & 0x0c) << 15);
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x10) << 4);
+ cirrus_define_video_mode();
+ })
+ );
+ // TODO: CR1D for GD543x
+ //vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xf7ffff) | ((data & 0x01) << 16);
+ map(0x27, 0x27).lr8(
+ NAME([this] (offs_t offset) {
+ return m_chip_id;
+ })
+ );
+}
+
+void cirrus_gd5428_device::gc_map(address_map &map)
+{
+ svga_device::gc_map(map);
+ map(0x00, 0x00).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.set_reset & ((gc_mode_ext & 0x04) ? 0xff : 0x0f);
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ // if extended writes are enabled (bit 2 of index 0bh), then index 0 and 1 are extended to 8 bits,
+ // however XFree86 does not appear to do this...
+ vga.gc.set_reset = data & 0xff;
+ })
+ );
+ map(0x01, 0x01).lrw8(
+ NAME([this](offs_t offset) {
+ return vga.gc.enable_set_reset & ((gc_mode_ext & 0x04) ? 0xff : 0x0f);
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.enable_set_reset = data & 0xff;
+ })
+ );
+ map(0x05, 0x05).lrw8(
+ NAME([this](offs_t offset) {
+ u8 res = (vga.gc.shift256 & 1) << 6;
+ res |= (vga.gc.shift_reg & 1) << 5;
+ res |= (vga.gc.host_oe & 1) << 4;
+ res |= (vga.gc.read_mode & 1) << 3;
+ if(gc_mode_ext & 0x04)
+ res |= (vga.gc.write_mode & 7);
+ else
+ res |= (vga.gc.write_mode & 3);
+ return res;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ vga.gc.shift256 = (data & 0x40) >> 6;
+ vga.gc.shift_reg = (data & 0x20) >> 5;
+ vga.gc.host_oe = (data & 0x10) >> 4;
+ vga.gc.read_mode = (data & 8) >> 3;
+ if(gc_mode_ext & 0x04)
+ vga.gc.write_mode = data & 7;
+ else
+ vga.gc.write_mode = data & 3;
+ })
+ );
+ // Offset register 0
+ map(0x09, 0x09).lrw8(
+ NAME([this](offs_t offset) {
+ return gc_bank_0;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ gc_bank_0 = data;
+ LOG("CL: Offset register 0 set to %i\n", data);
+ })
+ );
+ // Offset register 1
+ map(0x0a, 0x0a).lrw8(
+ NAME([this](offs_t offset) {
+ return gc_bank_1;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ gc_bank_1 = data;
+ LOG("CL: Offset register 1 set to %i\n", data);
+ })
+ );
+ // Graphics controller mode extensions
+ map(0x0b, 0x0b).lrw8(
+ NAME([this](offs_t offset) {
+ return gc_mode_ext;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ gc_mode_ext = data;
+ if(!(data & 0x04))
+ {
+ vga.gc.set_reset &= 0x0f;
+ vga.gc.enable_set_reset &= 0x0f;
+ }
+ if(!(data & 0x08))
+ vga.sequencer.map_mask &= 0x0f;
+ })
+ );
+ // Colour Key
+ // map(0x0c, 0x0c)
+ // Colour Key Mask
+ // map(0x0d, 0x0d)
+ // Miscellaneous Control
+ // map(0x0e, 0x0e)
+ // Background Colour Byte 1
+ map(0x10, 0x10).lrw8(
+ NAME([this](offs_t offset) {
+ return m_gr10;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_gr10 = data;
+ })
+ );
+ // Foreground Colour Byte 1
+ map(0x11, 0x11).lrw8(
+ NAME([this](offs_t offset) {
+ return m_gr11;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_gr11 = data;
+ })
+ );
+ // BLT Width 0
+ map(0x20, 0x20).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_width & 0x00ff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_width = (m_blt_width & 0xff00) | data;
+ })
+ );
+ // BLT Width 1
+ map(0x21, 0x21).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_width >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_width = (m_blt_width & 0x00ff) | (data << 8);
+ })
+ );
+ // BLT Height 0
+ map(0x22, 0x22).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_height & 0x00ff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_height = (m_blt_height & 0xff00) | data;
+ })
+ );
+ // BLT Height 1
+ map(0x23, 0x23).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_height >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_height = (m_blt_height & 0x00ff) | (data << 8);
+ })
+ );
+ // BLT Destination Pitch 0
+ map(0x24, 0x24).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_dest_pitch & 0x00ff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_dest_pitch = (m_blt_dest_pitch & 0xff00) | data;
+ })
+ );
+ // BLT Destination Pitch 1
+ map(0x25, 0x25).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_dest_pitch >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_dest_pitch = (m_blt_dest_pitch & 0x00ff) | (data << 8);
+ })
+ );
+ // BLT Source Pitch 0
+ map(0x26, 0x26).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_source_pitch & 0x00ff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_source_pitch = (m_blt_source_pitch & 0xff00) | data;
+ })
+ );
+ // BLT Source Pitch 1
+ map(0x27, 0x27).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_source_pitch >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_source_pitch = (m_blt_source_pitch & 0x00ff) | (data << 8);
+ })
+ );
+ // BLT Destination start 0/1/2
+ map(0x28, 0x2a).lrw8(
+ NAME([this](offs_t offset) {
+ return (m_blt_dest >> (8 * (offset & 3))) & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ const u8 byte_access = (8 * (offset & 3));
+ const u32 old_mask = ~(0xff << byte_access);
+ m_blt_dest = (m_blt_dest & old_mask) | (data << byte_access);
+ })
+ );
+ // BLT source start 0/1/2
+ map(0x2c, 0x2e).lrw8(
+ NAME([this](offs_t offset) {
+ return (m_blt_source >> (8 * (offset & 3))) & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ const u8 byte_access = (8 * (offset & 3));
+ const u32 old_mask = ~(0xff << byte_access);
+ m_blt_source = (m_blt_source & old_mask) | (data << byte_access);
+ })
+ );
+ // BLT destination write mask (GD5430/36/40 only)
+ // map(0x2f, 0x2f)
+ // BLT Mode
+ map(0x30, 0x30).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_mode;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_mode = data;
+ })
+ );
+ // BitBLT Start / Status
+ map(0x31, 0x31).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_status;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_status = data & ~0xf2;
+ if(data & 0x02)
+ {
+ if(m_blt_mode & 0x04) // blit source is system memory
+ start_system_bitblt();
+ else
+ start_bitblt();
+ }
+ })
+ );
+ // BitBLT ROP mode
+ map(0x32, 0x32).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_rop;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_rop = data;
+ })
+ );
+ // BitBLT Transparent Colour 0
+ map(0x34, 0x34).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_trans_colour & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_trans_colour = (m_blt_trans_colour & 0xff00) | data;
+ })
+ );
+ // BitBLT Transparent Colour 1
+ map(0x35, 0x35).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_trans_colour >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_trans_colour = (m_blt_trans_colour & 0x00ff) | (data << 8);
+ })
+ );
+ // BitBLT Transparent Colour Mask 0
+ map(0x36, 0x36).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_trans_colour_mask & 0xff;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0xff00) | data;
+ })
+ );
+ // BitBLT Transparent Colour Mask 1
+ map(0x37, 0x37).lrw8(
+ NAME([this](offs_t offset) {
+ return m_blt_trans_colour_mask >> 8;
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0x00ff) | (data << 8);
+ })
+ );
+}
+
+void cirrus_gd5428_device::sequencer_map(address_map &map)
+{
+ svga_device::sequencer_map(map);
+ map(0x02, 0x02).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.sequencer.map_mask & ((gc_mode_ext & 0x08) ? 0xff : 0x0f);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.sequencer.map_mask = data & ((gc_mode_ext & 0x08) ? 0xff : 0x0f);
+ })
+ );
+ map(0x06, 0x06).lrw8(
+ NAME([this] (offs_t offset) {
+ return (gc_locked) ? 0x0f : m_lock_reg;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // TODO: extensions are always enabled on the GD5429
+ // bits 3,5,6,7 ignored
+
+ gc_locked = (data & 0x17) != 0x12;
+ LOG("Cirrus register extensions %s\n", gc_locked ? "unlocked" : "locked");
+ m_lock_reg = data & 0x17;
+ })
+ );
+ map(0x07, 0x07).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ // TODO: bebox startup enables this
+ if((data & 0xf0) != 0)
+ popmessage("1MB framebuffer window enabled at %iMB (%02x)",data >> 4,data);
+ vga.sequencer.data[0x07] = data;
+ cirrus_define_video_mode();
+ })
+ );
+ // TODO: check me
+ map(0x09, 0x09).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.sequencer.data[0x09];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.sequencer.data[0x09] = data;
+ })
+ );
+ map(0x0a, 0x0a).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_scratchpad1;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // GD5402/GD542x BIOS writes VRAM size here
+ m_scratchpad1 = data;
+ })
+ );
+ map(0x0b, 0x0e).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_vclk_num[offset];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_vclk_num[offset] = data;
+ })
+ );
+ map(0x0f, 0x0f).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = vga.sequencer.data[0x0f] & 0xe7;
+ // 32-bit DRAM data bus width (1MB-2MB)
+ res |= 0x18;
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.sequencer.data[0x0f] = data;
+ })
+ );
+ // bits 5-7 of the register index are the low bits of the X co-ordinate
+ map(0x10, 0x10).select(0xe0).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ m_cursor_x = (data << 3) | ((offset & 0xe0) >> 5);
+ })
+ );
+ // bits 5-7 of the register index are the low bits of the Y co-ordinate
+ map(0x11, 0x11).select(0xe0).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ m_cursor_y = (data << 3) | ((offset & 0xe0) >> 5);
+ })
+ );
+ map(0x12, 0x12).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_cursor_attr;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // bit 0 - enable cursor
+ // bit 1 - enable extra palette (cursor colours are there)
+ // bit 2 - 64x64 cursor (32x32 if clear, GD5422+)
+ // bit 7 - overscan colour protect - if set, use colour 2 in the extra palette for the border (GD5424+)
+ m_cursor_attr = data;
+ m_ext_palette_enabled = data & 0x02;
+ })
+ );
+ map(0x13, 0x13).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ // bits 0 and 1 are ignored if using 64x64 cursor
+ m_cursor_addr = data;
+ })
+ );
+ map(0x14, 0x14).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_scratchpad2;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_scratchpad2 = data;
+ })
+ );
+ map(0x15, 0x15).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_scratchpad3;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // GD543x BIOS writes VRAM size here
+ m_scratchpad3 = data;
+ })
+ );
+ map(0x1b, 0x1e).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_vclk_denom[offset];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_vclk_denom[offset] = data;
+ })
+ );
}
void cirrus_gd5428_device::device_start()
@@ -77,8 +653,6 @@ void cirrus_gd5428_device::device_start()
vga.crtc.maximum_scan_line = 1;
// copy over interfaces
- vga.svga_intf.seq_regcount = 0x1f;
- vga.svga_intf.crtc_regcount = 0x2d;
vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
@@ -87,6 +661,8 @@ void cirrus_gd5428_device::device_start()
save_pointer(vga.sequencer.data,"Sequencer Registers",0x100);
save_pointer(vga.attribute.data,"Attribute Registers", 0x15);
save_item(NAME(m_chip_id));
+ save_item(NAME(m_hidden_dac_phase));
+ save_item(NAME(m_hidden_dac_mode));
m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
@@ -127,6 +703,8 @@ void cirrus_gd5428_device::device_reset()
memset(m_ext_palette, 0, sizeof(m_ext_palette));
m_ext_palette_enabled = false;
m_blt_system_transfer = false;
+ m_hidden_dac_phase = 0;
+ m_hidden_dac_mode = 0;
}
uint32_t cirrus_gd5428_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -226,14 +804,59 @@ void cirrus_gd5428_device::cirrus_define_video_mode()
clock = (xtal * numerator / denominator / mul).dvalue();
}
- if (!gc_locked && (vga.sequencer.data[0x07] & 0x01))
+ if (!gc_locked)
{
+ svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = 0;
+ // gambl186 relies on this, don't setup any hidden DAC but only this
+ if (vga.sequencer.data[0x07] & 0x01)
+ svga.rgb8_en = 1;
+
+ if (BIT(m_hidden_dac_mode, 7))
+ {
+ // TODO: needs subclassing, earlier chips don't have all of these modes
+ if (BIT(m_hidden_dac_mode, 4))
+ popmessage("Cirrus: Unsupported mixed 5-5-5 / 8bpp mode selected");
+ switch(m_hidden_dac_mode & 0x4f)
+ {
+ case 0x00:
+ case 0x40:
+ // 5-5-5 Sierra
+ svga.rgb15_en = 1;
+ break;
+ case 0x41:
+ svga.rgb16_en = 1;
+ break;
+ case 0x43: // CCIR601 YUV422 16-bit
+ case 0x44: // YUV411 8-bit
+ case 0x4a: // 16bpp + YUV422 overlay
+ case 0x4b: // 16bpp + YUV411 overlay
+ popmessage("Cirrus: CL-GD545 YUV mode selected %02x", m_hidden_dac_mode);
+ break;
+ case 0x45:
+ svga.rgb24_en = 1;
+ break;
+ case 0x46:
+ case 0x47:
+ popmessage("Cirrus: CL-GD545+ DAC power down selected %02x", m_hidden_dac_mode);
+ break;
+ case 0x48:
+ popmessage("Cirrus: CL-GD545+ 8-bit grayscale selected");
+ break;
+ case 0x49:
+ svga.rgb8_en = 1;
+ break;
+ default:
+ popmessage("Cirrus: reserved mode selected %02x", m_hidden_dac_mode);
+ break;
+ }
+ }
+
switch(vga.sequencer.data[0x07] & 0x06) // bit 3 is reserved on GD542x
{
- case 0x00: svga.rgb8_en = 1; break;
- case 0x02: svga.rgb16_en = 1; clock /= 2; break; // Clock / 2 for 16-bit data
- case 0x04: svga.rgb24_en = 1; clock /= 3; break; // Clock / 3 for 24-bit data
- case 0x06: svga.rgb16_en = 1; divisor = 2; break; // Clock rate for 16-bit data
+ case 0x00: break;
+ case 0x02: clock /= 2; break; // Clock / 2 for 16-bit data
+ case 0x04: clock /= 3; break; // Clock / 3 for 24-bit data
+ case 0x06: divisor = 2; break; // Clock rate for 16-bit data
}
}
recompute_params_clock(divisor, (int)clock);
@@ -243,7 +866,8 @@ uint16_t cirrus_gd5428_device::offset()
{
uint16_t off = vga_device::offset();
- if (svga.rgb8_en == 1) // guess
+ // TODO: check true enable condition
+ if (svga.rgb8_en == 1)
off <<= 2;
if (svga.rgb16_en == 1)
off <<= 2;
@@ -517,643 +1141,6 @@ void cirrus_gd5428_device::copy_pixel(uint8_t src, uint8_t dst)
vga.memory[m_blt_dest_current % vga.svga_intf.vram_size] = res;
}
-uint8_t cirrus_gd5428_device::cirrus_seq_reg_read(uint8_t index)
-{
- uint8_t res;
-
- res = 0xff;
-
- switch(index)
- {
- case 0x02:
- if(gc_mode_ext & 0x08)
- res = vga.sequencer.map_mask & 0xff;
- else
- res = vga.sequencer.map_mask & 0x0f;
- break;
- case 0x06:
- if(gc_locked)
- return 0x0f;
- else
- return m_lock_reg;
- break;
- case 0x09:
- //printf("%02x\n",index);
- res = vga.sequencer.data[index];
- break;
- case 0x0a:
- res = m_scratchpad1;
- break;
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- res = m_vclk_num[index-0x0b];
- break;
- case 0x0f:
- res = vga.sequencer.data[index] & 0xe7;
- res |= 0x18; // 32-bit DRAM data bus width (1MB-2MB)
- break;
- case 0x12:
- res = m_cursor_attr;
- break;
- case 0x14:
- res = m_scratchpad2;
- break;
- case 0x15:
- res = m_scratchpad3;
- break;
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- res = m_vclk_denom[index-0x1b];
- break;
- default:
- res = vga.sequencer.data[index];
- }
-
- return res;
-}
-
-void cirrus_gd5428_device::cirrus_seq_reg_write(uint8_t index, uint8_t data)
-{
- LOGMASKED(LOG_REG, "CL: SEQ write %02x to SR%02x\n",data,index);
- switch(index)
- {
- case 0x02:
- if(gc_mode_ext & 0x08)
- vga.sequencer.map_mask = data & 0xff;
- else
- vga.sequencer.map_mask = data & 0x0f;
- break;
- case 0x06:
- // Note: extensions are always enabled on the GD5429
- if((data & 0x17) == 0x12) // bits 3,5,6,7 ignored
- {
- gc_locked = false;
- logerror("Cirrus register extensions unlocked\n");
- }
- else
- {
- gc_locked = true;
- logerror("Cirrus register extensions locked\n");
- }
- m_lock_reg = data & 0x17;
- break;
- case 0x07:
- if((data & 0xf0) != 0)
- popmessage("1MB framebuffer window enabled at %iMB (%02x)",data >> 4,data);
- vga.sequencer.data[vga.sequencer.index] = data;
- break;
- case 0x09:
- //printf("%02x %02x\n",index,data);
- vga.sequencer.data[vga.sequencer.index] = data;
- break;
- case 0x0a:
- m_scratchpad1 = data; // GD5402/GD542x BIOS writes VRAM size here.
- break;
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- m_vclk_num[index-0x0b] = data;
- break;
- case 0x10:
- case 0x30:
- case 0x50:
- case 0x70:
- case 0x90:
- case 0xb0:
- case 0xd0:
- case 0xf0: // bits 5-7 of the register index are the low bits of the X co-ordinate
- m_cursor_x = (data << 3) | ((index & 0xe0) >> 5);
- break;
- case 0x11:
- case 0x31:
- case 0x51:
- case 0x71:
- case 0x91:
- case 0xb1:
- case 0xd1:
- case 0xf1: // bits 5-7 of the register index are the low bits of the Y co-ordinate
- m_cursor_y = (data << 3) | ((index & 0xe0) >> 5);
- break;
- case 0x12:
- // bit 0 - enable cursor
- // bit 1 - enable extra palette (cursor colours are there)
- // bit 2 - 64x64 cursor (32x32 if clear, GD5422+)
- // bit 7 - overscan colour protect - if set, use colour 2 in the extra palette for the border (GD5424+)
- m_cursor_attr = data;
- m_ext_palette_enabled = data & 0x02;
- break;
- case 0x13:
- m_cursor_addr = data; // bits 0 and 1 are ignored if using 64x64 cursor
- break;
- case 0x14:
- m_scratchpad2 = data;
- break;
- case 0x15:
- m_scratchpad3 = data; // GD543x BIOS writes VRAM size here
- break;
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- m_vclk_denom[index-0x1b] = data;
- break;
- default:
- vga.sequencer.data[vga.sequencer.index] = data;
- seq_reg_write(vga.sequencer.index,data);
- }
-}
-
-uint8_t cirrus_gd5428_device::cirrus_gc_reg_read(uint8_t index)
-{
- uint8_t res = 0xff;
-
- switch(index)
- {
- case 0x00:
- if(gc_mode_ext & 0x04)
- res = vga.gc.set_reset & 0xff;
- else
- res = vga.gc.set_reset & 0x0f;
- break;
- case 0x01:
- if(gc_mode_ext & 0x04)
- res = vga.gc.enable_set_reset & 0xff;
- else
- res = vga.gc.enable_set_reset & 0x0f;
- break;
- case 0x05:
- res = (vga.gc.shift256 & 1) << 6;
- res |= (vga.gc.shift_reg & 1) << 5;
- res |= (vga.gc.host_oe & 1) << 4;
- res |= (vga.gc.read_mode & 1) << 3;
- if(gc_mode_ext & 0x04)
- res |= (vga.gc.write_mode & 7);
- else
- res |= (vga.gc.write_mode & 3);
- break;
- case 0x09: // Offset register 0
- res = gc_bank_0;
- break;
- case 0x0a: // Offset register 1
- res = gc_bank_1;
- break;
- case 0x0b: // Graphics controller mode extensions
- res = gc_mode_ext;
- break;
- case 0x0c: // Colour Key
- break;
- case 0x0d: // Colour Key Mask
- break;
- case 0x0e: // Miscellaneous Control
- break;
- case 0x10: // Background Colour Byte 1
- res = m_gr10;
- break;
- case 0x11: // Foreground Colour Byte 1
- res = m_gr11;
- break;
- case 0x20: // BLT Width 0
- res = m_blt_width & 0x00ff;
- break;
- case 0x21: // BLT Width 1
- res = m_blt_width >> 8;
- break;
- case 0x22: // BLT Height 0
- res = m_blt_height & 0x00ff;
- break;
- case 0x23: // BLT Height 1
- res = m_blt_height >> 8;
- break;
- case 0x24: // BLT Destination Pitch 0
- res = m_blt_dest_pitch & 0x00ff;
- break;
- case 0x25: // BLT Destination Pitch 1
- res = m_blt_dest_pitch >> 8;
- break;
- case 0x26: // BLT Source Pitch 0
- res = m_blt_source_pitch & 0x00ff;
- break;
- case 0x27: // BLT Source Pitch 1
- res = m_blt_source_pitch >> 8;
- break;
- case 0x28: // BLT Destination start 0
- res = m_blt_dest & 0x000000ff;
- break;
- case 0x29: // BLT Destination start 1
- res = (m_blt_dest & 0x0000ff00) >> 8;
- break;
- case 0x2a: // BLT Destination start 2
- res = (m_blt_dest & 0x00ff0000) >> 16;
- break;
- case 0x2c: // BLT source start 0
- res = m_blt_source & 0x000000ff;
- break;
- case 0x2d: // BLT source start 1
- res = (m_blt_source & 0x0000ff00) >> 8;
- break;
- case 0x2e: // BLT source start 2
- res = (m_blt_source & 0x00ff0000) >> 16;
- break;
- case 0x2f: // BLT destination write mask (GD5430/36/40)
- // TODO
- break;
- case 0x30: // BLT Mode
- res = m_blt_mode;
- break;
- case 0x31: // BitBLT Start / Status
- res = m_blt_status;
- break;
- case 0x32: // BitBLT ROP mode
- res = m_blt_rop;
- break;
- case 0x34: // BitBLT Transparent Colour
- res = m_blt_trans_colour & 0x00ff;
- break;
- case 0x35:
- res = m_blt_trans_colour >> 8;
- break;
- case 0x36: // BitBLT Transparent Colour Mask
- res = m_blt_trans_colour_mask & 0x00ff;
- break;
- case 0x37:
- res = m_blt_trans_colour_mask >> 8;
- break;
- default:
- res = gc_reg_read(index);
- }
-
- return res;
-}
-
-void cirrus_gd5428_device::cirrus_gc_reg_write(uint8_t index, uint8_t data)
-{
- LOGMASKED(LOG_REG, "CL: GC write %02x to GR%02x\n",data,index);
- switch(index)
- {
- case 0x00: // if extended writes are enabled (bit 2 of index 0bh), then index 0 and 1 are extended to 8 bits, however XFree86 does not appear to do this...
- vga.gc.set_reset = data & 0xff;
- break;
- case 0x01:
- vga.gc.enable_set_reset = data & 0xff;
- break;
- case 0x05:
- vga.gc.shift256 = (data & 0x40) >> 6;
- vga.gc.shift_reg = (data & 0x20) >> 5;
- vga.gc.host_oe = (data & 0x10) >> 4;
- vga.gc.read_mode = (data & 8) >> 3;
- if(gc_mode_ext & 0x04)
- vga.gc.write_mode = data & 7;
- else
- vga.gc.write_mode = data & 3;
- break;
- case 0x09: // Offset register 0
- gc_bank_0 = data;
- logerror("CL: Offset register 0 set to %i\n",data);
- break;
- case 0x0a: // Offset register 1
- gc_bank_1 = data;
- logerror("CL: Offset register 1 set to %i\n",data);
- break;
- case 0x0b: // Graphics controller mode extensions
- gc_mode_ext = data;
- if(!(data & 0x04))
- {
- vga.gc.set_reset &= 0x0f;
- vga.gc.enable_set_reset &= 0x0f;
- }
- if(!(data & 0x08))
- vga.sequencer.map_mask &= 0x0f;
- break;
- case 0x0c: // Colour Key
- break;
- case 0x0d: // Colour Key Mask
- break;
- case 0x0e: // Miscellaneous Control
- break;
- case 0x10: // Background Colour Byte 1
- m_gr10 = data;
- break;
- case 0x11: // Foreground Colour Byte 1
- m_gr11 = data;
- break;
- case 0x20: // BLT Width 0
- m_blt_width = (m_blt_width & 0xff00) | data;
- break;
- case 0x21: // BLT Width 1
- m_blt_width = (m_blt_width & 0x00ff) | (data << 8);
- break;
- case 0x22: // BLT Height 0
- m_blt_height = (m_blt_height & 0xff00) | data;
- break;
- case 0x23: // BLT Height 1
- m_blt_height = (m_blt_height & 0x00ff) | (data << 8);
- break;
- case 0x24: // BLT Destination Pitch 0
- m_blt_dest_pitch = (m_blt_dest_pitch & 0xff00) | data;
- break;
- case 0x25: // BLT Destination Pitch 1
- m_blt_dest_pitch = (m_blt_dest_pitch & 0x00ff) | (data << 8);
- break;
- case 0x26: // BLT Source Pitch 0
- m_blt_source_pitch = (m_blt_source_pitch & 0xff00) | data;
- break;
- case 0x27: // BLT Source Pitch 1
- m_blt_source_pitch = (m_blt_source_pitch & 0x00ff) | (data << 8);
- break;
- case 0x28: // BLT Destination start 0
- m_blt_dest = (m_blt_dest & 0xffffff00) | data;
- break;
- case 0x29: // BLT Destination start 1
- m_blt_dest = (m_blt_dest & 0xffff00ff) | (data << 8);
- break;
- case 0x2a: // BLT Destination start 2
- m_blt_dest = (m_blt_dest & 0xff00ffff) | (data << 16);
- break;
- case 0x2c: // BLT source start 0
- m_blt_source = (m_blt_source & 0xffffff00) | data;
- break;
- case 0x2d: // BLT source start 1
- m_blt_source = (m_blt_source & 0xffff00ff) | (data << 8);
- break;
- case 0x2e: // BLT source start 2
- m_blt_source = (m_blt_source & 0xff00ffff) | (data << 16);
- break;
- case 0x2f: // BLT destination write mask (GD5430/36/40)
- // TODO
- break;
- case 0x30: // BLT Mode
- m_blt_mode = data;
- break;
- case 0x31: // BitBLT Start / Status
- m_blt_status = data & ~0xf2;
- if(data & 0x02)
- {
- if(m_blt_mode & 0x04) // blit source is system memory
- start_system_bitblt();
- else
- start_bitblt();
- }
- break;
- case 0x32: // BitBLT ROP mode
- m_blt_rop = data;
- break;
- case 0x34: // BitBLT Transparent Colour
- m_blt_trans_colour = (m_blt_trans_colour & 0xff00) | data;
- break;
- case 0x35:
- m_blt_trans_colour = (m_blt_trans_colour & 0x00ff) | (data << 8);
- break;
- case 0x36: // BitBLT Transparent Colour Mask
- m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0xff00) | data;
- break;
- case 0x37:
- m_blt_trans_colour_mask = (m_blt_trans_colour_mask & 0x00ff) | (data << 8);
- break;
- default:
- gc_reg_write(index,data);
- }
-}
-
-uint8_t cirrus_gd5428_device::port_03c0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- switch(offset)
- {
- case 0x05:
- res = cirrus_seq_reg_read(vga.sequencer.index);
- break;
- case 0x09:
- if(!m_ext_palette_enabled)
- res = vga_device::port_03c0_r(offset);
- else
- {
- if (vga.dac.read)
- {
- switch (vga.dac.state++)
- {
- case 0:
- res = m_ext_palette[vga.dac.read_index & 0x0f].red;
- break;
- case 1:
- res = m_ext_palette[vga.dac.read_index & 0x0f].green;
- break;
- case 2:
- res = m_ext_palette[vga.dac.read_index & 0x0f].blue;
- break;
- }
-
- if (vga.dac.state==3)
- {
- vga.dac.state = 0;
- vga.dac.read_index++;
- }
- }
- }
- break;
- case 0x0f:
- res = cirrus_gc_reg_read(vga.gc.index);
- break;
- default:
- res = vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void cirrus_gd5428_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x05:
- cirrus_seq_reg_write(vga.sequencer.index,data);
- break;
- case 0x09:
- if(!m_ext_palette_enabled)
- vga_device::port_03c0_w(offset,data);
- else
- {
- if (!vga.dac.read)
- {
- switch (vga.dac.state++) {
- case 0:
- m_ext_palette[vga.dac.write_index & 0x0f].red=data;
- break;
- case 1:
- m_ext_palette[vga.dac.write_index & 0x0f].green=data;
- break;
- case 2:
- m_ext_palette[vga.dac.write_index & 0x0f].blue=data;
- break;
- }
- vga.dac.dirty=1;
- if (vga.dac.state==3)
- {
- vga.dac.state=0;
- vga.dac.write_index++;
- }
- }
- }
- break;
- case 0x0f:
- cirrus_gc_reg_write(vga.gc.index,data);
- break;
- default:
- vga_device::port_03c0_w(offset,data);
- break;
- }
- cirrus_define_video_mode();
-}
-
-uint8_t cirrus_gd5428_device::port_03b0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- res = cirrus_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-uint8_t cirrus_gd5428_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = cirrus_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void cirrus_gd5428_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- cirrus_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03b0_w(offset,data);
- break;
- }
- }
- cirrus_define_video_mode();
-}
-
-void cirrus_gd5428_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- cirrus_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
- cirrus_define_video_mode();
-}
-
-uint8_t cirrus_gd5428_device::cirrus_crtc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- switch(index)
- {
- case 0x16: // VGA Vertical Blank end - some SVGA chipsets use all 8 bits, and this is one of them (according to MFGTST CRTC tests)
- res = vga.crtc.vert_blank_end & 0x00ff;
- break;
- case 0x19:
- res = m_cr19;
- break;
- case 0x1a:
- res = m_cr1a;
- break;
- case 0x1b:
- res = m_cr1b;
- break;
- case 0x27:
- res = m_chip_id;
- break;
- default:
- res = crtc_reg_read(index);
- break;
- }
-
- return res;
-}
-
-void cirrus_gd5428_device::cirrus_crtc_reg_write(uint8_t index, uint8_t data)
-{
- LOGMASKED(LOG_REG, "CL: CRTC write %02x to CR%02x\n",data,index);
- switch(index)
- {
- case 0x16: // VGA Vertical Blank end - some SVGA chipsets use all 8 bits, and this is one of them (according to MFGTST CRTC tests)
- vga.crtc.vert_blank_end &= ~0x00ff;
- vga.crtc.vert_blank_end |= data;
- break;
- case 0x19:
- m_cr19 = data;
- break;
- case 0x1a:
- m_cr1a = data;
- vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xff3f) | ((data & 0x30) << 2);
- vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & 0xfcff) | ((data & 0xc0) << 2);
- break;
- case 0x1b:
- m_cr1b = data;
- vga.crtc.start_addr_latch &= ~0x070000;
- vga.crtc.start_addr_latch |= ((data & 0x01) << 16);
- vga.crtc.start_addr_latch |= ((data & 0x0c) << 15);
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x10) << 4);
- cirrus_define_video_mode();
- break;
- case 0x1d:
- //vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xf7ffff) | ((data & 0x01) << 16); // GD543x
- break;
- case 0x27:
- // Do nothing, read only
- break;
- default:
- crtc_reg_write(index,data);
- break;
- }
-
-}
-
uint8_t cirrus_gd5428_device::vga_latch_write(int offs, uint8_t data)
{
uint8_t res = 0;
@@ -1198,7 +1185,9 @@ uint8_t cirrus_gd5428_device::mem_r(offs_t offset)
else // 4kB bank granularity
addr = bank * 0x1000;
- // Is the display address adjusted automatically when not using Chain-4 addressing? The GD542x BIOS doesn't do it, but Virtual Pool expects it.
+ // Is the display address adjusted automatically when not using Chain-4 addressing?
+ // The GD542x BIOS doesn't do it, but Virtual Pool expects it.
+
if(!(vga.sequencer.data[4] & 0x8))
addr <<= 2;
diff --git a/src/devices/video/clgd542x.h b/src/devices/video/pc_vga_cirrus.h
index 950163ec35f..38425d6d0cd 100644
--- a/src/devices/video/clgd542x.h
+++ b/src/devices/video/pc_vga_cirrus.h
@@ -5,8 +5,8 @@
Cirrus Logic GD542x/3x video chipsets
*/
-#ifndef MAME_VIDEO_CLGD542X_H
-#define MAME_VIDEO_CLGD542X_H
+#ifndef MAME_VIDEO_CIRRUS_H
+#define MAME_VIDEO_CIRRUS_H
#pragma once
@@ -18,12 +18,6 @@ public:
// construction/destruction
cirrus_gd5428_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
@@ -37,6 +31,14 @@ protected:
virtual void device_reset() override;
virtual uint16_t offset() override;
+ virtual void io_3cx_map(address_map &map) override;
+
+ u8 ramdac_hidden_mask_r(offs_t offset);
+ void ramdac_hidden_mask_w(offs_t offset, u8 data);
+ u8 ramdac_overlay_r(offs_t offset);
+ void ramdac_overlay_w(offs_t offset, u8 data);
+ u8 m_hidden_dac_mode = 0;
+ u8 m_hidden_dac_phase = 0;
uint8_t m_chip_id;
uint8_t gc_mode_ext;
@@ -88,14 +90,12 @@ protected:
virtual uint8_t vga_latch_write(int offs, uint8_t data) override;
+ virtual void crtc_map(address_map &map) override;
+ virtual void gc_map(address_map &map) override;
+ virtual void sequencer_map(address_map &map) override;
+
private:
void cirrus_define_video_mode();
- uint8_t cirrus_seq_reg_read(uint8_t index);
- void cirrus_seq_reg_write(uint8_t index, uint8_t data);
- uint8_t cirrus_gc_reg_read(uint8_t index);
- void cirrus_gc_reg_write(uint8_t index, uint8_t data);
- uint8_t cirrus_crtc_reg_read(uint8_t index);
- void cirrus_crtc_reg_write(uint8_t index, uint8_t data);
void start_bitblt();
void start_reverse_bitblt();
@@ -129,4 +129,4 @@ DECLARE_DEVICE_TYPE(CIRRUS_GD5428, cirrus_gd5428_device)
DECLARE_DEVICE_TYPE(CIRRUS_GD5430, cirrus_gd5430_device)
DECLARE_DEVICE_TYPE(CIRRUS_GD5446, cirrus_gd5446_device)
-#endif // MAME_VIDEO_CLGD542X_H
+#endif // MAME_VIDEO_CIRRUS_H
diff --git a/src/devices/video/pc_vga_nvidia.cpp b/src/devices/video/pc_vga_nvidia.cpp
index 2615b10fab1..372a17a5b1a 100644
--- a/src/devices/video/pc_vga_nvidia.cpp
+++ b/src/devices/video/pc_vga_nvidia.cpp
@@ -51,6 +51,8 @@ DEFINE_DEVICE_TYPE(NVIDIA_NV3_VGA, nvidia_nv3_vga_device, "nvidia_nv3_vga", "
nvidia_nv3_vga_device::nvidia_nv3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: svga_device(mconfig, NVIDIA_NV3_VGA, tag, owner, clock)
{
+ m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(nvidia_nv3_vga_device::io_3bx_3dx_map), this));
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(nvidia_nv3_vga_device::crtc_map), this));
}
void nvidia_nv3_vga_device::device_add_mconfig(machine_config &config)
@@ -78,8 +80,6 @@ void nvidia_nv3_vga_device::device_start()
vga.crtc.maximum_scan_line = 1;
- vga.svga_intf.seq_regcount = 0x05;
- vga.svga_intf.crtc_regcount = 0x40;
// TODO: shared with main GPU, fake it for now
// Start address ends at 20 bits so 0x1fffff mask / 2,097,151 bytes / 2MB window is (theorically) given
// we assume that is really 4 MB, VESA tests extensively tests with 0x7f banks
@@ -93,113 +93,18 @@ void nvidia_nv3_vga_device::device_start()
save_item(NAME(m_ext_offset));
}
-// TODO: should really calculate the access bit internally
-uint8_t nvidia_nv3_vga_device::port_03b0_r(offs_t offset)
+void nvidia_nv3_vga_device::io_3bx_3dx_map(address_map &map)
{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- LOGRMA("RMA_ACCESS R %02x\n", offset & 3);
- break;
-
- case 5:
- res = crtc_reg_read(vga.crtc.index);
- break;
-
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void nvidia_nv3_vga_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- LOGRMA("RMA_ACCESS W %02x -> %02x\n", offset & 3, data);
- break;
-
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- crtc_reg_write(vga.crtc.index, data);
- break;
-
- default:
- vga_device::port_03b0_w(offset, data);
- break;
- }
- }
- //define_video_mode();
-}
-
-uint8_t nvidia_nv3_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- LOGRMA("RMA_ACCESS R %02x\n", offset & 3);
- break;
-
- case 5:
- res = crtc_reg_read(vga.crtc.index);
- break;
-
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void nvidia_nv3_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- LOGRMA("RMA_ACCESS W %02x -> %02x\n", offset & 3, data);
- break;
-
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- crtc_reg_write(vga.crtc.index, data);
- break;
-
- default:
- vga_device::port_03d0_w(offset, data);
- break;
- }
- }
- //define_video_mode();
+ svga_device::io_3bx_3dx_map(map);
+ map(0x00, 0x03).lrw8(
+ NAME([this] (offs_t offset) {
+ LOGRMA("RMA_ACCESS R %02x\n", offset & 3);
+ return space().unmap();
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ LOGRMA("RMA_ACCESS W %02x -> %02x\n", offset & 3, data);
+ })
+ );
}
uint8_t nvidia_nv3_vga_device::mem_r(offs_t offset)
@@ -221,133 +126,26 @@ void nvidia_nv3_vga_device::mem_w(offs_t offset, uint8_t data)
uint16_t nvidia_nv3_vga_device::offset()
{
+ // TODO: check true enable condition
if (svga.rgb8_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
return (vga.crtc.offset << 3) + m_ext_offset;
return svga_device::offset();
}
+// TODO: lock mechanism
+void nvidia_nv3_vga_device::crtc_map(address_map &map)
+{
+ svga_device::crtc_map(map);
+ // REPAINT_0
/*
* xxx- ---- Row offset bits 3-5
* ---x xxxx Start address bits 16-20
*/
-// map(0x19, 0x19) REPAINT_0
-
-/*
- * ???? ?-?? <unknown, definitely used>
- * ---- -x-- Shifts row offset by 1 bit (verify)
- */
-// map(0x1a, 0x1a) REPAINT_1
-
-/*
- * --xx xxxx write bank, in 32k units
- */
-// map(0x1d, 0x1d) WRITE_BANK
-
-/*
- * --xx xxxx read bank
- */
-// map(0x1e, 0x1e) READ_BANK
-
-/*
- * ---x ---- Horizontal Total bit 8
- * ---- x--- Vertical Sync Start bit 10
- * ---- -x-- Vertical Blank Start bit 10
- * ---- --x- Vertical Display End bit 10
- * ---- ---x Vertical Total bit 10
- */
-// map(0x25, 0x25) EXTENDED_VERT
-
-/*
- * ---- --xx Pixel Format
- * ---- --00 VGA
- * ---- --01 8bpp
- * ---- --10 16bpp
- * ---- --11 32bpp
- */
-// map(0x28, 0x28) PIXEL_FMT
-
-/*
- * ---- ---x Horizontal Display End bit 8
- */
-// map(0x2d, 0x2d) EXTENDED_HORZ
-
-/*
- * ---- xxx- RMA index
- * ---- ---x enable RMA
- */
-// map(0x38, 0x38) RMA_MODE
-
-/*
- * ---- x--- SDA
- * ---- -x-- SCL
- */
-// map(0x3e, 0x3e) I2C_READ
-
-/*
- * ---x ---- SCL
- * ---- x--- SDA
- */
-// map(0x3f, 0x3f) I2C_WRITE
-
-uint8_t nvidia_nv3_vga_device::crtc_reg_read(uint8_t index)
-{
- uint8_t res = 0;
-
- //index &= 0x3f;
-
- if(index <= 0x18)
- return svga_device::crtc_reg_read(index);
-
- switch(index)
- {
- case 0x19:
- res = m_repaint[0];
- break;
- case 0x1a:
- res = m_repaint[1];
- break;
- case 0x1d:
- res = svga.bank_w;
- break;
- case 0x1e:
- res = svga.bank_r;
- break;
- case 0x25:
- res = vga.crtc.data[0x25];
- break;
- case 0x28:
- res = svga.rgb32_en ? 3 : svga.rgb16_en ? 2 : svga.rgb8_en ? 1 : 0;
- break;
- case 0x2d:
- res = (vga.crtc.horz_disp_end >> 10) & 1;
- break;
- case 0x38:
- res = vga.crtc.data[0x38];
- LOGRMA("RMA_MODE read %02x\n", res);
- break;
- default:
- LOGCRTC("EXT CRTC: %02x Read\n", index);
- //machine().debug_break();
- res = vga.crtc.data[index];
-
- break;
- }
-
- return res;
-}
-
-void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
-{
- //index &= 0x3f;
- if(index <= 0x18)
- {
- svga_device::crtc_reg_write(index,data);
- return;
- }
-
- switch(index)
- {
- case 0x19:
+ map(0x19, 0x19).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_repaint[0];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
// TODO: untested, likely used in extended text modes
//vga.crtc.start_addr_latch &= ~0x1f0000;
//vga.crtc.start_addr_latch |= ((data & 0x1f) << 16);
@@ -355,8 +153,18 @@ void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
m_repaint[0] = data;
//m_ext_offset = recalculate_ext_offset();
LOGCRTC("EXT CRTC: REPAINT_0 %02x\n", data);
- break;
- case 0x1a:
+ })
+ );
+ // REPAINT_1
+/*
+ * ???? ?-?? <unknown, definitely used>
+ * ---- -x-- Shifts row offset by 1 bit (verify)
+ */
+ map(0x1a, 0x1a).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_repaint[1];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
// TODO: this definitely uses more regs in the equation
// REPAINT_0 REPAINT_1 base_offset <expected_extra_offset>
// 10eh 320x200 16bpp 0x00 0x3c 0x50 560 / 0x230 (with scan doubler?)
@@ -372,18 +180,49 @@ void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
m_repaint[1] = data;
//m_ext_offset = recalculate_ext_offset();
LOGCRTC("EXT CRTC: REPAINT_1 %02x\n", data);
- break;
- case 0x1d:
+ })
+ );
+ // WRITE_BANK
+/*
+ * --xx xxxx write bank, in 32k units
+ */
+ map(0x1d, 0x1d).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.bank_w;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
if (data & 0x80)
LOGWARN("WRITE_BANK: attempt to write to undocumented bits %02x\n", data);
svga.bank_w = data & 0x7f;
- break;
- case 0x1e:
+ })
+ );
+ // READ_BANK
+/*
+ * --xx xxxx read bank
+ */
+ map(0x1e, 0x1e).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.bank_r;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
if (data & 0x80)
LOGWARN("READ_BANK: attempt to write to undocumented bits %02x\n", data);
svga.bank_r = data & 0x7f;
- break;
- case 0x25:
+ })
+ );
+ // EXTENDED_VERT
+/*
+ * ---x ---- Horizontal Total bit 8
+ * ---- x--- Vertical Sync Start bit 10
+ * ---- -x-- Vertical Blank Start bit 10
+ * ---- --x- Vertical Display End bit 10
+ * ---- ---x Vertical Total bit 10
+ */
+ map(0x25, 0x25).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.crtc.data[0x25];
+ }),
+ NAME([this] (offs_t offset, u8 data) {
if (data & 0xe0)
LOGWARN("EXTENDED_VERT: attempt to write to undocumented bits %02x\n", data);
LOGCRTC("EXT CRTC: EXTENDED_VERT %02x\n", data & 0x1f);
@@ -394,8 +233,21 @@ void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
vga.crtc.vert_total = (vga.crtc.vert_total & 0x03ff) | ((BIT(data, 0) << 10));
vga.crtc.data[0x25] = data;
recompute_params();
- break;
- case 0x28:
+ })
+ );
+ // PIXEL_FMT
+/*
+ * ---- --xx Pixel Format
+ * ---- --00 VGA
+ * ---- --01 8bpp
+ * ---- --10 16bpp
+ * ---- --11 32bpp
+ */
+ map(0x28, 0x28).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.rgb32_en ? 3 : svga.rgb16_en ? 2 : svga.rgb8_en ? 1 : 0;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
if (data & 0xfc)
LOGWARN("PIXEL_FMT: attempt to write to undocumented bits %02x\n", data);
data &= 3;
@@ -419,22 +271,50 @@ void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
LOGCRTC("PIXEL_FMT: SVGA 32bpp mode selected\n");
break;
}
- break;
- case 0x2d:
+ })
+ );
+ // EXTENDED_HORZ
+/*
+ * ---- ---x Horizontal Display End bit 8
+ */
+ map(0x2d, 0x2d).lrw8(
+ NAME([this] (offs_t offset) {
+ return (vga.crtc.horz_disp_end >> 10) & 1;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
if (data & 0xfc)
LOGWARN("EXTENDED_HORZ: attempt to write to undocumented bits %02x\n", data);
LOGCRTC("EXT CRTC: EXTENDED_HORZ %02x\n", data & 1);
vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0x00ff) | ((data & 0x01) << 8);
recompute_params();
- break;
- case 0x38:
- vga.crtc.data[index] = data;
+ })
+ );
+ // RMA_MODE
+/*
+ * ---- xxx- RMA index
+ * ---- ---x enable RMA
+ */
+ map(0x38, 0x38).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = vga.crtc.data[0x38];
+ LOGRMA("RMA_MODE read %02x\n", res);
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.data[0x38] = data;
LOGRMA("RMA_MODE write %s, index %d\n", data & 1 ? "enable" : "disable", (data & 0xe) >> 1);
- break;
- default:
- vga.crtc.data[index] = data;
-
- LOGCRTC("EXT CRTC [%02x] <- %02x\n",index,data);
- break;
- }
+ })
+ );
+ // I2C_READ
+/*
+ * ---- x--- SDA
+ * ---- -x-- SCL
+ */
+// map(0x3e, 0x3e)
+ // I2C_WRITE
+/*
+ * ---x ---- SCL
+ * ---- x--- SDA
+ */
+// map(0x3f, 0x3f)
}
diff --git a/src/devices/video/pc_vga_nvidia.h b/src/devices/video/pc_vga_nvidia.h
index 14213e64af2..9981b55f530 100644
--- a/src/devices/video/pc_vga_nvidia.h
+++ b/src/devices/video/pc_vga_nvidia.h
@@ -22,19 +22,11 @@ public:
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
-// virtual uint8_t port_03c0_r(offs_t offset) override;
-// virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
-// virtual uint8_t mem_r(offs_t offset) override;
-// virtual void mem_w(offs_t offset, uint8_t data) override;
+ virtual void io_3bx_3dx_map(address_map &map) override;
protected:
virtual void device_start() override;
- virtual uint8_t crtc_reg_read(uint8_t index) override;
- virtual void crtc_reg_write(uint8_t index, uint8_t data) override;
+ virtual void crtc_map(address_map &map) override;
virtual ioport_constructor device_input_ports() const override;
diff --git a/src/devices/video/pc_vga_s3.cpp b/src/devices/video/pc_vga_s3.cpp
index 28bc2b5de90..140a6b493fa 100644
--- a/src/devices/video/pc_vga_s3.cpp
+++ b/src/devices/video/pc_vga_s3.cpp
@@ -27,11 +27,14 @@ DEFINE_DEVICE_TYPE(S3_VGA, s3_vga_device, "s3_vga", "S3 Graphics VGA
s3_vga_device::s3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: s3_vga_device(mconfig, S3_VGA, tag, owner, clock)
{
+
}
s3_vga_device::s3_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)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3_vga_device::crtc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3_vga_device::sequencer_map), this));
}
void s3_vga_device::device_add_mconfig(machine_config &config)
@@ -125,188 +128,129 @@ void s3_vga_device::s3_define_video_mode()
recompute_params_clock(divisor, xtal);
}
-uint8_t s3_vga_device::crtc_reg_read(uint8_t index)
+void s3_vga_device::crtc_map(address_map &map)
{
- uint8_t res;
-
- if(index <= 0x18)
- res = svga_device::crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x2d:
- res = s3.id_high;
- break;
- case 0x2e:
- res = s3.id_low;
- break;
- case 0x2f:
- res = s3.revision;
- break;
- case 0x30: // CR30 Chip ID/REV register
- res = s3.id_cr30;
- break;
- case 0x31:
- res = s3.memory_config;
- break;
- case 0x35:
- res = s3.crt_reg_lock;
- break;
- case 0x36: // Configuration register 1
- res = s3.strapping & 0x000000ff; // PCI (not really), Fast Page Mode DRAM
- break;
- case 0x37: // Configuration register 2
- res = (s3.strapping & 0x0000ff00) >> 8; // enable chipset, 64k BIOS size, internal DCLK/MCLK
- break;
- case 0x38:
- res = s3.reg_lock1;
- break;
- case 0x39:
- res = s3.reg_lock2;
- break;
- case 0x42: // CR42 Mode Control
- res = s3.cr42 & 0x0f; // bit 5 set if interlaced, leave it unset for now.
- break;
- case 0x43:
- res = s3.cr43;
- break;
- case 0x45:
- res = s3.cursor_mode;
- s3.cursor_fg_ptr = 0;
- s3.cursor_bg_ptr = 0;
- break;
- case 0x46:
- res = (s3.cursor_x & 0xff00) >> 8;
- break;
- case 0x47:
- res = s3.cursor_x & 0x00ff;
- break;
- case 0x48:
- res = (s3.cursor_y & 0xff00) >> 8;
- break;
- case 0x49:
- res = s3.cursor_y & 0x00ff;
- break;
- case 0x4a:
- res = s3.cursor_fg[s3.cursor_fg_ptr++];
- s3.cursor_fg_ptr %= 4;
- break;
- case 0x4b:
- res = s3.cursor_bg[s3.cursor_bg_ptr++];
- s3.cursor_bg_ptr %= 4;
- break;
- case 0x4c:
- res = (s3.cursor_start_addr & 0xff00) >> 8;
- break;
- case 0x4d:
- res = s3.cursor_start_addr & 0x00ff;
- break;
- case 0x4e:
- res = s3.cursor_pattern_x;
- break;
- case 0x4f:
- res = s3.cursor_pattern_y;
- break;
- case 0x51:
- res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
- 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;
- 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)
- res = s3.cr42 & 0x0f;
- else
- res = (vga.miscellaneous_output & 0xc) >> 2;
- break;
- case 0x67:
- res = s3.ext_misc_ctrl_2;
- break;
- case 0x68: // Configuration register 3
- res = (s3.strapping & 0x00ff0000) >> 16; // no /CAS,/OE stretch time, 32-bit data bus size
- break;
- case 0x69:
- res = vga.crtc.start_addr_latch >> 16;
- break;
- case 0x6a:
- res = svga.bank_r & 0x7f;
- break;
- case 0x6f: // Configuration register 4 (Trio64V+)
- res = (s3.strapping & 0xff000000) >> 24; // LPB(?) mode, Serial port I/O at port 0xe8, Serial port I/O disabled (MMIO only), no WE delay
- break;
- default:
- res = vga.crtc.data[index];
- //machine().debug_break();
- //printf("%02x\n",index);
- break;
- }
- }
-
- return res;
-}
-
-void s3_vga_device::crtc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x18)
- svga_device::crtc_reg_write(index,data);
- else
- {
- switch(index)
- {
- case 0x31: // CR31 Memory Configuration Register
- s3.memory_config = data;
- vga.crtc.start_addr_latch &= ~0x30000;
- vga.crtc.start_addr_latch |= ((data & 0x30) << 12);
- s3_define_video_mode();
- break;
- case 0x35:
- if((s3.reg_lock1 & 0xc) != 8 || ((s3.reg_lock1 & 0xc0) == 0)) // lock register
- return;
- s3.crt_reg_lock = data;
- svga.bank_w = data & 0xf;
- svga.bank_r = svga.bank_w;
- break;
- case 0x36:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffffff00) | data;
- LOG("CR36: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x37:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8);
- LOG("CR37: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x38:
- s3.reg_lock1 = data;
- break;
- case 0x39:
- /* TODO: reg lock mechanism */
- s3.reg_lock2 = data;
- break;
- case 0x40:
- s3.enable_8514 = data & 0x01; // enable 8514/A registers (x2e8, x6e8, xae8, xee8)
- break;
- case 0x42:
- s3.cr42 = data; // bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented)
- 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();
- break;
+ svga_device::crtc_map(map);
+ map(0x2d, 0x2d).lr8(
+ NAME([this] (offs_t offset) {
+ return s3.id_high;
+ })
+ );
+ map(0x2e, 0x2e).lr8(
+ NAME([this] (offs_t offset) {
+ return s3.id_low;
+ })
+ );
+ map(0x2f, 0x2f).lr8(
+ NAME([this] (offs_t offset) {
+ return s3.revision;
+ })
+ );
+ // CR30 Chip ID/REV register
+ map(0x30, 0x30).lr8(
+ NAME([this] (offs_t offset) {
+ return s3.id_cr30;
+ })
+ );
+ // CR31 Memory Configuration Register
+ map(0x31, 0x31).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.memory_config;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.memory_config = data;
+ vga.crtc.start_addr_latch &= ~0x30000;
+ vga.crtc.start_addr_latch |= ((data & 0x30) << 12);
+ s3_define_video_mode();
+ })
+ );
+ map(0x35, 0x35).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.crt_reg_lock;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // lock register
+ if((s3.reg_lock1 & 0xc) != 8 || ((s3.reg_lock1 & 0xc0) == 0))
+ return;
+ s3.crt_reg_lock = data;
+ svga.bank_w = data & 0xf;
+ svga.bank_r = svga.bank_w;
+ })
+ );
+ // Configuration register 1
+ map(0x36, 0x36).lrw8(
+ NAME([this] (offs_t offset) {
+ // PCI (not really), Fast Page Mode DRAM
+ return s3.strapping & 0x000000ff;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(s3.reg_lock2 == 0xa5)
+ {
+ s3.strapping = (s3.strapping & 0xffffff00) | data;
+ LOG("CR36: Strapping data = %08x\n",s3.strapping);
+ }
+ })
+ );
+ // Configuration register 2
+ map(0x37, 0x37).lrw8(
+ NAME([this] (offs_t offset) {
+ return (s3.strapping & 0x0000ff00) >> 8; // enable chipset, 64k BIOS size, internal DCLK/MCLK
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(s3.reg_lock2 == 0xa5)
+ {
+ s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8);
+ LOG("CR37: Strapping data = %08x\n",s3.strapping);
+ }
+ })
+ );
+ map(0x38, 0x38).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.reg_lock1;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.reg_lock1 = data;
+ })
+ );
+ map(0x39, 0x39).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.reg_lock2;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // TODO: reg lock mechanism
+ s3.reg_lock2 = data;
+ })
+ );
+ map(0x40, 0x40).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ // enable 8514/A registers (x2e8, x6e8, xae8, xee8)
+ s3.enable_8514 = BIT(data, 0);
+ })
+ );
+ // CR42 Mode Control
+ map(0x42, 0x42).lrw8(
+ NAME([this] (offs_t offset) {
+ // bit 5 set if interlaced, leave it unset for now.
+ return s3.cr42 & 0x0f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented)
+ // TODO: interlace used by modes 116h / 117h at least (1024x768)
+ s3.cr42 = data;
+ })
+ );
+ map(0x43, 0x43).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cr43;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ 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();
+ })
+ );
/*
-3d4h index 45h (R/W): CR45 Hardware Graphics Cursor Mode
+CR45 Hardware Graphics Cursor Mode
bit 0 HWGC ENB. Hardware Graphics Cursor Enable. Set to enable the
HardWare Cursor in VGA and enhanced modes.
1 (911/24) Delay Timing for Pattern Data Fetch
@@ -330,36 +274,66 @@ bit 0 HWGC ENB. Hardware Graphics Cursor Enable. Set to enable the
/ODF) is the ODF output to a Bt485A compatible RamDAC (low for even
fields and high for odd fields), if clear pin185 is the RS3 output.
*/
- case 0x45:
- s3.cursor_mode = data;
- break;
+ map(0x45, 0x45).lrw8(
+ NAME([this] (offs_t offset) {
+ const u8 res = s3.cursor_mode;
+ if (!machine().side_effects_disabled())
+ {
+ s3.cursor_fg_ptr = 0;
+ s3.cursor_bg_ptr = 0;
+ }
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_mode = data;
+ })
+ );
/*
-3d4h index 46h M(R/W): CR46/7 Hardware Graphics Cursor Origin-X
+CR46/7 Hardware Graphics Cursor Origin-X
bit 0-10 The HardWare Cursor X position. For 64k modes this value should be
twice the actual X co-ordinate.
*/
- case 0x46:
- s3.cursor_x = (s3.cursor_x & 0x00ff) | (data << 8);
- break;
- case 0x47:
- s3.cursor_x = (s3.cursor_x & 0xff00) | data;
- break;
+ map(0x46, 0x46).lrw8(
+ NAME([this] (offs_t offset) {
+ return (s3.cursor_x & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_x = (s3.cursor_x & 0x00ff) | (data << 8);
+ })
+ );
+ map(0x47, 0x47).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_x & 0x00ff;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_x = (s3.cursor_x & 0xff00) | data;
+ })
+ );
/*
-3d4h index 48h M(R/W): CR48/9 Hardware Graphics Cursor Origin-Y
+CR48/9 Hardware Graphics Cursor Origin-Y
bit 0-9 (911/24) The HardWare Cursor Y position.
0-10 (80x +) The HardWare Cursor Y position.
Note: The position is activated when the high byte of the Y coordinate (index
48h) is written, so this byte should be written last (not 911/924 ?)
*/
- case 0x48:
- s3.cursor_y = (s3.cursor_y & 0x00ff) | (data << 8);
- break;
- case 0x49:
- s3.cursor_y = (s3.cursor_y & 0xff00) | data;
- break;
-
+ map(0x48, 0x48).lrw8(
+ NAME([this] (offs_t offset) {
+ return (s3.cursor_y & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_y = (s3.cursor_y & 0x00ff) | (data << 8);
+ })
+ );
+ map(0x49, 0x49).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_y & 0x00ff;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_y = (s3.cursor_y & 0xff00) | data;
+ })
+ );
/*
-3d4h index 4Ah (R/W): Hardware Graphics Cursor Foreground Stack (80x +)
+CR4A Hardware Graphics Cursor Foreground Stack (80x +)
bit 0-7 The Foreground Cursor color. Three bytes (4 for the 864/964) are
stacked here. When the Cursor Mode register (3d4h index 45h) is read
the stackpointer is reset. When a byte is written the byte is
@@ -368,12 +342,23 @@ bit 0-7 The Foreground Cursor color. Three bytes (4 for the 864/964) are
other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
index 45h bit 2-3) is enabled.
*/
- case 0x4a:
- s3.cursor_fg[s3.cursor_fg_ptr++] = data;
+ map(0x4a, 0x4a).lrw8(
+ NAME([this] (offs_t offset) {
+ const u8 res = s3.cursor_fg[s3.cursor_fg_ptr];
+ if (!machine().side_effects_disabled())
+ {
+ s3.cursor_fg_ptr++;
s3.cursor_fg_ptr %= 4;
- break;
+ }
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_fg[s3.cursor_fg_ptr++] = data;
+ s3.cursor_fg_ptr %= 4;
+ })
+ );
/*
-3d4h index 4Bh (R/W): Hardware Graphics Cursor Background Stack (80x +)
+CR4B Hardware Graphics Cursor Background Stack (80x +)
bit 0-7 The Background Cursor color. Three bytes (4 for the 864/964) are
stacked here. When the Cursor Mode register (3d4h index 45h) is read
the stackpointer is reset. When a byte is written the byte is
@@ -382,12 +367,23 @@ bit 0-7 The Background Cursor color. Three bytes (4 for the 864/964) are
other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
index 45h bit 2-3) is enabled.
*/
- case 0x4b:
- s3.cursor_bg[s3.cursor_bg_ptr++] = data;
+ map(0x4b, 0x4b).lrw8(
+ NAME([this] (offs_t offset) {
+ const u8 res = s3.cursor_bg[s3.cursor_bg_ptr];
+ if (!machine().side_effects_disabled())
+ {
+ s3.cursor_bg_ptr++;
s3.cursor_bg_ptr %= 4;
- break;
+ }
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_bg[s3.cursor_bg_ptr++] = data;
+ s3.cursor_bg_ptr %= 4;
+ })
+ );
/*
-3d4h index 4Ch M(R/W): CR4C/D Hardware Graphics Cursor Storage Start Address
+CR4C/D Hardware Graphics Cursor Storage Start Address
bit 0-9 (911,924) HCS_STADR. Hardware Graphics Cursor Storage Start Address
0-11 (80x,928) HWGC_STA. Hardware Graphics Cursor Storage Start Address
0-12 (864,964) HWGC_STA. Hardware Graphics Cursor Storage Start Address
@@ -408,44 +404,77 @@ bit 0-9 (911,924) HCS_STADR. Hardware Graphics Cursor Storage Start Address
(801/5,928) For Hi/True color modes use the Horizontal Stretch bits
(3d4h index 45h bits 2 and 3).
*/
- case 0x4c:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0x00ff) | (data << 8);
- popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr);
- break;
- case 0x4d:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data;
- popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr);
- break;
+ map(0x4c, 0x4c).lrw8(
+ NAME([this] (offs_t offset) {
+ return (s3.cursor_start_addr & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_start_addr = (s3.cursor_start_addr & 0x00ff) | (data << 8);
+ //popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr);
+ })
+ );
+ map(0x4d, 0x4d).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_start_addr & 0x00ff;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data;
+ //popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr);
+ })
+ );
/*
-3d4h index 4Eh (R/W): CR4E HGC Pattern Disp Start X-Pixel Position
+CR4E HGC Pattern Disp Start X-Pixel Position
bit 0-5 Pattern Display Start X-Pixel Position.
*/
- case 0x4e:
- s3.cursor_pattern_x = data;
- break;
+ map(0x4e, 0x4e).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_pattern_x;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_pattern_x = data;
+ })
+ );
/*
-3d4h index 4Fh (R/W): CR4F HGC Pattern Disp Start Y-Pixel Position
+CR4F HGC Pattern Disp Start Y-Pixel Position
bit 0-5 Pattern Display Start Y-Pixel Position.
*/
- case 0x4f:
- s3.cursor_pattern_y = data;
- break;
- case 0x51:
- vga.crtc.start_addr_latch &= ~0xc0000;
- vga.crtc.start_addr_latch |= ((data & 0x3) << 18);
- svga.bank_w = (svga.bank_w & 0xcf) | ((data & 0x0c) << 2);
- svga.bank_r = svga.bank_w;
- if((data & 0x30) != 0x00)
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x30) << 4);
- else
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr43 & 0x04) << 6);
- s3_define_video_mode();
- break;
- case 0x53:
- s3.cr53 = data;
- break;
+ map(0x4f, 0x4f).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_pattern_y;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_pattern_y = data;
+ })
+ );
+ map(0x51, 0x51).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
+ res |= ((svga.bank_w & 0x30) >> 2);
+ res |= ((vga.crtc.offset & 0x0300) >> 4);
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 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);
+ svga.bank_r = svga.bank_w;
+ if((data & 0x30) != 0x00)
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x30) << 4);
+ else
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr43 & 0x04) << 6);
+ s3_define_video_mode();
+ })
+ );
+ map(0x53, 0x53).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cr53;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cr53 = data;
+ })
+ );
/*
-3d4h index 55h (R/W): Extended Video DAC Control Register (80x +)
+CR55 Extended Video DAC Control Register (80x +)
bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the
RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs.
If this field is 0, 3d4h index 43h bit 1 is active.
@@ -465,11 +494,28 @@ bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the
(864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri
-stated if set
*/
- case 0x55:
- s3.extended_dac_ctrl = data;
- break;
+ map(0x55, 0x55).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.extended_dac_ctrl;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.extended_dac_ctrl = data;
+ })
+ );
+ map(0x5c, 0x5c).lr8(
+ NAME([this] (offs_t offset) {
+ u8 res = 0;
+ // 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)
+ res = s3.cr42 & 0x0f;
+ else
+ res = (vga.miscellaneous_output & 0xc) >> 2;
+ return res;
+ })
+ );
+// TODO: following two registers must be read-backable
/*
-3d4h index 5Dh (R/W): Extended Horizontal Overflow Register (80x +)
+CR5D Extended Horizontal Overflow Register (80x +)
bit 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h
index 0)
1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End
@@ -489,17 +535,19 @@ bit 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h
7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant
Termination register (3d4h index 5Fh).
*/
- case 0x5d:
- vga.crtc.horz_total = (vga.crtc.horz_total & 0xfeff) | ((data & 0x01) << 8);
- vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0xfeff) | ((data & 0x02) << 7);
- vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xfeff) | ((data & 0x04) << 6);
- vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xffbf) | ((data & 0x08) << 3);
- vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xfeff) | ((data & 0x10) << 4);
- vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0xffdf) | (data & 0x20);
- s3_define_video_mode();
- break;
+ map(0x5d, 0x5d).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.horz_total = (vga.crtc.horz_total & 0xfeff) | ((data & 0x01) << 8);
+ vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0xfeff) | ((data & 0x02) << 7);
+ vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xfeff) | ((data & 0x04) << 6);
+ vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xffbf) | ((data & 0x08) << 3);
+ vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xfeff) | ((data & 0x10) << 4);
+ vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0xffdf) | (data & 0x20);
+ s3_define_video_mode();
+ })
+ );
/*
-3d4h index 5Eh (R/W): Extended Vertical Overflow Register (80x +)
+CR5E: Extended Vertical Overflow Register (80x +)
bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h
index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5.
1 Vertical Display End bit 10. Bit 10 of the Vertical Display End
@@ -515,117 +563,108 @@ bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h
(3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h
index 9 bit 6.
*/
- case 0x5e:
- vga.crtc.vert_total = (vga.crtc.vert_total & 0xfbff) | ((data & 0x01) << 10);
- vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0xfbff) | ((data & 0x02) << 9);
- vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0xfbff) | ((data & 0x04) << 8);
- vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0xfbff) | ((data & 0x10) << 6);
- vga.crtc.line_compare = (vga.crtc.line_compare & 0xfbff) | ((data & 0x40) << 4);
- s3_define_video_mode();
- break;
- case 0x67:
- s3.ext_misc_ctrl_2 = data;
- s3_define_video_mode();
- break;
- case 0x68:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16);
- LOG("CR68: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x69:
- vga.crtc.start_addr_latch &= ~0x1f0000;
- vga.crtc.start_addr_latch |= ((data & 0x1f) << 16);
- s3_define_video_mode();
- break;
- case 0x6a:
- svga.bank_w = data & 0x3f;
- svga.bank_r = svga.bank_w;
- break;
- case 0x6f:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24);
- LOG("CR6F: Strapping data = %08x\n",s3.strapping);
- }
- break;
- default:
- LOG( "S3: 3D4 index %02x write %02x\n",index,data);
- break;
- }
- }
-}
-
-uint8_t s3_vga_device::s3_seq_reg_read(uint8_t index)
-{
- uint8_t res = 0xff;
-
- if(index <= 0x0c)
- res = vga.sequencer.data[index];
- else
- {
- switch(index)
- {
- case 0x10:
- res = s3.sr10;
- break;
- case 0x11:
- res = s3.sr11;
- break;
- case 0x12:
- res = s3.sr12;
- break;
- case 0x13:
- res = s3.sr13;
- break;
- case 0x15:
- res = s3.sr15;
- break;
- case 0x17:
- res = s3.sr17; // CLKSYN test register
- s3.sr17--; // who knows what it should return, docs only say it defaults to 0, and is reserved for testing of the clock synthesiser
- break;
- }
- }
-
- return res;
+ map(0x5e, 0x5e).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.vert_total = (vga.crtc.vert_total & 0xfbff) | ((data & 0x01) << 10);
+ vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0xfbff) | ((data & 0x02) << 9);
+ vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0xfbff) | ((data & 0x04) << 8);
+ vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0xfbff) | ((data & 0x10) << 6);
+ vga.crtc.line_compare = (vga.crtc.line_compare & 0xfbff) | ((data & 0x40) << 4);
+ s3_define_video_mode();
+ })
+ );
+ map(0x67, 0x67).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.ext_misc_ctrl_2;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.ext_misc_ctrl_2 = data;
+ s3_define_video_mode();
+ })
+ );
+ map(0x68, 0x68).lrw8(
+ NAME([this] (offs_t offset) { // Configuration register 3
+ // no /CAS,/OE stretch time, 32-bit data bus size
+ return (s3.strapping & 0x00ff0000) >> 16;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(s3.reg_lock2 == 0xa5)
+ {
+ s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16);
+ LOG("CR68: Strapping data = %08x\n",s3.strapping);
+ }
+ })
+ );
+ map(0x69, 0x69).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.crtc.start_addr_latch >> 16;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.start_addr_latch &= ~0x1f0000;
+ vga.crtc.start_addr_latch |= ((data & 0x1f) << 16);
+ s3_define_video_mode();
+ })
+ );
+ // TODO: doesn't match number of bits
+ map(0x6a, 0x6a).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.bank_r & 0x7f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ svga.bank_w = data & 0x3f;
+ svga.bank_r = svga.bank_w;
+ })
+ );
+ // Configuration register 4 (Trio64V+)
+ map(0x6f, 0x6f).lrw8(
+ NAME([this] (offs_t offset) {
+ // LPB(?) mode, Serial port I/O at port 0xe8, Serial port I/O disabled (MMIO only), no WE delay
+ return (s3.strapping & 0xff000000) >> 24;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(s3.reg_lock2 == 0xa5)
+ {
+ s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24);
+ LOG("CR6F: Strapping data = %08x\n",s3.strapping);
+ }
+ })
+ );
}
-void s3_vga_device::s3_seq_reg_write(uint8_t index, uint8_t data)
+void s3_vga_device::sequencer_map(address_map &map)
{
- if(index <= 0x0c)
- {
- vga.sequencer.data[vga.sequencer.index] = data;
- seq_reg_write(vga.sequencer.index,data);
- }
- else
- {
- switch(index)
- {
- // Memory CLK PLL
- case 0x10:
- s3.sr10 = data;
- break;
- case 0x11:
- s3.sr11 = data;
- break;
- // Video CLK PLL
- case 0x12:
- s3.sr12 = data;
- break;
- case 0x13:
- s3.sr13 = data;
- break;
- case 0x15:
- if(data & 0x02) // load DCLK frequency (would normally have a small variable delay)
+ svga_device::sequencer_map(map);
+ // Memory CLK PLL
+ map(0x10, 0x10).lrw8(
+ NAME([this] (offs_t offset) { return s3.sr10; }),
+ NAME([this] (offs_t offset, u8 data) { s3.sr10 = data; })
+ );
+ map(0x11, 0x11).lrw8(
+ NAME([this] (offs_t offset) { return s3.sr11; }),
+ NAME([this] (offs_t offset, u8 data) { s3.sr11 = data; })
+ );
+ // Video CLK PLL
+ map(0x12, 0x12).lrw8(
+ NAME([this] (offs_t offset) { return s3.sr12; }),
+ NAME([this] (offs_t offset, u8 data) { s3.sr12 = data; })
+ );
+ map(0x13, 0x13).lrw8(
+ NAME([this] (offs_t offset) { return s3.sr13; }),
+ NAME([this] (offs_t offset, u8 data) { s3.sr13 = data; })
+ );
+ map(0x15, 0x15).lrw8(
+ NAME([this] (offs_t offset) { return s3.sr15; }),
+ NAME([this] (offs_t offset, u8 data) {
+ // load DCLK frequency (would normally have a small variable delay)
+ if(data & 0x02)
{
s3.clk_pll_n = s3.sr12 & 0x1f;
s3.clk_pll_r = (s3.sr12 & 0x60) >> 5;
s3.clk_pll_m = s3.sr13 & 0x7f;
s3_define_video_mode();
}
- if(data & 0x20) // immediate DCLK/MCLK load
+ // immediate DCLK/MCLK load
+ if(data & 0x20)
{
s3.clk_pll_n = s3.sr12 & 0x1f;
s3.clk_pll_r = (s3.sr12 & 0x60) >> 5;
@@ -633,114 +672,18 @@ void s3_vga_device::s3_seq_reg_write(uint8_t index, uint8_t data)
s3_define_video_mode();
}
s3.sr15 = data;
- }
- }
-}
-
-
-
-uint8_t s3_vga_device::port_03b0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- res = s3_vga_device::crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3_vga_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- s3_vga_device::crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03b0_w(offset,data);
- break;
- }
- }
-}
-
-uint8_t s3_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t res;
-
- switch(offset)
- {
- case 5:
- res = s3_seq_reg_read(vga.sequencer.index);
- break;
- default:
- res = vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void s3_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 5:
- s3_seq_reg_write(vga.sequencer.index,data);
- break;
- default:
- vga_device::port_03c0_w(offset,data);
- break;
- }
-}
-
-uint8_t s3_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = s3_vga_device::crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
+ })
+ ),
+ map(0x17, 0x17).lr8(
+ NAME([this] (offs_t offset) {
+ // CLKSYN test register
+ const u8 res = s3.sr17;
+ // who knows what it should return, docs only say it defaults to 0, and is reserved for testing of the clock synthesiser
+ if (!machine().side_effects_disabled())
+ s3.sr17--;
+ return res;
+ })
+ );
}
uint8_t s3_vga_device::mem_r(offs_t offset)
diff --git a/src/devices/video/pc_vga_s3.h b/src/devices/video/pc_vga_s3.h
index a7de03db80c..700077fef05 100644
--- a/src/devices/video/pc_vga_s3.h
+++ b/src/devices/video/pc_vga_s3.h
@@ -17,12 +17,6 @@ public:
// construction/destruction
s3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
@@ -40,6 +34,10 @@ protected:
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
+ virtual void crtc_map(address_map &map) override;
+ virtual void sequencer_map(address_map &map) override;
+
+ // TODO: remove this leaky abstraction
struct
{
uint8_t memory_config;
@@ -89,15 +87,9 @@ protected:
} s3;
virtual uint16_t offset() override;
-protected:
- uint8_t crtc_reg_read(uint8_t index) override;
- void crtc_reg_write(uint8_t index, uint8_t data) override;
+ virtual void s3_define_video_mode(void);
private:
-
- void s3_define_video_mode(void);
- uint8_t s3_seq_reg_read(uint8_t index);
- void s3_seq_reg_write(uint8_t index, uint8_t data);
ibm8514a_device* m_8514;
};
diff --git a/src/devices/video/pc_vga_sis.cpp b/src/devices/video/pc_vga_sis.cpp
new file mode 100644
index 00000000000..50ec30ad110
--- /dev/null
+++ b/src/devices/video/pc_vga_sis.cpp
@@ -0,0 +1,301 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+Implementation of SiS family (S)VGA chipset
+
+TODO:
+- interlace (cfr. xubuntu 6.10 splash screen on 1024x768x32);
+- backport to earlier variants;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc_vga_sis.h"
+
+#include "screen.h"
+
+#define VERBOSE (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+// 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 SVGA")
+
+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)
+{
+ 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));
+}
+
+void sis630_svga_device::device_start()
+{
+ svga_device::device_start();
+ zero();
+
+ // Avoid an infinite loop when displaying. 0 is not possible anyway.
+ 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);
+}
+
+void sis630_svga_device::device_reset()
+{
+ svga_device::device_reset();
+
+ m_unlock_reg = false;
+ //m_dual_seg_mode = false;
+}
+
+void sis630_svga_device::io_3cx_map(address_map &map)
+{
+ svga_device::io_3cx_map(map);
+ // TODO: for '630 it's always with dual segment enabled?
+ // May be like trident_vga where there's a specific register
+
+ // read by gamecstl Kontron BIOS
+ map(0x0b, 0x0b).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.bank_r;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ svga.bank_r = data;
+ })
+ );
+ map(0x0d, 0x0d).lrw8(
+ NAME([this] (offs_t offset) {
+ return svga.bank_w;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ svga.bank_w = data & 0x3f;
+ })
+ );
+}
+
+// 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, undocumented stuff
+ 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
+ vga.crtc.data[offset] = data;
+ })
+ );
+ // make sure '301 CRT2 is not enabled for now
+ 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)
+{
+ svga_device::sequencer_map(map);
+ // extended ID register
+ map(0x05, 0x05).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_unlock_reg ? 0xa1 : 0x21;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // TODO: reimplement me thru memory_view or direct handler override
+ m_unlock_reg = (data == 0x86);
+ LOG("Unlock register write %02x (%s)\n", data, m_unlock_reg ? "unlocked" : "locked");
+ })
+ );
+ /*
+ * x--- ---- GFX mode linear addressing enable
+ * -x-- ---- GFX hardware cursor display
+ * --x- ---- GFX mode interlace
+ * ---x ---- True Color enable (ties with index 0x07 bit 2)
+ * ---- x--- RGB16 enable
+ * ---- -x-- RGB15 enable
+ * ---- --x- enhanced GFX mode enable
+ * ---- ---x enhanced text mode enable
+ */
+ map(0x06, 0x06).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_ramdac_mode;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_ramdac_mode = data;
+ LOG("RAMDAC mode %02x\n", data);
+
+ if (!BIT(data, 1))
+ {
+ svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = svga.rgb32_en = 0;
+ }
+ else
+ {
+ if (BIT(data, 2))
+ svga.rgb15_en = 1;
+ if (BIT(data, 3))
+ svga.rgb16_en = 1;
+ std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
+ }
+ })
+ );
+ map(0x07, 0x07).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_ext_misc_ctrl_0;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("Extended Misc. Control register 0 SR07 %02x\n", data);
+ m_ext_misc_ctrl_0 = data;
+ std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
+ })
+ );
+ map(0x0a, 0x0a).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_ext_vert_overflow;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("Extended vertical Overflow register SR0A %02x\n", data);
+ m_ext_vert_overflow = data;
+ vga.crtc.vert_retrace_end = (vga.crtc.vert_retrace_end & 0xf) | ((data & 0x20) >> 1);
+ vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & 0x00ff) | ((data & 0x10) << 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).lr8(
+ NAME([this] (offs_t offset) {
+ return m_ext_horz_overflow[offset];
+ })
+ );
+ map(0x0b, 0x0b).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ //m_dual_seg_mode = bool(BIT(data, 3));
+ LOG("Extended horizontal Overflow 1 SR0B %02x\n", data);
+ m_ext_horz_overflow[0] = data;
+
+ vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0x00ff) | ((data & 0xc0) << 2);
+ vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0x00ff) | ((data & 0x30) << 4);
+ vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0x00ff) | ((data & 0x0c) << 6);
+ vga.crtc.horz_total = (vga.crtc.horz_total & 0x00ff) | ((data & 0x03) << 8);
+
+ recompute_params();
+ })
+ );
+ map(0x0c, 0x0c).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("Extended horizontal Overflow 2 SR0C %02x\n", data);
+ m_ext_horz_overflow[1] = data;
+
+ vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0x001f) | ((data & 0x04) << 3);
+ vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0x003f) | ((data & 0x03) << 6);
+ recompute_params();
+ })
+ );
+ map(0x0d, 0x0d).lrw8(
+ NAME([this] (offs_t offset) {
+ return vga.crtc.start_addr_latch >> 16;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("Extended starting address register SR0D %02x\n", data);
+ vga.crtc.start_addr_latch &= ~0xff0000;
+ vga.crtc.start_addr_latch |= data << 16;
+ })
+ );
+ map(0x0e, 0x0e).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("Extended pitch register SR0E %02x\n", data);
+ // sis_main.c implicitly sets this with bits 0-3 granularity, assume being right
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x0f) << 8);
+ })
+ );
+ map(0x14, 0x14).lrw8(
+ NAME([this] (offs_t offset) {
+ // sis_main.c calculates VRAM size in two ways:
+ // 1. the legacy way ('300), by probing this register
+ // 2. by reading '630 PCI host register $63 (as shared DRAM?)
+ // Method 1 seems enough to enforce "64MB" message at POST,
+ // 2 is probably more correct but unsure about how to change the shared area in BIOS
+ // (shutms11 will always write a "0x41" on fresh CMOS then a "0x47"
+ // on successive boots no matter what)
+ return (m_bus_width) | ((vga.svga_intf.vram_size / (1024 * 1024) - 1) & 0x3f);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_bus_width = data & 0xc0;
+ })
+ );
+ map(0x1e, 0x1e).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ if (BIT(data, 6))
+ popmessage("Warning: enable 2d engine");
+ })
+ );
+ map(0x20, 0x20).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ if (data & 0x81)
+ popmessage("Warning: %s %s", BIT(data, 7) ? "PCI address enabled" : "", BIT(data, 0) ? "memory map I/O 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()
+{
+ // TODO: ext clock
+ recompute_params_clock(1, XTAL(25'174'800).value());
+}
+
+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);
+}
diff --git a/src/devices/video/pc_vga_sis.h b/src/devices/video/pc_vga_sis.h
new file mode 100644
index 00000000000..4d410b20dfa
--- /dev/null
+++ b/src/devices/video/pc_vga_sis.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_VIDEO_SIS_H
+#define MAME_VIDEO_SIS_H
+
+#pragma once
+
+#include "video/pc_vga.h"
+
+class sis630_svga_device : public svga_device
+{
+public:
+ sis630_svga_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:
+ 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_vert_overflow = 0;
+ u8 m_ext_horz_overflow[2]{};
+ u8 m_bus_width = 0;
+ bool m_unlock_reg = false;
+
+ std::tuple<u8, u8> flush_true_color_mode();
+// bool m_dual_seg_mode = false;
+};
+
+DECLARE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device)
+
+#endif // MAME_VIDEO_SIS_H
diff --git a/src/devices/video/pc_vga_trident.cpp b/src/devices/video/pc_vga_trident.cpp
index 53d34ea571d..9ef9e55bc19 100644
--- a/src/devices/video/pc_vga_trident.cpp
+++ b/src/devices/video/pc_vga_trident.cpp
@@ -10,7 +10,7 @@
* - TVGA8800 early SVGA
* - TVGA8900 (2MB VRAM)
* - TVGA9000 needs to be downgraded from '9680
- * \- none of the SVGA modes works
+ * \- none of the SVGA modes works properly;
* \- subclassed from TGUI9680 just for pntnpuzl, consider swapping inheritance or even decouple;
* \- it's also really a downgraded version of '8900
* - TVGA92xx, TVGA938x (2d accelerator)
@@ -47,6 +47,10 @@ DEFINE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device, "tvga9000_vga", "Trident TVGA9
trident_vga_device::trident_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)
{
+ m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(trident_vga_device::io_3bx_3dx_map), this));
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(trident_vga_device::crtc_map), this));
+ m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(trident_vga_device::gc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(trident_vga_device::sequencer_map), this));
}
tgui9860_device::tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -61,6 +65,543 @@ tvga9000_device::tvga9000_device(const machine_config &mconfig, const char *tag,
m_version = 0x43;
}
+void trident_vga_device::io_3cx_map(address_map &map)
+{
+ svga_device::io_3cx_map(map);
+ map(0x06, 0x06).rw(FUNC(trident_vga_device::ramdac_hidden_mask_r), FUNC(trident_vga_device::ramdac_hidden_mask_w));
+ map(0x07, 0x09).rw(FUNC(trident_vga_device::ramdac_overlay_r), FUNC(trident_vga_device::ramdac_overlay_w));
+}
+
+u8 trident_vga_device::ramdac_hidden_mask_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ tri.dac_count++;
+ if(tri.dac_count > 3)
+ tri.dac_active = true;
+ if(tri.dac_active)
+ return tri.dac;
+
+ return vga_device::ramdac_mask_r(offset);
+}
+
+void trident_vga_device::ramdac_hidden_mask_w(offs_t offset, u8 data)
+{
+ if(tri.dac_active)
+ {
+ tri.dac = data; // DAC command register
+ tri.dac_active = false;
+ tri.dac_count = 0;
+ recompute_params();
+ return;
+ }
+
+ vga_device::ramdac_mask_w(offset, data);
+}
+
+u8 trident_vga_device::ramdac_overlay_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ tri.dac_active = false;
+ tri.dac_count = 0;
+ }
+
+ switch(offset)
+ {
+ case 0:
+ return vga_device::ramdac_state_r(0);
+ case 1:
+ return vga_device::ramdac_write_index_r(0);
+ case 2:
+ return vga_device::ramdac_data_r(0);
+ }
+
+ return space().unmap();
+}
+
+void trident_vga_device::ramdac_overlay_w(offs_t offset, u8 data)
+{
+ tri.dac_active = false;
+ tri.dac_count = 0;
+
+ switch(offset)
+ {
+ case 0:
+ vga_device::ramdac_read_index_w(0, data);
+ break;
+ case 1:
+ vga_device::ramdac_write_index_w(0, data);
+ break;
+ case 2:
+ vga_device::ramdac_data_w(0, data);
+ break;
+ }
+}
+
+void trident_vga_device::io_3bx_3dx_map(address_map &map)
+{
+ svga_device::io_3bx_3dx_map(map);
+ map(0x08, 0x08).rw(FUNC(trident_vga_device::svga_bank_write_r), FUNC(trident_vga_device::svga_bank_write_w));
+ map(0x09, 0x09).rw(FUNC(trident_vga_device::svga_bank_read_r), FUNC(trident_vga_device::svga_bank_read_w));
+ // no info on this port
+ // Bit 5 appears to be a clock divider
+ map(0x0b, 0x0b).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.port_3db;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.port_3db = data;
+ recompute_params();
+ })
+ );
+}
+
+u8 trident_vga_device::svga_bank_write_r(offs_t offset)
+{
+ // if enabled
+ if(tri.gc0f & 0x04)
+ return svga.bank_w & 0x3f;
+
+ return space().unmap();
+}
+
+void trident_vga_device::svga_bank_write_w(offs_t offset, u8 data)
+{
+ // if enabled
+ if(tri.gc0f & 0x04)
+ {
+ svga.bank_w = data & 0x3f;
+ LOG("Trident: Write Bank set to %02x\n",data);
+ // if bank regs are not separated ...
+ if(!(tri.gc0f & 0x01))
+ {
+ // ... then this is also the read bank register
+ svga.bank_r = data & 0x3f;
+ LOG("Trident: Read Bank set to %02x\n",data);
+ }
+ }
+}
+
+u8 trident_vga_device::svga_bank_read_r(offs_t offset)
+{
+ // if enabled & if bank regs are separated
+ if(tri.gc0f & 0x04)
+ return svga.bank_r & 0x3f;
+
+ return space().unmap();
+}
+
+void trident_vga_device::svga_bank_read_w(offs_t offset, u8 data)
+{
+ // if enabled & if bank regs are separated
+ if(tri.gc0f & 0x04 && tri.gc0f & 0x01)
+ {
+ svga.bank_r = data & 0x3f;
+ LOG("Trident: Read Bank set to %02x\n",data);
+ }
+}
+
+void trident_vga_device::crtc_map(address_map &map)
+{
+ svga_device::crtc_map(map);
+ // Module Testing Register
+ map(0x1e, 0x1e).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr1e;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr1e = data;
+ vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x20)<<11);
+ recompute_params();
+ })
+ );
+ // "Software Programming Register" written to by the BIOS
+ map(0x1f, 0x1f).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr1f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr1f = data;
+ })
+ );
+ // FIFO Control (old MMIO enable? no documentation of this register)
+ map(0x20, 0x20).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr20;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr20 = data;
+ })
+ );
+ // Linear aperture
+ map(0x21, 0x21).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr21;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr21 = data;
+ tri.linear_address = ((data & 0xc0)<<18) | ((data & 0x0f)<<20);
+ tri.linear_active = data & 0x20;
+ if(tri.linear_active)
+ popmessage("Trident: Linear Aperture active - %08x, %s",tri.linear_address,(tri.cr21 & 0x10) ? "2MB" : "1MB" );
+ })
+ );
+ map(0x27, 0x27).lrw8(
+ NAME([this] (offs_t offset) {
+ return (vga.crtc.start_addr & 0x60000) >> 17;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ vga.crtc.start_addr = (vga.crtc.start_addr & 0xfff9ffff) | ((data & 0x03)<<17);
+ })
+ );
+ map(0x29, 0x29).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr29;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr29 = data;
+ vga.crtc.offset = (vga.crtc.offset & 0xfeff) | ((data & 0x10)<<4);
+ })
+ );
+ map(0x2a, 0x2a).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr2a;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr2a = data;
+ })
+ );
+ map(0x38, 0x38).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.pixel_depth;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // bit 0: 16 bit bus
+ // bits 2-3: pixel depth (1=15/16bit, 2=24/32bit, 0=anything else)
+ // bit 5: packed mode
+ tri.pixel_depth = data;
+ recompute_params();
+ })
+ );
+ map(0x39, 0x39).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cr39;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cr39 = data;
+ tri.mmio_active = data & 0x01;
+ if(tri.mmio_active)
+ popmessage("Trident: MMIO activated");
+ })
+ );
+ map(0x40, 0x40).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_x & 0x00ff);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_x = (tri.cursor_x & 0xff00) | data;
+ })
+ );
+ map(0x41, 0x41).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_x & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_x = (tri.cursor_x & 0x00ff) | (data << 8);
+ })
+ );
+ map(0x42, 0x42).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_y & 0x00ff);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_y = (tri.cursor_y & 0xff00) | data;
+ })
+ );
+ map(0x43, 0x43).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_y & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_y = (tri.cursor_y & 0x00ff) | (data << 8);
+ })
+ );
+ map(0x44, 0x44).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_loc & 0x00ff);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_loc = (tri.cursor_loc & 0xff00) | data;
+ })
+ );
+ map(0x45, 0x45).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_loc & 0xff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_loc = (tri.cursor_loc & 0x00ff) | (data << 8);
+ })
+ );
+ map(0x46, 0x46).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cursor_x_off;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_x_off = data;
+ })
+ );
+ map(0x47, 0x47).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cursor_y_off;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_y_off = data;
+ })
+ );
+ map(0x48, 0x48).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_fg & 0x000000ff);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_fg = (tri.cursor_fg & 0xffffff00) | data;
+ })
+ );
+ map(0x49, 0x49).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_fg & 0x0000ff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_fg = (tri.cursor_fg & 0xffff00ff) | (data << 8);
+ })
+ );
+ map(0x4a, 0x4a).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_fg & 0x00ff0000) >> 16;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_fg = (tri.cursor_fg & 0xff00ffff) | (data << 16);
+ })
+ );
+ map(0x4b, 0x4b).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_fg & 0xff000000) >> 24;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_fg = (tri.cursor_fg & 0x00ffffff) | (data << 24);
+ })
+ );
+ map(0x4c, 0x4c).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_bg & 0x000000ff);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_bg = (tri.cursor_bg & 0xffffff00) | data;
+ })
+ );
+ map(0x4d, 0x4d).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_bg & 0x0000ff00) >> 8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_bg = (tri.cursor_bg & 0xffff00ff) | (data << 8);
+ })
+ );
+ map(0x4e, 0x4e).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_bg & 0x00ff0000) >> 16;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_bg = (tri.cursor_bg & 0xff00ffff) | (data << 16);
+ })
+ );
+ map(0x4f, 0x4f).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.cursor_bg & 0xff000000) >> 24;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_bg = (tri.cursor_bg & 0x00ffffff) | (data << 24);
+ })
+ );
+ map(0x50, 0x50).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.cursor_ctrl;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.cursor_ctrl = data;
+ })
+ );
+}
+
+void trident_vga_device::gc_map(address_map &map)
+{
+ svga_device::gc_map(map);
+ // New Source Address Register (bit 1 is inverted here, also)
+ map(0x0e, 0x0e).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.gc0e;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.gc0e = data ^ 0x02;
+ if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled
+ {
+ if(tri.gc0f & 0x01) // if bank regs are separated
+ svga.bank_r = (data & 0x1f) ^ 0x02;
+ }
+ })
+ );
+ map(0x0f, 0x0f).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.gc0f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.gc0f = data;
+ recompute_params();
+ })
+ );
+ // XFree86 refers to this register as "MiscIntContReg", setting bit 2, but gives no indication as to what it does
+ map(0x2f, 0x2f).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.gc2f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.gc2f = data;
+ })
+ );
+}
+
+void trident_vga_device::sequencer_map(address_map &map)
+{
+ svga_device::sequencer_map(map);
+ map(0x09, 0x09).lr8(
+ NAME([this] (offs_t offset) {
+ return tri.revision;
+ })
+ );
+ map(0x0b, 0x0b).lrw8(
+ NAME([this] (offs_t offset) {
+ if (!machine().side_effects_disabled())
+ tri.new_mode = true;
+ return svga.id;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.new_mode = false;
+ })
+ );
+ // Power Up Mode register 1
+ map(0x0c, 0x0c).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = tri.sr0c & 0xef;
+ if(tri.port_3c3)
+ res |= 0x10;
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ // ---1 ---- 'post port at 0x3c3'
+ // ---0 ---- 'post port at 0x46e8'
+ tri.port_3c3 = bool(BIT(data, 4));
+ tri.sr0c = data;
+ })
+ );
+ // Mode Control 2
+ map(0x0d, 0x0d).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.new_mode) ? tri.sr0d_new : tri.sr0d_old;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(tri.new_mode)
+ {
+ tri.sr0d_new = data;
+ tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3);
+ recompute_params();
+ }
+ else
+ tri.sr0d_old = data;
+ })
+ );
+ // Mode Control 1
+ map(0x0e, 0x0e).lrw8(
+ NAME([this] (offs_t offset) {
+ return (tri.new_mode) ? tri.sr0e_new : tri.sr0e_old;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ if(tri.new_mode)
+ {
+ tri.sr0e_new = data ^ 0x02;
+ svga.bank_w = (data & 0x3f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading
+ if(!(tri.gc0f & 0x01))
+ svga.bank_r = (data & 0x3f) ^ 0x02;
+ // TODO: handle planar modes, where bits 0 and 2 only are used
+ }
+ else
+ {
+ tri.sr0e_old = data;
+ svga.bank_w = data & 0x0e;
+ if(!(tri.gc0f & 0x01))
+ svga.bank_r = data & 0x0e;
+ }
+ })
+ );
+ // Power Up Mode 2
+ map(0x0f, 0x0f).lrw8(
+ NAME([this] (offs_t offset) {
+ return tri.sr0f;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ tri.sr0f = data;
+ })
+ );
+}
+
+void trident_vga_device::device_start()
+{
+ zero();
+
+ for (int i = 0; i < 0x100; i++)
+ set_pen_color(i, 0, 0, 0);
+
+ // Avoid an infinite loop when displaying. 0 is not possible anyway.
+ vga.crtc.maximum_scan_line = 1;
+
+
+ // copy over interfaces
+ vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
+ memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
+
+ save_pointer(NAME(vga.memory), vga.svga_intf.vram_size);
+ save_pointer(vga.crtc.data,"CRTC Registers",0x100);
+ save_pointer(vga.sequencer.data,"Sequencer Registers",0x100);
+ save_pointer(vga.attribute.data,"Attribute Registers", 0x15);
+ save_pointer(tri.accel_pattern,"Pattern Data", 0x80);
+ save_pointer(tri.lutdac_reg,"LUTDAC registers", 0x100);
+
+ m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
+ svga.ignore_chain4 = true;
+ memset(&tri, 0, sizeof(tri));
+}
+
+void trident_vga_device::device_reset()
+{
+ svga_device::device_reset();
+ svga.id = m_version;
+ tri.revision = 0x01; // revision identifies as TGUI9680
+ tri.new_mode = false; // start up in old mode
+ tri.dac_active = false;
+ tri.linear_active = false;
+ tri.mmio_active = false;
+ tri.sr0f = 0x6f;
+ tri.sr0c = 0x70;
+ tri.cr2a = 0x03; // set ISA interface?
+ tri.mem_clock = 0x2c6; // 50MHz default
+ tri.vid_clock = 0;
+ tri.port_3c3 = true;
+ tri.accel_busy = false;
+ tri.accel_memwrite_active = false;
+ // Windows 3.1 TGUI9440AGi drivers do not set the pointer colour registers?
+ tri.cursor_bg = 0x00000000;
+ tri.cursor_fg = 0xffffffff;
+ tri.pixel_depth = 0x10; //disable 8bpp mode by default
+}
+
uint8_t trident_vga_device::READPIXEL8(int16_t x, int16_t y)
{
return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)) % vga.svga_intf.vram_size]);
@@ -176,59 +717,6 @@ void trident_vga_device::WRITEPIXEL(int16_t x,int16_t y, uint32_t data)
WRITEPIXEL32(x,y,data);
}
-
-void trident_vga_device::device_start()
-{
- zero();
-
- for (int i = 0; i < 0x100; i++)
- set_pen_color(i, 0, 0, 0);
-
- // Avoid an infinite loop when displaying. 0 is not possible anyway.
- vga.crtc.maximum_scan_line = 1;
-
-
- // copy over interfaces
- vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
- memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
-
- save_pointer(NAME(vga.memory), vga.svga_intf.vram_size);
- save_pointer(vga.crtc.data,"CRTC Registers",0x100);
- save_pointer(vga.sequencer.data,"Sequencer Registers",0x100);
- save_pointer(vga.attribute.data,"Attribute Registers", 0x15);
- save_pointer(tri.accel_pattern,"Pattern Data", 0x80);
- save_pointer(tri.lutdac_reg,"LUTDAC registers", 0x100);
-
- m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
- vga.svga_intf.seq_regcount = 0x0f;
- vga.svga_intf.crtc_regcount = 0x60;
- svga.ignore_chain4 = true;
- memset(&tri, 0, sizeof(tri));
-}
-
-void trident_vga_device::device_reset()
-{
- svga_device::device_reset();
- svga.id = m_version;
- tri.revision = 0x01; // revision identifies as TGUI9680
- tri.new_mode = false; // start up in old mode
- tri.dac_active = false;
- tri.linear_active = false;
- tri.mmio_active = false;
- tri.sr0f = 0x6f;
- tri.sr0c = 0x70;
- tri.cr2a = 0x03; // set ISA interface?
- tri.mem_clock = 0x2c6; // 50MHz default
- tri.vid_clock = 0;
- tri.port_3c3 = true;
- tri.accel_busy = false;
- tri.accel_memwrite_active = false;
- // Windows 3.1 TGUI9440AGi drivers do not set the pointer colour registers?
- tri.cursor_bg = 0x00000000;
- tri.cursor_fg = 0xffffffff;
- tri.pixel_depth = 0x10; //disable 8bpp mode by default
-}
-
uint32_t trident_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
svga_device::screen_update(screen,bitmap,cliprect);
@@ -349,7 +837,7 @@ int trident_vga_device::calculate_clock()
return freq * 1000000;
}
-void trident_vga_device::trident_define_video_mode()
+void trident_vga_device::recompute_params()
{
int divisor = 1;
int xtal;
@@ -416,543 +904,6 @@ void trident_vga_device::trident_define_video_mode()
recompute_params_clock(divisor, xtal);
}
-uint8_t trident_vga_device::trident_seq_reg_read(uint8_t index)
-{
- uint8_t res;
-
- res = 0xff;
-
- if(index <= 0x04)
- res = vga.sequencer.data[index];
- else
- {
- switch(index)
- {
- case 0x09:
- res = tri.revision;
- break;
- case 0x0b:
- res = svga.id;
- tri.new_mode = true;
- break;
- case 0x0c: // Power Up Mode register 1
- res = tri.sr0c & 0xef;
- if(tri.port_3c3)
- res |= 0x10;
- break;
- case 0x0d: // Mode Control 2
- //res = svga.rgb15_en;
- if(tri.new_mode)
- res = tri.sr0d_new;
- else
- res = tri.sr0d_old;
- break;
- case 0x0e: // Mode Control 1
- if(tri.new_mode)
- res = tri.sr0e_new;
- else
- res = tri.sr0e_old;
- break;
- case 0x0f: // Power Up Mode 2
- res = tri.sr0f;
- break;
- default:
- res = vga.sequencer.data[index];
- LOGWARN("Trident: Sequencer index %02x read\n",index);
- }
- }
- LOG("Trident SR%02X: read %02x\n",index,res);
- return res;
-}
-
-void trident_vga_device::trident_seq_reg_write(uint8_t index, uint8_t data)
-{
- vga.sequencer.data[vga.sequencer.index] = data;
- if(index <= 0x04)
- {
- seq_reg_write(vga.sequencer.index,data);
- recompute_params();
- }
- else
- {
- switch(index)
- {
- case 0x0b:
- tri.new_mode = false;
- break;
- case 0x0c: // Power Up Mode register 1
- if(data & 0x10)
- tri.port_3c3 = true; // 'post port at 0x3c3'
- else
- tri.port_3c3 = false; // 'post port at 0x46e8'
- tri.sr0c = data;
- break;
- case 0x0d: // Mode Control 2
- if(tri.new_mode)
- {
- tri.sr0d_new = data;
- tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3);
- trident_define_video_mode();
- }
- else
- tri.sr0d_old = data;
- break;
- case 0x0e: // Mode Control 1
- if(tri.new_mode)
- {
- tri.sr0e_new = data ^ 0x02;
- svga.bank_w = (data & 0x3f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading
- if(!(tri.gc0f & 0x01))
- svga.bank_r = (data & 0x3f) ^ 0x02;
- // TODO: handle planar modes, where bits 0 and 2 only are used
- }
- else
- {
- tri.sr0e_old = data;
- svga.bank_w = data & 0x0e;
- if(!(tri.gc0f & 0x01))
- svga.bank_r = data & 0x0e;
- }
- break;
- case 0x0f: // Power Up Mode 2
- tri.sr0f = data;
- break;
- default:
- LOGWARN("Trident: Sequencer index %02x read\n",index);
- }
- }
- LOG("Trident SR%02X: %s mode write %02x\n",index,tri.new_mode ? "new" : "old",data);
-}
-
-uint8_t trident_vga_device::trident_crtc_reg_read(uint8_t index)
-{
- uint8_t res = 0;
-
- if(index <= 0x18)
- res = crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x1e:
- res = tri.cr1e;
- break;
- case 0x1f:
- res = tri.cr1f;
- break;
- case 0x20:
- res = tri.cr20;
- break;
- case 0x21:
- res = tri.cr21;
- break;
- case 0x24:
- if(vga.attribute.state != 0)
- res |= 0x80;
- break;
- case 0x26:
- res = vga.attribute.index;
- break;
- case 0x27:
- res = (vga.crtc.start_addr & 0x60000) >> 17;
- break;
- case 0x29:
- res = tri.cr29;
- break;
- case 0x2a:
- res = tri.cr2a;
- break;
- case 0x38:
- res = tri.pixel_depth;
- break;
- case 0x39:
- res = tri.cr39;
- break;
- case 0x40:
- res = (tri.cursor_x & 0x00ff);
- break;
- case 0x41:
- res = (tri.cursor_x & 0xff00) >> 8;
- break;
- case 0x42:
- res = (tri.cursor_y & 0x00ff);
- break;
- case 0x43:
- res = (tri.cursor_y & 0xff00) >> 8;
- break;
- case 0x44:
- res = (tri.cursor_loc & 0x00ff);
- break;
- case 0x45:
- res = (tri.cursor_loc & 0xff00) >> 8;
- break;
- case 0x46:
- res = tri.cursor_x_off;
- break;
- case 0x47:
- res = tri.cursor_y_off;
- break;
- case 0x48:
- res = (tri.cursor_fg & 0x000000ff);
- break;
- case 0x49:
- res = (tri.cursor_fg & 0x0000ff00) >> 8;
- break;
- case 0x4a:
- res = (tri.cursor_fg & 0x00ff0000) >> 16;
- break;
- case 0x4b:
- res = (tri.cursor_fg & 0xff000000) >> 24;
- break;
- case 0x4c:
- res = (tri.cursor_bg & 0x000000ff);
- break;
- case 0x4d:
- res = (tri.cursor_bg & 0x0000ff00) >> 8;
- break;
- case 0x4e:
- res = (tri.cursor_bg & 0x00ff0000) >> 16;
- break;
- case 0x4f:
- res = (tri.cursor_bg & 0xff000000) >> 24;
- break;
- case 0x50:
- res = tri.cursor_ctrl;
- break;
- default:
- res = vga.crtc.data[index];
- LOGWARN("Trident: CRTC index %02x read\n",index);
- break;
- }
- }
- LOG("Trident CR%02X: read %02x\n",index,res);
- return res;
-}
-void trident_vga_device::trident_crtc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x18)
- {
- crtc_reg_write(index,data);
- trident_define_video_mode();
- }
- else
- {
- switch(index)
- {
- case 0x1e: // Module Testing Register
- tri.cr1e = data;
- vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x20)<<11);
- trident_define_video_mode();
- break;
- case 0x1f:
- tri.cr1f = data; // "Software Programming Register" written to by the BIOS
- break;
- case 0x20: // FIFO Control (old MMIO enable? no documentation of this register)
- tri.cr20 = data;
- break;
- case 0x21: // Linear aperture
- tri.cr21 = data;
- tri.linear_address = ((data & 0xc0)<<18) | ((data & 0x0f)<<20);
- tri.linear_active = data & 0x20;
- if(tri.linear_active)
- popmessage("Trident: Linear Aperture active - %08x, %s",tri.linear_address,(tri.cr21 & 0x10) ? "2MB" : "1MB" );
- break;
- case 0x27:
- vga.crtc.start_addr = (vga.crtc.start_addr & 0xfff9ffff) | ((data & 0x03)<<17);
- break;
- case 0x29:
- tri.cr29 = data;
- vga.crtc.offset = (vga.crtc.offset & 0xfeff) | ((data & 0x10)<<4);
- break;
- case 0x2a:
- tri.cr2a = data;
- break;
- case 0x38:
- // bit 0: 16 bit bus
- // bits 2-3: pixel depth (1=15/16bit, 2=24/32bit, 0=anything else)
- // bit 5: packed mode
- tri.pixel_depth = data;
- trident_define_video_mode();
- break;
- case 0x39:
- tri.cr39 = data;
- tri.mmio_active = data & 0x01;
- if(tri.mmio_active)
- popmessage("Trident: MMIO activated");
- break;
- case 0x40:
- tri.cursor_x = (tri.cursor_x & 0xff00) | data;
- break;
- case 0x41:
- tri.cursor_x = (tri.cursor_x & 0x00ff) | (data << 8);
- break;
- case 0x42:
- tri.cursor_y = (tri.cursor_y & 0xff00) | data;
- break;
- case 0x43:
- tri.cursor_y = (tri.cursor_y & 0x00ff) | (data << 8);
- break;
- case 0x44:
- tri.cursor_loc = (tri.cursor_loc & 0xff00) | data;
- break;
- case 0x45:
- tri.cursor_loc = (tri.cursor_loc & 0x00ff) | (data << 8);
- break;
- case 0x46:
- tri.cursor_x_off = data;
- break;
- case 0x47:
- tri.cursor_y_off = data;
- break;
- case 0x48:
- tri.cursor_fg = (tri.cursor_fg & 0xffffff00) | data;
- break;
- case 0x49:
- tri.cursor_fg = (tri.cursor_fg & 0xffff00ff) | (data << 8);
- break;
- case 0x4a:
- tri.cursor_fg = (tri.cursor_fg & 0xff00ffff) | (data << 16);
- break;
- case 0x4b:
- tri.cursor_fg = (tri.cursor_fg & 0x00ffffff) | (data << 24);
- break;
- case 0x4c:
- tri.cursor_bg = (tri.cursor_bg & 0xffffff00) | data;
- break;
- case 0x4d:
- tri.cursor_bg = (tri.cursor_bg & 0xffff00ff) | (data << 8);
- break;
- case 0x4e:
- tri.cursor_bg = (tri.cursor_bg & 0xff00ffff) | (data << 16);
- break;
- case 0x4f:
- tri.cursor_bg = (tri.cursor_bg & 0x00ffffff) | (data << 24);
- break;
- case 0x50:
- tri.cursor_ctrl = data;
- break;
- default:
- LOGWARN("Trident: 3D4 index %02x write %02x\n",index,data);
- break;
- }
- }
- LOG("Trident CR%02X: write %02x\n",index,data);
-}
-
-uint8_t trident_vga_device::trident_gc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- if(index <= 0x0d)
- res = gc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x0e:
- res = tri.gc0e;
- break;
- case 0x0f:
- res = tri.gc0f;
- break;
- case 0x2f:
- res = tri.gc2f;
- break;
- default:
- res = 0xff;
- LOGWARN("Trident: Sequencer index %02x read\n",index);
- break;
- }
- }
- LOG("Trident GC%02X: read %02x\n",index,res);
- return res;
-}
-
-void trident_vga_device::trident_gc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x0d)
- gc_reg_write(index,data);
- else
- {
- LOG("Trident GC%02X: write %02x\n",index,data);
- switch(index)
- {
- case 0x0e: // New Source Address Register (bit 1 is inverted here, also)
- tri.gc0e = data ^ 0x02;
- if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled
- {
- if(tri.gc0f & 0x01) // if bank regs are separated
- svga.bank_r = (data & 0x1f) ^ 0x02;
- }
- break;
- case 0x0f:
- tri.gc0f = data;
- trident_define_video_mode();
- break;
- case 0x2f: // XFree86 refers to this register as "MiscIntContReg", setting bit 2, but gives no indication as to what it does
- tri.gc2f = data;
- break;
- default:
- LOGWARN("Trident: Unimplemented GC register %02x write %02x\n",index,data);
- break;
- }
- }
- LOG("Trident GC%02X: write %02x\n",index,data);
-}
-
-uint8_t trident_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t res;
-
- switch(offset)
- {
- case 0x05:
- res = trident_seq_reg_read(vga.sequencer.index);
- break;
- case 0x06:
- tri.dac_count++;
- if(tri.dac_count > 3)
- tri.dac_active = true;
- if(tri.dac_active)
- res = tri.dac;
- else
- res = vga_device::port_03c0_r(offset);
- break;
- case 0x07:
- case 0x08:
- case 0x09:
- tri.dac_active = false;
- tri.dac_count = 0;
- res = vga_device::port_03c0_r(offset);
- break;
- case 0x0f:
- res = trident_gc_reg_read(vga.gc.index);
- break;
- default:
- res = vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void trident_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x05:
- trident_seq_reg_write(vga.sequencer.index,data);
- break;
- case 0x06:
- if(tri.dac_active)
- {
- tri.dac = data; // DAC command register
- tri.dac_active = false;
- tri.dac_count = 0;
- trident_define_video_mode();
- }
- else
- vga_device::port_03c0_w(offset,data);
- break;
- case 0x07:
- case 0x08:
- case 0x09:
- tri.dac_active = false;
- tri.dac_count = 0;
- vga_device::port_03c0_w(offset,data);
- break;
- case 0x0f:
- trident_gc_reg_write(vga.gc.index,data);
- break;
- default:
- vga_device::port_03c0_w(offset,data);
- break;
- }
-}
-
-
-uint8_t trident_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = trident_crtc_reg_read(vga.crtc.index);
- break;
- case 8:
- if(tri.gc0f & 0x04) // if enabled
- {
- res = svga.bank_w & 0x3f;
- }
- else
- res = 0xff;
- break;
- case 9:
- if(tri.gc0f & 0x04) // if enabled
- if(tri.gc0f & 0x01) // and if bank regs are separated
- res = svga.bank_r & 0x3f;
- else
- res = 0xff;
- else
- res = 0xff;
- break;
- case 11:
- res = tri.port_3db;
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void trident_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- trident_crtc_reg_write(vga.crtc.index,data);
- break;
- case 8:
- if(tri.gc0f & 0x04) // if enabled
- {
- svga.bank_w = data & 0x3f;
- LOG("Trident: Write Bank set to %02x\n",data);
- if(!(tri.gc0f & 0x01)) // if bank regs are not separated
- {
- svga.bank_r = data & 0x3f; // then this is also the read bank register
- LOG("Trident: Read Bank set to %02x\n",data);
- }
- }
- break;
- case 9:
- if(tri.gc0f & 0x04) // if enabled
- {
- if(tri.gc0f & 0x01) // and if bank regs are separated
- {
- svga.bank_r = data & 0x3f;
- LOG("Trident: Read Bank set to %02x\n",data);
- }
- }
- break;
- case 11:
- tri.port_3db = data; // no info on this port? Bit 5 appears to be a clock divider...
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
-}
-
uint8_t trident_vga_device::port_43c6_r(offs_t offset)
{
uint8_t res = 0xff;
@@ -1647,7 +1598,7 @@ void trident_vga_device::accel_data_write(uint32_t data)
// tvga9000 CRTC override
// not extensively tested, just enough for pntnpuzl to not throw a 168 Hz refresh rate.
-void tvga9000_device::trident_define_video_mode()
+void tvga9000_device::recompute_params()
{
int divisor = 1;
int xtal;
diff --git a/src/devices/video/pc_vga_trident.h b/src/devices/video/pc_vga_trident.h
index c0c72b0b939..6a1f6b97984 100644
--- a/src/devices/video/pc_vga_trident.h
+++ b/src/devices/video/pc_vga_trident.h
@@ -17,10 +17,6 @@
class trident_vga_device : public svga_device
{
public:
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
uint8_t port_83c6_r(offs_t offset);
void port_83c6_w(offs_t offset, uint8_t data);
uint8_t port_43c6_r(offs_t offset);
@@ -43,6 +39,28 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
+ virtual void io_3bx_3dx_map(address_map &map) override;
+ virtual void io_3cx_map(address_map &map) override;
+
+ u8 ramdac_hidden_mask_r(offs_t offset);
+ void ramdac_hidden_mask_w(offs_t offset, u8 data);
+ u8 ramdac_overlay_r(offs_t offset);
+ void ramdac_overlay_w(offs_t offset, u8 data);
+
+ u8 svga_bank_write_r(offs_t offset);
+ void svga_bank_write_w(offs_t offset, u8 data);
+ u8 svga_bank_read_r(offs_t offset);
+ void svga_bank_read_w(offs_t offset, u8 data);
+
+
+ virtual void crtc_map(address_map &map) override;
+ virtual void sequencer_map(address_map &map) override;
+ virtual void gc_map(address_map &map) override;
+
+ virtual void recompute_params() override;
+
+
+ // TODO: remove this leaky abstraction
struct
{
uint8_t sr0c;
@@ -117,13 +135,6 @@ protected:
} tri;
uint8_t m_version;
private:
- uint8_t trident_seq_reg_read(uint8_t index);
- void trident_seq_reg_write(uint8_t index, uint8_t data);
- virtual void trident_define_video_mode();
- uint8_t trident_crtc_reg_read(uint8_t index);
- void trident_crtc_reg_write(uint8_t index, uint8_t data);
- uint8_t trident_gc_reg_read(uint8_t index);
- void trident_gc_reg_write(uint8_t index, uint8_t data);
int calculate_clock();
@@ -162,7 +173,8 @@ public:
tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void trident_define_video_mode() override;
+protected:
+ virtual void recompute_params() override;
};
// device type definition
diff --git a/src/devices/video/pc_vga_tseng.cpp b/src/devices/video/pc_vga_tseng.cpp
index 6e4f7e8d7d8..5558a1d2f00 100644
--- a/src/devices/video/pc_vga_tseng.cpp
+++ b/src/devices/video/pc_vga_tseng.cpp
@@ -7,7 +7,7 @@
* - ET3000 (VGA only?)
* - ET4000AX
* \- No logging whatsoever;
- * \- Unsupported True Color modes;
+ * \- Unsupported True Color modes, also "Return current video mode failed" in VESA24_2 test;
* - ET4000/W32 (2d accelerator)
* - ET4000/W32p (PCI version)
*
@@ -24,6 +24,10 @@ DEFINE_DEVICE_TYPE(TSENG_VGA, tseng_vga_device, "tseng_vga", "Tseng Labs ET40
tseng_vga_device::tseng_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: svga_device(mconfig, TSENG_VGA, tag, owner, clock)
{
+ m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(tseng_vga_device::io_3bx_3dx_map), this));
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(tseng_vga_device::crtc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(tseng_vga_device::sequencer_map), this));
+ m_atc_space_config = address_space_config("attribute_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(tseng_vga_device::attribute_map), this));
}
void tseng_vga_device::device_start()
@@ -41,213 +45,131 @@ void tseng_vga_device::device_start()
save_item(NAME(et4k.misc2));
}
-void tseng_vga_device::tseng_define_video_mode()
+void tseng_vga_device::io_3bx_3dx_map(address_map &map)
{
- int divisor;
- int xtal = 0;
- svga.rgb8_en = 0;
- svga.rgb15_en = 0;
- svga.rgb16_en = 0;
- svga.rgb24_en = 0;
- switch(((et4k.aux_ctrl << 1) & 4)|(vga.miscellaneous_output & 0xc)>>2)
- {
- case 0:
- xtal = XTAL(25'174'800).value();
- break;
- case 1:
- xtal = XTAL(28'636'363).value();
- break;
- case 2:
- xtal = 16257000*2; //2xEGA clock
- break;
- case 3:
- xtal = XTAL(40'000'000).value();
- break;
- case 4:
- xtal = XTAL(36'000'000).value();
- break;
- case 5:
- xtal = XTAL(45'000'000).value();
- break;
- case 6:
- xtal = 31000000;
- break;
- case 7:
- xtal = 38000000;
- break;
- }
- switch(et4k.dac_ctrl & 0xe0)
- {
- case 0xa0:
- svga.rgb15_en = 1;
- divisor = 2;
- break;
- case 0xe0:
- svga.rgb16_en = 1;
- divisor = 2;
- break;
- case 0x60:
- svga.rgb24_en = 1;
- divisor = 3;
- xtal *= 2.0f/3.0f;
- break;
- default:
- svga.rgb8_en = (!(vga.sequencer.data[1] & 8) && (vga.sequencer.data[4] & 8) && vga.gc.shift256 && vga.crtc.div2 && GRAPHIC_MODE);
- divisor = 1;
- break;
- }
- recompute_params_clock(divisor, xtal);
+ svga_device::io_3bx_3dx_map(map);
+ map(0x08, 0x08).lrw8(
+ NAME([this] (offs_t offset) {
+ return et4k.reg_3d8;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ et4k.reg_3d8 = data;
+ if(data == 0xa0)
+ et4k.ext_reg_ena = true;
+ else if(data == 0x29)
+ et4k.ext_reg_ena = false;
+ })
+ );
}
-uint8_t tseng_vga_device::tseng_crtc_reg_read(uint8_t index)
+void tseng_vga_device::io_3cx_map(address_map &map)
{
- uint8_t res;
-
- if(index <= 0x18)
- res = crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x34:
- res = et4k.aux_ctrl;
- break;
- case 0x3f:
- res = et4k.horz_overflow;
- break;
- default:
- res = vga.crtc.data[index];
- //printf("%02x\n",index);
- break;
- }
- }
-
- return res;
+ svga_device::io_3cx_map(map);
+ map(0x06, 0x06).rw(FUNC(tseng_vga_device::ramdac_hidden_mask_r), FUNC(tseng_vga_device::ramdac_hidden_mask_w));
+ map(0x08, 0x08).r(FUNC(tseng_vga_device::ramdac_hidden_windex_r));
+ map(0x0d, 0x0d).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = svga.bank_w & 0xf;
+ res |= (svga.bank_r & 0xf) << 4;
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ svga.bank_w = data & 0xf;
+ svga.bank_r = (data & 0xf0) >> 4;
+ })
+ );
}
-void tseng_vga_device::tseng_crtc_reg_write(uint8_t index, uint8_t data)
+u8 tseng_vga_device::ramdac_hidden_mask_r(offs_t offset)
{
- if(index <= 0x18)
- crtc_reg_write(index,data);
- else
+ if(et4k.dac_state == 4)
{
- switch(index)
- {
- case 0x34:
- et4k.aux_ctrl = data;
- break;
- case 0x3f:
- et4k.horz_overflow = data;
- vga.crtc.horz_total = (vga.crtc.horz_total & 0xff) | ((data & 1) << 8);
- break;
- default:
- //printf("%02x %02x\n",index,data);
- break;
- }
+ if(!et4k.dac_ctrl)
+ et4k.dac_ctrl = 0x80;
+ return et4k.dac_ctrl;
}
+ if (!machine().side_effects_disabled())
+ et4k.dac_state++;
+ return vga_device::ramdac_mask_r(offset);
}
-uint8_t tseng_vga_device::tseng_seq_reg_read(uint8_t index)
+void tseng_vga_device::ramdac_hidden_mask_w(offs_t offset, u8 data)
{
- uint8_t res;
-
- res = 0xff;
-
- if(index <= 0x04)
- res = vga.sequencer.data[index];
- else
+ if(et4k.dac_state == 4)
{
- switch(index)
- {
- case 0x06:
- case 0x07:
- //printf("%02x\n",index);
- break;
- }
+ et4k.dac_ctrl = data;
+ recompute_params();
+ return;
}
- return res;
+ vga_device::ramdac_write_index_w(offset, data);
}
-void tseng_vga_device::tseng_seq_reg_write(uint8_t index, uint8_t data)
+u8 tseng_vga_device::ramdac_hidden_windex_r(offs_t offset)
{
- if(index <= 0x04)
- {
- vga.sequencer.data[vga.sequencer.index] = data;
- seq_reg_write(vga.sequencer.index,data);
- }
- else
- {
- switch(index)
- {
- case 0x06:
- case 0x07:
- //printf("%02x %02x\n",index,data);
- break;
- }
- }
+ if (!machine().side_effects_disabled())
+ et4k.dac_state = 0;
+ return vga_device::ramdac_write_index_r(offset);
}
-uint8_t tseng_vga_device::port_03b0_r(offs_t offset)
+void tseng_vga_device::crtc_map(address_map &map)
{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- res = tseng_crtc_reg_read(vga.crtc.index);
- break;
- case 8:
- res = et4k.reg_3d8;
- break;
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
+ svga_device::crtc_map(map);
+ map(0x34, 0x34).lrw8(
+ NAME([this] (offs_t offset) {
+ return et4k.aux_ctrl;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ et4k.aux_ctrl = data;
+ recompute_params();
+ })
+ );
+ map(0x3f, 0x3f).lrw8(
+ NAME([this] (offs_t offset) {
+ return et4k.horz_overflow;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ et4k.horz_overflow = data;
+ vga.crtc.horz_total = (vga.crtc.horz_total & 0xff) | ((data & 1) << 8);
+ recompute_params();
+ })
+ );
}
-void tseng_vga_device::port_03b0_w(offs_t offset, uint8_t data)
+void tseng_vga_device::sequencer_map(address_map &map)
{
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- tseng_crtc_reg_write(vga.crtc.index,data);
- break;
- case 8:
- et4k.reg_3d8 = data;
- if(data == 0xa0)
- et4k.ext_reg_ena = true;
- else if(data == 0x29)
- et4k.ext_reg_ena = false;
- break;
- default:
- vga_device::port_03b0_w(offset,data);
- break;
- }
- }
- tseng_define_video_mode();
+ svga_device::sequencer_map(map);
+ // TODO: preseve legacy hookup, to be investigated
+ map(0x05, 0xff).unmaprw();
}
-void tseng_vga_device::tseng_attribute_reg_write(uint8_t index, uint8_t data)
+void tseng_vga_device::attribute_map(address_map &map)
{
- switch(index)
- {
- case 0x16:
+ map.global_mask(0x3f);
+ map.unmap_value_high();
+ svga_device::attribute_map(map);
+ // Miscellaneous 1
+ /*
+ * x--- ---- Bypass the internal palette
+ * -x-- ---- 2 byte character code (presumably for the Korean variants TBD)
+ * --xx ---- Select High resolution/color mode
+ * --00 ---- Normal power-up
+ * --01 ---- <reserved>
+ * --10 ---- 8bpp
+ * --11 ---- 16bpp
+ * ---- xxxx <reserved>
+ */
+ // TODO: implement KEY protection
+ map(0x16, 0x16).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return et4k.misc1; }),
+ NAME([this] (offs_t offset, u8 data) {
et4k.misc1 = data;
+ // TODO: this should be taken into account for recompute_params
#if 0
svga.rgb8_en = 0;
svga.rgb15_en = 0;
svga.rgb16_en = 0;
svga.rgb32_en = 0;
- /* TODO: et4k and w32 are different here */
switch(et4k.misc1 & 0x30)
{
case 0:
@@ -262,147 +184,76 @@ void tseng_vga_device::tseng_attribute_reg_write(uint8_t index, uint8_t data)
break;
}
#endif
- break;
- case 0x17: et4k.misc2 = data; break;
- default:
- attribute_reg_write(index,data);
- }
-
+ })
+ );
+ // Miscellaneous 2
+ // TODO: not on stock et4k?
+ map(0x17, 0x17).mirror(0x20).lrw8(
+ NAME([this] (offs_t offset) { return et4k.misc2; }),
+ NAME([this] (offs_t offset, u8 data) {
+ et4k.misc2 = data;
+ })
+ );
}
-uint8_t tseng_vga_device::port_03c0_r(offs_t offset)
+void tseng_vga_device::recompute_params()
{
- uint8_t res;
-
- switch(offset)
+ int divisor;
+ int xtal = 0;
+ svga.rgb8_en = 0;
+ svga.rgb15_en = 0;
+ svga.rgb16_en = 0;
+ svga.rgb24_en = 0;
+ switch(((et4k.aux_ctrl << 1) & 4)|(vga.miscellaneous_output & 0xc)>>2)
{
- case 0x01:
- switch(vga.attribute.index)
- {
- case 0x16: res = et4k.misc1; break;
- case 0x17: res = et4k.misc2; break;
- default:
- res = vga_device::port_03c0_r(offset);
- break;
- }
-
+ case 0:
+ xtal = XTAL(25'174'800).value();
break;
-
- case 0x05:
- res = tseng_seq_reg_read(vga.sequencer.index);
+ case 1:
+ xtal = XTAL(28'636'363).value();
break;
- case 0x0d:
- res = svga.bank_w & 0xf;
- res |= (svga.bank_r & 0xf) << 4;
+ case 2:
+ xtal = 16257000*2; //2xEGA clock
break;
- case 0x06:
- if(et4k.dac_state == 4)
- {
- if(!et4k.dac_ctrl)
- et4k.dac_ctrl = 0x80;
- res = et4k.dac_ctrl;
- break;
- }
- et4k.dac_state++;
- res = vga_device::port_03c0_r(offset);
+ case 3:
+ xtal = XTAL(40'000'000).value();
break;
- case 0x08:
- et4k.dac_state = 0;
- [[fallthrough]];
- default:
- res = vga_device::port_03c0_r(offset);
+ case 4:
+ xtal = XTAL(36'000'000).value();
+ break;
+ case 5:
+ xtal = XTAL(45'000'000).value();
+ break;
+ case 6:
+ xtal = 31000000;
+ break;
+ case 7:
+ xtal = 38000000;
break;
}
-
- return res;
-}
-
-void tseng_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
+ switch(et4k.dac_ctrl & 0xe0)
{
- case 0:
- if (vga.attribute.state==0)
- {
- vga.attribute.index=data;
- }
- else
- {
- tseng_attribute_reg_write(vga.attribute.index,data);
- }
- vga.attribute.state=!vga.attribute.state;
+ case 0xa0:
+ svga.rgb15_en = 1;
+ divisor = 2;
break;
-
- case 0x05:
- tseng_seq_reg_write(vga.sequencer.index,data);
+ case 0xe0:
+ svga.rgb16_en = 1;
+ divisor = 2;
break;
- case 0x0d:
- svga.bank_w = data & 0xf;
- svga.bank_r = (data & 0xf0) >> 4;
+ case 0x60:
+ svga.rgb24_en = 1;
+ divisor = 3;
+ xtal *= 2.0f/3.0f;
break;
- case 0x06:
- if(et4k.dac_state == 4)
- {
- et4k.dac_ctrl = data;
- break;
- }
- [[fallthrough]];
default:
- vga_device::port_03c0_w(offset,data);
+ svga.rgb8_en = (!(vga.sequencer.data[1] & 8) && (vga.sequencer.data[4] & 8) && vga.gc.shift256 && vga.crtc.div2 && GRAPHIC_MODE);
+ divisor = 1;
break;
}
- tseng_define_video_mode();
-}
-
-uint8_t tseng_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = tseng_crtc_reg_read(vga.crtc.index);
- break;
- case 8:
- res = et4k.reg_3d8;
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
+ recompute_params_clock(divisor, xtal);
}
-void tseng_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- tseng_crtc_reg_write(vga.crtc.index,data);
- //if((vga.crtc.index & 0xfe) != 0x0e)
- // printf("%02x %02x %d\n",vga.crtc.index,data,screen().vpos());
- break;
- case 8:
- et4k.reg_3d8 = data;
- if(data == 0xa0)
- et4k.ext_reg_ena = true;
- else if(data == 0x29)
- et4k.ext_reg_ena = false;
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
- tseng_define_video_mode();
-}
uint8_t tseng_vga_device::mem_r(offs_t offset)
{
diff --git a/src/devices/video/pc_vga_tseng.h b/src/devices/video/pc_vga_tseng.h
index 85279de7580..cda09fa0acc 100644
--- a/src/devices/video/pc_vga_tseng.h
+++ b/src/devices/video/pc_vga_tseng.h
@@ -19,26 +19,25 @@ public:
// construction/destruction
tseng_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override;
-private:
- void tseng_define_video_mode();
- uint8_t tseng_crtc_reg_read(uint8_t index);
- void tseng_crtc_reg_write(uint8_t index, uint8_t data);
- uint8_t tseng_seq_reg_read(uint8_t index);
- void tseng_seq_reg_write(uint8_t index, uint8_t data);
- void tseng_attribute_reg_write(uint8_t index, uint8_t data);
+ virtual void io_3bx_3dx_map(address_map &map) override;
+ virtual void io_3cx_map(address_map &map) override;
+
+ u8 ramdac_hidden_mask_r(offs_t offset);
+ void ramdac_hidden_mask_w(offs_t offset, u8 data);
+ u8 ramdac_hidden_windex_r(offs_t offset);
+ virtual void crtc_map(address_map &map) override;
+ virtual void sequencer_map(address_map &map) override;
+ virtual void attribute_map(address_map &map) override;
+
+ virtual void recompute_params() override;
+private:
struct
{
uint8_t reg_3d8;
diff --git a/src/devices/video/pc_xga.cpp b/src/devices/video/pc_xga.cpp
index 60dc15a8538..84ca7766ccf 100644
--- a/src/devices/video/pc_xga.cpp
+++ b/src/devices/video/pc_xga.cpp
@@ -761,6 +761,7 @@ oak_oti111_vga_device::oak_oti111_vga_device(const machine_config &mconfig, cons
: svga_device(mconfig, OTI111, tag, owner, clock)
, m_xga(*this, "xga")
{
+ m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(oak_oti111_vga_device::io_3bx_3dx_map), this));
}
void oak_oti111_vga_device::device_add_mconfig(machine_config &config)
@@ -771,6 +772,38 @@ void oak_oti111_vga_device::device_add_mconfig(machine_config &config)
m_xga->set_type(xga_copro_device::TYPE::OTI111);
}
+void oak_oti111_vga_device::io_3bx_3dx_map(address_map &map)
+{
+ svga_device::io_3bx_3dx_map(map);
+ // TODO: convert to address_space
+ map(0x0e, 0xe).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_oak_idx;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_oak_idx = data;
+ })
+ );
+ map(0x0f, 0xf).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_oak_idx <= 0x3a ? m_oak_regs[m_oak_idx] : space().unmap();
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_oak_regs[m_oak_idx] = data;
+ switch(m_oak_idx)
+ {
+ case 0x21:
+ svga.rgb8_en = BIT(data, 2);
+ break;
+ case 0x33:
+ vga.crtc.no_wrap = BIT(data, 0);
+ break;
+ }
+ })
+ );
+}
+
+// TODO: convert to map
u8 oak_oti111_vga_device::xga_read(offs_t offset)
{
switch(offset)
@@ -794,64 +827,14 @@ void oak_oti111_vga_device::device_start()
std::fill(std::begin(m_oak_regs), std::end(m_oak_regs), 0);
}
-u8 oak_oti111_vga_device::dac_read(offs_t offset)
-{
- if(offset >= 6)
- return vga_device::port_03c0_r(offset);
- return 0;
-}
-
-void oak_oti111_vga_device::dac_write(offs_t offset, u8 data)
-{
- if(offset >= 6)
- vga_device::port_03c0_w(offset, data);
-}
-
-
-u8 oak_oti111_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
- switch(offset)
- {
- case 14:
- return m_oak_idx;
- case 15:
- return m_oak_idx <= 0x3a ? m_oak_regs[m_oak_idx] : 0;
- default:
- if (get_crtc_port() == 0x3d0)
- res = vga_device::port_03d0_r(offset);
- break;
- }
-
- return res;
-}
-
-void oak_oti111_vga_device::port_03d0_w(offs_t offset, uint8_t data)
+void oak_oti111_vga_device::ramdac_mmio_map(address_map &map)
{
- switch(offset)
- {
- case 14:
- m_oak_idx = data;
- break;
- case 15:
- if(m_oak_idx > 0x3a)
- break;
- m_oak_regs[m_oak_idx] = data;
- switch(m_oak_idx)
- {
- case 0x21:
- svga.rgb8_en = BIT(data, 2);
- break;
- case 0x33:
- vga.crtc.no_wrap = BIT(data, 0);
- break;
- }
- break;
- default:
- if (get_crtc_port() == 0x3d0)
- vga_device::port_03d0_w(offset,data);
- break;
- }
+ map.unmap_value_high();
+// TODO: 0x04, 0x05 alt accesses for CRTC?
+ map(0x06, 0x06).rw(FUNC(oak_oti111_vga_device::ramdac_mask_r), FUNC(oak_oti111_vga_device::ramdac_mask_w));
+ map(0x07, 0x07).rw(FUNC(oak_oti111_vga_device::ramdac_state_r), FUNC(oak_oti111_vga_device::ramdac_read_index_w));
+ map(0x08, 0x08).rw(FUNC(oak_oti111_vga_device::ramdac_write_index_r), FUNC(oak_oti111_vga_device::ramdac_write_index_w));
+ map(0x09, 0x09).rw(FUNC(oak_oti111_vga_device::ramdac_data_r), FUNC(oak_oti111_vga_device::ramdac_data_w));
}
uint16_t oak_oti111_vga_device::offset()
diff --git a/src/devices/video/pc_xga.h b/src/devices/video/pc_xga.h
index b3973608187..05dc7b4bca1 100644
--- a/src/devices/video/pc_xga.h
+++ b/src/devices/video/pc_xga.h
@@ -77,14 +77,15 @@ public:
u8 xga_read(offs_t offset);
void xga_write(offs_t offset, u8 data);
- u8 dac_read(offs_t offset);
- void dac_write(offs_t offset, u8 data);
- virtual u8 port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
+
+ void ramdac_mmio_map(address_map &map);
+
protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual uint16_t offset() override;
+
+ virtual void io_3bx_3dx_map(address_map &map) override;
private:
u8 m_oak_regs[0x3b];
u8 m_oak_idx;
diff --git a/src/devices/video/riva128.cpp b/src/devices/video/riva128.cpp
index 4be3204bf8e..f36885fd76c 100644
--- a/src/devices/video/riva128.cpp
+++ b/src/devices/video/riva128.cpp
@@ -194,9 +194,7 @@ void riva128_device::legacy_memory_map(address_map &map)
void riva128_device::legacy_io_map(address_map &map)
{
- map(0x03b0, 0x03bf).rw(FUNC(riva128_device::vga_3b0_r), FUNC(riva128_device::vga_3b0_w));
- map(0x03c0, 0x03cf).rw(FUNC(riva128_device::vga_3c0_r), FUNC(riva128_device::vga_3c0_w));
- map(0x03d0, 0x03df).rw(FUNC(riva128_device::vga_3d0_r), FUNC(riva128_device::vga_3d0_w));
+ map(0, 0x02f).m(m_svga, FUNC(nvidia_nv3_vga_device::io_map));
}
uint8_t riva128_device::vram_r(offs_t offset)
@@ -209,85 +207,6 @@ void riva128_device::vram_w(offs_t offset, uint8_t data)
downcast<nvidia_nv3_vga_device *>(m_svga.target())->mem_w(offset, data);
}
-u32 riva128_device::vga_3b0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void riva128_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 3, data >> 24);
-}
-
-
-u32 riva128_device::vga_3c0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void riva128_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 3, data >> 24);
-}
-
-u32 riva128_device::vga_3d0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void riva128_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<nvidia_nv3_vga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 3, data >> 24);
-}
-
void riva128_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)
{
@@ -295,9 +214,7 @@ void riva128_device::map_extra(uint64_t memory_window_start, uint64_t memory_win
{
memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(riva128_device::vram_r)), write8sm_delegate(*this, FUNC(riva128_device::vram_w)));
- io_space->install_readwrite_handler(0x3b0, 0x3bf, read32s_delegate(*this, FUNC(riva128_device::vga_3b0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3b0_w)));
- io_space->install_readwrite_handler(0x3c0, 0x3cf, read32s_delegate(*this, FUNC(riva128_device::vga_3c0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3c0_w)));
- io_space->install_readwrite_handler(0x3d0, 0x3df, read32s_delegate(*this, FUNC(riva128_device::vga_3d0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3d0_w)));
+ io_space->install_device(0x03b0, 0x03df, *this, &riva128_device::legacy_io_map);
//memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom);
}
}
diff --git a/src/devices/video/riva128.h b/src/devices/video/riva128.h
index a70bf909c16..ce03de39a68 100644
--- a/src/devices/video/riva128.h
+++ b/src/devices/video/riva128.h
@@ -42,12 +42,6 @@ protected:
private:
u8 vram_r(offs_t offset);
void vram_w(offs_t offset, uint8_t data);
- u32 vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- u32 vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0);
void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0);
diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/video/s3virge.cpp
index a621c3ed22c..3d3bdd023a5 100644
--- a/src/devices/bus/isa/s3virge.cpp
+++ b/src/devices/video/s3virge.cpp
@@ -54,6 +54,8 @@ DEFINE_DEVICE_TYPE(S3VIRGEDX1, s3virgedx_rev1_vga_device, "virgedx_vga_r1", "S3
s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: s3virge_vga_device(mconfig, S3VIRGE, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virge_vga_device::crtc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virge_vga_device::sequencer_map), this));
}
s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -65,6 +67,8 @@ s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, device_typ
s3virgedx_vga_device::s3virgedx_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: s3virgedx_vga_device(mconfig, S3VIRGEDX, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virgedx_vga_device::crtc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virgedx_vga_device::sequencer_map), this));
}
s3virgedx_vga_device::s3virgedx_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -75,6 +79,8 @@ s3virgedx_vga_device::s3virgedx_vga_device(const machine_config &mconfig, device
s3virgedx_rev1_vga_device::s3virgedx_rev1_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: s3virgedx_vga_device(mconfig, S3VIRGEDX1, tag, owner, clock)
{
+ m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virgedx_rev1_vga_device::crtc_map), this));
+ m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(s3virgedx_rev1_vga_device::sequencer_map), this));
}
void s3virge_vga_device::device_start()
@@ -88,8 +94,6 @@ void s3virge_vga_device::device_start()
vga.crtc.maximum_scan_line = 1;
// copy over interfaces
- vga.svga_intf.seq_regcount = 0x1c;
- vga.svga_intf.crtc_regcount = 0x19;
vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
@@ -188,150 +192,158 @@ uint16_t s3virge_vga_device::offset()
return s3_vga_device::offset();
}
-uint8_t s3virge_vga_device::s3_crtc_reg_read(uint8_t index)
+void s3virge_vga_device::crtc_map(address_map &map)
{
- uint8_t res;
+ s3_vga_device::crtc_map(map);
+ // TODO: verify these overrides
+ map(0x3a, 0x3a).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cr3a = data;
+ s3_define_video_mode();
+ })
+ );
+ map(0x40, 0x40).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ // enable S3D registers
+ s3.enable_s3d = data & 0x01;
+ })
+ );
+ map(0x43, 0x43).lw8(
+ NAME([this] (offs_t offset, u8 data) {
+ // bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h.
+ s3.cr43 = data;
+ if((s3.cr51 & 0x30) == 0)
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6);
+ else
+ vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr51 & 0x30) << 4);
+ s3_define_video_mode();
+ })
+ );
+ map(0x45, 0x45).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cursor_mode;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cursor_mode = data;
+ })
+ );
+ map(0x4a, 0x4a).lr8(
+ NAME([this] (offs_t offset) {
+ u8 res = s3.cursor_fg[s3.cursor_fg_ptr];
+ s3.cursor_fg_ptr = 0;
+ return res;
+ })
+ );
+ map(0x4b, 0x4b).lr8(
+ NAME([this] (offs_t offset) {
+ u8 res = s3.cursor_bg[s3.cursor_bg_ptr];
+ s3.cursor_bg_ptr = 0;
+ return res;
+ })
+ );
+ map(0x51, 0x51).lr8(
+ NAME([this] (offs_t offset) {
+ u8 res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
+ res |= ((svga.bank_w & 0x30) >> 2);
+ //res |= ((vga.crtc.offset & 0x0300) >> 4);
+ return res;
+ })
+ );
+ map(0x53, 0x53).lrw8(
+ NAME([this] (offs_t offset) {
+ return s3.cr53;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ s3.cr53 = data;
+ //m_linear_config_changed_cb(s3virge.linear_address_enable);
+ })
+ );
+ map(0x58, 0x58).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = s3virge.linear_address_size & 0x03;
+ res |= s3virge.linear_address_enable ? 0x10 : 0x00;
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ const uint8_t old_size = s3virge.linear_address_size;
+ const bool old_enable = s3virge.linear_address_enable;
+ const bool size_changed = old_size != s3virge.linear_address_size;
+
+ 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;
+ }
- if(index <= 0x18)
- res = crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x2d:
- res = s3.id_high;
- break;
- case 0x2e:
- res = s3.id_low;
- break;
- case 0x2f:
- res = s3.revision;
- break;
- case 0x30: // CR30 Chip ID/REV register
- res = s3.id_cr30;
- break;
- case 0x31:
- res = s3.memory_config;
- break;
- case 0x35:
- res = s3.crt_reg_lock;
- break;
- case 0x36: // Configuration register 1
- res = s3.strapping & 0x000000ff;
- break;
- case 0x37: // Configuration register 2
- res = (s3.strapping & 0x0000ff00) >> 8;
- break;
- case 0x38:
- res = s3.reg_lock1;
- break;
- case 0x39:
- res = s3.reg_lock2;
- break;
- case 0x42: // CR42 Mode Control
- res = s3.cr42 & 0x0f; // bit 5 set if interlaced, leave it unset for now.
- break;
- case 0x43:
- res = s3.cr43;
- break;
- case 0x45:
- res = s3.cursor_mode;
- break;
- case 0x46:
- res = (s3.cursor_x & 0xff00) >> 8;
- break;
- case 0x47:
- res = s3.cursor_x & 0x00ff;
- break;
- case 0x48:
- res = (s3.cursor_y & 0xff00) >> 8;
- break;
- case 0x49:
- res = s3.cursor_y & 0x00ff;
- break;
- case 0x4a:
- res = s3.cursor_fg[s3.cursor_fg_ptr];
- s3.cursor_fg_ptr = 0;
- break;
- case 0x4b:
- res = s3.cursor_bg[s3.cursor_bg_ptr];
- s3.cursor_bg_ptr = 0;
- break;
- case 0x4c:
- res = (s3.cursor_start_addr & 0xff00) >> 8;
- break;
- case 0x4d:
- res = s3.cursor_start_addr & 0x00ff;
- break;
- case 0x4e:
- res = s3.cursor_pattern_x;
- break;
- case 0x4f:
- res = s3.cursor_pattern_y;
- break;
- case 0x51:
- res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
- res |= ((svga.bank_w & 0x30) >> 2);
- break;
- 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
- default:
- 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)
- res = s3.cr42 & 0x0f;
- else
- res = (vga.miscellaneous_output & 0xc) >> 2;
- break;
- case 0x67:
- res = s3.ext_misc_ctrl_2;
- break;
- case 0x68: // Configuration register 3
- res = (s3.strapping & 0x00ff0000) >> 16;
- break;
- case 0x69:
- res = vga.crtc.start_addr_latch >> 16;
- break;
- case 0x6a:
- res = svga.bank_r & 0x7f;
- break;
- case 0x6f: // Configuration register 4
- res = (s3.strapping & 0xff000000) >> 24;
- break;
- default:
- res = vga.crtc.data[index];
- //machine.debug_break();
- //printf("%02x\n",index);
- break;
- }
- }
+ if ((s3virge.linear_address_enable != old_enable) || size_changed)
+ {
+ m_linear_config_changed_cb(s3virge.linear_address_enable);
+ }
- return res;
+ LOGREG("CR58: write %02x\n", data);
+ })
+ );
+ map(0x59, 0x59).lrw8(
+ NAME([this] (offs_t offset) {
+ return (s3virge.linear_address & 0xff000000) >> 24;;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ const uint32_t old_address = s3virge.linear_address;
+ s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24);
+ LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
+
+ if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
+ {
+ m_linear_config_changed_cb(1);
+ }
+ })
+ );
+ map(0x5a, 0x5a).lrw8(
+ NAME([this] (offs_t offset) {
+ u8 res = 0;
+ switch(s3virge.linear_address_size & 0x03)
+ {
+ case 0: // 64kB
+ default:
+ 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;
+ }
+ return res;
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ const uint32_t old_address = s3virge.linear_address;
+ s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16);
+ LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
+
+ if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
+ {
+ m_linear_config_changed_cb(1);
+ }
+ })
+ );
+ //map(0x5d, 0x5e).unmapr();
}
void s3virge_vga_device::s3_define_video_mode()
@@ -376,480 +388,6 @@ void s3virge_vga_device::s3_define_video_mode()
recompute_params_clock(divisor, xtal.value());
}
-void s3virge_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x18)
- {
- crtc_reg_write(index,data);
- s3_define_video_mode();
- }
- else
- {
- switch(index)
- {
- case 0x31: // CR31 Memory Configuration Register
- s3.memory_config = data;
- vga.crtc.start_addr_latch &= ~0x30000;
- vga.crtc.start_addr_latch |= ((data & 0x30) << 12);
- s3_define_video_mode();
- break;
- case 0x35:
- if((s3.reg_lock1 & 0xc) != 8 || ((s3.reg_lock1 & 0xc0) == 0)) // lock register
- return;
- s3.crt_reg_lock = data;
- svga.bank_w = data & 0xf;
- svga.bank_r = svga.bank_w;
- break;
- case 0x36:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffffff00) | data;
- LOGREG("CR36: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x37:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8);
- LOGREG("CR37: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x38:
- s3.reg_lock1 = data;
- break;
- case 0x39:
- /* TODO: reg lock mechanism */
- s3.reg_lock2 = data;
- break;
- case 0x3a:
- s3.cr3a = data;
- break;
- case 0x40:
- s3.enable_s3d = data & 0x01; // enable S3D registers
- break;
- case 0x42:
- s3.cr42 = data; // bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented)
- break;
- case 0x43:
- s3.cr43 = data; // bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h.
- if((s3.cr51 & 0x30) == 0)
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6);
- else
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr51 & 0x30) << 4);
- s3_define_video_mode();
- break;
-/*
-3d4h index 45h (R/W): CR45 Hardware Graphics Cursor Mode
-bit 0 HWGC ENB. Hardware Graphics Cursor Enable. Set to enable the
- HardWare Cursor in VGA and enhanced modes.
- 1 (911/24) Delay Timing for Pattern Data Fetch
- 2 (801/5,928) Hardware Cursor Horizontal Stretch 2. If set the cursor
- pixels are stretched horizontally to two bytes and items 0 and 1 of
- the fore/background stacks in 3d4h index 4Ah/4Bh are used.
- 3 (801/5,928) Hardware Cursor Horizontal Stretch 3. If set the cursor
- pixels are stretched horizontally to three bytes and items 0,1 and
- 2 of the fore/background stacks in 3d4h index 4Ah/4Bh are used.
- 2-3 (805i,864/964) HWC-CSEL. Hardware Cursor Color Select.
- 0: 4/8bit, 1: 15/16bt, 2: 24bit, 3: 32bit
- Note: So far I've had better luck with: 0: 8/15/16bit, 1: 32bit??
- 4 (80x +) Hardware Cursor Right Storage. If set the cursor data is
- stored in the last 256 bytes of 4 1Kyte lines (4bits/pixel) or the
- last 512 bytes of 2 2Kbyte lines (8bits/pixel). Intended for
- 1280x1024 modes where there are no free lines at the bottom.
- 5 (928) Cursor Control Enable for Brooktree Bt485 DAC. If set and 3d4h
- index 55h bit 5 is set the HC1 output becomes the ODF and the HC0
- output becomes the CDE
- (964) BT485 ODF Selection for Bt485A RAMDAC. If set pin 185 (RS3
- /ODF) is the ODF output to a Bt485A compatible RamDAC (low for even
- fields and high for odd fields), if clear pin185 is the RS3 output.
- */
- case 0x45:
- s3.cursor_mode = data;
- break;
-/*
-3d4h index 46h M(R/W): CR46/7 Hardware Graphics Cursor Origin-X
-bit 0-10 The HardWare Cursor X position. For 64k modes this value should be
- twice the actual X co-ordinate.
- */
- case 0x46:
- s3.cursor_x = (s3.cursor_x & 0x00ff) | (data << 8);
- break;
- case 0x47:
- s3.cursor_x = (s3.cursor_x & 0xff00) | data;
- break;
-/*
-3d4h index 48h M(R/W): CR48/9 Hardware Graphics Cursor Origin-Y
-bit 0-9 (911/24) The HardWare Cursor Y position.
- 0-10 (80x +) The HardWare Cursor Y position.
-Note: The position is activated when the high byte of the Y coordinate (index
- 48h) is written, so this byte should be written last (not 911/924 ?)
- */
- case 0x48:
- s3.cursor_y = (s3.cursor_y & 0x00ff) | (data << 8);
- break;
- case 0x49:
- s3.cursor_y = (s3.cursor_y & 0xff00) | data;
- break;
-
-/*
-3d4h index 4Ah (R/W): Hardware Graphics Cursor Foreground Stack (80x +)
-bit 0-7 The Foreground Cursor color. Three bytes (4 for the 864/964) are
- stacked here. When the Cursor Mode register (3d4h index 45h) is read
- the stackpointer is reset. When a byte is written the byte is
- written into the current top of stack and the stackpointer is
- increased. The first byte written (item 0) is allways used, the
- other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
- index 45h bit 2-3) is enabled.
- */
- case 0x4a:
- s3.cursor_fg[s3.cursor_fg_ptr++] = data;
- s3.cursor_fg_ptr %= 4;
- break;
-/*
-3d4h index 4Bh (R/W): Hardware Graphics Cursor Background Stack (80x +)
-bit 0-7 The Background Cursor color. Three bytes (4 for the 864/964) are
- stacked here. When the Cursor Mode register (3d4h index 45h) is read
- the stackpointer is reset. When a byte is written the byte is
- written into the current top of stack and the stackpointer is
- increased. The first byte written (item 0) is allways used, the
- other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
- index 45h bit 2-3) is enabled.
- */
- case 0x4b:
- s3.cursor_bg[s3.cursor_bg_ptr++] = data;
- s3.cursor_bg_ptr %= 4;
- break;
-/*
-3d4h index 4Ch M(R/W): CR4C/D Hardware Graphics Cursor Storage Start Address
-bit 0-9 (911,924) HCS_STADR. Hardware Graphics Cursor Storage Start Address
- 0-11 (80x,928) HWGC_STA. Hardware Graphics Cursor Storage Start Address
- 0-12 (864,964) HWGC_STA. Hardware Graphics Cursor Storage Start Address
- Address of the HardWare Cursor Map in units of 1024 bytes (256 bytes
- for planar modes). The cursor map is a 64x64 bitmap with 2 bits (A
- and B) per pixel. The map is stored as one word (16 bits) of bit A,
- followed by one word with the corresponding 16 B bits.
- The bits are interpreted as:
- A B MS-Windows: X-11:
- 0 0 Background Screen data
- 0 1 Foreground Screen data
- 1 0 Screen data Background
- 1 1 Inverted screen Foreground
- The Windows/X11 switch is only available for the 80x +.
- (911/24) For 64k color modes the cursor is stored as one byte (8
- bits) of A bits, followed by the 8 B-bits, and each bit in the
- cursor should be doubled to provide a consistent cursor image.
- (801/5,928) For Hi/True color modes use the Horizontal Stretch bits
- (3d4h index 45h bits 2 and 3).
- */
- case 0x4c:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0x00ff) | (data << 8);
- LOGREG("HW Cursor Address: %08x\n",s3.cursor_start_addr);
- break;
- case 0x4d:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data;
- LOGREG("HW Cursor Address: %08x\n",s3.cursor_start_addr);
- break;
-/*
-3d4h index 4Eh (R/W): CR4E HGC Pattern Disp Start X-Pixel Position
-bit 0-5 Pattern Display Start X-Pixel Position.
- */
- case 0x4e:
- s3.cursor_pattern_x = data;
- break;
-/*
-3d4h index 4Fh (R/W): CR4F HGC Pattern Disp Start Y-Pixel Position
-bit 0-5 Pattern Display Start Y-Pixel Position.
- */
- case 0x4f:
- 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);
- svga.bank_r = svga.bank_w;
- if((data & 0x30) != 0x00)
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x30) << 4);
- else
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr43 & 0x04) << 6);
- s3_define_video_mode();
- break;
- case 0x53:
- s3.cr53 = data;
- break;
-/*
-3d4h index 55h (R/W): Extended Video DAC Control Register (80x +)
-bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the
- RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs.
- If this field is 0, 3d4h index 43h bit 1 is active.
- 2 Enable General Input Port Read. If set DAC reads are disabled and the
- STRD strobe for reading the General Input Port is enabled for reading
- while DACRD is active, if clear DAC reads are enabled.
- 3 (928) Enable External SID Operation if set. If set video data is
- passed directly from the VRAMs to the DAC rather than through the
- VGA chip
- 4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11
- mode, if clear in MS-Windows mode
- 5 (80x,928) Hardware Cursor External Operation Mode. If set the two
- bits of cursor data ,is output on the HC[0-1] pins for the video DAC
- The SENS pin becomes HC1 and the MID2 pin becomes HC0.
- 6 ??
- 7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated.
- (864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri
- -stated if set
- */
- case 0x55:
- s3.extended_dac_ctrl = data;
- break;
-
- case 0x58:
- {
- const uint8_t old_size = s3virge.linear_address_size;
- const bool old_enable = s3virge.linear_address_enable;
- const bool size_changed = old_size != s3virge.linear_address_size;
-
- 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;
- }
-
- if ((s3virge.linear_address_enable != old_enable) || size_changed)
- {
- m_linear_config_changed_cb(s3virge.linear_address_enable);
- }
-
- LOGREG("CR58: write %02x\n", data);
- break;
- }
- case 0x59:
- {
- const uint32_t old_address = s3virge.linear_address;
- s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
-
- if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
- {
- m_linear_config_changed_cb(1);
- }
- break;
- }
- case 0x5a:
- {
- const uint32_t old_address = s3virge.linear_address;
- s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
-
- if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
- {
- m_linear_config_changed_cb(1);
- }
- 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
- index 0)
- 1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End
- register (3d4h index 1)
- 2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking
- register (3d4h index 2).
- 3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse
- is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or
- does it really extend by 64 ?
- 4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start
- Retrace register (3d4h index 4).
- 5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse
- is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or
- does it really extend by 32 ?
- 6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer
- Position register (3d4h index 3Bh)
- 7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant
- Termination register (3d4h index 5Fh).
-*/
- case 0x5d:
- vga.crtc.horz_total = (vga.crtc.horz_total & 0xfeff) | ((data & 0x01) << 8);
- vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0xfeff) | ((data & 0x02) << 7);
- vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xfeff) | ((data & 0x04) << 6);
- vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xffbf) | ((data & 0x08) << 3);
- vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xfeff) | ((data & 0x10) << 4);
- vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0xffdf) | (data & 0x20);
- s3_define_video_mode();
- break;
-/*
-3d4h index 5Eh (R/W): Extended Vertical Overflow Register (80x +)
-bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h
- index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5.
- 1 Vertical Display End bit 10. Bit 10 of the Vertical Display End
- register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1
- and 6
- 2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking
- register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9
- in 3d4h index 9 bit 5
- 4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace
- register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2
- and 7.
- 6 Line Compare Position bit 10. Bit 10 of the Line Compare register
- (3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h
- index 9 bit 6.
- */
- case 0x5e:
- vga.crtc.vert_total = (vga.crtc.vert_total & 0xfbff) | ((data & 0x01) << 10);
- vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0xfbff) | ((data & 0x02) << 9);
- vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0xfbff) | ((data & 0x04) << 8);
- vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0xfbff) | ((data & 0x10) << 6);
- vga.crtc.line_compare = (vga.crtc.line_compare & 0xfbff) | ((data & 0x40) << 4);
- s3_define_video_mode();
- break;
- case 0x67:
- s3.ext_misc_ctrl_2 = data;
- s3_define_video_mode();
- //printf("%02x X\n",data);
- break;
- case 0x68:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16);
- LOGREG("CR68: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x69:
- vga.crtc.start_addr_latch &= ~0x1f0000;
- vga.crtc.start_addr_latch |= ((data & 0x1f) << 16);
- s3_define_video_mode();
- break;
- case 0x6a:
- svga.bank_w = data & 0x3f;
- svga.bank_r = svga.bank_w;
- break;
- case 0x6f:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24);
- LOGREG("CR6F: Strapping data = %08x\n",s3.strapping);
- }
- break;
- default:
- LOGREG("S3: CR%02X write %02x\n",index,data);
- break;
- }
- }
-}
-
-
-uint8_t s3virge_vga_device::port_03b0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- res = s3_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- s3_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03b0_w(offset,data);
- break;
- }
- }
-}
-
-uint8_t s3virge_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t res;
-
- switch(offset)
- {
- default:
- res = s3_vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- default:
- s3_vga_device::port_03c0_w(offset,data);
- break;
- }
-}
-
-uint8_t s3virge_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = s3_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (get_crtc_port() == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- s3_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
-}
-
uint8_t s3virge_vga_device::mem_r(offs_t offset)
{
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
@@ -1099,7 +637,7 @@ uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uin
ret = 0xffffffff;
break;
default:
- popmessage("bus/isa/s3virge.cpp: Unimplemented ROP 0x%02x",rop);
+ popmessage("video/s3virge.cpp: Unimplemented ROP 0x%02x",rop);
}
return ret;
diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/video/s3virge.h
index ba2abd8cfd9..67eef830e71 100644
--- a/src/devices/bus/isa/s3virge.h
+++ b/src/devices/video/s3virge.h
@@ -24,12 +24,6 @@ public:
auto linear_config_changed() { return m_linear_config_changed_cb.bind(); }
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
virtual uint8_t mem_r(offs_t offset) override;
virtual void mem_w(offs_t offset, uint8_t data) override;
@@ -85,6 +79,8 @@ protected:
virtual void device_reset() override;
virtual uint16_t offset() override;
+ virtual void crtc_map(address_map &map) override;
+
enum
{
LAW_64K = 0,
@@ -197,6 +193,8 @@ protected:
devcb_write_line m_linear_config_changed_cb;
+ virtual void s3_define_video_mode(void) override;
+ // has no 8514/A device
private:
emu_timer* m_draw_timer;
void bitblt_step();
@@ -209,11 +207,6 @@ private:
void add_command(int cmd_type);
void command_start();
void command_finish();
-
- virtual uint8_t s3_crtc_reg_read(uint8_t index);
- virtual void s3_define_video_mode(void);
- virtual void s3_crtc_reg_write(uint8_t index, uint8_t data);
- // has no 8514/A device
};
diff --git a/src/devices/video/virge_pci.cpp b/src/devices/video/virge_pci.cpp
index 08f392a8e0d..cd5ea859a85 100644
--- a/src/devices/video/virge_pci.cpp
+++ b/src/devices/video/virge_pci.cpp
@@ -36,9 +36,7 @@ void virge_pci_device::mmio_map(address_map& map)
//map(0x1008220,0x1008227) DMA control
// MMIO address map
- map(0x10083b0,0x10083bf).rw(FUNC(virge_pci_device::vga_3b0_r), FUNC(virge_pci_device::vga_3b0_w));
- map(0x10083c0,0x10083df).rw(FUNC(virge_pci_device::vga_3c0_r), FUNC(virge_pci_device::vga_3c0_w));
- map(0x10083d0,0x10083df).rw(FUNC(virge_pci_device::vga_3d0_r), FUNC(virge_pci_device::vga_3d0_w));
+ map(0x10083b0,0x10083df).m(m_vga, FUNC(s3virge_vga_device::io_map));
map(0x1008504,0x1008507).rw(m_vga, FUNC(s3virge_vga_device::s3d_sub_status_r), FUNC(s3virge_vga_device::s3d_sub_control_w));
map(0x100850c,0x100850f).r(m_vga, FUNC(s3virge_vga_device::s3d_func_ctrl_r));
@@ -67,6 +65,11 @@ void virge_pci_device::config_map(address_map &map)
map(0x10, 0x13).rw(FUNC(virge_pci_device::base_address_r),FUNC(virge_pci_device::base_address_w));
}
+void virge_pci_device::legacy_io_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3virge_vga_device::io_map));
+}
+
void virge_pci_device::refresh_linear_window()
{
if(downcast<s3virge_vga_device *>(m_vga.target())->is_linear_address_active())
@@ -114,132 +117,10 @@ void virge_pci_device::base_address_w(offs_t offset, uint32_t data)
refresh_linear_window();
}
-uint32_t virge_pci_device::vga_3b0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03b0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void virge_pci_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- {
- downcast<s3_vga_device *>(m_vga.target())->port_03b0_w(offset * 4 + 0, data >> 0);
- 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(offset * 4 + 1, data >> 8);
- // TODO: make this more transparent
- // it shouldn't expose the S3 CRTC regs directly and don't repeat on 0x3d0 I/O below.
- if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3b0)
- {
- if (m_current_crtc_reg == 0x53)
- {
- refresh_linear_window();
- remap_cb();
- }
- else if(m_current_crtc_reg == 0x58)
- {
- refresh_linear_window();
- remap_cb();
- }
- else if(m_current_crtc_reg == 0x59 || m_current_crtc_reg == 0x5a)
- {
- refresh_linear_window();
- remap_cb();
- }
- }
- }
- if (ACCESSING_BITS_16_23)
- downcast<s3_vga_device *>(m_vga.target())->port_03b0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<s3_vga_device *>(m_vga.target())->port_03b0_w(offset * 4 + 3, data >> 24);
-}
-
-uint32_t virge_pci_device::vga_3c0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03c0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void virge_pci_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- if (ACCESSING_BITS_0_7)
- downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(offset * 4 + 0, data >> 0);
- if (ACCESSING_BITS_8_15)
- downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(offset * 4 + 1, data >> 8);
- if (ACCESSING_BITS_16_23)
- downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<s3_vga_device *>(m_vga.target())->port_03c0_w(offset * 4 + 3, data >> 24);
-}
-
-uint32_t virge_pci_device::vga_3d0_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t result = 0;
- if (ACCESSING_BITS_0_7)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(offset * 4 + 0) << 0;
- if (ACCESSING_BITS_8_15)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(offset * 4 + 1) << 8;
- if (ACCESSING_BITS_16_23)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(offset * 4 + 2) << 16;
- if (ACCESSING_BITS_24_31)
- result |= downcast<s3_vga_device *>(m_vga.target())->port_03d0_r(offset * 4 + 3) << 24;
- return result;
-}
-
-void virge_pci_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void virge_pci_device::linear_config_changed_w(int state)
{
- if (ACCESSING_BITS_0_7)
- {
- downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(offset * 4 + 0, data >> 0);
- 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(offset * 4 + 1, data >> 8);
- if(offset == 1 && downcast<s3virge_vga_device *>(m_vga.target())->get_crtc_port() == 0x3d0)
- {
- if (m_current_crtc_reg == 0x53)
- {
- refresh_linear_window();
- remap_cb();
- }
- else if(m_current_crtc_reg == 0x58)
- {
- refresh_linear_window();
- remap_cb();
- }
- else if(m_current_crtc_reg == 0x59 || m_current_crtc_reg == 0x5a)
- {
- refresh_linear_window();
- remap_cb();
- }
- }
- }
- if (ACCESSING_BITS_16_23)
- downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(offset * 4 + 2, data >> 16);
- if (ACCESSING_BITS_24_31)
- downcast<s3_vga_device *>(m_vga.target())->port_03d0_w(offset * 4 + 3, data >> 24);
+ refresh_linear_window();
+ remap_cb();
}
uint8_t virge_pci_device::vram_r(offs_t offset)
@@ -294,9 +175,7 @@ void virge_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_w
{
memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(virge_pci_device::vram_r)), write8sm_delegate(*this, FUNC(virge_pci_device::vram_w)));
- io_space->install_readwrite_handler(0x3b0, 0x3bf, read32s_delegate(*this, FUNC(virge_pci_device::vga_3b0_r)), write32s_delegate(*this, FUNC(virge_pci_device::vga_3b0_w)));
- io_space->install_readwrite_handler(0x3c0, 0x3cf, read32s_delegate(*this, FUNC(virge_pci_device::vga_3c0_r)), write32s_delegate(*this, FUNC(virge_pci_device::vga_3c0_w)));
- io_space->install_readwrite_handler(0x3d0, 0x3df, read32s_delegate(*this, FUNC(virge_pci_device::vga_3d0_r)), write32s_delegate(*this, FUNC(virge_pci_device::vga_3d0_w)));
+ io_space->install_device(0x03b0, 0x03df, *this, &virge_pci_device::legacy_io_map);
}
void virge_pci_device::device_add_mconfig(machine_config &config)
@@ -308,6 +187,7 @@ void virge_pci_device::device_add_mconfig(machine_config &config)
S3VIRGE(config, m_vga, 0);
m_vga->set_screen("screen");
m_vga->set_vram_size(0x400000);
+ m_vga->linear_config_changed().set(FUNC(virge_pci_device::linear_config_changed_w));
}
void virgedx_pci_device::device_add_mconfig(machine_config &config)
@@ -319,6 +199,7 @@ void virgedx_pci_device::device_add_mconfig(machine_config &config)
S3VIRGEDX(config, m_vga, 0);
m_vga->set_screen("screen");
m_vga->set_vram_size(0x400000);
+ m_vga->linear_config_changed().set(FUNC(virgedx_pci_device::linear_config_changed_w));
}
diff --git a/src/devices/video/virge_pci.h b/src/devices/video/virge_pci.h
index f4b6ce29009..51c902c871e 100644
--- a/src/devices/video/virge_pci.h
+++ b/src/devices/video/virge_pci.h
@@ -11,7 +11,7 @@
#pragma once
#include "machine/pci.h"
-#include "bus/isa/s3virge.h"
+#include "video/s3virge.h"
class virge_pci_device : public pci_device
{
@@ -37,17 +37,13 @@ public:
void lfb_map(address_map &map);
void mmio_map(address_map& map);
- uint32_t vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- uint32_t vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- uint32_t vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0);
- void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint8_t vram_r(offs_t offset);
void vram_w(offs_t offset, uint8_t data);
uint32_t base_address_r();
void base_address_w(offs_t offset, uint32_t data);
+ void legacy_io_map(address_map &map);
+
protected:
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
@@ -63,10 +59,10 @@ protected:
required_memory_region m_bios;
optional_device<screen_device> m_screen;
+ void linear_config_changed_w(int state);
+
private:
void refresh_linear_window();
-
- uint8_t m_current_crtc_reg;
};
class virgedx_pci_device : public virge_pci_device