From 77cc71b9329f006c17cc90dc6517f55190d90bc6 Mon Sep 17 00:00:00 2001 From: angelosa Date: Fri, 7 Jul 2023 01:15:19 +0200 Subject: [PATCH] video/pc_vga_paradise.cpp: add basic extended GC interface --- src/devices/video/pc_vga_paradise.cpp | 203 +++++++++++++++++++++++++- src/devices/video/pc_vga_paradise.h | 24 +++ 2 files changed, 223 insertions(+), 4 deletions(-) diff --git a/src/devices/video/pc_vga_paradise.cpp b/src/devices/video/pc_vga_paradise.cpp index c026faf6ebe..5b66743bfa0 100644 --- a/src/devices/video/pc_vga_paradise.cpp +++ b/src/devices/video/pc_vga_paradise.cpp @@ -22,14 +22,22 @@ TODO: #include "screen.h" -#define VERBOSE (LOG_GENERAL) +#define LOG_BANK (1U << 2) // log banking r/ws +#define LOG_LOCKED (1U << 8) // log locking mechanism + +#define VERBOSE (LOG_GENERAL | LOG_LOCKED) //#define LOG_OUTPUT_FUNC osd_printf_info #include "logmacro.h" +#define LOGBANK(...) LOGMASKED(LOG_BANK, __VA_ARGS__) +#define LOGLOCKED(...) LOGMASKED(LOG_LOCKED, __VA_ARGS__) + + DEFINE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device, "pvga1a_vga", "Paradise Systems PVGA1A") 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") { m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(pvga1a_vga_device::gc_map), this)); } @@ -51,12 +59,199 @@ void pvga1a_vga_device::device_reset() { svga_device::device_reset(); - // ... + m_memory_size = 0; + m_video_control = 0; // &= 0x8; + m_video_select = 0; + m_crtc_lock = 0; + m_ext_unlock = false; + m_ext_view.select(0); +} + +uint8_t pvga1a_vga_device::mem_r(offs_t offset) +{ + if (svga.rgb8_en) + return svga_device::mem_linear_r(offset + (svga.bank_w * 0x1000)); + return svga_device::mem_r(offset); +} + +void pvga1a_vga_device::mem_w(offs_t offset, uint8_t data) +{ + // TODO: Address Offset B, not extensively tested + if (svga.rgb8_en) + { + svga_device::mem_linear_w(offset + (svga.bank_w * 0x1000), data); + return; + } + svga_device::mem_w(offset, data); } void pvga1a_vga_device::gc_map(address_map &map) { svga_device::gc_map(map); - // TODO: temp hack so the card boots - map(0x09, 0x0f).ram(); + map(0x09, 0x0e).view(m_ext_view); + m_ext_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; + }) + ); + 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)); +} + +/* + * [0x09] PR0A Address Offset A + * [0x0a] PR0B Address Offset B + * + * -xxx xxxx bank selects, in 4KB units + */ +u8 pvga1a_vga_device::address_offset_r(offs_t offset) +{ + if (!offset) + { + LOGBANK("PR0A read Address Offset A\n"); + return svga.bank_w & 0x7f; + } + // Address Offset B, TBD + LOGBANK("PR0A read Address Offset B\n"); + return 0; +} + +void pvga1a_vga_device::address_offset_w(offs_t offset, u8 data) +{ + if (!offset) + { + LOG("PR0A write Address Offset A %02x\n", data); + svga.bank_w = data & 0x7f; + } + else + { + LOG("PR0B write Address Offset B %02x\n", data); + // ... + } +} + +/* + * [0x0b] PR1 Memory Size + * + * xx-- ---- Memory Size + * 11-- ---- 1MB + * 10-- ---- 512KB + * 0x-- ---- 256KB + * --xx ---- Memory Map Select + * ---- x--- Enable PR0B + * ---- -x-- Enable 16-bit memory bus + * ---- --x- Enable 16-bit BIOS ROM reads (MD1) + * ---- ---x BIOS ROM mapped (MD0) + */ +u8 pvga1a_vga_device::memory_size_r(offs_t offset) +{ + LOG("PR1 Memory Size R\n"); + return 0xc0 | (m_memory_size & 0x3f); +} + +void pvga1a_vga_device::memory_size_w(offs_t offset, u8 data) +{ + LOG("PR1 Memory Size W %02x\n", data); + m_memory_size = data; +} + +// m_ext_view[1](0x0d, 0x0d) PR3 CRT Control [locks groups in CRTC] +/* + * [0x0c] PR2 Video Select + * + * x--- ---- M24 Mode Enable + * -x-- ---- 6845 Compatiblity Mode + * --x- -x-- Character Map Select + * ---- -1-- \- also enables special underline effect (?) + * ---x x--- Character Clock Period Control + * ---0 0--- VGA 8/9 dots + * ---0 1--- 7 dots + * ---1 0--- 9 dots + * ---1 1--- 10 dots + * ---- --x- external clock select 3 + * ---- ---x Set horizontal sync timing (0) doubled? + */ +u8 pvga1a_vga_device::video_select_r(offs_t offset) +{ + LOG("PR2 Video Select R\n"); + return m_video_select; +} + +void pvga1a_vga_device::video_select_w(offs_t offset, u8 data) +{ + LOG("PR2 Video Select W %02x\n", data); + m_video_select = data; +} + +/* + * [0x0d] PR3 CRT Control [locks groups in CRTC] + * + * x--- ---- Lock VSYNC polarity + * -x-- ---- Lock HSYNC polarity + * --x- ---- Lock horizontal timing (group 0 & 4) + * ---x ---- bit 9 of CRTC Start Memory Address + * ---- x--- bit 8 of CRTC Start Memory Address + * ---- -x-- CRT Control cursor start, cursor stop, preset row scan, maximum scan line x2 (??) + * ---- --x- Lock vertical display enable end (group 1) + * ---- ---x Lock vertical total/retrace (group 2 & 3) + */ +u8 pvga1a_vga_device::crtc_lock_r(offs_t offset) +{ + LOG("PR3 CRTC lock R\n"); + return m_crtc_lock; +} + +void pvga1a_vga_device::crtc_lock_w(offs_t offset, u8 data) +{ + LOG("PR3 CRTC lock W\n", data); + m_crtc_lock = data; +} + +/* + * [0x0e] PR4 Video Control + * + * x--- ---- BLNKN (0) enables external Video DAC + * -x-- ---- Tristate HSYNC, VSYNC, BLNKN + * --x- ---- Tristate VID7-VID0 + * ---x ---- Tristate Memory Control outputs + * ---- x--- Disable CGA (unaffected by POR) + * ---- -x-- Lock palette and overscan regs + * ---- --x- Enable EGA compatible mode + * ---- ---x Enable 640x400x8bpp + */ +u8 pvga1a_vga_device::video_control_r(offs_t offset) +{ + LOG("PR4 Video Control R\n"); + return m_video_control; +} + +void pvga1a_vga_device::video_control_w(offs_t offset, u8 data) +{ + LOG("PR4 Video Control W %02x\n", data); + m_video_control = data; + svga.rgb8_en = BIT(data, 0); +} + +/* + * [0x0f] PR5 Lock/Status + * + * xxxx ---- MD7/MD4 config reads + * ---- -xxx lock register + * ---- -101 unlock, any other value locks r/w to the extensions + */ +u8 pvga1a_vga_device::ext_status_r(offs_t offset) +{ + return m_ext_unlock ? 0x05 : 0x00; +} + +void pvga1a_vga_device::ext_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); } diff --git a/src/devices/video/pc_vga_paradise.h b/src/devices/video/pc_vga_paradise.h index c6782779c2d..d4ec7cc44d2 100644 --- a/src/devices/video/pc_vga_paradise.h +++ b/src/devices/video/pc_vga_paradise.h @@ -11,13 +11,37 @@ class pvga1a_vga_device : public svga_device { public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + pvga1a_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; protected: virtual void device_start() override; virtual void device_reset() override; virtual void gc_map(address_map &map) override; + memory_view m_ext_view; +private: + u8 address_offset_r(offs_t offset); + void address_offset_w(offs_t offset, u8 data); + u8 memory_size_r(offs_t offset); + void memory_size_w(offs_t offset, u8 data); + u8 video_select_r(offs_t offset); + void video_select_w(offs_t offset, u8 data); + u8 crtc_lock_r(offs_t offset); + 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 m_memory_size = 0; + u8 m_video_control = 0; + bool m_ext_unlock = false; + u8 m_video_select = 0; + u8 m_crtc_lock = 0; }; DECLARE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device)