video/pc_vga_matrox.cpp: add screen extension bit hook ups

video/mga2064w.cpp: translate alias space to 32-bits
This commit is contained in:
angelosa 2023-08-09 23:12:24 +02:00
parent 0268ef195e
commit 2dccaba3b4
5 changed files with 177 additions and 25 deletions

View File

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

View File

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

View File

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

View File

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

View File

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