diff --git a/.gitattributes b/.gitattributes index 41229f90954..92b939d5ed9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3490,6 +3490,9 @@ src/mame/machine/mc8123.c svneol=native#text/plain src/mame/machine/mc8123.h svneol=native#text/plain src/mame/machine/mcr.c svneol=native#text/plain src/mame/machine/mcr68.c svneol=native#text/plain +src/mame/machine/md_pcb.c svneol=native#text/plain +src/mame/machine/md_pcb.h svneol=native#text/plain +src/mame/machine/megadriv.c svneol=native#text/plain src/mame/machine/meters.c svneol=native#text/plain src/mame/machine/meters.h svneol=native#text/plain src/mame/machine/mexico86.c svneol=native#text/plain diff --git a/src/mame/drivers/megadriv.c b/src/mame/drivers/megadriv.c index fa8a525032f..6b5ca9f86b3 100644 --- a/src/mame/drivers/megadriv.c +++ b/src/mame/drivers/megadriv.c @@ -9260,21 +9260,460 @@ DRIVER_INIT( _32x ) DRIVER_INIT_CALL(megadriv); } -#if 1 -ROM_START( 32x_bios ) +/************************************* + * + * Input handlers + * + *************************************/ - ROM_REGION16_BE( 0x400000, "gamecart", ROMREGION_ERASEFF ) /* 68000 Code */ +/* We need to always initialize 6 buttons pad */ +static emu_timer *mess_io_timeout[3]; +static int mess_io_stage[3]; - ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ - ROM_COPY( "gamecart", 0x0, 0x0, 0x400000) +static TIMER_CALLBACK( mess_io_timeout_timer_callback ) +{ + mess_io_stage[(int)(FPTR)ptr] = -1; +} + +/* J-Cart controller port */ + +static UINT8 jcart_io_data[2]; + +WRITE16_HANDLER( jcart_ctrl_w ) +{ + jcart_io_data[0] = (data & 1) << 6; + jcart_io_data[1] = (data & 1) << 6; +} + +READ16_HANDLER( jcart_ctrl_r ) +{ + UINT16 retdata = 0; + UINT8 joy[2]; + + if (jcart_io_data[0] & 0x40) + { + joy[0] = input_port_read_safe(space->machine, "JCART3_3B", 0); + joy[1] = input_port_read_safe(space->machine, "JCART4_3B", 0); + retdata = (jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8); + } + else + { + joy[0] = ((input_port_read_safe(space->machine, "JCART3_3B", 0) & 0xc0) >> 2) | + (input_port_read_safe(space->machine, "JCART3_3B", 0) & 0x03); + joy[1] = ((input_port_read_safe(space->machine, "JCART4_3B", 0) & 0xc0) >> 2) | + (input_port_read_safe(space->machine, "JCART4_3B", 0) & 0x03); + retdata = (jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8); + } + return retdata; +} + +static void mess_init_6buttons_pad(running_machine *machine) +{ + int i; + + for (i = 0; i < 3; i++) + { + mess_io_timeout[i] = timer_alloc(machine, mess_io_timeout_timer_callback, (void*)(FPTR)i); + mess_io_stage[i] = -1; + } +} + +/* These overwrite the MAME ones in DRIVER_INIT */ +/* They're needed to give the users the choice between different controllers */ +static UINT8 mess_md_io_read_data_port(running_machine *machine, int portnum) +{ + static const char *const pad6names[2][4] = { + { "PAD1_6B", "PAD2_6B", "UNUSED", "UNUSED" }, + { "EXTRA1", "EXTRA2", "UNUSED", "UNUSED" } + }; + static const char *const pad3names[4] = { "PAD1_3B", "PAD2_3B", "UNUSED", "UNUSED" }; + + UINT8 retdata; + int controller; + UINT8 helper_6b = (megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from megadrive_io_data_regs + UINT8 helper_3b = (megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs + + switch (portnum) + { + case 0: + controller = (input_port_read(machine, "CTRLSEL") & 0x0f); + break; + + case 1: + controller = (input_port_read(machine, "CTRLSEL") & 0xf0); + break; + + default: + controller = 0; + break; + } + + /* Are we using a 6 buttons Joypad? */ + if (controller) + { + if (megadrive_io_data_regs[portnum] & 0x40) + { + if (mess_io_stage[portnum] == 2) + { + /* here we read B, C & the additional buttons */ + retdata = (megadrive_io_data_regs[portnum] & helper_6b) | + (((input_port_read_safe(machine, pad6names[0][portnum], 0) & 0x30) | + (input_port_read_safe(machine, pad6names[1][portnum], 0) & 0x0f)) & ~helper_6b); + } + else + { + /* here we read B, C & the directional buttons */ + retdata = (megadrive_io_data_regs[portnum] & helper_6b) | + ((input_port_read_safe(machine, pad6names[0][portnum], 0) & 0x3f) & ~helper_6b); + } + } + else + { + if (mess_io_stage[portnum] == 1) + { + /* here we read ((Start & A) >> 2) | 0x00 */ + retdata = (megadrive_io_data_regs[portnum] & helper_6b) | + (((input_port_read_safe(machine, pad6names[0][portnum], 0) & 0xc0) >> 2) & ~helper_6b); + } + else if (mess_io_stage[portnum]==2) + { + /* here we read ((Start & A) >> 2) | 0x0f */ + retdata = (megadrive_io_data_regs[portnum] & helper_6b) | + ((((input_port_read_safe(machine, pad6names[0][portnum], 0) & 0xc0) >> 2) | 0x0f) & ~helper_6b); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (megadrive_io_data_regs[portnum] & helper_6b) | + ((((input_port_read_safe(machine, pad6names[0][portnum], 0) & 0xc0) >> 2) | + (input_port_read_safe(machine, pad6names[0][portnum], 0) & 0x03)) & ~helper_6b); + } + } + + // mame_printf_debug("read io data port stage %d port %d %02x\n",mess_io_stage[portnum],portnum,retdata); + + retdata |= (retdata << 8); + } + /* Otherwise it's a 3 buttons Joypad */ + else + { + if (megadrive_io_data_regs[portnum] & 0x40) + { + /* here we read B, C & the directional buttons */ + retdata = (megadrive_io_data_regs[portnum] & helper_3b) | + (((input_port_read_safe(machine, pad3names[portnum], 0) & 0x3f) | 0x40) & ~helper_3b); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (megadrive_io_data_regs[portnum] & helper_3b) | + ((((input_port_read_safe(machine, pad3names[portnum], 0) & 0xc0) >> 2) | + (input_port_read_safe(machine, pad3names[portnum], 0) & 0x03) | 0x40) & ~helper_3b); + } + } + + return retdata; +} + + +static void mess_md_io_write_data_port(running_machine *machine, int portnum, UINT16 data) +{ + int controller; + + switch (portnum) + { + case 0: + controller = (input_port_read(machine, "CTRLSEL") & 0x0f); + break; + + case 1: + controller = (input_port_read(machine, "CTRLSEL") & 0xf0); + break; + + default: + controller = 0; + break; + } + + if (controller) + { + if (megadrive_io_ctrl_regs[portnum] & 0x40) + { + if (((megadrive_io_data_regs[portnum] & 0x40) == 0x00) && ((data & 0x40) == 0x40)) + { + mess_io_stage[portnum]++; + timer_adjust_oneshot(mess_io_timeout[portnum], machine->device("maincpu")->cycles_to_attotime(8192), 0); + } + + } + } + megadrive_io_data_regs[portnum] = data; + //mame_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); +} + + +/************************************* + * + * Input ports + * + *************************************/ + + +static INPUT_PORTS_START( md ) + PORT_START("CTRLSEL") /* Controller selection */ + PORT_CATEGORY_CLASS( 0x0f, 0x00, "Player 1 Controller" ) + PORT_CATEGORY_ITEM( 0x00, "Joystick 3 Buttons", 10 ) + PORT_CATEGORY_ITEM( 0x01, "Joystick 6 Buttons", 11 ) +// PORT_CATEGORY_ITEM( 0x02, "Sega Mouse", 12 ) +/* there exists both a 2 buttons version of the Mouse (Jpn ver, to be used with RPGs, it + can aslo be used as trackball) and a 3 buttons version (US ver, no trackball feats.) */ +// PORT_CATEGORY_ITEM( 0x03, "Sega Menacer", 13 ) +// PORT_CATEGORY_ITEM( 0x04, "Konami Justifier", 14 ) +// PORT_CATEGORY_ITEM( 0x05, "Team Player (Sega Multitap)", 15 ) +// PORT_CATEGORY_ITEM( 0x06, "4-Play (EA Multitap)", 16 ) +// PORT_CATEGORY_ITEM( 0x07, "J-Cart", 17 ) + PORT_CATEGORY_CLASS( 0xf0, 0x00, "Player 2 Controller" ) + PORT_CATEGORY_ITEM( 0x00, "Joystick 3 Buttons", 20 ) + PORT_CATEGORY_ITEM( 0x10, "Joystick 6 Buttons", 21 ) + PORT_CATEGORY_CLASS( 0xf00, 0x00, "Player 3 Controller (J-Cart)" ) + PORT_CATEGORY_ITEM( 0x00, "Joystick 3 Buttons", 30 ) + PORT_CATEGORY_CLASS( 0xf000, 0x00, "Player 4 Controller (J-Cart)" ) + PORT_CATEGORY_ITEM( 0x00, "Joystick 3 Buttons", 40 ) + + PORT_START("PAD1_3B") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(10) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(10) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(10) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(10) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CATEGORY(10) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CATEGORY(10) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CATEGORY(10) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CATEGORY(10) + + PORT_START("PAD2_3B") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(20) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(20) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(20) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(20) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CATEGORY(20) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CATEGORY(20) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CATEGORY(20) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CATEGORY(20) + + PORT_START("JCART3_3B") /* Joypad 3 on J-Cart (3 button + start) */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3) PORT_CATEGORY(30) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3) PORT_CATEGORY(30) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3) PORT_CATEGORY(30) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3) PORT_CATEGORY(30) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B") PORT_CATEGORY(30) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 C") PORT_CATEGORY(30) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A") PORT_CATEGORY(30) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(3) PORT_CATEGORY(30) + + PORT_START("JCART4_3B") /* Joypad 4 on J-Cart (3 button + start) */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4) PORT_CATEGORY(40) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4) PORT_CATEGORY(40) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4) PORT_CATEGORY(40) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4) PORT_CATEGORY(40) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B") PORT_CATEGORY(40) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 C") PORT_CATEGORY(40) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A") PORT_CATEGORY(40) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(4) PORT_CATEGORY(40) + + PORT_START("PAD1_6B") /* Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(11) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(11) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(11) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CATEGORY(11) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CATEGORY(11) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CATEGORY(11) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CATEGORY(11) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CATEGORY(11) + + PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Z") PORT_CATEGORY(11) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 Y") PORT_CATEGORY(11) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 X") PORT_CATEGORY(11) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Mode") PORT_CATEGORY(11) + + PORT_START("PAD2_6B") /* Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(21) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(21) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(21) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CATEGORY(21) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CATEGORY(21) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CATEGORY(21) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CATEGORY(21) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CATEGORY(21) + + PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Z") PORT_CATEGORY(21) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 Y") PORT_CATEGORY(21) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 X") PORT_CATEGORY(21) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Mode") PORT_CATEGORY(21) + + PORT_START("RESET") /* Buttons on Genesis Console */ + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) +INPUT_PORTS_END + + +/* MegaDrive inputs + Fake Region Selection */ +/* We need this as long as we only have the US version of the SVP add-on, otherwise we could not play + Non-US Virtua Racing versions. It is also handy to develop add-ons emulation without adding each + region variants, while they do not even work. Once emulation is working this must disappear. */ +static INPUT_PORTS_START( md_sel ) + PORT_INCLUDE( md ) + + PORT_START("REGION") + /* Region setting for Console */ + PORT_CONFNAME( 0x000f, 0x0000, DEF_STR( Region ) ) + PORT_CONFSETTING( 0x0000, "Use Default Choice" ) + PORT_CONFSETTING( 0x0001, "US (NTSC, 60fps)" ) + PORT_CONFSETTING( 0x0002, "Japan (NTSC, 60fps)" ) + PORT_CONFSETTING( 0x0003, "Europe (PAL, 50fps)" ) +INPUT_PORTS_END + + +/************************************* + * + * Machine driver + * + *************************************/ + +static MACHINE_START( ms_megadriv ) +{ + mess_init_6buttons_pad(machine); +} + +static MACHINE_RESET( ms_megadriv ) +{ + MACHINE_RESET_CALL( megadriv ); + MACHINE_RESET_CALL( md_mappers ); +} + +static MACHINE_CONFIG_DERIVED( ms_megadriv, megadriv ) + + MCFG_MACHINE_START( ms_megadriv ) + MCFG_MACHINE_RESET( ms_megadriv ) + + MCFG_FRAGMENT_ADD( genesis_cartslot ) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( ms_megadpal, megadpal ) + + MCFG_MACHINE_START( ms_megadriv ) + MCFG_MACHINE_RESET( ms_megadriv ) + + MCFG_FRAGMENT_ADD( genesis_cartslot ) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( ms_megdsvp, megdsvp ) + + MCFG_MACHINE_START( ms_megadriv ) + MCFG_MACHINE_RESET( ms_megadriv ) + + MCFG_FRAGMENT_ADD( genesis_cartslot ) +MACHINE_CONFIG_END + + + +/************************************* + * + * ROM definition(s) + * + *************************************/ + + +/* we don't use the bios rom (it's not needed and only provides security on early models) */ + +ROM_START(genesis) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(gensvp) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(megadriv) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(megadrij) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + + +/************************************* + * + * Driver initialization + * + *************************************/ + +static DRIVER_INIT( mess_md_common ) +{ + megadrive_io_read_data_port_ptr = mess_md_io_read_data_port; + megadrive_io_write_data_port_ptr = mess_md_io_write_data_port; +} + +static DRIVER_INIT( genesis ) +{ + DRIVER_INIT_CALL(megadriv); + DRIVER_INIT_CALL(mess_md_common); +} + +static DRIVER_INIT( gensvp ) +{ + DRIVER_INIT_CALL(megadriv); + DRIVER_INIT_CALL(mess_md_common); +} + +static DRIVER_INIT( md_eur ) +{ + DRIVER_INIT_CALL(megadrie); + DRIVER_INIT_CALL(mess_md_common); +} + +static DRIVER_INIT( md_jpn ) +{ + DRIVER_INIT_CALL(megadrij); + DRIVER_INIT_CALL(mess_md_common); +} + +/****************************************** SegaCD & 32X emulation ****************************************/ + +/* Very preliminary skeleton code from David Haywood, borrowed for MESS by Fabio Priuli */ +/* These are only included to document BIOS informations currently available */ + +static DRIVER_INIT( mess_32x ) +{ + DRIVER_INIT_CALL(_32x); + DRIVER_INIT_CALL(mess_md_common); +} + +static MACHINE_CONFIG_DERIVED( ms_32x, genesis_32x ) + + MCFG_FRAGMENT_ADD( _32x_cartslot ) +MACHINE_CONFIG_END + + +ROM_START( 32x ) + ROM_REGION16_BE( 0x400000, "gamecart", ROMREGION_ERASE00 ) /* 68000 Code */ +// ROM_CART_LOAD("cart", 0x000000, 0x400000, ROM_NOMIRROR) + + ROM_REGION32_BE( 0x400000, "gamecart_sh2", ROMREGION_ERASE00 ) /* Copy for the SH2 */ +// ROM_CART_LOAD("cart", 0x000000, 0x400000, ROM_NOMIRROR) ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ -// ROM_COPY( "gamecart", 0x0, 0x0, 0x400000) ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) // temp, rom should only be visible here when one of the regs is set, tempo needs it +// ROM_CART_LOAD("cart", 0x000000, 0x400000, ROM_NOMIRROR) ROM_COPY( "32x_68k_bios", 0x0, 0x0, 0x100) ROM_REGION( 0x400000, "32x_master_sh2", 0 ) /* SH2 Code */ @@ -9283,22 +9722,112 @@ ROM_START( 32x_bios ) ROM_SYSTEM_BIOS( 1, "sdk", "Mars Version 1.0 (early sdk)" ) ROMX_LOAD( "32x_m_bios_sdk.bin", 0x000000, 0x000800, BAD_DUMP CRC(c7102c53) SHA1(ed73a47f186b373b8eff765f84ef26c3d9ef6cb0), ROM_BIOS(2) ) - ROM_REGION( 0x400000, "32x_slave_sh2", 0 ) /* SH2 Code */ ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) ROM_END -ROM_START( segacdbi ) +/* We need proper names for most of these BIOS ROMs! */ +ROM_START( segacd ) ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_LOAD( "segacd_model2_bios_2_11_u.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b) ) + /* v1.10 */ + ROM_LOAD( "segacd_model1_bios_1_10_u.bin", 0x000000, 0x020000, CRC(c6d10268) SHA1(f4f315adcef9b8feb0364c21ab7f0eaf5457f3ed) ) +ROM_END + +ROM_START( megacd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.00, confirmed good dump */ + ROM_LOAD( "megacd_model1_bios_1_00_e.bin", 0x000000, 0x020000, CRC(529ac15a) SHA1(f891e0ea651e2232af0c5c4cb46a0cae2ee8f356) ) +ROM_END + +ROM_START( megacdj ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v100s", "v1.00S") /* also used for Asia PAL - not handled yet */ + ROMX_LOAD( "megacd_model1_bios_1_00s_j.bin", 0x000000, 0x020000, CRC(550f30bb) SHA1(e4193c6ae44c3cea002707d2a88f1fbcced664de), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "v100p", "v1.00P") + ROMX_LOAD( "megacd_model1_bios_1_00p_j.bin", 0x000000, 0x020000, CRC(9d2da8f2) SHA1(4846f448160059a7da0215a5df12ca160f26dd69), ROM_BIOS(2) ) +ROM_END + +ROM_START( segacd2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v211x", "Model 2 v2.11X") + ROMX_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "v200", "Model 2 v2.00") /* verified dump */ + ROMX_LOAD( "us_scd2_930314.bin", 0x000000, 0x020000, CRC(8af65f58) SHA1(5a8c4b91d3034c1448aac4b5dc9a6484fce51636), ROM_BIOS(2) ) + /* this is reportedly a bad dump, it has many differences from the verified dump and does not boot in Kega */ + /* ROMX_LOAD( "segacd_model2_bios_2_00_u.bin", 0x000000, 0x020000, CRC(340b4be4) SHA1(bd3ee0c8ab732468748bf98953603ce772612704), ROM_BIOS(2) ) */ + ROM_SYSTEM_BIOS(2, "v200w", "Model 2 v2.00W") + ROMX_LOAD( "segacd_model2_bios_2_00w_u.bin", 0x000000, 0x020000, CRC(9f6f6276) SHA1(5adb6c3af218c60868e6b723ec47e36bbdf5e6f0), ROM_BIOS(3) ) +ROM_END + +ROM_START( megacd2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v200w", "v2.00W") // confirmed good dump + ROMX_LOAD( "mpr-15512a.bin", 0x000000, 0x020000, CRC(2a4b82b5) SHA1(45134ef8655b9d06b130726786efe2f8b1d430a3), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "v200", "v2.00") + ROMX_LOAD( "mpr-15512-t.bin", 0x000000, 0x020000, CRC(62108fff) SHA1(cfcf092e0a70779fc5912da0fbd154838df997da), ROM_BIOS(2) ) +ROM_END + +ROM_START( megacd2j ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v200c", "v2.00C") + ROMX_LOAD( "mpr-15398.bin", 0x000000, 0x020000, CRC(ba7bf31d) SHA1(762d20ebb85b980c17c53f928c002d747920a281), ROM_BIOS(1) ) +ROM_END + +ROM_START( laseract ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v104", "v1.04") + ROMX_LOAD( "laseractive_bios_1_04_u.bin", 0x000000, 0x020000, CRC(50cd3d23) SHA1(aa811861f8874775075bd3f53008c8aaf59b07db), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "v102", "v1.02") + ROMX_LOAD( "laseractive_bios_1_02_u.bin", 0x000000, 0x020000, CRC(3b10cf41) SHA1(8af162223bb12fc19b414f126022910372790103), ROM_BIOS(2) ) +ROM_END + +ROM_START( laseractj ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.02 */ + ROM_LOAD( "laseractive_bios_1_02_j.bin", 0x000000, 0x020000, CRC(00eedb3a) SHA1(26237b333db4a4c6770297fa5e655ea95840d5d9) ) +ROM_END + +ROM_START( xeye ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.00 (US), confirmed good with a chip dump */ + ROM_LOAD( "g304.bin", 0x000000, 0x020000, CRC(290f8e33) SHA1(651f14d5a5e0ecb974a60c0f43b1d2006323fb09) ) +ROM_END + +ROM_START( wmega ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.00 (Japan NTSC) Sega BIOS, chip-dumped */ + ROM_LOAD( "g301.bin", 0x000000, 0x020000, CRC(d21fe71d) SHA1(3fc9358072f74bd24e3e297ea11b2bf15a7af891) ) +ROM_END + +ROM_START( wmegam2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.00 */ + ROM_LOAD( "wondermega_m2_bios_2_00_j.bin", 0x000000, 0x020000, CRC(2b19972f) SHA1(b3f32e409bd5508c89ed8be33d41a58d791d0e5d) ) +ROM_END + +ROM_START( cdx ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.21X */ + ROM_LOAD( "segacdx_bios_2_21_u.bin", 0x000000, 0x020000, CRC(d48c44b5) SHA1(2b125c0545afa089b617f2558e686ea723bdc06e) ) +ROM_END + +ROM_START( multmega ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.21X */ + ROM_LOAD( "opr-16140.bin", 0x000000, 0x020000, CRC(aacb851e) SHA1(75548ac9aaa6e81224499f9a1403b2b42433f5b7) ) + /* the below was marked "confirmed good dump", but 0x72 and 0x73 are 0xFF, indicating a bad dump made from memory */ + /* ROM_LOAD( "multimega_bios_2_21_e.bin", 0x000000, 0x020000, CRC(34d3cce1) SHA1(73fc9c014ad803e9e7d8076b3642a8a5224b3e51) ) */ ROM_END /* some games use the 32x and SegaCD together to give better quality FMV */ -ROM_START( 32x_scdb ) +ROM_START( 32x_scd ) ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ - ROM_LOAD( "segacd_model2_bios_2_11_u.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b) ) + ROM_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b) ) + + ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ + ROM_COPY( "gamecart", 0x0, 0x0, 0x400000) ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) @@ -9310,31 +9839,274 @@ ROM_START( 32x_scdb ) ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) ROM_END -ROM_START( g_virr ) - ROM_REGION( 0x400000, "maincpu", 0 ) /* 68000 Code */ - ROM_LOAD( "g_virr.bin", 0x000000, 0x200000, CRC(7e1a324a) SHA1(ff969ae53120cc4e7cb1a8a7e47458f2eb8a2165) ) -ROM_END -ROM_START( g_virrj ) - ROM_REGION( 0x400000, "maincpu", 0 ) /* 68000 Code */ - ROM_LOAD( "g_virrj.bin", 0x000000, 0x200000, CRC(53a293b5) SHA1(0ad38a3ab1cc99edac72184f8ae420e13df5cac6) ) -ROM_END -ROM_START( g_virre ) - ROM_REGION( 0x400000, "maincpu", 0 ) /* 68000 Code */ - ROM_LOAD( "g_virre.bin", 0x000000, 0x200000, CRC(9624d4ef) SHA1(2c3812f8a010571e51269a33a989598787d27c2d) ) -ROM_END -ROM_START( g_virrea ) - ROM_REGION( 0x400000, "maincpu", 0 ) /* 68000 Code */ - ROM_LOAD( "g_virrea.bin", 0x000000, 0x200000, CRC(5a943df9) SHA1(2c08ea556c79d48e88ff5202944c161ae1b41c63) ) + +/****************************************** PICO emulation ****************************************/ + +/* + Pico Implementation By ElBarto (Emmanuel Vadot, elbarto@megadrive.org) + Still missing the PCM custom chip + Some game will not boot due to this + + Pico Info from Notaz (http://notaz.gp2x.de/docs/picodoc.txt) + + addr acc description +-------+-----+------------ +800001 byte Version register. + ?vv? ????, where v can be: + 00 - hardware is for Japan + 01 - European version + 10 - USA version + 11 - ? +800003 byte Buttons, 0 for pressed, 1 for released: + bit 0: UP (white) + bit 1: DOWN (orange) + bit 2: LEFT (blue) + bit 3: RIGHT (green) + bit 4: red button + bit 5: unused? + bit 6: unused? + bit 7: pen button +800005 byte Most significant byte of pen x coordinate. +800007 byte Least significant byte of pen x coordinate. +800009 byte Most significant byte of pen y coordinate. +80000b byte Least significant byte of pen y coordinate. +80000d byte Page register. One bit means one uncovered page sensor. + 00 - storyware closed + 01, 03, 07, 0f, 1f, 3f - pages 1-6 + either page 5 or page 6 is often unused. +800010 word PCM data register. + r/w read returns free bytes left in PCM FIFO buffer + writes write data to buffer. +800012 word PCM control register. + r/w For writes, it has following possible meanings: + ?p?? ???? ???? ?rrr + p - set to enable playback? + r - sample rate / PCM data type? + 0: 8kHz 4bit ADPCM? + 1-7: 16kHz variants? + For reads, if bit 15 is cleared, it means PCM is 'busy' or + something like that, as games sometimes wait for it to become 1. +800019 byte Games write 'S' +80001b byte Games write 'E' +80001d byte Games write 'G' +80001f byte Games write 'A' + +*/ + +#define PICO_PENX 1 +#define PICO_PENY 2 + +static UINT16 pico_read_penpos(running_machine *machine, int pen) +{ + UINT16 penpos = 0; + + switch (pen) + { + case PICO_PENX: + penpos = input_port_read_safe(machine, "PENX", 0); + penpos |= 0x6; + penpos = penpos * 320 / 255; + penpos += 0x3d; + break; + case PICO_PENY: + penpos = input_port_read_safe(machine, "PENY", 0); + penpos |= 0x6; + penpos = penpos * 251 / 255; + penpos += 0x1fc; + break; + } + return penpos; +} + +static READ16_HANDLER( pico_68k_io_read ) +{ + UINT8 retdata; + static UINT8 page_register = 0; + + + retdata = 0; + + switch (offset) + { + case 0: /* Version register ?XX?????? where XX is 00 for japan, 01 for europe and 10 for USA*/ + retdata = (megadrive_region_export << 6) | (megadrive_region_pal << 5); + break; + case 1: + retdata = input_port_read_safe(space->machine, "PAD", 0); + break; + + /* + Still notes from notaz for the pen : + + The pen can be used to 'draw' either on the drawing pad or on the storyware + itself. Both storyware and drawing pad are mapped on single virtual plane, where + coordinates range: + + x: 0x03c - 0x17c + y: 0x1fc - 0x2f7 (drawing pad) + 0x2f8 - 0x3f3 (storyware) + */ + case 2: + retdata = pico_read_penpos(space->machine, PICO_PENX) >> 8; + break; + case 3: + retdata = pico_read_penpos(space->machine, PICO_PENX) & 0x00ff; + break; + case 4: + retdata = pico_read_penpos(space->machine, PICO_PENY) >> 8; + break; + case 5: + retdata = pico_read_penpos(space->machine, PICO_PENY) & 0x00ff; + break; + case 6: + /* Page register : + 00 - storyware closed + 01, 03, 07, 0f, 1f, 3f - pages 1-6 + either page 5 or page 6 is often unused. + */ + { + UINT8 tmp; + + tmp = input_port_read_safe(space->machine, "PAGE", 0); + if (tmp == 2 && page_register != 0x3f) + { + page_register <<= 1; + page_register |= 1; + } + if (tmp == 1 && page_register != 0x00) + page_register >>= 1; + retdata = page_register; + break; + } + case 7: + /* Returns free bytes left in the PCM FIFO buffer */ + retdata = 0x00; + break; + case 8: + /* + For reads, if bit 15 is cleared, it means PCM is 'busy' or + something like that, as games sometimes wait for it to become 1. + */ + retdata = 0x00; + } + return retdata | retdata <<8; +} + +static WRITE16_HANDLER( pico_68k_io_write ) +{ + switch (offset) + { + } +} + +static ADDRESS_MAP_START( _pico_mem, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0x000000, 0x3fffff) AM_ROM + + AM_RANGE(0x800000, 0x80001f) AM_READWRITE(pico_68k_io_read, pico_68k_io_write) + + AM_RANGE(0xc00000, 0xc0001f) AM_READWRITE(megadriv_vdp_r, megadriv_vdp_w) + AM_RANGE(0xe00000, 0xe0ffff) AM_RAM AM_MIRROR(0x1f0000) AM_BASE(&megadrive_ram) +ADDRESS_MAP_END + + +static INPUT_PORTS_START( pico ) + PORT_START("PAD") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("Red Button") + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Pen Button") + + PORT_START("PAGE") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Increment Page") + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Decrement Page") + + PORT_START("PENX") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_CATEGORY(5) PORT_PLAYER(1) PORT_NAME("PEN X") + + PORT_START("PENY") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0,255 ) PORT_CATEGORY(5) PORT_PLAYER(1) PORT_NAME("PEN Y") + + PORT_START("REGION") + /* Region setting for Console */ + PORT_DIPNAME( 0x000f, 0x0000, DEF_STR( Region ) ) + PORT_DIPSETTING( 0x0000, "Use HazeMD Default Choice" ) + PORT_DIPSETTING( 0x0001, "US (NTSC, 60fps)" ) + PORT_DIPSETTING( 0x0002, "JAPAN (NTSC, 60fps)" ) + PORT_DIPSETTING( 0x0003, "EUROPE (PAL, 50fps)" ) +INPUT_PORTS_END + + +static MACHINE_CONFIG_DERIVED( pico, megadriv ) + + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(_pico_mem) + + MCFG_DEVICE_REMOVE("genesis_snd_z80") + + MCFG_MACHINE_RESET( ms_megadriv ) + + MCFG_FRAGMENT_ADD( pico_cartslot ) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( picopal, megadpal ) + + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(_pico_mem) + + MCFG_DEVICE_REMOVE("genesis_snd_z80") + + MCFG_MACHINE_RESET( ms_megadriv ) + + MCFG_FRAGMENT_ADD( pico_cartslot ) +MACHINE_CONFIG_END + + + +ROM_START( pico ) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) ROM_END -#ifndef MESS -GAME( 1994, 32x_bios, 0, genesis_32x, megadriv, _32x, ROT0, "Sega", "32X Bios", GAME_NOT_WORKING ) -GAME( 1994, segacdbi, 0, genesis_scd, megadriv, megadriv,ROT0, "Sega", "Sega-CD Model 2 BIOS V2.11 (U)", GAME_NOT_WORKING ) -GAME( 1994, 32x_scdb, 0, genesis_32x_scd, megadriv, _32x, ROT0, "Sega", "Sega-CD Model 2 BIOS V2.11 (U) (with 32X)", GAME_NOT_WORKING ) -GAME( 1994, g_virr, 0, megdsvp, megadriv, megadriv, ROT0, "Sega", "Virtua Racing (U) [!]", 0 ) -GAME( 1994, g_virrj, g_virr, megdsvp, megadriv, megadrij, ROT0, "Sega", "Virtua Racing (J) [!]", 0 ) -GAME( 1994, g_virre, g_virr, megdsvppal, megadriv, megadrie, ROT0, "Sega", "Virtua Racing (E) [!]", 0 ) -GAME( 1994, g_virrea, g_virr, megdsvppal, megadriv, megadrie, ROT0, "Sega", "Virtua Racing (E) [a1]", 0 ) -#endif +ROM_START( picou ) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END -#endif +ROM_START( picoj ) + ROM_REGION(0x1415000, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ +CONS( 1989, genesis, 0, 0, ms_megadriv, md, genesis, "Sega", "Genesis (USA, NTSC)", 0) +CONS( 1993, gensvp, genesis, 0, ms_megdsvp, md_sel, gensvp, "Sega", "Genesis (USA, NTSC, w/SVP)", 0) +CONS( 1990, megadriv, genesis, 0, ms_megadpal, md, md_eur, "Sega", "Mega Drive (Europe, PAL)", 0) +CONS( 1988, megadrij, genesis, 0, ms_megadriv, md, md_jpn, "Sega", "Mega Drive (Japan, NTSC)", 0) +CONS( 1994, pico, 0, 0, picopal, pico, md_eur, "Sega", "Pico (Europe, PAL)", 0) +CONS( 1994, picou, pico, 0, pico, pico, genesis, "Sega", "Pico (USA, NTSC)", 0) +CONS( 1993, picoj, pico, 0, pico, pico, md_jpn, "Sega", "Pico (Japan, NTSC)", 0) + +/* Not Working */ +CONS( 1994, 32x, 0, 0, ms_32x, md_sel, mess_32x, "Sega", "32X", GAME_NOT_WORKING ) +CONS( 1992, segacd, 0, 0, genesis_scd, md, genesis, "Sega", "Sega CD (USA, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, megacd, segacd, 0, genesis_scd, md, md_eur, "Sega", "Mega-CD (Europe, PAL)", GAME_NOT_WORKING ) +CONS( 1991, megacdj, segacd, 0, genesis_scd, md, md_jpn, "Sega", "Mega-CD (Japan, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, segacd2, 0, 0, genesis_scd, md, genesis, "Sega", "Sega CD 2 (USA, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, megacd2, segacd2, 0, genesis_scd, md, md_eur, "Sega", "Mega-CD 2 (Europe, PAL)", GAME_NOT_WORKING ) +CONS( 1993, megacd2j, segacd2, 0, genesis_scd, md, md_jpn, "Sega", "Mega-CD 2 (Japan, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, laseract, 0, 0, genesis_scd, md, genesis, "Pioneer","LaserActive (USA, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, laseractj, laseract, 0, genesis_scd, md, md_jpn, "Pioneer","LaserActive (Japan, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, xeye, 0, 0, genesis_scd, md, genesis, "JVC", "X'eye (USA, NTSC)", GAME_NOT_WORKING ) +CONS( 1992, wmega, xeye, 0, genesis_scd, md, md_jpn, "Sega", "Wondermega (Japan, NTSC)", GAME_NOT_WORKING ) +CONS( 1993, wmegam2, xeye, 0, genesis_scd, md, md_jpn, "Victor", "Wondermega M2 (Japan, NTSC)", GAME_NOT_WORKING ) +CONS( 1994, cdx, 0, 0, genesis_scd, md, genesis, "Sega", "CDX (USA, NTSC)", GAME_NOT_WORKING ) +CONS( 1994, multmega, cdx, 0, genesis_scd, md, md_eur, "Sega", "Multi-Mega (Europe, PAL)", GAME_NOT_WORKING ) +CONS( 1994, 32x_scd, segacd, 0, genesis_32x_scd, md_sel, mess_32x, "Sega", "Sega CD (USA, NTSC, w/32X)", GAME_NOT_WORKING ) diff --git a/src/mame/includes/megadriv.h b/src/mame/includes/megadriv.h index 3c8a5a65109..b596f540b04 100644 --- a/src/mame/includes/megadriv.h +++ b/src/mame/includes/megadriv.h @@ -2,6 +2,7 @@ #define MASTER_CLOCK_PAL 53203424 #define SEGACD_CLOCK 12500000 +#include "imagedev/cartslot.h" extern DRIVER_INIT( megadriv_c2 ); extern DRIVER_INIT( megadrie ); @@ -112,3 +113,15 @@ struct _mtech_bios /* once all the regs are saved in this structure, it would be int mt_bank_partial; int mt_bank_addr; }; + +/*----------- defined in machine/megadriv.c -----------*/ + +MACHINE_RESET( md_mappers ); + +MACHINE_CONFIG_EXTERN( genesis_cartslot ); +MACHINE_CONFIG_EXTERN( _32x_cartslot ); +MACHINE_CONFIG_EXTERN( pico_cartslot ); + +WRITE16_HANDLER( jcart_ctrl_w ); +READ16_HANDLER( jcart_ctrl_r ); + diff --git a/src/mame/machine/md_pcb.c b/src/mame/machine/md_pcb.c new file mode 100644 index 00000000000..ed0bf66e333 --- /dev/null +++ b/src/mame/machine/md_pcb.c @@ -0,0 +1,61 @@ +/***************************************************************************************** + + Genesis/MegaDrive Cart PCBs Emulation + +****************************************************************************************/ + +#include "emu.h" +#include "md_pcb.h" + +typedef struct _md_pcb md_pcb; +struct _md_pcb +{ + const char *pcb_name; + int pcb_id; +}; + +// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it +static const md_pcb pcb_list[] = +{ + /* Standard Sega PCB (one rom) */ + {"171-5703", STD_ROM}, + {"171-5927", STD_ROM}, + {"171-5978B", STD_ROM}, + {"171-5978BA", STD_ROM}, + {"171-6329A", STD_ROM}, + + /* Sega PCB with two roms */ + {"171-5841", STD_ROM}, + + /* Sega PCB with Serial EEPROM */ + {"171-5878", SEGA_5878}, + {"171-6584A", SEGA_6584A}, + + /* Sega PCB with sram */ + {"171-5921", SEGA_5921}, + {"171-6278A", SEGA_6278A}, + + /* Sega PCB with fram */ + {"171-6658A", SEGA_6658A}, + + /* Namcot PCB (blob epoxy chip) */ + {"837-8861", STD_ROM}, + + /* Codemasters PCB */ + {"SRJCV1-2", CM_JCART}, + {"SRJCV2-1", CM_JCART_SEPROM}, + {"SRJCV2-2", CM_JCART_SEPROM} +}; + +int md_get_pcb_id(const char *pcb) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH(pcb_list); i++) + { + if (!mame_stricmp(pcb_list[i].pcb_name, pcb)) + return pcb_list[i].pcb_id; + } + + return STD_ROM; +} diff --git a/src/mame/machine/md_pcb.h b/src/mame/machine/md_pcb.h new file mode 100644 index 00000000000..d48e615c910 --- /dev/null +++ b/src/mame/machine/md_pcb.h @@ -0,0 +1,19 @@ +#ifndef __GENESIS_PCB_H +# define __GENESIS_PCB_H + +/* PCB */ +enum + { + STD_ROM = 0, + + /* Sega PCB */ + SEGA_5878, SEGA_6584A, SEGA_5921, SEGA_6278A, SEGA_6658A, + + /* Codemasters PCB (J-Carts and SEPROM) */ + CM_JCART, CM_JCART_SEPROM + }; + +int md_get_pcb_id(const char *pcb); + +#endif + diff --git a/src/mame/machine/megadriv.c b/src/mame/machine/megadriv.c new file mode 100644 index 00000000000..38def05551b --- /dev/null +++ b/src/mame/machine/megadriv.c @@ -0,0 +1,1625 @@ +/*************************************************************************** + + genesis.c + + Machine file to handle emulation of the Sega Mega Drive & Genesis. + + i2c games mapping table: + + game name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK | + ----------------------------------|------------|------------|------------|----------------|-----------| + NBA Jam | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x00ff (24C02) | 0x03 | xx + NBA Jam TE | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | xx + NBA Jam TE (32x) | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | + NFL Quarterback Club | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | xx + NFL Quarterback Club 96 | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x07ff (24C16) | 0x07 | xx + College Slam | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | xx + Frank Thomas Big Hurt Baseball | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | xx + NHLPA Hockey 93 | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | xx + Rings of Power | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | xx + Evander Holyfield's Boxing | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx + Greatest Heavyweights of the Ring | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx + Wonder Boy V | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx + Sports Talk Baseball | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx + Megaman - the Wily Wars | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx ** + Micro Machines 2 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | + Micro Machines Military | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | + Micro Machines 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x07ff (24C16) | 0x0f | + Brian Lara Cricket 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x1fff (24C64) | 0x??* | + ----------------------------------|------------|------------|------------|----------------|-----------| + + * Notes: check these + ** original Rockman Mega World (J) set uses normal backup RAM + + 2008-09: Moved here cart code and custom mapper handlers. Hopefully, + it will make painless the future merging with HazeMD + 2008-10: Fixed SRAM, matching as much as possible HazeMD. Some game is + not detected, however. E.g. Sonic 3. Also some games seem false + positives (e.g. Wonderboy 5: according to its headers it should + have 1byte of SRAM). Better detection routines would be welcome. + 2009-06: Changed SRAM code, fixing more games, including Sonic 3. The + false positives seem only some of the games using EEPROM. Todo + list in mess/drivers/genesis.c includes EEPROM emulation. + +***************************************************************************/ + + +#include "emu.h" +#include "imageutl.h" +#include "cpu/m68000/m68000.h" + +#include "imagedev/cartslot.h" +#include "../includes/megadriv.h" +#include "md_pcb.h" + + +#define MAX_MD_CART_SIZE 0x500000 + +/* where a fresh copy of rom is stashed for reset and banking setup */ +#define VIRGIN_COPY_GEN 0xd00000 + +enum t_cart_type +{ + STANDARD = 0, + SSF2, /* Super Street Fighter 2 */ + LIONK3, /* Lion King 3 */ + SKINGKONG, /* Super King Kong 99 */ + SDK99, /* Super Donkey Kong 99 */ + REDCLIFF, /* Romance of the Three Kingdoms - Battle of Red Cliffs, already decoded from .mdx format */ + REDCL_EN, /* The encoded version... */ + RADICA, /* Radica TV games.. these probably should be a seperate driver since they are a seperate 'console' */ + KOF99, /* King of Fighters '99 */ + SOULBLAD, /* Soul Blade */ + MJLOVER, /* Mahjong Lover */ + SQUIRRELK, /* Squirrel King */ + SMOUSE, /* Smart Mouse */ + SMB, /* Super Mario Bros. */ + SMB2, /* Super Mario Bros. 2 */ + KAIJU, /* Pokemon Stadium */ + CHINFIGHT3, /* Chinese Fighters 3 */ + LIONK2, /* Lion King 2 */ + BUGSLIFE, /* A Bug's Life */ + ELFWOR, /* Elf Wor */ + ROCKMANX3, /* Rockman X3 */ + SBUBBOB, /* Super Bubble Bobble */ + KOF98, /* King of Fighters '98 */ + REALTEC, /* Whac a Critter/Mallet legend, Defend the Earth, Funnyworld/Ballonboy */ + SUP19IN1, /* Super 19 in 1 */ + SUP15IN1, /* Super 15 in 1 */ + NBA_JAM, /* NBA Jam */ + NBA_JAM_TE, /* NBA Jam TE / NFL Quarterback Club */ + NFL_QB_96, /* NFL Quarterback Club '96 */ + C_SLAM, /* College Slam / Frank Thomas Big Hurt Baseball */ + EA_NHLPA, /* NHLPA Hockey 93 / Rings of Power */ + WBOY_V, /* Wonder Boy V / Evander Holyfield's Boxing / Greatest Heavyweights of the Ring / Sports Talk Baseball / Megaman */ + CODE_MASTERS /* Micro Machines 2 / Military / 96 / Brian Lara Cricket */ +}; + + +static enum t_cart_type cart_type; + + +static UINT16 squirrel_king_extra; +static UINT16 lion2_prot1_data, lion2_prot2_data; +static UINT16 realtec_bank_addr, realtec_bank_size, realtec_old_bank_addr; +static UINT16 g_l3alt_pdat; +static UINT16 g_l3alt_pcmd; + +static int genesis_last_loaded_image_length; + +UINT16 *genesis_sram; +static int genesis_sram_start, genesis_sram_end; +static int genesis_sram_active, genesis_sram_readonly; +static int sram_handlers_installed; + +static int has_serial_eeprom; + + +/************************************* + * + * Handlers for custom mappers + * + *************************************/ + +static WRITE16_HANDLER( genesis_ssf2_bank_w ) +{ + static int lastoffset = -1,lastdata = -1; + UINT8 *ROM = space->machine->region("maincpu")->base(); + + if ((lastoffset != offset) || (lastdata != data)) + { + lastoffset = offset; lastdata = data; + switch (offset << 1) + { + case 0x00: /* write protect register */ // this is not a write protect, but seems to do nothing useful but reset bank0 after the checksum test (red screen otherwise) + if (data == 2) + { + memcpy(ROM + 0x000000, ROM + 0x400000 + (((data & 0xf) - 2) * 0x080000), 0x080000); + } + break; + case 0x02: /* 0x080000 - 0x0FFFFF */ + memcpy(ROM + 0x080000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x04: /* 0x100000 - 0x17FFFF */ + memcpy(ROM + 0x100000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x06: /* 0x180000 - 0x1FFFFF */ + memcpy(ROM + 0x180000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x08: /* 0x200000 - 0x27FFFF */ + memcpy(ROM + 0x200000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x0a: /* 0x280000 - 0x2FFFFF */ + memcpy(ROM + 0x280000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x0c: /* 0x300000 - 0x37FFFF */ + memcpy(ROM + 0x300000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + case 0x0e: /* 0x380000 - 0x3FFFFF */ + memcpy(ROM + 0x380000, ROM + 0x400000 + ((data & 0xf) * 0x080000), 0x080000); + break; + } + } +} + +#ifdef UNUSED_FUNCTION +static WRITE16_HANDLER( g_l3alt_pdat_w ) +{ + g_l3alt_pdat = data; +} + +static WRITE16_HANDLER( g_l3alt_pcmd_w ) +{ + g_l3alt_pcmd = data; +} +#endif + +static READ16_HANDLER( g_l3alt_prot_r ) +{ + int retdata = 0; + + offset &= 0x07; + + switch (offset) + { + + case 2: + + switch (g_l3alt_pcmd) + { + case 1: + retdata = g_l3alt_pdat >> 1; + break; + + case 2: + retdata = g_l3alt_pdat >> 4; + retdata |= (g_l3alt_pdat & 0x0f) << 4; + break; + + default: + /* printf("unk prot case %d\n", g_l3alt_pcmd); */ + retdata = (((g_l3alt_pdat >> 7) & 1) << 0); + retdata |= (((g_l3alt_pdat >> 6) & 1) << 1); + retdata |= (((g_l3alt_pdat >> 5) & 1) << 2); + retdata |= (((g_l3alt_pdat >> 4) & 1) << 3); + retdata |= (((g_l3alt_pdat >> 3) & 1) << 4); + retdata |= (((g_l3alt_pdat >> 2) & 1) << 5); + retdata |= (((g_l3alt_pdat >> 1) & 1) << 6); + retdata |= (((g_l3alt_pdat >> 0) & 1) << 7); + break; + } + break; + + default: + + printf("protection read, unknown offset\n"); + break; + } + +/* printf("%06x: g_l3alt_pdat_w %04x g_l3alt_pcmd_w %04x return %04x\n", activecpu_get_pc(), g_l3alt_pdat, g_l3alt_pcmd, retdata); */ + + return retdata; +} + +static WRITE16_HANDLER( g_l3alt_prot_w ) +{ + offset &= 0x7; + + switch (offset) + { + case 0x0: + g_l3alt_pdat = data; + break; + case 0x1: + g_l3alt_pcmd = data; + break; + default: + printf("protection write, unknown offst\n"); + break; + } +} + +static WRITE16_HANDLER( g_l3alt_bank_w ) +{ + offset &= 0x7; + + switch (offset) + { + case 0: + { + UINT8 *ROM = space->machine->region("maincpu")->base(); + /* printf("%06x data %04x\n",activecpu_get_pc(), data); */ + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN + (data & 0xffff) * 0x8000], 0x8000); + } + break; + + default: + printf("unk bank w\n"); + break; + + } + +} + + +static WRITE16_HANDLER( realtec_402000_w ) +{ + realtec_bank_addr = 0; + realtec_bank_size = (data >> 8) & 0x1f; +} + +static WRITE16_HANDLER( realtec_400000_w ) +{ + int bankdata = (data >> 9) & 0x7; + + UINT8 *ROM = space->machine->region("maincpu")->base(); + + realtec_old_bank_addr = realtec_bank_addr; + realtec_bank_addr = (realtec_bank_addr & 0x7) | bankdata << 3; + + memcpy(ROM, ROM + (realtec_bank_addr * 0x20000) + 0x400000, realtec_bank_size * 0x20000); + memcpy(ROM + realtec_bank_size * 0x20000, ROM + (realtec_bank_addr * 0x20000) + 0x400000, realtec_bank_size * 0x20000); +} + +static WRITE16_HANDLER( realtec_404000_w ) +{ + int bankdata = (data >> 8) & 0x3; + UINT8 *ROM = space->machine->region("maincpu")->base(); + + realtec_old_bank_addr = realtec_bank_addr; + realtec_bank_addr = (realtec_bank_addr & 0xf8) | bankdata; + + if (realtec_old_bank_addr != realtec_bank_addr) + { + memcpy(ROM, ROM + (realtec_bank_addr * 0x20000)+ 0x400000, realtec_bank_size * 0x20000); + memcpy(ROM + realtec_bank_size * 0x20000, ROM + (realtec_bank_addr * 0x20000) + 0x400000, realtec_bank_size * 0x20000); + } +} + +static WRITE16_HANDLER( g_chifi3_bank_w ) +{ + UINT8 *ROM = space->machine->region("maincpu")->base(); + + if (data == 0xf100) // *hit player + { + int x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(ROM + x, ROM + 0x410000, 0x10000); + } + } + else if (data == 0xd700) // title screen.. + { + int x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(ROM + x, ROM + 0x470000, 0x10000); + } + } + else if (data == 0xd300) // character hits floor + { + int x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(ROM + x, ROM + 0x430000, 0x10000); + } + } + else if (data == 0x0000) + { + int x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(ROM + x, ROM + 0x400000 + x, 0x10000); + } + } + else + { + logerror("%06x chifi3, bankw? %04x %04x\n", cpu_get_pc(space->cpu), offset, data); + } + +} + +static READ16_HANDLER( g_chifi3_prot_r ) +{ + UINT32 retdat; + + /* not 100% correct, there may be some relationship between the reads here + and the writes made at the start of the game.. */ + + /* + 04dc10 chifi3, prot_r? 2800 + 04cefa chifi3, prot_r? 65262 + */ + + if (cpu_get_pc(space->cpu) == 0x01782) // makes 'VS' screen appear + { + retdat = cpu_get_reg(space->cpu, M68K_D3) & 0xff; + retdat <<= 8; + return retdat; + } + else if (cpu_get_pc(space->cpu) == 0x1c24) // background gfx etc. + { + retdat = cpu_get_reg(space->cpu, M68K_D3) & 0xff; + retdat <<= 8; + return retdat; + } + else if (cpu_get_pc(space->cpu) == 0x10c4a) // unknown + { + return space->machine->rand(); + } + else if (cpu_get_pc(space->cpu) == 0x10c50) // unknown + { + return space->machine->rand(); + } + else if (cpu_get_pc(space->cpu) == 0x10c52) // relates to the game speed.. + { + retdat = cpu_get_reg(space->cpu, M68K_D4) & 0xff; + retdat <<= 8; + return retdat; + } + else if (cpu_get_pc(space->cpu) == 0x061ae) + { + retdat = cpu_get_reg(space->cpu, M68K_D3) & 0xff; + retdat <<= 8; + return retdat; + } + else if (cpu_get_pc(space->cpu) == 0x061b0) + { + retdat = cpu_get_reg(space->cpu, M68K_D3) & 0xff; + retdat <<= 8; + return retdat; + } + else + { + logerror("%06x chifi3, prot_r? %04x\n", cpu_get_pc(space->cpu), offset); + } + + return 0; +} + +static WRITE16_HANDLER( s19in1_bank ) +{ + UINT8 *ROM = space->machine->region("maincpu")->base(); + memcpy(ROM + 0x000000, ROM + 0x400000 + ((offset << 1) * 0x10000), 0x80000); +} + +// Kaiju? (Pokemon Stadium) handler from HazeMD +static WRITE16_HANDLER( g_kaiju_bank_w ) +{ + UINT8 *ROM = space->machine->region("maincpu")->base(); + memcpy(ROM + 0x000000, ROM + 0x400000 + (data & 0x7f) * 0x8000, 0x8000); +} + +// Soulblade handler from HazeMD +static READ16_HANDLER( soulb_0x400006_r ) +{ + return 0xf000; +} + +static READ16_HANDLER( soulb_0x400002_r ) +{ + return 0x9800; +} + +static READ16_HANDLER( soulb_0x400004_r ) +{ + return 0xc900; +} + +// Mahjong Lover handler from HazeMD +static READ16_HANDLER( mjlovr_prot_1_r ) +{ + return 0x9000; +} + +static READ16_HANDLER( mjlovr_prot_2_r ) +{ + return 0xd300; +} + +// Super Mario Bros handler from HazeMD +static READ16_HANDLER( smbro_prot_r ) +{ + return 0xc; +} + + +// Smart Mouse handler from HazeMD +static READ16_HANDLER( smous_prot_r ) +{ + switch (offset) + { + case 0: return 0x5500; + case 1: return 0x0f00; + case 2: return 0xaa00; + case 3: return 0xf000; + } + + return -1; +} + +// Super Bubble Bobble MD handler from HazeMD +static READ16_HANDLER( sbub_extra1_r ) +{ + return 0x5500; +} + +static READ16_HANDLER( sbub_extra2_r ) +{ + return 0x0f00; +} + +// KOF99 handler from HazeMD +static READ16_HANDLER( kof99_0xA13002_r ) +{ + // write 02 to a13002.. shift right 1? + return 0x01; +} + +static READ16_HANDLER( kof99_00A1303E_r ) +{ + // write 3e to a1303e.. shift right 1? + return 0x1f; +} + +static READ16_HANDLER( kof99_0xA13000_r ) +{ + // no write, startup check, chinese message if != 0 + return 0x0; +} + +// Radica handler from HazeMD + +static READ16_HANDLER( radica_bank_select ) +{ + int bank = offset&0x3f; + UINT8 *ROM = space->machine->region("maincpu")->base(); + memcpy(ROM, ROM + (bank * 0x10000) + 0x400000, 0x400000); + return 0; +} + +// ROTK Red Cliff handler from HazeMD + +static READ16_HANDLER( redclif_prot_r ) +{ + return -0x56 << 8; +} + +static READ16_HANDLER( redclif_prot2_r ) +{ + return 0x55 << 8; +} + +// Squirrel King handler from HazeMD, this does not give screen garbage like HazeMD compile If you reset it twice +static READ16_HANDLER( squirrel_king_extra_r ) +{ + return squirrel_king_extra; + +} +static WRITE16_HANDLER( squirrel_king_extra_w ) +{ + squirrel_king_extra = data; +} + +// Lion King 2 handler from HazeMD +static READ16_HANDLER( lion2_prot1_r ) +{ + return lion2_prot1_data; +} + +static READ16_HANDLER( lion2_prot2_r ) +{ + return lion2_prot2_data; +} + +static WRITE16_HANDLER ( lion2_prot1_w ) +{ + lion2_prot1_data = data; +} + +static WRITE16_HANDLER ( lion2_prot2_w ) +{ + lion2_prot2_data = data; +} + +// Rockman X3 handler from HazeMD +static READ16_HANDLER( rx3_extra_r ) +{ + return 0xc; +} + +// King of Fighters 98 handler from HazeMD +static READ16_HANDLER( g_kof98_aa_r ) +{ + return 0xaa00; +} + +static READ16_HANDLER( g_kof98_0a_r ) +{ + return 0x0a00; +} + +static READ16_HANDLER( g_kof98_00_r ) +{ + return 0x0000; +} + +// Super Mario Bros 2 handler from HazeMD +static READ16_HANDLER( smb2_extra_r ) +{ + return 0xa; +} + +// Bug's Life handler from HazeMD +static READ16_HANDLER( bugl_extra_r ) +{ + return 0x28; +} + +// Elf Wor handler from HazeMD (DFJustin says the title is 'Linghuan Daoshi Super Magician') +static READ16_HANDLER( elfwor_0x400000_r ) +{ + return 0x5500; +} + +static READ16_HANDLER( elfwor_0x400002_r ) +{ + return 0x0f00; +} + +static READ16_HANDLER( elfwor_0x400004_r ) +{ + return 0xc900; +} + +static READ16_HANDLER( elfwor_0x400006_r ) +{ + return 0x1800; +} + +static WRITE16_HANDLER( genesis_TMSS_bank_w ) +{ + /* this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly */ +} + + + +/************************************* + * + * Handlers for SRAM + * + *************************************/ + +static void alloc_sram(running_machine *machine) +{ + genesis_sram = auto_alloc_array(machine, UINT16, (genesis_sram_end - genesis_sram_start + 1) / sizeof(UINT16)); + device_image_interface *image = dynamic_cast(machine->device("cart")); + image->battery_load(genesis_sram, genesis_sram_end - genesis_sram_start + 1, 0xff); // Dino Dini's Soccer needs backup RAM to be 1fill + memcpy(megadriv_backupram, genesis_sram, genesis_sram_end - genesis_sram_start + 1); +} + +static READ16_HANDLER( genesis_sram_read ) +{ + UINT8 *ROM; + int rom_offset; + + if (genesis_sram_active) + { + if (genesis_sram == NULL) + alloc_sram(space->machine); + return genesis_sram[offset]; + } + else + { + ROM = space->machine->region("maincpu")->base(); + rom_offset = genesis_sram_start + (offset << 1); + + return (UINT16) ROM[rom_offset] | (ROM[rom_offset + 1] << 8); + } +} + +static WRITE16_HANDLER( genesis_sram_write ) +{ + if (genesis_sram_active) + { + if (genesis_sram == NULL) + alloc_sram(space->machine); + if (!genesis_sram_readonly) + genesis_sram[offset] = data; + } +} + +static void install_sram_rw_handlers(running_machine *machine) +{ + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), genesis_sram_start & 0x3fffff, genesis_sram_end & 0x3fffff, 0, 0, genesis_sram_read); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), genesis_sram_start & 0x3fffff, genesis_sram_end & 0x3fffff, 0, 0, genesis_sram_write); + sram_handlers_installed = 1; +} + +static WRITE16_HANDLER( genesis_sram_toggle ) +{ + + /* unsure if this is actually supposed to toggle or just switch on? + * Yet to encounter game that utilizes + */ + genesis_sram_active = (data & 1) ? 1 : 0; + genesis_sram_readonly = (data & 2) ? 1 : 0; + + if (genesis_sram_active && !sram_handlers_installed) + install_sram_rw_handlers (space->machine); +} + +/* +I2c bare minimum handlings (TODO: supports proper device interfacing and parameter change!) +*/ + +static UINT8 i2c_mem,i2c_clk; + +static READ16_HANDLER( nba_jam_eeprom_r ) +{ +// i2c_mem = (i2cmem_sda_read(space->machine->device("i2cmem")) & 1); + + return i2c_mem & 1; +} + +static WRITE16_HANDLER( nba_jam_eeprom_w ) +{ + i2c_clk = (data & 0x0002) >> 1; + i2c_mem = (data & 0x0001); + +// i2cmem_sda_write(space->machine->device("i2cmem"), i2c_clk); +// i2cmem_scl_write(space->machine->device("i2cmem"), i2c_mem); +} + +static READ16_HANDLER( nba_jam_te_eeprom_r ) +{ +// i2c_mem = (i2cmem_sda_read(space->machine->device("i2cmem")) & 1); + + return (i2c_mem & 1); +} + +static WRITE16_HANDLER( nba_jam_te_eeprom_w ) +{ + i2c_clk = ((data & 0x0100) >> 8); + i2c_mem = data & 0x0001; + +// i2cmem_sda_write(space->machine->device("i2cmem"), i2c_clk); +// i2cmem_scl_write(space->machine->device("i2cmem"), i2c_mem); +} + +static READ16_HANDLER( ea_nhlpa_eeprom_r ) +{ +// i2c_mem = (i2cmem_sda_read(space->machine->device("i2cmem")) & 1); + + return (i2c_mem & 1) << 7; +} + +static WRITE16_HANDLER( ea_nhlpa_eeprom_w ) +{ + i2c_clk = ((data & 0x0040) >> 6); + i2c_mem = ((data & 0x0080) >> 7); + +// i2cmem_sda_write(space->machine->device("i2cmem"), i2c_clk); +// i2cmem_scl_write(space->machine->device("i2cmem"), i2c_mem); +} + +/* TODO: identical as NBA Jam, used as kludge */ +static READ16_HANDLER( wboy_v_eeprom_r ) +{ +// i2c_mem = (i2cmem_sda_read(space->machine->device("i2cmem")) & 1); + + return ~i2c_mem & 1; +} + +static WRITE16_HANDLER( wboy_v_eeprom_w ) +{ + i2c_clk = (data & 0x0002) >> 1; + i2c_mem = (data & 0x0001); + +// i2cmem_sda_write(space->machine->device("i2cmem"), i2c_clk); +// i2cmem_scl_write(space->machine->device("i2cmem"), i2c_mem); +} + +static READ16_HANDLER( codemasters_eeprom_r ) +{ +// i2c_mem = (i2cmem_sda_read(space->machine->device("i2cmem")) & 1); + + return (i2c_mem & 1) << 7; +} + +static WRITE16_HANDLER( codemasters_eeprom_w ) +{ + i2c_clk = (data & 0x0200) >> 9; + i2c_mem = (data & 0x0100) >> 8; + +// i2cmem_sda_write(space->machine->device("i2cmem"), i2c_clk); +// i2cmem_scl_write(space->machine->device("i2cmem"), i2c_mem); +} + +/************************************* + * + * Machine driver reset + * + *************************************/ + + +static void setup_megadriv_custom_mappers(running_machine *machine) +{ + static int relocate = VIRGIN_COPY_GEN; + unsigned char *ROM; + UINT32 mirroraddr; + + /* SRAM data */ + sram_handlers_installed = 0; + genesis_sram_readonly = 0; + genesis_sram_active = 0; + + ROM = machine->region("maincpu")->base(); + + if (cart_type == SSF2) + { + memcpy(&ROM[0x800000], &ROM[VIRGIN_COPY_GEN + 0x400000], 0x100000); + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x400000); + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x400000); + + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa130f0, 0xa130ff, 0, 0, genesis_ssf2_bank_w); + } + + if (cart_type == LIONK3 || cart_type == SKINGKONG) + { + g_l3alt_pdat = g_l3alt_pcmd = 0; + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x200000); /* default rom */ + memcpy(&ROM[0x200000], &ROM[VIRGIN_COPY_GEN], 0x200000); /* default rom */ + + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x600000, 0x6fffff, 0, 0, g_l3alt_prot_r, g_l3alt_prot_w); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x700000, 0x7fffff, 0, 0, g_l3alt_bank_w); + } + + if (cart_type == SDK99) + { + g_l3alt_pdat = g_l3alt_pcmd = 0; + + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x300000); /* default rom */ + memcpy(&ROM[0x300000], &ROM[VIRGIN_COPY_GEN], 0x100000); /* default rom */ + + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x600000, 0x6fffff, 0, 0, g_l3alt_prot_r, g_l3alt_prot_w); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x700000, 0x7fffff, 0, 0, g_l3alt_bank_w); + } + + if (cart_type == REDCLIFF) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, redclif_prot2_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400004, 0x400005, 0, 0, redclif_prot_r); + } + + if (cart_type == REDCL_EN) + { + int x; + + for (x = VIRGIN_COPY_GEN; x < VIRGIN_COPY_GEN + 0x200005; x++) + { + ROM[x] ^= 0x40; + } + + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN + 4], 0x200000); /* default rom */ + + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, redclif_prot2_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400004, 0x400005, 0, 0, redclif_prot_r); + } + + if (cart_type == RADICA) + { + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x400000); // keep a copy for later banking.. making use of huge ROM_REGION allocated to genesis driver + memcpy(&ROM[0x800000], &ROM[VIRGIN_COPY_GEN], 0x400000); // wraparound banking (from hazemd code) + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x400000); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa1307f, 0, 0, radica_bank_select); + } + + if (cart_type == KOF99) + { + //memcpy(&ROM[0x000000],&ROM[VIRGIN_COPY_GEN],0x300000); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13001, 0, 0, kof99_0xA13000_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13002, 0xa13003, 0, 0, kof99_0xA13002_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa1303e, 0xa1303f, 0, 0, kof99_00A1303E_r); + } + + if (cart_type == SOULBLAD) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400002, 0x400003, 0, 0, soulb_0x400002_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400004, 0x400005, 0, 0, soulb_0x400004_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400006, 0x400007, 0, 0, soulb_0x400006_r); + } + + if (cart_type == MJLOVER) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, mjlovr_prot_1_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x401000, 0x401001, 0, 0, mjlovr_prot_2_r); + } + + if (cart_type == SQUIRRELK) + { + squirrel_king_extra = 0; + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400007, 0, 0, squirrel_king_extra_r); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400007, 0, 0, squirrel_king_extra_w); + } + + if (cart_type == SMOUSE) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400007, 0, 0, smous_prot_r); + } + + if (cart_type == SMB) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13001, 0, 0, smbro_prot_r); + } + + if (cart_type == SMB2) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13001, 0, 0, smb2_extra_r); + } + + if (cart_type == KAIJU) + { + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x200000); + memcpy(&ROM[0x600000], &ROM[VIRGIN_COPY_GEN], 0x200000); + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x200000); + + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x700000, 0x7fffff, 0, 0, g_kaiju_bank_w); + } + + if (cart_type == CHINFIGHT3) + { + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x200000); + memcpy(&ROM[0x600000], &ROM[VIRGIN_COPY_GEN], 0x200000); + memcpy(&ROM[0x000000], &ROM[VIRGIN_COPY_GEN], 0x200000); + + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x4fffff, 0, 0, g_chifi3_prot_r); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x600000, 0x6fffff, 0, 0, g_chifi3_bank_w); + } + + if (cart_type == LIONK2) + { + lion2_prot1_data = lion2_prot2_data = 0; + + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400002, 0x400003, 0, 0, lion2_prot1_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400006, 0x400007, 0, 0, lion2_prot2_r); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, lion2_prot1_w); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400004, 0x400005, 0, 0, lion2_prot2_w); + } + + if (cart_type == BUGSLIFE) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13001, 0, 0, bugl_extra_r); + } + + if (cart_type == ELFWOR) + { + /* It return (0x55 @ 0x400000 OR 0xc9 @ 0x400004) AND (0x0f @ 0x400002 OR 0x18 @ 0x400006). It is probably best to add handlers for all 4 addresses. */ + + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, elfwor_0x400000_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400002, 0x400003, 0, 0, elfwor_0x400002_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400004, 0x400005, 0, 0, elfwor_0x400004_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400006, 0x400007, 0, 0, elfwor_0x400006_r); + } + + if (cart_type == ROCKMANX3) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13001, 0, 0, rx3_extra_r); + } + + if (cart_type == SBUBBOB) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, sbub_extra1_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400002, 0x400003, 0, 0, sbub_extra2_r); + } + + if (cart_type == KOF98) + { + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x480000, 0x480001, 0, 0, g_kof98_aa_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x4800e0, 0x4800e1, 0, 0, g_kof98_aa_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x4824a0, 0x4824a1, 0, 0, g_kof98_aa_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x488880, 0x488881, 0, 0, g_kof98_aa_r); + + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x4a8820, 0x4a8821, 0, 0, g_kof98_0a_r); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x4f8820, 0x4f8821, 0, 0, g_kof98_00_r); + } + + if (cart_type == REALTEC) + { + /* Realtec mapper!*/ + realtec_bank_addr = realtec_bank_size = 0; + realtec_old_bank_addr = -1; + + memcpy(&ROM[0x400000], &ROM[relocate], 0x80000); + + for (mirroraddr = 0; mirroraddr < 0x400000; mirroraddr += 0x2000) + { + memcpy(ROM + mirroraddr, ROM + relocate + 0x7e000, 0x002000); /* copy last 8kb across the whole rom region */ + } + + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x400000, 0x400001, 0, 0, realtec_400000_w); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x402000, 0x402001, 0, 0, realtec_402000_w); + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x404000, 0x404001, 0, 0, realtec_404000_w); + } + + if (cart_type == SUP19IN1) + { + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x400000); // allow hard reset to menu + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13039, 0, 0, s19in1_bank); + } + + if (cart_type == SUP15IN1) + { + memcpy(&ROM[0x400000], &ROM[VIRGIN_COPY_GEN], 0x200000); // allow hard reset to menu + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa13000, 0xa13039, 0, 0, s19in1_bank); + } + + /* Disable SRAM handlers if it's a game using EEPROM to save + progresses. Currently EEPROM is not emulated. */ + if (!has_serial_eeprom) + { + /* Info from DGen: If SRAM does not overlap main ROM, set it active by + default since a few games can't manage to properly switch it on/off. */ + if (genesis_last_loaded_image_length <= genesis_sram_start) + genesis_sram_active = 1; + + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa130f0, 0xa130f1, 0, 0, genesis_sram_toggle); + + /* Sonic 1 included in Sonic Classics doesn't have SRAM and + does lots of ROM access at this range, then only install read/ + write handlers if SRAM is active to not slow down emulation. */ + if (genesis_sram_active) + install_sram_rw_handlers (machine); + } + + /* install i2c handlers */ + if(cart_type == NBA_JAM) + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x200000, 0x200001, 0, 0, nba_jam_eeprom_r,nba_jam_eeprom_w); + + if(cart_type == WBOY_V) + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x200000, 0x200001, 0, 0, wboy_v_eeprom_r,wboy_v_eeprom_w); + + if(cart_type == NBA_JAM_TE || cart_type == NFL_QB_96 || cart_type == C_SLAM) // same handling but different sizes + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x200000, 0x200001, 0, 0, nba_jam_te_eeprom_r,nba_jam_te_eeprom_w); + + if(cart_type == EA_NHLPA) + memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x200000, 0x200001, 0, 0, ea_nhlpa_eeprom_r,ea_nhlpa_eeprom_w); + + if(cart_type == CODE_MASTERS) + { + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x300000, 0x300001, 0, 0, codemasters_eeprom_w); + memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x380000, 0x380001, 0, 0, codemasters_eeprom_r); + + // TODO: J-Cart device + } + + /* install NOP handler for TMSS */ + memory_install_write16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa14000, 0xa14003, 0, 0, genesis_TMSS_bank_w); +} + + +MACHINE_RESET( md_mappers ) +{ + setup_megadriv_custom_mappers(machine); +} + + +/************************************* + * + * Cart handling + * + *************************************/ + + +/******* Memcmp for both endianness *******/ + +static int allendianmemcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *realbuf; + +#ifdef LSB_FIRST + unsigned char flippedbuf[64]; + unsigned int i; + + if ((n & 1) || (n > 63)) return -1 ; // don't want odd sized buffers or too large a compare + for (i = 0; i < n; i++) flippedbuf[i] = *((char *)s2 + (i ^ 1)); + realbuf = flippedbuf; + +#else + + realbuf = (unsigned char *)s2; + +#endif + return memcmp(s1,realbuf,n); +} + + +/******* SMD files detection *******/ + +/* code taken directly from GoodGEN by Cowering */ +static int genesis_is_funky_SMD(unsigned char *buf,unsigned int len) +{ + /* aq quiz */ + if (!strncmp("UZ(-01 ", (const char *) &buf[0xf0], 8)) + return 1; + + /* Phelios USA redump */ + /* target earth */ + /* klax (namcot) */ + if (buf[0x2080] == ' ' && buf[0x0080] == 'S' && buf[0x2081] == 'E' && buf[0x0081] == 'G') + return 1; + + /* jap baseball 94 */ + if (!strncmp("OL R-AEAL", (const char *) &buf[0xf0], 9)) + return 1; + + /* devilish Mahjong Tower */ + if (!strncmp("optrEtranet", (const char *) &buf[0xf3], 11)) + return 1; + + /* golden axe 2 beta */ + if (buf[0x0100] == 0x3c && buf[0x0101] == 0 && buf[0x0102] == 0 && buf[0x0103] == 0x3c) + return 1; + + /* omega race */ + if (!strncmp("OEARC ", (const char *) &buf[0x90], 8)) + return 1; + + /* budokan beta */ + if ((len >= 0x6708+8) && !strncmp(" NTEBDKN", (const char *) &buf[0x6708], 8)) + return 1; + + /* cdx pro 1.8 bios */ + if (!strncmp("so fCXP", (const char *) &buf[0x2c0], 7)) + return 1; + + /* ishido (hacked) */ + if (!strncmp("sio-Wyo ", (const char *) &buf[0x0090], 8)) + return 1; + + /* onslaught */ + if (!strncmp("SS CAL ", (const char *) &buf[0x0088], 8)) + return 1; + + /* tram terror pirate */ + if ((len >= 0x3648 + 8) && !strncmp("SG NEPIE", (const char *) &buf[0x3648], 8)) + return 1; + + /* breath of fire 3 chinese */ + if (buf[0x0007] == 0x1c && buf[0x0008] == 0x0a && buf[0x0009] == 0xb8 && buf[0x000a] == 0x0a) + return 1; + + /*tetris pirate */ + if ((len >= 0x1cbe + 5) && !strncmp("@TTI>", (const char *) &buf[0x1cbe], 5)) + return 1; + + return 0; +} + + + +/* code taken directly from GoodGEN by Cowering */ +static int genesis_is_SMD(unsigned char *buf,unsigned int len) +{ + if (buf[0x2080] == 'S' && buf[0x80] == 'E' && buf[0x2081] == 'G' && buf[0x81] == 'A') + return 1; + return genesis_is_funky_SMD(buf,len); +} + + +/******* Image loading *******/ + +static DEVICE_IMAGE_LOAD( genesis_cart ) +{ + unsigned char *ROM, *rawROM, *tmpROMnew, *tmpROM, *secondhalf; + int relocate, length, ptr, x, sram_detected; +#ifdef LSB_FIRST + unsigned char fliptemp; +#endif + + genesis_sram = NULL; + sram_detected = 0; + genesis_sram_start = genesis_sram_end = 0; + has_serial_eeprom = 0; + cart_type = STANDARD; + + if (image.software_entry() == NULL) + { + rawROM = image.device().machine->region("maincpu")->base(); + ROM = rawROM /*+ 512 */; + + genesis_last_loaded_image_length = -1; + + length = image.fread( rawROM + 0x2000, 0x600000); + + logerror("image length = 0x%x\n", length); + + /* is this a SMD file? */ + if (genesis_is_SMD(&rawROM[0x2200], (unsigned)length)) + { + tmpROMnew = ROM; + tmpROM = ROM + 0x2000 + 512; + + for (ptr = 0; ptr < MAX_MD_CART_SIZE / (8192); ptr += 2) + { + for (x = 0; x < 8192; x++) + { + *tmpROMnew++ = *(tmpROM + ((ptr + 1) * 8192) + x); + *tmpROMnew++ = *(tmpROM + ((ptr + 0) * 8192) + x); + } + } + +#ifdef LSB_FIRST + tmpROMnew = ROM; + for (ptr = 0; ptr < length; ptr += 2) + { + fliptemp = tmpROMnew[ptr]; + tmpROMnew[ptr] = tmpROMnew[ptr + 1]; + tmpROMnew[ptr + 1] = fliptemp; + } +#endif + genesis_last_loaded_image_length = length - 512; + memcpy(&ROM[VIRGIN_COPY_GEN], &ROM[0x000000], MAX_MD_CART_SIZE); /* store a copy of data for MACHINE_RESET processing */ + + relocate = 0; + + } + + /* is this a MD file? */ + else if ((rawROM[0x2080] == 'E') && (rawROM[0x2081] == 'A') && + (rawROM[0x2082] == 'M' || rawROM[0x2082] == 'G')) + { + tmpROMnew = (unsigned char *)osd_malloc(length); + secondhalf = &tmpROMnew[length >> 1]; + + if (!tmpROMnew) + { + logerror("Memory allocation failed reading roms!\n"); + return IMAGE_INIT_FAIL; + } + + memcpy(tmpROMnew, ROM + 0x2000, length); + for (ptr = 0; ptr < length; ptr += 2) + { + + ROM[ptr] = secondhalf[ptr >> 1]; + ROM[ptr + 1] = tmpROMnew[ptr >> 1]; + } + free(tmpROMnew); + +#ifdef LSB_FIRST + for (ptr = 0; ptr < length; ptr += 2) + { + fliptemp = ROM[ptr]; + ROM[ptr] = ROM[ptr+1]; + ROM[ptr+1] = fliptemp; + } +#endif + genesis_last_loaded_image_length = length; + memcpy(&ROM[VIRGIN_COPY_GEN], &ROM[0x000000], MAX_MD_CART_SIZE); /* store a copy of data for MACHINE_RESET processing */ + relocate = 0; + + } + + /* BIN it is, then */ + else + { + relocate = 0x2000; + genesis_last_loaded_image_length = length; + + for (ptr = 0; ptr < MAX_MD_CART_SIZE + relocate; ptr += 2) /* mangle bytes for little endian machines */ + { +#ifdef LSB_FIRST + int temp = ROM[relocate + ptr]; + + ROM[ptr] = ROM[relocate + ptr + 1]; + ROM[ptr + 1] = temp; +#else + ROM[ptr] = ROM[relocate + ptr]; + ROM[ptr + 1] = ROM[relocate + ptr + 1]; +#endif + } + + memcpy(&ROM[VIRGIN_COPY_GEN], &ROM[0x000000], MAX_MD_CART_SIZE); /* store a copy of data for MACHINE_RESET processing */ + } + + /* Default cartridge type */ + cart_type = STANDARD; + + /* Detect carts which need additional handlers */ + { + static const unsigned char smouse_sig[] = { 0x4d, 0xf9, 0x00, 0x40, 0x00, 0x02 }, + mjlover_sig[] = { 0x13, 0xf9, 0x00, 0x40, 0x00, 0x00 }, // move.b ($400000).l,($FFFF0C).l (partial) + squir_sig[] = { 0x26, 0x79, 0x00, 0xff, 0x00, 0xfa }, + bugsl_sig[] = { 0x20, 0x12, 0x13, 0xc0, 0x00, 0xff }, + sbub_sig[] = { 0x0c, 0x39, 0x00, 0x55, 0x00, 0x40 }, // cmpi.b #$55,($400000).l + lk3_sig[] = { 0x0c, 0x01, 0x00, 0x30, 0x66, 0xe4 }, + sdk_sig[] = { 0x48, 0xe7, 0xff, 0xfe, 0x52, 0x79 }, + redcliff_sig[] = { 0x10, 0x39, 0x00, 0x40, 0x00, 0x04 }, // move.b ($400004).l,d0 + redcl_en_sig[] = { 0x50, 0x79, 0x40, 0x00, 0x40, 0x44 }, // move.b ($400004).l,d0 + smb_sig[] = { 0x20, 0x4d, 0x41, 0x52, 0x49, 0x4f }, + smb2_sig[] = { 0x4e, 0xb9, 0x00, 0x0f, 0x25, 0x84 }, + kaiju_sig[] = { 0x19, 0x7c, 0x00, 0x01, 0x00, 0x00 }, + chifi3_sig[] = { 0xb6, 0x16, 0x66, 0x00, 0x00, 0x4a }, + lionk2_sig[] = { 0x26, 0x79, 0x00, 0xff, 0x00, 0xf4 }, + rx3_sig[] = { 0x66, 0x00, 0x00, 0x0e, 0x30, 0x3c }, + kof98_sig[] = { 0x9b, 0xfc, 0x00, 0x00, 0x4a, 0x00 }, + s15in1_sig[] = { 0x22, 0x3c, 0x00, 0xa1, 0x30, 0x00 }, + kof99_sig[] = { 0x20, 0x3c, 0x30, 0x00, 0x00, 0xa1 }, // move.l #$300000A1,d0 + radica_sig[] = { 0x4e, 0xd0, 0x30, 0x39, 0x00, 0xa1 }, // jmp (a0) move.w ($a130xx),d0 + soulb_sig[] = { 0x33, 0xfc, 0x00, 0x0c, 0x00, 0xff }, // move.w #$C,($FF020A).l (what happens if check fails) + s19in1_sig[] = { 0x13, 0xc0, 0x00, 0xa1, 0x30, 0x38 }, + rockman_sig[] = { 0xea, 0x80 }; + + switch (genesis_last_loaded_image_length) + { + case 0x80000: + if (!allendianmemcmp(&ROM[0x08c8], &smouse_sig[0], sizeof(smouse_sig))) + cart_type = SMOUSE; + + if (!allendianmemcmp((char *)&ROM[0x7e30e], "SEGA", 4) || + !allendianmemcmp((char *)&ROM[0x7e100], "SEGA", 4) || + !allendianmemcmp((char *)&ROM[0x7e1e6], "SEGA", 4)) + cart_type = REALTEC; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-50396", 10)) // NHLPA Hockey 93 + cart_type = EA_NHLPA; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM MK-1215", 10)) // Evander Holyfield + cart_type = WBOY_V; + + break; + + case 0xc0000: + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM G-4060 ", 8)) // Wonder Boy V + cart_type = WBOY_V; + + break; + + case 0x100000: + if (!allendianmemcmp(&ROM[0x01b24], &mjlover_sig[0], sizeof(mjlover_sig))) + cart_type = MJLOVER; + + if (!allendianmemcmp(&ROM[0x03b4], &squir_sig[0], sizeof(squir_sig))) + cart_type = SQUIRRELK; + + if (!allendianmemcmp(&ROM[0xee0d0], &bugsl_sig[0], sizeof(bugsl_sig))) + cart_type = BUGSLIFE; + + if (!allendianmemcmp((char *)&ROM[0x0172], "GAME : ELF WOR", 14)) + cart_type = ELFWOR; + + if (!allendianmemcmp(&ROM[0x123e4], &sbub_sig[0], sizeof(sbub_sig))) + cart_type = SBUBBOB; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-50176", 10)) // Rings of Power + cart_type = EA_NHLPA; + + if (!allendianmemcmp((char *)&ROM[0x0180], "MK 00001211-00", 14)) // Sports Talk Baseball + cart_type = WBOY_V; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-120096-", 12)) // Micro Machines 2 + cart_type = CODE_MASTERS; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-120146-", 12)) // Brian Lara Cricket 96 / Shane Wayne Cricket 96 + cart_type = CODE_MASTERS; + + if (!allendianmemcmp((char *)&ROM[0x0190], "OJKRPTBVFCA ", 0x10)) // Micro Machines '96 / Military TODO: better way to recognize these? + cart_type = CODE_MASTERS; + break; + + case 0x200000: + if (!allendianmemcmp(&ROM[0x18c6], &lk3_sig[0], sizeof(lk3_sig))) + cart_type = LIONK3; + + if (!allendianmemcmp(&ROM[0x220], &sdk_sig[0], sizeof(sdk_sig))) + cart_type = SKINGKONG; + + if (!allendianmemcmp(&ROM[0xce560], &redcliff_sig[0], sizeof(redcliff_sig))) + cart_type = REDCLIFF; + + if (!allendianmemcmp(&ROM[0xc8cb0], &smb_sig[0], sizeof(smb_sig))) + cart_type = SMB; + + if (!allendianmemcmp(&ROM[0xf24d6], &smb2_sig[0], sizeof(smb2_sig))) + cart_type = SMB2; + + if (!allendianmemcmp(&ROM[0x674e], &kaiju_sig[0], sizeof(kaiju_sig))) + cart_type = KAIJU; + + if (!allendianmemcmp(&ROM[0x1780], &chifi3_sig[0], sizeof(chifi3_sig))) + cart_type = CHINFIGHT3; + + if (!allendianmemcmp(&ROM[0x03c2], &lionk2_sig[0], sizeof(lionk2_sig))) + cart_type = LIONK2; + + if (!allendianmemcmp(&ROM[0xc8b90], &rx3_sig[0], sizeof(rx3_sig))) + cart_type = ROCKMANX3; + + if (!allendianmemcmp(&ROM[0x56ae2], &kof98_sig[0], sizeof(kof98_sig))) + cart_type = KOF98; + + if (!allendianmemcmp(&ROM[0x17bb2], &s15in1_sig[0], sizeof(s15in1_sig))) + cart_type = SUP15IN1; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-081326 ", 12)) // NBA Jam + cart_type = NBA_JAM; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM MK-1228", 10)) // Greatest Heavyweight of the Ring + cart_type = WBOY_V; + + if ((!allendianmemcmp((char *)&ROM[0x0180], "GM T-12046", 10)) || // Mega Man + (!allendianmemcmp((char *)&ROM[0x0180], "GM T-12053", 10) && !allendianmemcmp(&ROM[0x18e], &rockman_sig[0], sizeof(rockman_sig)))) // / Rock Man (EEPROM version) + cart_type = WBOY_V; + + break; + + case 0x200005: + if (!allendianmemcmp(&ROM[0xce564], &redcl_en_sig[0], sizeof(redcliff_sig))) + cart_type = REDCL_EN; + break; + + case 0x300000: + if (!allendianmemcmp(&ROM[0x220], &sdk_sig[0], sizeof(sdk_sig))) + cart_type = SDK99; + + if (!allendianmemcmp(&ROM[0x1fd0d2], &kof99_sig[0], sizeof(kof99_sig))) + cart_type = KOF99; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-81406", 10)) // NBA Jam TE + cart_type = NBA_JAM_TE; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-081276 ", 12)) // NFL Quarterback Club + cart_type = NBA_JAM_TE; + + break; + + case 0x400000: + if (!allendianmemcmp(&ROM[0x3c031c], &radica_sig[0], sizeof(radica_sig)) || + !allendianmemcmp(&ROM[0x3f031c], &radica_sig[0], sizeof(radica_sig))) // ssf+gng + radica vol1 + cart_type = RADICA; + + if (!allendianmemcmp(&ROM[0x028460], &soulb_sig[0], sizeof(soulb_sig))) + cart_type = SOULBLAD; + + if (!allendianmemcmp(&ROM[0x1e700], &s19in1_sig[0], sizeof(s19in1_sig))) + cart_type = SUP19IN1; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-081586-", 12)) // NFL Quarterback Club 96 + cart_type = NFL_QB_96; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-081576 ", 12)) // College Slam + cart_type = C_SLAM; + + if (!allendianmemcmp((char *)&ROM[0x0180], "GM T-81476", 10)) // Big Hurt Baseball + cart_type = C_SLAM; + + break; + + case 0x500000: + if (!allendianmemcmp((char *)&ROM[0x0120], "SUPER STREET FIGHTER2 ", 22)) + cart_type = SSF2; + break; + + default: + break; + } + } + + logerror("cart type: %d\n", cart_type); + + genesis_sram = NULL; + sram_detected = 0; + genesis_sram_start = genesis_sram_end = 0; + has_serial_eeprom = 0; + + /* check if cart has battery save */ + + /* For games using SRAM, unfortunately there are ROMs without info + about it in header. The solution adopted is do the mapping anyway, + then active SRAM later if the game will access it. */ + + if (ROM[0x1b1] == 'R' && ROM[0x1b0] == 'A') + { + /* SRAM info found in header */ + genesis_sram_start = (ROM[0x1b5] << 24 | ROM[0x1b4] << 16 | ROM[0x1b7] << 8 | ROM[0x1b6]); + genesis_sram_end = (ROM[0x1b9] << 24 | ROM[0x1b8] << 16 | ROM[0x1bb] << 8 | ROM[0x1ba]); + + if ((genesis_sram_start > genesis_sram_end) || ((genesis_sram_end - genesis_sram_start) >= 0x10000)) // we assume at most 64k of SRAM (HazeMD uses at most 64k). is this correct? + genesis_sram_end = genesis_sram_start + 0x0FFFF; + + /* for some games using serial EEPROM, difference between SRAM + end to start is 0 or 1. Currently EEPROM is not emulated. */ + if ((genesis_sram_end - genesis_sram_start) < 2) + has_serial_eeprom = 1; + else + sram_detected = 1; + } + else + { + /* set default SRAM positions, with size = 64k */ + genesis_sram_start = 0x200000; + genesis_sram_end = genesis_sram_start + 0xffff; + } + + if (genesis_sram_start & 1) + genesis_sram_start -= 1; + + if (!(genesis_sram_end & 1)) + genesis_sram_end += 1; + + /* calculate backup RAM location */ + megadriv_backupram = (UINT16*) (ROM + (genesis_sram_start & 0x3fffff)); + + /* Until serial EEPROM is emulated, clears one byte at beginning of + backup RAM, but only if the value is 0xFFFF, to not break MLBPA Sports + Talk Baseball. With this hack some games at least run (NBA Jam, Evander + Holyfield's Real Deal Boxing, Greatest Heavyweights of the Ring) */ + //if (has_serial_eeprom && megadriv_backupram[0] == 0xffff) + // megadriv_backupram[0] = 0xff00; + + if (sram_detected) + logerror("SRAM detected from header: starting location %X - SRAM Length %X\n", genesis_sram_start, genesis_sram_end - genesis_sram_start + 1); + } + else /* Handle pcb with the softlist info */ + { + int pcb_id; + const char *pcb_name; + + length = image.get_software_region_length("rom"); + ROM = image.device().machine->region("maincpu")->base(); + memcpy(ROM, image.get_software_region("rom"), length); + + genesis_last_loaded_image_length = length; + megadriv_backupram = NULL; + if ((pcb_name = image.get_feature("pcb")) == NULL) + pcb_id = STD_ROM; + else + pcb_id = md_get_pcb_id(pcb_name); + + switch (pcb_id) + { + /* Sega PCB */ + case SEGA_6584A: + fatalerror("Need Serial EEPROM emulation"); + break; + case SEGA_5921: + case SEGA_6278A: + genesis_sram_start = 0x200000; + genesis_sram_end = genesis_sram_start + 0x3fff; + sram_detected = 1; + megadriv_backupram = (UINT16*) (ROM + (genesis_sram_start & 0x3fffff)); + break; + case SEGA_6658A: + genesis_sram_start = 0x200000; + genesis_sram_end = genesis_sram_start + 0x3ff; + sram_detected = 1; + megadriv_backupram = (UINT16*) (ROM + (genesis_sram_start & 0x3fffff)); + break; + + /* Codemasters PCB (J-Carts) */ + case CM_JCART: + memory_install_read16_handler(cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x38FFFE, 0x38FFFF, 0, 0, jcart_ctrl_r); + memory_install_write16_handler(cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x38FFFE, 0x38FFFF, 0, 0, jcart_ctrl_w); + break; + case CM_JCART_SEPROM: + memory_install_read16_handler(cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x38FFFE, 0x38FFFF, 0, 0, jcart_ctrl_r); + memory_install_write16_handler(cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x38FFFE, 0x38FFFF, 0, 0, jcart_ctrl_w); + /* TODO add SEPROM part */ + break; + } + } + + return IMAGE_INIT_PASS; +} + +/******* Image unloading (with SRAM saving) *******/ + +static DEVICE_IMAGE_UNLOAD( genesis_cart ) +{ + /* Write out the battery file if necessary */ + if (genesis_sram != NULL) + { + image.battery_save(genesis_sram, genesis_sram_end - genesis_sram_start + 1); + free(genesis_sram); + } +} + + +/******* 32X image loading *******/ + +// FIXME: non-softlist loading should keep using ROM_CART_LOAD in the ROM definitions, +// once we better integrate softlist with the old loading procedures +static DEVICE_IMAGE_LOAD( _32x_cart ) +{ + UINT32 length; + UINT8 *temp_copy; + UINT16 *ROM16; + UINT32 *ROM32; + int i; + + if (image.software_entry() == NULL) + { + length = image.length(); + temp_copy = auto_alloc_array(image.device().machine, UINT8, length); + image.fread( temp_copy, length); + } + else + { + length = image.get_software_region_length("rom"); + temp_copy = auto_alloc_array(image.device().machine, UINT8, length); + memcpy(temp_copy, image.get_software_region("rom"), length); + } + + /* Copy the cart image in the locations the driver expects */ + // Notice that, by using pick_integer, we are sure the code works on both LE and BE machines + ROM16 = (UINT16 *) image.device().machine->region("gamecart")->base(); + for (i = 0; i < length; i += 2) + ROM16[i / 2] = pick_integer_be(temp_copy, i, 2); + + ROM32 = (UINT32 *) image.device().machine->region("gamecart_sh2")->base(); + for (i = 0; i < length; i += 4) + ROM32[i / 4] = pick_integer_be(temp_copy, i, 4); + + ROM16 = (UINT16 *) image.device().machine->region("maincpu")->base(); + for (i = 0x00; i < length; i += 2) + ROM16[i / 2] = pick_integer_be(temp_copy, i, 2); + + auto_free(image.device().machine, temp_copy); + + cart_type = NBA_JAM_TE; + + return IMAGE_INIT_PASS; +} + +/******* Cart getinfo *******/ + +MACHINE_CONFIG_FRAGMENT( genesis_cartslot ) + MCFG_CARTSLOT_ADD("cart") + MCFG_CARTSLOT_EXTENSION_LIST("smd,bin,md,gen") + MCFG_CARTSLOT_MANDATORY + MCFG_CARTSLOT_INTERFACE("megadriv_cart") + MCFG_CARTSLOT_LOAD(genesis_cart) + MCFG_CARTSLOT_UNLOAD(genesis_cart) + MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv") +MACHINE_CONFIG_END + +MACHINE_CONFIG_FRAGMENT( _32x_cartslot ) + MCFG_CARTSLOT_ADD("cart") + MCFG_CARTSLOT_EXTENSION_LIST("32x,bin") + MCFG_CARTSLOT_MANDATORY + MCFG_CARTSLOT_INTERFACE("_32x_cart") + MCFG_CARTSLOT_LOAD(_32x_cart) + MCFG_SOFTWARE_LIST_ADD("cart_list","32x") +MACHINE_CONFIG_END + +MACHINE_CONFIG_FRAGMENT( pico_cartslot ) + MCFG_CARTSLOT_ADD("cart") + MCFG_CARTSLOT_EXTENSION_LIST("bin") + MCFG_CARTSLOT_MANDATORY + MCFG_CARTSLOT_INTERFACE("pico_cart") + MCFG_CARTSLOT_LOAD(genesis_cart) + MCFG_CARTSLOT_UNLOAD(genesis_cart) + MCFG_SOFTWARE_LIST_ADD("cart_list","pico") +MACHINE_CONFIG_END diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 4c3ab487f2e..03015618332 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -1136,6 +1136,8 @@ $(MAMEOBJ)/sega.a: \ $(DRIVERS)/kopunch.o $(VIDEO)/kopunch.o \ $(DRIVERS)/megadriv.o \ $(DRIVERS)/megadrvb.o \ + $(MACHINE)/megadriv.o \ + $(MACHINE)/md_pcb.o \ $(DRIVERS)/megaplay.o \ $(DRIVERS)/megatech.o \ $(DRIVERS)/model1.o $(MACHINE)/model1.o $(VIDEO)/model1.o \