From 9027f281730c17556fe72b4e70c5ba0bf9d69c2f Mon Sep 17 00:00:00 2001 From: angelosa Date: Sat, 17 Feb 2024 00:19:12 +0100 Subject: [PATCH] video/pc_vga_oak: preliminary HW cursor, add path for 32bpp color mode --- src/devices/bus/pci/oti_spitfire.cpp | 3 + src/devices/video/pc_vga_oak.cpp | 137 ++++++++++++++++++++++----- src/devices/video/pc_vga_oak.h | 10 ++ 3 files changed, 128 insertions(+), 22 deletions(-) diff --git a/src/devices/bus/pci/oti_spitfire.cpp b/src/devices/bus/pci/oti_spitfire.cpp index 05203acb224..a3e6ecbf7b9 100644 --- a/src/devices/bus/pci/oti_spitfire.cpp +++ b/src/devices/bus/pci/oti_spitfire.cpp @@ -79,6 +79,8 @@ void oti64111_pci_device::device_start() // INTA# intr_pin = 1; + + // TODO: (default?) min_gnt = 0xff, max_lat = 0x01 } void oti64111_pci_device::device_reset() @@ -101,6 +103,7 @@ void oti64111_pci_device::config_map(address_map &map) void oti64111_pci_device::mmio_map(address_map &map) { map(0x00, 0x7f).rw(m_svga, FUNC(oak_oti111_vga_device::xga_read), FUNC(oak_oti111_vga_device::xga_write)); + map(0x80, 0xbf).m(m_svga, FUNC(oak_oti111_vga_device::multimedia_map)); } void oti64111_pci_device::vram_aperture_map(address_map &map) diff --git a/src/devices/video/pc_vga_oak.cpp b/src/devices/video/pc_vga_oak.cpp index 9a6eeff8af6..e5654a14b0c 100644 --- a/src/devices/video/pc_vga_oak.cpp +++ b/src/devices/video/pc_vga_oak.cpp @@ -52,6 +52,8 @@ void oak_oti111_vga_device::device_reset() m_oti_map_select = false; m_oti_aperture_mask = 0x3ffff; m_oak_gfx_mode = false; + + m_cursor_control = 0; } void oak_oti111_vga_device::io_3bx_3dx_map(address_map &map) @@ -91,7 +93,9 @@ void oak_oti111_vga_device::oak_map(address_map &map) //machine().debug_break(); return 0x06; }) - ); + // win98se also manages to write here a lot ... + ).nopw(); + // status, set by BIOS for memory size map(0x02, 0x02).lrw8( NAME([this] (offs_t offset) { @@ -247,26 +251,6 @@ void oak_oti111_vga_device::oak_map(address_map &map) ); //map(0x39, 0x3a) Extended Overscan Color - //HC = Hardware Cursor - //HW = Hardware Window - //map(0x80, 0x81) HC & HW window H Position Start - //map(0x82, 0x83) HC & HW window V Position Start - //map(0x84, 0x84) HC Horizontal Preset/HW Width Low - //map(0x85, 0x85) HW Width High - //map(0x86, 0x86) HC Vertical Preset/HW Height Low - //map(0x87, 0x87) HW Height High - //map(0x88, 0x8a) HC Start Address - //map(0x8c, 0x8f) HC Color 0 - //map(0x90, 0x93) HC Color 1 - //map(0x94, 0x94) HC Control - //map(0x96, 0x97) HW Control - //map(0x98, 0x9a) HW Mask Map Start Address - //map(0x9b, 0x9b) Multimedia Mask Map Offset - //map(0x9c, 0x9e) HW Start Address - //map(0x9f, 0x9f) HW Address Offset - //map(0xa0, 0xa1) Video Window Width - //map(0xa2, 0xa3) Video Window Height - // Scratch Pad map(0xf0, 0xf7).lrw8( NAME([this] (offs_t offset) { @@ -296,6 +280,70 @@ void oak_oti111_vga_device::xga_write(offs_t offset, u8 data) m_xga->xga_write(offset, data); } +void oak_oti111_vga_device::multimedia_map(address_map &map) +{ + //HC = Hardware Cursor + //HW = Hardware Window + map(0x00, 0x01).lrw16( + NAME([this] (offs_t offset) { + return m_cursor_x; + }), + NAME([this] (offs_t offset, u16 data, u16 mem_mask) { + COMBINE_DATA(&m_cursor_x); + }) + ); + map(0x02, 0x03).lrw16( + NAME([this] (offs_t offset) { + return m_cursor_y; + }), + NAME([this] (offs_t offset, u16 data, u16 mem_mask) { + COMBINE_DATA(&m_cursor_y); + }) + ); + //map(0x04, 0x04) HC Horizontal Preset/HW Width Low + //map(0x05, 0x05) HW Width High + //map(0x06, 0x06) HC Vertical Preset/HW Height Low + //map(0x07, 0x07) HW Height High + map(0x08, 0x0b).lrw32( + NAME([this] (offs_t offset) { + return m_cursor_address_base; + }), + NAME([this] (offs_t offset, u32 data, u32 mem_mask) { + COMBINE_DATA(&m_cursor_address_base); + // clamp to 24-bits + m_cursor_address_base &= 0xffffff; + //LOG("HC Start Address %08x & %08x\n", data, mem_mask); + + }) + ); + map(0x0c, 0x13).lrw32( + NAME([this] (offs_t offset) { + return m_cursor_color[offset]; + }), + NAME([this] (offs_t offset, u32 data, u32 mem_mask) { + COMBINE_DATA(&m_cursor_color[offset]); + LOG("HC color %d %08x & %08x\n", offset, data, mem_mask); + }) + ); + map(0x14, 0x14).lrw8( + NAME([this] (offs_t offset) { + return m_cursor_control; + }), + NAME([this] (offs_t offset, u8 data) { + m_cursor_control = data; + LOG("HC control $94 %02x\n", data); + }) + ); + //map(0x15, 0x15) Multimedia Port + //map(0x16, 0x17) HW Control + //map(0x18, 0x1a) HW Mask Map Start Address + //map(0x1b, 0x1b) Multimedia Mask Map Offset + //map(0x1c, 0x1e) HW Start Address + //map(0x1f, 0x1f) HW Address Offset + //map(0x20, 0x21) Video Window Width + //map(0x22, 0x23) Video Window Height +} + void oak_oti111_vga_device::ramdac_mmio_map(address_map &map) { map.unmap_value_high(); @@ -339,7 +387,7 @@ void oak_oti111_vga_device::recompute_params() u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2; int xtal; - svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = 0; + svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = svga.rgb32_en = 0; if (m_oak_gfx_mode) { @@ -362,6 +410,10 @@ void oak_oti111_vga_device::recompute_params() case 7: svga.rgb24_en = 1; break; + case 8: + // SciTech can't detect this, assumed by win98se + svga.rgb32_en = 1; + break; default: popmessage("pc_vga_oak: unhandled pixel mode %02x", m_pixel_mode); break; @@ -388,3 +440,44 @@ void oak_oti111_vga_device::recompute_params() recompute_params_clock(1, xtal); } + +uint32_t oak_oti111_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + svga_device::screen_update(screen, bitmap, cliprect); + + // HW cursor + + if (BIT(m_cursor_control, 0)) + { + // TODO: preliminary, should be 64x64, win98se just uses this portion + // Drawing specifics aren't really documented beyond what the register does. + + // TODO: x4 in planar mode, x8 in packed pixel + const u32 base_offs = (m_cursor_address_base * 8) + 0x200; + const u8 transparent_pen = 2; + + for (int y = 0; y < 32; y ++) + { + int res_y = y + m_cursor_y; + for (int x = 0; x < 32; x++) + { + int res_x = x + m_cursor_x; + if (!cliprect.contains(res_x, res_y)) + continue; + const u32 cursor_address = ((x >> 3) + y * 16) + base_offs; + // TODO: std::function for Intel format (win98se uses Motorola) + const int xi = 7 - (x & 7); + u8 cursor_gfx = (vga.memory[(cursor_address + 0x8) % vga.svga_intf.vram_size] >> (xi) & 1); + cursor_gfx |= ((vga.memory[(cursor_address + 0xc) % vga.svga_intf.vram_size] >> (xi)) & 1) << 1; + + if (cursor_gfx & transparent_pen) + continue; + + // TODO: should really mask by pixel depth + bitmap.pix(res_y, res_x) = m_cursor_color[cursor_gfx] & 0xffffff; + } + } + } + + return 0; +} diff --git a/src/devices/video/pc_vga_oak.h b/src/devices/video/pc_vga_oak.h index 8115667a69f..f7207636dea 100644 --- a/src/devices/video/pc_vga_oak.h +++ b/src/devices/video/pc_vga_oak.h @@ -20,9 +20,14 @@ public: // $xxe0-$xxef in EXTIO void ramdac_mmio_map(address_map &map); + // $80 in MMIO space + void multimedia_map(address_map &map); + virtual uint8_t mem_r(offs_t offset) override; virtual void mem_w(offs_t offset, uint8_t data) override; + virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; + protected: virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; @@ -57,6 +62,11 @@ private: u8 m_pixel_mode = 0; bool m_color_swap = false; u8 m_bpp = 0; + + u16 m_cursor_x = 0, m_cursor_y = 0; + u8 m_cursor_control = 0; + u32 m_cursor_address_base = 0; + u32 m_cursor_color[2]{}; }; DECLARE_DEVICE_TYPE(OTI111, oak_oti111_vga_device)