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:
notaz 2009-09-09 16:00:42 +00:00
parent 45f2f245f5
commit 000f53350c
7 changed files with 512 additions and 109 deletions

View file

@ -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')

View file

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

View file

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

View file

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

View file

@ -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 - ...)

View file

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

View file

@ -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__)