From 7b5219935aa4cedd293013110ef6030e224c4b61 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sun, 1 Mar 2020 13:19:49 +0100 Subject: -s3virge: Plumbed out linear framebuffer support. Fixes graphics in 'Analog 801' demoscene demo. [Ryan Holtz] --- src/devices/bus/isa/isa.cpp | 5 +++ src/devices/bus/isa/isa.h | 1 + src/devices/bus/isa/s3virge.cpp | 94 +++++++++++++++++++++++++++++++++++++---- src/devices/bus/isa/s3virge.h | 10 +++++ src/devices/bus/isa/svga_s3.cpp | 56 ++++++++++++++++++++++++ src/devices/bus/isa/svga_s3.h | 9 ++++ 6 files changed, 166 insertions(+), 9 deletions(-) diff --git a/src/devices/bus/isa/isa.cpp b/src/devices/bus/isa/isa.cpp index df21453268f..9537febc93c 100644 --- a/src/devices/bus/isa/isa.cpp +++ b/src/devices/bus/isa/isa.cpp @@ -371,6 +371,11 @@ bool isa8_device::is_option_rom_space_available(offs_t start, int size) return true; } +void isa8_device::unmap_readwrite(offs_t start, offs_t end) +{ + m_memspace->unmap_readwrite(start, end); +} + // interrupt request from isa card WRITE_LINE_MEMBER( isa8_device::irq2_w ) { m_out_irq2_cb(state); } WRITE_LINE_MEMBER( isa8_device::irq3_w ) { m_out_irq3_cb(state); } diff --git a/src/devices/bus/isa/isa.h b/src/devices/bus/isa/isa.h index 4eefa1ff548..4cd032a1a9e 100644 --- a/src/devices/bus/isa/isa.h +++ b/src/devices/bus/isa/isa.h @@ -155,6 +155,7 @@ public: void unmap_device(offs_t start, offs_t end) const { m_iospace->unmap_readwrite(start, end); } void unmap_bank(offs_t start, offs_t end); void unmap_rom(offs_t start, offs_t end); + void unmap_readwrite(offs_t start, offs_t end); bool is_option_rom_space_available(offs_t start, int size); // FIXME: shouldn't need to expose this diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp index 111d87002e8..9fa8739a13d 100644 --- a/src/devices/bus/isa/s3virge.cpp +++ b/src/devices/bus/isa/s3virge.cpp @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Barry Rodewald /* - * s3virge.c + * s3virge.cpp * * Implementation of the S3 Virge series of video card * @@ -42,6 +42,7 @@ s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, const char s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : s3_vga_device(mconfig, type, tag, owner, clock) + , m_linear_config_changed_cb(*this) { } @@ -64,9 +65,7 @@ void s3virge_vga_device::device_start() { zero(); - int x; - int i; - for (i = 0; i < 0x100; i++) + for (int i = 0; i < 0x100; i++) set_pen_color(i, 0, 0, 0); // Avoid an infinite loop when displaying. 0 is not possible anyway. @@ -90,6 +89,7 @@ void s3virge_vga_device::device_start() memset(&s3, 0, sizeof(s3)); memset(&s3virge, 0, sizeof(s3virge)); s3virge.linear_address = 0x70000000; + s3virge.linear_address_size_full = 0x10000; s3virge.s3d.cmd_fifo_slots_free = 16; save_item(s3virge.s3d.pattern,"S3D Pattern Data"); save_item(s3virge.s3d.reg[0],"S3D Registers: BitBLT"); @@ -98,8 +98,10 @@ void s3virge_vga_device::device_start() save_item(s3virge.s3d.reg[3],"S3D Registers: 3D Line"); save_item(s3virge.s3d.reg[4],"S3D Registers: 3D Triangle"); + m_linear_config_changed_cb.resolve_safe(); + // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason - for(x=0;x<4;x++) + for (int x = 0; x < 4; x++) { s3.cursor_fg[x] = 0xff; s3.cursor_bg[x] = 0x00; @@ -581,8 +583,14 @@ bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the break; case 0x58: + { + const uint8_t old_size = s3virge.linear_address_size; + const bool old_enable = s3virge.linear_address_enable; + const bool size_changed = old_size != s3virge.linear_address_size; + s3virge.linear_address_size = data & 0x03; s3virge.linear_address_enable = data & 0x10; + switch(data & 0x03) { case LAW_64K: @@ -598,16 +606,39 @@ bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the s3virge.linear_address_size_full = 0x400000; break; } + + if ((s3virge.linear_address_enable != old_enable) || size_changed) + { + m_linear_config_changed_cb(s3virge.linear_address_enable); + } + LOGREG("CR58: write %02x\n", data); break; + } case 0x59: + { + const uint32_t old_address = s3virge.linear_address; s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24); LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address); + + if (old_address != s3virge.linear_address && s3virge.linear_address_enable) + { + m_linear_config_changed_cb(1); + } break; + } case 0x5a: + { + const uint32_t old_address = s3virge.linear_address; s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16); LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address); + + if (old_address != s3virge.linear_address && s3virge.linear_address_enable) + { + m_linear_config_changed_cb(1); + } break; + } /* 3d4h index 5Dh (R/W): Extended Horizontal Overflow Register (80x +) @@ -887,12 +918,12 @@ void s3virge_vga_device::add_command(int cmd_type) // add command to S3D FIFO if(s3virge.s3d.cmd_fifo_slots_free == 0) { - LOGMMIO("Attempt to add command when all command slots are full\n"); + LOGCMD("Attempt to add command when all command slots are full\n"); return; } memcpy(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].reg,s3virge.s3d.reg[cmd_type],256*4); s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].op_type = cmd_type; - LOGMMIO("Added command type %i cmd %08x ptr %u\n",s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].op_type,s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].reg[S3D_REG_COMMAND],s3virge.s3d.cmd_fifo_next_ptr); + LOGCMD("Added command type %i cmd %08x ptr %u\n",s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].op_type,s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].reg[S3D_REG_COMMAND],s3virge.s3d.cmd_fifo_next_ptr); s3virge.s3d.cmd_fifo_next_ptr++; if(s3virge.s3d.cmd_fifo_next_ptr >= 16) s3virge.s3d.cmd_fifo_next_ptr = 0; @@ -909,6 +940,18 @@ void s3virge_vga_device::command_start() switch(cmd_type) { + case OP_2DLINE: + LOGCMD("2D Line command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); + break; + case OP_2DPOLY: + LOGCMD("2D Poly command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); + break; + case OP_3DLINE: + LOGCMD("3D Line command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); + break; + case OP_3DTRI: + LOGCMD("3D Tri command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); + break; case OP_BITBLT: s3virge.s3d.state = S3D_STATE_BITBLT; s3virge.s3d.busy = true; @@ -936,7 +979,7 @@ void s3virge_vga_device::command_start() s3virge.s3d.bitblt_current_pixel = 0; s3virge.s3d.bitblt_pixel_pos = 0; s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR] = 0xffffffff; // win31 never sets this? - LOGMMIO("Started BitBLT command [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); + LOGCMD("Started BitBLT command [%u]\n", s3virge.s3d.cmd_fifo_current_ptr); //if(((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17) == 0xf0) machine().debug_break(); break; } @@ -958,10 +1001,31 @@ void s3virge_vga_device::command_finish() command_start(); else s3virge.s3d.busy = false; - //machine().debug_break(); + LOGMMIO("Command finished [%u] (%u slots free)\n",s3virge.s3d.cmd_fifo_current_ptr,s3virge.s3d.cmd_fifo_slots_free); } +void s3virge_vga_device::line2d_step() +{ + command_finish(); +} + +void s3virge_vga_device::poly2d_step() +{ + command_finish(); +} + +void s3virge_vga_device::line3d_step() +{ + command_finish(); +} + +void s3virge_vga_device::poly3d_step() +{ + command_finish(); +} + + uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat) { uint32_t ret = 0; @@ -1373,6 +1437,18 @@ void s3virge_vga_device::device_timer(emu_timer &timer, device_timer_id id, int case S3D_STATE_IDLE: m_draw_timer->adjust(attotime::zero); break; + case S3D_STATE_2DLINE: + line2d_step(); + break; + case S3D_STATE_2DPOLY: + poly2d_step(); + break; + case S3D_STATE_3DLINE: + line3d_step(); + break; + case S3D_STATE_3DPOLY: + poly3d_step(); + break; case S3D_STATE_BITBLT: bitblt_step(); break; diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h index 997377fcd38..558dcbad189 100644 --- a/src/devices/bus/isa/s3virge.h +++ b/src/devices/bus/isa/s3virge.h @@ -22,6 +22,8 @@ public: // construction/destruction s3virge_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + auto linear_config_changed() { return m_linear_config_changed_cb.bind(); } + virtual READ8_MEMBER(port_03b0_r) override; virtual WRITE8_MEMBER(port_03b0_w) override; virtual READ8_MEMBER(port_03c0_r) override; @@ -54,6 +56,7 @@ public: uint32_t get_linear_address() { return s3virge.linear_address; } void set_linear_address(uint32_t addr) { s3virge.linear_address = addr; } uint8_t get_linear_address_size() { return s3virge.linear_address_size; } + uint32_t get_linear_address_size_full() { return s3virge.linear_address_size_full; } bool is_linear_address_active() { return s3virge.linear_address_enable; } bool is_new_mmio_active() { return s3.cr53 & 0x08; } uint16_t dest_stride() @@ -236,11 +239,18 @@ protected: } uint32_t GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat); bool advance_pixel(); + + devcb_write_line m_linear_config_changed_cb; + private: emu_timer* m_draw_timer; void bitblt_step(); void bitblt_colour_step(); void bitblt_monosrc_step(); + void line2d_step(); + void poly2d_step(); + void line3d_step(); + void poly3d_step(); void add_command(int cmd_type); void command_start(); void command_finish(); diff --git a/src/devices/bus/isa/svga_s3.cpp b/src/devices/bus/isa/svga_s3.cpp index ddac8fc77c1..26225d06215 100644 --- a/src/devices/bus/isa/svga_s3.cpp +++ b/src/devices/bus/isa/svga_s3.cpp @@ -150,6 +150,17 @@ void isa16_s3virge_device::device_add_mconfig(machine_config &config) screen.set_screen_update(m_vga, FUNC(s3virge_vga_device::screen_update)); S3VIRGE(config, m_vga, 0).set_screen("screen"); + m_vga->linear_config_changed().set(FUNC(isa16_s3virge_device::linear_config_changed_w)); +} + +//------------------------------------------------- +// linear_config_changed_w - callback to indicate +// enabling, disabling, or changig of the linear +// framebuffer configuration. +//------------------------------------------------- + +WRITE_LINE_MEMBER(isa16_s3virge_device::linear_config_changed_w) +{ } //------------------------------------------------- @@ -229,6 +240,33 @@ void isa16_s3virgedx_device::device_add_mconfig(machine_config &config) screen.set_screen_update(m_vga, FUNC(s3virgedx_vga_device::screen_update)); S3VIRGEDX(config, m_vga, 0).set_screen("screen"); + m_vga->linear_config_changed().set(FUNC(isa16_s3virgedx_device::linear_config_changed_w)); +} + +//------------------------------------------------- +// linear_config_changed_w - callback to indicate +// enabling, disabling, or changig of the linear +// framebuffer configuration. +//------------------------------------------------- + +WRITE_LINE_MEMBER(isa16_s3virgedx_device::linear_config_changed_w) +{ + const bool old = m_lfb_enable; + m_lfb_enable = state; + if (state) + { + if (old) + { + m_isa->unmap_readwrite(m_lfb_start, m_lfb_end); + } + m_lfb_start = m_vga->get_linear_address(); + m_lfb_end = m_lfb_start + m_vga->get_linear_address_size_full() - 1; + m_isa->install_memory(m_lfb_start, m_lfb_end, read8_delegate(*m_vga, FUNC(s3virge_vga_device::fb_r)), write8_delegate(*m_vga, FUNC(s3virge_vga_device::fb_w))); + } + else + { + m_isa->unmap_readwrite(m_lfb_start, m_lfb_end); + } } //------------------------------------------------- @@ -271,6 +309,10 @@ void isa16_s3virgedx_device::device_start() m_isa->install_device(0x03d0, 0x03df, read8_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w))); m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w))); + + save_item(NAME(m_lfb_enable)); + save_item(NAME(m_lfb_start)); + save_item(NAME(m_lfb_end)); } //------------------------------------------------- @@ -279,6 +321,9 @@ void isa16_s3virgedx_device::device_start() void isa16_s3virgedx_device::device_reset() { + m_lfb_enable = m_vga->is_linear_address_active(); + m_lfb_start = m_vga->get_linear_address(); + m_lfb_end = m_lfb_start + m_vga->get_linear_address_size_full() - 1; } @@ -309,6 +354,17 @@ void isa16_stealth3d2kpro_device::device_add_mconfig(machine_config &config) screen.set_screen_update(m_vga, FUNC(s3virgedx_rev1_vga_device::screen_update)); S3VIRGEDX1(config, m_vga, 0).set_screen("screen"); + m_vga->linear_config_changed().set(FUNC(isa16_stealth3d2kpro_device::linear_config_changed_w)); +} + +//------------------------------------------------- +// linear_config_changed_w - callback to indicate +// enabling, disabling, or changig of the linear +// framebuffer configuration. +//------------------------------------------------- + +WRITE_LINE_MEMBER(isa16_stealth3d2kpro_device::linear_config_changed_w) +{ } //------------------------------------------------- diff --git a/src/devices/bus/isa/svga_s3.h b/src/devices/bus/isa/svga_s3.h index 3889a2ed8e8..3c4e891c750 100644 --- a/src/devices/bus/isa/svga_s3.h +++ b/src/devices/bus/isa/svga_s3.h @@ -58,6 +58,8 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w); + private: required_device m_vga; }; @@ -81,8 +83,13 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w); + private: required_device m_vga; + bool m_lfb_enable; + uint32_t m_lfb_start; + uint32_t m_lfb_end; }; class isa16_stealth3d2kpro_device : @@ -104,6 +111,8 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w); + private: required_device m_vga; }; -- cgit v1.2.3