mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
video/pc_vga_matrox.cpp: implement RAMDAC extended indexed mechanism, add basic SVGA mode switcher
This commit is contained in:
parent
8368a3da29
commit
449f468204
2 changed files with 198 additions and 27 deletions
|
@ -13,12 +13,15 @@ matrox_vga_device::matrox_vga_device(const machine_config &mconfig, const char *
|
|||
// 3 bits of address space?
|
||||
m_crtcext_space_config = address_space_config("crtcext_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(matrox_vga_device::crtcext_map), this));
|
||||
// TODO: docs mentions using 0x22 / 0x24 / 0x26 for regular CRTC (coming from plain VGA?)
|
||||
|
||||
m_ramdac_indexed_space_config = address_space_config("ramdac_indexed_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(matrox_vga_device::ramdac_indexed_map), this));
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector matrox_vga_device::memory_space_config() const
|
||||
{
|
||||
auto r = svga_device::memory_space_config();
|
||||
r.emplace_back(std::make_pair(EXT_REG, &m_crtcext_space_config));
|
||||
r.emplace_back(std::make_pair(EXT_REG, &m_crtcext_space_config));
|
||||
r.emplace_back(std::make_pair(EXT_REG + 1, &m_ramdac_indexed_space_config));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -27,6 +30,10 @@ void matrox_vga_device::device_reset()
|
|||
svga_device::device_reset();
|
||||
|
||||
m_crtcext_index = 0;
|
||||
m_crtcext_misc = 0;
|
||||
m_mgamode = false;
|
||||
m_truecolor_ctrl = 0x80;
|
||||
m_multiplex_ctrl = 0x98;
|
||||
}
|
||||
|
||||
void matrox_vga_device::io_3bx_3dx_map(address_map &map)
|
||||
|
@ -56,7 +63,7 @@ void matrox_vga_device::crtcext_map(address_map &map)
|
|||
// map(0x00, 0x00) Address Generator Extensions
|
||||
// map(0x01, 0x01) Horizontal Counter Extensions
|
||||
// map(0x02, 0x02) Vertical Counter Extensions
|
||||
// map(0x03, 0x03) Miscellaneous
|
||||
map(0x03, 0x03).rw(FUNC(matrox_vga_device::crtcext3_misc_r), FUNC(matrox_vga_device::crtcext3_misc_w));
|
||||
// CRTCEXT4 Memory Page register
|
||||
map(0x04, 0x04).lrw8(
|
||||
NAME([this] (offs_t offset) { return svga.bank_w & 0x7f; }),
|
||||
|
@ -68,53 +75,198 @@ void matrox_vga_device::crtcext_map(address_map &map)
|
|||
// seems to disable SVGA drawing -> diagnostic check?
|
||||
}
|
||||
|
||||
/*
|
||||
* CRTCEXT3 Miscellaneous
|
||||
*
|
||||
* x--- ---- MGA mode (SVGA and accelerated modes)
|
||||
* -x-- ---- CSYNCEN
|
||||
* --x- ---- SLOW256 disables HW acceleration if '1' for VGA mode 13h
|
||||
* ---x x--- VIDDELAY delay for CRTC signals, depends on RAM configuration
|
||||
* ---0 0--- 4MB board
|
||||
* ---0 1--- 2MB board
|
||||
* ---1 x--- 8MB board
|
||||
* ---- -xxx SCALE dot clock scaling factor
|
||||
* ---- -000 /1
|
||||
* ---- -001 /2
|
||||
* ---- -010 /3
|
||||
* ---- -011 /4
|
||||
* ---- -100 <reserved>
|
||||
* ---- -101 /6
|
||||
* ---- -110 <reserved>
|
||||
* ---- -111 /8
|
||||
*/
|
||||
u8 matrox_vga_device::crtcext3_misc_r()
|
||||
{
|
||||
return m_crtcext_misc;
|
||||
}
|
||||
|
||||
void matrox_vga_device::crtcext3_misc_w(offs_t offset, u8 data)
|
||||
{
|
||||
logerror("CRTCEXT3: %02x\n", data);
|
||||
m_crtcext_misc = data;
|
||||
m_mgamode = bool(BIT(data, 7));
|
||||
}
|
||||
|
||||
// RAMDAC
|
||||
// - paired with a Texas Instruments TVP3026 here -> a superset of INMOS IMSG176/IMSG178
|
||||
// - integrated with a superset in G400 at least
|
||||
void matrox_vga_device::ramdac_ext_map(address_map &map)
|
||||
{
|
||||
// map(0x00, 0x00).rw(FUNC(matrox_vga_device::ramdac_write_index_r), FUNC(matrox_vga_device::ramdac_write_index_w));
|
||||
// map(0x01, 0x01).rw(FUNC(matrox_vga_device::ramdac_data_r), FUNC(matrox_vga_device::ramdac_data_w));
|
||||
// map(0x02, 0x02).rw(FUNC(matrox_vga_device::ramdac_mask_r), FUNC(matrox_vga_device::ramdac_mask_w));
|
||||
// map(0x03, 0x03).rw(FUNC(matrox_vga_device::ramdac_read_index_r), FUNC(matrox_vga_device::ramdac_read_index_w));
|
||||
// map(0x04, 0x04) Cursor/Overscan Color Write Index
|
||||
// map(0x05, 0x05) Cursor/Overscan Color data
|
||||
// map(0x07, 0x07) Cursor/Overscan Color Read Index
|
||||
// map(0x09, 0x09) Direct Cursor control
|
||||
// map(0x00, 0x00).rw(FUNC(matrox_vga_device::ramdac_write_index_r), FUNC(matrox_vga_device::ramdac_write_index_w));
|
||||
// map(0x01, 0x01).rw(FUNC(matrox_vga_device::ramdac_data_r), FUNC(matrox_vga_device::ramdac_data_w));
|
||||
// map(0x02, 0x02).rw(FUNC(matrox_vga_device::ramdac_mask_r), FUNC(matrox_vga_device::ramdac_mask_w));
|
||||
// map(0x03, 0x03).rw(FUNC(matrox_vga_device::ramdac_read_index_r), FUNC(matrox_vga_device::ramdac_read_index_w));
|
||||
// map(0x04, 0x04) Cursor/Overscan Color Write Index
|
||||
// map(0x05, 0x05) Cursor/Overscan Color data
|
||||
// map(0x07, 0x07) Cursor/Overscan Color Read Index
|
||||
// map(0x09, 0x09) Direct Cursor control
|
||||
map(0x0a, 0x0a).rw(FUNC(matrox_vga_device::ramdac_ext_indexed_r), FUNC(matrox_vga_device::ramdac_ext_indexed_w));
|
||||
// map(0x0b, 0x0b) Cursor RAM data
|
||||
// map(0x0c, 0x0f) Cursor X/Y positions
|
||||
// map(0x10, 0x1f) <reserved>
|
||||
// map(0x0b, 0x0b) Cursor RAM data
|
||||
// map(0x0c, 0x0f) Cursor X/Y positions
|
||||
// map(0x10, 0x1f) <reserved>
|
||||
}
|
||||
|
||||
u8 matrox_vga_device::ramdac_ext_indexed_r()
|
||||
{
|
||||
// Unclear from the docs, according to usage seems to be the write index with no autoincrement
|
||||
logerror("RAMDAC ext read [%02x]++\n", vga.dac.write_index);
|
||||
return m_ramdac_mode;
|
||||
logerror("RAMDAC ext read [%02x]\n", vga.dac.write_index);
|
||||
return space(EXT_REG + 1).read_byte(vga.dac.write_index);
|
||||
;
|
||||
}
|
||||
|
||||
void matrox_vga_device::ramdac_ext_indexed_w(offs_t offset, u8 data)
|
||||
{
|
||||
// TODO: really uses the palette write index, cheating for now
|
||||
m_ramdac_mode = data;
|
||||
logerror("RAMDAC ext [%02x]++ %02x\n", vga.dac.write_index, data);
|
||||
if (!machine().side_effects_disabled())
|
||||
vga.dac.write_index ++;
|
||||
svga.rgb16_en = (data & 0xf8) == 0xf0;
|
||||
logerror("RAMDAC ext [%02x] %02x\n", vga.dac.write_index, data);
|
||||
space(EXT_REG + 1).write_byte(vga.dac.write_index, data);
|
||||
}
|
||||
|
||||
void matrox_vga_device::ramdac_indexed_map(address_map &map)
|
||||
{
|
||||
map(0x18, 0x18).rw(FUNC(matrox_vga_device::truecolor_ctrl_r), FUNC(matrox_vga_device::truecolor_ctrl_w));
|
||||
map(0x19, 0x19).rw(FUNC(matrox_vga_device::multiplex_ctrl_r), FUNC(matrox_vga_device::multiplex_ctrl_w));
|
||||
}
|
||||
|
||||
u8 matrox_vga_device::truecolor_ctrl_r()
|
||||
{
|
||||
return m_truecolor_ctrl;
|
||||
}
|
||||
|
||||
void matrox_vga_device::truecolor_ctrl_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_truecolor_ctrl = data;
|
||||
flush_true_color_mode();
|
||||
}
|
||||
|
||||
u8 matrox_vga_device::multiplex_ctrl_r()
|
||||
{
|
||||
return m_multiplex_ctrl;
|
||||
}
|
||||
|
||||
void matrox_vga_device::multiplex_ctrl_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_multiplex_ctrl = data;
|
||||
flush_true_color_mode();
|
||||
}
|
||||
|
||||
void matrox_vga_device::flush_true_color_mode()
|
||||
{
|
||||
logerror("New video mode %02x %02x\n", m_truecolor_ctrl, m_multiplex_ctrl);
|
||||
svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = svga.rgb32_en = 0;
|
||||
if (m_truecolor_ctrl == 0x80 && m_multiplex_ctrl == 0x98)
|
||||
{
|
||||
logerror("\tVGA mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(m_truecolor_ctrl)
|
||||
{
|
||||
case 0x80:
|
||||
if (m_multiplex_ctrl >= 0x49 && m_multiplex_ctrl <= 0x4c)
|
||||
{
|
||||
logerror("\tSVGA 8-bit mode\n");
|
||||
svga.rgb8_en = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// [0x41, 0x42, 0x43, 0x44] for normal
|
||||
// [0x61, 0x62, 0x63, 0x64] for nibble swapped
|
||||
popmessage("TVP3026: Unemulated 4-bit %s with multiplex: %02x"
|
||||
, m_multiplex_ctrl & 0x20 ? "normal" : "nibble swapped"
|
||||
, m_multiplex_ctrl
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
case 0x1e:
|
||||
case 0x56:
|
||||
case 0x5e:
|
||||
if (m_multiplex_ctrl == 0x5b || m_multiplex_ctrl == 0x5c)
|
||||
{
|
||||
logerror("\tRGB 8-8-8 mode\n");
|
||||
svga.rgb24_en = 1;
|
||||
}
|
||||
break;
|
||||
case 0x17:
|
||||
case 0x1f:
|
||||
case 0x57:
|
||||
case 0x5f:
|
||||
if (m_multiplex_ctrl == 0x5b || m_multiplex_ctrl == 0x5c)
|
||||
popmessage("TVP3026: Unemulated BGR 8-8-8 mode");
|
||||
break;
|
||||
case 0x06:
|
||||
case 0x46:
|
||||
if (m_multiplex_ctrl == 0x5b || m_multiplex_ctrl == 0x5c)
|
||||
{
|
||||
logerror("\t%cRGB 8-8-8-8 mode\n", m_truecolor_ctrl & 0x40 ? "X" : "O");
|
||||
svga.rgb32_en = 1;
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
case 0x47:
|
||||
if (m_multiplex_ctrl == 0x5b || m_multiplex_ctrl == 0x5c)
|
||||
popmessage("TVP3026: Unemulated BGR%c 8-8-8-8 mode", m_truecolor_ctrl & 0x40 ? "X" : "O");
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x45:
|
||||
if (m_multiplex_ctrl >= 0x52 && m_multiplex_ctrl <= 0x54)
|
||||
{
|
||||
logerror("\tXGA RGB 5-6-5 mode\n");
|
||||
svga.rgb16_en = 1;
|
||||
}
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x44:
|
||||
// 0x04 is selected by VESA 2.4 test, which may be buggy?
|
||||
// (extended mode 110h, while above uses 111h)
|
||||
if (m_multiplex_ctrl >= 0x52 && m_multiplex_ctrl <= 0x54)
|
||||
{
|
||||
logerror("\tTarga %cRGB 1-5-5-5 mode\n", m_truecolor_ctrl & 0x40 ? "X" : "O");
|
||||
svga.rgb16_en = 1;
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x43:
|
||||
if (m_multiplex_ctrl >= 0x52 && m_multiplex_ctrl <= 0x54)
|
||||
popmessage("TVP3026: Unemulated RGB 6-6-4 mode");
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x41:
|
||||
if (m_multiplex_ctrl >= 0x52 && m_multiplex_ctrl <= 0x54)
|
||||
popmessage("TVP3026: Unemulated RGB%c 4-4-4-4 mode", m_truecolor_ctrl & 0x40 ? "X" : "O");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t matrox_vga_device::mem_r(offs_t offset)
|
||||
{
|
||||
// TODO: MGA mode CRTCEXT3 bit 7
|
||||
if (svga.rgb16_en)
|
||||
if (m_mgamode)
|
||||
return svga_device::mem_linear_r(offset + (svga.bank_w * 0x10000));
|
||||
return svga_device::mem_r(offset);
|
||||
}
|
||||
|
||||
void matrox_vga_device::mem_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (svga.rgb16_en)
|
||||
if (m_mgamode)
|
||||
{
|
||||
svga_device::mem_linear_w(offset + (svga.bank_w * 0x10000), data);
|
||||
return;
|
||||
|
|
|
@ -24,17 +24,36 @@ protected:
|
|||
|
||||
virtual void device_reset() override;
|
||||
|
||||
void crtcext_map(address_map &map);
|
||||
virtual uint16_t offset() override;
|
||||
|
||||
void crtcext_map(address_map &map);
|
||||
void ramdac_indexed_map(address_map &map);
|
||||
void flush_true_color_mode();
|
||||
private:
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
address_space_config m_crtcext_space_config;
|
||||
address_space_config m_ramdac_indexed_space_config;
|
||||
|
||||
// CRTC
|
||||
u8 crtcext3_misc_r();
|
||||
void crtcext3_misc_w(offs_t offset, u8 data);
|
||||
u8 m_crtcext_index = 0;
|
||||
|
||||
u8 m_crtcext_misc = 0;
|
||||
bool m_mgamode = false;
|
||||
|
||||
// RAMDAC
|
||||
u8 ramdac_ext_indexed_r();
|
||||
void ramdac_ext_indexed_w(offs_t offset, u8 data);
|
||||
|
||||
u8 m_crtcext_index = 0;
|
||||
u8 m_ramdac_mode = 0;
|
||||
u8 truecolor_ctrl_r();
|
||||
void truecolor_ctrl_w(offs_t offset, u8 data);
|
||||
u8 multiplex_ctrl_r();
|
||||
void multiplex_ctrl_w(offs_t offset, u8 data);
|
||||
|
||||
u8 m_multiplex_ctrl = 0;
|
||||
u8 m_truecolor_ctrl = 0;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(MATROX_VGA, matrox_vga_device)
|
||||
|
|
Loading…
Reference in a new issue