From 5d1f29637ed4cc6775a0f25ce8bb11278600082f Mon Sep 17 00:00:00 2001 From: ekeeke31 Date: Fri, 7 Aug 2009 17:30:14 +0000 Subject: [PATCH] improved cartridge emulation (SRAM mapping & detection, ROM mirroring) fixed Lock-ON option configuration --- source/cart_hw/cart_hw.c | 80 +++++++++++++++++++++------------------- source/cart_hw/cart_hw.h | 7 ++-- source/cart_hw/eeprom.c | 4 +- source/cart_hw/sram.c | 16 ++++---- source/cart_hw/sram.h | 1 - 5 files changed, 56 insertions(+), 52 deletions(-) diff --git a/source/cart_hw/cart_hw.c b/source/cart_hw/cart_hw.c index 57d96a8..61cfd06 100644 --- a/source/cart_hw/cart_hw.c +++ b/source/cart_hw/cart_hw.c @@ -126,6 +126,8 @@ static uint8 mem_chunk[0x10000]; /* cart hardware detection */ void cart_hw_init() { + int i; + /*************************************************************************************************************** CARTRIDGE ROM MIRRORING *************************************************************************************************************** @@ -176,6 +178,7 @@ void cart_hw_init() while (cart.romsize > size) size <<= 1; /* total ROM size is not a factor of 2 */ + /* TODO: handle more possible ROM configurations (using cartridge database ???) */ if ((size < MAXROMSIZE) && (cart.romsize < size)) { /* two chips with different size */ @@ -200,20 +203,15 @@ void cart_hw_init() } /* ROM is mirrored each 2^k bytes */ - int i = size; - while (i < 0x400000) - { - memcpy(cart.rom + i, cart.rom, size); - i += size; - } - + cart.mask = size -1; + /********************************************** DEFAULT CARTRIDGE MAPPING ***********************************************/ for (i=0; i<0x40; i++) { /* 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].read16 = NULL; m68k_memory_map[i].write8 = m68k_unused_8_w; @@ -325,7 +323,7 @@ void cart_hw_init() break; 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) { /* load Sonic & Knuckles ROM (2 MBytes) */ @@ -340,16 +338,11 @@ void cart_hw_init() fread(cart.rom+0x900000,1,0x40000,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 /* Byteswap ROM */ int i; uint8 temp; - for(i = 0; i < 0x300000; i += 2) + for(i = 0; i < 0x240000; i += 2) { temp = cart.rom[i+0x700000]; cart.rom[i+0x700000] = cart.rom[i+1+0x700000]; @@ -357,6 +350,10 @@ void cart_hw_init() } #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; } @@ -449,7 +446,7 @@ void cart_hw_reset() if (cart.hw.bankshift) { 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 */ @@ -482,10 +479,8 @@ void cart_hw_reset() if (cart.lock_on) { /* 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++) - m68k_memory_map[i].base = cart.rom + (i<<16); + m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask); } 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) */ if (data & 1) { - /* SRAM enabled */ - m68k_memory_map[0x20].base = sram.sram; + /* $200000-$3fffff is mapped to SRAM (only if SRAM exists) */ + if (sram.on) + { + for (i=0x20; i<0x40; i++) + m68k_memory_map[i].base = sram.sram; - if (data & 2) - { - /* SRAM write disabled */ - m68k_memory_map[0x20].write8 = m68k_unused_8_w; - m68k_memory_map[0x20].write16 = m68k_unused_16_w; - zbank_memory_map[0x20].write = zbank_unused_w; - } - else - { - /* SRAM write enabled */ - m68k_memory_map[0x20].write8 = NULL; - m68k_memory_map[0x20].write16 = NULL; - zbank_memory_map[0x20].write = NULL; + if (data & 2) + { + /* SRAM write disabled */ + for (i=0x20; i<0x40; i++) + { + m68k_memory_map[i].write8 = m68k_unused_8_w; + m68k_memory_map[i].write16 = m68k_unused_16_w; + zbank_memory_map[i].write = zbank_unused_w; + } + } + else + { + /* 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) { /* enable UPMEM chip at $300000-$3fffff */ 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 { /* 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) { /* enable cartridge ROM at $300000-$3fffff */ 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; diff --git a/source/cart_hw/cart_hw.h b/source/cart_hw/cart_hw.h index 35629f8..a60c309 100644 --- a/source/cart_hw/cart_hw.h +++ b/source/cart_hw/cart_hw.h @@ -28,9 +28,9 @@ #define _CART_HW_H_ /* Lock-ON cartridge type */ -#define TYPE_GG 0x10 /* Game Genie */ -#define TYPE_AR 0x20 /* Action Replay (Pro) */ -#define TYPE_SK 0x40 /* Sonic & Knuckles */ +#define TYPE_GG 0x01 /* Game Genie */ +#define TYPE_AR 0x02 /* Action Replay (Pro) */ +#define TYPE_SK 0x03 /* Sonic & Knuckles */ /* Cartridge extra hardware */ typedef struct @@ -52,6 +52,7 @@ typedef struct { uint8 *rom; /* ROM data */ uint8 *base; /* ROM area (slot 0) */ + uint32 mask; /* mask ROM */ uint32 lock_on; /* 1: Lock-On enabled */ uint32 romsize; /* ROM size */ T_CART_HW hw; /* Custom hardware */ diff --git a/source/cart_hw/eeprom.c b/source/cart_hw/eeprom.c index 1dfa816..e77e38a 100644 --- a/source/cart_hw/eeprom.c +++ b/source/cart_hw/eeprom.c @@ -100,7 +100,6 @@ void eeprom_init() { sram.custom = 1; sram.on = 1; - sram.write = 1; memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE)); } } @@ -114,8 +113,7 @@ void eeprom_init() { sram.custom = 1; sram.on = 1; - sram.write = 1; - + /* set SEGA mapper as default */ memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE)); } diff --git a/source/cart_hw/sram.c b/source/cart_hw/sram.c index 5f50a72..970c6aa 100644 --- a/source/cart_hw/sram.c +++ b/source/cart_hw/sram.c @@ -57,6 +57,7 @@ void sram_init() sram.end = sram.start + 0xffff; sram.start &= 0xfffffffe; sram.end |= 1; + sram.on = 1; } else { @@ -66,24 +67,24 @@ void sram_init() } /* set SRAM ON by default when ROM is not mapped */ - if (cart.romsize <= sram.start) - { - sram.on = 1; - sram.write = 1; - } + if (cart.romsize <= sram.start) sram.on = 1; /* Some games with bad header or specific configuration */ if (strstr(rominfo.product,"T-113016") != NULL) { /* Pugsy (try accessing unmapped area for copy protection) */ 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)) { /* Psy-O-Blade (bad header) */ sram.on = 1; - sram.write = 1; sram.start = 0x200001; sram.end = 0x203fff; } @@ -91,7 +92,6 @@ void sram_init() { /* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */ sram.on = 1; - sram.write = 1; sram.start = 0x400000; sram.end = 0x40ffff; } diff --git a/source/cart_hw/sram.h b/source/cart_hw/sram.h index 040ef0b..4dd21e8 100644 --- a/source/cart_hw/sram.h +++ b/source/cart_hw/sram.h @@ -27,7 +27,6 @@ typedef struct { uint8 detected; uint8 on; - uint8 write; uint8 custom; uint32 start; uint32 end;