This is from a much older version of MAME but here is a driver you can probably update, or you may already have it I'm not sure
// BEGIN Modifications
int multipac_bankaddress;
extern int gfx_bank;
extern void multipac_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom);
extern void gfx_bank_zero(void);
extern void z80_reset(void);
WRITE_HANDLER( superabc_gfxbank_w );
WRITE_HANDLER( multipac_gfxbank_w );
WRITE_HANDLER( multipac_color_w );
// END Modifications
/*********************************************************************
SUPER ABC & MULTIPAC
*********************************************************************/
// Multipac 1.4 & 1.5 Driver
// I've made the driver so that It resets the hardware as soon as the banks
// change. This means that the games all _work_, wether that's what the
// original does? beats me!
static int multipac_interrupt(void)
{
unsigned char *RAM = memory_region(REGION_CPU1);
/* speed up cheat */
if (speedcheat)
{
if (readinputport(4) & 1) /* check status of the fake dip switch */
{
/* activate the cheat */
RAM[0x180b] = 0x01;
RAM[0x1ffd] = 0xbd;
}
else
{
/* remove the cheat */
RAM[0x180b] = 0xbe;
RAM[0x1ffd] = 0x00;
}
}
/* Menu Button */
// If menu button pressed, set bank to 0, and reset the cpu
// THIS DOESN'T WORK!!!!
// I need a way to force gfx_bank to be zero
// and to disable interrupts, and turn off sound.
// beyond my reach atm...
if (readinputport(5) & 1) {
memset(dirtybuffer,1,videoram_size);
RAM[0xa000]=0;
RAM[0xa001]=0;
multipac_bankaddress = 0x10000;
memset (dirtybuffer,1,videoram_size);
cpu_setbank(1, &RAM[multipac_bankaddress]);
cpu_set_reg(1, 0x0000); // Force 0 into PC
gfx_bank_zero(); // Force GFX Bank 0 (Menu Bank)
// z80_reset(); This Crashes MAME (boo-hoo!)
}
return interrupt();
}
INPUT_PORTS_START( multipac )
PORT_START /* IN0 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY )
PORT_BITX( 0x10, 0x10, IPT_DIPSWITCH_NAME | IPF_CHEAT, "Rack Test", KEYCODE_F1, IP_JOY_NONE )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_START /* IN1 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_COCKTAIL )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_COCKTAIL )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_COCKTAIL )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_COCKTAIL )
PORT_SERVICE( 0x10, IP_ACTIVE_LOW )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 ) // Button 1 maps to start button also.
// makes lizard wizard easier to play
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
PORT_DIPNAME(0x80, 0x80, DEF_STR( Cabinet ) )
PORT_DIPSETTING( 0x80, DEF_STR( Upright ) )
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_START /* DSW 1 */
PORT_DIPNAME( 0x03, 0x01, DEF_STR( Coinage ) )
PORT_DIPSETTING( 0x03, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x01, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
PORT_DIPNAME( 0x0c, 0x08, DEF_STR( Lives ) )
PORT_DIPSETTING( 0x00, "1" )
PORT_DIPSETTING( 0x04, "2" )
PORT_DIPSETTING( 0x08, "3" )
PORT_DIPSETTING( 0x0c, "5" )
PORT_DIPNAME( 0x30, 0x00, DEF_STR( Bonus_Life ) )
PORT_DIPSETTING( 0x00, "10000" )
PORT_DIPSETTING( 0x10, "15000" )
PORT_DIPSETTING( 0x20, "20000" )
PORT_DIPSETTING( 0x30, "None" )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Difficulty ) )
PORT_DIPSETTING( 0x40, "Normal" )
PORT_DIPSETTING( 0x00, "Hard" )
PORT_DIPNAME( 0x80, 0x80, "Ghost Names" )
PORT_DIPSETTING( 0x80, "Normal" )
PORT_DIPSETTING( 0x00, "Alternate" )
PORT_START /* DSW 2 */
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START /* FAKE */
/* This fake input port is used to get the status of the fire button */
/* and activate the speedup cheat if it is. */
PORT_BITX( 0x01, 0x00, IPT_DIPSWITCH_NAME | IPF_CHEAT, "Speedup Cheat", KEYCODE_LCONTROL, JOYCODE_1_BUTTON1 )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
PORT_START /* MENU BUTTON */
/* This fake input port is used to get the status of the fire button */
/* and activate the speedup cheat if it is. */
PORT_BITX( 0x01, 0x00, IPT_DIPSWITCH_NAME, "Menu Button", KEYCODE_RCONTROL, JOYCODE_1_BUTTON1 )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
static struct GfxDecodeInfo multipac_gfxdecodeinfo[] =
{
{ REGION_GFX1, 0x00000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x01000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x02000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x03000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x04000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x05000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x06000, &tilelayout, 4*32, 32 }, //Pacman Plus//
{ REGION_GFX1, 0x07000, &spritelayout, 4*32, 32 }, //Pacman Plus//
{ REGION_GFX1, 0x08000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x09000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x0a000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x0b000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x0c000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x0d000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x0e000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x0f000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x10000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x11000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x12000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x13000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x14000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x15000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x16000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x17000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x18000, &tilelayout, 0, 32 },
{ REGION_GFX1, 0x19000, &spritelayout, 0, 32 },
{ REGION_GFX1, 0x1a000, &tilelayout, 8*32, 32 }, // Crush Roller //
{ REGION_GFX1, 0x1b000, &spritelayout, 8*32, 32 }, // Crush Roller //
{ REGION_GFX1, 0x1c000, &tilelayout, 12*32, 32 }, // Liz Wiz //
{ REGION_GFX1, 0x1d000, &spritelayout, 12*32, 32 }, // Liz Wiz //
{ REGION_GFX1, 0x1e000, &tilelayout, 0, 32 }, // Unused? //
{ REGION_GFX1, 0x1f000, &spritelayout, 0, 32 }, // Unused? //
{ -1 } /* end of array */
};
static void init_multipac(void)
{
int i;
unsigned char *RAM;
/* Clear Bank Swap addresses */
for (i=0; i<8; i++) {
RAM = memory_region(REGION_CPU1);
RAM[0xa000+i] = 0;
}
/* And clear Sprites */
for (i=0; i<8; i++) {
RAM = memory_region(REGION_CPU1);
RAM[0x5060+i*2]=0;
RAM[0x5061+i*2]=0;
}
multipac_bankaddress = 0x10000;
cpu_setbank(1, &RAM[multipac_bankaddress]);
}
static WRITE_HANDLER( multipac_bankswitch_w)
{
unsigned char *RAM = memory_region(REGION_CPU1);
if (data != 0) {
if (data != multipac_bankaddress) {
if (data < 0x20) // Check for valid codes...
multipac_bankaddress = 0x10000+ ((data & 0x10) / 0x10 + (data & 0x0f) *2) * 0x4000;
else
multipac_bankaddress = 0x10000;
cpu_setbank(1, &RAM[multipac_bankaddress]);
if (RAM[0xa007]==0)
cpu_setbank(2, &RAM[multipac_bankaddress+0x4000]);
}
}
}
static WRITE_HANDLER( multipac_a000_w )
{
unsigned char *RAM = memory_region(REGION_CPU1);
if (data != multipac_bankaddress) {
if (data < 0x20) // Check for valid codes...
multipac_bankaddress = 0x10000 + ((data & 0x10) / 0x10 + (data & 0x0f) *2) * 0x4000;
else
multipac_bankaddress = 0x10000;
cpu_setbank(1, &RAM[multipac_bankaddress]);
if (RAM[0xa007]==0)
cpu_setbank(2, &RAM[multipac_bankaddress+0x4000]);
cpu_set_reg(1,0x0000); // Set PC <- 0000
}
}
static MEMORY_READ_START( multipac_readmem )
{ 0x0000, 0x3fff, MRA_BANK1 },
{ 0x4000, 0x47ff, MRA_RAM }, /* video and color RAM */
{ 0x4c00, 0x4fff, MRA_RAM }, /* including sprite codes at 4ff0-4fff */
{ 0x5000, 0x503f, input_port_0_r }, /* IN0 */
{ 0x5040, 0x507f, input_port_1_r }, /* IN1 */
{ 0x5080, 0x50bf, input_port_2_r }, /* DSW1 */
{ 0x50c0, 0x50ff, input_port_3_r }, /* DSW2 */
// { 0x8000, 0x9fff, MRA_ROM }, /* Ms. Pac-Man */
{ 0x8000, 0x9fff, MRA_BANK2 }, /* Ms. Pac-Man, LizWiz */
// to implement bank switching
// { 0xa000, 0xafff, MRA_RAM }, /* Multi Pac : Must it be RAM? */
{ 0xf000, 0xfffe, MRA_RAM },
MEMORY_END
static MEMORY_WRITE_START( multipac_writemem )
{ 0x0000, 0x3fff, MWA_ROM },
{ 0x4000, 0x43ff, videoram_w, &videoram, &videoram_size },
{ 0x4400, 0x47ff, colorram_w, &colorram },
{ 0x4900, 0x49ff, MWA_RAM }, /* MULTIPAC */
{ 0x4c00, 0x4fef, MWA_RAM },
{ 0x4ff0, 0x4fff, MWA_RAM, &spriteram, &spriteram_size },
{ 0x5000, 0x5000, interrupt_enable_w },
{ 0x5001, 0x5001, pengo_sound_enable_w },
{ 0x5002, 0x5002, MWA_NOP },
{ 0x5003, 0x5003, pengo_flipscreen_w },
{ 0x5004, 0x5005, pacman_leds_w },
// { 0x5006, 0x5006, pacman_coin_lockout_global_w }, this breaks many games
{ 0x5007, 0x5007, pacman_coin_counter_w },
{ 0x5040, 0x505f, pengo_sound_w, &pengo_soundregs },
{ 0x5060, 0x506f, MWA_RAM, &spriteram_2 },
// { 0x50c0, 0x50c0, watchdog_reset_w },
{ 0x8000, 0x9fff, MWA_ROM }, /* Ms. Pac-Man */
{ 0xa000, 0xa000, multipac_a000_w },
{ 0xa001, 0xa001, multipac_gfxbank_w },
{ 0xa002, 0xa002, multipac_color_w },
{ 0xa003, 0xa00f, MWA_RAM }, /* Used by Multipac */
{ 0xc000, 0xc3ff, videoram_w }, /* mirror address for video ram, */
{ 0xc400, 0xc7ef, colorram_w }, /* used to display HIGH SCORE and CREDITS */
{ 0xf000, 0xfffe, MWA_RAM },
{ 0xffff, 0xffff, MWA_NOP }, /* Eyes writes to this location to simplify code */
MEMORY_END
static const struct MachineDriver machine_driver_multipac =
{
/* basic machine hardware */
{
{
CPU_Z80,
18432000/6, /* 3.072 MHz */
multipac_readmem,multipac_writemem,0,writeport,
multipac_interrupt,1
}
},
60.606060, 2500, /* frames per second, vblank duration */
1, /* single CPU, no need for interleaving */
pacman_init_machine,
/* video hardware */
36*8, 28*8, { 0*8, 36*8-1, 0*8, 28*8-1 },
multipac_gfxdecodeinfo,
64, // Pacman 16 Pengo 32 (Number of colours used, right?
4*128, // Number of colour schemes (Pacman 4*32, Pengo 4*64 (4*32*2)
multipac_vh_convert_color_prom,
VIDEO_TYPE_RASTER,
0,
pacman_vh_start,
generic_vh_stop,
pengo_vh_screenrefresh,
/* sound hardware */
0,0,0,0,
{
{
SOUND_NAMCO,
&namco_interface
}
}
};
in src\vidhrdw\pengo.c
/************************************************************************
BEGIN MODIFICATIONS FOR MULTIPAC
************************************************************************/
void multipac_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
{
int i;
#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
for (i = 0;i < Machine->drv->total_colors;i++)
{
int bit0,bit1,bit2;
/* red component */
bit0 = (*color_prom >> 0) & 0x01;
bit1 = (*color_prom >> 1) & 0x01;
bit2 = (*color_prom >> 2) & 0x01;
*(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
/* green component */
bit0 = (*color_prom >> 3) & 0x01;
bit1 = (*color_prom >> 4) & 0x01;
bit2 = (*color_prom >> 5) & 0x01;
*(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
/* blue component */
bit0 = 0;
bit1 = (*color_prom >> 6) & 0x01;
bit2 = (*color_prom >> 7) & 0x01;
*(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
color_prom++;
}
/* color_prom now points to the beginning of the lookup table */
/* character lookup table */
/* sprites use the same color lookup table as characters */
for (i = 0;i < TOTAL_COLORS(0);i++)
COLOR(0,i) = *(color_prom++) & 0x0f;
color_prom += 0x80;
/* second bank character lookup table */
/* sprites use the same color lookup table as characters */
for (i = 0;i < TOTAL_COLORS(6);i++)
{
if (*color_prom &0x0f)
COLOR(6,i) = (*color_prom & 0x0f) + 0x10; /* second palette bank */
else
COLOR(6,i) = 0; /* preserve transparency */
color_prom++;
}
color_prom += 0x80;
/* third bank character lookup table */
/* sprites use the same color lookup table as characters */
for (i = 0;i < TOTAL_COLORS(26);i++)
{
if (*color_prom) COLOR(26,i) = (*color_prom & 0x0f) + 0x00; /* third palette bank */
else COLOR(26,i) = 0; /* preserve transparency */
color_prom++;
}
color_prom += 0x80;
/* fourth bank character lookup table */
/* sprites use the same color lookup table as characters */
for (i = 0;i < TOTAL_COLORS(0x1c);i++)
{
if (*color_prom) COLOR(0x1c,i) = (*color_prom & 0x0f) + 0x30; /* fourth palette bank */
else COLOR(0x1c,i) = 0; /* preserve transparency */
color_prom++;
}
}
WRITE_HANDLER( multipac_gfxbank_w )
{
// This handler handles the character set banking
// (memory location 0a001)
// graphics rom banking all in one.
unsigned char *RAM = memory_region(REGION_CPU1);
if (gfx_bank!=data) {
int i;
for (i=0x4000; i<0x4400; i++)
RAM[i]=0x40;
memset(dirtybuffer,1,videoram_size);
gfx_bank=data;
}
}
WRITE_HANDLER( multipac_color_w )
{
// The colours are currently handled by the graphics banking, but here
// is an exception
unsigned char *RAM = memory_region(REGION_CPU1);
if (data==2) {
RAM[0xf000]=0;
}
}
void gfx_bank_zero( void )
{
if (gfx_bank!=0) {
gfx_bank=0;
}
}