improved cartridge emulation (SRAM mapping & detection, ROM mirroring)

fixed Lock-ON option configuration
This commit is contained in:
ekeeke31 2009-08-07 17:30:14 +00:00
parent 5b888e725b
commit 5d1f29637e
5 changed files with 56 additions and 52 deletions

View File

@ -126,6 +126,8 @@ static uint8 mem_chunk[0x10000];
/* cart hardware detection */ /* cart hardware detection */
void cart_hw_init() void cart_hw_init()
{ {
int i;
/*************************************************************************************************************** /***************************************************************************************************************
CARTRIDGE ROM MIRRORING CARTRIDGE ROM MIRRORING
*************************************************************************************************************** ***************************************************************************************************************
@ -176,6 +178,7 @@ void cart_hw_init()
while (cart.romsize > size) size <<= 1; while (cart.romsize > size) size <<= 1;
/* total ROM size is not a factor of 2 */ /* total ROM size is not a factor of 2 */
/* TODO: handle more possible ROM configurations (using cartridge database ???) */
if ((size < MAXROMSIZE) && (cart.romsize < size)) if ((size < MAXROMSIZE) && (cart.romsize < size))
{ {
/* two chips with different size */ /* two chips with different size */
@ -200,20 +203,15 @@ void cart_hw_init()
} }
/* ROM is mirrored each 2^k bytes */ /* ROM is mirrored each 2^k bytes */
int i = size; cart.mask = size -1;
while (i < 0x400000)
{
memcpy(cart.rom + i, cart.rom, size);
i += size;
}
/********************************************** /**********************************************
DEFAULT CARTRIDGE MAPPING DEFAULT CARTRIDGE MAPPING
***********************************************/ ***********************************************/
for (i=0; i<0x40; i++) for (i=0; i<0x40; i++)
{ {
/* cartridge ROM */ /* cartridge ROM */
m68k_memory_map[i].base = cart.rom + (i<<16); m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
m68k_memory_map[i].read8 = NULL; m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL; m68k_memory_map[i].read16 = NULL;
m68k_memory_map[i].write8 = m68k_unused_8_w; m68k_memory_map[i].write8 = m68k_unused_8_w;
@ -325,7 +323,7 @@ void cart_hw_init()
break; break;
case TYPE_SK: case TYPE_SK:
/* be sure we have enough place to copy everything */ /* be sure we have enough place to store both ROMs */
if (cart.romsize < 0x700000) if (cart.romsize < 0x700000)
{ {
/* load Sonic & Knuckles ROM (2 MBytes) */ /* load Sonic & Knuckles ROM (2 MBytes) */
@ -340,16 +338,11 @@ void cart_hw_init()
fread(cart.rom+0x900000,1,0x40000,f); fread(cart.rom+0x900000,1,0x40000,f);
fclose(f); fclose(f);
/* ROM is mirrored each 256K */
memcpy(cart.rom+0x940000,cart.rom+0x900000,0x40000);
memcpy(cart.rom+0x980000,cart.rom+0x900000,0x40000);
memcpy(cart.rom+0x9C0000,cart.rom+0x900000,0x40000);
#ifdef LSB_FIRST #ifdef LSB_FIRST
/* Byteswap ROM */ /* Byteswap ROM */
int i; int i;
uint8 temp; uint8 temp;
for(i = 0; i < 0x300000; i += 2) for(i = 0; i < 0x240000; i += 2)
{ {
temp = cart.rom[i+0x700000]; temp = cart.rom[i+0x700000];
cart.rom[i+0x700000] = cart.rom[i+1+0x700000]; cart.rom[i+0x700000] = cart.rom[i+1+0x700000];
@ -357,6 +350,10 @@ void cart_hw_init()
} }
#endif #endif
/*$000000-$1fffff is mapped to S&K ROM */
for (i=0x00; i<0x20; i++)
m68k_memory_map[i].base = (cart.rom + 0x700000) + (i<<16);
cart.lock_on = 1; cart.lock_on = 1;
} }
@ -449,7 +446,7 @@ void cart_hw_reset()
if (cart.hw.bankshift) if (cart.hw.bankshift)
{ {
for (i=0x00; i<0x40; i++) for (i=0x00; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16); m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
} }
/* Realtec mapper */ /* Realtec mapper */
@ -482,10 +479,8 @@ void cart_hw_reset()
if (cart.lock_on) if (cart.lock_on)
{ {
/* reset memory map */ /* reset memory map */
for (i=0x00; i<0x20; i++)
m68k_memory_map[i].base = cart.rom + 0x700000 + (i<<16);
for (i=0x30; i<0x40; i++) for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16); m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
} }
break; break;
@ -516,41 +511,52 @@ static void sega_mapper_w(uint32 address, uint32 data)
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */ /* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
if (data & 1) if (data & 1)
{ {
/* SRAM enabled */ /* $200000-$3fffff is mapped to SRAM (only if SRAM exists) */
m68k_memory_map[0x20].base = sram.sram; if (sram.on)
{
for (i=0x20; i<0x40; i++)
m68k_memory_map[i].base = sram.sram;
if (data & 2) if (data & 2)
{ {
/* SRAM write disabled */ /* SRAM write disabled */
m68k_memory_map[0x20].write8 = m68k_unused_8_w; for (i=0x20; i<0x40; i++)
m68k_memory_map[0x20].write16 = m68k_unused_16_w; {
zbank_memory_map[0x20].write = zbank_unused_w; m68k_memory_map[i].write8 = m68k_unused_8_w;
} m68k_memory_map[i].write16 = m68k_unused_16_w;
else zbank_memory_map[i].write = zbank_unused_w;
{ }
/* SRAM write enabled */ }
m68k_memory_map[0x20].write8 = NULL; else
m68k_memory_map[0x20].write16 = NULL; {
zbank_memory_map[0x20].write = NULL; /* SRAM write enabled */
for (i=0x20; i<0x40; i++)
{
m68k_memory_map[0x20].write8 = NULL;
m68k_memory_map[0x20].write16 = NULL;
zbank_memory_map[0x20].write = NULL;
}
}
} }
if (cart.lock_on) if (cart.lock_on)
{ {
/* enable UPMEM chip at $300000-$3fffff */ /* enable UPMEM chip at $300000-$3fffff */
for (i=0x30; i<0x40; i++) for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + 0x600000 + (i<<16); m68k_memory_map[i].base = (cart.rom + 0x900000) + ((i & 3)<<16);
} }
} }
else else
{ {
/* ROM enabled */ /* ROM enabled */
m68k_memory_map[0x20].base = cart.rom + 0x200000; for (i=0x20; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
if (cart.lock_on) if (cart.lock_on)
{ {
/* enable cartridge ROM at $300000-$3fffff */ /* enable cartridge ROM at $300000-$3fffff */
for (i=0x30; i<0x40; i++) for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16); m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
} }
} }
break; break;

View File

@ -28,9 +28,9 @@
#define _CART_HW_H_ #define _CART_HW_H_
/* Lock-ON cartridge type */ /* Lock-ON cartridge type */
#define TYPE_GG 0x10 /* Game Genie */ #define TYPE_GG 0x01 /* Game Genie */
#define TYPE_AR 0x20 /* Action Replay (Pro) */ #define TYPE_AR 0x02 /* Action Replay (Pro) */
#define TYPE_SK 0x40 /* Sonic & Knuckles */ #define TYPE_SK 0x03 /* Sonic & Knuckles */
/* Cartridge extra hardware */ /* Cartridge extra hardware */
typedef struct typedef struct
@ -52,6 +52,7 @@ typedef struct
{ {
uint8 *rom; /* ROM data */ uint8 *rom; /* ROM data */
uint8 *base; /* ROM area (slot 0) */ uint8 *base; /* ROM area (slot 0) */
uint32 mask; /* mask ROM */
uint32 lock_on; /* 1: Lock-On enabled */ uint32 lock_on; /* 1: Lock-On enabled */
uint32 romsize; /* ROM size */ uint32 romsize; /* ROM size */
T_CART_HW hw; /* Custom hardware */ T_CART_HW hw; /* Custom hardware */

View File

@ -100,7 +100,6 @@ void eeprom_init()
{ {
sram.custom = 1; sram.custom = 1;
sram.on = 1; sram.on = 1;
sram.write = 1;
memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE)); memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE));
} }
} }
@ -114,8 +113,7 @@ void eeprom_init()
{ {
sram.custom = 1; sram.custom = 1;
sram.on = 1; sram.on = 1;
sram.write = 1;
/* set SEGA mapper as default */ /* set SEGA mapper as default */
memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE)); memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE));
} }

