(MESS) megadriv.c: many updates to cart handling [Fabio Priuli]

- updated carts to be slot devices
  - simplified loading and bankswitch mechanism
  - added support for real Sonic & Knuckles lock-on emulation (you can combine it freely 
    with other carts, through the -cart2 slot which gets added automatically)
  - remove need for "pcb_type" feature from xml softlist, since the new "slot" feature is enough
  - moved SVP emulation to src/mess/ in view of conversion to a slot device as well
This commit is contained in:
Fabio Priuli 2013-02-03 13:13:52 +00:00
parent 7c37d1945e
commit 6d7b97aca4
25 changed files with 4689 additions and 2592 deletions

16
.gitattributes vendored
View File

@ -4852,7 +4852,6 @@ src/mame/machine/mc8123.c svneol=native#text/plain
src/mame/machine/mc8123.h 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/mcr.c svneol=native#text/plain
src/mame/machine/mcr68.c svneol=native#text/plain src/mame/machine/mcr68.c svneol=native#text/plain
src/mame/machine/md_cart.c svneol=native#text/plain
src/mame/machine/mega32x.c svneol=native#text/plain src/mame/machine/mega32x.c svneol=native#text/plain
src/mame/machine/mega32x.h svneol=native#text/plain src/mame/machine/mega32x.h svneol=native#text/plain
src/mame/machine/megacd.c svneol=native#text/plain src/mame/machine/megacd.c svneol=native#text/plain
@ -4860,7 +4859,6 @@ src/mame/machine/megacd.h svneol=native#text/plain
src/mame/machine/megacdcd.c svneol=native#text/plain src/mame/machine/megacdcd.c svneol=native#text/plain
src/mame/machine/megacdcd.h svneol=native#text/plain src/mame/machine/megacdcd.h svneol=native#text/plain
src/mame/machine/megadriv.c svneol=native#text/plain src/mame/machine/megadriv.c svneol=native#text/plain
src/mame/machine/megasvp.c svneol=native#text/plain
src/mame/machine/megavdp.c svneol=native#text/plain src/mame/machine/megavdp.c svneol=native#text/plain
src/mame/machine/megavdp.h svneol=native#text/plain src/mame/machine/megavdp.h svneol=native#text/plain
src/mame/machine/meters.c svneol=native#text/plain src/mame/machine/meters.c svneol=native#text/plain
@ -6453,6 +6451,7 @@ src/mess/includes/mboard.h svneol=native#text/plain
src/mess/includes/mc1000.h svneol=native#text/plain src/mess/includes/mc1000.h svneol=native#text/plain
src/mess/includes/mc68328.h svneol=native#text/plain src/mess/includes/mc68328.h svneol=native#text/plain
src/mess/includes/mc80.h svneol=native#text/plain src/mess/includes/mc80.h svneol=native#text/plain
src/mess/includes/md.h svneol=native#text/plain
src/mess/includes/micronic.h svneol=native#text/plain src/mess/includes/micronic.h svneol=native#text/plain
src/mess/includes/microtan.h svneol=native#text/plain src/mess/includes/microtan.h svneol=native#text/plain
src/mess/includes/mikro80.h svneol=native#text/plain src/mess/includes/mikro80.h svneol=native#text/plain
@ -7239,6 +7238,19 @@ src/mess/machine/mc6846.h svneol=native#text/plain
src/mess/machine/mc6854.c svneol=native#text/plain src/mess/machine/mc6854.c svneol=native#text/plain
src/mess/machine/mc6854.h svneol=native#text/plain src/mess/machine/mc6854.h svneol=native#text/plain
src/mess/machine/mc80.c svneol=native#text/plain src/mess/machine/mc80.c svneol=native#text/plain
src/mess/machine/md_eeprom.c svneol=native#text/plain
src/mess/machine/md_eeprom.h svneol=native#text/plain
src/mess/machine/md_jcart.c svneol=native#text/plain
src/mess/machine/md_jcart.h svneol=native#text/plain
src/mess/machine/md_rom.c svneol=native#text/plain
src/mess/machine/md_rom.h svneol=native#text/plain
src/mess/machine/md_sk.c svneol=native#text/plain
src/mess/machine/md_sk.h svneol=native#text/plain
src/mess/machine/md_slot.c svneol=native#text/plain
src/mess/machine/md_slot.h svneol=native#text/plain
src/mess/machine/md_stm95.c svneol=native#text/plain
src/mess/machine/md_stm95.h svneol=native#text/plain
src/mess/machine/megasvp.c svneol=native#text/plain
src/mess/machine/mface2.c svneol=native#text/plain src/mess/machine/mface2.c svneol=native#text/plain
src/mess/machine/mface2.h svneol=native#text/plain src/mess/machine/mface2.h svneol=native#text/plain
src/mess/machine/micropolis.c svneol=native#text/plain src/mess/machine/micropolis.c svneol=native#text/plain

File diff suppressed because it is too large Load Diff

View File

