mirror of
https://github.com/holub/mame
synced 2025-10-09 09:44:40 +03:00
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:
parent
a8d254d416
commit
ecb3c47796
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
IBM Professional Graphics Controller (PGC), skeleton driver.
|
IBM Professional Graphics Controller (PGC).
|
||||||
|
|
||||||
Designed for IBM by Vermont Microsystems. References:
|
Designed for IBM by Vermont Microsystems. References:
|
||||||
|
|
||||||
@ -16,13 +16,13 @@
|
|||||||
http://www.seasip.info/VintagePC/pgc.html
|
http://www.seasip.info/VintagePC/pgc.html
|
||||||
|
|
||||||
To do:
|
To do:
|
||||||
- decode memory map
|
- pass IBM diagnostics (currently fail with code 3905)
|
||||||
- various VRAM write modes
|
- CGA emulator
|
||||||
- what's up with irq 3 (= vblank irq)? (causes soft reset)
|
- what's up with irq 3 (= vblank irq)? (causes soft reset)
|
||||||
- "test pin of the microprocessor samples the hsync pulse"
|
- "test pin of the microprocessor samples the hsync pulse"
|
||||||
- CGA emulator
|
|
||||||
- bus state handling?
|
- bus state handling?
|
||||||
- VRAM address translator ROM?
|
- 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"
|
#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"
|
#define PGC_SCREEN_NAME "pgc_screen"
|
||||||
|
|
||||||
@ -111,18 +112,16 @@ void isa8_pgc_device::pgc_map(address_map &map)
|
|||||||
map(0x00000, 0x07fff).rom();
|
map(0x00000, 0x07fff).rom();
|
||||||
map(0x08000, 0x0ffff).rom().region("maincpu", 0x8000);
|
map(0x08000, 0x0ffff).rom().region("maincpu", 0x8000);
|
||||||
map(0x10000, 0x1001f).rw(this, FUNC(isa8_pgc_device::stateparam_r), FUNC(isa8_pgc_device::stateparam_w));
|
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(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));
|
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);
|
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 =
|
static const gfx_layout pgc_charlayout =
|
||||||
{
|
{
|
||||||
8, 16, /* 8x16 pixels */
|
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)
|
MACHINE_CONFIG_START(isa8_pgc_device::device_add_mconfig)
|
||||||
MCFG_CPU_ADD("maincpu", I8088, XTAL(24'000'000)/3)
|
MCFG_CPU_ADD("maincpu", I8088, XTAL(24'000'000)/3)
|
||||||
MCFG_CPU_PROGRAM_MAP(pgc_map)
|
MCFG_CPU_PROGRAM_MAP(pgc_map)
|
||||||
MCFG_CPU_IO_MAP(pgc_io)
|
|
||||||
#if 0
|
#if 0
|
||||||
MCFG_CPU_VBLANK_INT_DRIVER(PGC_SCREEN_NAME, isa8_pgc_device, vblank_irq)
|
MCFG_CPU_VBLANK_INT_DRIVER(PGC_SCREEN_NAME, isa8_pgc_device, vblank_irq)
|
||||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(isa8_pgc_device, irq_callback)
|
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(isa8_pgc_device, irq_callback)
|
||||||
@ -219,7 +217,6 @@ isa8_pgc_device::isa8_pgc_device(const machine_config &mconfig, device_type type
|
|||||||
|
|
||||||
void isa8_pgc_device::device_start()
|
void isa8_pgc_device::device_start()
|
||||||
{
|
{
|
||||||
address_space &space = m_cpu->space( AS_PROGRAM );
|
|
||||||
int width = PGC_DISP_HORZ;
|
int width = PGC_DISP_HORZ;
|
||||||
int height = PGC_DISP_VERT;
|
int height = PGC_DISP_VERT;
|
||||||
|
|
||||||
@ -237,9 +234,6 @@ void isa8_pgc_device::device_start()
|
|||||||
m_bitmap->fill(0);
|
m_bitmap->fill(0);
|
||||||
|
|
||||||
m_vram = std::make_unique<uint8_t[]>(0x78000);
|
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);
|
m_eram = std::make_unique<uint8_t[]>(0x8000);
|
||||||
|
|
||||||
machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&isa8_pgc_device::reset_common, this));
|
machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&isa8_pgc_device::reset_common, this));
|
||||||
@ -257,6 +251,7 @@ void isa8_pgc_device::device_reset()
|
|||||||
{
|
{
|
||||||
memset(m_stateparam, 0, sizeof(m_stateparam));
|
memset(m_stateparam, 0, sizeof(m_stateparam));
|
||||||
memset(m_lut, 0, sizeof(m_lut));
|
memset(m_lut, 0, sizeof(m_lut));
|
||||||
|
m_accel = 0;
|
||||||
|
|
||||||
m_commarea = memregion("commarea")->base();
|
m_commarea = memregion("commarea")->base();
|
||||||
if (BIT(ioport("DSW")->read(), 1))
|
if (BIT(ioport("DSW")->read(), 1))
|
||||||
@ -269,61 +264,135 @@ void isa8_pgc_device::device_reset()
|
|||||||
|
|
||||||
INTERRUPT_GEN_MEMBER(isa8_pgc_device::vblank_irq)
|
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);
|
m_cpu->set_input_line(0, ASSERT_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRQ_CALLBACK_MEMBER(isa8_pgc_device::irq_callback)
|
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);
|
m_cpu->set_input_line(0, CLEAR_LINE);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory handlers
|
// 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;
|
uint8_t ret;
|
||||||
|
|
||||||
ret = m_stateparam[offset >> 1];
|
ret = m_stateparam[offset >> 1];
|
||||||
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_MEMBER( isa8_pgc_device::stateparam_w ) {
|
WRITE8_MEMBER(isa8_pgc_device::stateparam_w)
|
||||||
|
{
|
||||||
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
|
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;
|
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;
|
uint8_t o = (offset >> 1) * 3;
|
||||||
|
|
||||||
if (offset & 1) {
|
if (offset & 1)
|
||||||
|
{
|
||||||
m_lut[o + 2] = (data & 15) << 4;
|
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] );
|
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",
|
LOG("lut W @ %02X <- %d %d %d\n",
|
||||||
offset >> 1, m_lut[o], m_lut[o + 1], m_lut[o + 2] ));
|
offset >> 1, m_lut[o], m_lut[o + 1], m_lut[o + 2] );
|
||||||
} else {
|
} else {
|
||||||
m_lut[o ] = data & 0xf0;
|
m_lut[o ] = data & 0xf0;
|
||||||
m_lut[o + 1] = (data & 15) << 4;
|
m_lut[o + 1] = (data & 15) << 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
READ8_MEMBER( isa8_pgc_device::init_r ) {
|
READ8_MEMBER(isa8_pgc_device::init_r)
|
||||||
DBG_LOG(1,"INIT",("unmapping ROM\n"));
|
{
|
||||||
|
LOG("INIT: unmapping ROM\n");
|
||||||
space.unmap_read(0xf8000, 0xfffff);
|
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");
|
space.install_readwrite_bank(0xf8000, 0xfffff, "eram");
|
||||||
membank("eram")->set_base(m_eram.get());
|
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,
|
space.install_write_handler(0xf8400, 0xf85ff,
|
||||||
write8_delegate(FUNC(isa8_pgc_device::lut_w), this));
|
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;
|
uint8_t *v;
|
||||||
|
|
||||||
// XXX hpos shifts every frame -- fix
|
// XXX hpos shifts every frame -- fix
|
||||||
if (y == 0) DBG_LOG(2,"scanline_cb",
|
if (y == 0) LOGCMD("scanline_cb frame %d x %.4d y %.3d\n",
|
||||||
("frame %d x %.4d y %.3d\n",
|
(int) m_screen->frame_number(), m_screen->hpos(), y);
|
||||||
(int) m_screen->frame_number(), m_screen->hpos(), y));
|
|
||||||
|
|
||||||
if (y < PGC_VERT_START) return;
|
if (y < PGC_VERT_START) return;
|
||||||
y -= PGC_VERT_START;
|
y -= PGC_VERT_START;
|
||||||
@ -349,7 +417,8 @@ TIMER_DEVICE_CALLBACK_MEMBER(isa8_pgc_device::scanline_callback)
|
|||||||
v = &m_vram[y * 1024];
|
v = &m_vram[y * 1024];
|
||||||
p = &m_bitmap->pix16(y, 0);
|
p = &m_bitmap->pix16(y, 0);
|
||||||
|
|
||||||
for (x = 0; x < PGC_DISP_HORZ; x++) {
|
for (x = 0; x < PGC_DISP_HORZ; x++)
|
||||||
|
{
|
||||||
*p++ = *v++;
|
*p++ = *v++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,13 @@ private:
|
|||||||
INTERRUPT_GEN_MEMBER(vblank_irq);
|
INTERRUPT_GEN_MEMBER(vblank_irq);
|
||||||
IRQ_CALLBACK_MEMBER(irq_callback);
|
IRQ_CALLBACK_MEMBER(irq_callback);
|
||||||
|
|
||||||
|
DECLARE_WRITE8_MEMBER(vram_w);
|
||||||
|
DECLARE_READ8_MEMBER(vram_r);
|
||||||
DECLARE_WRITE8_MEMBER(stateparam_w);
|
DECLARE_WRITE8_MEMBER(stateparam_w);
|
||||||
DECLARE_READ8_MEMBER(stateparam_r);
|
DECLARE_READ8_MEMBER(stateparam_r);
|
||||||
DECLARE_WRITE8_MEMBER(lut_w);
|
DECLARE_WRITE8_MEMBER(lut_w);
|
||||||
DECLARE_READ8_MEMBER(init_r);
|
DECLARE_READ8_MEMBER(init_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(accel_w);
|
||||||
|
|
||||||
void reset_common();
|
void reset_common();
|
||||||
|
|
||||||
@ -65,6 +68,7 @@ private:
|
|||||||
uint8_t m_stateparam[16];
|
uint8_t m_stateparam[16];
|
||||||
uint8_t m_lut[256 * 3];
|
uint8_t m_lut[256 * 3];
|
||||||
std::unique_ptr<bitmap_ind16> m_bitmap;
|
std::unique_ptr<bitmap_ind16> m_bitmap;
|
||||||
|
int m_accel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user