diff options
author | 2023-07-04 19:10:46 +0200 | |
---|---|---|
committer | 2023-07-04 19:10:46 +0200 | |
commit | 498b7a0a7ddf138e83b79acbc159597587db3804 (patch) | |
tree | f0e56fee0f4c89734d4fb3c5eef64bf4b298c38b /src/devices | |
parent | 9013ece6ee4883037265626684d7d45803959dd2 (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')
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 |