isa_ibm_pgc: new skeleton driver

This commit is contained in:
Sergey Svishchev 2014-11-12 02:05:36 +03:00
parent 00a276f7d1
commit b7f4c082e6
5 changed files with 444 additions and 0 deletions

View File

@ -779,6 +779,8 @@ if (BUSES["ISA"]~=null) then
MAME_DIR .. "src/emu/bus/isa/svga_cirrus.h",
MAME_DIR .. "src/emu/bus/isa/ega.c",
MAME_DIR .. "src/emu/bus/isa/ega.h",
MAME_DIR .. "src/emu/bus/isa/pgc.c",
MAME_DIR .. "src/emu/bus/isa/pgc.h",
MAME_DIR .. "src/emu/bus/isa/vga.c",
MAME_DIR .. "src/emu/bus/isa/vga.h",
MAME_DIR .. "src/emu/bus/isa/vga_ati.c",

View File

@ -18,6 +18,7 @@ SLOT_INTERFACE_START( pc_isa8_cards )
SLOT_INTERFACE("aga", ISA8_AGA)
SLOT_INTERFACE("aga_pc200", ISA8_AGA_PC200)
SLOT_INTERFACE("ega", ISA8_EGA)
SLOT_INTERFACE("pgc", ISA8_PGC)
SLOT_INTERFACE("svga_et4k", ISA8_SVGA_ET4K)
SLOT_INTERFACE("num9rev",ISA8_NUM_9_REV)
SLOT_INTERFACE("com", ISA8_COM)
@ -55,6 +56,7 @@ SLOT_INTERFACE_START( pc_isa16_cards )
SLOT_INTERFACE("cga", ISA8_CGA)
SLOT_INTERFACE("wyse700", ISA8_WYSE700)
SLOT_INTERFACE("ega", ISA8_EGA)
SLOT_INTERFACE("pgc", ISA8_PGC)
SLOT_INTERFACE("vga", ISA8_VGA)
SLOT_INTERFACE("svga_et4k", ISA8_SVGA_ET4K)
SLOT_INTERFACE("num9rev",ISA8_NUM_9_REV)

View File

@ -18,6 +18,7 @@
#include "cga.h"
#include "aga.h"
#include "ega.h"
#include "pgc.h"
#include "vga.h"
#include "vga_ati.h"
#include "svga_cirrus.h"

372
src/emu/bus/isa/pgc.c Normal file
View File

