summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Fabio Priuli <etabeta78@users.noreply.github.com>2013-03-13 08:05:41 +0000
committer Fabio Priuli <etabeta78@users.noreply.github.com>2013-03-13 08:05:41 +0000
commite4e14a06b23481d604ce74e150a00e7489bbfab6 (patch)
treeebc502eecda408e4ad74dc6db1911dac9030785c /src
parent2c7f75772cc3034f1f48117822dbe8e60e35ee81 (diff)
(MESS) snes.c: misc work on pirate carts. [Fabio Priuli]
- added support for Korean Super 20 Collection multigame cart, even if a few games still have glitches. - added support for bankswitch mechanism used in a few pirate multigame carts. - added support for protection used by Tekken 2 and Street Fighter Alpha EX, based on notes by d4s and nocash. (MESS) snes.xml: added a few pirate multigame carts. Most of these are incomplete dumps, so redumps are needed to promote them to working state, but their existence is now at least documented. [Fabio Priuli] out of whatsnew: I also have fixed sram issue from fullpath in snesnew driver, due to a silly copy&paste mistake.
Diffstat (limited to 'src')
-rw-r--r--src/mess/drivers/snes.c120
-rw-r--r--src/mess/machine/sns_rom.c344
-rw-r--r--src/mess/machine/sns_rom.h167
-rw-r--r--src/mess/machine/sns_slot.c11
-rw-r--r--src/mess/machine/sns_slot.h7
5 files changed, 589 insertions, 60 deletions
diff --git a/src/mess/drivers/snes.c b/src/mess/drivers/snes.c
index cddcaa6ea9a..b5bf8cffd63 100644
--- a/src/mess/drivers/snes.c
+++ b/src/mess/drivers/snes.c
@@ -1616,7 +1616,18 @@ READ8_MEMBER( snsnew_state::snes20_hi_r )
else if (m_slotcart->get_type() == SNES_CX4
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000)) // hack until we emulate the real CPU
return CX4_read((offset & 0xffff) - 0x6000);
-
+ else if (m_slotcart->get_type() == SNES_BANANA
+ && (offset & 0x78000) == 0x8000)
+ {
+ return m_slotcart->m_cart->chip_read(space, offset);
+ }
+ else if (m_slotcart->get_type() == SNES_BUGS
+ && (offset & 0x7f000) == 0xf000)
+ {
+ printf("read hi addr %X\n", offset);
+// return m_slotcart->m_cart->chip_read(space, offset);
+ }
+
if (offset < 0x400000)
{
if (address < 0x2000)
@@ -1676,7 +1687,20 @@ WRITE8_MEMBER( snsnew_state::snes20_hi_w )
else if (m_type == SNES_SUFAMITURBO
&& address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
{ m_slotcart->m_cart->write_h(space, offset, data); return; }
-
+// else if (m_slotcart->get_type() == SNES_BANANA
+// && (offset & 0x8000) == 0x8000)
+// {
+// printf("write addr hi %X data %X\n", offset, data);
+// m_slotcart->m_cart->chip_write(space, offset, data);
+// return;
+// }
+ else if (m_slotcart->get_type() == SNES_BUGS
+ && (offset & 0x7f000) == 0xf000)
+ {
+// printf("write hi addr %X data %X\n", offset, data);
+ }
+
+
if (offset < 0x400000)
{
if (address < 0x2000)
@@ -1711,7 +1735,14 @@ READ8_MEMBER( snsnew_state::snes20_lo_r )
else if (m_slotcart->get_type() == SNES_CX4
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000)) // hack until we emulate the real CPU
return CX4_read((offset & 0xffff) - 0x6000);
-
+ else if (m_slotcart->get_type() == SNES_BUGS
+ && (offset & 0x78000) == 0x8000)
+ {
+// printf("read lo addr %X\n", offset);
+// return m_slotcart->m_cart->chip_read(space, offset);
+ }
+
+
if (offset < 0x400000)
{
if (address < 0x2000)
@@ -1759,14 +1790,22 @@ WRITE8_MEMBER( snsnew_state::snes20_lo_w )
if (m_type == SNES_SUFAMITURBO
&& (offset & 0xffff) >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
{ m_slotcart->m_cart->write_l(space, offset, data); return; }
+ else if (m_slotcart->get_type() == SNES_20COL
+ && offset >= 0x8000 && offset < 0x9000)
+ { m_slotcart->m_cart->chip_write(space, offset, data); return; }
else if (m_slotcart->get_type() == SNES_BANANA
- && (offset & 0x78000) == 0x8000)
+ && (offset & 0x8000) == 0x8000)
{
-// printf("lo write %x\n", offset);
+ printf("write addr lo %X data %X\n", offset, data);
m_slotcart->m_cart->chip_write(space, offset, data);
return;
}
-
+ else if (m_slotcart->get_type() == SNES_BUGS
+ && (offset & 0x78000) == 0x8000)
+ {
+// printf("write lo addr %X data %X\n", offset, data);
+ }
+
// other add-on writes matches the hi handler
snes20_hi_w(space, offset, data, 0xff);
}
@@ -2280,6 +2319,13 @@ static SLOT_INTERFACE_START(snes_cart)
SLOT_INTERFACE_INTERNAL("bsxrom", SNS_ROM_BSX) // BS-X base cart - partial support only
// pirate carts
SLOT_INTERFACE_INTERNAL("lorom_poke", SNS_LOROM_POKEMON)
+ SLOT_INTERFACE_INTERNAL("lorom_tekken2", SNS_LOROM_TEKKEN2)
+ SLOT_INTERFACE_INTERNAL("lorom_sbld", SNS_LOROM_SOULBLAD)
+ SLOT_INTERFACE_INTERNAL("lorom_mcpir1", SNS_LOROM_MCPIR1)
+ SLOT_INTERFACE_INTERNAL("lorom_mcpir2", SNS_LOROM_MCPIR2)
+ SLOT_INTERFACE_INTERNAL("lorom_20col", SNS_LOROM_20COL)
+ SLOT_INTERFACE_INTERNAL("lorom_pija", SNS_LOROM_BANANA) // not working yet
+ SLOT_INTERFACE_INTERNAL("lorom_bugs", SNS_LOROM_BUGSLIFE) // not working yet
SLOT_INTERFACE_END
@@ -2294,19 +2340,14 @@ static MACHINE_START( snesnew )
// in progress...
switch (state->m_type)
{
+ // LoROM & LoROM + addons
case SNES_MODE20:
case SNES_BSXLO:
case SNES_SUFAMITURBO:
- case SNES_BANANA:
case SNES_CX4: // this still uses the old simulation instead of emulating the CPU
case SNES_ST010: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w
case SNES_ST011: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w
break;
- case SNES_POKEMON:
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x800000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x800000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
-// set_5a22_map(*state->m_maincpu);
- break;
case SNES_DSP:
machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x208000, 0x20ffff, 0, 0x9f0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x208000, 0x20ffff, 0, 0x9f0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
@@ -2323,6 +2364,22 @@ static MACHINE_START( snesnew )
machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0xbf0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0xbf0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
break;
+ case SNES_SFX:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessfx_lo_r),state), write8_delegate(FUNC(snsnew_state::snessfx_lo_w),state));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessfx_hi_r),state), write8_delegate(FUNC(snsnew_state::snessfx_hi_w),state));
+ set_5a22_map(*state->m_maincpu);
+ break;
+ case SNES_SDD1:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessdd1_lo_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_lo_w),state));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessdd1_hi_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_hi_w),state));
+ set_5a22_map(*state->m_maincpu);
+ break;
+ case SNES_BSX:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snesbsx_lo_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_lo_w),state));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snesbsx_hi_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_hi_w),state));
+ set_5a22_map(*state->m_maincpu);
+ break;
+ // HiROM & HiROM + addons
case SNES_MODE21:
case SNES_BSXHI:
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
@@ -2343,26 +2400,39 @@ static MACHINE_START( snesnew )
machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0, 0xbf0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
set_5a22_map(*state->m_maincpu);
break;
- case SNES_SFX:
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessfx_lo_r),state), write8_delegate(FUNC(snsnew_state::snessfx_lo_w),state));
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessfx_hi_r),state), write8_delegate(FUNC(snsnew_state::snessfx_hi_w),state));
- set_5a22_map(*state->m_maincpu);
- break;
case SNES_SPC7110:
case SNES_SPC7110_RTC:
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes7110_lo_r),state), write8_delegate(FUNC(snsnew_state::snes7110_lo_w),state));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes7110_hi_r),state), write8_delegate(FUNC(snsnew_state::snes7110_hi_w),state));
set_5a22_map(*state->m_maincpu);
break;
- case SNES_SDD1:
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessdd1_lo_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_lo_w),state));
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessdd1_hi_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_hi_w),state));
- set_5a22_map(*state->m_maincpu);
+ // pirate 'mappers'
+ case SNES_POKEMON:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x800000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x800000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
break;
- case SNES_BSX:
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snesbsx_lo_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_lo_w),state));
- machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snesbsx_hi_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_hi_w),state));
- set_5a22_map(*state->m_maincpu);
+ case SNES_TEKKEN2:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x8087ff, 0, 0x3f0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x8087ff, 0, 0x3f0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
+ break;
+ case SNES_MCPIR1:
+ case SNES_MCPIR2:
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0xffff00, 0xffffff, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
+ break;
+ case SNES_20COL:
+ // why is this not working? investigate...
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x008000, 0x008fff, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
+ break;
+ case SNES_SOULBLAD:
+ // reads from xxx0-xxx3in range [80-bf] return a fixed sequence of 4bits; reads in range [c0-ff] return open bus
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x808003, 0, 0x3f7ff0, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
+ machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0xc00000, 0xffffff, FUNC(snes_open_bus_r));
+ break;
+ case SNES_BUGS:
+ case SNES_BANANA:
+// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
+// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
+// set_5a22_map(*state->m_maincpu);
break;
}
}
diff --git a/src/mess/machine/sns_rom.c b/src/mess/machine/sns_rom.c
index 1bcc7208709..084de845738 100644
--- a/src/mess/machine/sns_rom.c
+++ b/src/mess/machine/sns_rom.c
@@ -20,6 +20,14 @@ const device_type SNS_LOROM = &device_creator<sns_rom_device>;
const device_type SNS_LOROM_OBC1 = &device_creator<sns_rom_obc1_device>;
// LoROM pirate carts with protection
const device_type SNS_LOROM_POKEMON = &device_creator<sns_rom_pokemon_device>;
+const device_type SNS_LOROM_TEKKEN2 = &device_creator<sns_rom_tekken2_device>;
+const device_type SNS_LOROM_SOULBLAD = &device_creator<sns_rom_soulblad_device>;
+const device_type SNS_LOROM_BANANA = &device_creator<sns_rom_banana_device>;
+const device_type SNS_LOROM_BUGSLIFE = &device_creator<sns_rom_bugs_device>;
+// LoROM pirate multicarts
+const device_type SNS_LOROM_MCPIR1 = &device_creator<sns_rom_mcpirate1_device>;
+const device_type SNS_LOROM_MCPIR2 = &device_creator<sns_rom_mcpirate2_device>;
+const device_type SNS_LOROM_20COL = &device_creator<sns_rom_20col_device>;
sns_rom_device::sns_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
@@ -34,29 +42,58 @@ sns_rom_device::sns_rom_device(const machine_config &mconfig, const char *tag, d
{
}
+sns_rom_obc1_device::sns_rom_obc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_OBC1, "SNES Cart (LoROM) + OBC-1", tag, owner, clock)
+{
+}
+
+
+
+// Pirate LoROM 'mappers'
sns_rom_pokemon_device::sns_rom_pokemon_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sns_rom_device(mconfig, SNS_LOROM_POKEMON, "SNES Pirate Carts with Protection", tag, owner, clock)
{
}
-sns_rom_obc1_device::sns_rom_obc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : sns_rom_device(mconfig, SNS_LOROM_OBC1, "SNES Cart (LoROM) + OBC-1", tag, owner, clock)
+sns_rom_tekken2_device::sns_rom_tekken2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_TEKKEN2, "SNES Pirate Carts with Protection", tag, owner, clock)
{
}
+sns_rom_soulblad_device::sns_rom_soulblad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_SOULBLAD, "SNES Pirate Carts with Protection", tag, owner, clock)
+{
+}
-void sns_rom_device::device_start()
+sns_rom_banana_device::sns_rom_banana_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_BANANA, "SNES Pirate Carts with Protection", tag, owner, clock)
{
}
-void sns_rom_pokemon_device::device_start()
+sns_rom_bugs_device::sns_rom_bugs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_BUGSLIFE, "SNES Pirate Carts with Protection", tag, owner, clock)
{
- save_item(NAME(m_latch));
}
-void sns_rom_pokemon_device::device_reset()
+// Multigame LoROM 'mappers'
+sns_rom_mcpirate1_device::sns_rom_mcpirate1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_MCPIR1, "SNES Pirate Multigame Carts Type 1", tag, owner, clock)
+{
+}
+
+sns_rom_mcpirate2_device::sns_rom_mcpirate2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_MCPIR2, "SNES Pirate Multigame Carts Type 2", tag, owner, clock)
+{
+}
+
+sns_rom_20col_device::sns_rom_20col_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sns_rom_device(mconfig, SNS_LOROM_20COL, "SNES Super 20 Collection", tag, owner, clock)
+{
+}
+
+
+void sns_rom_device::device_start()
{
- m_latch = 0;
}
void sns_rom_obc1_device::device_start()
@@ -77,35 +114,81 @@ void sns_rom_obc1_device::device_reset()
}
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+void sns_rom_pokemon_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
-READ8_MEMBER(sns_rom_device::read_l)
+void sns_rom_pokemon_device::device_reset()
{
- return read_h(space, offset);
+ m_latch = 0;
}
-READ8_MEMBER(sns_rom_device::read_h)
+void sns_rom_tekken2_device::device_start()
{
- int bank = offset / 0x10000;
- return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
+ save_item(NAME(m_prot));
+}
+
+void sns_rom_tekken2_device::device_reset()
+{
+ m_prot = 0;
+}
+
+void sns_rom_bugs_device::device_start()
+{
+ save_item(NAME(m_latch));
}
+void sns_rom_bugs_device::device_reset()
+{
+ memset(m_latch, 0, sizeof(m_latch));
+}
-// Lo-ROM + Protection device
-READ8_MEMBER( sns_rom_pokemon_device::chip_read )
+void sns_rom_mcpirate1_device::device_start()
{
- return BITSWAP8(m_latch,0,6,7,1,2,3,4,5);
+ save_item(NAME(m_base_bank));
}
-WRITE8_MEMBER( sns_rom_pokemon_device::chip_write )
+void sns_rom_mcpirate1_device::device_reset()
{
- m_latch = data;
+ m_base_bank = 0;
}
+void sns_rom_mcpirate2_device::device_start()
+{
+ save_item(NAME(m_base_bank));
+}
+
+void sns_rom_mcpirate2_device::device_reset()
+{
+ m_base_bank = 0;
+}
+
+void sns_rom_20col_device::device_start()
+{
+ m_base_bank = 4;
+ save_item(NAME(m_base_bank));
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+READ8_MEMBER(sns_rom_device::read_l)
+{
+ return read_h(space, offset);
+}
+
+READ8_MEMBER(sns_rom_device::read_h)
+{
+ int bank = offset / 0x10000;
+ return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
+}
+
+
// Lo-ROM + OBC-1 (used by Metal Combat - Falcon's Revenge)
// same as above but additional read/write handling for the add-on chip
@@ -207,3 +290,224 @@ WRITE8_MEMBER( sns_rom_obc1_device::chip_write )
break;
}
}
+
+
+
+// Lo-ROM + Protection devices used in pirate carts
+
+
+// Pokemon (and many others): a byte is written and a permutation of its bits must be returned.
+// Address range for read/write depends on the game (check snes.xml)
+READ8_MEMBER( sns_rom_pokemon_device::chip_read )
+{
+ return BITSWAP8(m_latch,0,6,7,1,2,3,4,5);
+}
+
+WRITE8_MEMBER( sns_rom_pokemon_device::chip_write )
+{
+ m_latch = data;
+}
+
+
+// Tekken 2: It accesses the protection in a very strange way, always reading/writing the same data $f0 times,
+// because each access must be repeated a couple of times to be registered (typically around 7-30 times)
+// They probably used a microcontroller here.
+// The protection itself is accessed in banks $80-$bf. Accessing (read/write, doesn't matter) adress lines
+// A8,A9,A10 in these banks in a certain sequence makes the mc return a 4bit value. [d4s]
+// Details on a possible algorythm behind the sequence of accesses were provided by nocash. Thanks!
+void sns_rom_tekken2_device::update_prot(UINT32 offset)
+{
+ // accesses to [80-bf][8000-87ff] ranges update the protection value
+ offset &= 0x7ff;
+
+ switch (offset & 0x700)
+ {
+ case 0x000:
+ m_prot = 0;
+ break;
+ case 0x100:
+ // used for read access
+ break;
+ case 0x200: // BIT 0
+ m_prot |= 1;
+ break;
+ case 0x300: // BIT 1
+ m_prot |= 2;
+ break;
+ case 0x400: // BIT 2
+ m_prot |= 4;
+ break;
+ case 0x500: // BIT 3
+ m_prot |= 8;
+ break;
+ case 0x600: // DIRECTION
+ m_prot |= 0x10;
+ break;
+ case 0x700: // FUNCTION
+ m_prot |= 0x20;
+ break;
+ }
+}
+
+READ8_MEMBER( sns_rom_tekken2_device::chip_read )
+{
+ update_prot(offset);
+
+ if ((offset & 0x700) == 0x100)
+ {
+ if (BIT(m_prot, 5)) // FUNCTION = 1 means Shift
+ {
+ if (BIT(m_prot, 4)) // DIRECTION = 1 means Right
+ return (m_prot & 0x0f) >> 1;
+ else // DIRECTION = 0 means Left
+ return (m_prot & 0x0f) << 1;
+ }
+ else // FUNCTION = 0 means Add/Sub
+ {
+ if (BIT(m_prot, 4)) // DIRECTION = 1 means Minus
+ return (m_prot & 0x0f) - 1;
+ else // DIRECTION = 0 means Plus
+ return (m_prot & 0x0f) + 1;
+ }
+ }
+
+ return 0xff; // should be open_bus
+}
+
+WRITE8_MEMBER( sns_rom_tekken2_device::chip_write )
+{
+ update_prot(offset);
+}
+
+
+// Soul Blade: Adresses $xxx0-$xxx3 in banks $80-$bf always read $55, $0f, $aa, $f0.
+// Banks $c0-$ff return open bus.
+READ8_MEMBER( sns_rom_soulblad_device::chip_read )
+{
+ UINT8 value = 0;
+ offset &= 3;
+ switch (offset)
+ {
+ case 0:
+ default:
+ value = 0x55;
+ break;
+ case 1:
+ value = 0x0f;
+ break;
+ case 2:
+ value = 0xaa;
+ break;
+ case 3:
+ value = 0xf0;
+ break;
+ }
+ return value;
+}
+
+// Multicart pirate banking emulation
+// LoROM games, writes to [ff][ff00-ffff] control bankswitch
+// The actual banks depends on the last 8bits of the address accessed.
+
+// Type 1: bits0-4 of the address are used as base bank (256KB chunks)
+READ8_MEMBER(sns_rom_mcpirate1_device::read_l)
+{
+ return read_h(space, offset);
+}
+
+READ8_MEMBER(sns_rom_mcpirate1_device::read_h)
+{
+ int bank = (offset / 0x10000) + (m_base_bank * 8);
+ return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
+}
+
+WRITE8_MEMBER( sns_rom_mcpirate1_device::chip_write )
+{
+ m_base_bank = offset & 0x1f;
+// printf("offset %X data %X bank %X\n", offset, data, m_base_bank);
+}
+
+// Type 2: bits0-3 & bit5 of the address are used as base bank (256KB chunks)
+READ8_MEMBER(sns_rom_mcpirate2_device::read_l)
+{
+ return read_h(space, offset);
+}
+
+READ8_MEMBER(sns_rom_mcpirate2_device::read_h)
+{
+ int bank = (offset / 0x10000) + (m_base_bank * 8);
+ return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
+}
+
+WRITE8_MEMBER( sns_rom_mcpirate2_device::chip_write )
+{
+ m_base_bank = (offset & 0x0f) | ((offset & 0x20) >> 1);
+// printf("offset %X data %X bank %X\n", offset, data, m_base_bank);
+}
+
+// Korean 20 in 1 collection with NES games
+// base bank is selected (in 32KB chunks) by bits 0-4 of data written at 0x808000
+READ8_MEMBER(sns_rom_20col_device::read_l)
+{
+ return read_h(space, offset);
+}
+
+READ8_MEMBER(sns_rom_20col_device::read_h)
+{
+ int bank = (offset / 0x10000);
+ return m_rom[(rom_bank_map[bank] + m_base_bank) * 0x8000 + (offset & 0x7fff)];
+}
+
+WRITE8_MEMBER( sns_rom_20col_device::chip_write )
+{
+ // [#] game - written bank value
+ // [01] spartan x - c6
+ // [02] smb - c8
+ // [03] antarcitc adv - 8e
+ // [04] twinbee - ca
+ // [05] battle city - 8f
+ // [06] circus charlie - 90
+ // [07] galaga - 91
+ // [08] yie ar kungfu - 92
+ // [09] star force - 93
+ // [10] road fighter - 94
+ // [11] pinball - 95
+ // [12] bomberman - 96
+ // [13] new tetris?? - 0
+ // [14] arkanoid - cc
+ // [15] balloon fight - 97
+ // [16] donkey kong - 98
+ // [17] donkey kong 3 - 99
+ // [18] donkey kong jr - 9a
+ // [19] mario bros - 9b
+ // [20] popeye - 9c
+ m_base_bank = data & 0x1f;
+// printf("offset %X data %X bank %X\n", offset, data, m_base_bank);
+}
+
+
+
+// Work in progress (probably very wrong)
+
+READ8_MEMBER( sns_rom_banana_device::chip_read )
+{
+ return BITSWAP8(m_latch[0xf],0,6,7,1,2,3,4,5);
+}
+
+WRITE8_MEMBER( sns_rom_banana_device::chip_write )
+{
+// printf("write addr %X data %X\n", offset, data);
+ m_latch[0xf] = data;
+}
+
+READ8_MEMBER( sns_rom_bugs_device::chip_read )
+{
+ return BITSWAP8(m_latch[offset & 0xff],0,6,7,1,2,3,4,5);
+}
+
+WRITE8_MEMBER( sns_rom_bugs_device::chip_write )
+{
+ m_latch[offset & 0xff] = data;
+}
+
+
diff --git a/src/mess/machine/sns_rom.h b/src/mess/machine/sns_rom.h
index 6b136e1c839..2cded87bfbe 100644
--- a/src/mess/machine/sns_rom.h
+++ b/src/mess/machine/sns_rom.h
@@ -23,6 +23,31 @@ public:
virtual DECLARE_READ8_MEMBER(read_h);
};
+// ======================> sns_rom_obc1_device
+
+class sns_rom_obc1_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_obc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete() { m_shortname = "sns_rom_obc1"; }
+
+ // additional reading and writing
+ virtual DECLARE_READ8_MEMBER(chip_read);
+ virtual DECLARE_WRITE8_MEMBER(chip_write);
+
+ int m_address;
+ int m_offset;
+ int m_shift;
+ UINT8 m_ram[0x2000];
+};
+
+
+
// ======================> sns_rom_pokemon_device
class sns_rom_pokemon_device : public sns_rom_device
@@ -42,27 +67,140 @@ public:
UINT8 m_latch;
};
-// ======================> sns_rom_obc1_device
+// ======================> sns_rom_tekken2_device
-class sns_rom_obc1_device : public sns_rom_device
+class sns_rom_tekken2_device : public sns_rom_device
{
public:
// construction/destruction
- sns_rom_obc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ sns_rom_tekken2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete() { m_shortname = "sns_rom_tekken2"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(chip_read); // protection device
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // protection device
+
+ void update_prot(UINT32 offset);
+ // bit0-3 prot value, bit4 direction, bit5 function
+ // reads must return (prot value) +1/-1/<<1/>>1 depending on bit4 & bit5
+ UINT8 m_prot;
+};
+
+// ======================> sns_rom_soulblad_device
+
+class sns_rom_soulblad_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_soulblad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_config_complete() { m_shortname = "sns_rom_soulblad"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(chip_read); // protection device
+};
+
+// ======================> sns_rom_mcpirate1_device
+
+class sns_rom_mcpirate1_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_mcpirate1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
// device-level overrides
virtual void device_start();
virtual void device_reset();
- virtual void device_config_complete() { m_shortname = "sns_rom_obc1"; }
+ virtual void device_config_complete() { m_shortname = "sns_rom_mcpirate1"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_l);
+ virtual DECLARE_READ8_MEMBER(read_h);
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // bankswitch device
+ UINT8 m_base_bank;
+};
- // additional reading and writing
- virtual DECLARE_READ8_MEMBER(chip_read);
- virtual DECLARE_WRITE8_MEMBER(chip_write);
+// ======================> sns_rom_mcpirate2_device
- int m_address;
- int m_offset;
- int m_shift;
- UINT8 m_ram[0x2000];
+class sns_rom_mcpirate2_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_mcpirate2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete() { m_shortname = "sns_rom_mcpirate2"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_l);
+ virtual DECLARE_READ8_MEMBER(read_h);
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // bankswitch device
+ UINT8 m_base_bank;
+};
+
+// ======================> sns_rom_20col_device
+
+class sns_rom_20col_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_20col_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 = "sns_rom_20col"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_l);
+ virtual DECLARE_READ8_MEMBER(read_h);
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // bankswitch device
+ UINT8 m_base_bank;
+};
+
+// ======================> sns_rom_banana_device
+
+class sns_rom_banana_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_banana_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+// virtual void device_start();
+// virtual void device_reset();
+ virtual void device_config_complete() { m_shortname = "sns_rom_banana"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(chip_read); // protection device
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // protection device
+ UINT8 m_latch[16];
+};
+
+// ======================> sns_rom_bugs_device
+
+class sns_rom_bugs_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_bugs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete() { m_shortname = "sns_rom_bugslife"; }
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(chip_read); // protection device
+ virtual DECLARE_WRITE8_MEMBER(chip_write); // protection device
+ UINT8 m_latch[0x800];
};
@@ -70,5 +208,12 @@ public:
extern const device_type SNS_LOROM;
extern const device_type SNS_LOROM_OBC1;
extern const device_type SNS_LOROM_POKEMON;
+extern const device_type SNS_LOROM_TEKKEN2;
+extern const device_type SNS_LOROM_SOULBLAD;
+extern const device_type SNS_LOROM_MCPIR1;
+extern const device_type SNS_LOROM_MCPIR2;
+extern const device_type SNS_LOROM_20COL;
+extern const device_type SNS_LOROM_BANANA;
+extern const device_type SNS_LOROM_BUGSLIFE;
#endif
diff --git a/src/mess/machine/sns_slot.c b/src/mess/machine/sns_slot.c
index edb9b77f2a0..7bde75736dc 100644
--- a/src/mess/machine/sns_slot.c
+++ b/src/mess/machine/sns_slot.c
@@ -259,8 +259,13 @@ static const sns_slot slot_list[] =
{ SNES_STROM, "strom"},
// pirate carts
{ SNES_POKEMON, "lorom_poke"},
- { SNES_BANANA, "lorom_paja"}, // wip
- { SNES_SOULBLAD, "lorom_sbld"} // wip
+ { SNES_TEKKEN2, "lorom_tekken2"},
+ { SNES_SOULBLAD, "lorom_sbld"},
+ { SNES_MCPIR1, "lorom_mcpir1"},
+ { SNES_MCPIR2, "lorom_mcpir2"},
+ { SNES_20COL, "lorom_20col"},
+ { SNES_BANANA, "lorom_pija"}, // wip
+ { SNES_BUGS, "lorom_bugs"} // wip
};
static int sns_get_pcb_id(const char *slot)
@@ -695,7 +700,7 @@ void base_sns_cart_slot_device::setup_nvram()
if (sram_size)
{
UINT32 max = (hilo_mode == 0x007fc0) ? 0x80000 : 0x20000; // MODE20 vs MODE21
- size = 1024 << (ROM[0x00ffbd] & 0x07);
+ size = 1024 << sram_size;
if (size > max)
size = max;
}
diff --git a/src/mess/machine/sns_slot.h b/src/mess/machine/sns_slot.h
index 77c4b1d6a8d..a350ee81456 100644
--- a/src/mess/machine/sns_slot.h
+++ b/src/mess/machine/sns_slot.h
@@ -37,8 +37,13 @@ enum
SNES_STROM,
// pirate carts
SNES_POKEMON,
+ SNES_TEKKEN2,
+ SNES_SOULBLAD,
+ SNES_MCPIR1,
+ SNES_MCPIR2,
+ SNES_20COL,
SNES_BANANA, // wip
- SNES_SOULBLAD // wip
+ SNES_BUGS // wip
};