diff options
author | Aaron Giles <aaron@aarongiles.com> | 2008-04-02 08:31:21 +0000 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2008-04-02 08:31:21 +0000 |
commit | 86e9f195a9e8b89825f3a80667ed4135613eea19 (patch) | |
tree | 88fde6b508a394897adf43d2fccd2ef643d69d6a | |
parent | 95189012812895f77d2f083a7275b8bfa85b60aa (diff) |
From: Mariusz Wojcieszek
Attached diff adds Multi Game III (yet another NES-based hack) to multigam.c. Game is playable.
Multi Game III
-rw-r--r-- | src/mame/drivers/multigam.c | 431 | ||||
-rw-r--r-- | src/mame/mamedriv.c | 1 |
2 files changed, 392 insertions, 40 deletions
diff --git a/src/mame/drivers/multigam.c b/src/mame/drivers/multigam.c index 701b17edcb0..129fac5edad 100644 --- a/src/mame/drivers/multigam.c +++ b/src/mame/drivers/multigam.c @@ -35,6 +35,8 @@ - ROM at 0x80000: Several things patched and/or relocated. Most original NOPs were replaced by proper code. + Multi Game III: 21 games included, hardware features MMC3 NES mapper and additional + RAM used by Super Mario Bros 3. */ #include "driver.h" @@ -43,6 +45,12 @@ #include "sound/nes_apu.h" #include "cpu/m6502/m6502.h" +/****************************************************** + + NES interface + +*******************************************************/ + static WRITE8_HANDLER( sprite_dma_w ) { int source = ( data & 7 ); @@ -64,7 +72,11 @@ static WRITE8_HANDLER( psg_4017_w ) NESPSG_0_w(machine, 0x17, data); } -/* Inputs */ +/****************************************************** + + Inputs + +*******************************************************/ static UINT32 in_0; static UINT32 in_1; @@ -109,43 +121,42 @@ static READ8_HANDLER( multigam_inputs_r ) } -/*PRG and VROM Banking */ +/****************************************************** + + ROM/VROM banking (Multi Game) + +*******************************************************/ static int multigam_game_gfx_bank = 0; -static WRITE8_HANDLER( multigam_mapper_w ) +static WRITE8_HANDLER(multigam_switch_prg_rom) { - if ( offset == 0x0fff ) - { - /* switch PRG rom */ - UINT8* dst = memory_region( REGION_CPU1 ); - UINT8* src = memory_region( REGION_USER1 ); + /* 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 + if ( data & 0x80 ) + { + if ( data & 0x01 ) { - memcpy( &dst[0x8000], &src[data*0x4000], 0x4000 ); - memcpy( &dst[0xc000], &src[data*0x4000], 0x4000 ); + data &= ~0x01; } - } - 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; + memcpy( &dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000 ); } else { - logerror( "Unmapped multigam_mapper_w: offset = %04X, data = %02X\n", offset, data ); + memcpy( &dst[0x8000], &src[data*0x4000], 0x4000 ); + memcpy( &dst[0xc000], &src[data*0x4000], 0x4000 ); } -} +}; + +static WRITE8_HANDLER(multigam_switch_gfx_rom) +{ + 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; +}; + static WRITE8_HANDLER(multigam_mapper2_w) { @@ -159,6 +170,12 @@ static WRITE8_HANDLER(multigam_mapper2_w) } } +/****************************************************** + + Memory map (Multi Game) + +*******************************************************/ + 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 */ @@ -171,11 +188,263 @@ static ADDRESS_MAP_START( multigam_map, ADDRESS_SPACE_PROGRAM, 8 ) 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(0x6000, 0x7fff) AM_ROM + AM_RANGE(0x6fff, 0x6fff) AM_WRITE(multigam_switch_prg_rom) + AM_RANGE(0x7fff, 0x7fff) AM_WRITE(multigam_switch_gfx_rom) AM_RANGE(0x8000, 0xffff) AM_ROM AM_WRITE(multigam_mapper2_w) ADDRESS_MAP_END -static INPUT_PORTS_START( multigam ) +/****************************************************** + + MMC3 (Multi Game III) + +*******************************************************/ + +static int multigam3_mmc3_scanline_counter; +static int multigam3_mmc3_scanline_latch; +static int multigam3_mmc3_banks[2]; +static int multigam3_mmc3_4screen; +static int multigam3_mmc3_last_bank = 0xff; +static UINT8* multigmc_mmc3_6000_ram; + +static void multigam3_mmc3_scanline_cb( int num, int scanline, int vblank, int blanked ) +{ + if ( !vblank && !blanked ) + { + if ( --multigam3_mmc3_scanline_counter == -1 ) + { + multigam3_mmc3_scanline_counter = multigam3_mmc3_scanline_latch; + cpunum_set_input_line(Machine, 0, 0, PULSE_LINE ); + } + } +} + +static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) +{ + /* basically, a MMC3 mapper from the nes */ + static int multigam3_mmc3_command; + + switch( offset & 0x7001 ) + { + case 0x0000: + multigam3_mmc3_command = data; + + if ( multigam3_mmc3_last_bank != ( data & 0xc0 ) ) + { + int bank; + + /* reset the banks */ + if ( multigam3_mmc3_command & 0x40 ) + { + /* high bank */ + bank = multigam3_mmc3_banks[0] * 0x2000 + 0xa0000; + + memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_USER1 )[0xa0000 + 0x3c000], 0x2000 ); + } + else + { + /* low bank */ + bank = multigam3_mmc3_banks[0] * 0x2000 + 0xa0000; + + memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_USER1 )[0xa0000 + 0x3c000], 0x2000 ); + } + + /* mid bank */ + bank = multigam3_mmc3_banks[1] * 0x2000 + 0xa0000; + memcpy( &memory_region( REGION_CPU1 )[0x0a000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + + multigam3_mmc3_last_bank = data & 0xc0; + } + break; + + case 0x0001: + { + UINT8 cmd = multigam3_mmc3_command & 0x07; + int page = ( multigam3_mmc3_command & 0x80 ) >> 5; + int bank; + + switch( cmd ) + { + case 0: /* char banking */ + case 1: /* char banking */ + data &= 0xfe; + page ^= ( cmd << 1 ); + ppu2c0x_set_videorom_bank( 0, page, 2, 0x100 + data, 64 ); + break; + + case 2: /* char banking */ + case 3: /* char banking */ + case 4: /* char banking */ + case 5: /* char banking */ + page ^= cmd + 2; + ppu2c0x_set_videorom_bank( 0, page, 1, 0x100 + data, 64 ); + break; + + case 6: /* program banking */ + if ( multigam3_mmc3_command & 0x40 ) + { + /* high bank */ + multigam3_mmc3_banks[0] = data & 0x1f; + bank = ( multigam3_mmc3_banks[0] ) * 0x2000 + 0xa0000; + + memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_USER1 )[0xa0000 + 0x3c000], 0x2000 ); + } + else + { + /* low bank */ + multigam3_mmc3_banks[0] = data & 0x1f; + bank = ( multigam3_mmc3_banks[0] ) * 0x2000 + 0xa0000; + + memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_USER1 )[0xa0000 + 0x3c000], 0x2000 ); + } + break; + + case 7: /* program banking */ + { + /* mid bank */ + multigam3_mmc3_banks[1] = data & 0x1f; + bank = multigam3_mmc3_banks[1] * 0x2000 + 0xa0000; + + memcpy( &memory_region( REGION_CPU1 )[0x0a000], &memory_region( REGION_USER1 )[bank], 0x2000 ); + } + break; + } + } + break; + + case 0x2000: /* mirroring */ + if( !multigam3_mmc3_4screen ) + { + if ( data & 0x40 ) + ppu2c0x_set_mirroring( 0, PPU_MIRROR_HIGH ); + else + ppu2c0x_set_mirroring( 0, ( data & 1 ) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + } + break; + + case 0x2001: /* enable ram at $6000 */ + /* ignored - we always enable it */ + break; + + case 0x4000: /* scanline counter */ + multigam3_mmc3_scanline_counter = data; + break; + + case 0x4001: /* scanline latch */ + multigam3_mmc3_scanline_latch = data; + break; + + case 0x6000: /* disable irqs */ + ppu2c0x_set_scanline_callback( 0, 0 ); + break; + + case 0x6001: /* enable irqs */ + ppu2c0x_set_scanline_callback( 0, multigam3_mmc3_scanline_cb ); + break; + } +} + +static void multigam_init_smb3(void) +{ + UINT8* dst = memory_region( REGION_CPU1 ); + UINT8* src = memory_region( REGION_USER1 ); + + memcpy(&dst[0x8000], &src[0xa0000 + 0x3c000], 0x4000); + memcpy(&dst[0xc000], &src[0xa0000 + 0x3c000], 0x4000); + + memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, multigam3_mmc3_rom_switch_w ); + + memory_set_bankptr(1, multigmc_mmc3_6000_ram); + + multigam3_mmc3_banks[0] = 0x1e; + multigam3_mmc3_banks[1] = 0x1f; + multigam3_mmc3_scanline_counter = 0; + multigam3_mmc3_scanline_latch = 0; + multigam3_mmc3_4screen = 0; + multigam3_mmc3_last_bank = 0xff; + +}; + +static WRITE8_HANDLER(multigm3_mapper2_w) +{ + if ( multigam_game_gfx_bank & 0x80 ) + { + ppu2c0x_set_videorom_bank( 0, 0, 8, (multigam_game_gfx_bank & 0xfc) + (data & 0x3), 512 ); + } + else + { + logerror( "Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data ); + } +}; + +static WRITE8_HANDLER(multigm3_switch_prg_rom) +{ + /* switch PRG rom */ + UINT8* dst = memory_region( REGION_CPU1 ); + UINT8* src = memory_region( REGION_USER1 ); + + if ( data == 0xa8 ) + { + multigam_init_smb3(); + return; + } + else + { + memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, multigm3_mapper2_w ); + memory_set_bankptr(1, memory_region(REGION_CPU1) + 0x6000); + } + + 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 ); + } +}; + +/****************************************************** + + Memory map (Multi Game III) + +*******************************************************/ + +static ADDRESS_MAP_START( multigm3_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(0x5001, 0x5001) AM_WRITE(multigm3_switch_prg_rom) + AM_RANGE(0x5002, 0x5002) AM_WRITENOP + AM_RANGE(0x5003, 0x5003) AM_WRITE(multigam_switch_gfx_rom) + AM_RANGE(0x5000, 0x5ffe) AM_ROM + AM_RANGE(0x5fff, 0x5fff) AM_READ(multigam_inputs_r) + AM_RANGE(0x6000, 0x7fff) AM_RAMBANK(1) + AM_RANGE(0x6fff, 0x6fff) AM_WRITENOP /* 0x00 in attract mode, 0xff during play */ + AM_RANGE(0x8000, 0xffff) AM_ROM AM_WRITE(multigm3_mapper2_w) +ADDRESS_MAP_END + +/****************************************************** + + Input ports + +*******************************************************/ + +static INPUT_PORTS_START( multigam_common ) 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) @@ -198,6 +467,10 @@ static INPUT_PORTS_START( multigam ) PORT_START /* IN2 */ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN1 ) +INPUT_PORTS_END + +static INPUT_PORTS_START( multigam ) + PORT_INCLUDE( multigam_common ) PORT_START /* IN3 */ PORT_DIPNAME( 0x06, 0x00, "Coin/Time" ) @@ -207,17 +480,29 @@ static INPUT_PORTS_START( multigam ) PORT_DIPSETTING( 0x06, "10 min" ) INPUT_PORTS_END +static INPUT_PORTS_START( multigm3 ) + PORT_INCLUDE( multigam_common ) + + PORT_START /* IN3 */ + PORT_DIPNAME( 0x06, 0x00, "Coin/Time" ) + PORT_DIPSETTING( 0x00, "15 min" ) + PORT_DIPSETTING( 0x04, "8 min" ) + PORT_DIPSETTING( 0x02, "11 min" ) + PORT_DIPSETTING( 0x06, "5 min" ) +INPUT_PORTS_END + + +/****************************************************** + + PPU/Video interface + +*******************************************************/ + static const 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 ); @@ -252,15 +537,30 @@ static VIDEO_UPDATE( multigam ) return 0; } -static DRIVER_INIT( multigam ) -{ - multigam_mapper_w( machine, 0x0fff, 0x01 ); -} - static GFXDECODE_START( multigam ) /* none, the ppu generates one */ GFXDECODE_END +/****************************************************** + + Machine + +*******************************************************/ + +static MACHINE_RESET( multigam ) +{ + /* reset the ppu */ + ppu2c0x_reset( 0, 1 ); +} + +static MACHINE_RESET( multigm3 ) +{ + /* reset the ppu */ + ppu2c0x_reset( 0, 1 ); + multigm3_switch_prg_rom(machine, 0, 0x01 ); +}; + + static MACHINE_DRIVER_START( multigam ) /* basic machine hardware */ MDRV_CPU_ADD_TAG("main", N2A03, N2A03_DEFAULTCLOCK) @@ -293,6 +593,14 @@ static MACHINE_DRIVER_START( multigam ) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_DRIVER_END +static MACHINE_DRIVER_START( multigm3 ) + MDRV_IMPORT_FROM(multigam) + MDRV_CPU_MODIFY("main") + MDRV_CPU_PROGRAM_MAP(multigm3_map, 0) + + MDRV_MACHINE_RESET( multigm3 ) +MACHINE_DRIVER_END + ROM_START( multigam ) ROM_REGION( 0x10000, REGION_CPU1, 0 ) ROM_LOAD( "7.bin", 0x0000, 0x8000, CRC(f0fa7cf2) SHA1(7f3b3dca796b964893197aef7f0f31dfd7a2c1a4) ) @@ -331,6 +639,49 @@ ROM_START( multigmb ) ROM_FILL( 0x60000, 0x20000, 0x00 ) ROM_END +ROM_START( multigm3 ) + ROM_REGION( 0x10000, REGION_CPU1, 0 ) + ROM_LOAD( "mg3-6.bin", 0x0000, 0x8000, CRC(3c1e53f1) SHA1(2eaf84e592db58cd268738da2642c716895e4eaa) ) + + ROM_REGION( 0x100000, REGION_USER1, 0 ) + ROM_LOAD( "mg3-2.bin", 0x00000, 0x20000, CRC(de6d2232) SHA1(30a5e6cd44cfbce2c5186dbc45c0c14c8b1510c4) ) + ROM_LOAD( "mg3-1.bin", 0x40000, 0x20000, CRC(b0dc8136) SHA1(6d7334aae9047ec2028790bd3b326458b5cdc737) ) + ROM_LOAD( "mg3-3.bin", 0x60000, 0x20000, CRC(6e96d642) SHA1(45eb954a0a905ad48ebc04ee3ed8858a1077817a) ) + ROM_LOAD( "mg3-5.bin", 0xa0000, 0x40000, CRC(44609e6f) SHA1(c12a63e34b379427a3c146f1f85688fedf55ed0f) ) + ROM_LOAD( "mg3-4.bin", 0xe0000, 0x20000, CRC(9b022e13) SHA1(96ad9c49cf72fe19a3e9944f8102d2d905266e92) ) + + + ROM_REGION( 0x80000, REGION_GFX1, 0 ) + ROM_LOAD( "mg3-7.bin", 0x00000, 0x20000, CRC(d8308cdb) SHA1(7bfb864611c32cf3740cfd650bfe275513d511d7) ) + ROM_LOAD( "mg3-8.bin", 0x20000, 0x20000, CRC(b4a53b9d) SHA1(63d8901149d0d9b69f28bfc096f7932448542032) ) + ROM_LOAD( "mg3-9.bin", 0x40000, 0x20000, CRC(a0ae2b4b) SHA1(5e026ad8a6b2a8120e386471d5178625bda04525) ) + ROM_FILL( 0x60000, 0x20000, 0x00 ) +ROM_END + +static DRIVER_INIT( multigam ) +{ + multigam_switch_prg_rom( machine, 0x0, 0x01 ); +} + +static void multigm3_decrypt(UINT8* mem, int memsize, const UINT8* decode_nibble) +{ + int i; + for (i = 0; i < memsize; i++) + { + mem[i] = decode_nibble[mem[i] & 0x0f] | (decode_nibble[mem[i] >> 4] << 4); + } +}; + +static DRIVER_INIT(multigm3) +{ + const UINT8 decode[16] = { 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a }; + + multigm3_decrypt(memory_region(REGION_CPU1), memory_region_length(REGION_CPU1), decode ); + multigm3_decrypt(memory_region(REGION_USER1), memory_region_length(REGION_USER1), decode ); + + multigmc_mmc3_6000_ram = auto_malloc(0x2000); +} 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 ) +GAME( 19??, multigm3, 0, multigm3, multigm3, multigm3, ROT0, "Seo Jin", "Multi Game III", 0 ) diff --git a/src/mame/mamedriv.c b/src/mame/mamedriv.c index b011ac8b507..504e0ebe157 100644 --- a/src/mame/mamedriv.c +++ b/src/mame/mamedriv.c @@ -1082,6 +1082,7 @@ const game_driver * const drivers[] = /* NES-based hacks */ DRIVER( multigam ) /* 1992 */ DRIVER( multigmb ) /* 1992 */ + DRIVER( multigm3 ) /* 19?? */ DRIVER( cham24 ) /* 2002 */ /* Nintendo Super System Games */ |