video/pc_vga_paradise.cpp: add basic extended GC interface

This commit is contained in:
angelosa 2023-07-07 01:15:19 +02:00
parent 3868cf5d69
commit 77cc71b932
2 changed files with 223 additions and 4 deletions

View File

@ -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);
}

View File

@ -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)