summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit86e9f195a9e8b89825f3a80667ed4135613eea19 (patch)
tree88fde6b508a394897adf43d2fccd2ef643d69d6a
parent95189012812895f77d2f083a7275b8bfa85b60aa (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.c431
-rw-r--r--src/mame/mamedriv.c1
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 */