View File

@ -57,6 +57,7 @@ void sram_init()
sram.end = sram.start + 0xffff; sram.end = sram.start + 0xffff;
sram.start &= 0xfffffffe; sram.start &= 0xfffffffe;
sram.end |= 1; sram.end |= 1;
sram.on = 1;
} }
else else
{ {
@ -66,24 +67,24 @@ void sram_init()
} }
/* set SRAM ON by default when ROM is not mapped */ /* set SRAM ON by default when ROM is not mapped */
if (cart.romsize <= sram.start) if (cart.romsize <= sram.start) sram.on = 1;
{
sram.on = 1;
sram.write = 1;
}
/* Some games with bad header or specific configuration */ /* Some games with bad header or specific configuration */
if (strstr(rominfo.product,"T-113016") != NULL) if (strstr(rominfo.product,"T-113016") != NULL)
{ {
/* Pugsy (try accessing unmapped area for copy protection) */ /* Pugsy (try accessing unmapped area for copy protection) */
sram.on = 0; sram.on = 0;
sram.write = 0; }
else if (strstr(rominfo.international,"SONIC THE HEDGEHOG 2") != NULL)
{
/* Sonic the Hedgehog 2 does not use SRAM */
/* this prevents SRAM activation when using Sonic & Knuckles LOCK-ON feature */
sram.on = 0;
} }
else if ((strstr(rominfo.product,"T-26013") != NULL) && (rominfo.checksum == 0xa837)) else if ((strstr(rominfo.product,"T-26013") != NULL) && (rominfo.checksum == 0xa837))
{ {
/* Psy-O-Blade (bad header) */ /* Psy-O-Blade (bad header) */
sram.on = 1; sram.on = 1;
sram.write = 1;
sram.start = 0x200001; sram.start = 0x200001;
sram.end = 0x203fff; sram.end = 0x203fff;
} }
@ -91,7 +92,6 @@ void sram_init()
{ {
/* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */ /* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */
sram.on = 1; sram.on = 1;
sram.write = 1;
sram.start = 0x400000; sram.start = 0x400000;
sram.end = 0x40ffff; sram.end = 0x40ffff;
} }

View File

@ -27,7 +27,6 @@ typedef struct
{ {
uint8 detected; uint8 detected;
uint8 on; uint8 on;
uint8 write;
uint8 custom; uint8 custom;
uint32 start; uint32 start;
uint32 end; uint32 end;