mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
protection and more mapper support for new mem code
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@771 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
45f2f245f5
commit
000f53350c
7 changed files with 512 additions and 109 deletions
92
pico/cart.c
92
pico/cart.c
|
@ -379,7 +379,7 @@ int pm_close(pm_file *fp)
|
|||
}
|
||||
|
||||
|
||||
void Byteswap(unsigned char *data,int len)
|
||||
static void Byteswap(unsigned char *data,int len)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
|
@ -612,6 +612,18 @@ void PicoCartUnload(void)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int rom_crc32(void)
|
||||
{
|
||||
unsigned int crc;
|
||||
elprintf(EL_STATUS, "caclulating CRC32..");
|
||||
|
||||
// have to unbyteswap for calculation..
|
||||
Byteswap(Pico.rom, Pico.romsize);
|
||||
crc = crc32(0, Pico.rom, Pico.romsize);
|
||||
Byteswap(Pico.rom, Pico.romsize);
|
||||
return crc;
|
||||
}
|
||||
|
||||
static int rom_strcmp(int rom_offset, const char *s1)
|
||||
{
|
||||
int i, len = strlen(s1);
|
||||
|
@ -643,6 +655,30 @@ static void rstrip(char *s)
|
|||
*p = 0;
|
||||
}
|
||||
|
||||
static int parse_3_vals(char *p, int *val0, int *val1, int *val2)
|
||||
{
|
||||
char *r;
|
||||
*val0 = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
*val1 = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
*val2 = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_expr(const char *expr, char **pr)
|
||||
{
|
||||
int len = strlen(expr);
|
||||
|
@ -661,6 +697,7 @@ static int is_expr(const char *expr, char **pr)
|
|||
static void parse_carthw(int *fill_sram)
|
||||
{
|
||||
int line = 0, any_checks_passed = 0, skip_sect = 0;
|
||||
int tmp, rom_crc = 0;
|
||||
char buff[256], *p, *r;
|
||||
FILE *f;
|
||||
|
||||
|
@ -739,6 +776,21 @@ static void parse_carthw(int *fill_sram)
|
|||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("check_crc32", &p))
|
||||
{
|
||||
unsigned int crc;
|
||||
crc = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
|
||||
if (rom_crc == 0)
|
||||
rom_crc = rom_crc32();
|
||||
if (crc == rom_crc)
|
||||
any_checks_passed = 1;
|
||||
else
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* now time for actions */
|
||||
if (is_expr("hw", &p)) {
|
||||
|
@ -750,12 +802,18 @@ static void parse_carthw(int *fill_sram)
|
|||
PicoSVPStartup();
|
||||
else if (strcmp(p, "pico") == 0)
|
||||
PicoInitPico();
|
||||
else if (strcmp(p, "prot") == 0)
|
||||
carthw_sprot_startup();
|
||||
else if (strcmp(p, "ssf2_mapper") == 0)
|
||||
carthw_ssf2_startup();
|
||||
else if (strcmp(p, "x_in_1_mapper") == 0)
|
||||
carthw_Xin1_startup();
|
||||
else if (strcmp(p, "realtec_mapper") == 0)
|
||||
carthw_realtec_startup();
|
||||
else if (strcmp(p, "radica_mapper") == 0)
|
||||
carthw_radica_startup();
|
||||
else if (strcmp(p, "prot_lk3") == 0)
|
||||
carthw_prot_lk3_startup();
|
||||
else {
|
||||
elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p);
|
||||
skip_sect = 1;
|
||||
|
@ -823,20 +881,10 @@ static void parse_carthw(int *fill_sram)
|
|||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
scl = strtoul(p, &r, 0);
|
||||
if (r == p || scl < 0 || scl > 15)
|
||||
if (!parse_3_vals(p, &scl, &sda_in, &sda_out))
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
sda_in = strtoul(p, &r, 0);
|
||||
if (r == p || sda_in < 0 || sda_in > 15)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
sda_out = strtoul(p, &r, 0);
|
||||
if (r == p || sda_out < 0 || sda_out > 15)
|
||||
if (scl < 0 || scl > 15 || sda_in < 0 || sda_in > 15 ||
|
||||
sda_out < 0 || sda_out > 15)
|
||||
goto bad;
|
||||
|
||||
SRam.eeprom_bit_cl = scl;
|
||||
|
@ -844,6 +892,18 @@ static void parse_carthw(int *fill_sram)
|
|||
SRam.eeprom_bit_out= sda_out;
|
||||
continue;
|
||||
}
|
||||
else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) {
|
||||
int addr, mask, val;
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
if (!parse_3_vals(p, &addr, &mask, &val))
|
||||
goto bad;
|
||||
|
||||
carthw_sprot_new_location(addr, mask, val, tmp ? 1 : 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
bad:
|
||||
|
@ -865,9 +925,7 @@ no_checks:
|
|||
*/
|
||||
static void PicoCartDetect(void)
|
||||
{
|
||||
int fill_sram = 0, csum;
|
||||
|
||||
csum = rom_read32(0x18c) & 0xffff;
|
||||
int fill_sram = 0;
|
||||
|
||||
memset(&SRam, 0, sizeof(SRam));
|
||||
if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A')
|
||||
|
|
124
pico/carthw.cfg
124
pico/carthw.cfg
|
@ -1,6 +1,8 @@
|
|||
# hardware (hw = ...):
|
||||
# svp - Sega Virtua Processor
|
||||
# pico - Sega Pico (not really cart hw, but convenient to support here)
|
||||
# prot - siple copy protection devices in unlicensed cartridges (see prot. below)
|
||||
# prot_lk3 - Lion King 3 / Super King Kong 99 protection.
|
||||
#
|
||||
# cartridge properties (prop = ...):
|
||||
# no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there
|
||||
|
@ -8,6 +10,7 @@
|
|||
# filled_sram - save storage needs to be initialized with FFh instead of 00h
|
||||
#
|
||||
# mappers (hw = ...):
|
||||
# ssf2_mapper - used in Super Street Fighter2
|
||||
# x_in_1_mapper - used in many *-in-1 pirate carts
|
||||
# realtec_mapper
|
||||
# radica_mapper - similar to x_in_1_mapper
|
||||
|
@ -21,6 +24,10 @@
|
|||
# eeprom_lines = <SCL,SDA_IN,SDA_OUT>
|
||||
# - select data bus pins that are connected to EEPROM
|
||||
# SCL, SDA_IN and SDA_OUT pins (0-15 for D0-D15).
|
||||
# hw = prot:
|
||||
# prot_ro_value16 = <addr, mask, val> - return constant <val> on reads at location
|
||||
# (<addr> & <mask>), ignore writes.
|
||||
# prot_rw_value16 = <addr, mask, val> - same as above, but writeable
|
||||
|
||||
[Virtua Racing - SVP]
|
||||
check_str = 0x150, "Virtua Racing"
|
||||
|
@ -52,6 +59,12 @@ prop = filled_sram
|
|||
check_str = 0x150, "MICRO MACHINES II"
|
||||
prop = filled_sram
|
||||
|
||||
# The SSF2 mapper
|
||||
[Super Street Fighter II - The New Challengers (U)]
|
||||
check_str = 0x150, "SUPER STREET FIGHTER2 The New Challengers"
|
||||
hw = ssf2_mapper
|
||||
prop = no_sram
|
||||
|
||||
# detect *_in_1 based on first game and if it's larger than it should be,
|
||||
# as some dumps look like to be incomplete.
|
||||
# This will also pick overdumps, but those should still work with the mapper applied.
|
||||
|
@ -178,3 +191,114 @@ sram_range = 0x200000,0x200001
|
|||
eeprom_type = 1
|
||||
eeprom_lines = 6,7,7
|
||||
|
||||
# Unlicensed games with simple protections
|
||||
# some of these come from Haze, some from myself (notaz).
|
||||
[Bug's Life, A (Unl)]
|
||||
check_str = 0x104, " "
|
||||
check_crc32 = 0x10458e09
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13000,0xffff00,0x28
|
||||
|
||||
[Elf Wor (Unl)]
|
||||
check_str = 0x172, "GAME : ELF WOR"
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x400000,-2,0x5500
|
||||
prot_ro_value16 = 0x400002,-2,0xc900 # check is done if the above one fails
|
||||
prot_ro_value16 = 0x400004,-2,0x0f00
|
||||
prot_ro_value16 = 0x400006,-2,0x1800 # similar to above
|
||||
|
||||
[King of Fighters '98, The (Unl)]
|
||||
check_str = 0x104, " "
|
||||
check_crc32 = 0xcbc38eea
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x480000,0xff0000,0xaa00
|
||||
prot_ro_value16 = 0x4a0000,0xff0000,0x0a00
|
||||
prot_ro_value16 = 0x4c0000,0xff0000,0xf000
|
||||
prot_ro_value16 = 0x400000,0xc00000,0x0000 # default for 400000-7f0000
|
||||
|
||||
[Lion King 3 (Unl)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0xc004219d
|
||||
hw = prot_lk3
|
||||
|
||||
[Lion King II, The (Unl)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0xaff46765
|
||||
hw = prot
|
||||
prot_rw_value16 = 0x400000,0xc00004,0
|
||||
prot_rw_value16 = 0x400004,0xc00004,0
|
||||
|
||||
[Mahjong Lover (Unl)]
|
||||
check_str = 0x118, "CREATON. "
|
||||
check_crc32 = 0xddd02ba4
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x400000,-2,0x9000
|
||||
prot_ro_value16 = 0x401000,-2,0xd300
|
||||
|
||||
[Pocket Monsters (Unl)]
|
||||
check_str = 0x104, " "
|
||||
check_crc32 = 0xf68f6367
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13002,-2,0x01
|
||||
prot_ro_value16 = 0xa1303e,-2,0x1f
|
||||
|
||||
[Pocket Monsters (Unl) [a1]]
|
||||
check_str = 0x104, " "
|
||||
check_crc32 = 0xfb176667
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13000,-2,0x14
|
||||
prot_ro_value16 = 0xa13002,-2,0x01
|
||||
prot_ro_value16 = 0xa1303e,-2,0x1f
|
||||
|
||||
[Rockman X3 (Unl)]
|
||||
check_csum = 0
|
||||
check_crc32 = 0x3ee639f0
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13000,-2,0x0c
|
||||
|
||||
[Smart Mouse (Unl)]
|
||||
check_csum = 0
|
||||
check_crc32 = 0xdecdf740
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x400000,-2,0x5500
|
||||
prot_ro_value16 = 0x400002,-2,0x0f00
|
||||
prot_ro_value16 = 0x400004,-2,0xaa00
|
||||
prot_ro_value16 = 0x400006,-2,0xf000
|
||||
|
||||
[Soul Blade (Unl)]
|
||||
check_str = 0x104, " "
|
||||
check_crc32 = 0xf26f88d1
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x400002,-2,0x9800
|
||||
prot_ro_value16 = 0x400004,-2,0xaa00 # or 0xc900
|
||||
prot_ro_value16 = 0x400006,-2,0xf000
|
||||
|
||||
[Super Bubble Bobble (Unl)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0x4820a161
|
||||
hw = prot
|
||||
prot_ro_value16 = 0x400000,-2,0x5500
|
||||
prot_ro_value16 = 0x400002,-2,0x0f00
|
||||
|
||||
[Super King Kong 99 (Unl)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0x413dfee2
|
||||
hw = prot_lk3
|
||||
|
||||
[Super Mario Bros. (Unl)]
|
||||
check_str = 0x140, "SUPER MARIO BROS "
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13000,-2,0x0c
|
||||
|
||||
[Super Mario 2 1998 (Unl)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0xf7e1b3e1
|
||||
hw = prot
|
||||
prot_ro_value16 = 0xa13000,-2,0x0a
|
||||
|
||||
[Squirrel King (R)]
|
||||
check_str = 0x104, " are Registered Trademarks"
|
||||
check_crc32 = 0xb8261ff5
|
||||
hw = prot
|
||||
prot_rw_value16 = 0x400000,0xc00000,0
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Support for a few cart mappers.
|
||||
* Support for a few cart mappers and some protection.
|
||||
*
|
||||
* (c) Copyright 2008-2009, Grazvydas "notaz" Ignotas
|
||||
* Free for non-commercial use.
|
||||
|
@ -10,6 +10,68 @@
|
|||
#include "../memory.h"
|
||||
|
||||
|
||||
/* The SSFII mapper */
|
||||
unsigned char ssf2_banks[8];
|
||||
|
||||
static carthw_state_chunk carthw_ssf2_state[] =
|
||||
{
|
||||
{ CHUNK_CARTHW, sizeof(ssf2_banks), &ssf2_banks },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static void carthw_ssf2_write8(u32 a, u32 d)
|
||||
{
|
||||
u32 target, base;
|
||||
|
||||
if ((a & 0xfffff0) != 0xa130f0) {
|
||||
PicoWrite8_io(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
a &= 0x0e;
|
||||
if (a == 0)
|
||||
return;
|
||||
|
||||
ssf2_banks[a >> 1] = d;
|
||||
base = d << 19;
|
||||
target = a << 18;
|
||||
if (base + 0x80000 > Pico.romsize) {
|
||||
elprintf(EL_ANOMALY|EL_STATUS, "ssf2: missing bank @ %06x", base);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu68k_map_set(m68k_read8_map, target, target + 0x80000 - 1, Pico.rom + base, 0);
|
||||
cpu68k_map_set(m68k_read16_map, target, target + 0x80000 - 1, Pico.rom + base, 0);
|
||||
}
|
||||
|
||||
static void carthw_ssf2_mem_setup(void)
|
||||
{
|
||||
cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_ssf2_write8, 1);
|
||||
}
|
||||
|
||||
static void carthw_ssf2_statef(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < 8; i++)
|
||||
carthw_ssf2_write8(0xa130f0 | (i << 1), ssf2_banks[i]);
|
||||
}
|
||||
|
||||
void carthw_ssf2_startup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
elprintf(EL_STATUS, "SSF2 mapper startup");
|
||||
|
||||
// default map
|
||||
for (i = 0; i < 8; i++)
|
||||
ssf2_banks[i] = i;
|
||||
|
||||
PicoCartMemSetup = carthw_ssf2_mem_setup;
|
||||
PicoLoadStateHook = carthw_ssf2_statef;
|
||||
carthw_chunks = carthw_ssf2_state;
|
||||
}
|
||||
|
||||
|
||||
/* Common *-in-1 pirate mapper.
|
||||
* Switches banks based on addr lines when /TIME is set.
|
||||
* TODO: verify
|
||||
|
@ -202,3 +264,243 @@ void carthw_radica_startup(void)
|
|||
carthw_chunks = carthw_Xin1_state;
|
||||
}
|
||||
|
||||
/* Simple unlicensed ROM protection emulation */
|
||||
static struct {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
u16 val;
|
||||
u16 readonly;
|
||||
} *sprot_items;
|
||||
static int sprot_item_alloc;
|
||||
static int sprot_item_count;
|
||||
|
||||
static u16 *carthw_sprot_get_val(u32 a, int rw_only)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sprot_item_count; i++)
|
||||
if ((a & sprot_items[i].mask) == sprot_items[i].addr)
|
||||
if (!rw_only || !sprot_items[i].readonly)
|
||||
return &sprot_items[i].val;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u32 PicoRead8_sprot(u32 a)
|
||||
{
|
||||
u16 *val;
|
||||
u32 d;
|
||||
|
||||
if (0xa10000 <= a && a < 0xa12000)
|
||||
return PicoRead8_io(a);
|
||||
|
||||
val = carthw_sprot_get_val(a, 0);
|
||||
if (val != NULL) {
|
||||
d = *val;
|
||||
if (!(a & 1))
|
||||
d >>= 8;
|
||||
elprintf(EL_UIO, "prot r8 [%06x] %02x @%06x", a, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
else {
|
||||
elprintf(EL_UIO, "prot r8 [%06x] MISS @%06x", a, SekPc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 PicoRead16_sprot(u32 a)
|
||||
{
|
||||
u16 *val;
|
||||
|
||||
if (0xa10000 <= a && a < 0xa12000)
|
||||
return PicoRead16_io(a);
|
||||
|
||||
val = carthw_sprot_get_val(a, 0);
|
||||
if (val != NULL) {
|
||||
elprintf(EL_UIO, "prot r16 [%06x] %04x @%06x", a, *val, SekPc);
|
||||
return *val;
|
||||
}
|
||||
else {
|
||||
elprintf(EL_UIO, "prot r16 [%06x] MISS @%06x", a, SekPc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void PicoWrite8_sprot(u32 a, u32 d)
|
||||
{
|
||||
u16 *val;
|
||||
|
||||
if (0xa10000 <= a && a < 0xa12000) {
|
||||
PicoWrite8_io(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
val = carthw_sprot_get_val(a, 1);
|
||||
if (val != NULL) {
|
||||
if (a & 1)
|
||||
*val = (*val & 0xff00) | (d | 0xff);
|
||||
else
|
||||
*val = (*val & 0x00ff) | (d << 8);
|
||||
elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
}
|
||||
else
|
||||
elprintf(EL_UIO, "prot w8 [%06x] %02x MISS @%06x", a, d & 0xff, SekPc);
|
||||
}
|
||||
|
||||
static void PicoWrite16_sprot(u32 a, u32 d)
|
||||
{
|
||||
u16 *val;
|
||||
|
||||
if (0xa10000 <= a && a < 0xa12000) {
|
||||
PicoWrite16_io(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
val = carthw_sprot_get_val(a, 1);
|
||||
if (val != NULL) {
|
||||
*val = d;
|
||||
elprintf(EL_UIO, "prot w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
}
|
||||
else
|
||||
elprintf(EL_UIO, "prot w16 [%06x] %04x MISS @%06x", a, d & 0xffff, SekPc);
|
||||
}
|
||||
|
||||
void carthw_sprot_new_location(unsigned int a, unsigned int mask, unsigned short val, int is_ro)
|
||||
{
|
||||
if (sprot_items == NULL) {
|
||||
sprot_items = calloc(8, sizeof(sprot_items[0]));
|
||||
sprot_item_alloc = 8;
|
||||
sprot_item_count = 0;
|
||||
}
|
||||
|
||||
if (sprot_item_count == sprot_item_alloc) {
|
||||
void *tmp;
|
||||
sprot_item_alloc *= 2;
|
||||
tmp = realloc(sprot_items, sprot_item_alloc);
|
||||
if (tmp == NULL) {
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
}
|
||||
sprot_items = tmp;
|
||||
}
|
||||
|
||||
sprot_items[sprot_item_count].addr = a;
|
||||
sprot_items[sprot_item_count].mask = mask;
|
||||
sprot_items[sprot_item_count].val = val;
|
||||
sprot_items[sprot_item_count].readonly = is_ro;
|
||||
sprot_item_count++;
|
||||
}
|
||||
|
||||
static void carthw_sprot_unload(void)
|
||||
{
|
||||
free(sprot_items);
|
||||
sprot_items = NULL;
|
||||
sprot_item_count = sprot_item_alloc = 0;
|
||||
}
|
||||
|
||||
static void carthw_sprot_mem_setup(void)
|
||||
{
|
||||
int start;
|
||||
|
||||
// map ROM - 0x7fffff, /TIME areas (which are tipically used)
|
||||
start = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
|
||||
cpu68k_map_set(m68k_read8_map, start, 0x7fffff, PicoRead8_sprot, 1);
|
||||
cpu68k_map_set(m68k_read16_map, start, 0x7fffff, PicoRead16_sprot, 1);
|
||||
cpu68k_map_set(m68k_write8_map, start, 0x7fffff, PicoWrite8_sprot, 1);
|
||||
cpu68k_map_set(m68k_write16_map, start, 0x7fffff, PicoWrite16_sprot, 1);
|
||||
|
||||
cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_sprot, 1);
|
||||
cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_sprot, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_sprot, 1);
|
||||
cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_sprot, 1);
|
||||
}
|
||||
|
||||
void carthw_sprot_startup(void)
|
||||
{
|
||||
elprintf(EL_STATUS, "Prot emu startup");
|
||||
|
||||
PicoCartMemSetup = carthw_sprot_mem_setup;
|
||||
PicoCartUnloadHook = carthw_sprot_unload;
|
||||
}
|
||||
|
||||
/* Protection emulation for Lion King 3. Credits go to Haze */
|
||||
static u8 prot_lk3_cmd, prot_lk3_data;
|
||||
|
||||
static u32 PicoRead8_plk3(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
switch (prot_lk3_cmd) {
|
||||
case 1: d = prot_lk3_data >> 1; break;
|
||||
case 2: // nibble rotate
|
||||
d = ((prot_lk3_data >> 4) | (prot_lk3_data << 4)) & 0xff;
|
||||
break;
|
||||
case 3: // bit rotate
|
||||
d = prot_lk3_data;
|
||||
d = (d >> 4) | (d << 4);
|
||||
d = ((d & 0xcc) >> 2) | ((d & 0x33) << 2);
|
||||
d = ((d & 0xaa) >> 1) | ((d & 0x55) << 1);
|
||||
break;
|
||||
/* Top Fighter 2000 MK VIII (Unl)
|
||||
case 0x98: d = 0x50; break; // prot_lk3_data == a8 here
|
||||
case 0x67: d = 0xde; break; // prot_lk3_data == 7b here (rot!)
|
||||
case 0xb5: d = 0x9f; break; // prot_lk3_data == 4a
|
||||
*/
|
||||
default:
|
||||
elprintf(EL_UIO, "unhandled prot cmd %02x @%06x", prot_lk3_cmd, SekPc);
|
||||
break;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "prot r8 [%06x] %02x @%06x", a, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
static void PicoWrite8_plk3p(u32 a, u32 d)
|
||||
{
|
||||
elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
if (a & 2)
|
||||
prot_lk3_cmd = d;
|
||||
else
|
||||
prot_lk3_data = d;
|
||||
}
|
||||
|
||||
static void PicoWrite8_plk3b(u32 a, u32 d)
|
||||
{
|
||||
int addr;
|
||||
|
||||
elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
addr = d << 15;
|
||||
if (addr + 0x8000 > Pico.romsize) {
|
||||
elprintf(EL_UIO|EL_ANOMALY, "prot_lk3: bank too large: %02x", d);
|
||||
return;
|
||||
}
|
||||
if (addr == 0)
|
||||
memcpy(Pico.rom, Pico.rom + Pico.romsize, 0x8000);
|
||||
else
|
||||
memcpy(Pico.rom, Pico.rom + addr, 0x8000);
|
||||
}
|
||||
|
||||
static void carthw_prot_lk3_mem_setup(void)
|
||||
{
|
||||
cpu68k_map_set(m68k_read8_map, 0x600000, 0x7fffff, PicoRead8_plk3, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0x600000, 0x6fffff, PicoWrite8_plk3p, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0x700000, 0x7fffff, PicoWrite8_plk3b, 1);
|
||||
}
|
||||
|
||||
void carthw_prot_lk3_startup(void)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
elprintf(EL_STATUS, "lk3 prot emu startup");
|
||||
|
||||
// allocate space for bank0 backup
|
||||
tmp = realloc(Pico.rom, Pico.romsize + 0x8000);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
}
|
||||
Pico.rom = tmp;
|
||||
memcpy(Pico.rom + Pico.romsize, Pico.rom, 0x8000);
|
||||
|
||||
PicoCartMemSetup = carthw_prot_lk3_mem_setup;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,13 @@ void PicoSVPStartup(void);
|
|||
void PicoSVPMemSetup(void);
|
||||
|
||||
/* misc */
|
||||
void carthw_ssf2_startup(void);
|
||||
void carthw_Xin1_startup(void);
|
||||
void carthw_realtec_startup(void);
|
||||
void carthw_radica_startup(void);
|
||||
|
||||
void carthw_sprot_startup(void);
|
||||
void carthw_sprot_new_location(unsigned int a,
|
||||
unsigned int mask, unsigned short val, int is_ro);
|
||||
|
||||
void carthw_prot_lk3_startup(void);
|
||||
|
|
|
@ -317,93 +317,6 @@ static void ctl_write_z80reset(u32 d)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// for nonstandard reads
|
||||
// TODO: mv to carthw
|
||||
u32 OtherRead16End(u32 a, int realsize)
|
||||
{
|
||||
u32 d=0;
|
||||
|
||||
// 32x test
|
||||
/*
|
||||
if (a == 0xa130ec) { d = 0x4d41; goto end; } // MA
|
||||
else if (a == 0xa130ee) { d = 0x5253; goto end; } // RS
|
||||
else if (a == 0xa15100) { d = 0x0080; goto end; }
|
||||
else
|
||||
*/
|
||||
|
||||
// for games with simple protection devices, discovered by Haze
|
||||
// some dumb detection is used, but that should be enough to make things work
|
||||
if ((a>>22) == 1 && Pico.romsize >= 512*1024) {
|
||||
if (*(int *)(Pico.rom+0x123e4) == 0x00550c39 && *(int *)(Pico.rom+0x123e8) == 0x00000040) { // Super Bubble Bobble (Unl) [!]
|
||||
if (a == 0x400000) { d=0x55<<8; goto end; }
|
||||
else if (a == 0x400002) { d=0x0f<<8; goto end; }
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0x008c4) == 0x66240055 && *(int *)(Pico.rom+0x008c8) == 0x00404df9) { // Smart Mouse (Unl)
|
||||
if (a == 0x400000) { d=0x55<<8; goto end; }
|
||||
else if (a == 0x400002) { d=0x0f<<8; goto end; }
|
||||
else if (a == 0x400004) { d=0xaa<<8; goto end; }
|
||||
else if (a == 0x400006) { d=0xf0<<8; goto end; }
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0x00404) == 0x00a90600 && *(int *)(Pico.rom+0x00408) == 0x6708b013) { // King of Fighters '98, The (Unl) [!]
|
||||
if (a == 0x480000 || a == 0x4800e0 || a == 0x4824a0 || a == 0x488880) { d=0xaa<<8; goto end; }
|
||||
else if (a == 0x4a8820) { d=0x0a<<8; goto end; }
|
||||
// there is also a read @ 0x4F8820 which needs 0, but that is returned in default case
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0x01b24) == 0x004013f9 && *(int *)(Pico.rom+0x01b28) == 0x00ff0000) { // Mahjong Lover (Unl) [!]
|
||||
if (a == 0x400000) { d=0x90<<8; goto end; }
|
||||
else if (a == 0x401000) { d=0xd3<<8; goto end; } // this one doesn't seem to be needed, the code does 2 comparisons and only then
|
||||
// checks the result, which is of the above one. Left it just in case.
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0x05254) == 0x0c3962d0 && *(int *)(Pico.rom+0x05258) == 0x00400055) { // Elf Wor (Unl)
|
||||
if (a == 0x400000) { d=0x55<<8; goto end; }
|
||||
else if (a == 0x400004) { d=0xc9<<8; goto end; } // this check is done if the above one fails
|
||||
else if (a == 0x400002) { d=0x0f<<8; goto end; }
|
||||
else if (a == 0x400006) { d=0x18<<8; goto end; } // similar to above
|
||||
}
|
||||
// our default behaviour is to return whatever was last written a 0x400000-0x7fffff range (used by Squirrel King (R) [!])
|
||||
// Lion King II, The (Unl) [!] writes @ 400000 and wants to get that val @ 400002 and wites another val
|
||||
// @ 400004 which is expected @ 400006, so we really remember 2 values here
|
||||
/// d = Pico.m.prot_bytes[(a>>2)&1]<<8;
|
||||
}
|
||||
else if (a == 0xa13000 && Pico.romsize >= 1024*1024) {
|
||||
if (*(int *)(Pico.rom+0xc8af0) == 0x30133013 && *(int *)(Pico.rom+0xc8af4) == 0x000f0240) { // Rockman X3 (Unl) [!]
|
||||
d=0x0c; goto end;
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0x28888) == 0x07fc0000 && *(int *)(Pico.rom+0x2888c) == 0x4eb94e75) { // Bug's Life, A (Unl) [!]
|
||||
d=0x28; goto end; // does the check from RAM
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0xc8778) == 0x30133013 && *(int *)(Pico.rom+0xc877c) == 0x000f0240) { // Super Mario Bros. (Unl) [!]
|
||||
d=0x0c; goto end; // seems to be the same code as in Rockman X3 (Unl) [!]
|
||||
}
|
||||
else if (*(int *)(Pico.rom+0xf20ec) == 0x30143013 && *(int *)(Pico.rom+0xf20f0) == 0x000f0200) { // Super Mario 2 1998 (Unl) [!]
|
||||
d=0x0a; goto end;
|
||||
}
|
||||
}
|
||||
else if (a == 0xa13002) { // Pocket Monsters (Unl)
|
||||
d=0x01; goto end;
|
||||
}
|
||||
else if (a == 0xa1303E) { // Pocket Monsters (Unl)
|
||||
d=0x1f; goto end;
|
||||
}
|
||||
else if (a == 0x30fe02) {
|
||||
// Virtua Racing - just for fun
|
||||
// this seems to be some flag that SVP is ready or something similar
|
||||
d=1; goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
elprintf(EL_UIO, "strange r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
void OtherWrite8End(u32 a,u32 d,int realsize)
|
||||
{
|
||||
// for games with simple protection devices, discovered by Haze
|
||||
if ((a>>22) == 1)
|
||||
;/// Pico.m.prot_bytes[(a>>2)&1] = (u8)d;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// cart (save) RAM area (usually 0x200000 - ...)
|
||||
|
|
|
@ -140,7 +140,6 @@ int pm_seek(pm_file *stream, long offset, int whence);
|
|||
int pm_close(pm_file *fp);
|
||||
int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms);
|
||||
int PicoCartInsert(unsigned char *rom,unsigned int romsize);
|
||||
void Byteswap(unsigned char *data,int len);
|
||||
void PicoCartUnload(void);
|
||||
extern void (*PicoCartLoadProgressCB)(int percent);
|
||||
extern void (*PicoCDLoadProgressCB)(const char *fname, int percent);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define SIMPLE_WRITE_SOUND 0
|
||||
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
|
||||
|
||||
#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_UIO|EL_IDLE|EL_SRAMIO|EL_EEPROM)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
|
||||
#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_UIO|EL_IDLE)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
|
||||
// EL_VDPDMA|EL_ASVDP|EL_SR) // |EL_BUSREQ|EL_Z80BNK)
|
||||
|
||||
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue