/*************************************************************************** Ms.Pac-Man/Galaga - 20 Year Reunion hardware driver by Nicola Salmoria Notes: * There are four start buttons: the first two are for Ms. Pac-Man, the other two for Galaga. * To play Pac-Man instead of Ms. Pac-Man, insert coins then enter the following sequence: U U U D D D L R L R L. A sound will play and the ghost will change from red to pink. * To toggle the built-in speedup, insert coins then enter the following sequence: L R L R U U U Fire. A sound will play if you did it correctly. This will toggle the speed in both Ms Pacman & Pacman as well as provide a "Fast Shot" in Galaga * Writes to the Z180 ASCI port: MS PAC-MAN/GALAGA arcade video system version 1.01 (c) 2000 Cosmodog, Ltd. > and it listens for incoming characters. * CPU is a Z8S18020VSC (20MHz part), OSC is 73.728MHz Known issues/to-do's: * ROM banking is not understood. Shouldn't require copying and other trickey * Starfield missing * Check the ASCI interface, there probably is fully working debug code. * The timed interrupt is a kludge; it is supposed to be generated internally by the Z180, but the cpu core doesn't support that yet. * Is the clock divide 3 or 4? Versions known to exist but not dumped: v1.03 & v1.04 ***************************************************************************/ #include "driver.h" #include "machine/eeprom.h" #include "sound/namco.h" #include "sound/dac.h" #include "20pacgal.h" /************************************* * * Clocks * *************************************/ #define MASTER_CLOCK (XTAL_73_728MHz) #define MAIN_CPU_CLOCK (MASTER_CLOCK / 4) /* divider is either 3 or 4 */ #define NAMCO_AUDIO_CLOCK (MASTER_CLOCK / 4 / 6 / 32) /************************************* * * Interrupt system * *************************************/ static WRITE8_HANDLER( irqack_w ) { int bit = data & 1; cpu_interrupt_enable(0, bit); if (!bit) cpunum_set_input_line(machine, 0, 0, CLEAR_LINE ); } /************************************* * * Audio * *************************************/ static const namco_interface namco_config = { 3, /* number of voices */ 0 /* stereo */ }; static WRITE8_HANDLER( _20pacgal_dac_w ) { dac_signed_data_w(0, data); } /************************************* * * Non-volatile memory * *************************************/ static const eeprom_interface eeprom_intf = { 7, /* address bits */ 8, /* data bits */ "*110", /* read command */ "*101", /* write command */ 0, /* erase command */ "*10000xxxxx", /* lock command */ "*10011xxxxx", /* unlock command */ }; static NVRAM_HANDLER( eeprom ) { if (read_or_write) eeprom_save(file); else { eeprom_init(&eeprom_intf); if (file) eeprom_load(file); } } static READ8_HANDLER( eeprom_r ) { /* bit 7 is EEPROM data */ return eeprom_read_bit() << 7; } static WRITE8_HANDLER( eeprom_w ) { /* bit 7 is data */ /* bit 6 is clock (active high) */ /* bit 5 is cs (active low) */ eeprom_write_bit(data & 0x80); eeprom_set_cs_line((data & 0x20) ? CLEAR_LINE : ASSERT_LINE); eeprom_set_clock_line((data & 0x40) ? ASSERT_LINE : CLEAR_LINE); } /************************************* * * Coin counter * *************************************/ static WRITE8_HANDLER( _20pacgal_coin_counter_w ) { coin_counter_w(0, data & 1); } /************************************* * * ROM banking - FIXME * *************************************/ static WRITE8_HANDLER( rom_bank_select_w ) { _20pacgal_state *state = machine->driver_data; state->game_selected = data & 1; if (state->game_selected == 0) { UINT8 *rom = memory_region(machine, "main"); memcpy(rom+0x48000, rom+0x8000, 0x2000); } } static WRITE8_HANDLER( rom_48000_w ) { _20pacgal_state *state = machine->driver_data; if (state->game_selected) { if (offset < 0x0800) state->video_ram[offset & 0x07ff] = data; memory_region(machine, "main")[0x48000 + offset] = data; } } /************************************* * * Memory handlers * *************************************/ static ADDRESS_MAP_START( 20pacgal_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x00000, 0x03fff) AM_ROM AM_RANGE(0x08000, 0x09fff) AM_ROM AM_RANGE(0x0a000, 0x0ffff) AM_MIRROR(0x40000) AM_ROM AM_RANGE(0x10000, 0x3ffff) AM_ROM AM_RANGE(0x44000, 0x447ff) AM_RAM AM_BASE_MEMBER(_20pacgal_state, video_ram) AM_RANGE(0x45040, 0x4505f) AM_WRITE(pacman_sound_w) AM_BASE(&namco_soundregs) AM_RANGE(0x44800, 0x45eff) AM_RAM AM_RANGE(0x45f00, 0x45fff) AM_WRITE(_20pacgal_wavedata_w) AM_BASE(&namco_wavedata) AM_RANGE(0x46000, 0x46fff) AM_WRITE(SMH_RAM) AM_BASE_MEMBER(_20pacgal_state, char_gfx_ram) AM_RANGE(0x47100, 0x47100) AM_RAM /* leftover from original Galaga code */ AM_RANGE(0x48000, 0x49fff) AM_READWRITE(SMH_ROM, rom_48000_w) /* this should be a mirror of 08000-09ffff */ AM_RANGE(0x4c000, 0x4dfff) AM_WRITE(SMH_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_gfx_ram) AM_RANGE(0x4e000, 0x4e17f) AM_WRITE(SMH_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_ram) AM_RANGE(0x4ff00, 0x4ffff) AM_WRITE(SMH_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_color_lookup) ADDRESS_MAP_END /************************************* * * I/O port handlers * *************************************/ static ADDRESS_MAP_START( 20pacgal_io_map, ADDRESS_SPACE_IO, 8 ) ADDRESS_MAP_GLOBAL_MASK(0xff) AM_RANGE(0x00, 0x3f) AM_NOP /* Z180 internal registers */ AM_RANGE(0x40, 0x7f) AM_NOP /* Z180 internal registers */ AM_RANGE(0x80, 0x80) AM_READ_PORT("P1") AM_RANGE(0x81, 0x81) AM_READ_PORT("P2") AM_RANGE(0x82, 0x82) AM_READ_PORT("SERVICE") AM_RANGE(0x80, 0x80) AM_WRITE(watchdog_reset_w) AM_RANGE(0x81, 0x81) AM_WRITE(SMH_NOP) /* ??? pulsed by the timer irq */ AM_RANGE(0x82, 0x82) AM_WRITE(irqack_w) AM_RANGE(0x85, 0x86) AM_WRITE(SMH_NOP) /* stars: rng seed (lo/hi) */ AM_RANGE(0x87, 0x87) AM_READWRITE(eeprom_r, eeprom_w) AM_RANGE(0x88, 0x88) AM_WRITE(rom_bank_select_w) AM_RANGE(0x89, 0x89) AM_WRITE(_20pacgal_dac_w) AM_RANGE(0x8a, 0x8a) AM_WRITE(SMH_NOP) /* stars: bits 3-4 = active set; bit 5 = enable */ AM_RANGE(0x8b, 0x8b) AM_WRITE(SMH_RAM) AM_BASE_MEMBER(_20pacgal_state, flip) AM_RANGE(0x8f, 0x8f) AM_WRITE(_20pacgal_coin_counter_w) ADDRESS_MAP_END /************************************* * * Port definitions * *************************************/ static INPUT_PORTS_START( 20pacgal ) PORT_START("P1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_START("P2") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_COCKTAIL PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_COCKTAIL PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START3 ) PORT_NAME( "Right 1 Player Start" ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME( "Left 1 Player Start" ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME( "Left 2 Players Start" ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START4 ) PORT_NAME( "Right 2 Players Start" ) PORT_START("SERVICE") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_SERVICE_NO_TOGGLE( 0x80, IP_ACTIVE_LOW ) INPUT_PORTS_END /************************************* * * Machine driver * *************************************/ static MACHINE_DRIVER_START( 20pacgal ) MDRV_DRIVER_DATA(_20pacgal_state) /* basic machine hardware */ MDRV_CPU_ADD("main", Z180, MAIN_CPU_CLOCK) MDRV_CPU_PROGRAM_MAP(20pacgal_map,0) MDRV_CPU_IO_MAP(20pacgal_io_map,0) MDRV_CPU_VBLANK_INT("main", irq0_line_assert) MDRV_NVRAM_HANDLER(eeprom) /* video hardware */ MDRV_IMPORT_FROM(20pacgal_video) /* sound hardware */ MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD("namco", NAMCO, NAMCO_AUDIO_CLOCK) MDRV_SOUND_CONFIG(namco_config) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MDRV_SOUND_ADD("dac", DAC, 0) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_DRIVER_END /************************************* * * ROM definition * *************************************/ ROM_START( 20pacgal ) /* Version 1.01 */ ROM_REGION( 0x100000, "main", 0 ) ROM_LOAD( "20th_101.u13", 0x00000, 0x40000, CRC(77159582) SHA1(c05e005a941cbdc806dcd76b315069362c792a72) ) ROM_REGION( 0x8000, "proms", 0 ) /* palette */ ROM_LOAD( "20th_101.u14", 0x0000, 0x8000, CRC(c19d9ad0) SHA1(002581fbc2c32cdf7cfb0b0f64061591a462ec14) ) ROM_END /************************************* * * Game driver * *************************************/ GAME( 2000, 20pacgal, 0, 20pacgal, 20pacgal, 0, ROT90, "Namco", "Ms. Pac-Man/Galaga - 20 Year Reunion", GAME_IMPERFECT_GRAPHICS )