@ -0,0 +1,372 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
IBM Professional Graphics Controller (PGC), skeleton driver.
Designed for IBM by Vermont Microsystems. References:
IBM Options and Adapters manual
http://www.minuszerodegrees.net/oa/OA%20-%20IBM%20Professional%20Graphics%20Controller.pdf
http://bitsavers.org/pdf/ibm/pc/cards/Technical_Reference_Options_and_Adapters_Volume_3.pdf
IBM Systems Journal white paper
http://wayback.archive.org/web/20061015235146/http://www.research.ibm.com/journal/sj/241/ibmsj2401D.pdf
John Elliott's page
http://www.seasip.info/VintagePC/pgc.html
To do:
- memory map (restore ROM mapping on reset, ...)
- various VRAM write modes
- what's up with irq 3 (= vblank irq)?
- "test pin of the microprocessor samples the hsync pulse"
- CGA emulator
- bus state handling?
- VRAM address translator ROM?
***************************************************************************/
#include "emu.h"
//nclude "machine/ram.h"
#include "pgc.h"
#define VERBOSE_PGC 1
#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_TOTAL_HORZ 820
#define PGC_DISP_HORZ 640
#define PGC_HORZ_START 80
#define PGC_TOTAL_VERT 508
#define PGC_DISP_VERT 480
#define PGC_VERT_START 10
/*
Prototypes
*/
ROM_START( pgc )
ROM_REGION(0x100000, "maincpu", 0)
ROM_DEFAULT_BIOS("1985")
ROM_SYSTEM_BIOS(0, "1984", "1984 firmware, P/N 6137322/3")
ROMX_LOAD("ibm_6137323_pgc_card_27256.bin", 0x00000, 0x8000, CRC(f564f342) SHA1(c5ef17fd1569043cb59f61faf828ea8b0ee95526), ROM_BIOS(1))
ROMX_LOAD("ibm_6137322_pgc_card_27256.bin", 0x08000, 0x8000, CRC(5e6cc82f) SHA1(45b3ffb5a9c51986862f8d47b3e03dcaaf4073d5), ROM_BIOS(1))
ROM_SYSTEM_BIOS(1, "1985", "1985 firmware, P/N 59X7354/5")
ROMX_LOAD("pgc_u44.bin", 0x00000, 0x8000, CRC(71280241) SHA1(7042ccd4ebd03f576a256a433b8aa38d1b4fefa8), ROM_BIOS(2))
ROMX_LOAD("pgc_u43.bin", 0x08000, 0x8000, CRC(923f5ea3) SHA1(2b2a55d64b20d3a613b00c51443105aa03eca5d6), ROM_BIOS(2))
ROM_REGION(0x800, "commarea", ROMREGION_ERASE00)
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD("pgc_u27.bin", 0x0000, 0x1000, CRC(6be256cc) SHA1(deb1195886268dcddce10459911e020f7a9f74f7))
ROM_END
static INPUT_PORTS_START( pgc )
PORT_START("DSW")
/*
PORT_DIPNAME( 0x01, 0x00, "CGA emulator")
PORT_DIPSETTING( 0x00, DEF_STR(No) )
PORT_DIPSETTING( 0x01, DEF_STR(Yes) )
*/
PORT_DIPNAME( 0x02, 0x00, "Communication area")
PORT_DIPSETTING( 0x00, "C6000" )
PORT_DIPSETTING( 0x02, "C6400" )
INPUT_PORTS_END
/*
write only
30000 LUT WR O L
30001 LUT WR I L
32000 MODE WT L
32001 NIBBLE WT L
3200A ??
34000 FUNCTION WT L
34001 STARTADD WT L
36001 CURSOR WT L
read only
38000 LUT RD O L
38001 LUT RD I L
3C001 INIT L/INIT H
*/
static ADDRESS_MAP_START( pgc_map, AS_PROGRAM, 8, isa8_pgc_device )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00000, 0x07fff) AM_ROM
AM_RANGE(0x08000, 0x0ffff) AM_ROM AM_REGION("maincpu", 0x8000)
AM_RANGE(0x10000, 0x1001f) AM_READWRITE(stateparam_r, stateparam_w)
// AM_RANGE(0x18000, 0x18fff) AM_RAM // ??
AM_RANGE(0x28000, 0x287ff) AM_RAM AM_REGION("commarea", 0) AM_MIRROR(0x800)
AM_RANGE(0x3c000, 0x3c001) AM_READ(init_r)
// AM_RANGE(0x3e000, 0x3efff) AM_RAM // ??
AM_RANGE(0xf8000, 0xfffff) AM_ROM AM_REGION("maincpu", 0x8000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( pgc_io, AS_IO, 8, isa8_pgc_device )
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_END
static const gfx_layout pgc_charlayout =
{
8, 16, /* 8x16 pixels */
256, /* 256 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8*16 /* every char takes 10 bytes */
};
static GFXDECODE_START( pgc )
GFXDECODE_REVERSEBITS("chargen", 0, pgc_charlayout, 0, 1)
GFXDECODE_END
MACHINE_CONFIG_FRAGMENT( pcvideo_pgc )
MCFG_CPU_ADD("maincpu", I8088, XTAL_24MHz/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)
#endif
MCFG_TIMER_DRIVER_ADD_PERIODIC("scantimer", isa8_pgc_device, scanline_callback,
attotime::from_hz(60*PGC_TOTAL_VERT))
MCFG_TIMER_START_DELAY(attotime::from_hz(XTAL_50MHz/(2*PGC_HORZ_START)))
MCFG_SCREEN_ADD(PGC_SCREEN_NAME, RASTER)
MCFG_SCREEN_RAW_PARAMS(XTAL_50MHz/2,
PGC_TOTAL_HORZ, PGC_HORZ_START, PGC_HORZ_START+PGC_DISP_HORZ,
PGC_TOTAL_VERT, PGC_VERT_START, PGC_VERT_START+PGC_DISP_VERT)
MCFG_SCREEN_UPDATE_DRIVER(isa8_pgc_device, screen_update)
MCFG_SCREEN_PALETTE("palette")
MCFG_GFXDECODE_ADD("gfxdecode", "palette", pgc)
MCFG_PALETTE_ADD( "palette", 256 )
MACHINE_CONFIG_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type ISA8_PGC = &device_creator<isa8_pgc_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor isa8_pgc_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( pcvideo_pgc );
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const rom_entry *isa8_pgc_device::device_rom_region() const
{
return ROM_NAME( pgc );
}
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor isa8_pgc_device::device_input_ports() const
{
return INPUT_PORTS_NAME( pgc );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// isa8_pgc_device - constructor
//-------------------------------------------------
isa8_pgc_device::isa8_pgc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, ISA8_PGC, "IBM Professional Graphics Controller", tag, owner, clock, "isa_ibm_pgc", __FILE__),
device_isa8_card_interface(mconfig, *this),
m_cpu(*this, "maincpu"),
m_screen(*this, PGC_SCREEN_NAME),
m_palette(*this, "palette")
{
}
isa8_pgc_device::isa8_pgc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_isa8_card_interface(mconfig, *this),
m_cpu(*this, "maincpu"),
m_screen(*this, PGC_SCREEN_NAME),
m_palette(*this, "palette")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void isa8_pgc_device::device_start()
{
address_space &space = m_cpu->space( AS_PROGRAM );
int width = PGC_DISP_HORZ;
int height = PGC_DISP_VERT;
if (m_palette != NULL && !m_palette->started())
throw device_missing_dependencies();
set_isa_device();
for (int i = 0; i < 256; i++ )
{
m_palette->set_pen_color( i, 0, 0, 0 );
}
m_bitmap = auto_bitmap_ind16_alloc(machine(), width, height);
m_bitmap->fill(0);
m_vram = auto_alloc_array(machine(), UINT8, 0x78000);
space.install_readwrite_bank(0x80000, 0xf7fff, "vram");
membank("vram")->set_base(m_vram);
m_eram = auto_alloc_array(machine(), UINT8, 0x8000);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void isa8_pgc_device::device_reset()
{
address_space &space = m_cpu->space( AS_PROGRAM );
memset(m_stateparam, 0, sizeof(m_stateparam));
memset(m_lut, 0, sizeof(m_lut));
m_commarea = memregion("commarea")->base();
if (BIT(ioport("DSW")->read(), 1))
m_isa->install_bank(0xc6400, 0xc67ff, 0, 0, "commarea", m_commarea);
else
m_isa->install_bank(0xc6000, 0xc63ff, 0, 0, "commarea", m_commarea);
#if 0
space.unmap_readwrite(0xf8000, 0xfffff);
space.install_rom(0xf8000, 0xfffff,
space.machine().root_device().memregion("maincpu")->base() + 0x8000);
#endif
}
//
INTERRUPT_GEN_MEMBER(isa8_pgc_device::vblank_irq)
{
DBG_LOG(2,"irq",("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"));
m_cpu->set_input_line(0, CLEAR_LINE);
return 3;
}
// memory handlers
READ8_MEMBER( isa8_pgc_device::stateparam_r ) {
UINT8 ret;
ret = m_stateparam[offset >> 1];
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(1,"stateparam",("R @ %02x == %02x\n", offset, ret));
}
return ret;
}
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));
}
m_stateparam[offset >> 1] = data;
}
WRITE8_MEMBER( isa8_pgc_device::lut_w ) {
UINT8 o = (offset >> 1) * 3;
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] ));
} 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"));
space.unmap_read(0xf8000, 0xfffff);
DBG_LOG(1,"INIT",("mapping emulator RAM\n"));
space.install_readwrite_bank(0xf8000, 0xfffff, "eram");
membank("eram")->set_base(m_eram);
DBG_LOG(1,"INIT",("mapping LUT\n"));
space.install_write_handler(0xf8400, 0xf85ff,
write8_delegate(FUNC(isa8_pgc_device::lut_w), this));
return 0; // XXX ignored
}
TIMER_DEVICE_CALLBACK_MEMBER(isa8_pgc_device::scanline_callback)
{
UINT16 x, y = m_screen->vpos();
UINT16 *p;
UINT8 *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 < PGC_VERT_START) return;
y -= PGC_VERT_START;
if (y >= PGC_DISP_VERT) return;
// XXX address translation happens in hardware
v = &m_vram[y * 1024];
p = &m_bitmap->pix16(y, 0);
for (x = 0; x < PGC_DISP_HORZ; x++) {
*p++ = *v++;
}
}
UINT32 isa8_pgc_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
copybitmap(bitmap, *m_bitmap, 0, 0, PGC_HORZ_START, PGC_VERT_START, cliprect);
return 0;
}

67
src/emu/bus/isa/pgc.h Normal file
View File

@ -0,0 +1,67 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
#pragma once
#ifndef __ISA_PGC_H__
#define __ISA_PGC_H__
#include "emu.h"
#include "cpu/i86/i86.h"
#include "isa.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> isa8_pgc_device
class isa8_pgc_device :
public device_t,
public device_isa8_card_interface
{
public:
// construction/destruction
isa8_pgc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
isa8_pgc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
virtual const rom_entry *device_rom_region() const;
virtual ioport_constructor device_input_ports() const;
UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
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 );
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
private:
required_device<i8088_cpu_device> m_cpu;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
UINT8 *m_commarea;
UINT8 *m_vram;
UINT8 *m_eram;
UINT8 m_stateparam[16];
UINT8 m_lut[256*3];
bitmap_ind16 *m_bitmap;
};
// device type definition
extern const device_type ISA8_PGC;
#endif /* __ISA_PGC_H__ */