mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-04 18:05:06 +01:00
* added support for Top Shooter (custom arcade board using modified Genesis hardware)
* added emulation of a few additional unlicensed game copy protections (fixes 777 Casino crashing randomly) (NB: it appears that most of those unlicensed games were already patched by ROM dumpers, emulating copy protection hardware only for documentation)
This commit is contained in:
parent
03c3f9c135
commit
f34b8d4557
@ -27,7 +27,7 @@
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define CART_CNT 30
|
||||
#define CART_CNT (44)
|
||||
|
||||
extern int emulate_address_error;
|
||||
|
||||
@ -56,8 +56,11 @@ static uint32 mapper_radica_r(uint32 address);
|
||||
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 void custom_regs_w(uint32 address, uint32 data);
|
||||
static void custom_alt_regs_w(uint32 address, uint32 data);
|
||||
static uint32 topshoot_read_byte(uint32 address);
|
||||
static void topshoot_write_byte(uint32 address, uint32 data);
|
||||
|
||||
/* Games that need extra hardware emulation:
|
||||
- copy protection device
|
||||
@ -71,11 +74,11 @@ static const T_CART_ENTRY 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) (not byteswapped) */
|
||||
/* 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}},
|
||||
/* 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) */
|
||||
/* 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}},
|
||||
/* Chinese Fighters III */
|
||||
{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}},
|
||||
@ -95,22 +98,50 @@ static const T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{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 */
|
||||
{0x0000,0x8ec8,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffff4,0xffffff,0xffffff,0xffffff},{0x400004,0x000000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Lian Huan Pao - Barver Battle Saga (registers accessed by Z80, related to sound engine ?) */
|
||||
{0x30b9,0x1c2a,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 Zhuan (registers accessed by Z80, related to sound engine ?) */
|
||||
{0x6001,0x0211,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Feng Shen Ying Jie Chuan (registers accessed by Z80, related to sound engine ?) */
|
||||
{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}},
|
||||
/* (*) 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}},
|
||||
/* King of Fighter 98 (needs better register masking) */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},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}},
|
||||
/* Supper 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}},
|
||||
/* Mahjong Lover */
|
||||
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x401000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Elf Wor */
|
||||
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Huan Le Tao Qi Shu - Smart Mouse */
|
||||
{0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* (*) Hei Tao 2 - Super Big 2 (patched ROM, unused registers) */
|
||||
{0x0000,0x5843,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Elf Wor */
|
||||
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Ya-Se Chuanshuo */
|
||||
{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}},
|
||||
/* Soul Blade */
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
{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) */
|
||||
{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) */
|
||||
{0x0000,0x96b0,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* Super Mario 2 1998 */
|
||||
{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 */
|
||||
@ -121,10 +152,10 @@ static const T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{0x0000,0x021e,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,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}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x400004,0x000000,0x000000},0,0,default_regs_r,NULL,default_regs_r,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}}
|
||||
{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,topshoot_read_byte,topshoot_write_byte}}
|
||||
};
|
||||
|
||||
|
||||
@ -886,6 +917,19 @@ static uint32 default_regs_r(uint32 address)
|
||||
return m68k_read_bus_8(address);
|
||||
}
|
||||
|
||||
static uint32 default_regs_r_16(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] << 8);
|
||||
}
|
||||
}
|
||||
return m68k_read_bus_16(address);
|
||||
}
|
||||
|
||||
static void default_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
@ -951,3 +995,67 @@ static void custom_alt_regs_w(uint32 address, uint32 data)
|
||||
/* write regs */
|
||||
default_regs_w(address, data);
|
||||
}
|
||||
|
||||
static uint32 topshoot_read_byte(uint32 address)
|
||||
{
|
||||
if (address < 0x202000)
|
||||
{
|
||||
uint8 temp = 0xff;
|
||||
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x43:
|
||||
{
|
||||
if (input.pad[0] & INPUT_A) temp &= ~0x80; /* Shoot */
|
||||
if (input.pad[0] & INPUT_B) temp &= ~0x10; /* Bet */
|
||||
if (input.pad[0] & INPUT_START) temp &= ~0x20; /* Start */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x45: /* ??? (DOWN) & Service Mode (UP) */
|
||||
{
|
||||
if (input.pad[0] & INPUT_UP) temp &= ~0x08; /* Service Mode */
|
||||
if (input.pad[0] & INPUT_DOWN) temp &= ~0x10; /* ???, used in service menu to select next option */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x47:
|
||||
{
|
||||
if (input.pad[0] & INPUT_RIGHT) temp &= ~0x03; /* Insert 10 coins */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x49:
|
||||
{
|
||||
if (input.pad[0] & INPUT_LEFT) temp &= ~0x03; /* Clear coins */
|
||||
if (input.pad[0] & INPUT_C) temp &= ~0x01; /* Insert XXX coins */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x51:
|
||||
{
|
||||
temp = 0xA5;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
temp = m68k_read_bus_8(address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
return READ_BYTE(sram.sram , address & 0xffff);
|
||||
}
|
||||
|
||||
static void topshoot_write_byte(uint32 address, uint32 data)
|
||||
{
|
||||
if (address >= 0x202000)
|
||||
{
|
||||
WRITE_BYTE(sram.sram , address & 0xffff, data);
|
||||
return;
|
||||
}
|
||||
m68k_unused_8_w(address, data);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user