@ -115,7 +115,7 @@ ROM_END
#endif #endif
DRIVER_INIT_MEMBER(md_cons_state,hshavoc) DRIVER_INIT_MEMBER(md_havoc_state,hshavoc)
{ {
int x; int x;
UINT16 *src = (UINT16 *)machine().root_device().memregion("maincpu")->base(); UINT16 *src = (UINT16 *)machine().root_device().memregion("maincpu")->base();
@ -227,5 +227,5 @@ DRIVER_INIT_MEMBER(md_cons_state,hshavoc)
GAME( 1993, hshavoc, 0, md_bootleg, hshavoc, md_cons_state, hshavoc, ROT0, "Data East", "High Seas Havoc",GAME_NOT_WORKING ) GAME( 1993, hshavoc, 0, md_bootleg, hshavoc, md_havoc_state, hshavoc, ROT0, "Data East", "High Seas Havoc",GAME_NOT_WORKING )
//GAME( 1993, hshavoc2, hshavoc, md_bootleg, hshavoc, md_cons_state, genesis, ROT0, "Data East", "High Seas Havoc (Genesis ROM)",GAME_NOT_WORKING ) //GAME( 1993, hshavoc2, hshavoc, md_bootleg, hshavoc, md_havoc_state, genesis, ROT0, "Data East", "High Seas Havoc (Genesis ROM)",GAME_NOT_WORKING )

View File

@ -763,7 +763,7 @@ DRIVER_INIT_MEMBER(md_boot_state,srmdb)
DRIVER_INIT_CALL(megadriv); DRIVER_INIT_CALL(megadriv);
} }
DRIVER_INIT_MEMBER(md_cons_state,topshoot) DRIVER_INIT_MEMBER(md_boot_state,topshoot)
{ {
machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x200050, 0x200051, FUNC(topshoot_200051_r) ); machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x200050, 0x200051, FUNC(topshoot_200051_r) );
machine().device("maincpu")->memory().space(AS_PROGRAM).install_read_port(0x200042, 0x200043, "IN0"); machine().device("maincpu")->memory().space(AS_PROGRAM).install_read_port(0x200042, 0x200043, "IN0");
@ -785,4 +785,4 @@ GAME( 1993, aladmdb, 0, megadrvb, aladmdb, md_boot_state, aladmdb, ROT0, "b
GAME( 1996, mk3mdb, 0, megadrvb, mk3mdb, md_boot_state, mk3mdb, ROT0, "bootleg / Midway", "Mortal Kombat 3 (bootleg of Megadrive version)", 0) GAME( 1996, mk3mdb, 0, megadrvb, mk3mdb, md_boot_state, mk3mdb, ROT0, "bootleg / Midway", "Mortal Kombat 3 (bootleg of Megadrive version)", 0)
GAME( 1994, ssf2mdb, 0, megadrvb, ssf2mdb, md_boot_state, ssf2mdb, ROT0, "bootleg / Capcom", "Super Street Fighter II - The New Challengers (bootleg of Japanese MegaDrive version)", 0) GAME( 1994, ssf2mdb, 0, megadrvb, ssf2mdb, md_boot_state, ssf2mdb, ROT0, "bootleg / Capcom", "Super Street Fighter II - The New Challengers (bootleg of Japanese MegaDrive version)", 0)
GAME( 1993, srmdb, 0, megadrvb, srmdb, md_boot_state, srmdb, ROT0, "bootleg / Konami", "Sunset Riders (bootleg of Megadrive version)", 0) GAME( 1993, srmdb, 0, megadrvb, srmdb, md_boot_state, srmdb, ROT0, "bootleg / Konami", "Sunset Riders (bootleg of Megadrive version)", 0)
GAME( 1995, topshoot, 0, md_bootleg, topshoot, md_cons_state, topshoot, ROT0, "Sun Mixing", "Top Shooter", 0) GAME( 1995, topshoot, 0, md_bootleg, topshoot, md_boot_state, topshoot, ROT0, "Sun Mixing", "Top Shooter", 0)

View File

@ -599,17 +599,17 @@ static DEVICE_IMAGE_LOAD( megatech_cart )
{ {
if (!mame_stricmp("genesis", pcb_name)) if (!mame_stricmp("genesis", pcb_name))
{ {
printf("%s is genesis\n", mt_cart->tag); mame_printf_debug("%s is genesis\n", mt_cart->tag);
state->m_cart_is_genesis[this_cart->slot] = 1; state->m_cart_is_genesis[this_cart->slot] = 1;
} }
else if (!mame_stricmp("sms", pcb_name)) else if (!mame_stricmp("sms", pcb_name))
{ {
printf("%s is sms\n", mt_cart->tag); mame_printf_debug("%s is sms\n", mt_cart->tag);
state->m_cart_is_genesis[this_cart->slot] = 0; state->m_cart_is_genesis[this_cart->slot] = 0;
} }
else else
{ {
printf("%s is invalid\n", mt_cart->tag); mame_printf_debug("%s is invalid\n", mt_cart->tag);
} }
} }

View File

@ -23,13 +23,7 @@
#define MASTER_CLOCK_PAL 53203424 #define MASTER_CLOCK_PAL 53203424
#define SEGACD_CLOCK 12500000 #define SEGACD_CLOCK 12500000
#define MD_CPU_REGION_SIZE 0x800000
#define MAX_MD_CART_SIZE 0x800000
/* where a fresh copy of rom is stashed for reset and banking setup */
#define VIRGIN_COPY_GEN 0xd00000
#define MD_CPU_REGION_SIZE (MAX_MD_CART_SIZE + VIRGIN_COPY_GEN)
extern int sega_cd_connected; extern int sega_cd_connected;
@ -41,17 +35,12 @@ INPUT_PORTS_EXTERN( megadriv );
INPUT_PORTS_EXTERN( megadri6 ); INPUT_PORTS_EXTERN( megadri6 );
INPUT_PORTS_EXTERN( ssf2mdb ); INPUT_PORTS_EXTERN( ssf2mdb );
INPUT_PORTS_EXTERN( mk3mdb ); INPUT_PORTS_EXTERN( mk3mdb );
INPUT_PORTS_EXTERN( megdsvp );
MACHINE_CONFIG_EXTERN( megadriv_timers ); MACHINE_CONFIG_EXTERN( megadriv_timers );
MACHINE_CONFIG_EXTERN( md_ntsc ); MACHINE_CONFIG_EXTERN( md_ntsc );
MACHINE_CONFIG_EXTERN( md_pal ); MACHINE_CONFIG_EXTERN( md_pal );
MACHINE_CONFIG_EXTERN( md_svp ); MACHINE_CONFIG_EXTERN( md_svp );
MACHINE_CONFIG_EXTERN( megdsvppal );
MACHINE_CONFIG_EXTERN( megadriv );
MACHINE_CONFIG_EXTERN( megadpal );
MACHINE_CONFIG_EXTERN( megdsvp );
MACHINE_CONFIG_EXTERN( genesis_32x ); MACHINE_CONFIG_EXTERN( genesis_32x );
MACHINE_CONFIG_EXTERN( genesis_32x_pal ); MACHINE_CONFIG_EXTERN( genesis_32x_pal );
MACHINE_CONFIG_EXTERN( genesis_scd ); MACHINE_CONFIG_EXTERN( genesis_scd );
@ -61,8 +50,7 @@ MACHINE_CONFIG_EXTERN( genesis_scd_mcdj );
MACHINE_CONFIG_EXTERN( genesis_32x_scd ); MACHINE_CONFIG_EXTERN( genesis_32x_scd );
MACHINE_CONFIG_EXTERN( md_bootleg ); // for topshoot.c & hshavoc.c MACHINE_CONFIG_EXTERN( md_bootleg ); // for topshoot.c & hshavoc.c
extern UINT16* megadriv_backupram; extern cpu_device *_svp_cpu;
extern int megadriv_backupram_length;
extern UINT8 megatech_bios_port_cc_dc_r(running_machine &machine, int offset, int ctrl); extern UINT8 megatech_bios_port_cc_dc_r(running_machine &machine, int offset, int ctrl);
extern void megadriv_stop_scanline_timer(running_machine &machine); extern void megadriv_stop_scanline_timer(running_machine &machine);
@ -384,52 +372,16 @@ struct megadriv_cart
int ssf2_lastoff, ssf2_lastdata; int ssf2_lastoff, ssf2_lastdata;
}; };
class md_cons_state : public md_base_state class md_havoc_state : public md_base_state
{ {
public: public:
md_cons_state(const machine_config &mconfig, device_type type, const char *tag) md_havoc_state(const machine_config &mconfig, device_type type, const char *tag)
: md_base_state(mconfig, type, tag) { } : md_base_state(mconfig, type, tag) { }
emu_timer *m_mess_io_timeout[3];
int m_mess_io_stage[3];
UINT8 m_jcart_io_data[2];
megadriv_cart m_md_cart;
DECLARE_DRIVER_INIT(hshavoc); DECLARE_DRIVER_INIT(hshavoc);
DECLARE_DRIVER_INIT(topshoot);
DECLARE_DRIVER_INIT(genesis);
DECLARE_DRIVER_INIT(mess_md_common);
DECLARE_DRIVER_INIT(md_eur);
DECLARE_DRIVER_INIT(md_jpn);
}; };
class mdsvp_state : public md_cons_state
{
public:
mdsvp_state(const machine_config &mconfig, device_type type, const char *tag)
: md_cons_state(mconfig, type, tag) { }
UINT8 *m_iram; // IRAM (0-0x7ff)
UINT8 *m_dram; // [0x20000];
UINT32 m_pmac_read[6]; // read modes/addrs for PM0-PM5
UINT32 m_pmac_write[6]; // write ...
PAIR m_pmc;
UINT32 m_emu_status;
UINT16 m_XST; // external status, mapped at a15000 and a15002 on 68k side.
UINT16 m_XST2; // status of XST (bit1 set when 68k writes to XST)
};
ADDRESS_MAP_EXTERN( svp_ssp_map, driver_device );
ADDRESS_MAP_EXTERN( svp_ext_map, driver_device );
extern void svp_init(running_machine &machine);
extern cpu_device *_svp_cpu;
UINT8 megadrive_io_read_data_port_3button(running_machine &machine, int portnum); UINT8 megadrive_io_read_data_port_3button(running_machine &machine, int portnum);
class _32x_state : public md_base_state class _32x_state : public md_base_state
@ -459,13 +411,8 @@ public:
{ } { }
}; };
/*----------- defined in machine/md_cart.c -----------*/
MACHINE_CONFIG_EXTERN( genesis_cartslot );
MACHINE_CONFIG_EXTERN( _32x_cartslot ); MACHINE_CONFIG_EXTERN( _32x_cartslot );
MACHINE_CONFIG_EXTERN( pico_cartslot );
MACHINE_START( md_sram );
/*----------- defined in drivers/megadriv.c -----------*/ /*----------- defined in drivers/megadriv.c -----------*/

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,12 @@ Known Non-Issues (confirmed on Real Genesis)
#include "sound/2612intf.h" #include "sound/2612intf.h"
#include "sound/dac.h" #include "sound/dac.h"
#include "sound/sn76496.h" #include "sound/sn76496.h"
#include "imagedev/chd_cd.h" #include "imagedev/chd_cd.h"
#include "imagedev/cartslot.h"
#include "formats/imageutl.h"
#include "includes/megadriv.h" #include "includes/megadriv.h"
#include "machine/nvram.h" #include "machine/nvram.h"
#include "cpu/ssp1601/ssp1601.h" #include "cpu/ssp1601/ssp1601.h"
@ -40,12 +43,14 @@ Known Non-Issues (confirmed on Real Genesis)
#include "machine/megavdp.h" #include "machine/megavdp.h"
MACHINE_CONFIG_EXTERN( megadriv );
static cpu_device *_genesis_snd_z80_cpu; static cpu_device *_genesis_snd_z80_cpu;
int genesis_other_hacks = 0; // misc hacks int genesis_other_hacks = 0; // misc hacks
timer_device* megadriv_scanline_timer; timer_device* megadriv_scanline_timer;
cpu_device *_svp_cpu;
struct genesis_z80_vars struct genesis_z80_vars
{ {
@ -318,7 +323,7 @@ UINT8 megadrive_io_read_data_port_3button(running_machine &machine, int portnum)
{ {
UINT8 retdata, helper = (megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs UINT8 retdata, helper = (megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs
static const char *const pad3names[] = { "PAD1", "PAD2", "IN0", "UNK" }; static const char *const pad3names[] = { "PAD1", "PAD2", "IN0", "UNK" };
if (megadrive_io_data_regs[portnum] & 0x40) if (megadrive_io_data_regs[portnum] & 0x40)
{ {
/* here we read B, C & the directional buttons */ /* here we read B, C & the directional buttons */
@ -885,41 +890,6 @@ MACHINE_CONFIG_END
INPUT_PORTS_START( megdsvp )
PORT_INCLUDE( megadriv )
PORT_START("MEMORY_TEST") /* special memtest mode */
/* Region setting for Console */
PORT_DIPNAME( 0x01, 0x00, DEF_STR( Test ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
MACHINE_CONFIG_FRAGMENT( md_svp )
MCFG_CPU_ADD("svp", SSP1601, MASTER_CLOCK_NTSC / 7 * 3) /* ~23 MHz (guessed) */
MCFG_CPU_PROGRAM_MAP(svp_ssp_map)
MCFG_CPU_IO_MAP(svp_ext_map)
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED( megdsvp, megadriv )
MCFG_CPU_ADD("svp", SSP1601, MASTER_CLOCK_NTSC / 7 * 3) /* ~23 MHz (guessed) */
MCFG_CPU_PROGRAM_MAP(svp_ssp_map)
MCFG_CPU_IO_MAP(svp_ext_map)
/* IRQs are not used by this CPU */
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED( megdsvppal, megadpal )
MCFG_CPU_ADD("svp", SSP1601, MASTER_CLOCK_PAL / 7 * 3) /* ~23 MHz (guessed) */
MCFG_CPU_PROGRAM_MAP(svp_ssp_map)
MCFG_CPU_IO_MAP(svp_ext_map)
/* IRQs are not used by this CPU */
MACHINE_CONFIG_END
SCREEN_UPDATE_RGB32(megadriv) SCREEN_UPDATE_RGB32(megadriv)
{ {
@ -1030,8 +1000,8 @@ void megadriv_stop_scanline_timer(running_machine &machine)
UINT16* megadriv_backupram; static UINT16* megadriv_backupram;
int megadriv_backupram_length; static int megadriv_backupram_length;
static NVRAM_HANDLER( megadriv ) static NVRAM_HANDLER( megadriv )
{ {
@ -1190,7 +1160,7 @@ MACHINE_CONFIG_FRAGMENT( md_ntsc )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker",0.25) /* 3.58 MHz */ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker",0.25) /* 3.58 MHz */
MACHINE_CONFIG_END MACHINE_CONFIG_END
MACHINE_CONFIG_START( megadriv, md_cons_state ) MACHINE_CONFIG_START( megadriv, md_base_state )
MCFG_FRAGMENT_ADD(md_ntsc) MCFG_FRAGMENT_ADD(md_ntsc)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -1245,7 +1215,7 @@ MACHINE_CONFIG_FRAGMENT( md_pal )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker",0.25) /* 3.58 MHz */ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker",0.25) /* 3.58 MHz */
MACHINE_CONFIG_END MACHINE_CONFIG_END
MACHINE_CONFIG_START( megadpal, md_cons_state ) MACHINE_CONFIG_START( megadpal, md_base_state )
MCFG_FRAGMENT_ADD(md_pal) MCFG_FRAGMENT_ADD(md_pal)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -1295,6 +1265,64 @@ MACHINE_CONFIG_DERIVED( genesis_32x_pal, megadpal )
MACHINE_CONFIG_END MACHINE_CONFIG_END
/******* 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().root_device().memregion("gamecart")->base();
for (i = 0; i < length; i += 2)
ROM16[i / 2] = pick_integer_be(temp_copy, i, 2);
ROM32 = (UINT32 *) image.device().machine().root_device().memregion("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().root_device().memregion("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);
return IMAGE_INIT_PASS;
}
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
struct cdrom_interface scd_cdrom = struct cdrom_interface scd_cdrom =
{ {
"scd_cdrom", "scd_cdrom",
@ -1362,7 +1390,7 @@ void md_base_state::megadriv_init_common()
_svp_cpu = machine().device<cpu_device>("svp"); _svp_cpu = machine().device<cpu_device>("svp");
if (_svp_cpu != NULL) if (_svp_cpu != NULL)
{ {
printf("SVP (cpu) found '%s'\n", _svp_cpu->tag() ); printf("SVP (cpu) found '%s'\n", _svp_cpu->tag());
} }
machine().device("maincpu")->execute().set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(md_base_state::genesis_int_callback),this)); machine().device("maincpu")->execute().set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(md_base_state::genesis_int_callback),this));
@ -1405,14 +1433,6 @@ void md_base_state::megadriv_init_common()
} }
mame_printf_debug("\n"); mame_printf_debug("\n");
} }
/* if we have an SVP cpu then do some extra initilization for it */
if (_svp_cpu != NULL)
{
svp_init(machine());
}
} }
DRIVER_INIT_MEMBER(md_base_state,megadriv_c2) DRIVER_INIT_MEMBER(md_base_state,megadriv_c2)

View File

@ -1257,9 +1257,7 @@ $(MAMEOBJ)/sega.a: \
$(MACHINE)/megacd.o \ $(MACHINE)/megacd.o \
$(MACHINE)/megacdcd.o \ $(MACHINE)/megacdcd.o \
$(MACHINE)/mega32x.o \ $(MACHINE)/mega32x.o \
$(MACHINE)/megasvp.o \
$(MACHINE)/megavdp.o \ $(MACHINE)/megavdp.o \
$(MACHINE)/md_cart.o \
$(DRIVERS)/megadrvb.o \ $(DRIVERS)/megadrvb.o \
$(DRIVERS)/megaplay.o \ $(DRIVERS)/megaplay.o \
$(DRIVERS)/megatech.o \ $(DRIVERS)/megatech.o \

View File

@ -1,15 +1,14 @@
#include "emu.h" #include "emu.h"
#include "includes/megadriv.h" #include "includes/md.h"
#include "machine/md_slot.h"
#include "machine/md_rom.h"
//#include "machine/md_svp.h"
#include "machine/md_sk.h"
#include "machine/md_eeprom.h"
#include "machine/md_jcart.h"
#include "machine/md_stm95.h"
class pico_state : public md_cons_state
{
public:
pico_state(const machine_config &mconfig, device_type type, const char *tag)
: md_cons_state(mconfig, type, tag) { }
UINT8 m_page_register;
};
/************************************* /*************************************
* *
@ -24,37 +23,6 @@ static TIMER_CALLBACK( mess_io_timeout_timer_callback )
state->m_mess_io_stage[(int)(FPTR)ptr] = -1; state->m_mess_io_stage[(int)(FPTR)ptr] = -1;
} }
/* J-Cart controller port */
WRITE16_HANDLER( jcart_ctrl_w )
{
md_cons_state *state = space.machine().driver_data<md_cons_state>();
state->m_jcart_io_data[0] = (data & 1) << 6;
state->m_jcart_io_data[1] = (data & 1) << 6;
}
READ16_HANDLER( jcart_ctrl_r )
{
md_cons_state *state = space.machine().driver_data<md_cons_state>();
UINT16 retdata = 0;
UINT8 joy[2];
if (state->m_jcart_io_data[0] & 0x40)
{
joy[0] = state->ioport("JCART3_3B")->read_safe(0);
joy[1] = state->ioport("JCART4_3B")->read_safe(0);
retdata = (state->m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
else
{
joy[0] = ((state->ioport("JCART3_3B")->read_safe(0) & 0xc0) >> 2) |
(state->ioport("JCART3_3B")->read_safe(0) & 0x03);
joy[1] = ((state->ioport("JCART4_3B")->read_safe(0) & 0xc0) >> 2) |
(state->ioport("JCART4_3B")->read_safe(0) & 0x03);
retdata = (state->m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
return retdata;
}
static void mess_init_6buttons_pad(running_machine &machine) static void mess_init_6buttons_pad(running_machine &machine)
{ {
md_cons_state *state = machine.driver_data<md_cons_state>(); md_cons_state *state = machine.driver_data<md_cons_state>();
@ -147,7 +115,12 @@ static UINT8 mess_md_io_read_data_port(running_machine &machine, int portnum)
/* Otherwise it's a 3 buttons Joypad */ /* Otherwise it's a 3 buttons Joypad */
else else
{ {
if (megadrive_io_data_regs[portnum] & 0x40) // handle test input for SVP test
if (portnum == 0 && machine.root_device().ioport("MEMORY_TEST")->read_safe(0x00))
{
retdata = (megadrive_io_data_regs[0] & 0xc0);
}
else if (megadrive_io_data_regs[portnum] & 0x40)
{ {
/* here we read B, C & the directional buttons */ /* here we read B, C & the directional buttons */
retdata = (megadrive_io_data_regs[portnum] & helper_3b) | retdata = (megadrive_io_data_regs[portnum] & helper_3b) |
@ -226,10 +199,6 @@ static INPUT_PORTS_START( md )
PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" )
PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" )
PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" )
PORT_CONFNAME( 0xf00, 0x00, "Player 3 Controller (J-Cart)" )
PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" )
PORT_CONFNAME( 0xf000, 0x00, "Player 4 Controller (J-Cart)" )
PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" )
PORT_START("PAD1_3B") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ 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_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00)
@ -251,26 +220,6 @@ static INPUT_PORTS_START( md )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00)
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_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B") PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 C") PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A") PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0xf00, EQUALS, 0x00)
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_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B") PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 C") PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A") PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x00)
PORT_START("PAD1_6B") /* Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ 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_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
@ -317,8 +266,20 @@ INPUT_PORTS_END
static MACHINE_START( ms_megadriv ) static MACHINE_START( ms_megadriv )
{ {
md_cons_state *state = machine.driver_data<md_cons_state>();
mess_init_6buttons_pad(machine); mess_init_6buttons_pad(machine);
MACHINE_START_CALL( md_sram );
// small hack, until SVP is converted to be a slot device
if (machine.device<cpu_device>("svp") != NULL)
svp_init(machine);
else
{
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7fffff, read16_delegate(FUNC(device_md_cart_interface::read),state->m_slotcart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write),state->m_slotcart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16_delegate(FUNC(device_md_cart_interface::read_a13),state->m_slotcart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write_a13),state->m_slotcart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16_delegate(FUNC(device_md_cart_interface::read_a15),state->m_slotcart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write_a15),state->m_slotcart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16_delegate(FUNC(device_md_cart_interface::write_tmss_bank),state->m_slotcart->m_cart));
}
} }
static MACHINE_RESET( ms_megadriv ) static MACHINE_RESET( ms_megadriv )
@ -326,6 +287,61 @@ static MACHINE_RESET( ms_megadriv )
MACHINE_RESET_CALL( megadriv ); MACHINE_RESET_CALL( megadriv );
} }
static SLOT_INTERFACE_START(md_cart)
SLOT_INTERFACE_INTERNAL("rom", MD_STD_ROM)
SLOT_INTERFACE_INTERNAL("rom_svp", MD_STD_ROM)
// SLOT_INTERFACE_INTERNAL("rom_svp", MD_ROM_SVP) // not ready yet...
SLOT_INTERFACE_INTERNAL("rom_sk", MD_ROM_SK)
// NVRAM handling
SLOT_INTERFACE_INTERNAL("rom_sram", MD_ROM_SRAM)
SLOT_INTERFACE_INTERNAL("rom_sramsafe", MD_ROM_SRAM)
SLOT_INTERFACE_INTERNAL("rom_fram", MD_ROM_FRAM)
SLOT_INTERFACE_INTERNAL("rom_beggar", MD_ROM_BEGGAR)
// EEPROM handling (not supported fully yet)
SLOT_INTERFACE_INTERNAL("rom_eeprom", MD_STD_EEPROM)
SLOT_INTERFACE_INTERNAL("rom_nbajam", MD_EEPROM_NBAJAM)
SLOT_INTERFACE_INTERNAL("rom_nbajamte", MD_EEPROM_NBAJAMTE)
SLOT_INTERFACE_INTERNAL("rom_nflqb", MD_EEPROM_NFLQB)
SLOT_INTERFACE_INTERNAL("rom_cslam", MD_EEPROM_CSLAM)
SLOT_INTERFACE_INTERNAL("rom_nhlpa", MD_EEPROM_NHLPA)
SLOT_INTERFACE_INTERNAL("rom_blara", MD_EEPROM_BLARA)
// J-Cart controller (Sampras Tennis)
SLOT_INTERFACE_INTERNAL("rom_jcart", MD_JCART)
// J-Cart controller + EEPROM handling (not supported fully yet)
SLOT_INTERFACE_INTERNAL("rom_codemast", MD_SEPROM_CODEMAST)
SLOT_INTERFACE_INTERNAL("rom_mm96", MD_SEPROM_MM96)
// STM95 EEPROM
SLOT_INTERFACE_INTERNAL("rom_stm95", MD_EEPROM_STM95)
// unique bankswitch
SLOT_INTERFACE_INTERNAL("rom_ssf2", MD_ROM_SSF2)
SLOT_INTERFACE_INTERNAL("rom_radica", MD_ROM_RADICA)
// pirate mappers (protection and/or bankswitch)
SLOT_INTERFACE_INTERNAL("rom_bugs", MD_ROM_BUGSLIFE)
SLOT_INTERFACE_INTERNAL("rom_chinf3", MD_ROM_CHINF3)
SLOT_INTERFACE_INTERNAL("rom_elfwor", MD_ROM_ELFWOR)
SLOT_INTERFACE_INTERNAL("rom_kof98", MD_ROM_KOF98)
SLOT_INTERFACE_INTERNAL("rom_kof99", MD_ROM_KOF99)
SLOT_INTERFACE_INTERNAL("rom_lion2", MD_ROM_LION2)
SLOT_INTERFACE_INTERNAL("rom_lion3", MD_ROM_LION3)
SLOT_INTERFACE_INTERNAL("rom_mcpir", MD_ROM_MCPIR)
SLOT_INTERFACE_INTERNAL("rom_mjlov", MD_ROM_MJLOV)
SLOT_INTERFACE_INTERNAL("rom_pokestad", MD_ROM_POKESTAD)
SLOT_INTERFACE_INTERNAL("rom_realtec", MD_ROM_REALTEC)
SLOT_INTERFACE_INTERNAL("rom_redcl", MD_ROM_REDCL)
SLOT_INTERFACE_INTERNAL("rom_rx3", MD_ROM_RX3)
SLOT_INTERFACE_INTERNAL("rom_sbubl", MD_ROM_SBUBL)
SLOT_INTERFACE_INTERNAL("rom_smb", MD_ROM_SMB)
SLOT_INTERFACE_INTERNAL("rom_smb2", MD_ROM_SMB2)
SLOT_INTERFACE_INTERNAL("rom_smouse", MD_ROM_SMOUSE)
SLOT_INTERFACE_INTERNAL("rom_soulb", MD_ROM_SOULB)
SLOT_INTERFACE_INTERNAL("rom_squir", MD_ROM_SQUIR)
SLOT_INTERFACE_INTERNAL("rom_topf", MD_ROM_TOPF)
// these have protection patched out, instead of emulated!
SLOT_INTERFACE_INTERNAL("rom_mulan", MD_STD_ROM)
SLOT_INTERFACE_INTERNAL("rom_poke", MD_STD_ROM)
SLOT_INTERFACE_INTERNAL("rom_poke2", MD_STD_ROM)
SLOT_INTERFACE_END
static MACHINE_CONFIG_START( ms_megadriv, md_cons_state ) static MACHINE_CONFIG_START( ms_megadriv, md_cons_state )
MCFG_FRAGMENT_ADD( md_ntsc ) MCFG_FRAGMENT_ADD( md_ntsc )
MCFG_NVRAM_HANDLER_CLEAR() MCFG_NVRAM_HANDLER_CLEAR()
@ -333,7 +349,8 @@ static MACHINE_CONFIG_START( ms_megadriv, md_cons_state )
MCFG_MACHINE_START( ms_megadriv ) MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv ) MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( genesis_cartslot ) MCFG_MD_CARTRIDGE_ADD("mdslot", md_cart, NULL, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_START( ms_megadpal, md_cons_state ) static MACHINE_CONFIG_START( ms_megadpal, md_cons_state )
@ -343,29 +360,8 @@ static MACHINE_CONFIG_START( ms_megadpal, md_cons_state )
MCFG_MACHINE_START( ms_megadriv ) MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv ) MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( genesis_cartslot ) MCFG_MD_CARTRIDGE_ADD("mdslot", md_cart, NULL, NULL)
MACHINE_CONFIG_END MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
static MACHINE_CONFIG_START( ms_megdsvp, mdsvp_state )
MCFG_FRAGMENT_ADD( md_ntsc )
MCFG_FRAGMENT_ADD( md_svp )
MCFG_NVRAM_HANDLER_CLEAR()
MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( genesis_cartslot )
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( ms_megdsvppal, mdsvp_state )
MCFG_FRAGMENT_ADD( md_pal )
MCFG_FRAGMENT_ADD( md_svp )
MCFG_NVRAM_HANDLER_CLEAR()
MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( genesis_cartslot )
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -640,6 +636,51 @@ ROM_START( 32x_scd )
ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) )
ROM_END ROM_END
/****************************************** SVP emulation *****************************************/
INPUT_PORTS_START( megdsvp )
PORT_INCLUDE( megadriv )
PORT_START("MEMORY_TEST") /* special memtest mode */
/* Region setting for Console */
PORT_DIPNAME( 0x01, 0x00, DEF_STR( Test ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
static MACHINE_CONFIG_START( megdsvp, mdsvp_state )
MCFG_FRAGMENT_ADD( md_ntsc )
MCFG_NVRAM_HANDLER_CLEAR()
MCFG_CPU_ADD("svp", SSP1601, MASTER_CLOCK_NTSC / 7 * 3) /* ~23 MHz (guessed) */
MCFG_CPU_PROGRAM_MAP(svp_ssp_map)
MCFG_CPU_IO_MAP(svp_ext_map)
/* IRQs are not used by this CPU */
MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv )
MCFG_MD_CARTRIDGE_ADD("mdslot", md_cart, NULL, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( megdsvp_pal, mdsvp_state )
MCFG_FRAGMENT_ADD( md_pal )
MCFG_NVRAM_HANDLER_CLEAR()
MCFG_CPU_ADD("svp", SSP1601, MASTER_CLOCK_PAL / 7 * 3) /* ~23 MHz (guessed) */
MCFG_CPU_PROGRAM_MAP(svp_ssp_map)
MCFG_CPU_IO_MAP(svp_ext_map)
/* IRQs are not used by this CPU */
MCFG_MACHINE_START( ms_megadriv )
MCFG_MACHINE_RESET( ms_megadriv )
MCFG_MD_CARTRIDGE_ADD("mdslot", md_cart, NULL, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
MACHINE_CONFIG_END
/****************************************** PICO emulation ****************************************/ /****************************************** PICO emulation ****************************************/
@ -828,6 +869,19 @@ static INPUT_PORTS_START( pico )
INPUT_PORTS_END INPUT_PORTS_END
static SLOT_INTERFACE_START(pico_cart)
SLOT_INTERFACE_INTERNAL("rom", MD_STD_ROM)
SLOT_INTERFACE_END
static MACHINE_START(pico)
{
pico_state *state = machine.driver_data<pico_state>();
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7fffff, read16_delegate(FUNC(device_md_cart_interface::read),state->m_picocart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write),state->m_picocart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16_delegate(FUNC(device_md_cart_interface::read_a13),state->m_picocart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write_a13),state->m_picocart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16_delegate(FUNC(device_md_cart_interface::read_a15),state->m_picocart->m_cart), write16_delegate(FUNC(device_md_cart_interface::write_a15),state->m_picocart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16_delegate(FUNC(device_md_cart_interface::write_tmss_bank),state->m_picocart->m_cart));
}
static MACHINE_CONFIG_START( pico, pico_state ) static MACHINE_CONFIG_START( pico, pico_state )
MCFG_FRAGMENT_ADD( md_ntsc ) MCFG_FRAGMENT_ADD( md_ntsc )
MCFG_NVRAM_HANDLER_CLEAR() MCFG_NVRAM_HANDLER_CLEAR()
@ -837,9 +891,11 @@ static MACHINE_CONFIG_START( pico, pico_state )
MCFG_DEVICE_REMOVE("genesis_snd_z80") MCFG_DEVICE_REMOVE("genesis_snd_z80")
MCFG_MACHINE_START( pico )
MCFG_MACHINE_RESET( ms_megadriv ) MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( pico_cartslot ) MCFG_PICO_CARTRIDGE_ADD("picoslot", pico_cart, NULL, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list","pico")
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_START( picopal, pico_state ) static MACHINE_CONFIG_START( picopal, pico_state )
@ -851,9 +907,11 @@ static MACHINE_CONFIG_START( picopal, pico_state )
MCFG_DEVICE_REMOVE("genesis_snd_z80") MCFG_DEVICE_REMOVE("genesis_snd_z80")
MCFG_MACHINE_START( pico )
MCFG_MACHINE_RESET( ms_megadriv ) MCFG_MACHINE_RESET( ms_megadriv )
MCFG_FRAGMENT_ADD( pico_cartslot ) MCFG_PICO_CARTRIDGE_ADD("picoslot", pico_cart, NULL, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list","pico")
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -886,9 +944,9 @@ CONS( 1988, megadrij, genesis, 0, ms_megadriv, md, md_cons_state,
// these should not exist, the SVP hardware is in the cart and should be installed dynamically when selected from the Software List // these should not exist, the SVP hardware is in the cart and should be installed dynamically when selected from the Software List
// this however involves installing entire CPUs at run/load time and I don't think we can do that. // this however involves installing entire CPUs at run/load time and I don't think we can do that.
CONS( 1993, gensvp, genesis, 0, ms_megdsvp, md, md_cons_state, genesis, "Sega", "Genesis (USA, NTSC, for SVP cart)", 0) CONS( 1993, gensvp, genesis, 0, megdsvp, md, md_cons_state, genesis, "Sega", "Genesis (USA, NTSC, for SVP cart)", 0)
CONS( 1990, mdsvp, genesis, 0, ms_megdsvppal, md, md_cons_state, md_eur, "Sega", "Mega Drive (Europe, PAL, for SVP cart)", 0) CONS( 1990, mdsvp, genesis, 0, megdsvp_pal, md, md_cons_state, md_eur, "Sega", "Mega Drive (Europe, PAL, for SVP cart)", 0)
CONS( 1988, mdsvpj, genesis, 0, ms_megdsvp, md, md_cons_state, md_jpn, "Sega", "Mega Drive (Japan, NTSC, for SVP cart)", 0) CONS( 1988, mdsvpj, genesis, 0, megdsvp, md, md_cons_state, md_jpn, "Sega", "Mega Drive (Japan, NTSC, for SVP cart)", 0)
// the 32X plugged in the cart slot, games plugged into the 32x. Maybe it should be handled as an expansion device? // the 32X plugged in the cart slot, games plugged into the 32x. Maybe it should be handled as an expansion device?
CONS( 1994, 32x, 0, 0, ms_32x, md, md_cons_state, genesis, "Sega", "Genesis with 32X (USA, NTSC)", GAME_NOT_WORKING ) CONS( 1994, 32x, 0, 0, ms_32x, md, md_cons_state, genesis, "Sega", "Genesis with 32X (USA, NTSC)", GAME_NOT_WORKING )

64
src/mess/includes/md.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef __MD__
#define __MD__
// Temporary include file to handle SVP add-on, until converted to a proper slot device
// Afterwards, these classes can be moved back to mess/drivers/megadriv.c!
#include "includes/megadriv.h"
#include "machine/md_slot.h"
class md_cons_state : public md_base_state
{
public:
md_cons_state(const machine_config &mconfig, device_type type, const char *tag)
: md_base_state(mconfig, type, tag),
m_slotcart(*this, "mdslot")
{ }
emu_timer *m_mess_io_timeout[3];
int m_mess_io_stage[3];
optional_device<md_cart_slot_device> m_slotcart;
DECLARE_DRIVER_INIT(mess_md_common);
DECLARE_DRIVER_INIT(genesis);
DECLARE_DRIVER_INIT(md_eur);
DECLARE_DRIVER_INIT(md_jpn);
};
class mdsvp_state : public md_cons_state
{
public:
mdsvp_state(const machine_config &mconfig, device_type type, const char *tag)
: md_cons_state(mconfig, type, tag) { }
UINT8 *m_iram; // IRAM (0-0x7ff)
UINT8 *m_dram; // [0x20000];
UINT32 m_pmac_read[6]; // read modes/addrs for PM0-PM5
UINT32 m_pmac_write[6]; // write ...
PAIR m_pmc;
UINT32 m_emu_status;
UINT16 m_XST; // external status, mapped at a15000 and a15002 on 68k side.
UINT16 m_XST2; // status of XST (bit1 set when 68k writes to XST)
};
class pico_state : public md_cons_state
{
public:
pico_state(const machine_config &mconfig, device_type type, const char *tag)
: md_cons_state(mconfig, type, tag),
m_picocart(*this, "picoslot") { }
optional_device<pico_cart_slot_device> m_picocart;
UINT8 m_page_register;
};
ADDRESS_MAP_EXTERN( svp_ssp_map, driver_device );
ADDRESS_MAP_EXTERN( svp_ext_map, driver_device );
extern void svp_init(running_machine &machine);
extern cpu_device *_svp_cpu;
#endif

View File

@ -0,0 +1,360 @@
/***********************************************************************************************************
MegaDrive / Genesis cart+EEPROM emulation
TODO: proper EEPROM emulation, still not worked on (just hooked up the I2C device)
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
Micro Machines 2, Micro Machines Military, Micro Machines 96 are emulated in md_jcart
***********************************************************************************************************/
#include "emu.h"
#include "machine/md_eeprom.h"
//-------------------------------------------------
// md_rom_device - constructor
//-------------------------------------------------
const device_type MD_STD_EEPROM = &device_creator<md_std_eeprom_device>;
const device_type MD_EEPROM_NBAJAM = &device_creator<md_eeprom_nbajam_device>;
const device_type MD_EEPROM_NBAJAMTE = &device_creator<md_eeprom_nbajamte_device>;
const device_type MD_EEPROM_NFLQB = &device_creator<md_eeprom_nflqb_device>;
const device_type MD_EEPROM_CSLAM = &device_creator<md_eeprom_cslam_device>;
const device_type MD_EEPROM_NHLPA = &device_creator<md_eeprom_nhlpa_device>;
const device_type MD_EEPROM_BLARA = &device_creator<md_eeprom_blara_device>;
md_std_eeprom_device::md_std_eeprom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_i2cmem(*this, "i2cmem")
{
}
md_std_eeprom_device::md_std_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MD_STD_EEPROM, "MD Standard cart + EEPROM", tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_i2cmem(*this, "i2cmem")
{
}
md_eeprom_nbajam_device::md_eeprom_nbajam_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_NBAJAM, "MD NBA Jam", tag, owner, clock)
{
}
md_eeprom_nbajamte_device::md_eeprom_nbajamte_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_NBAJAMTE, "MD NBA Jam TE (and a few more)", tag, owner, clock)
{
}
md_eeprom_cslam_device::md_eeprom_cslam_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_CSLAM, "MD College Slam", tag, owner, clock)
{
}
md_eeprom_nflqb_device::md_eeprom_nflqb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_NFLQB, "MD NFL Quarterback 96", tag, owner, clock)
{
}
md_eeprom_nhlpa_device::md_eeprom_nhlpa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_NHLPA, "MD NHLPA 93", tag, owner, clock)
{
}
md_eeprom_blara_device::md_eeprom_blara_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_eeprom_device(mconfig, MD_EEPROM_BLARA, "MD Brian Lara", tag, owner, clock)
{
}
//-------------------------------------------------
// SERIAL I2C DEVICE
//-------------------------------------------------
static const i2cmem_interface md_24c01_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x80
};
static const i2cmem_interface md_24c02_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x100
};
static const i2cmem_interface md_24c16_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x800
};
static const i2cmem_interface md_24c64_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x2000
};
// MD_STD_EEPROM & MD_EEPROM_NHLPA
MACHINE_CONFIG_FRAGMENT( md_i2c_24c01 )
MCFG_I2CMEM_ADD("i2cmem", md_24c01_i2cmem_interface)
MACHINE_CONFIG_END
// MD_EEPROM_NBAJAM & MD_EEPROM_NBAJAMTE
MACHINE_CONFIG_FRAGMENT( md_i2c_24c02 )
MCFG_I2CMEM_ADD("i2cmem", md_24c02_i2cmem_interface)
MACHINE_CONFIG_END
// MD_EEPROM_NFLQB
MACHINE_CONFIG_FRAGMENT( md_i2c_24c16 )
MCFG_I2CMEM_ADD("i2cmem", md_24c16_i2cmem_interface)
MACHINE_CONFIG_END
// MD_EEPROM_CSLAM & MD_EEPROM_BLARA
MACHINE_CONFIG_FRAGMENT( md_i2c_24c64 )
MCFG_I2CMEM_ADD("i2cmem", md_24c64_i2cmem_interface)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor md_std_eeprom_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c01 );
}
machine_config_constructor md_eeprom_nbajam_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c02 );
}
machine_config_constructor md_eeprom_nbajamte_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c02 );
}
machine_config_constructor md_eeprom_cslam_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c64 );
}
machine_config_constructor md_eeprom_nflqb_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c16 );
}
machine_config_constructor md_eeprom_nhlpa_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c01 );
}
machine_config_constructor md_eeprom_blara_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c64 );
}
void md_std_eeprom_device::device_start()
{
m_i2c_mem = 0;
m_i2c_clk = 0;
save_item(NAME(m_i2c_mem));
save_item(NAME(m_i2c_clk));
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
/*-------------------------------------------------
CART + EEPROM
-------------------------------------------------*/
READ16_MEMBER(md_std_eeprom_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return ~m_i2c_mem & 1;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_std_eeprom_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 1);
m_i2c_mem = BIT(data, 0);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
READ16_MEMBER(md_eeprom_nbajam_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return m_i2c_mem & 1;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_nbajam_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 1);
m_i2c_mem = BIT(data, 0);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
READ16_MEMBER(md_eeprom_nbajamte_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return m_i2c_mem & 1;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_nbajamte_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 8);
m_i2c_mem = BIT(data, 0);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
// same as NBAJAMTE above... derived class?
READ16_MEMBER(md_eeprom_cslam_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return m_i2c_mem & 1;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_cslam_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 8);
m_i2c_mem = BIT(data, 0);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
// same as NBAJAMTE above... derived class?
READ16_MEMBER(md_eeprom_nflqb_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return m_i2c_mem & 1;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_nflqb_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 8);
m_i2c_mem = BIT(data, 0);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
READ16_MEMBER(md_eeprom_nhlpa_device::read)
{
if (offset == 0x200000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return (m_i2c_mem & 1) << 7;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_nhlpa_device::write)
{
if (offset == 0x200000/2)
{
m_i2c_clk = BIT(data, 6);
m_i2c_mem = BIT(data, 7);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}
READ16_MEMBER(md_eeprom_blara_device::read)
{
if (offset == 0x380000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return (m_i2c_mem & 1) << 7;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_eeprom_blara_device::write)
{
if (offset == 0x380000/2)
{
m_i2c_clk = BIT(data, 9);
m_i2c_mem = BIT(data, 8);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
}

View File

@ -0,0 +1,147 @@
#ifndef __MD_EEPROM_H
#define __MD_EEPROM_H
#include "machine/md_slot.h"
#include "machine/i2cmem.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> md_std_eeprom_device
class md_std_eeprom_device : public device_t,
public device_md_cart_interface
{
public:
// construction/destruction
md_std_eeprom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_std_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_std_eeprom"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
required_device<i2cmem_device> m_i2cmem;
UINT8 m_i2c_mem, m_i2c_clk;
};
// ======================> md_eeprom_nbajam_device
class md_eeprom_nbajam_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_nbajam_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_nbajam"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// ======================> md_eeprom_nbajamte_device
class md_eeprom_nbajamte_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_nbajamte_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_nbajamte"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// ======================> md_eeprom_cslam_device (same read/write as nbajamte, but different I2C type)
class md_eeprom_cslam_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_cslam_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_cslam"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// ======================> md_eeprom_nflqb_device (same read/write as nbajamte, but different I2C type)
class md_eeprom_nflqb_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_nflqb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_nflqb"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// ======================> md_eeprom_nhlpa_device
class md_eeprom_nhlpa_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_nhlpa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_nhlpa"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// ======================> md_eeprom_blara_device (same read/write as codemast, but different I2C type)
class md_eeprom_blara_device : public md_std_eeprom_device
{
public:
// construction/destruction
md_eeprom_blara_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_eeprom_blara"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
};
// device type definition
extern const device_type MD_STD_EEPROM;
extern const device_type MD_EEPROM_NBAJAM;
extern const device_type MD_EEPROM_NBAJAMTE;
extern const device_type MD_EEPROM_CSLAM;
extern const device_type MD_EEPROM_NFLQB;
extern const device_type MD_EEPROM_NHLPA;
extern const device_type MD_EEPROM_BLARA;
#endif

249
src/mess/machine/md_jcart.c Normal file
View File

@ -0,0 +1,249 @@
/***********************************************************************************************************
MegaDrive / Genesis J-Cart (+SEPROM) emulation
i2c games mapping table:
game name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK |
----------------------------------|------------|------------|------------|----------------|-----------|
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 |
----------------------------------|------------|------------|------------|----------------|-----------|
* Notes: check these
TODO: proper SEPROM emulation, still not worked on (just hooked up the I2C device)
***********************************************************************************************************/
#include "emu.h"
#include "machine/md_jcart.h"
//-------------------------------------------------
// md_rom_device - constructor
//-------------------------------------------------
const device_type MD_JCART = &device_creator<md_jcart_device>;
const device_type MD_SEPROM_CODEMAST = &device_creator<md_seprom_codemast_device>;
const device_type MD_SEPROM_MM96 = &device_creator<md_seprom_mm96_device>;
// Sampras, Super Skidmarks?
md_jcart_device::md_jcart_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_jcart3(*this, "JCART3"),
m_jcart4(*this, "JCART4")
{
}
md_jcart_device::md_jcart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MD_JCART, "MD J-Cart games", tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_jcart3(*this, "JCART3"),
m_jcart4(*this, "JCART4")
{
}
// Micro Machines 2, Micro Machines Military
md_seprom_codemast_device::md_seprom_codemast_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: md_jcart_device(mconfig, type, name, tag, owner, clock),
m_i2cmem(*this, "i2cmem")
{
}
md_seprom_codemast_device::md_seprom_codemast_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_jcart_device(mconfig, MD_SEPROM_CODEMAST, "MD J-Cart games + SEPROM", tag, owner, clock),
m_i2cmem(*this, "i2cmem")
{
}
// Micro Machines 96
md_seprom_mm96_device::md_seprom_mm96_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_seprom_codemast_device(mconfig, MD_SEPROM_MM96, "MD Micro Machine 96", tag, owner, clock)
{
}
//-------------------------------------------------
// SERIAL I2C DEVICE
//-------------------------------------------------
static const i2cmem_interface md_24c08_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x400
};
static const i2cmem_interface md_24c16a_i2cmem_interface =
{
I2CMEM_SLAVE_ADDRESS, 0, 0x800
};
// MD_SEPROM_CODEMAST
MACHINE_CONFIG_FRAGMENT( md_i2c_24c08 )
MCFG_I2CMEM_ADD("i2cmem", md_24c08_i2cmem_interface)
MACHINE_CONFIG_END
// MD_SEPROM_MM96
MACHINE_CONFIG_FRAGMENT( md_i2c_24c16a )
MCFG_I2CMEM_ADD("i2cmem", md_24c16a_i2cmem_interface)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor md_seprom_codemast_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c08 );
}
machine_config_constructor md_seprom_mm96_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( md_i2c_24c16a );
}
static INPUT_PORTS_START( jcart_ipt )
PORT_START("JCART3") /* Joypad 3 on J-Cart (3 button + start) */
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B")
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 C")
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A")
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(3)
PORT_START("JCART4") /* Joypad 4 on J-Cart (3 button + start) */
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B")
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 C")
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A")
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(4)
INPUT_PORTS_END
ioport_constructor md_jcart_device::device_input_ports() const
{
return INPUT_PORTS_NAME( jcart_ipt );
}
void md_jcart_device::device_start()
{
m_jcart_io_data[0] = 0;
m_jcart_io_data[1] = 0;
save_item(NAME(m_jcart_io_data));
}
void md_seprom_codemast_device::device_start()
{
m_i2c_mem = 0;
m_i2c_clk = 0;
m_jcart_io_data[0] = 0;
m_jcart_io_data[1] = 0;
save_item(NAME(m_i2c_mem));
save_item(NAME(m_i2c_clk));
save_item(NAME(m_jcart_io_data));
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
/*-------------------------------------------------
J-CART ONLY (Pete Sampras Tennis)
-------------------------------------------------*/
READ16_MEMBER(md_jcart_device::read)
{
if (offset == 0x38fffe/2)
{
UINT8 joy[2];
if (m_jcart_io_data[0] & 0x40)
{
joy[0] = m_jcart3->read_safe(0);
joy[1] = m_jcart4->read_safe(0);
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
else
{
joy[0] = ((m_jcart3->read_safe(0) & 0xc0) >> 2) | (m_jcart3->read_safe(0) & 0x03);
joy[1] = ((m_jcart4->read_safe(0) & 0xc0) >> 2) | (m_jcart4->read_safe(0) & 0x03);
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
}
return m_rom[offset];
}
WRITE16_MEMBER(md_jcart_device::write)
{
if (offset == 0x38fffe/2)
{
m_jcart_io_data[0] = (data & 1) << 6;
m_jcart_io_data[1] = (data & 1) << 6;
}
}
/*-------------------------------------------------
J-CART + SEPROM
-------------------------------------------------*/
READ16_MEMBER(md_seprom_codemast_device::read)
{
if (offset == 0x380000/2)
{
m_i2c_mem = i2cmem_sda_read(m_i2cmem);
return (m_i2c_mem & 1) << 7;
}
if (offset == 0x38fffe/2)
{
UINT8 joy[2];
if (m_jcart_io_data[0] & 0x40)
{
joy[0] = m_jcart3->read_safe(0);
joy[1] = m_jcart4->read_safe(0);
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
else
{
joy[0] = ((m_jcart3->read_safe(0) & 0xc0) >> 2) | (m_jcart3->read_safe(0) & 0x03);
joy[1] = ((m_jcart4->read_safe(0) & 0xc0) >> 2) | (m_jcart4->read_safe(0) & 0x03);
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
}
}
return m_rom[offset];
}
WRITE16_MEMBER(md_seprom_codemast_device::write)
{
if (offset == 0x380000/2)
{
m_i2c_clk = BIT(data, 9);
m_i2c_mem = BIT(data, 8);
i2cmem_scl_write(m_i2cmem, m_i2c_clk);
i2cmem_sda_write(m_i2cmem, m_i2c_mem);
}
if (offset == 0x38fffe/2)
{
m_jcart_io_data[0] = (data & 1) << 6;
m_jcart_io_data[1] = (data & 1) << 6;
}
}

View File

@ -0,0 +1,83 @@
#ifndef __MD_JCART_H
#define __MD_JCART_H
#include "machine/md_slot.h"
#include "machine/i2cmem.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> md_jcart_device
class md_jcart_device : public device_t,
public device_md_cart_interface
{
public:
// construction/destruction
md_jcart_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_jcart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_jcart"; }
virtual ioport_constructor device_input_ports() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
required_ioport m_jcart3;
required_ioport m_jcart4;
private:
UINT8 m_jcart_io_data[2];
};
// ======================> md_seprom_codemast_device
class md_seprom_codemast_device : public md_jcart_device
{
public:
// construction/destruction
md_seprom_codemast_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_seprom_codemast_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_seprom_codemast"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
required_device<i2cmem_device> m_i2cmem;
private:
UINT8 m_jcart_io_data[2];
UINT8 m_i2c_mem, m_i2c_clk;
};
// ======================> md_seprom_mm96_device (same read/write as codemast, but different I2C type)
class md_seprom_mm96_device : public md_seprom_codemast_device
{
public:
// construction/destruction
md_seprom_mm96_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_seprom_mm96"; }
virtual machine_config_constructor device_mconfig_additions() const;
};
// device type definition
extern const device_type MD_JCART;
extern const device_type MD_SEPROM_CODEMAST;
extern const device_type MD_SEPROM_MM96;
#endif

924
src/mess/machine/md_rom.c Normal file
View File

@ -0,0 +1,924 @@
/***********************************************************************************************************
MegaDrive / Genesis cart emulation
Here we emulate bankswitch / protection / NVRAM found on generic carts with no additional hardware
***********************************************************************************************************/
#include "emu.h"
#include "machine/md_rom.h"
#include "cpu/m68000/m68000.h"
//-------------------------------------------------
// md_rom_device - constructor
//-------------------------------------------------
// BASE CARTS + NVRAM
const device_type MD_STD_ROM = &device_creator<md_std_rom_device>;
const device_type MD_ROM_SRAM = &device_creator<md_rom_sram_device>;
const device_type MD_ROM_FRAM = &device_creator<md_rom_fram_device>;
// BASE CARTS + PROTECTION / BANKSWITCH
const device_type MD_ROM_SSF2 = &device_creator<md_rom_ssf2_device>;
const device_type MD_ROM_BUGSLIFE = &device_creator<md_rom_bugslife_device>;
const device_type MD_ROM_SMOUSE = &device_creator<md_rom_smouse_device>;
const device_type MD_ROM_SMB = &device_creator<md_rom_smb_device>;
const device_type MD_ROM_SMB2 = &device_creator<md_rom_smb2_device>;
const device_type MD_ROM_SBUBL = &device_creator<md_rom_sbubl_device>;
const device_type MD_ROM_RX3 = &device_creator<md_rom_rx3_device>;
const device_type MD_ROM_MJLOV = &device_creator<md_rom_mjlov_device>;
const device_type MD_ROM_KOF98 = &device_creator<md_rom_kof98_device>;
const device_type MD_ROM_KOF99 = &device_creator<md_rom_kof99_device>;
const device_type MD_ROM_SOULB = &device_creator<md_rom_soulb_device>;
const device_type MD_ROM_CHINF3 = &device_creator<md_rom_chinf3_device>;
const device_type MD_ROM_ELFWOR = &device_creator<md_rom_elfwor_device>;
const device_type MD_ROM_LION2 = &device_creator<md_rom_lion2_device>;
const device_type MD_ROM_LION3 = &device_creator<md_rom_lion3_device>;
const device_type MD_ROM_MCPIR = &device_creator<md_rom_mcpirate_device>;
const device_type MD_ROM_POKESTAD = &device_creator<md_rom_pokestad_device>;
const device_type MD_ROM_REALTEC = &device_creator<md_rom_realtec_device>;
const device_type MD_ROM_REDCL = &device_creator<md_rom_redcl_device>;
const device_type MD_ROM_SQUIR = &device_creator<md_rom_squir_device>;
const device_type MD_ROM_TOPF = &device_creator<md_rom_topf_device>;
const device_type MD_ROM_RADICA = &device_creator<md_rom_radica_device>;
const device_type MD_ROM_BEGGAR = &device_creator<md_rom_beggar_device>;
// below ones are currently unused, because the protection is patched out
const device_type MD_ROM_MULAN = &device_creator<md_std_rom_device>;
const device_type MD_ROM_POKE = &device_creator<md_std_rom_device>;
const device_type MD_ROM_POKE2 = &device_creator<md_std_rom_device>;
md_std_rom_device::md_std_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_md_cart_interface( mconfig, *this )
{
}
md_std_rom_device::md_std_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MD_STD_ROM, "MD Standard cart", tag, owner, clock),
device_md_cart_interface( mconfig, *this )
{
}
md_rom_sram_device::md_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SRAM, "MD Standard cart + SRAM", tag, owner, clock)
{
}
md_rom_beggar_device::md_rom_beggar_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_BEGGAR, "MD Xin Qigai Wangzi", tag, owner, clock)
{
}
md_rom_fram_device::md_rom_fram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_FRAM, "MD Standard cart + FRAM", tag, owner, clock)
{
}
md_rom_ssf2_device::md_rom_ssf2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SSF2, "MD Super SF2", tag, owner, clock)
{
}
md_rom_mcpirate_device::md_rom_mcpirate_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_MCPIR, "MD Pirate Multicarts (Various)", tag, owner, clock)
{
}
md_rom_bugslife_device::md_rom_bugslife_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_BUGSLIFE, "MD A Bug's Life", tag, owner, clock)
{
}
md_rom_smouse_device::md_rom_smouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SMOUSE, "MD Huan Le Tao Qi Shu / Smart Mouse", tag, owner, clock)
{
}
md_rom_smb_device::md_rom_smb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SMB, "MD Super Mario Bros.", tag, owner, clock)
{
}
md_rom_smb2_device::md_rom_smb2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SMB2, "MD Super Mario Bros. 2", tag, owner, clock)
{
}
md_rom_sbubl_device::md_rom_sbubl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SBUBL, "MD Super Bubble Bobble", tag, owner, clock)
{
}
md_rom_rx3_device::md_rom_rx3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SMB2, "MD Rockman X3", tag, owner, clock)
{
}
md_rom_mjlov_device::md_rom_mjlov_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_MJLOV, "MD Ma Jiang Qing Ren / Mahjong Lover", tag, owner, clock)
{
}
md_rom_kof98_device::md_rom_kof98_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_KOF98, "MD KOF 98", tag, owner, clock)
{
}
md_rom_kof99_device::md_rom_kof99_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_KOF99, "MD KOF 99", tag, owner, clock)
{
}
md_rom_soulb_device::md_rom_soulb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SOULB, "MD Soul Blade", tag, owner, clock)
{
}
md_rom_chinf3_device::md_rom_chinf3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_CHINF3, "MD Chinese Fighter 3", tag, owner, clock)
{
}
md_rom_elfwor_device::md_rom_elfwor_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_ELFWOR, "MD Linghuan Daoshi Super Magician / Elf Wor", tag, owner, clock)
{
}
md_rom_lion2_device::md_rom_lion2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_LION2, "MD Lion King 2", tag, owner, clock)
{
}
md_rom_lion3_device::md_rom_lion3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_LION3, "MD Lion King 3", tag, owner, clock)
{
}
md_rom_pokestad_device::md_rom_pokestad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_POKESTAD, "MD Pokemon Stadium", tag, owner, clock)
{
}
md_rom_realtec_device::md_rom_realtec_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_REALTEC, "MD Realtec", tag, owner, clock)
{
}
md_rom_redcl_device::md_rom_redcl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_REDCL, "MD Redcliff", tag, owner, clock)
{
}
md_rom_squir_device::md_rom_squir_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_SQUIR, "MD Squirrel King", tag, owner, clock)
{
}
md_rom_topf_device::md_rom_topf_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_TOPF, "MD Top Fighter", tag, owner, clock)
{
}
md_rom_radica_device::md_rom_radica_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: md_std_rom_device(mconfig, MD_ROM_RADICA, "MD Radica TV games", tag, owner, clock)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void md_rom_ssf2_device::device_start()
{
for (int i = 0; i < 7; i++)
m_bank[i] = i;
m_lastoff = -1;
m_lastdata = -1;
save_item(NAME(m_bank));
save_item(NAME(m_lastoff));
save_item(NAME(m_lastdata));
}
void md_rom_mcpirate_device::device_start()
{
m_bank = 0;
save_item(NAME(m_bank));
}
void md_rom_chinf3_device::device_start()
{
m_bank = 0;
save_item(NAME(m_bank));
}
void md_rom_lion2_device::device_start()
{
m_prot1_data = 0;
m_prot2_data = 0;
save_item(NAME(m_prot1_data));
save_item(NAME(m_prot2_data));
}
void md_rom_lion3_device::device_start()
{
m_prot_data = 0;
m_prot_cmd = 0;
m_bank = 0;
save_item(NAME(m_prot_data));
save_item(NAME(m_prot_cmd));
save_item(NAME(m_bank));
}
void md_rom_pokestad_device::device_start()
{
m_bank = 0;
save_item(NAME(m_bank));
}
void md_rom_realtec_device::device_start()
{
m_bank_addr = 0;
m_bank_size = 0;
m_old_bank_addr = -1;
save_item(NAME(m_bank_addr));
save_item(NAME(m_bank_size));
save_item(NAME(m_old_bank_addr));
}
void md_rom_squir_device::device_start()
{
m_latch = 0;
save_item(NAME(m_latch));
}
void md_rom_topf_device::device_start()
{
m_latch = 0;
m_bank[0] = m_bank[1] = m_bank[2] = 0;
save_item(NAME(m_latch));
save_item(NAME(m_bank));
}
void md_rom_radica_device::device_start()
{
m_bank = 0;
save_item(NAME(m_bank));
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
/*-------------------------------------------------
CART + SRAM
-------------------------------------------------*/
READ16_MEMBER(md_rom_sram_device::read)
{
offset <<= 1;
// since a lot of generic carts ends up here if loaded from fullpath
// we access nvram only if m_nvram_handlers_installed has been turned on
if (m_nvram_handlers_installed)
{
if (offset >= m_nvram_start && offset < m_nvram_end && m_nvram_active)
return m_nvram[(offset - m_nvram_start)/2];
}
return m_rom[offset/2];
}
WRITE16_MEMBER(md_rom_sram_device::write)
{
// since a lot of generic carts ends up here if loaded from fullpath
// we access nvram only if m_nvram_handlers_installed has been turned on
if (m_nvram_handlers_installed)
{
offset <<= 1;
if (offset >= m_nvram_start && offset <= m_nvram_end && m_nvram_active && !m_nvram_readonly)
m_nvram[(offset - m_nvram_start)/2] = data;
}
}
WRITE16_MEMBER(md_rom_sram_device::write_a13)
{
offset <<= 1;
if (offset == 0xf)
{
/* unsure if this is actually supposed to toggle or just switch on? yet to encounter game that uses this */
m_nvram_active = BIT(data, 0);
m_nvram_readonly = BIT(data, 1);
// since a lot of generic carts ends up here if loaded from fullpath
// we turn on nvram (with m_nvram_handlers_installed) only if they toggle it on by writing here!
if (m_nvram_active && !m_nvram_handlers_installed)
m_nvram_handlers_installed = 1;
}
}
/*-------------------------------------------------
BEGGAR PRINCE / XIN QIGAI WANGZI [same as above, but diff start/end... merge?]
-------------------------------------------------*/
READ16_MEMBER(md_rom_beggar_device::read)
{
offset <<= 1;
if (offset >= m_nvram_start && offset < m_nvram_end && m_nvram_active)
return m_nvram[(offset - m_nvram_start)/2];
return m_rom[offset/2];
}
WRITE16_MEMBER(md_rom_beggar_device::write)
{
offset <<= 1;
if (offset >= m_nvram_start && offset <= m_nvram_end && m_nvram_active && !m_nvram_readonly)
m_nvram[(offset - m_nvram_start)/2] = data;
}
WRITE16_MEMBER(md_rom_beggar_device::write_a13)
{
offset <<= 1;
if (offset == 0xf)
{
/* unsure if this is actually supposed to toggle or just switch on? yet to encounter game that uses this */
m_nvram_active = BIT(data, 0);
m_nvram_readonly = BIT(data, 1);
}
}
/*-------------------------------------------------
CART + FRAM [almost same as SRAM... merge common parts?]
-------------------------------------------------*/
READ16_MEMBER(md_rom_fram_device::read)
{
offset <<= 1;
if (offset >= m_nvram_start && offset < m_nvram_end && m_nvram_active)
return m_nvram[(offset - m_nvram_start)/2];
return m_rom[offset/2];
}
WRITE16_MEMBER(md_rom_fram_device::write_a13)
{
offset <<= 1;
if (offset == 0xf)
m_nvram_active = BIT(data, 0);
}
READ16_MEMBER(md_rom_fram_device::read_a13)
{
if (offset == 0xf)
return m_nvram_active;
else
return 0xffff;
}
/*-------------------------------------------------
SUPER STREET FIGHTERS 2
-------------------------------------------------*/
READ16_MEMBER(md_rom_ssf2_device::read)
{
if (offset < 0x400000/2)
return m_rom[offset];
else
return 0xffff;
}
// I'm not very fond of the code below...
WRITE16_MEMBER(md_rom_ssf2_device::write_a13)
{
if (offset >= 0xf0/2)
{
offset -= 0xf0/2;
if ((m_lastoff != offset) || (m_lastdata != data))
{
m_lastoff = offset;
m_lastdata = data;
if (offset) // bank 0 is not modified
{
UINT16 *ROM = get_rom_base();
m_bank[offset] = data & 0xf;
memcpy(ROM + offset * 0x080000/2, ROM + 0x400000/2 + (m_bank[offset] * 0x080000)/2, 0x080000);
}
}
}
}
/*-------------------------------------------------
PIRATE MULTICARTS
-------------------------------------------------*/
READ16_MEMBER(md_rom_mcpirate_device::read)
{
if (offset < 0x400000/2)
{
return m_rom[offset + (m_bank * 0x10000)/2];
}
else
{
return read(space, offset - 0x400000/2, 0xffff);
}
}
WRITE16_MEMBER(md_rom_mcpirate_device::write_a13)
{
offset <<= 1;
if (offset < 0x40)
m_bank = offset;
}
/*-------------------------------------------------
A BUG'S LIFE
-------------------------------------------------*/
READ16_MEMBER(md_rom_bugslife_device::read_a13)
{
if (offset == 0)
return 0x28;
else
return 0xffff;
}
/*-------------------------------------------------
CHINESE FIGHTER 3
-------------------------------------------------*/
READ16_MEMBER(md_rom_chinf3_device::read)
{
if (offset < 0x100000/2)
{
if (!m_bank)
return m_rom[offset & 0xfffff/2];
else
return m_rom[(offset & 0xffff/2) + (m_bank * 0x10000)/2];
}
// PROTECTION in 0x400000 - 0x4fffff
/* not 100% correct, there may be some relationship between the reads here
and the writes made at the start of the game.. */
if (offset >= 0x400000/2 && offset < 0x500000/2)
{
UINT32 retdat = 0;
/*
04dc10 chifi3, prot_r? 2800
04cefa chifi3, prot_r? 65262
*/
if (space.machine().device("maincpu")->safe_pc() == 0x01782) // makes 'VS' screen appear
{
retdat = space.machine().device("maincpu")->state().state_int(M68K_D3) & 0xff;
retdat <<= 8;
return retdat;
}
else if (space.machine().device("maincpu")->safe_pc() == 0x1c24) // background gfx etc.
{
retdat = space.machine().device("maincpu")->state().state_int(M68K_D3) & 0xff;
retdat <<= 8;
return retdat;
}
else if (space.machine().device("maincpu")->safe_pc() == 0x10c4a) // unknown
{
return space.machine().rand();
}
else if (space.machine().device("maincpu")->safe_pc() == 0x10c50) // unknown
{
return space.machine().rand();
}
else if (space.machine().device("maincpu")->safe_pc() == 0x10c52) // relates to the game speed..
{
retdat = space.machine().device("maincpu")->state().state_int(M68K_D4) & 0xff;
retdat <<= 8;
return retdat;
}
else if (space.machine().device("maincpu")->safe_pc() == 0x061ae)
{
retdat = space.machine().device("maincpu")->state().state_int(M68K_D3) & 0xff;
retdat <<= 8;
return retdat;
}
else if (space.machine().device("maincpu")->safe_pc() == 0x061b0)
{
retdat = space.machine().device("maincpu")->state().state_int(M68K_D3) & 0xff;
retdat <<= 8;
return retdat;
}
else
{
logerror("%06x chifi3, prot_r? %04x\n", space.machine().device("maincpu")->safe_pc(), offset);
}
return 0;
}
return m_rom[offset & 0x1fffff/2];
}
WRITE16_MEMBER(md_rom_chinf3_device::write)
{
if (offset >= 0x600000/2 && offset < 0x700000/2)
{
if (data == 0xf100) // *hit player
m_bank = 1;
else if (data == 0xd700) // title screen..
m_bank = 7;
else if (data == 0xd300) // character hits floor
m_bank = 3;
else if (data == 0x0000)
m_bank = 0;
else
logerror("%06x chifi3, bankw? %04x %04x\n", space.device().safe_pc(), offset, data);
}
}
/*-------------------------------------------------
LINGHUAN DAOSHI SUPER MAGICIAN / ELF WOR
-------------------------------------------------*/
READ16_MEMBER(md_rom_elfwor_device::read)
{
/* It returns (0x55 @ 0x400000 OR 0xc9 @ 0x400004) AND (0x0f @ 0x400002 OR 0x18 @ 0x400006).
It is probably best to add handlers for all 4 addresses. */
if (offset == 0x400000/2) return 0x5500;
if (offset == 0x400002/2) return 0x0f00;
if (offset == 0x400004/2) return 0xc900;
if (offset == 0x400006/2) return 0x1800;
return m_rom[offset];
}
/*-------------------------------------------------
HUAN LE TAO QI SHU / SMART MOUSE
-------------------------------------------------*/
READ16_MEMBER(md_rom_smouse_device::read)
{
if (offset == 0x400000/2) return 0x5500;
if (offset == 0x400002/2) return 0x0f00;
if (offset == 0x400004/2) return 0xaa00;
if (offset == 0x400006/2) return 0xf000;
return m_rom[offset];
}
/*-------------------------------------------------
KOF98
-------------------------------------------------*/
READ16_MEMBER(md_rom_kof98_device::read)
{
if (offset == 0x480000/2) return 0xaa00;
if (offset == 0x4800e0/2) return 0xaa00;
if (offset == 0x4824a0/2) return 0xaa00;
if (offset == 0x488880/2) return 0xaa00;
if (offset == 0x4a8820/2) return 0x0a00;
if (offset == 0x4f8820/2) return 0x0000;
return m_rom[offset];
}
/*-------------------------------------------------
KOF 99
-------------------------------------------------*/
// gfx glitch with the new code... uninitialized ram somewhere?
READ16_MEMBER(md_rom_kof99_device::read_a13)
{
if (offset == 0x00/2) return 0x00; // startup protection check, chinese message if != 0
if (offset == 0x02/2) return 0x01; // write 02 to a13002.. shift right 1?
if (offset == 0x3e/2) return 0x1f; // write 3e to a1303e.. shift right 1?
else return 0xffff;
}
/*-------------------------------------------------
LION KING 2
-------------------------------------------------*/
READ16_MEMBER(md_rom_lion2_device::read)
{
if (offset == 0x400002/2) return m_prot1_data;
if (offset == 0x400006/2) return m_prot2_data;
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_lion2_device::write)
{
if (offset == 0x400000/2) m_prot1_data = data;
if (offset == 0x400004/2) m_prot2_data = data;
}
/*-------------------------------------------------
LION KING 3
-------------------------------------------------*/
READ16_MEMBER(md_rom_lion3_device::read)
{
if (offset < 0x8000/2)
return m_rom[offset + (m_bank * 0x8000)/2];
else if (offset >= 0x600000/2 && offset < 0x700000/2)
{
UINT16 retdata = 0;
switch (offset & 0x7)
{
case 2:
if (m_prot_cmd == 0)
retdata = (m_prot_data << 1);
else if (m_prot_cmd == 1)
retdata = (m_prot_data >> 1);
else if (m_prot_cmd == 2)
{
retdata = m_prot_data >> 4;
retdata |= (m_prot_data & 0x0f) << 4;
}
else
{
/* printf("unk prot case %d\n", m_prot_cmd); */
retdata = (BIT(m_prot_data, 7) << 0);
retdata |= (BIT(m_prot_data, 6) << 1);
retdata |= (BIT(m_prot_data, 5) << 2);
retdata |= (BIT(m_prot_data, 4) << 3);
retdata |= (BIT(m_prot_data, 3) << 4);
retdata |= (BIT(m_prot_data, 2) << 5);
retdata |= (BIT(m_prot_data, 1) << 6);
retdata |= (BIT(m_prot_data, 0) << 7);
}
break;
default:
logerror("protection read, unknown offset %x\n", offset & 0x7);
break;
}
return retdata;
}
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_lion3_device::write)
{
if (offset >= 0x600000/2 && offset < 0x700000/2)
{
switch (offset & 0x7)
{
case 0x0:
m_prot_data = data;
break;
case 0x1:
m_prot_cmd = data;
break;
default:
logerror("protection write, unknown offset %d\n", offset & 0x7);
break;
}
}
if (offset >= 0x700000/2 && offset < 0x800000/2)
{
switch (offset & 0x7)
{
case 0x0:
m_bank = data & 0xffff;
break;
default:
logerror("bank write, unknown offset %d\n", offset & 0x7);
break;
}
}
}
/*-------------------------------------------------
MA JIANG QING REN / MAHJONG LOVER
-------------------------------------------------*/
READ16_MEMBER(md_rom_mjlov_device::read)
{
if (offset == 0x400000/2) return 0x9000;
if (offset == 0x401000/2) return 0xd300;
return m_rom[offset];
}
/*-------------------------------------------------
SUPER BUBBLE BOBBLE MD
-------------------------------------------------*/
READ16_MEMBER(md_rom_sbubl_device::read)
{
if (offset == 0x400000/2) return 0x5500;
if (offset == 0x400002/2) return 0x0f00;
return m_rom[offset];
}
/*-------------------------------------------------
SOUL BLADE
-------------------------------------------------*/
READ16_MEMBER(md_rom_soulb_device::read)
{
if (offset == 0x400002/2) return 0x9800;
if (offset == 0x400004/2) return 0xc900;
if (offset == 0x400006/2) return 0xf000;
return m_rom[offset];
}
/*-------------------------------------------------
POKEMON STADIUM / KAIJU
-------------------------------------------------*/
READ16_MEMBER(md_rom_pokestad_device::read)
{
if (offset < 0x8000/2)
return m_rom[offset + (m_bank * 0x8000)/2];
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_pokestad_device::write)
{
if (offset >= 0x700000/2 && offset < 0x800000/2)
m_bank = data & 0x7f;
}
/*-------------------------------------------------
REALTEC
-------------------------------------------------*/
READ16_MEMBER(md_rom_realtec_device::read)
{
if (offset < (m_bank_size * 0x20000)) // two banks of same (variable) size at the bottom of the rom
return m_rom[offset + (m_bank_addr * 0x20000)/2];
return m_rom[(offset & 0x1fff/2) + 0x7e000/2]; // otherwise it accesses the final 8k of the image
}
WRITE16_MEMBER(md_rom_realtec_device::write)
{
if (offset == 0x400000/2)
{
m_old_bank_addr = m_bank_addr;
m_bank_addr = (m_bank_addr & 0x7) | ((data >> 9) & 0x7) << 3;
}
if (offset == 0x402000/2)
{
m_bank_addr = 0;
m_bank_size = (data >> 8) & 0x1f;
}
if (offset == 0x404000/2)
{
m_old_bank_addr = m_bank_addr;
m_bank_addr = (m_bank_addr & 0xf8) | ((data >> 8) & 0x3);
}
}
/*-------------------------------------------------
RED CLIFF
-------------------------------------------------*/
READ16_MEMBER(md_rom_redcl_device::read)
{
if (offset == 0x400000/2) return 0x55 << 8;
if (offset == 0x400004/2) return -0x56 << 8;
return m_rom[offset];
}
/*-------------------------------------------------
ROCKMAN X3
-------------------------------------------------*/
READ16_MEMBER(md_rom_rx3_device::read_a13)
{
if (offset == 0)
return 0x0c;
else
return 0xffff;
}
/*-------------------------------------------------
SQUIRREL KING
-------------------------------------------------*/
READ16_MEMBER(md_rom_squir_device::read)
{
if ((offset >= 0x400000/2) && (offset < 0x400008/2))
return m_latch;
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_squir_device::write)
{
if (offset >= 0x400000/2 && offset < 0x400008/2)
m_latch = data;
}
/*-------------------------------------------------
SUPER MARIO BROS
-------------------------------------------------*/
READ16_MEMBER(md_rom_smb_device::read_a13)
{
if (offset == 0)
return 0x0c;
else
return 0xffff;
}
/*-------------------------------------------------
SUPER MARIO BROS 2
-------------------------------------------------*/
READ16_MEMBER(md_rom_smb2_device::read_a13)
{
if (offset == 0)
return 0x0a;
else
return 0xffff;
}
/*-------------------------------------------------
TOP FIGHTER
-------------------------------------------------*/
READ16_MEMBER(md_rom_topf_device::read)
{
//cpu #0 (PC=0004CBAE): unmapped program memory word read from 006A35D4 & 00FF -- wants regD7
if (offset == 0x645b44/2)
{
//cpu #0 (PC=0004DE00): unmapped program memory word write to 00689B80 = 004A & 00FF
//cpu #0 (PC=0004DE08): unmapped program memory word write to 00 = 00B5 & 00FF
//cpu #0 (PC=0004DE0C): unmapped program memory word read from 00645B44 & 00FF
return 0x9f;//0x25;
}
if (offset == 0x6bd294/2)
{
/*
cpu #0 (PC=00177192): unmapped program memory word write to 006BD240 = 00A8 & 00FF
cpu #0 (PC=0017719A): unmapped program memory word write to 006BD2D2 = 0098 & 00FF
cpu #0 (PC=001771A2): unmapped program memory word read from 006BD294 & 00FF
*/
if (space.device().safe_pc()==0x1771a2) return 0x50;
else
{
m_latch++;
logerror("%06x topfig_6BD294_r %04x\n",space.device().safe_pc(), m_latch);
return m_latch;
}
}
if (offset == 0x6f5344/2)
{
if (space.device().safe_pc()==0x4C94E)
return space.machine().device("maincpu")->state().state_int((M68K_D0)) & 0xff;
else
{
m_latch++;
logerror("%06x topfig_6F5344_r %04x\n", space.device().safe_pc(), m_latch);
return m_latch;
}
}
if (offset >= 0x20000/2 && offset < 0x28000/2)
return m_rom[offset + (m_bank[0] * 0x188000)/2];
if (offset >= 0x58000/2 && offset < 0x60000/2)
return m_rom[offset + (m_bank[1] * 0x20000)/2];
if (offset >= 0x60000/2 && offset < 0x68000/2)
return m_rom[offset + (m_bank[2] * 0x110000)/2];
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_topf_device::write)
{
if (offset >= 0x700000/2 && offset < 0x800000/2)
{
if (data == 0x002a)
m_bank[2] = 1; // == 0x2e*0x8000?!
else if (data==0x0035) // characters ingame
m_bank[0] = 1; // == 0x35*0x8000
else if (data==0x000f) // special moves
m_bank[1] = 1; // == 0xf*0x8000
else if (data==0x0000)
{
m_bank[0] = 0;
m_bank[1] = 0;
m_bank[2] = 0;
}
else
logerror("%06x offset %06x, data %04x\n", space.device().safe_pc(), offset, data);
}
}
/*-------------------------------------------------
RADICA TV GAMES [to be split...]
-------------------------------------------------*/
READ16_MEMBER(md_rom_radica_device::read)
{
return m_rom[m_bank * 0x10000/2 + offset];
}
READ16_MEMBER(md_rom_radica_device::read_a13)
{
if (offset < 0x80)
m_bank = offset & 0x3f;
return 0;
}

501
src/mess/machine/md_rom.h Normal file
View File

@ -0,0 +1,501 @@
#ifndef __MD_ROM_H
#define __MD_ROM_H
#include "machine/md_slot.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> md_std_rom_device
class md_std_rom_device : public device_t,
public device_md_cart_interface
{
public:
// construction/destruction
md_std_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_std_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start() {};
virtual void device_config_complete() { m_shortname = "md_std_rom"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read) { return m_rom[offset]; };
virtual DECLARE_WRITE16_MEMBER(write) { };
};
// ======================> md_rom_sram_device
class md_rom_sram_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_sram"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
virtual DECLARE_WRITE16_MEMBER(write_a13);
};
// ======================> md_rom_beggar_device
class md_rom_beggar_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_beggar_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_beggar"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
virtual DECLARE_WRITE16_MEMBER(write_a13);
};
// ======================> md_rom_fram_device
class md_rom_fram_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_fram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_fram"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_READ16_MEMBER(read_a13);
virtual DECLARE_WRITE16_MEMBER(write_a13);
};
// ======================> md_rom_ssf2_device
class md_rom_ssf2_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_ssf2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_ssf2"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write_a13);
private:
UINT8 m_bank[16];
int m_lastoff, m_lastdata;
};
// ======================> md_rom_mcpirate_device
class md_rom_mcpirate_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_mcpirate_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_mcpirate"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write_a13);
private:
UINT8 m_bank;
};
// ======================> md_rom_bugslife_device
class md_rom_bugslife_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_bugslife_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_bugslife"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read_a13);
};
// ======================> md_rom_chinf3_device
class md_rom_chinf3_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_chinf3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_chinf3"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
int m_bank;
};
// ======================> md_rom_elfwor_device
class md_rom_elfwor_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_elfwor_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_elfwor"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_kof98_device
class md_rom_kof98_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_kof98_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_kof98"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_kof99_device
class md_rom_kof99_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_kof99_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_kof99"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read_a13);
};
// ======================> md_rom_lion2_device
class md_rom_lion2_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_lion2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_lion2"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT16 m_prot1_data, m_prot2_data;
};
// ======================> md_rom_lion3_device
class md_rom_lion3_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_lion3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_lion3"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT8 m_prot_data, m_prot_cmd;
UINT16 m_bank;
};
// ======================> md_rom_mjlov_device
class md_rom_mjlov_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_mjlov_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_mjlov"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_pokestad_device
class md_rom_pokestad_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_pokestad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_pokestad"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT8 m_bank;
};
// ======================> md_rom_realtec_device
class md_rom_realtec_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_realtec_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_realtec"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT16 m_bank_addr, m_bank_size, m_old_bank_addr;
};
// ======================> md_rom_redcl_device
class md_rom_redcl_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_redcl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_redcl"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_rx3_device
class md_rom_rx3_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_rx3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_rx3"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read_a13);
};
// ======================> md_rom_sbubl_device
class md_rom_sbubl_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_sbubl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_sbubl"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_smb_device
class md_rom_smb_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_smb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_smb"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read_a13);
};
// ======================> md_rom_smb2_device
class md_rom_smb2_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_smb2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_smb2"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read_a13);
};
// ======================> md_rom_smouse_device
class md_rom_smouse_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_smouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_smouse"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_soulb_device
class md_rom_soulb_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_soulb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_config_complete() { m_shortname = "md_rom_soulb"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
};
// ======================> md_rom_squir_device
class md_rom_squir_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_squir_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_squir"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT16 m_latch;
};
// ======================> md_rom_topf_device
class md_rom_topf_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_topf_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_topf"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
UINT16 m_latch;
UINT8 m_bank[3];
};
// ======================> md_rom_radica_device
class md_rom_radica_device : public md_std_rom_device
{
public:
// construction/destruction
md_rom_radica_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_radica"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_READ16_MEMBER(read_a13);
private:
UINT8 m_bank;
};
// device type definition
extern const device_type MD_STD_ROM;
extern const device_type MD_ROM_SRAM;
extern const device_type MD_ROM_FRAM;
extern const device_type MD_ROM_BEGGAR;
extern const device_type MD_ROM_BUGSLIFE;
extern const device_type MD_ROM_CHINF3;
extern const device_type MD_ROM_ELFWOR;
extern const device_type MD_ROM_KOF98;
extern const device_type MD_ROM_KOF99;
extern const device_type MD_ROM_LION2;
extern const device_type MD_ROM_LION3;
extern const device_type MD_ROM_MCPIR;
extern const device_type MD_ROM_MJLOV;
extern const device_type MD_ROM_POKESTAD;
extern const device_type MD_ROM_REALTEC;
extern const device_type MD_ROM_REDCL;
extern const device_type MD_ROM_RX3;
extern const device_type MD_ROM_SBUBL;
extern const device_type MD_ROM_SMB;
extern const device_type MD_ROM_SMB2;
extern const device_type MD_ROM_SMOUSE;
extern const device_type MD_ROM_SOULB;
extern const device_type MD_ROM_SSF2;
extern const device_type MD_ROM_SQUIR;
extern const device_type MD_ROM_TOPF;
extern const device_type MD_ROM_RADICA;
// this are currently unused... protection is directly patched out!
extern const device_type MD_ROM_MULAN;
extern const device_type MD_ROM_POKE;
extern const device_type MD_ROM_POKE2;
#endif

