(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.
This commit is contained in:
Fabio Priuli 2013-03-13 08:05:41 +00:00
parent 2c7f75772c
commit e4e14a06b2
6 changed files with 709 additions and 81 deletions

View File

@ -3918,6 +3918,11 @@ List of pirate cartridges
</part>
</software>
<!--
protection actually seems more similar to tekken 2 than to pokemon
the game writes (low) a lot of time to [ff00-ffff] range and reads (high) to ffcc/ffcd/ffce
more investigation needed...
-->
<software name="banpija" cloneof="chester" supported="no">
<!-- single cartridge source: d4s -->
<description>Bananas de Pijamas (Asia)</description>
@ -3925,7 +3930,7 @@ List of pirate cartridges
<publisher>&lt;unlicensed&gt;</publisher>
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom" />
<feature name="slot" value="lorom_pija" />
<dataarea name="rom" size="1048576">
<rom name="bananas de pijamas (unl) [!].sfc" size="1048576" crc="52b0d84b" sha1="149e916dfd4058f8de97d7bc8f74d5e630853ffb" offset="0x000000" />
</dataarea>
@ -3946,7 +3951,12 @@ List of pirate cartridges
</part>
</software>
<software name="abugslif" supported="no">
<!--
protection actually seems more similar to tekken 2 than to pokemon
the game writes (high) a lot of time to [ff00-ffff] range, but it does not seem to read back (possibly it reads from the same range where it reads rom from...)
more investigation needed...
-->
<software name="bugslife" supported="no">
<!-- single cartridge source: d4s -->
<!-- Notes: highly similar to the game boy color version, this could be based on a prototype -->
<description>A Bug's Life (Bra)</description>
@ -3956,7 +3966,7 @@ List of pirate cartridges
<feature name="pcb" value="890409C" /> <!-- epoxy board -->
<feature name="cart_model" value="SNS-006" />
<feature name="slot" value="lorom" />
<feature name="slot" value="lorom_bugs" />
<dataarea name="rom" size="2097152">
<rom name="u2" size="2097152" crc="014f0fcf" sha1="930ab53fded53a65824690b394d6e8c6565c083b" offset="0x000000" />
</dataarea>
@ -3964,7 +3974,7 @@ List of pirate cartridges
</software>
<!--Notes: this is temporarily included for reference, until we fix emulation of the good dump -->
<software name="abugslifh" cloneof="abugslif">
<software name="bugslifeh" cloneof="bugslife">
<description>A Bug's Life (Bra, Cracked)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
@ -4199,7 +4209,7 @@ List of pirate cartridges
</part>
</software>
<software name="soulblad" supported="no">
<software name="soulblad" supported="partial">
<!-- single cartridge source: d4s -->
<description>Soul Blade (Asia)</description>
<year>199?</year>
@ -4210,7 +4220,7 @@ List of pirate cartridges
<feature name="cart_model" value="SNS-006" />
<feature name="cart_back_label" value="n/a" />
<feature name="slot" value="lorom" />
<feature name="slot" value="lorom_sbld" />
<dataarea name="rom" size="3145728">
<rom name="soul blade (world) (unl).sfc" size="3145728" crc="c97d1d7b" sha1="f7501045b5326255f3bde0543eb0a541b62588a9" offset="0x000000" />
</dataarea>
@ -4259,14 +4269,14 @@ List of pirate cartridges
</part>
</software>
<software name="sfex" supported="no">
<software name="sfex">
<!-- single cartridge source: d4s -->
<description>Street Fighter EX Plus α (Asia)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_poke" />
<feature name="slot" value="lorom_tekken2" />
<dataarea name="rom" size="2097152">
<rom name="street fighter ex plus alpha (world) (unl).sfc" size="2097152" crc="dad59b9f" sha1="22f864b4a8728f08513b979d2a960eb3083b2c83" offset="0x000000" />
</dataarea>
@ -4322,7 +4332,96 @@ List of pirate cartridges
</part>
</software>
<software name="super20m" supported="no"> <!-- not working probably due to custom bankswitching -->
<!-- The image should be 8MB, while this is only 4MB. Half of game data is missing (only games 1 & 2 are present). Redump needed! -->
<software name="sup5in1" supported="partial">
<description>Super 5 in 1 (Bad Dump)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir1" />
<dataarea name="rom" size="4194304">
<rom name="super 5-in-1 [p1].sfc" size="4194304" crc="41975d1b" sha1="16778a78cadc54b54ba41fbed4aac8beca25d5d2" offset="0x000000" />
</dataarea>
</part>
</software>
<software name="sup6in1">
<description>Super 6 in 1</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir1" />
<dataarea name="rom" size="4194304">
<rom name="super 6-in-1 [p1].sfc" size="4194304" crc="2f9169cb" sha1="9f6c4ba3a1035ca97a77eff92690bf873d0eca09" offset="0x000000" />
</dataarea>
</part>
</software>
<!-- The image should be 8MB, while this is only 2MB. Most of game data is missing (only games 2 & 6 are present). Redump needed! -->
<software name="new7in1" supported="partial">
<description>1997 New 7 in 1 (Bad Dump)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir2" />
<dataarea name="rom" size="2097152">
<rom name="super 11-in-1 [p1].sfc" size="2097152" crc="8a8f8d96" sha1="c8cde5ee5f4dafc450e12bebb0f3f74480dde739" offset="0x000000" />
</dataarea>
</part>
</software>
<!-- This actually uses a different bankswitch mechanism, and it uses bit6 to select HiROM access, not sure how to emulate it, yet... -->
<software name="sup7in1" supported="no">
<description>Super 7-in-1 1997 (Bad Dump)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir1" />
<dataarea name="rom" size="4194304">
<rom name="super 7-in-1 1997 [p1].sfc" size="4194304" crc="fc5036b2" sha1="04907f8b963bc1f0012f1594cbf244b05416ce58" offset="0x000000" />
</dataarea>
</part>
</software>
<!-- The image should be 8MB, while this is only 4MB. Half of game data is missing (only games 2, 3, 4 & 5 are present). Redump needed! -->
<software name="sup9in1" supported="partial">
<description>8 in 1 and 10 in 1 (Bad Dump)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir1" />
<dataarea name="rom" size="4194304">
<rom name="super 9-in-1 [p1].sfc" size="4194304" crc="213d6d24" sha1="80f5eb1c55292fd4d47275a13dea21e8cb0c2f91" offset="0x000000" />
</dataarea>
</part>
</software>
<!-- The image should be ~8MB, while this is only 1MB. Most of game data is missing. Redump needed! -->
<software name="sup11in1" supported="partial">
<description>Super 11 in 1 (Bad Dump)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom_mcpir1" />
<dataarea name="rom" size="1048576">
<rom name="super 11-in-1 [p1].sfc" size="1048576" crc="81747ee1" sha1="1c0ddb21cde72d4738a56e6618f81b82092c01bd" offset="0x000000" />
</dataarea>
</part>
</software>
<software name="super20m" supported="partial">
<!-- single cartridge source: d4s -->
<description>Super 20 Collection (Kor)</description>
<year>199?</year>
@ -4330,21 +4429,21 @@ List of pirate cartridges
<info name="alt_title" value="슈퍼20합" />
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom" />
<feature name="slot" value="lorom_20col" />
<dataarea name="rom" size="1048576">
<rom name="c20h.u1" size="1048576" crc="ac19b8f4" sha1="3a64c817ff3fc3819f2fd726868b6f27eb4523df" offset="0x000000" />
</dataarea>
</part>
</software>
<software name="tekken2" supported="no">
<software name="tekken2">
<!-- single cartridge source: d4s -->
<description>Tekken 2 (Asia)</description>
<year>199?</year>
<publisher>&lt;unlicensed&gt;</publisher>
<part name="cart" interface="snes_cart">
<feature name="slot" value="lorom" />
<feature name="slot" value="lorom_tekken2" />
<dataarea name="rom" size="2097152">
<rom name="tekken 2 (world) (unl).sfc" size="2097152" crc="066687ca" sha1="8aa2ee03fe40f289e30723a1c8cd4564481bdfdf" offset="0x000000" />
</dataarea>

View File

@ -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;
}
}

