video/pc_vga_matrox.cpp: preliminary HW cursor, add a debug VRAM viewer

This commit is contained in:
angelosa 2023-09-16 13:20:23 +02:00
parent 2fe44733e5
commit 5d4b71f4b6
2 changed files with 180 additions and 7 deletions

View File

@ -4,6 +4,8 @@
#include "emu.h"
#include "pc_vga_matrox.h"
#define DEBUG_VRAM_VIEWER 0
DEFINE_DEVICE_TYPE(MATROX_VGA, matrox_vga_device, "matrox_vga", "Matrox MGA2064W VGA")
matrox_vga_device::matrox_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@ -32,7 +34,10 @@ void matrox_vga_device::device_start()
save_item(NAME(m_cursor_read_index));
save_item(NAME(m_cursor_write_index));
save_item(NAME(m_cursor_index_state));
save_item(NAME(m_cursor_ccr));
save_item(NAME(m_cursor_dcc));
save_pointer(NAME(m_cursor_color), 12);
save_pointer(NAME(m_cursor_ram), 0x400);
}
void matrox_vga_device::device_reset()
@ -48,6 +53,10 @@ void matrox_vga_device::device_reset()
m_interlace_mode = false;
m_cursor_read_index = m_cursor_write_index = m_cursor_index_state = 0;
m_cursor_ccr = 0;
m_cursor_x = 0;
m_cursor_y = 0;
m_truecolor_ctrl = 0x80;
m_multiplex_ctrl = 0x98;
}
@ -224,10 +233,55 @@ void matrox_vga_device::ramdac_ext_map(address_map &map)
map(0x04, 0x04).rw(FUNC(matrox_vga_device::cursor_write_index_r), FUNC(matrox_vga_device::cursor_write_index_w));
map(0x05, 0x05).rw(FUNC(matrox_vga_device::cursor_data_r), FUNC(matrox_vga_device::cursor_data_w));
map(0x07, 0x07).rw(FUNC(matrox_vga_device::cursor_read_index_r), FUNC(matrox_vga_device::cursor_read_index_w));
// map(0x09, 0x09) Direct Cursor control
// DDC Direct Cursor control
map(0x09, 0x09).lrw8(
NAME([this] (offs_t offset) {
return m_cursor_dcc & 3;
}),
NAME([this] (offs_t offset, u8 data) {
// compatible alias to setup cursor mode
m_cursor_dcc = (data & 3);
})
);
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(0x0b, 0x0b).lrw8(
NAME([this] (offs_t offset) {
u16 cursor_address = vga.dac.read_index | ((m_cursor_ccr & 0xc) >> 2) << 8;
u8 res = m_cursor_ram[cursor_address++];
cursor_address &= 0x3ff;
vga.dac.read_index = cursor_address & 0xff;
m_cursor_ccr = (((cursor_address & 0x300) >> 8) << 2) | (m_cursor_ccr & 0xf3);
return res;
}),
NAME([this] (offs_t offset, u8 data) {
u16 cursor_address = vga.dac.write_index | ((m_cursor_ccr & 0xc) >> 2) << 8;
m_cursor_ram[cursor_address++] = data;
cursor_address &= 0x3ff;
vga.dac.write_index = cursor_address & 0xff;
m_cursor_ccr = (((cursor_address & 0x300) >> 8) << 2) | (m_cursor_ccr & 0xf3);
})
);
map(0x0c, 0x0d).lrw8(
NAME([this] (offs_t offset) {
return m_cursor_x >> (offset * 8);
}),
NAME([this] (offs_t offset, u8 data) {
const u8 shift_mask = 0xff00 >> (offset * 8);
m_cursor_x = (data << (offset * 8)) | (m_cursor_x & shift_mask);
m_cursor_x &= 0xfff;
})
);
map(0x0e, 0x0f).lrw8(
NAME([this] (offs_t offset) {
return m_cursor_y >> (offset * 8);
}),
NAME([this] (offs_t offset, u8 data) {
const u8 shift_mask = 0xff00 >> (offset * 8);
m_cursor_y = (data << (offset * 8)) | (m_cursor_y & shift_mask);
m_cursor_y &= 0xfff;
})
);
// map(0x10, 0x1f) <reserved>
}
@ -254,7 +308,7 @@ void matrox_vga_device::cursor_write_index_w(offs_t offset, u8 data)
m_cursor_write_index = data & 3;
m_cursor_index_state = 0;
if (data & 0xfc)
logerror("RAMDAC cursor write index > 3");
logerror("RAMDAC cursor_write_index_w > 3 -> %02x\n", data);
}
u8 matrox_vga_device::cursor_read_index_r()
@ -267,7 +321,7 @@ void matrox_vga_device::cursor_read_index_w(offs_t offset, u8 data)
m_cursor_read_index = data & 3;
m_cursor_index_state = 0;
if (data & 0xfc)
logerror("RAMDAC cursor read index > 3");
logerror("RAMDAC cursor_read_index_w > 3 -> %02x\n", data);
}
u8 matrox_vga_device::cursor_data_r()
@ -292,7 +346,7 @@ void matrox_vga_device::cursor_data_w(offs_t offset, u8 data)
if (!machine().side_effects_disabled())
{
m_cursor_index_state ++;
if (m_cursor_write_index > 2)
if (m_cursor_index_state > 2)
{
m_cursor_index_state = 0;
m_cursor_write_index ++;
@ -307,7 +361,15 @@ void matrox_vga_device::ramdac_indexed_map(address_map &map)
map(0x01, 0x01).lr8(
NAME([] (offs_t offset) { return 0x00; })
);
// map(0x06, 0x06) CCR indirect cursor control
// CCR indirect cursor control
map(0x06, 0x06).lrw8(
NAME([this] (offs_t offset) {
return m_cursor_ccr;
}),
NAME([this] (offs_t offset, u8 data) {
m_cursor_ccr = data;
})
);
// map(0x0f, 0x0f) LCR latch control
map(0x18, 0x18).rw(FUNC(matrox_vga_device::truecolor_ctrl_r), FUNC(matrox_vga_device::truecolor_ctrl_w));
@ -382,7 +444,8 @@ void matrox_vga_device::flush_true_color_mode()
{
// [0x41, 0x42, 0x43, 0x44] for normal
// [0x61, 0x62, 0x63, 0x64] for nibble swapped
popmessage("TVP3026: Unemulated 4-bit %s with multiplex: %02x"
// Used a lot on intermediate states between VGA and Power Modes ...
logerror("TVP3026: Unemulated 4-bit %s with multiplex: %02x\n"
, m_multiplex_ctrl & 0x20 ? "normal" : "nibble swapped"
, m_multiplex_ctrl
);
@ -511,3 +574,98 @@ u16 matrox_vga_device::line_compare_mask()
{
return m_mgamode ? 0x7ff : 0x3ff;
}
uint32_t matrox_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
svga_device::screen_update(screen, bitmap, cliprect);
// HW cursor
const u8 cursor_mode = (BIT(m_cursor_ccr, 7) ? m_cursor_dcc : m_cursor_ccr) & 3;
if (cursor_mode)
{
// partial XGA mode only for now (Win 3.1), others TBD
// mode 1: 3 color mode -> transparent/color 0-1-2
// mode 2: xga mode -> color 0-1/transparent/complement
// mode 3: x-window mode -> transparent/transparent/color 0-1
const u8 transparent_pen = 2;
for (int y = 0; y < 64; y ++)
{
int res_y = y + m_cursor_y - 64;
for (int x = 0; x < 64; x++)
{
int res_x = x + m_cursor_x - 64;
if (!cliprect.contains(res_x, res_y))
continue;
const u16 cursor_address = (x >> 3) + y * 8;
const int xi = 7 - (x & 7);
u8 cursor_gfx = (m_cursor_ram[cursor_address] >> (xi) & 1) | ((m_cursor_ram[cursor_address + 0x200] >> (xi)) & 1) << 1;
if (cursor_gfx == transparent_pen)
continue;
// FIXME: Win 3.1 writes to clut 2 for white, may be wrong
cursor_gfx ++;
cursor_gfx &= 3;
const u8 r = m_cursor_color[3 * cursor_gfx + 0];
const u8 g = m_cursor_color[3 * cursor_gfx + 1];
const u8 b = m_cursor_color[3 * cursor_gfx + 2];
bitmap.pix(res_y, res_x) = r << 16 | g << 8 | b;
}
}
}
#if DEBUG_VRAM_VIEWER
static int m_test_x = 640, m_start_offs;
static int m_test_trigger = 1;
const int m_test_y = cliprect.max_y;
if(machine().input().code_pressed(JOYCODE_X_RIGHT_SWITCH))
m_test_x += 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);;
if(machine().input().code_pressed(JOYCODE_X_LEFT_SWITCH))
m_test_x -= 1 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 4 : 0);;
//if(machine().input().code_pressed(JOYCODE_Y_DOWN_SWITCH))
// m_test_y++;
//if(machine().input().code_pressed(JOYCODE_Y_UP_SWITCH))
// m_test_y--;
if(machine().input().code_pressed(JOYCODE_Y_DOWN_SWITCH))
m_start_offs+= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
if(machine().input().code_pressed(JOYCODE_Y_UP_SWITCH))
m_start_offs-= 0x100 << (machine().input().code_pressed(JOYCODE_BUTTON2) ? 8 : 0);
m_start_offs %= vga.svga_intf.vram_size;
if(machine().input().code_pressed_once(JOYCODE_BUTTON1))
m_test_trigger ^= 1;
if (!m_test_trigger)
return 0;
popmessage("%d %d %04x", m_test_x, m_test_y, m_start_offs);
bitmap.fill(0, cliprect);
int count = m_start_offs;
for(int y = 0; y < m_test_y; y++)
{
for(int x = 0; x < m_test_x; x ++)
{
u8 color = vga.memory[count % vga.svga_intf.vram_size];
if(cliprect.contains(x, y))
{
//bitmap.pix(y, x) = pal565(color, 11, 5, 0);
bitmap.pix(y, x) = pen(color);
}
count ++;
// count += 2;
}
}
#endif
return 0;
}

View File

@ -24,6 +24,18 @@ public:
bool vsync_status() { return vga_vblank(); }
u32 vcount_r() { return screen().vpos() & 0xfff; }
u8 read_memory(u32 address)
{
return vga.memory[address % vga.svga_intf.vram_size];
}
void write_memory(u32 address, u8 data)
{
vga.memory[address % vga.svga_intf.vram_size] = data;
}
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
protected:
virtual void io_3bx_3dx_map(address_map &map) override;
@ -77,6 +89,9 @@ private:
u8 m_cursor_read_index = 0;
u8 m_cursor_index_state = 0;
u8 m_cursor_color[12]{};
u8 m_cursor_ram[0x400]{};
u8 m_cursor_ccr = 0, m_cursor_dcc = 0;
u16 m_cursor_x = 0, m_cursor_y = 0;
u8 truecolor_ctrl_r();
void truecolor_ctrl_w(offs_t offset, u8 data);