From ecb3c47796135d2b7440ddff76130d5fd4cef908 Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Sat, 24 Mar 2018 23:09:49 +0300 Subject: [PATCH] isa/pgc: accelerated VRAM writes + cleanups (#3385) * isa/pgc: use logmacro.h (nw) * isa/pgc: implement accelerated VRAM writes * isa/pgc: code style cleanup (nw) --- src/devices/bus/isa/pgc.cpp | 167 +++++++++++++++++++++++++----------- src/devices/bus/isa/pgc.h | 16 ++-- 2 files changed, 128 insertions(+), 55 deletions(-) diff --git a/src/devices/bus/isa/pgc.cpp b/src/devices/bus/isa/pgc.cpp index 97d46e98125..b37beba811f 100644 --- a/src/devices/bus/isa/pgc.cpp +++ b/src/devices/bus/isa/pgc.cpp @@ -3,7 +3,7 @@ /*************************************************************************** - IBM Professional Graphics Controller (PGC), skeleton driver. + IBM Professional Graphics Controller (PGC). Designed for IBM by Vermont Microsystems. References: @@ -16,13 +16,13 @@ http://www.seasip.info/VintagePC/pgc.html To do: - - decode memory map - - various VRAM write modes + - pass IBM diagnostics (currently fail with code 3905) + - CGA emulator - what's up with irq 3 (= vblank irq)? (causes soft reset) - "test pin of the microprocessor samples the hsync pulse" - - CGA emulator - bus state handling? - VRAM address translator ROM? + - clones/compatibles? CompuShow apparently was tested with a clone and sends opcode E6, writes 2 to C630C ***************************************************************************/ @@ -32,17 +32,18 @@ #include "screen.h" -#define VERBOSE_PGC 1 +//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already +#define LOG_VRAM (1U << 1) +#define LOG_CMD (1U << 2) + +//#define VERBOSE (LOG_GENERAL | LOG_VRAM) +//#define LOG_OUTPUT_STREAM std::cout + +#include "logmacro.h" + +#define LOGV(...) LOGMASKED(LOG_VRAM, __VA_ARGS__) +#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) -#define DBG_LOG(N,M,A) \ - do { \ - if(VERBOSE_PGC>=N) \ - { \ - if( M ) \ - logerror("%11.6f at %s: %-24s",machine().time().as_double(),machine().describe_context(),(char*)M ); \ - logerror A; \ - } \ - } while (0) #define PGC_SCREEN_NAME "pgc_screen" @@ -111,18 +112,16 @@ void isa8_pgc_device::pgc_map(address_map &map) map(0x00000, 0x07fff).rom(); map(0x08000, 0x0ffff).rom().region("maincpu", 0x8000); map(0x10000, 0x1001f).rw(this, FUNC(isa8_pgc_device::stateparam_r), FUNC(isa8_pgc_device::stateparam_w)); -// AM_RANGE(0x18000, 0x18fff) AM_RAM // ?? +// map(0x18000, 0x18fff).ram(); // ?? map(0x28000, 0x287ff).ram().region("commarea", 0).mirror(0x800); + map(0x32001, 0x32001).nopw(); + map(0x32020, 0x3203f).w(this, FUNC(isa8_pgc_device::accel_w)); map(0x3c000, 0x3c001).r(this, FUNC(isa8_pgc_device::init_r)); -// AM_RANGE(0x3e000, 0x3efff) AM_RAM // ?? +// map(0x3e000, 0x3efff).ram(); // ?? + map(0x80000, 0xf7fff).rw(this, FUNC(isa8_pgc_device::vram_r), FUNC(isa8_pgc_device::vram_w)); map(0xf8000, 0xfffff).rom().region("maincpu", 0x8000); } -void isa8_pgc_device::pgc_io(address_map &map) -{ - map.unmap_value_high(); -} - static const gfx_layout pgc_charlayout = { 8, 16, /* 8x16 pixels */ @@ -155,7 +154,6 @@ DEFINE_DEVICE_TYPE(ISA8_PGC, isa8_pgc_device, "isa_ibm_pgc", "IBM Professional G MACHINE_CONFIG_START(isa8_pgc_device::device_add_mconfig) MCFG_CPU_ADD("maincpu", I8088, XTAL(24'000'000)/3) MCFG_CPU_PROGRAM_MAP(pgc_map) - MCFG_CPU_IO_MAP(pgc_io) #if 0 MCFG_CPU_VBLANK_INT_DRIVER(PGC_SCREEN_NAME, isa8_pgc_device, vblank_irq) MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(isa8_pgc_device, irq_callback) @@ -182,7 +180,7 @@ MACHINE_CONFIG_END const tiny_rom_entry *isa8_pgc_device::device_rom_region() const { - return ROM_NAME( pgc ); + return ROM_NAME(pgc); } //------------------------------------------------- @@ -191,7 +189,7 @@ const tiny_rom_entry *isa8_pgc_device::device_rom_region() const ioport_constructor isa8_pgc_device::device_input_ports() const { - return INPUT_PORTS_NAME( pgc ); + return INPUT_PORTS_NAME(pgc); } //************************************************************************** @@ -219,7 +217,6 @@ isa8_pgc_device::isa8_pgc_device(const machine_config &mconfig, device_type type void isa8_pgc_device::device_start() { - address_space &space = m_cpu->space( AS_PROGRAM ); int width = PGC_DISP_HORZ; int height = PGC_DISP_VERT; @@ -228,18 +225,15 @@ void isa8_pgc_device::device_start() set_isa_device(); - for (int i = 0; i < 256; i++ ) + for (int i = 0; i < 256; i++) { - m_palette->set_pen_color( i, 0, 0, 0 ); + m_palette->set_pen_color(i, 0, 0, 0); } m_bitmap = std::make_unique(width, height); m_bitmap->fill(0); m_vram = std::make_unique(0x78000); - space.install_readwrite_bank(0x80000, 0xf7fff, "vram"); - membank("vram")->set_base(m_vram.get()); - m_eram = std::make_unique(0x8000); machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&isa8_pgc_device::reset_common, this)); @@ -247,7 +241,7 @@ void isa8_pgc_device::device_start() void isa8_pgc_device::reset_common() { - address_space &space = m_cpu->space( AS_PROGRAM ); + address_space &space = m_cpu->space(AS_PROGRAM); space.unmap_readwrite(0xf8000, 0xfffff); space.install_rom(0xf8000, 0xfffff, memregion("maincpu")->base() + 0x8000); @@ -257,6 +251,7 @@ void isa8_pgc_device::device_reset() { memset(m_stateparam, 0, sizeof(m_stateparam)); memset(m_lut, 0, sizeof(m_lut)); + m_accel = 0; m_commarea = memregion("commarea")->base(); if (BIT(ioport("DSW")->read(), 1)) @@ -269,61 +264,135 @@ void isa8_pgc_device::device_reset() INTERRUPT_GEN_MEMBER(isa8_pgc_device::vblank_irq) { - DBG_LOG(2,"irq",("vblank_irq\n")); + LOGCMD("vblank_irq\n"); m_cpu->set_input_line(0, ASSERT_LINE); } IRQ_CALLBACK_MEMBER(isa8_pgc_device::irq_callback) { - DBG_LOG(2,"irq",("irq_callback\n")); + LOGCMD("irq_callback\n"); m_cpu->set_input_line(0, CLEAR_LINE); return 3; } // memory handlers -READ8_MEMBER( isa8_pgc_device::stateparam_r ) { +READ8_MEMBER(isa8_pgc_device::vram_r) +{ + uint8_t ret; + + ret = m_vram[offset]; + LOGV("vram R @ %02x == %02x\n", offset, ret); + return ret; +} + +/* + * accel modes (decimal) + * + * 0 - none + * 1 - write 4 pixels, starting at offset + * 2 - write up to 4 pixels, ending at offset + * 3 - write up to 4 pixels, starting at offset + * 5 - write 20 pixels, starting at offset + * 9 - write up to 5 pixel groups, ending at offset. offset may be in the middle of pixel group. + * 13 - write up to 5 pixel groups, starting at offset. + */ +WRITE8_MEMBER(isa8_pgc_device::vram_w) +{ + bool handled = true; + + switch (m_accel) + { + case 0: + m_vram[offset] = data; + break; + + case 1: + std::fill(&m_vram[offset], &m_vram[offset + 4], data); + break; + + case 2: + std::fill(&m_vram[offset & ~3], &m_vram[offset + 1], data); + break; + + case 3: + std::fill(&m_vram[offset], &m_vram[(offset + 4) & ~3], data); + break; + + case 5: + std::fill(&m_vram[offset], &m_vram[offset + 20], data); + break; + + case 9: + std::fill(&m_vram[offset - ((offset % 1024) % 20)], &m_vram[(offset + 4) & ~3], data); + break; + + case 13: + std::fill(&m_vram[offset], &m_vram[(offset + 20) - ((offset % 1024) + 20) % 20], data); + break; + + default: + m_vram[offset] = data; + handled = false; + break; + } + LOGV("vram W @ %02x <- %02x (accel %d)%s\n", offset, data, m_accel, + handled ? "" : " (unsupported)"); +} + +WRITE8_MEMBER(isa8_pgc_device::accel_w) +{ + m_accel = offset >> 1; + LOGV("accel @ %05x <- %02x (%d)\n", 0x32020 + offset, data, m_accel); +} + +READ8_MEMBER(isa8_pgc_device::stateparam_r) +{ uint8_t ret; ret = m_stateparam[offset >> 1]; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(1,"stateparam",("R @ %02x == %02x\n", offset, ret)); + LOG("stateparam R @ %02x == %02x\n", offset, ret); } return ret; } -WRITE8_MEMBER( isa8_pgc_device::stateparam_w ) { +WRITE8_MEMBER(isa8_pgc_device::stateparam_w) +{ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(1,"stateparam",("W @ %02x <- %02x\n", offset, data)); + LOG("stateparam W @ %02x <- %02x\n", offset, data); } m_stateparam[offset >> 1] = data; } -WRITE8_MEMBER( isa8_pgc_device::lut_w ) { +WRITE8_MEMBER(isa8_pgc_device::lut_w) +{ uint8_t o = (offset >> 1) * 3; - if (offset & 1) { + if (offset & 1) + { m_lut[o + 2] = (data & 15) << 4; m_palette->set_pen_color( offset >> 1, m_lut[o], m_lut[o + 1], m_lut[o + 2] ); - DBG_LOG(1,"lut",("W @ %02X <- %d %d %d\n", - offset >> 1, m_lut[o], m_lut[o + 1], m_lut[o + 2] )); + LOG("lut W @ %02X <- %d %d %d\n", + offset >> 1, m_lut[o], m_lut[o + 1], m_lut[o + 2] ); } else { m_lut[o ] = data & 0xf0; m_lut[o + 1] = (data & 15) << 4; } } -READ8_MEMBER( isa8_pgc_device::init_r ) { - DBG_LOG(1,"INIT",("unmapping ROM\n")); +READ8_MEMBER(isa8_pgc_device::init_r) +{ + LOG("INIT: unmapping ROM\n"); space.unmap_read(0xf8000, 0xfffff); - DBG_LOG(1,"INIT",("mapping emulator RAM\n")); + LOG("INIT: mapping emulator RAM\n"); space.install_readwrite_bank(0xf8000, 0xfffff, "eram"); membank("eram")->set_base(m_eram.get()); - DBG_LOG(1,"INIT",("mapping LUT\n")); + LOG("INIT: mapping LUT\n"); space.install_write_handler(0xf8400, 0xf85ff, write8_delegate(FUNC(isa8_pgc_device::lut_w), this)); @@ -337,9 +406,8 @@ TIMER_DEVICE_CALLBACK_MEMBER(isa8_pgc_device::scanline_callback) uint8_t *v; // XXX hpos shifts every frame -- fix - if (y == 0) DBG_LOG(2,"scanline_cb", - ("frame %d x %.4d y %.3d\n", - (int) m_screen->frame_number(), m_screen->hpos(), y)); + if (y == 0) LOGCMD("scanline_cb frame %d x %.4d y %.3d\n", + (int) m_screen->frame_number(), m_screen->hpos(), y); if (y < PGC_VERT_START) return; y -= PGC_VERT_START; @@ -349,7 +417,8 @@ TIMER_DEVICE_CALLBACK_MEMBER(isa8_pgc_device::scanline_callback) v = &m_vram[y * 1024]; p = &m_bitmap->pix16(y, 0); - for (x = 0; x < PGC_DISP_HORZ; x++) { + for (x = 0; x < PGC_DISP_HORZ; x++) + { *p++ = *v++; } } diff --git a/src/devices/bus/isa/pgc.h b/src/devices/bus/isa/pgc.h index 91184a4ee8a..2982cb81c4f 100644 --- a/src/devices/bus/isa/pgc.h +++ b/src/devices/bus/isa/pgc.h @@ -40,15 +40,18 @@ protected: private: uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - TIMER_DEVICE_CALLBACK_MEMBER( scanline_callback ); + TIMER_DEVICE_CALLBACK_MEMBER(scanline_callback); INTERRUPT_GEN_MEMBER(vblank_irq); IRQ_CALLBACK_MEMBER(irq_callback); - DECLARE_WRITE8_MEMBER( stateparam_w ); - DECLARE_READ8_MEMBER( stateparam_r ); - DECLARE_WRITE8_MEMBER( lut_w ); - DECLARE_READ8_MEMBER( init_r ); + DECLARE_WRITE8_MEMBER(vram_w); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(stateparam_w); + DECLARE_READ8_MEMBER(stateparam_r); + DECLARE_WRITE8_MEMBER(lut_w); + DECLARE_READ8_MEMBER(init_r); + DECLARE_WRITE8_MEMBER(accel_w); void reset_common(); @@ -63,8 +66,9 @@ private: std::unique_ptr m_vram; std::unique_ptr m_eram; uint8_t m_stateparam[16]; - uint8_t m_lut[256*3]; + uint8_t m_lut[256 * 3]; std::unique_ptr m_bitmap; + int m_accel; };