summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/multigam.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/multigam.c')
-rw-r--r--src/mame/drivers/multigam.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/mame/drivers/multigam.c b/src/mame/drivers/multigam.c
new file mode 100644
index 00000000000..6dd4bb476cf
--- /dev/null
+++ b/src/mame/drivers/multigam.c
@@ -0,0 +1,336 @@
+/*
+ Multi Game
+
+ driver by Mariusz Wojcieszek
+ uses NES emulation by Brad Olivier
+
+ Hardware is based around Nintendo NES. After coin up, it allows to play one of
+ 35 NES games (choosen from text menu). Manufacturer is unknown, code for title
+ screen and game selection contains string:
+ "Programed by SANG HO ENG. K. B. KIM 1986/1/ 1"
+
+ Notes:
+ - rom at 0x6000-0x7fff contains control program, which handles coins and timer
+ - each game rom has NMI (VBLANK) vector changed to 0x6100 (control program). Then,
+ game NMI is called through IRQ vector
+ - there is additional RAM (0x800-0xfff) used by control program
+ - ROM banked at 0x5000-0x5ffe seems to contain patches for games. At least
+ Ninja code jumps into this area
+ - game roms are banked in 16KB units. Bank switching of game rom is handled by
+ writing to 0x6fff. If bank select has 7th bit turned on, then 32KB rom is
+ switched into $8000 - $ffff. Otherwise, 16KB rom is switched on.
+ - PPU VROMS are banked in 8KB units. Write to 0x7fff controls PPU VROM banking.
+ - some games use additional banking on PPU VROMS. This is enabled by writing
+ value with bit 7 on to 0x7fff and then selecting a vrom by writing into
+ 0x8000 - 0xffff range.
+ - there is a register at 0x5002. 0xff is written there when game is played,
+ 0x00 otherwise. Its purpose is unknown.
+
+
+ Notes by Roberto Fresca:
+
+ - Added multigame (set2).
+ - Main differences are:
+ - Control program: Offset 0x79b4 = JMP $c4c4 was changed to JMP $c4c6.
+ - ROM at 0x80000: Several things patched and/or relocated.
+ Most original NOPs were replaced by proper code.
+
+*/
+
+#include "driver.h"
+#include "video/ppu2c0x.h"
+#include "sound/nes_apu.h"
+#include "cpu/m6502/m6502.h"
+
+static WRITE8_HANDLER( sprite_dma_w )
+{
+ int source = ( data & 7 );
+ ppu2c0x_spriteram_dma( 0, source );
+}
+
+static READ8_HANDLER( psg_4015_r )
+{
+ return NESPSG_0_r(0x15);
+}
+
+static WRITE8_HANDLER( psg_4015_w )
+{
+ NESPSG_0_w(0x15, data);
+}
+
+static WRITE8_HANDLER( psg_4017_w )
+{
+ NESPSG_0_w(0x17, data);
+}
+
+/* Inputs */
+
+static UINT32 in_0;
+static UINT32 in_1;
+static UINT32 in_0_shift;
+static UINT32 in_1_shift;
+static UINT32 multigam_in_dsw;
+static UINT32 multigam_in_dsw_shift;
+
+static READ8_HANDLER( multigam_IN0_r )
+{
+ return ((in_0 >> in_0_shift++) & 0x01) | 0x40;
+}
+
+static WRITE8_HANDLER( multigam_IN0_w )
+{
+ if ( data & 0x01 )
+ {
+ return;
+ }
+
+ in_0_shift = 0;
+ in_1_shift = 0;
+
+ in_0 = readinputport(0);
+ in_1 = readinputport(1);
+
+ multigam_in_dsw_shift = 0;
+ multigam_in_dsw = readinputport(3);
+}
+
+static READ8_HANDLER( multigam_IN1_r )
+{
+ return ((in_1 >> in_1_shift++) & 0x01) | 0x40;
+}
+
+static READ8_HANDLER( multigam_inputs_r )
+{
+ /* bit 0: serial input (dsw)
+ bit 1: coin */
+ return ((multigam_in_dsw >> multigam_in_dsw_shift++) & 0x01) |
+ readinputport(2);
+}
+
+
+/*PRG and VROM Banking */
+
+static int multigam_game_gfx_bank = 0;
+
+static WRITE8_HANDLER( multigam_mapper_w )
+{
+ if ( offset == 0x0fff )
+ {
+ /* switch PRG rom */
+ UINT8* dst = memory_region( REGION_CPU1 );
+ UINT8* src = memory_region( REGION_USER1 );
+
+ if ( data & 0x80 )
+ {
+ if ( data & 0x01 )
+ {
+ data &= ~0x01;
+ }
+ memcpy( &dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000 );
+ }
+ else
+ {
+ memcpy( &dst[0x8000], &src[data*0x4000], 0x4000 );
+ memcpy( &dst[0xc000], &src[data*0x4000], 0x4000 );
+ }
+ }
+ else if ( offset == 0x1fff )
+ {
+ ppu2c0x_set_videorom_bank( 0, 0, 8, data /*& 0x3f*/, 512 );
+ ppu2c0x_set_mirroring( 0, data & 0x40 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT );
+ multigam_game_gfx_bank = data;
+ }
+ else
+ {
+ logerror( "Unmapped multigam_mapper_w: offset = %04X, data = %02X\n", offset, data );
+ }
+}
+
+static WRITE8_HANDLER(multigam_mapper2_w)
+{
+ if ( multigam_game_gfx_bank & 0x80 )
+ {
+ ppu2c0x_set_videorom_bank( 0, 0, 8, multigam_game_gfx_bank + (data & 0xf), 512 );
+ }
+ else
+ {
+ logerror( "Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data );
+ }
+}
+
+static ADDRESS_MAP_START( multigam_map, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x07ff) AM_RAM /* NES RAM */
+ AM_RANGE(0x0800, 0x0fff) AM_RAM /* additional RAM */
+ AM_RANGE(0x2000, 0x3fff) AM_READWRITE(ppu2c0x_0_r, ppu2c0x_0_w)
+ AM_RANGE(0x4000, 0x4013) AM_READWRITE(NESPSG_0_r, NESPSG_0_w) /* PSG primary registers */
+ AM_RANGE(0x4014, 0x4014) AM_WRITE(sprite_dma_w)
+ AM_RANGE(0x4015, 0x4015) AM_READWRITE(psg_4015_r, psg_4015_w) /* PSG status / first control register */
+ AM_RANGE(0x4016, 0x4016) AM_READWRITE(multigam_IN0_r, multigam_IN0_w) /* IN0 - input port 1 */
+ AM_RANGE(0x4017, 0x4017) AM_READWRITE(multigam_IN1_r, psg_4017_w) /* IN1 - input port 2 / PSG second control register */
+ AM_RANGE(0x5002, 0x5002) AM_WRITENOP
+ AM_RANGE(0x5000, 0x5ffe) AM_ROM
+ AM_RANGE(0x5fff, 0x5fff) AM_READ(multigam_inputs_r)
+ AM_RANGE(0x6000, 0x7fff) AM_ROM AM_WRITE(multigam_mapper_w)
+ AM_RANGE(0x8000, 0xffff) AM_ROM AM_WRITE(multigam_mapper2_w)
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( multigam )
+ PORT_START /* IN0 */
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) /* Select */
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
+
+ PORT_START /* IN1 */
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) /* Select */
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+
+ PORT_START /* IN2 */
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN1 )
+
+ PORT_START /* IN3 */
+ PORT_DIPNAME( 0x06, 0x00, "Coin/Time" )
+ PORT_DIPSETTING( 0x00, "3 min" )
+ PORT_DIPSETTING( 0x04, "5 min" )
+ PORT_DIPSETTING( 0x02, "7 min" )
+ PORT_DIPSETTING( 0x06, "10 min" )
+INPUT_PORTS_END
+
+static struct NESinterface multigam_interface_1 =
+{
+ REGION_CPU1
+};
+
+static MACHINE_RESET( multigam )
+{
+ /* reset the ppu */
+ ppu2c0x_reset( 0, 1 );
+};
+
+static PALETTE_INIT( multigam )
+{
+ ppu2c0x_init_palette(machine, 0 );
+}
+
+static void ppu_irq( int num, int *ppu_regs )
+{
+ cpunum_set_input_line(num, INPUT_LINE_NMI, PULSE_LINE );
+}
+
+/* our ppu interface */
+static const ppu2c0x_interface ppu_interface =
+{
+ PPU_2C04, /* type */
+ 1, /* num */
+ { REGION_GFX1 }, /* vrom gfx region */
+ { 0 }, /* gfxlayout num */
+ { 0 }, /* color base */
+ { PPU_MIRROR_NONE }, /* mirroring */
+ { ppu_irq } /* irq */
+};
+
+static VIDEO_START( multigam )
+{
+ ppu2c0x_init(machine, &ppu_interface );
+}
+
+static VIDEO_UPDATE( multigam )
+{
+ /* render the ppu */
+ ppu2c0x_render( 0, bitmap, 0, 0, 0, 0 );
+ return 0;
+}
+
+static DRIVER_INIT( multigam )
+{
+ multigam_mapper_w( 0x0fff, 0x01 );
+}
+
+static GFXDECODE_START( multigam )
+ /* none, the ppu generates one */
+GFXDECODE_END
+
+static MACHINE_DRIVER_START( multigam )
+ /* basic machine hardware */
+ MDRV_CPU_ADD_TAG("main", N2A03, N2A03_DEFAULTCLOCK)
+ MDRV_CPU_PROGRAM_MAP(multigam_map, 0)
+
+ MDRV_SCREEN_REFRESH_RATE(60)
+
+ MDRV_MACHINE_RESET( multigam )
+
+ /* video hardware */
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
+ MDRV_SCREEN_SIZE(32*8, 262)
+ MDRV_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 30*8-1)
+ MDRV_GFXDECODE(multigam)
+ MDRV_PALETTE_LENGTH(8*4*16)
+ MDRV_COLORTABLE_LENGTH(4*8)
+
+ MDRV_PALETTE_INIT(multigam)
+ MDRV_VIDEO_START(multigam)
+ MDRV_VIDEO_UPDATE(multigam)
+
+ /* sound hardware */
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(NES, N2A03_DEFAULTCLOCK)
+ MDRV_SOUND_CONFIG(multigam_interface_1)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MDRV_SOUND_ADD(DAC, 0)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+ROM_START( multigam )
+ ROM_REGION( 0x10000, REGION_CPU1, 0 )
+ ROM_LOAD( "7.bin", 0x0000, 0x8000, CRC(f0fa7cf2) SHA1(7f3b3dca796b964893197aef7f0f31dfd7a2c1a4) )
+
+ ROM_REGION( 0xC0000, REGION_USER1, 0 )
+ ROM_LOAD( "1.bin", 0x00000, 0x20000, CRC(e0bb14a5) SHA1(74026f59dfb08456183adaaf381bb28830212a1c) )
+ ROM_LOAD( "2.bin", 0x20000, 0x20000, CRC(f52c07ad) SHA1(51be288bcf5aeab5bdd95ee93a6d807867e30e97) )
+ ROM_LOAD( "3.bin", 0x40000, 0x20000, CRC(92e8303e) SHA1(4a735fce22cdea65801aa7e4e00fa8c15a022ea4) )
+ ROM_LOAD( "4.bin", 0x60000, 0x20000, CRC(f5c50f29) SHA1(6f3bd969d9d82a0d92aa6119375a607ccdb5d8b9) )
+ ROM_LOAD( "5.bin", 0x80000, 0x20000, CRC(e1232243) SHA1(fa864b255b7f3cb195d3789f8a2a7b3848b255a2) )
+ ROM_LOAD( "6.bin", 0xa0000, 0x20000, CRC(fb129b09) SHA1(b677937d6cf7800359dc6d35dd2de3ec27919d71) )
+
+ ROM_REGION( 0x80000, REGION_GFX1, 0 )
+ ROM_LOAD( "8.bin", 0x00000, 0x20000, CRC(509c0e94) SHA1(9e87c74e76afe6c3a7ba194439434f54e2c879eb) )
+ ROM_LOAD( "9.bin", 0x20000, 0x20000, CRC(48416f20) SHA1(f461fcbff6d2fa4774d64c26475089d1aeea7fb5) )
+ ROM_LOAD( "10.bin", 0x40000, 0x20000, CRC(869d1661) SHA1(ac155bd24ebfea8e064859e1a05317001286f9ae) )
+ ROM_FILL( 0x60000, 0x20000, 0x00 )
+ROM_END
+
+ROM_START( multigmb )
+ ROM_REGION( 0x10000, REGION_CPU1, 0 )
+ ROM_LOAD( "mg_4.bin", 0x0000, 0x8000, CRC(079226c1) SHA1(f4ceedd9b6cc3454550be7421dc75904ad664545) )
+
+ ROM_REGION( 0xC0000, REGION_USER1, 0 )
+ ROM_LOAD( "1.bin", 0x00000, 0x20000, CRC(e0bb14a5) SHA1(74026f59dfb08456183adaaf381bb28830212a1c) )
+ ROM_LOAD( "2.bin", 0x20000, 0x20000, CRC(f52c07ad) SHA1(51be288bcf5aeab5bdd95ee93a6d807867e30e97) )
+ ROM_LOAD( "3.bin", 0x40000, 0x20000, CRC(92e8303e) SHA1(4a735fce22cdea65801aa7e4e00fa8c15a022ea4) )
+ ROM_LOAD( "4.bin", 0x60000, 0x20000, CRC(f5c50f29) SHA1(6f3bd969d9d82a0d92aa6119375a607ccdb5d8b9) )
+ ROM_LOAD( "mg_9.bin", 0x80000, 0x20000, CRC(47f968af) SHA1(ed60bda060984e5acc2c6b6cac5b36eafbb2b631) )
+ ROM_LOAD( "6.bin", 0xa0000, 0x20000, CRC(fb129b09) SHA1(b677937d6cf7800359dc6d35dd2de3ec27919d71) )
+
+ ROM_REGION( 0x80000, REGION_GFX1, 0 )
+ ROM_LOAD( "8.bin", 0x00000, 0x20000, CRC(509c0e94) SHA1(9e87c74e76afe6c3a7ba194439434f54e2c879eb) )
+ ROM_LOAD( "9.bin", 0x20000, 0x20000, CRC(48416f20) SHA1(f461fcbff6d2fa4774d64c26475089d1aeea7fb5) )
+ ROM_LOAD( "10.bin", 0x40000, 0x20000, CRC(869d1661) SHA1(ac155bd24ebfea8e064859e1a05317001286f9ae) )
+ ROM_FILL( 0x60000, 0x20000, 0x00 )
+ROM_END
+
+
+GAME( 1992, multigam, 0, multigam, multigam, multigam, ROT0, "unknown", "Multi Game (set 1)", 0 )
+GAME( 1992, multigmb, multigam, multigam, multigam, multigam, ROT0, "unknown", "Multi Game (set 2)", 0 )