mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-09-10 16:53:15 +02:00
[Core/MD]
.added support for a few recently dumped unlicensed games .fixed support for RADICA dumps .improved SMW64 original dump detection .improved existing unlicensed cartridge hardware emulation
This commit is contained in:
parent
325f6dd5a7
commit
5b33778524
@ -46,7 +46,7 @@
|
||||
#include "eeprom_spi.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
#define CART_CNT (48)
|
||||
#define CART_CNT (53)
|
||||
|
||||
/* Cart database entry */
|
||||
typedef struct
|
||||
@ -79,10 +79,13 @@ static void default_time_w(uint32 address, uint32 data);
|
||||
static void default_regs_w(uint32 address, uint32 data);
|
||||
static uint32 default_regs_r(uint32 address);
|
||||
static uint32 default_regs_r_16(uint32 address);
|
||||
static uint32 custom_regs_r(uint32 address);
|
||||
static void custom_regs_w(uint32 address, uint32 data);
|
||||
static void custom_alt_regs_w(uint32 address, uint32 data);
|
||||
static uint32 topshooter_r(uint32 address);
|
||||
static void topshooter_w(uint32 address, uint32 data);
|
||||
static uint32 tekken_regs_r(uint32 address);
|
||||
static void tekken_regs_w(uint32 address, uint32 data);
|
||||
|
||||
/* Games that need extra hardware emulation:
|
||||
- copy protection device
|
||||
@ -96,14 +99,20 @@ static const md_entry_t rom_database[CART_CNT] =
|
||||
{0xffff,0xf863,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
|
||||
/* Earth Defense */
|
||||
{0xffff,0x44fb,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
|
||||
|
||||
|
||||
/* RADICA (Volume 1) (bad dump ?) */
|
||||
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* RADICA (Volume 1) */
|
||||
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
{0x24f4,0xfc84,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* RADICA (Volume 2) */
|
||||
{0x4f10,0x0836,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* RADICA (Volume 1) (byteswapped version) */
|
||||
{0xf424,0x9f82,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
{0x104f,0x32e9,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
|
||||
|
||||
/* Tenchi wo Kurau III: Sangokushi Gaiden - Chinese Fighter */
|
||||
{0x9490,0x8180,0x40,0x6f,{{0x00,0x00,0x00,0x00},{0xf0000c,0xf0000c,0xf0000c,0xf0000c},{0x400000,0x400004,0x400008,0x40000c},0,1,NULL,NULL,default_regs_r,custom_alt_regs_w}},
|
||||
|
||||
|
||||
/* Top Fighter */
|
||||
{0x4eb9,0x5d8b,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Soul Edge VS Samurai Spirits */
|
||||
@ -118,6 +127,12 @@ static const md_entry_t rom_database[CART_CNT] =
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Pokemon Stadium */
|
||||
{0x0000,0x843c,0x70,0x7f,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,NULL,NULL,NULL,custom_regs_w}},
|
||||
|
||||
|
||||
/* Tekken 3 Special (original dump) (a bootleg version also exists, with patched protection & different boot routine which reads unused !TIME mapped area) */
|
||||
{0x0000,0xc2f0,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,NULL,tekken_regs_r,tekken_regs_w}},
|
||||
|
||||
|
||||
/* Lion King 2 */
|
||||
{0xffff,0x1d9b,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Squirell King */
|
||||
@ -132,20 +147,35 @@ static const md_entry_t rom_database[CART_CNT] =
|
||||
{0xffff,0x5d98,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* (*) Shui Hu - Feng Yun Zhuan (patched ROM, unused registers) */
|
||||
{0x3332,0x872b,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
|
||||
|
||||
/* (*) Chao Ji Da Fu Weng (patched ROM, various words witten to register, long word also read from $7E0000, unknown banking hardware ?) */
|
||||
{0xa697,0xa697,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x000000,0x000000,0x000000},0,0,NULL,NULL,NULL,default_regs_w}},
|
||||
|
||||
/* (*) Aq Renkan Awa (patched ROM, ON/OFF bit sequence is written to register, unknown banking hardware ?) */
|
||||
{0x8104,0x0517,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400001,0x000000,0x000000,0x000000},0,0,NULL,NULL,NULL,default_regs_w}},
|
||||
/* (*) Jiu Ji Ma Jiang II - Ye Yan Bian (patched ROM, using expected register value - $0f - crashes the game) (uses 16-bits reads) */
|
||||
{0x0c44,0xba81,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x400006},0,0,NULL,NULL,default_regs_r_16,NULL}},
|
||||
|
||||
|
||||
/* (*) Tun Shi Tian Di III (patched ROM, unused register) */
|
||||
{0x0000,0x9c5e,0x40,0x40,{{0xab,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400046,0x000000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
|
||||
|
||||
/* Ma Jiang Qing Ren - Ji Ma Jiang Zhi */
|
||||
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x401000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Super Majon Club */
|
||||
{0x0000,0x3b95,0x40,0x40,{{0x90,0xd3,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x401000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Feng Kuang Tao Hua Yuan (original version from Creaton Softec Inc) (a bootleg version also exists with patched protection and minor title screen variations) */
|
||||
{0x0000,0x9dc4,0x40,0x40,{{0x90,0xd3,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x401000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
|
||||
|
||||
/* (*) Jiu Ji Ma Jiang II - Ye Yan Bian (patched ROM, using expected register value - $0f - crashes the game) (uses 16-bits reads) */
|
||||
{0x0c44,0xba81,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x400006},0,0,NULL,NULL,default_regs_r_16,NULL}},
|
||||
/* 16 Zhang Ma Jiang (uses 16-bits reads) */
|
||||
{0xfb40,0x4bed,0x40,0x40,{{0x00,0xaa,0x00,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x400002,0x000000,0x400006},0,0,NULL,NULL,default_regs_r_16,NULL}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0x00,0x00,0xaa,0xf0},{0xffffff,0xffffff,0xfc0000,0xfc0000},{0x000000,0x000000,0x480000,0x4c0000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* 16 Tiles Mahjong II (uses 16-bits reads) */
|
||||
{0xffff,0x0903,0x40,0x40,{{0x00,0x00,0xc9,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x400004,0x000000},0,0,NULL,NULL,default_regs_r_16,NULL}},
|
||||
|
||||
|
||||
/* Super Bubble Bobble */
|
||||
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Tenchi wo Kurau II - The Battle of Red Cliffs (Unl) */
|
||||
@ -162,12 +192,20 @@ static const md_entry_t rom_database[CART_CNT] =
|
||||
{0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* 777 Casino (For first one, 0x55 works as well. Other values are never used so they are guessed from on other unlicensed games using similar mapper) */
|
||||
{0x0000,0xf8d9,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Wu Kong Wai Zhuan (original) (a bootleg version also exists, with patched protection & modified SRAM test routine ?) */
|
||||
{0x0000,0x19ff,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Soul Blade */
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x63,0x98,0xc9,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Rockman X3 (half-patched ROM, two last register values are not used, 0xaa/0x18 works too) */
|
||||
|
||||
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0x00,0x00,0xaa,0xf0},{0xffffff,0xffffff,0xfc0000,0xfc0000},{0x000000,0x000000,0x480000,0x4c0000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
|
||||
|
||||
/* Rockman X3 (bootleg version ? two last register returned values are ignored, note that 0xaa/0x18 would work as well) */
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x00,0xc9,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x400004,0x400006},0,0,default_regs_r,NULL,default_regs_r,NULL}},
|
||||
/* (*) Tekken 3 Special (patched ROM, register value not used, unknown writes to $400000-$40000E, read from $400002) */
|
||||
{0x0000,0x8c6e,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
|
||||
|
||||
/* (*) Dragon Ball Final Bout (patched ROM, in original code, different switches occurs depending on returned value $00-$0f) */
|
||||
{0xc65a,0xc65a,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* (*) Yang Jia Jiang - Yang Warrior Family (patched ROM, register value unused) */
|
||||
@ -176,14 +214,22 @@ static const md_entry_t rom_database[CART_CNT] =
|
||||
{0xffff,0x0474,0x00,0x00,{{0x0a,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* Super Mario World */
|
||||
{0x2020,0xb4eb,0x00,0x00,{{0x1c,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* A Bug's Life */
|
||||
{0x7f7f,0x2aad,0x00,0x00,{{0x28,0x1f,0x01,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
|
||||
|
||||
/* King of Fighter 99 */
|
||||
{0x0000,0x021e,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
{0x0000,0x021e,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,custom_regs_r,default_regs_w,NULL,NULL}},
|
||||
/* Pocket Monster */
|
||||
{0xd6fc,0x1eb1,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
{0xd6fc,0x1eb1,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,custom_regs_r,default_regs_w,NULL,NULL}},
|
||||
/* Pocket Monster (bootleg version ? two last register returned values are ignored & first register test has been modified) */
|
||||
{0xd6fc,0x6319,0x00,0x00,{{0x14,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,m68k_unused_8_w,NULL,NULL}},
|
||||
/* A Bug's Life (bootleg version ? two last register returned values are ignored & first register test has been modified ?) */
|
||||
{0x7f7f,0x2aad,0x00,0x00,{{0x28,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,m68k_unused_8_w,NULL,NULL}},
|
||||
|
||||
|
||||
/* Game no Kanzume Otokuyou */
|
||||
{0x0000,0xf9d1,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,mapper_seganet_w,NULL,NULL}},
|
||||
|
||||
|
||||
/* Top Shooter (arcade hardware) */
|
||||
{0xffff,0x3632,0x20,0x20,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,NULL,topshooter_r,topshooter_w}}
|
||||
};
|
||||
@ -603,7 +649,7 @@ void md_cart_init(void)
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
}
|
||||
else if ((*(uint16 *)(cart.rom + 0x08) == 0x6000) && (*(uint16 *)(cart.rom + 0x0a) == 0x01f6))
|
||||
else if ((*(uint16 *)(cart.rom + 0x08) == 0x6000) && (*(uint16 *)(cart.rom + 0x0a) == 0x01f6) && (rominfo.realchecksum == 0xf894))
|
||||
{
|
||||
/* Super Mario World 64 (unlicensed) mapper */
|
||||
for (i=0x08; i<0x10; i++)
|
||||
@ -1594,6 +1640,21 @@ static void default_regs_w(uint32 address, uint32 data)
|
||||
m68k_unused_8_w(address, data);
|
||||
}
|
||||
|
||||
/* basic register shifting hardware (Bug's Life, Pocket Monster) */
|
||||
static uint32 custom_regs_r(uint32 address)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart.hw.mask[i]) == cart.hw.addr[i])
|
||||
{
|
||||
return cart.hw.regs[i] >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
return m68k_read_bus_8(address);
|
||||
}
|
||||
|
||||
/* custom register hardware (Top Fighter, Lion King III, Super Donkey Kong 99, Mulan, Pocket Monsters II, Pokemon Stadium) */
|
||||
static void custom_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
@ -1649,7 +1710,62 @@ static void custom_alt_regs_w(uint32 address, uint32 data)
|
||||
}
|
||||
|
||||
|
||||
/* Top Shooter arcade board hardware */
|
||||
/* "Tekken 3 Special" custom register hardware */
|
||||
static uint32 tekken_regs_r(uint32 address)
|
||||
{
|
||||
/* data output */
|
||||
if ((address & 0x0e) == 0x02)
|
||||
{
|
||||
/* maybe depends on mode bits ? */
|
||||
return (cart.hw.regs[0] - 1);
|
||||
}
|
||||
|
||||
return m68k_read_bus_16(address);
|
||||
}
|
||||
|
||||
static void tekken_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
switch (address & 0x0e)
|
||||
{
|
||||
case 0x00:
|
||||
{
|
||||
/* data output reset ? (game writes $FF before & after protection check) */
|
||||
cart.hw.regs[0]= 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x02:
|
||||
{
|
||||
/* read only ? */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0c:
|
||||
{
|
||||
/* data output mode bit 0 ? (game writes $01) */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0e:
|
||||
{
|
||||
/* data output mode bit 1 ? (never written by game) */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
/* data input (only connected to D0 ?)*/
|
||||
if (data & 1)
|
||||
{
|
||||
/* 4-bit hardware register ($400004 corresponds to bit0, $400006 to bit1, etc) */
|
||||
cart.hw.regs[0] |= 1 << (((address - 0x04) >> 1) & 3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* "Top Shooter" arcade board hardware */
|
||||
static uint32 topshooter_r(uint32 address)
|
||||
{
|
||||
if (address < 0x202000)
|
||||
|
Loading…
Reference in New Issue
Block a user