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)
This commit is contained in:
Sergey Svishchev 2018-03-24 23:09:49 +03:00 committed by Vas Crabb
parent a8d254d416
commit ecb3c47796
2 changed files with 128 additions and 55 deletions

View File

@ -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<bitmap_ind16>(width, height);
m_bitmap->fill(0);
m_vram = std::make_unique<uint8_t[]>(0x78000);
space.install_readwrite_bank(0x80000, 0xf7fff, "vram");
membank("vram")->set_base(m_vram.get());
m_eram = std::make_unique<uint8_t[]>(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++;
}
}

View File

@ -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<uint8_t[]> m_vram;
std::unique_ptr<uint8_t[]> m_eram;
uint8_t m_stateparam[16];
uint8_t m_lut[256*3];
uint8_t m_lut[256 * 3];
std::unique_ptr<bitmap_ind16> m_bitmap;
int m_accel;
};