90
src/mess/machine/md_sk.c Normal file
View File

@ -0,0 +1,90 @@
/***********************************************************************************************************
Sonic & Knuckles pass-thorugh cart emulation
TODO: currently we only support loading of base carts with no bankswitch or protection...
shall we support other as well?
***********************************************************************************************************/
#include "emu.h"
#include "machine/md_sk.h"
#include "machine/md_rom.h"
//-------------------------------------------------
// md_rom_device - constructor
//-------------------------------------------------
const device_type MD_ROM_SK = &device_creator<md_rom_sk_device>;
md_rom_sk_device::md_rom_sk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_exp(*this, "subslot")
{
}
md_rom_sk_device::md_rom_sk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MD_ROM_SK, "MD Sonic & Knuckles", tag, owner, clock),
device_md_cart_interface( mconfig, *this ),
m_exp(*this, "subslot")
{
}
void md_rom_sk_device::device_start()
{
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
READ16_MEMBER(md_rom_sk_device::read)
{
if (m_exp->m_cart != NULL && m_exp->m_cart->get_rom_base() != NULL && offset >= 0x200000/2 && offset < (0x200000 + m_exp->m_cart->get_rom_size())/2)
return m_exp->m_cart->m_rom[offset - 0x200000/2];
return m_rom[offset];
}
WRITE16_MEMBER(md_rom_sk_device::write)
{
// should there be anything here?
}
//-------------------------------------------------
// MACHINE_CONFIG_FRAGMENT( sk_slot )
//-------------------------------------------------
static SLOT_INTERFACE_START(sk_sub_cart)
SLOT_INTERFACE_INTERNAL("rom", MD_STD_ROM)
SLOT_INTERFACE_INTERNAL("rom_svp", MD_STD_ROM)
SLOT_INTERFACE_INTERNAL("rom_sram", MD_ROM_SRAM)
SLOT_INTERFACE_INTERNAL("rom_sramsafe", MD_ROM_SRAM)
SLOT_INTERFACE_INTERNAL("rom_fram", MD_ROM_FRAM)
// add all types??
SLOT_INTERFACE_END
static MACHINE_CONFIG_FRAGMENT( sk_slot )
MCFG_MDSUB_CARTRIDGE_ADD("subslot", sk_sub_cart, NULL, NULL)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor md_rom_sk_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( sk_slot );
}

