diff --git a/src/devices/video/pc_vga_matrox.cpp b/src/devices/video/pc_vga_matrox.cpp index ab43443a70b..20e9e5d8f5e 100644 --- a/src/devices/video/pc_vga_matrox.cpp +++ b/src/devices/video/pc_vga_matrox.cpp @@ -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 + * ---- -101 /6 + * ---- -110 + * ---- -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) +// map(0x0b, 0x0b) Cursor RAM data +// map(0x0c, 0x0f) Cursor X/Y positions +// map(0x10, 0x1f) } 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; diff --git a/src/devices/video/pc_vga_matrox.h b/src/devices/video/pc_vga_matrox.h index 295253c45c1..b6cbc14fc31 100644 --- a/src/devices/video/pc_vga_matrox.h +++ b/src/devices/video/pc_vga_matrox.h @@ -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)