View File

@ -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,31 +42,60 @@ sns_rom_device::sns_rom_device(const machine_config &mconfig, const char *tag, d
{
}
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)
{
}
// 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_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)
{
}
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)
{
}
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)
{
}
// 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()
{
}
void sns_rom_pokemon_device::device_start()
{
save_item(NAME(m_latch));
}
void sns_rom_pokemon_device::device_reset()
{
m_latch = 0;
}
void sns_rom_obc1_device::device_start()
{
save_item(NAME(m_ram));
@ -77,6 +114,65 @@ void sns_rom_obc1_device::device_reset()
}
void sns_rom_pokemon_device::device_start()
{
save_item(NAME(m_latch));
}
void sns_rom_pokemon_device::device_reset()
{
m_latch = 0;
}
void sns_rom_tekken2_device::device_start()
{
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));
}
void sns_rom_mcpirate1_device::device_start()
{
save_item(NAME(m_base_bank));
}
void sns_rom_mcpirate1_device::device_reset()
{
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
-------------------------------------------------*/
@ -94,19 +190,6 @@ READ8_MEMBER(sns_rom_device::read_h)
// Lo-ROM + Protection device
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;
}
// 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;
}

View File

@ -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_obc1"; }
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
// additional reading and writing
virtual DECLARE_READ8_MEMBER(chip_read);
virtual DECLARE_WRITE8_MEMBER(chip_write);
void update_prot(UINT32 offset);
int m_address;
int m_offset;
int m_shift;
UINT8 m_ram[0x2000];
// 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_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;
};
// ======================> sns_rom_mcpirate2_device
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

View File

@ -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;
}

View File

@ -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
};