diff --git a/src/devices/video/mga2064w.cpp b/src/devices/video/mga2064w.cpp index cb271348fcd..3a6e2f86896 100644 --- a/src/devices/video/mga2064w.cpp +++ b/src/devices/video/mga2064w.cpp @@ -22,7 +22,7 @@ mga2064w_device::mga2064w_device(const machine_config &mconfig, const char *tag, , m_vga_rom(*this, "vga_rom") { set_ids(0x102b0519, 0x01, 0x030000, 0x00000000); - m_mgabase1_real_space_config = address_space_config("mgabase1_regs", ENDIANNESS_LITTLE, 8, 14, 0, address_map_constructor(FUNC(mga2064w_device::mgabase1_map), this)); + m_mgabase1_real_space_config = address_space_config("mgabase1_regs", ENDIANNESS_LITTLE, 32, 14, 0, address_map_constructor(FUNC(mga2064w_device::mgabase1_map), this)); } ROM_START( mga2064w ) @@ -128,8 +128,8 @@ void mga2064w_device::mgabase1_map(address_map &map) // map(0x1cc0, 0x1cff) DR0-DR15 (DR1-5-9-13 ) // map(0x1e00, 0x1eff) HSTREG Host registers -// map(0x1e10, 0x1e13) FIFOSTATUS (r/o) -// map(0x1e14, 0x1e17) Status (r/o) + map(0x1e10, 0x1e13).r(FUNC(mga2064w_device::fifo_status_r)); + map(0x1e14, 0x1e17).r(FUNC(mga2064w_device::status_r)); // map(0x1e18, 0x1e1b) ICLEAR // map(0x1e1c, 0x1e1f) IEN // map(0x1e20, 0x1e23) VCOUNT (r/o) @@ -146,6 +146,32 @@ void mga2064w_device::mgabase2_map(address_map &map) map(0x000000, 0x7fffff).rw(m_svga, FUNC(matrox_vga_device::mem_linear_r), FUNC(matrox_vga_device::mem_linear_w)); } +/* + * MGABASE1 + 1e10h FIFO Status (r/o) + * + * ---- -x-- ---- ---- BEMPTY Bus FIFO empty + * ---- --x- ---- ---- BFULL Bus FIFO full + * ---- ---- ---x xxxx FIFOCOUNT free locations in FIFO (max: 32) + */ +u32 mga2064w_device::fifo_status_r() +{ + return (1 << 9) | 32; +} + +/* + * MGABASE1 + 1e14h Status (r/o) + * + * ---- ---- ---- ---x ---- ---- ---- ---- DWGENGSTS + * ---- ---- ---- ---- ---- ---- -x-- ---- EXTPEN + * ---- ---- ---- ---- ---- ---- --x- ---- VLINEPEN + * ---- ---- ---- ---- ---- ---- ---x ---- VSYNCPEN + * ---- ---- ---- ---- ---- ---- ---- x--- VSYNCSTS + * ---- ---- ---- ---- ---- ---- ---- -x-- PICKPEN + */ +u32 mga2064w_device::status_r() +{ + return m_svga->vsync_status() << 3; +} // TODO: this should really be a subclass of VGA void mga2064w_device::legacy_memory_map(address_map &map) @@ -153,7 +179,6 @@ void mga2064w_device::legacy_memory_map(address_map &map) map(0xa0000, 0xbffff).rw(FUNC(mga2064w_device::vram_r), FUNC(mga2064w_device::vram_w)); } -// TODO: card may not even support MDA access void mga2064w_device::legacy_io_map(address_map &map) { map(0, 0x02f).m(m_svga, FUNC(matrox_vga_device::io_map)); @@ -201,12 +226,12 @@ void mga2064w_device::mga_index_w(offs_t offset, u32 data, u32 mem_mask) m_mgabase1_real_index &= 0x3ffc; } -u8 mga2064w_device::mga_data_r(offs_t offset) +u32 mga2064w_device::mga_data_r(offs_t offset, u32 mem_mask) { - return space(AS_IO).read_byte(offset + m_mgabase1_real_index); + return space(AS_IO).read_dword(m_mgabase1_real_index, mem_mask); } -void mga2064w_device::mga_data_w(offs_t offset, u8 data) +void mga2064w_device::mga_data_w(offs_t offset, u32 data, u32 mem_mask) { - space(AS_IO).write_byte(offset + m_mgabase1_real_index, data); + space(AS_IO).write_dword(m_mgabase1_real_index, data, mem_mask); } diff --git a/src/devices/video/mga2064w.h b/src/devices/video/mga2064w.h index 9165639e435..80b75633d16 100644 --- a/src/devices/video/mga2064w.h +++ b/src/devices/video/mga2064w.h @@ -40,10 +40,12 @@ private: address_space_config m_mgabase1_real_space_config; u32 mga_index_r(); void mga_index_w(offs_t offset, u32 data, u32 mem_mask = ~0); - u8 mga_data_r(offs_t offset); - void mga_data_w(offs_t offset, u8 data); - + u32 mga_data_r(offs_t offset, u32 mem_mask = ~0); + void mga_data_w(offs_t offset, u32 data, u32 mem_mask = ~0); u32 m_mgabase1_real_index = 0; + + u32 status_r(); + u32 fifo_status_r(); }; DECLARE_DEVICE_TYPE(MGA2064W, mga2064w_device); diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp index 44f79f20362..d583f25be66 100644 --- a/src/devices/video/pc_vga.cpp +++ b/src/devices/video/pc_vga.cpp @@ -1327,7 +1327,8 @@ void vga_device::vga_vh_ega(bitmap_rgb32 &bitmap, const rectangle &cliprect) } } -/* TODO: I'm guessing that in 256 colors mode every pixel actually outputs two pixels. Is it right? */ +// In mode 13h (256 colors) every pixel actually double height/width +// i.e. a 320x200 is really 640x400 void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) { int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); @@ -1335,6 +1336,7 @@ void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) int addrmask = vga.crtc.no_wrap ? -1 : 0xffff; /* line compare is screen sensitive */ + // FIXME: some clients extends line compare with bit 10 uint16_t mask_comp = 0x3ff; //| (LINES & 0x300); // popmessage("%02x %02x",vga.attribute.pel_shift,vga.sequencer.data[4] & 0x08); @@ -1806,7 +1808,8 @@ void svga_device::svga_vh_rgb8(bitmap_rgb32 &bitmap, const rectangle &cliprect) int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); /* line compare is screen sensitive */ - uint16_t mask_comp = 0x3ff; + // FIXME: some clients extends line compare with bit 10 + uint16_t mask_comp = 0x3ff; int curr_addr = 0; // uint16_t line_length; // if(vga.crtc.dw) diff --git a/src/devices/video/pc_vga_matrox.cpp b/src/devices/video/pc_vga_matrox.cpp index 20e9e5d8f5e..144be5a0a64 100644 --- a/src/devices/video/pc_vga_matrox.cpp +++ b/src/devices/video/pc_vga_matrox.cpp @@ -31,7 +31,9 @@ void matrox_vga_device::device_reset() m_crtcext_index = 0; m_crtcext_misc = 0; + m_crtcext_horz_counter = 0; m_mgamode = false; + m_interlace_mode = false; m_truecolor_ctrl = 0x80; m_multiplex_ctrl = 0x98; } @@ -60,11 +62,11 @@ void matrox_vga_device::io_3bx_3dx_map(address_map &map) // "CRTCEXT*" 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(0x00, 0x00).rw(FUNC(matrox_vga_device::crtcext0_address_gen_r), FUNC(matrox_vga_device::crtcext0_address_gen_w)); + map(0x01, 0x01).rw(FUNC(matrox_vga_device::crtcext1_horizontal_counter_r), FUNC(matrox_vga_device::crtcext1_horizontal_counter_w)); + map(0x02, 0x02).rw(FUNC(matrox_vga_device::crtcext2_vertical_counter_r), FUNC(matrox_vga_device::crtcext2_vertical_counter_w)); map(0x03, 0x03).rw(FUNC(matrox_vga_device::crtcext3_misc_r), FUNC(matrox_vga_device::crtcext3_misc_w)); -// CRTCEXT4 Memory Page register + // CRTCEXT4 Memory Page register map(0x04, 0x04).lrw8( NAME([this] (offs_t offset) { return svga.bank_w & 0x7f; }), NAME([this] (offs_t offset, u8 data) { svga.bank_w = data & 0x7f; }) @@ -75,6 +77,87 @@ void matrox_vga_device::crtcext_map(address_map &map) // seems to disable SVGA drawing -> diagnostic check? } +/* + * CRTCEXT0 Address Generator extensions + * + * x--- ---- Interlace mode + * --xx ---- Offset bits 9-8 + * ---- xxxx Start Address bits 19-16 + */ +u8 matrox_vga_device::crtcext0_address_gen_r() +{ + u8 res = ((vga.crtc.start_addr >> 16) & 0xf); + res |= ((vga.crtc.offset >> 8) & 3) << 4; + res |= (m_interlace_mode) << 7; + return res; +} + +void matrox_vga_device::crtcext0_address_gen_w(offs_t offset, u8 data) +{ + m_interlace_mode = bool(BIT(data, 7)); + vga.crtc.offset = (vga.crtc.offset & 0xff) | ((data & 0x30) << 4); + vga.crtc.start_addr = (vga.crtc.start_addr & 0xffff) | ((data & 0xf) << 16); + if (m_interlace_mode) + popmessage("MGA2064W: interlace mode enable"); +// recompute_params(); +} + +/* + * CRTCEXT1 Horizontal Counter Extensions + * + * x--- ---- VRSTEN Vertical reset enable + * -x-- ---- HBLKEND Horizontal end blank bit 6 (MGA mode only) + * --x- ---- VSYNCOFF + * ---x ---- HSYNCOFF + * ---- x--- HRSTEN Horizontal reset enable + * ---- -x-- HSYNCSTR horizontal retrace start bit 8 + * ---- --x- HBLKSTR horizontal blanking start bit 8 + * ---- ---x HTOTAL bit 8 + */ +u8 matrox_vga_device::crtcext1_horizontal_counter_r() +{ + return m_crtcext_horz_counter; +} + +void matrox_vga_device::crtcext1_horizontal_counter_w(offs_t offset, u8 data) +{ + // TODO: honor CRTC protect enable + m_crtcext_horz_counter = data; + vga.crtc.horz_total = (vga.crtc.horz_total & 0xff) | (BIT(data, 0) << 8); + vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xff) | (BIT(data, 1) << 8); + vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xff) | (BIT(data, 2) << 8); + vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0x3f) | (BIT(data, 6) << 6); + + logerror("MGA2064W: CRTCEXT1 reset enable %02x syncoff %02x\n",data & 0x88, data & 0x30); + recompute_params(); +} + +/* + * CRTCEXT1 Vertical Counter Extensions + * + * x--- ---- LINECOMP Line compare bit 10 + * -xx- ---- VSYNCSTR Vertical retrace start bits 11-10 + * ---x x--- VBLKSTR Vertical blank start bits 11-10 + * ---- -x-- VDISPEND Vertical display end bit 10 + * ---- --xx VTOTAL bits 11-10 + */ +u8 matrox_vga_device::crtcext2_vertical_counter_r() +{ + return m_crtcext_vert_counter; +} + +void matrox_vga_device::crtcext2_vertical_counter_w(offs_t offset, u8 data) +{ + // TODO: honor CRTC protect enable + m_crtcext_vert_counter = data; + vga.crtc.vert_total = (vga.crtc.vert_total & 0x3ff) | ((data & 3) << 10); + vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0x3ff) | (BIT(data, 2) << 10); + vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0x3ff) | ((data & 0x18) << (10-3)); + vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0x3ff) | ((data & 0x60) << (10-5)); + vga.crtc.line_compare = (vga.crtc.line_compare & 0x3ff) | (BIT(data, 7) << 10); + recompute_params(); +} + /* * CRTCEXT3 Miscellaneous * @@ -107,15 +190,19 @@ void matrox_vga_device::crtcext3_misc_w(offs_t offset, u8 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 +/* + * RAMDAC + * - paired with a Texas Instruments TVP3026 here -> a superset of INMOS IMSG176/IMSG178 + * - integrated and customized with supersets in the next iteration (Mystique MGA-1064SG) and onward + */ 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(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).lr8( + NAME([this] (offs_t offset) { return vga.dac.read_index; }) + ).w(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 @@ -255,6 +342,8 @@ void matrox_vga_device::flush_true_color_mode() popmessage("TVP3026: Unemulated RGB%c 4-4-4-4 mode", m_truecolor_ctrl & 0x40 ? "X" : "O"); break; } + + recompute_params(); } uint8_t matrox_vga_device::mem_r(offs_t offset) @@ -274,10 +363,29 @@ void matrox_vga_device::mem_w(offs_t offset, uint8_t data) svga_device::mem_w(offset, data); } +void matrox_vga_device::recompute_params() +{ + u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2; + int xtal; + + switch(xtal_select & 3) + { + case 0: xtal = XTAL(25'174'800).value(); break; + case 1: xtal = XTAL(28'636'363).value(); break; + // TODO: stub, derives from RAMDAC PLLs + case 2: + default: + xtal = XTAL(50'000'000).value(); + break; + } + + recompute_params_clock(1, xtal); +} + uint16_t matrox_vga_device::offset() { // TODO: shifts depending on RAMDAC mode + CRTCEXT0 bits 5-4 if (svga.rgb16_en) - return (vga.crtc.offset << 5); + return (vga.crtc.offset << 4); return svga_device::offset(); } diff --git a/src/devices/video/pc_vga_matrox.h b/src/devices/video/pc_vga_matrox.h index b6cbc14fc31..a3c30b90ab7 100644 --- a/src/devices/video/pc_vga_matrox.h +++ b/src/devices/video/pc_vga_matrox.h @@ -19,12 +19,17 @@ public: virtual uint8_t mem_r(offs_t offset) override; virtual void mem_w(offs_t offset, uint8_t data) override; + + // TODO: polarity + bool vsync_status() { return vga_vblank(); } + protected: virtual void io_3bx_3dx_map(address_map &map) override; virtual void device_reset() override; virtual uint16_t offset() override; + virtual void recompute_params() override; void crtcext_map(address_map &map); void ramdac_indexed_map(address_map &map); @@ -36,12 +41,21 @@ private: address_space_config m_ramdac_indexed_space_config; // CRTC + u8 crtcext0_address_gen_r(); + void crtcext0_address_gen_w(offs_t offset, u8 data); + u8 crtcext1_horizontal_counter_r(); + void crtcext1_horizontal_counter_w(offs_t offset, u8 data); + u8 crtcext2_vertical_counter_r(); + void crtcext2_vertical_counter_w(offs_t offset, u8 data); u8 crtcext3_misc_r(); void crtcext3_misc_w(offs_t offset, u8 data); u8 m_crtcext_index = 0; u8 m_crtcext_misc = 0; + u8 m_crtcext_horz_counter = 0; + u8 m_crtcext_vert_counter = 0; bool m_mgamode = false; + bool m_interlace_mode = false; // RAMDAC u8 ramdac_ext_indexed_r();