From 9945ff79dea4bc681d61ae77d4de578e57554623 Mon Sep 17 00:00:00 2001 From: angelosa Date: Fri, 7 Jul 2023 23:32:01 +0200 Subject: video/pc_vga_paradise.cpp: preliminary WD90C00 implementation --- src/devices/bus/isa/isa_cards.cpp | 1 + src/devices/bus/isa/svga_paradise.cpp | 67 ++++++++++++++++-- src/devices/bus/isa/svga_paradise.h | 25 ++++++- src/devices/video/pc_vga_paradise.cpp | 126 +++++++++++++++++++++++++++------- src/devices/video/pc_vga_paradise.h | 29 ++++++-- 5 files changed, 213 insertions(+), 35 deletions(-) diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp index b8c9a2bf6f1..e00c27c395d 100644 --- a/src/devices/bus/isa/isa_cards.cpp +++ b/src/devices/bus/isa/isa_cards.cpp @@ -222,6 +222,7 @@ void pc_isa16_cards(device_slot_interface &device) // device.option_add("tgui9680",ISA16_SVGA_TGUI9680); device.option_add("pvga1a", ISA16_PVGA1A); device.option_add("pvga1a_jk", ISA16_PVGA1A_JK); + device.option_add("wd90c00_jk", ISA16_WD90C00_JK); device.option_add("3c505", ISA16_3C505); device.option_add("mach64", ISA16_SVGA_MACH64); device.option_add("sb16_lle", ISA16_SB16); diff --git a/src/devices/bus/isa/svga_paradise.cpp b/src/devices/bus/isa/svga_paradise.cpp index 99b81f51e59..4a6f4c789ac 100644 --- a/src/devices/bus/isa/svga_paradise.cpp +++ b/src/devices/bus/isa/svga_paradise.cpp @@ -1,12 +1,13 @@ // license:BSD-3-Clause -// copyright-holders:Angelo Salese +// copyright-holders: Angelo Salese /*************************************************************************** ISA SVGA Paradise / Western Digital wrapper TODO: - Add ISA8 and MCA variants for pvga1a_jk; -- Nokia NVGA2 doesn't boot; +- Nokia NVGA2, wd90c00_jk: they don't boot, accesses areas $c6000-$c7fff + that aren't covered in current dumps; ***************************************************************************/ @@ -15,9 +16,11 @@ TODO: #include "screen.h" -DEFINE_DEVICE_TYPE(ISA16_PVGA1A, isa16_pvga1a_device, "pvga1a", "Paradise Systems PVGA1A Graphics Card") -DEFINE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device, "pvga1a_jk", "Paradise Systems PVGA1A-JK Graphics Card") -DEFINE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device, "wd90c90_jk", "Western Digital WD90C90-JK Graphics Card") +// TODO: some of these are also ISA8 +DEFINE_DEVICE_TYPE(ISA16_PVGA1A, isa16_pvga1a_device, "pvga1a", "Paradise Systems PVGA1A Graphics Card") +DEFINE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device, "pvga1a_jk", "Paradise Systems PVGA1A-JK Graphics Card") +DEFINE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device, "wd90c90_jk", "Western Digital WD90C90-JK Graphics Card") +DEFINE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device, "wd90c00_jk", "Western Digital WD90C00-JK Graphics Card") isa16_pvga1a_device::isa16_pvga1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : @@ -98,8 +101,9 @@ ROM_START( pvga1a_jk ) // BIOS.BIN 1xxxxxxxxxxxxxxx = 0xFF ROMX_LOAD( "bios.bin", 0x000000, 0x08000, CRC(2bfe8adb) SHA1(afd8c33f24e28b025e43ae68d95fd6811659013b), ROM_BIOS(0) ) ROM_IGNORE( 0x8000 ) + // TODO: consider splitting if a good dump surfaces ROM_SYSTEM_BIOS(1, "nvga2", "Nokia NVGA2") - ROMX_LOAD( "nokia.vbi", 0x000000, 0x06000, CRC(9f430ae7) SHA1(3d37b86853347d43ebc85a7e92e4a609b13406bb), ROM_BIOS(1) ) + ROMX_LOAD( "nokia.vbi", 0x000000, 0x06000, BAD_DUMP CRC(9f430ae7) SHA1(3d37b86853347d43ebc85a7e92e4a609b13406bb), ROM_BIOS(1) ) ROM_END const tiny_rom_entry *isa16_pvga1a_jk_device::device_rom_region() const @@ -186,3 +190,54 @@ void isa8_wd90c90_jk_device::device_start() m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_w))); m_isa->install_device(0x03b0, 0x03df, *this, &isa8_wd90c90_jk_device::io_isa_map); } + +/****************** + * + * WD90C00-JK + * + *****************/ + +isa16_wd90c00_jk_device::isa16_wd90c00_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, ISA16_WD90C00_JK, tag, owner, clock), + device_isa16_card_interface(mconfig, *this), + m_vga(*this, "vga") +{ +} + +ROM_START( wd90c00_jk ) + ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00) + ROM_SYSTEM_BIOS(0, "wd90c00_jk", "Western Digital WD90C00-JK") + ROMX_LOAD( "90c00jk-lh6673.vbi", 0x000000, 0x006000, BAD_DUMP CRC(595eda15) SHA1(a3d4a978f30a0669bcb4a74ce196fd7a798d456f), ROM_BIOS(0) ) +ROM_END + +const tiny_rom_entry *isa16_wd90c00_jk_device::device_rom_region() const +{ + return ROM_NAME( wd90c00_jk ); +} + +void isa16_wd90c00_jk_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480); + screen.set_screen_update("vga", FUNC(wd90c00_vga_device::screen_update)); + + WD90C00(config, m_vga, 0); + m_vga->set_screen("screen"); + // 256kB to 1MB + m_vga->set_vram_size(0x100000); +} + +void isa16_wd90c00_jk_device::io_isa_map(address_map &map) +{ + map(0x00, 0x2f).m(m_vga, FUNC(wd90c00_vga_device::io_map)); +} + +void isa16_wd90c00_jk_device::device_start() +{ + set_isa_device(); + + m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom"); + + m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_w))); + m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c00_jk_device::io_isa_map); +} diff --git a/src/devices/bus/isa/svga_paradise.h b/src/devices/bus/isa/svga_paradise.h index d5e96924ff4..9277e241fa6 100644 --- a/src/devices/bus/isa/svga_paradise.h +++ b/src/devices/bus/isa/svga_paradise.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Angelo Salese +// copyright-holders: Angelo Salese #ifndef MAME_BUS_ISA_SVGA_PARADISE_H #define MAME_BUS_ISA_SVGA_PARADISE_H @@ -79,9 +79,32 @@ private: required_device m_vga; }; +class isa16_wd90c00_jk_device : + public device_t, + public device_isa16_card_interface +{ +public: + // construction/destruction + isa16_wd90c00_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + + // optional information overrides + 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 m_vga; +}; + // device type definition DECLARE_DEVICE_TYPE(ISA16_PVGA1A, isa16_pvga1a_device) DECLARE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device) DECLARE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device) +DECLARE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device) #endif // MAME_BUS_ISA_SVGA_PARADISE_H diff --git a/src/devices/video/pc_vga_paradise.cpp b/src/devices/video/pc_vga_paradise.cpp index 5b66743bfa0..d4f1fe743b6 100644 --- a/src/devices/video/pc_vga_paradise.cpp +++ b/src/devices/video/pc_vga_paradise.cpp @@ -4,10 +4,11 @@ Paradise / Western Digital (S)VGA chipsets -TODO: -- stub, (S?)VGA features not yet implemented; +- PVGA1A - PVGA1A-JK / WD90C90-JK (same as PVGA1A with extra connectors?) -- WD90C00-JK + +TODO: +- Complete WD90C00-JK - WD90C11-LR / WD90C11A-LR - WD90C30-LR / WD90C31-LR / WD90C31-ZS / WD90C31A-LR / WD90C31A-ZS - WD90C33-ZZ @@ -15,6 +16,9 @@ TODO: - WD90C26A (apple/macpwrbk030.cpp macpb180c, no ISA) - WD9710-MZ (PCI + MPEG-1, a.k.a. Pipeline 9710 / 9712) +- Memory Data pins (MD) & CNF +- /EBROM signal (for enabling ROM readback) + **************************************************************************************************/ #include "emu.h" @@ -34,10 +38,16 @@ TODO: DEFINE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device, "pvga1a_vga", "Paradise Systems PVGA1A") +DEFINE_DEVICE_TYPE(WD90C00, wd90c00_vga_device, "wd90c00_vga", "Western Digital WD90C00 VGA Controller") + +pvga1a_vga_device::pvga1a_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_ext_gc_view(*this, "ext_gc_view") +{ +} pvga1a_vga_device::pvga1a_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : svga_device(mconfig, PVGA1A, tag, owner, clock) - , m_ext_view(*this, "ext_view") + : pvga1a_vga_device(mconfig, PVGA1A, tag, owner, clock) { m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(pvga1a_vga_device::gc_map), this)); } @@ -60,11 +70,11 @@ void pvga1a_vga_device::device_reset() svga_device::device_reset(); m_memory_size = 0; - m_video_control = 0; // &= 0x8; + m_video_control = 0; // Really &= 0x8; at POR according to docs m_video_select = 0; m_crtc_lock = 0; - m_ext_unlock = false; - m_ext_view.select(0); + m_ext_gc_unlock = false; + m_ext_gc_view.select(0); } uint8_t pvga1a_vga_device::mem_r(offs_t offset) @@ -77,6 +87,7 @@ uint8_t pvga1a_vga_device::mem_r(offs_t offset) void pvga1a_vga_device::mem_w(offs_t offset, uint8_t data) { // TODO: Address Offset B, not extensively tested + // Should also enable thru bits 5-4 of PR1 but instead SW seems to use 7-6!? if (svga.rgb8_en) { svga_device::mem_linear_w(offset + (svga.bank_w * 0x1000), data); @@ -88,19 +99,19 @@ void pvga1a_vga_device::mem_w(offs_t offset, uint8_t data) void pvga1a_vga_device::gc_map(address_map &map) { svga_device::gc_map(map); - map(0x09, 0x0e).view(m_ext_view); - m_ext_view[0](0x09, 0x0e).lr8( + map(0x09, 0x0e).view(m_ext_gc_view); + m_ext_gc_view[0](0x09, 0x0e).lr8( NAME([this] (offs_t offset) { LOGLOCKED("Attempt to R ext. register offset %02x while locked\n", offset + 9); - return 0; + return 0xff; }) ); - m_ext_view[1](0x09, 0x0a).rw(FUNC(pvga1a_vga_device::address_offset_r), FUNC(pvga1a_vga_device::address_offset_w)); - m_ext_view[1](0x0b, 0x0b).rw(FUNC(pvga1a_vga_device::memory_size_r), FUNC(pvga1a_vga_device::memory_size_w)); - m_ext_view[1](0x0c, 0x0c).rw(FUNC(pvga1a_vga_device::video_select_r), FUNC(pvga1a_vga_device::video_select_w)); - m_ext_view[1](0x0d, 0x0d).rw(FUNC(pvga1a_vga_device::crtc_lock_r), FUNC(pvga1a_vga_device::crtc_lock_w)); - m_ext_view[1](0x0e, 0x0e).rw(FUNC(pvga1a_vga_device::video_control_r), FUNC(pvga1a_vga_device::video_control_w)); - map(0x0f, 0x0f).rw(FUNC(pvga1a_vga_device::ext_status_r), FUNC(pvga1a_vga_device::ext_unlock_w)); + m_ext_gc_view[1](0x09, 0x0a).rw(FUNC(pvga1a_vga_device::address_offset_r), FUNC(pvga1a_vga_device::address_offset_w)); + m_ext_gc_view[1](0x0b, 0x0b).rw(FUNC(pvga1a_vga_device::memory_size_r), FUNC(pvga1a_vga_device::memory_size_w)); + m_ext_gc_view[1](0x0c, 0x0c).rw(FUNC(pvga1a_vga_device::video_select_r), FUNC(pvga1a_vga_device::video_select_w)); + m_ext_gc_view[1](0x0d, 0x0d).rw(FUNC(pvga1a_vga_device::crtc_lock_r), FUNC(pvga1a_vga_device::crtc_lock_w)); + m_ext_gc_view[1](0x0e, 0x0e).rw(FUNC(pvga1a_vga_device::video_control_r), FUNC(pvga1a_vga_device::video_control_w)); + map(0x0f, 0x0f).rw(FUNC(pvga1a_vga_device::ext_gc_status_r), FUNC(pvga1a_vga_device::ext_gc_unlock_w)); } /* @@ -160,7 +171,6 @@ void pvga1a_vga_device::memory_size_w(offs_t offset, u8 data) m_memory_size = data; } -// m_ext_view[1](0x0d, 0x0d) PR3 CRT Control [locks groups in CRTC] /* * [0x0c] PR2 Video Select * @@ -244,14 +254,82 @@ void pvga1a_vga_device::video_control_w(offs_t offset, u8 data) * ---- -xxx lock register * ---- -101 unlock, any other value locks r/w to the extensions */ -u8 pvga1a_vga_device::ext_status_r(offs_t offset) +u8 pvga1a_vga_device::ext_gc_status_r(offs_t offset) +{ + return m_ext_gc_unlock ? 0x05 : 0x00; +} + +void pvga1a_vga_device::ext_gc_unlock_w(offs_t offset, u8 data) +{ + m_ext_gc_unlock = (data & 0x7) == 5; + LOGLOCKED("PR5 %s state (%02x)\n", m_ext_gc_unlock ? "unlock" : "lock", data); + m_ext_gc_view.select(m_ext_gc_unlock); +} + +/************************************** + * + * Western Digital WD90C00 + * + *************************************/ + +wd90c00_vga_device::wd90c00_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : pvga1a_vga_device(mconfig, WD90C00, tag, owner, clock) + , m_ext_crtc_view(*this, "ext_crtc_view") +{ + m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(wd90c00_vga_device::crtc_map), this)); + m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(wd90c00_vga_device::gc_map), this)); +} + +void wd90c00_vga_device::device_reset() +{ + pvga1a_vga_device::device_reset(); + + m_pr10_scratch = 0; + m_ext_crtc_write_unlock = false; + m_ext_crtc_view.select(0); +} + +void wd90c00_vga_device::crtc_map(address_map &map) +{ + pvga1a_vga_device::crtc_map(map); + map(0x29, 0x29).rw(FUNC(wd90c00_vga_device::ext_crtc_status_r), FUNC(wd90c00_vga_device::ext_crtc_unlock_w)); + map(0x2a, 0x3f).view(m_ext_crtc_view); + m_ext_crtc_view[0](0x2a, 0x3f).lr8( + NAME([this] (offs_t offset) { + LOGLOCKED("Attempt to R ext. register offset %02x while locked\n", offset + 0x2a); + return 0xff; + }) + ); +// m_ext_crtc_view[1](0x2a, 0x2a) PR11 EGA Switches + m_ext_crtc_view[1](0x2b, 0x2b).ram(); // PR12 scratch pad +// m_ext_crtc_view[1](0x2c, 0x2c) PR13 Interlace H/2 Start +// m_ext_crtc_view[1](0x2d, 0x2d) PR14 Interlace H/2 End +// m_ext_crtc_view[1](0x2e, 0x2e) PR15 Misc Control 1 +// m_ext_crtc_view[1](0x2f, 0x2f) PR16 Misc Control 2 +// m_ext_crtc_view[1](0x30, 0x30) PR17 Misc Control 3 +// m_ext_crtc_view[1](0x31, 0x3f) +} + +/* + * [0x29] PR10 Unlock PR11/PR17 + * + * x--- x--- Read lock + * 1--- 0--- Unlocks, any other write locks reading + * -xxx ---- Scratch Pad + * ---- -xxx Write lock + * ---- -101 Unlocks, any other write locks writing + */ +u8 wd90c00_vga_device::ext_crtc_status_r(offs_t offset) { - return m_ext_unlock ? 0x05 : 0x00; + return m_pr10_scratch | (m_ext_crtc_write_unlock ? 0x05 : 0x00); } -void pvga1a_vga_device::ext_unlock_w(offs_t offset, u8 data) +void wd90c00_vga_device::ext_crtc_unlock_w(offs_t offset, u8 data) { - m_ext_unlock = (data & 0x7) == 5; - LOGLOCKED("PR5 %s state (%02x)\n", m_ext_unlock ? "unlock" : "lock", data); - m_ext_view.select(m_ext_unlock); + m_ext_crtc_write_unlock = (data & 0x7) == 5; + LOGLOCKED("PR10 %s state (%02x)\n", m_ext_crtc_write_unlock ? "unlock" : "lock", data); + // TODO: read unlock + //m_ext_crtc_read_unlock = (data & 0x88) == 0x80; + m_ext_crtc_view.select(m_ext_crtc_write_unlock); + m_pr10_scratch = data & 0x70; } diff --git a/src/devices/video/pc_vga_paradise.h b/src/devices/video/pc_vga_paradise.h index d4ec7cc44d2..5ebf022c312 100644 --- a/src/devices/video/pc_vga_paradise.h +++ b/src/devices/video/pc_vga_paradise.h @@ -18,11 +18,13 @@ public: virtual uint8_t mem_r(offs_t offset) override; virtual void mem_w(offs_t offset, uint8_t data) override; protected: + pvga1a_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + virtual void device_start() override; virtual void device_reset() override; virtual void gc_map(address_map &map) override; - memory_view m_ext_view; + memory_view m_ext_gc_view; private: u8 address_offset_r(offs_t offset); void address_offset_w(offs_t offset, u8 data); @@ -34,16 +36,35 @@ private: void crtc_lock_w(offs_t offset, u8 data); u8 video_control_r(offs_t offset); void video_control_w(offs_t offset, u8 data); - u8 ext_status_r(offs_t offset); - void ext_unlock_w(offs_t offset, u8 data); + u8 ext_gc_status_r(offs_t offset); + void ext_gc_unlock_w(offs_t offset, u8 data); u8 m_memory_size = 0; u8 m_video_control = 0; - bool m_ext_unlock = false; + bool m_ext_gc_unlock = false; u8 m_video_select = 0; u8 m_crtc_lock = 0; }; +class wd90c00_vga_device : public pvga1a_vga_device +{ +public: + wd90c00_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void crtc_map(address_map &map) override; + virtual void device_reset() override; + + memory_view m_ext_crtc_view; +private: + u8 ext_crtc_status_r(offs_t offset); + void ext_crtc_unlock_w(offs_t offset, u8 data); + + bool m_ext_crtc_write_unlock = false; + u8 m_pr10_scratch = 0; +}; + DECLARE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device) +DECLARE_DEVICE_TYPE(WD90C00, wd90c00_vga_device) #endif // MAME_VIDEO_PC_VGA_PARADISE_H -- cgit v1.2.3