34
src/mess/machine/md_sk.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef __MD_SK_H
#define __MD_SK_H
#include "machine/md_slot.h"
// ======================> md_rom_sk_device
class md_rom_sk_device : public device_t,
public device_md_cart_interface
{
public:
// construction/destruction
md_rom_sk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_rom_sk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_rom_sk"; }
virtual machine_config_constructor device_mconfig_additions() const;
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
private:
required_device<md_subcart_slot_device> m_exp;
};
// device type definition
extern const device_type MD_ROM_SK;
#endif

899
src/mess/machine/md_slot.c Normal file
View File

@ -0,0 +1,899 @@
/***********************************************************************************************************
MegaDrive cart emulation
(through slot devices)
The driver exposes address ranges
0x000000-0x7fffff to read/write (typically cart data, possibly banked, and some protection)
0x130000-0x1300ff to read_a13/write_a13 (typically SRAM toggling or protection)
0x150000-0x1500ff to read_a15/write_a15 (for SVP registers, not converted yet to slots)
currently available slot devices:
md_rom: standard carts + carts with NVRAM (SRAM/FRAM) + pirate carts with protection & bankswitch
md_eeprom: carts + I2C EEPROM (EEPROM device hooked up only, support to be completed)
md_jcart: Codemasters J-Cart & J-Cart+SEPROM (again, EEPROM device hooked up only, support to be completed)
md_sk: Sonic & Knuckles pass-thorugh cart (enables a second slot to mount any other cart)
md_stm95: cart + STM95 EEPROM (e.g. Pier Solar)
TODO: currently read access in 0x000000-0x7fffff are not masked (so we assume that no game attempts to
read beyond its ROM size). A regression test is pending to identify which games need this and mirror
them properly (Eke's doc states ROM data should be mirrored), but none of the ~120 games I tried
attempted that and a testcase would be appreciated
***********************************************************************************************************/
#include "emu.h"
#include "machine/md_slot.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type MD_CART_SLOT = &device_creator<md_cart_slot_device>;
const device_type PICO_CART_SLOT = &device_creator<pico_cart_slot_device>;
const device_type MD_SUBCART_SLOT = &device_creator<md_subcart_slot_device>;
//**************************************************************************
// MD cartridges Interface
//**************************************************************************
//-------------------------------------------------
// device_md_cart_interface - constructor
//-------------------------------------------------
device_md_cart_interface::device_md_cart_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device),
m_rom(NULL),
m_nvram(NULL),
m_rom_size(0),
m_nvram_size(0)
{
}
//-------------------------------------------------
// ~device_md_cart_interface - destructor
//-------------------------------------------------
device_md_cart_interface::~device_md_cart_interface()
{
}
//-------------------------------------------------
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
void device_md_cart_interface::rom_alloc(running_machine &machine, size_t size)
{
if (m_rom == NULL)
{
m_rom = auto_alloc_array_clear(machine, UINT16, size/sizeof(UINT16));
m_rom_size = size;
}
}
//-------------------------------------------------
// nvram_alloc - alloc the space for the nvram
//-------------------------------------------------
void device_md_cart_interface::nvram_alloc(running_machine &machine, size_t size)
{
if (m_nvram == NULL)
{
m_nvram = auto_alloc_array_clear(machine, UINT16, size/sizeof(UINT16));
m_nvram_size = size;
}
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// base_md_cart_slot_device - constructor
//-------------------------------------------------
base_md_cart_slot_device::base_md_cart_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, type, name, tag, owner, clock),
device_image_interface(mconfig, *this),
device_slot_interface(mconfig, *this),
m_type(SEGA_STD)
{
}
md_cart_slot_device::md_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
base_md_cart_slot_device(mconfig, MD_CART_SLOT, "MD Cartridge Slot", tag, owner, clock)
{
}
md_subcart_slot_device::md_subcart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
base_md_cart_slot_device(mconfig, MD_SUBCART_SLOT, "MD Cartridge SubSlot", tag, owner, clock)
{
}
pico_cart_slot_device::pico_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
base_md_cart_slot_device(mconfig, PICO_CART_SLOT, "Pico Cartridge Slot", tag, owner, clock)
{
}
//-------------------------------------------------
// base_md_cart_slot_device - destructor
//-------------------------------------------------
base_md_cart_slot_device::~base_md_cart_slot_device()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void base_md_cart_slot_device::device_start()
{
m_cart = dynamic_cast<device_md_cart_interface *>(get_card_device());
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void base_md_cart_slot_device::device_config_complete()
{
// set brief and instance name
update_names();
}
//-------------------------------------------------
// MD PCB
//-------------------------------------------------
struct md_slot
{
int pcb_id;
const char *slot_option;
};
// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
static const md_slot slot_list[] =
{
{ SEGA_SK, "rom_sk" },
{ SEGA_STD, "rom_svp"},
// { SEGA_SVP, "rom_svp"}, // not ready yet...
{ SEGA_SRAM, "rom_sram" },
{ SEGA_FRAM, "rom_fram" },
{ BEGGAR, "rom_beggar"},
{ SEGA_EEPROM, "rom_eeprom" },
{ NBA_JAM, "rom_nbajam" },
{ NBA_JAM_TE, "rom_nbajamte" },
{ NFL_QB_96, "rom_nflqb" },
{ C_SLAM, "rom_cslam" },
{ EA_NHLPA, "rom_nhlpa" },
{ BRIAN_LARA, "rom_blara" },
{ CM_JCART, "rom_jcart" },
{ CODE_MASTERS, "rom_codemast" },
{ CM_MM96, "rom_mm96" },
{ PSOLAR, "rom_stm95"},
{ SSF2, "rom_ssf2" },
{ RADICA, "rom_radica" },
// { GAME_KANDUME, "rom_gkand" }, // what's needed by this?
{ BUGSLIFE, "rom_bugs" },
{ CHINFIGHT3, "rom_chinf3" },
{ ELFWOR, "rom_elfwor" },
{ KAIJU, "rom_pokestad" },
{ KOF98, "rom_kof98" },
{ KOF99, "rom_kof99" },
{ LIONK2, "rom_lion2" },
{ LIONK3, "rom_lion3" },
{ MC_PIRATE, "rom_mcpir" },
{ MJLOVER, "rom_mjlov" },
{ MULAN, "rom_mulan"},
{ POKEMON, "rom_poke"},
{ POKEMON2, "rom_poke2"},
{ REALTEC, "rom_realtec" },
{ REDCL_EN, "rom_redcl" },
{ REDCLIFF, "rom_redcl" },
{ ROCKMANX3, "rom_rx3" },
{ SBUBBOB, "rom_sbubl" },
{ SMB, "rom_smb" },
{ SMB2, "rom_smb2" },
{ SMOUSE, "rom_smouse" },
{ SOULBLAD, "rom_soulblad" },
{ SQUIRRELK, "rom_squir" },
{ TOPFIGHTER, "rom_topf" },
{ SEGA_SRAM_FULLPATH, "rom_sram" },
{ SEGA_SRAM_FALLBACK, "rom_sramsafe" }
};
static int md_get_pcb_id(const char *slot)
{
for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
{
if (!mame_stricmp(slot_list[i].slot_option, slot))
return slot_list[i].pcb_id;
}
return SEGA_STD;
}
static const char *md_get_slot(int type)
{
for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
{
if (slot_list[i].pcb_id == type)
return slot_list[i].slot_option;
}
return "rom";
}
/*-------------------------------------------------
SRAM handling
-------------------------------------------------*/
/*-------------------------------------------------
call load
-------------------------------------------------*/
bool base_md_cart_slot_device::call_load()
{
if (m_cart)
{
m_type = SEGA_STD;
int res;
// STEP 1: load the file image and keep a copy for later banking
// STEP 2: identify the cart type
// The two steps are carried out differently if we are loading from a list or not
if (software_entry() == NULL)
res = load_nonlist();
else
res = load_list();
//printf("cart type: %d\n", m_type);
if (res == IMAGE_INIT_PASS)
{
// STEP 3: install memory handlers for this type of cart
setup_custom_mappers();
// STEP 4: take care of SRAM.
setup_nvram();
if (m_cart->get_nvram_size())
battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0xff);
}
return res;
}
return IMAGE_INIT_PASS;
}
int base_md_cart_slot_device::load_list()
{
UINT16 *ROM;
UINT32 length = get_software_region_length("rom");
const char *slot_name;
m_cart->rom_alloc(machine(), length);
ROM = m_cart->get_rom_base();
memcpy(ROM, get_software_region("rom"), length);
if ((slot_name = get_feature("slot")) == NULL)
m_type = SEGA_STD;
else
m_type = md_get_pcb_id(slot_name);
return IMAGE_INIT_PASS;
}
/*************************************
* Helper function: Detect SMD file
*************************************/
/* 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;
/* 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;
}
/*************************************
* Loading a cart image *not* from
* softlist
*************************************/
int base_md_cart_slot_device::load_nonlist()
{
unsigned char *ROM, *tmpROM;
UINT32 len = length();
// this contains an hack for SSF2: its current bankswitch code needs larger rom space to work
m_cart->rom_alloc(machine(), (len == 0x500000) ? 0x900000 : len);
ROM = (unsigned char *)m_cart->get_rom_base();
tmpROM = global_alloc_array(unsigned char, len);
// STEP 1: determine the file type (SMD? MD? BIN?)
fread(tmpROM, len);
/* is this a SMD file? */
if (genesis_is_SMD(&tmpROM[0x200], len))
{
mame_printf_debug("SMD!\n");
for (int ptr = 0; ptr < (len - 0x200) / 0x2000; ptr += 2)
{
for (int x = 0; x < 0x2000; x++)
{
*ROM++ = *(tmpROM + 0x200 + ((ptr + 1) * 0x2000) + x);
*ROM++ = *(tmpROM + 0x200 + ((ptr + 0) * 0x2000) + x);
}
}
len -= 0x200;
}
/* is this a MD file? */
else if ((tmpROM[0x80] == 'E') && (tmpROM[0x81] == 'A') && (tmpROM[0x82] == 'M' || tmpROM[0x82] == 'G'))
{
mame_printf_debug("MD!\n");
for (int ptr = 0; ptr < len; ptr += 2)
{
ROM[ptr] = tmpROM[(len >> 1) + (ptr >> 1)];
ROM[ptr + 1] = tmpROM[(ptr >> 1)];
}
}
/* BIN it is, then */
else
{
fseek(0, SEEK_SET);
fread(ROM, len);
}
global_free(tmpROM);
// STEP 2: determine the cart type (to deal with pirate mappers & eeprom)
m_type = get_cart_type(ROM, len);
#ifdef LSB_FIRST
unsigned char fliptemp;
// is this really needed nowadays?
for (int ptr = 0; ptr < len; ptr += 2)
{
fliptemp = ROM[ptr];
ROM[ptr] = ROM[ptr+1];
ROM[ptr+1] = fliptemp;
}
#endif
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
call_unloadload
-------------------------------------------------*/
void base_md_cart_slot_device::call_unload()
{
if (m_cart->get_nvram_size())
battery_save(m_cart->get_nvram_base(), m_cart->get_nvram_size());
}
void base_md_cart_slot_device::setup_custom_mappers()
{
UINT16 *ROM16 = m_cart->get_rom_base();
switch (m_type)
{
case SSF2:
// copy the image in 0x400000-0x900000 and keep the beginning for bankswitch
for (int x = 0x500000/2; x > 0; x--)
ROM16[x + 0x400000/2 - 1] = ROM16[x - 1];
for (int x = 0; x < 0x400000/2; x++)
ROM16[x] = ROM16[x + 0x400000/2];
break;
case REDCL_EN:
// decrypt
for (int x = 0; x < 0x200000/2; x++)
ROM16[x] = ROM16[x + 2] ^ 0x4040;
break;
// patch out protection in a bunch of titles...
case POKEMON:
/*todo: emulate protection instead
0dd19e:47f8
0dd1a0:fff0
0dd1a2:4e63
0dd46e:4ef8
0dd470:0300
0dd49c:6002
*/
/* you need to return 1 @ 0xa13002 and 0???1f @ 0xa1303e (it does word reads). */
ROM16[0x0dd19e/2] = 0x47f8;
ROM16[0x0dd1a0/2] = 0xfff0;
ROM16[0x0dd1a2/2] = 0x4e63;
ROM16[0x0dd46e/2] = 0x4ef8;
ROM16[0x0dd470/2] = 0x0300;
ROM16[0x0dd49c/2] = 0x6002;
break;
case POKEMON2:
/*todo: emulate protection instead
006036:e000
002540:6026
001ed0:6026
002476:6022
*/
ROM16[0x06036/2] = 0xe000;
ROM16[0x02540/2] = 0x6026;
ROM16[0x01ed0/2] = 0x6026;
ROM16[0x02476/2] = 0x6022;
ROM16[0x7e300/2] = 0x60fe;
break;
case MULAN:
/*todo: emulate protection instead
006036:e000
+more?
*/
// ROM16[0x01ed0/2] = 0xe000;
// ROM16[0x02540/2] = 0xe000;
ROM16[0x06036/2] = 0xe000;
break;
}
}
void base_md_cart_slot_device::setup_nvram()
{
UINT8 *ROM = (UINT8 *)m_cart->get_rom_base();
m_cart->m_nvram_readonly = 0;
m_cart->m_nvram_active = 0;
m_cart->m_nvram_handlers_installed = 0;
/* install SRAM & i2c handlers for the specific type of cart */
switch (m_type)
{
// These types only come from fullpath loading
case SEGA_SRAM_FULLPATH:
m_cart->m_nvram_start = (ROM[0x1b5] << 24 | ROM[0x1b4] << 16 | ROM[0x1b7] << 8 | ROM[0x1b6]);
m_cart->m_nvram_end = (ROM[0x1b9] << 24 | ROM[0x1b8] << 16 | ROM[0x1bb] << 8 | ROM[0x1ba]);
logerror("SRAM detected from header: starting location %X - SRAM Length %X\n", m_cart->m_nvram_start, m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
// We assume at most 64k of SRAM. is this correct?
if ((m_cart->m_nvram_start > m_cart->m_nvram_end) || ((m_cart->m_nvram_end - m_cart->m_nvram_start) >= 0x10000))
m_cart->m_nvram_end = m_cart->m_nvram_start + 0xffff;
if (m_cart->m_nvram_start & 1)
m_cart->m_nvram_start -= 1;
if (!(m_cart->m_nvram_end & 1))
m_cart->m_nvram_end += 1;
m_cart->nvram_alloc(machine(), m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
if (m_cart->m_rom_size <= m_cart->m_nvram_start)
m_cart->m_nvram_active = 1;
m_cart->m_nvram_handlers_installed = 1;
// don't trust too much header?
m_cart->m_nvram_start &= 0x3fffff;
m_cart->m_nvram_end &= 0x3fffff;
break;
case SEGA_SRAM_FALLBACK:
m_cart->m_nvram_start = 0x200000;
m_cart->m_nvram_end = m_cart->m_nvram_start + 0xffff;
m_cart->nvram_alloc(machine(), m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
if (m_cart->m_rom_size <= m_cart->m_nvram_start)
m_cart->m_nvram_active = 1;
break;
// These types only come from softlist loading
case SEGA_SRAM:
m_cart->m_nvram_start = 0x200000;
m_cart->m_nvram_end = m_cart->m_nvram_start + get_software_region_length("sram") - 1;
m_cart->nvram_alloc(machine(), m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
if (m_cart->m_rom_size <= m_cart->m_nvram_start)
m_cart->m_nvram_active = 1;
m_cart->m_nvram_handlers_installed = 1;
break;
case SEGA_FRAM:
m_cart->m_nvram_start = 0x200000;
m_cart->m_nvram_end = m_cart->m_nvram_start + get_software_region_length("fram") - 1;
m_cart->nvram_alloc(machine(), m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
m_cart->m_nvram_active = 1;
m_cart->m_nvram_handlers_installed = 1;
break;
// These types might come from both (pending proper id routines)
case BEGGAR:
m_cart->m_nvram_start = 0x400000;
m_cart->m_nvram_end = m_cart->m_nvram_start + 0xffff;
m_cart->nvram_alloc(machine(), m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
m_cart->m_nvram_active = 1;
m_cart->m_nvram_handlers_installed = 1;
break;
}
}
/*-------------------------------------------------
call softlist load
-------------------------------------------------*/
bool base_md_cart_slot_device::call_softlist_load(char *swlist, char *swname, rom_entry *start_entry)
{
load_software_part_region(this, swlist, swname, start_entry );
return TRUE;
}
int base_md_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len)
{
int type = SEGA_STD;
/* 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 (len)
{
case 0x80000:
if (!memcmp(&ROM[0x08c8], smouse_sig, sizeof(smouse_sig)))
type = SMOUSE;
if (!memcmp((char *)&ROM[0x7e30e], "SEGA", 4) ||
!memcmp((char *)&ROM[0x7e100], "SEGA", 4) ||
!memcmp((char *)&ROM[0x7e1e6], "SEGA", 4))
type = REALTEC;
if (!memcmp((char *)&ROM[0x0180], "GM T-50396", 10)) // NHLPA Hockey 93
type = EA_NHLPA;
if (!memcmp((char *)&ROM[0x0180], "GM MK-1215", 10)) // Evander Holyfield
type = SEGA_EEPROM;
break;
case 0xc0000:
if (!memcmp((char *)&ROM[0x0180], "GM G-4060 ", 8)) // Wonder Boy V
type = SEGA_EEPROM;
break;
case 0x100000:
if (!memcmp(&ROM[0x01b24], mjlover_sig, sizeof(mjlover_sig)))
type = MJLOVER;
if (!memcmp(&ROM[0x03b4], squir_sig, sizeof(squir_sig)))
type = SQUIRRELK;
if (!memcmp(&ROM[0xee0d0], bugsl_sig, sizeof(bugsl_sig)))
type = BUGSLIFE;
if (!memcmp((char *)&ROM[0x0172], "GAME : ELF WOR", 14))
type = ELFWOR;
if (!memcmp(&ROM[0x123e4], sbub_sig, sizeof(sbub_sig)))
type = SBUBBOB;
if (!memcmp((char *)&ROM[0x0180], "GM T-50176", 10)) // Rings of Power
type = EA_NHLPA;
if (!memcmp((char *)&ROM[0x0180], "MK 00001211-00", 14)) // Sports Talk Baseball
type = SEGA_EEPROM;
if (!memcmp((char *)&ROM[0x0180], "GM T-120096-", 12)) // Micro Machines 2
type = CODE_MASTERS;
if (!memcmp((char *)&ROM[0x0180], "GM T-120146-", 12)) // Brian Lara Cricket 96 / Shane Wayne Cricket 96
type = BRIAN_LARA;
if (!memcmp((char *)&ROM[0x0190], "OJKRPTBVFCA ", 0x10)) // Micro Machines '96 / Military TODO: better way to recognize these?
type = CODE_MASTERS;
break;
case 0x200000:
if (!memcmp(&ROM[0x18c6], lk3_sig, sizeof(lk3_sig)))
type = LIONK3;
if (!memcmp(&ROM[0x220], sdk_sig, sizeof(sdk_sig)))
type = LIONK3;
if (!memcmp(&ROM[0xce560], redcliff_sig, sizeof(redcliff_sig)))
type = REDCLIFF;
if (!memcmp(&ROM[0xc8cb0], smb_sig, sizeof(smb_sig)))
type = SMB;
if (!memcmp(&ROM[0xf24d6], smb2_sig, sizeof(smb2_sig)))
type = SMB2;
if (!memcmp(&ROM[0x674e], kaiju_sig, sizeof(kaiju_sig)))
type = KAIJU;
if (!memcmp(&ROM[0x1780], chifi3_sig, sizeof(chifi3_sig)))
type = CHINFIGHT3;
if (!memcmp(&ROM[0x03c2], lionk2_sig, sizeof(lionk2_sig)))
type = LIONK2;
if (!memcmp(&ROM[0xc8b90], rx3_sig, sizeof(rx3_sig)))
type = ROCKMANX3;
if (!memcmp(&ROM[0x56ae2], kof98_sig, sizeof(kof98_sig)))
type = KOF98;
if (!memcmp(&ROM[0x17bb2], s15in1_sig, sizeof(s15in1_sig)))
type = MC_PIRATE;
if (!memcmp((char *)&ROM[0x0180], "GM T-081326 ", 12)) // NBA Jam
type = NBA_JAM;
if (!memcmp((char *)&ROM[0x0180], "GM MK-1228", 10)) // Greatest Heavyweight of the Ring
type = SEGA_EEPROM;
if ((!memcmp((char *)&ROM[0x0180], "GM T-12046", 10)) || // Mega Man
(!memcmp((char *)&ROM[0x0180], "GM T-12053", 10) && !memcmp(&ROM[0x18e], rockman_sig, sizeof(rockman_sig)))) // / Rock Man (EEPROM version)
type = SEGA_EEPROM;
break;
case 0x200005:
if (!memcmp(&ROM[0xce564], redcl_en_sig, sizeof(redcliff_sig)))
type = REDCL_EN;
break;
case 0x300000:
if (!memcmp(&ROM[0x220], sdk_sig, sizeof(sdk_sig)))
type = LIONK3;
if (!memcmp(&ROM[0x1fd0d2], kof99_sig, sizeof(kof99_sig)))
type = KOF99;
if (!memcmp((char *)&ROM[0x0180], "GM T-81406", 10)) // NBA Jam TE
type = NBA_JAM_TE;
if (!memcmp((char *)&ROM[0x0180], "GM T-081276 ", 12)) // NFL Quarterback Club
type = NBA_JAM_TE;
break;
case 0x400000:
if (!memcmp(&ROM[0x3c031c], radica_sig, sizeof(radica_sig)) ||
!memcmp(&ROM[0x3f031c], radica_sig, sizeof(radica_sig))) // ssf+gng + radica vol1
type = RADICA;
if (!memcmp(&ROM[0x028460], soulb_sig, sizeof(soulb_sig)))
type = SOULBLAD;
if (!memcmp(&ROM[0x1e700], s19in1_sig, sizeof(s19in1_sig)))
type = MC_PIRATE;
if (!memcmp((char *)&ROM[0x0180], "GM T-081586-", 12)) // NFL Quarterback Club 96
type = NFL_QB_96;
if (!memcmp((char *)&ROM[0x0180], "GM T-081576 ", 12)) // College Slam
type = C_SLAM;
if (!memcmp((char *)&ROM[0x0180], "GM T-81476", 10)) // Big Hurt Baseball
type = C_SLAM;
break;
case 0x500000:
if (!memcmp((char *)&ROM[0x0120], "SUPER STREET FIGHTER2 ", 22))
type = SSF2;
break;
case 0x800000:
if (!memcmp((char *)&ROM[0x0180], "GM T-574023-", 12)) // Pier Solar
type = PSOLAR;
break;
default:
break;
}
//check for SRAM among the general carts
if (type == SEGA_STD)
{
// If the cart is not of a special type, we check the header for SRAM.
if (ROM[0x1b1] == 'R' && ROM[0x1b0] == 'A')
{
UINT32 start, end;
start = (ROM[0x1b5] << 24 | ROM[0x1b4] << 16 | ROM[0x1b7] << 8 | ROM[0x1b6]);
end = (ROM[0x1b9] << 24 | ROM[0x1b8] << 16 | ROM[0x1bb] << 8 | ROM[0x1ba]);
logerror("SRAM detected from header: starting location %X - SRAM Length %X\n", start, end - start + 1);
// For some games using serial EEPROM, difference between SRAM end to start is 0 or 1.
// Carts with EEPROM should have been already detected above, but better safe than sorry
if (end - start < 2)
type = SEGA_EEPROM;
else
type = SEGA_SRAM_FULLPATH;
}
else
{
// Unfortunately, there are ROMs without correct info in the header,
// Hence, when loading from fullpath we do the SRAM mapping anyway...
// but treat it in a custom way
type = SEGA_SRAM_FALLBACK;
}
}
return type;
}
/*-------------------------------------------------
get default card software
-------------------------------------------------*/
const char * base_md_cart_slot_device::get_default_card_software(const machine_config &config, emu_options &options)
{
const char *slot_string = "rom";
if (open_image_file(options))
{
UINT32 len = core_fsize(m_file);
UINT8 *ROM = global_alloc_array(UINT8, len);
int type;
core_fread(m_file, ROM, len);
type = get_cart_type(ROM, len);
slot_string = md_get_slot(type);
global_free(ROM);
clear();
return slot_string;
}
else
return software_get_default_slot(config, options, this, "rom");
}
/*-------------------------------------------------
read
-------------------------------------------------*/
READ16_MEMBER(base_md_cart_slot_device::read)
{
if (m_cart)
return m_cart->read(space, offset);
else
return 0xffff;
}
READ16_MEMBER(base_md_cart_slot_device::read_a13)
{
if (m_cart)
return m_cart->read_a13(space, offset);
else
return 0xffff;
}
READ16_MEMBER(base_md_cart_slot_device::read_a15)
{
if (m_cart)
return m_cart->read_a15(space, offset);
else
return 0xffff;
}
/*-------------------------------------------------
write
-------------------------------------------------*/
WRITE16_MEMBER(base_md_cart_slot_device::write)
{
if (m_cart)
m_cart->write(space, offset, data);
}
WRITE16_MEMBER(base_md_cart_slot_device::write_a13)
{
if (m_cart)
m_cart->write_a13(space, offset, data);
}
WRITE16_MEMBER(base_md_cart_slot_device::write_a15)
{
if (m_cart)
m_cart->write_a15(space, offset, data);
}

242
src/mess/machine/md_slot.h Normal file
View File

@ -0,0 +1,242 @@
#ifndef __MD_SLOT_H
#define __MD_SLOT_H
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
/* PCB */
enum
{
SEGA_STD = 0,
// Cart + Slot Expansion
SEGA_SK, /* Sonic & Knuckles pass-through cart */
// Cart + SVP
SEGA_SVP, /* Virtua Racing */
// Cart + NVRAM
SEGA_SRAM, SEGA_FRAM,
BEGGAR, /* Xin Qigai Wangzi uses different sram start address and has no valid header */
// EEPROM
SEGA_EEPROM, /* Wonder Boy V / Evander Holyfield's Boxing / Greatest Heavyweights of the Ring / Sports Talk Baseball / Megaman */
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 */
BRIAN_LARA, /* Brian Lara Cricket 96 */
PSOLAR, /* Pier Solar (STM95 EEPROM) */
// J-Cart
CM_JCART, /* Pete Sampras Tennis */
CODE_MASTERS, /* Micro Machines 2 / Military (J-Cart + SEPROM) */
CM_MM96, /* Micro Machines 96 (J-Cart + SEPROM, diff I2C model) */
// Various
SSF2, /* Super Street Fighter 2 */
GAME_KANDUME, /* Game no Kandume Otokuyou */
RADICA, /* Radica TV games.. these probably should be a separate driver since they are a separate 'console' */
BUGSLIFE, /* A Bug's Life */
CHINFIGHT3, /* Chinese Fighters 3 */
ELFWOR, /* Linghuan Daoshi Super Magician */
KAIJU, /* Pokemon Stadium */
KOF98, /* King of Fighters '98 */
KOF99, /* King of Fighters '99 */
LIONK2, /* Lion King 2 */
LIONK3, /* Lion King 3, Super Donkey Kong 99, Super King Kong 99 */
MC_PIRATE, /* Super 19 in 1, Super 15 in 1, 12 in 1 and a few more multicarts */
MJLOVER, /* Mahjong Lover */
MULAN, /* Hua Mu Lan - Mulan */
POKEMON, /* Pocket Monster */
POKEMON2, /* Pocket Monster 2 */
REALTEC, /* Whac a Critter/Mallet legend, Defend the Earth, Funnyworld/Ballonboy */
REDCLIFF, /* Romance of the Three Kingdoms - Battle of Red Cliffs, already decoded from .mdx format */
REDCL_EN, /* The encoded version... */
ROCKMANX3, /* Rockman X3 */
SBUBBOB, /* Super Bubble Bobble */
SMB, /* Super Mario Bros. */
SMB2, /* Super Mario Bros. 2 */
SMOUSE, /* Smart Mouse */
SOULBLAD, /* Soul Blade */
SQUIRRELK, /* Squirrel King */
TOPFIGHTER, /* Top Fighter 2000 MK VIII */
// when loading from fullpath, we need to treat SRAM in custom way
SEGA_SRAM_FULLPATH,
SEGA_SRAM_FALLBACK
};
// ======================> md_cart_interface
struct md_cart_interface
{
};
// ======================> device_md_cart_interface
class device_md_cart_interface : public device_slot_card_interface
{
public:
// construction/destruction
device_md_cart_interface(const machine_config &mconfig, device_t &device);
virtual ~device_md_cart_interface();
// reading and writing
virtual DECLARE_READ16_MEMBER(read) { return 0xffff; }
virtual DECLARE_WRITE16_MEMBER(write) {}
virtual DECLARE_READ16_MEMBER(read_a13) { return 0xffff; };
virtual DECLARE_WRITE16_MEMBER(write_a13) {};
virtual DECLARE_READ16_MEMBER(read_a15) { return 0xffff; };
virtual DECLARE_WRITE16_MEMBER(write_a15) {};
/* this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly */
virtual DECLARE_WRITE16_MEMBER(write_tmss_bank) { logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); };
virtual void rom_alloc(running_machine &machine, size_t size);
virtual void nvram_alloc(running_machine &machine, size_t size);
virtual UINT16* get_rom_base() { return m_rom; };
virtual UINT16* get_nvram_base() { return m_nvram; };
virtual UINT32 get_rom_size() { return m_rom_size; };
virtual UINT32 get_nvram_size() { return m_nvram_size; };
int m_nvram_start, m_nvram_end;
int m_nvram_active, m_nvram_readonly;
// when loading from fullpath, we create NVRAM even if not set in the header
// however in this case we access it only if the game turn it on
// the variable below is basically needed to track this...
int m_nvram_handlers_installed;
// internal state
UINT16 *m_rom;
UINT16 *m_nvram;
UINT32 m_rom_size;
UINT32 m_nvram_size;
};
// ======================> base_md_cart_slot_device
class base_md_cart_slot_device : public device_t,
public md_cart_interface,
public device_image_interface,
public device_slot_interface
{
public:
// construction/destruction
base_md_cart_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
virtual ~base_md_cart_slot_device();
// device-level overrides
virtual void device_start();
virtual void device_config_complete();
// image-level overrides
virtual bool call_load();
virtual void call_unload();
virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry);
virtual int load_list();
virtual int load_nonlist();
virtual int get_cart_type(UINT8 *ROM, UINT32 len);
virtual void setup_custom_mappers();
virtual void setup_nvram();
virtual iodevice_t image_type() const { return IO_CARTSLOT; }
virtual bool is_readable() const { return 1; }
virtual bool is_writeable() const { return 0; }
virtual bool is_creatable() const { return 0; }
virtual bool must_be_loaded() const { return 1; }
virtual bool is_reset_on_load() const { return 0; }
virtual const option_guide *create_option_guide() const { return NULL; }
// slot interface overrides
virtual const char * get_default_card_software(const machine_config &config, emu_options &options);
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_WRITE16_MEMBER(write);
virtual DECLARE_READ16_MEMBER(read_a13);
virtual DECLARE_WRITE16_MEMBER(write_a13);
virtual DECLARE_READ16_MEMBER(read_a15);
virtual DECLARE_WRITE16_MEMBER(write_a15);
// FIXME:
// this should be private, but then there is some problem installing delegates in the driver...
//private:
device_md_cart_interface* m_cart;
int m_type;
};
// ======================> md_cart_slot_device
class md_cart_slot_device : public base_md_cart_slot_device
{
public:
// construction/destruction
md_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual const char *image_interface() const { return "megadriv_cart"; }
virtual const char *file_extensions() const { return "smd,bin,md,gen"; }
};
// ======================> md_subcart_slot_device
class md_subcart_slot_device : public base_md_cart_slot_device
{
public:
// construction/destruction
md_subcart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual bool must_be_loaded() const { return 0; }
virtual const char *image_interface() const { return "megadriv_cart"; }
virtual const char *file_extensions() const { return "smd,bin,md,gen"; }
};
// ======================> pico_cart_slot_device
class pico_cart_slot_device : public base_md_cart_slot_device
{
public:
// construction/destruction
pico_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual const char *image_interface() const { return "pico_cart"; }
virtual const char *file_extensions() const { return "bin,md"; }
};
// device type definition
extern const device_type MD_CART_SLOT;
extern const device_type MD_SUBCART_SLOT; // needed to allow S&K pass-through to have non-mandatory cart
extern const device_type PICO_CART_SLOT;
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_MD_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot,_def_inp) \
MCFG_DEVICE_ADD(_tag, MD_CART_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp, false)
#define MCFG_MDSUB_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot,_def_inp) \
MCFG_DEVICE_ADD(_tag, MD_SUBCART_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp, false)
#define MCFG_PICO_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot,_def_inp) \
MCFG_DEVICE_ADD(_tag, PICO_CART_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp, false)
#endif

245
src/mess/machine/md_stm95.c Normal file
View File

@ -0,0 +1,245 @@
/***************************************************************************
MegaDrive / Genesis Cart + STM95 EEPROM device
Emulation by MetalliC, converted to slot by Fabio Priuli
TO DO: split STM95 to a separate device...
***************************************************************************/
#include "emu.h"
#include "machine/md_stm95.h"
void stm95_eeprom_device::set_cs_line(int state)
{
reset_line = state;
if (reset_line != CLEAR_LINE)
{
stream_pos = 0;
stm_state = IDLE;
}
}
void stm95_eeprom_device::set_si_line(int state)
{
latch = state;
}
int stm95_eeprom_device::get_so_line(void)
{
if (stm_state == READING || stm_state == CMD_RDSR)
return (stream_data >> 8) & 1;
else
return 0;
}
void stm95_eeprom_device::set_sck_line(int state)
{
if (reset_line == CLEAR_LINE)
{
if (state == ASSERT_LINE && sck_line == CLEAR_LINE)
{
switch (stm_state)
{
case IDLE:
stream_data = (stream_data << 1) | (latch ? 1 : 0);
stream_pos++;
if (stream_pos == 8)
{
stream_pos = 0;
//printf("STM95 EEPROM: got cmd %02X\n", stream_data&0xff);
switch(stream_data & 0xff)
{
case 0x01: // write status register
if (WEL != 0)
stm_state = CMD_WRSR;
WEL = 0;
break;
case 0x02: // write
if (WEL != 0)
stm_state = CMD_WRITE;
stream_data = 0;
WEL = 0;
break;
case 0x03: // read
stm_state = M95320_CMD_READ;
stream_data = 0;
break;
case 0x04: // write disable
WEL = 0;
break;
case 0x05: // read status register
stm_state = CMD_RDSR;
stream_data = WEL<<1;
break;
case 0x06: // write enable
WEL = 1;
break;
default:
logerror("STM95 EEPROM: unknown cmd %02X\n", stream_data&0xff);
}
}
break;
case CMD_WRSR:
stream_pos++; // just skip, don't care block protection
if (stream_pos == 8)
{
stm_state = IDLE;
stream_pos = 0;
}
break;
case CMD_RDSR:
stream_data = stream_data<<1;
stream_pos++;
if (stream_pos == 8)
{
stm_state = IDLE;
stream_pos = 0;
}
break;
case M95320_CMD_READ:
stream_data = (stream_data << 1) | (latch ? 1 : 0);
stream_pos++;
if (stream_pos == 16)
{
eeprom_addr = stream_data & (M95320_SIZE - 1);
stream_data = eeprom_data[eeprom_addr];
stm_state = READING;
stream_pos = 0;
}
break;
case READING:
stream_data = stream_data<<1;
stream_pos++;
if (stream_pos == 8)
{
if (++eeprom_addr == M95320_SIZE)
eeprom_addr = 0;
stream_data |= eeprom_data[eeprom_addr];
stream_pos = 0;
}
break;
case CMD_WRITE:
stream_data = (stream_data << 1) | (latch ? 1 : 0);
stream_pos++;
if (stream_pos == 16)
{
eeprom_addr = stream_data & (M95320_SIZE - 1);
stm_state = WRITING;
stream_pos = 0;
}
break;
case WRITING:
stream_data = (stream_data << 1) | (latch ? 1 : 0);
stream_pos++;
if (stream_pos == 8)
{
eeprom_data[eeprom_addr] = stream_data;
if (++eeprom_addr == M95320_SIZE)
eeprom_addr = 0;
stream_pos = 0;
}
break;
}
}
}
sck_line = state;
}
//-------------------------------------------------
// md_rom_device - constructor
//-------------------------------------------------
const device_type MD_EEPROM_STM95 = &device_creator<md_eeprom_stm95_device>;
md_eeprom_stm95_device::md_eeprom_stm95_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_md_cart_interface( mconfig, *this )
{
}
md_eeprom_stm95_device::md_eeprom_stm95_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MD_EEPROM_STM95, "MD Cart + EEPROM STM95", tag, owner, clock),
device_md_cart_interface( mconfig, *this )
{
}
void md_eeprom_stm95_device::device_start()
{
m_rdcnt = 0;
m_bank[0] = 0;
m_bank[1] = 0;
m_bank[2] = 0;
nvram_alloc(machine(), M95320_SIZE);
m_stm95.eeprom_data = (UINT8*)get_nvram_base();
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
READ16_MEMBER(md_eeprom_stm95_device::read)
{
if (offset == 0x0015e6/2 || offset == 0x0015e8/2)
{
// ugly hack until we don't know much about game protection
// first 3 reads from 15e6 return 0x00000010, then normal 0x00018010 value for crc check
UINT16 res;
offset -= 0x0015e6/2;
logerror("read 0x15e6 %d\n", m_rdcnt);
if (m_rdcnt < 6)
{
m_rdcnt++;
res = offset ? 0x10 : 0;
}
else
res = offset ? 0x8010 : 0x0001;
return res;
}
if (offset < 0x280000/2)
return m_rom[offset];
else // last 0x180000 are bankswitched
{
UINT8 bank = (offset - 0x280000/2) >> 18;
return m_rom[(offset & 0x7ffff/2) + (m_bank[bank] * 0x80000)/2];
}
}
READ16_MEMBER(md_eeprom_stm95_device::read_a13)
{
if (offset == 0x0a/2)
{
return m_stm95.get_so_line() & 1;
}
return 0xffff;
}
WRITE16_MEMBER(md_eeprom_stm95_device::write_a13)
{
if (offset == 0x00/2)
{
logerror("A13001 write %02x\n", data);
}
else if (offset < 0x08/2)
{
m_bank[offset - 1] = data & 0x0f;
}
else if (offset < 0x0a/2)
{
m_stm95.set_si_line(BIT(data, 0));
m_stm95.set_sck_line(BIT(data, 1));
m_stm95.set_halt_line(BIT(data, 2));
m_stm95.set_cs_line(BIT(data, 3));
}
}

View File

@ -0,0 +1,84 @@
#ifndef __MD_STM95_H
#define __MD_STM95_H
#include "machine/md_slot.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/* ST M95320 32Kbit serial EEPROM implementation */
// TO DO: STM95 should be made a separate EEPROM device and this should be merged with md_eeprom.c!
#define M95320_SIZE 0x1000
enum STMSTATE
{
IDLE = 0,
CMD_WRSR,
CMD_RDSR,
M95320_CMD_READ,
CMD_WRITE,
READING,
WRITING
};
class stm95_eeprom_device
{
public:
stm95_eeprom_device() :
stm_state(IDLE),
stream_pos(0)
{};
UINT8 *eeprom_data;
void set_cs_line(int);
void set_halt_line(int state) {}; // not implemented
void set_si_line(int);
void set_sck_line(int state);
int get_so_line(void);
protected:
int latch;
int reset_line;
int sck_line;
int WEL;
STMSTATE stm_state;
int stream_pos;
int stream_data;
int eeprom_addr;
};
// ======================> md_eeprom_stm95_device
class md_eeprom_stm95_device : public device_t,
public device_md_cart_interface
{
public:
// construction/destruction
md_eeprom_stm95_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
md_eeprom_stm95_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "md_eeprom_stm95"; }
// reading and writing
virtual DECLARE_READ16_MEMBER(read);
virtual DECLARE_READ16_MEMBER(read_a13);
virtual DECLARE_WRITE16_MEMBER(write_a13);
private:
UINT8 m_bank[3];
int m_rdcnt;
stm95_eeprom_device m_stm95;
};
// device type definition
extern const device_type MD_EEPROM_STM95;
#endif

View File

@ -1,11 +1,6 @@
/* Megadrive SVP emulation (Virtua Racing) */ /* Megadrive SVP emulation (Virtua Racing) */
#include "includes/megadriv.h" #include "includes/md.h"
/* SVP (virtua racing) */
cpu_device *_svp_cpu;
/****************************************** SVP related *****************************************/ /****************************************** SVP related *****************************************/
@ -65,15 +60,15 @@ static UINT32 pm_io(address_space &space, int reg, int write, UINT32 d)
state->m_emu_status &= ~SSP_PMC_SET; state->m_emu_status &= ~SSP_PMC_SET;
return 0; return 0;
} }
// just in case // just in case
if (state->m_emu_status & SSP_PMC_HAVE_ADDR) { if (state->m_emu_status & SSP_PMC_HAVE_ADDR) {
state->m_emu_status &= ~SSP_PMC_HAVE_ADDR; state->m_emu_status &= ~SSP_PMC_HAVE_ADDR;
} }
if (reg == 4 || (space.device().state().state_int(SSP_ST) & 0x60)) if (reg == 4 || (space.device().state().state_int(SSP_ST) & 0x60))
{ {
#define CADDR ((((mode<<16)&0x7f0000)|addr)<<1) #define CADDR ((((mode<<16)&0x7f0000)|addr)<<1)
UINT16 *dram = (UINT16 *)state->m_dram; UINT16 *dram = (UINT16 *)state->m_dram;
if (write) if (write)
{ {
@ -83,14 +78,14 @@ static UINT32 pm_io(address_space &space, int reg, int write, UINT32 d)
{ {
int inc = get_inc(mode); int inc = get_inc(mode);
if (mode & 0x0400) { if (mode & 0x0400) {
overwrite_write(&dram[addr], d); overwrite_write(&dram[addr], d);
} else dram[addr] = d; } else dram[addr] = d;
state->m_pmac_write[reg] += inc; state->m_pmac_write[reg] += inc;
} }
else if ((mode & 0xfbff) == 0x4018) // DRAM, cell inc else if ((mode & 0xfbff) == 0x4018) // DRAM, cell inc
{ {
if (mode & 0x0400) { if (mode & 0x0400) {
overwrite_write(&dram[addr], d); overwrite_write(&dram[addr], d);
} else dram[addr] = d; } else dram[addr] = d;
state->m_pmac_write[reg] += (addr&1) ? 31 : 1; state->m_pmac_write[reg] += (addr&1) ? 31 : 1;
} }
@ -103,7 +98,7 @@ static UINT32 pm_io(address_space &space, int reg, int write, UINT32 d)
else else
{ {
logerror("ssp FIXME: PM%i unhandled write mode %04x, [%06x] %04x\n", logerror("ssp FIXME: PM%i unhandled write mode %04x, [%06x] %04x\n",
reg, mode, CADDR, d); reg, mode, CADDR, d);
} }
} }
else else
@ -125,17 +120,17 @@ static UINT32 pm_io(address_space &space, int reg, int write, UINT32 d)
else else
{ {
logerror("ssp FIXME: PM%i unhandled read mode %04x, [%06x]\n", logerror("ssp FIXME: PM%i unhandled read mode %04x, [%06x]\n",
reg, mode, CADDR); reg, mode, CADDR);
d = 0; d = 0;
} }
} }
// PMC value corresponds to last PMR accessed (not sure). // PMC value corresponds to last PMR accessed (not sure).
state->m_pmc.d = state->m_pmac_read[write ? reg + 6 : reg]; state->m_pmc.d = state->m_pmac_read[write ? reg + 6 : reg];
return d; return d;
} }
return (UINT32)-1; return (UINT32)-1;
} }
@ -192,7 +187,7 @@ static READ16_HANDLER( read_XST )
mdsvp_state *state = space.machine().driver_data<mdsvp_state>(); mdsvp_state *state = space.machine().driver_data<mdsvp_state>();
UINT32 d = pm_io(space, 3, 0, 0); UINT32 d = pm_io(space, 3, 0, 0);
if (d != (UINT32)-1) return d; if (d != (UINT32)-1) return d;
return state->m_XST; return state->m_XST;
} }
@ -201,7 +196,7 @@ static WRITE16_HANDLER( write_XST )
mdsvp_state *state = space.machine().driver_data<mdsvp_state>(); mdsvp_state *state = space.machine().driver_data<mdsvp_state>();
UINT32 r = pm_io(space, 3, 1, data); UINT32 r = pm_io(space, 3, 1, data);
if (r != (UINT32)-1) return; if (r != (UINT32)-1) return;
state->m_XST2 |= 1; state->m_XST2 |= 1;
state->m_XST = data; state->m_XST = data;
} }
@ -261,10 +256,10 @@ static READ16_HANDLER( svp_68k_io_r )
UINT32 d; UINT32 d;
switch (offset) switch (offset)
{ {
// 0xa15000, 0xa15002 // 0xa15000, 0xa15002
case 0: case 0:
case 1: return state->m_XST; case 1: return state->m_XST;
// 0xa15004 // 0xa15004
case 2: d = state->m_XST2; state->m_XST2 &= ~1; return d; case 2: d = state->m_XST2; state->m_XST2 &= ~1; return d;
default: logerror("unhandled SVP reg read @ %x\n", offset<<1); default: logerror("unhandled SVP reg read @ %x\n", offset<<1);
} }
@ -276,10 +271,10 @@ static WRITE16_HANDLER( svp_68k_io_w )
mdsvp_state *state = space.machine().driver_data<mdsvp_state>(); mdsvp_state *state = space.machine().driver_data<mdsvp_state>();
switch (offset) switch (offset)
{ {
// 0xa15000, 0xa15002 // 0xa15000, 0xa15002
case 0: case 0:
case 1: state->m_XST = data; state->m_XST2 |= 2; break; case 1: state->m_XST = data; state->m_XST2 |= 2; break;
// 0xa15006 // 0xa15006
case 3: break; // possibly halts SSP1601 case 3: break; // possibly halts SSP1601
default: logerror("unhandled SVP reg write %04x @ %x\n", data, offset<<1); default: logerror("unhandled SVP reg write %04x @ %x\n", data, offset<<1);
} }
@ -320,20 +315,9 @@ ADDRESS_MAP_START( svp_ext_map, AS_IO, 16, driver_device )
ADDRESS_MAP_END ADDRESS_MAP_END
/* emulate testmode plug */
static UINT8 megadrive_io_read_data_port_svp(running_machine &machine, int portnum)
{
if (portnum == 0 && machine.root_device().ioport("MEMORY_TEST")->read_safe(0x00))
{
return (megadrive_io_data_regs[0] & 0xc0);
}
return megadrive_io_read_data_port_3button(machine, portnum);
}
static READ16_HANDLER( svp_speedup_r ) static READ16_HANDLER( svp_speedup_r )
{ {
space.device().execute().spin_until_time(attotime::from_usec(100)); space.device().execute().spin_until_time(attotime::from_usec(100));
return 0x0425; return 0x0425;
} }
@ -341,8 +325,8 @@ static READ16_HANDLER( svp_speedup_r )
void svp_init(running_machine &machine) void svp_init(running_machine &machine)
{ {
mdsvp_state *state = machine.driver_data<mdsvp_state>(); mdsvp_state *state = machine.driver_data<mdsvp_state>();
UINT8 *ROM; UINT8 *ROM = state->memregion("maincpu")->base();
memset(state->m_pmac_read, 0, ARRAY_LENGTH(state->m_pmac_read)); memset(state->m_pmac_read, 0, ARRAY_LENGTH(state->m_pmac_read));
memset(state->m_pmac_write, 0, ARRAY_LENGTH(state->m_pmac_write)); memset(state->m_pmac_write, 0, ARRAY_LENGTH(state->m_pmac_write));
state->m_pmc.d = 0; state->m_pmc.d = 0;
@ -351,7 +335,7 @@ void svp_init(running_machine &machine)
state->m_emu_status = 0; state->m_emu_status = 0;
state->m_XST = 0; state->m_XST = 0;
state->m_XST2 = 0; state->m_XST2 = 0;
/* SVP stuff */ /* SVP stuff */
state->m_dram = auto_alloc_array(machine, UINT8, 0x20000); state->m_dram = auto_alloc_array(machine, UINT8, 0x20000);
machine.device("maincpu")->memory().space(AS_PROGRAM).install_ram(0x300000, 0x31ffff, state->m_dram); machine.device("maincpu")->memory().space(AS_PROGRAM).install_ram(0x300000, 0x31ffff, state->m_dram);
@ -359,14 +343,14 @@ void svp_init(running_machine &machine)
// "cell arrange" 1 and 2 // "cell arrange" 1 and 2
machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x390000, 0x39ffff, FUNC(svp_68k_cell1_r)); machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x390000, 0x39ffff, FUNC(svp_68k_cell1_r));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x3a0000, 0x3affff, FUNC(svp_68k_cell2_r)); machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x3a0000, 0x3affff, FUNC(svp_68k_cell2_r));
machine.device("svp")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x438, 0x438, FUNC(svp_speedup_r)); machine.device("svp")->memory().space(AS_PROGRAM).install_legacy_read_handler(0x438, 0x438, FUNC(svp_speedup_r));
if (state->m_slotcart->m_cart->get_rom_base() != NULL)
memcpy(ROM, state->m_slotcart->m_cart->get_rom_base(), state->m_slotcart->m_cart->get_rom_size());
state->m_iram = auto_alloc_array(machine, UINT8, 0x800); state->m_iram = auto_alloc_array(machine, UINT8, 0x800);
state->membank("bank3")->set_base(state->m_iram); state->membank("bank3")->set_base(state->m_iram);
/* SVP ROM just shares m68k region.. */ /* SVP ROM just shares m68k region.. */
ROM = state->memregion("maincpu")->base();
state->membank("bank4")->set_base(ROM + 0x800); state->membank("bank4")->set_base(ROM + 0x800);
megadrive_io_read_data_port_ptr = megadrive_io_read_data_port_svp;
} }

View File

@ -455,7 +455,6 @@ $(MESSOBJ)/mame.a: \
$(MAME_MACHINE)/megacd.o \ $(MAME_MACHINE)/megacd.o \
$(MAME_MACHINE)/megacdcd.o \ $(MAME_MACHINE)/megacdcd.o \
$(MAME_MACHINE)/mega32x.o \ $(MAME_MACHINE)/mega32x.o \
$(MAME_MACHINE)/megasvp.o \
$(MAME_MACHINE)/megavdp.o \ $(MAME_MACHINE)/megavdp.o \
$(MAME_MACHINE)/dc.o \ $(MAME_MACHINE)/dc.o \
$(MAME_DRIVERS)/naomi.o \ $(MAME_DRIVERS)/naomi.o \
@ -1617,7 +1616,13 @@ $(MESSOBJ)/sanyo.a: \
$(MESSOBJ)/sega.a: \ $(MESSOBJ)/sega.a: \
$(MESS_DRIVERS)/sg1000.o \ $(MESS_DRIVERS)/sg1000.o \
$(MAME_MACHINE)/md_cart.o \ $(MESS_MACHINE)/md_slot.o \
$(MESS_MACHINE)/md_rom.o \
$(MESS_MACHINE)/md_sk.o \
$(MESS_MACHINE)/md_eeprom.o \
$(MESS_MACHINE)/md_jcart.o \
$(MESS_MACHINE)/md_stm95.o \
$(MESS_MACHINE)/megasvp.o \
$(MESS_DRIVERS)/megadriv.o \ $(MESS_DRIVERS)/megadriv.o \
$(MESS_DRIVERS)/dccons.o \ $(MESS_DRIVERS)/dccons.o \
$(MAME_MACHINE)/gdrom.o \ $(MAME_MACHINE)/gdrom.o \