From cfe11b9b95f049d12b20ee72500404e7970ed9b3 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 6 Feb 2020 12:53:26 +0800 Subject: [PATCH] MMC1: Better work ram and battery saves support for size greater than 8K --- src/boards/mmc1.c | 123 +++++++++++++++++++++++++++------------------- src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index a3f670d..48752c0 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -22,12 +22,17 @@ #include "mapinc.h" static void GenMMC1Power(void); -static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery); +static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram); static uint8 DRegs[4]; static uint8 Buffer, BufferShift; -static int mmc1opts; +static uint32 WRAMSIZE = 0; + + /* size of non-battery-backed portion of WRAM */ + /* serves as starting offset for actual save ram from total wram size */ + /* returns 0 if entire work ram is battery backed ram */ +static uint32 NONSaveRAMSIZE = 0; static void (*MMC1CHRHook4)(uint32 A, uint8 V); static void (*MMC1PRGHook16)(uint32 A, uint8 V); @@ -52,9 +57,9 @@ static DECLFR(MAWRAM) { } static void MMC1CHR(void) { - if (mmc1opts & 4) { - if (DRegs[0] & 0x10) - setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1); + if (WRAMSIZE > 8192) { + if (WRAMSIZE > 16384) + setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); else setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); } @@ -183,24 +188,44 @@ static void MMC1CMReset(void) { MMC1PRG(); } -static int DetectMMC1WRAMSize(uint32 crc32) { - switch (crc32) { - case 0xc6182024: /* Romance of the 3 Kingdoms */ - case 0x2225c20f: /* Genghis Khan */ - case 0x4642dda6: /* Nobunaga's Ambition */ - case 0x29449ba9: /* "" "" (J) */ - case 0x2b11e0b0: /* "" "" (J) */ - case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) */ - case 0xc9556b36: /* Final Fantasy I & II (J) [!] */ - FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n"); - return(16); +static int DetectMMC1WRAMSize(CartInfo *info, int *saveRAM) { + int workRAM = 8; + switch (info->CRC32) { + case 0xc6182024: /* Romance of the 3 Kingdoms */ + case 0xabbf7217: /* "" "" (J) (PRG0) */ + case 0xccf35c02: /* "" "" (J) (PRG1) */ + case 0x2225c20f: /* Genghis Khan */ + case 0xfb69743a: /* "" "" (J) */ + case 0x4642dda6: /* Nobunaga's Ambition */ + case 0x3f7ad415: /* "" "" (J) (PRG0) */ + case 0x2b11e0b0: /* "" "" (J) (PRG1) */ + *saveRAM = 8; + workRAM = 16; + break; + case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) (PRG0) */ + case 0xc3de7c69: /* "" "" (J) (PRG1) */ + case 0xc9556b36: /* Final Fantasy I & II (J) [!] */ + *saveRAM = 32; + workRAM = 32; + break; + default: + if (info->iNES2) { + workRAM = (info->prgRam + info->prgRam_battery) / 1024; + *saveRAM = info->prgRam_battery / 1024; + /* we only support sizes between 8K and 32K */ + if (workRAM > 0 && workRAM < 8) + workRAM = 8; + if (workRAM > 32) + workRAM = 32; + if (*saveRAM > workRAM) + *saveRAM = workRAM; + } break; - case 0xd1e50064: /* Dezaemon */ - FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n"); - return(32); - break; - default: return(8); - } + } + if (workRAM > 8) + FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n"); + + return workRAM; } static uint32 NWCIRQCount; @@ -258,17 +283,16 @@ void Mapper105_Init(CartInfo *info) { static void GenMMC1Power(void) { lreset = 0; - if (mmc1opts & 1) { - FCEU_CheatAddRAM(8, 0x6000, WRAM); - if (mmc1opts & 4) - FCEU_dwmemset(WRAM, 0, 8192) - else if (!(mmc1opts & 2)) - FCEU_dwmemset(WRAM, 0, 8192); - } SetWriteHandler(0x8000, 0xFFFF, MMC1_write); SetReadHandler(0x8000, 0xFFFF, CartBR); - if (mmc1opts & 1) { + if (WRAMSIZE) { + FCEU_CheatAddRAM(8, 0x6000, WRAM); + + /* clear non-battery-backed portion of WRAM */ + if (NONSaveRAMSIZE) + FCEU_dwmemset(WRAM, 0, NONSaveRAMSIZE); + SetReadHandler(0x6000, 0x7FFF, MAWRAM); SetWriteHandler(0x6000, 0x7FFF, MBWRAM); setprg8r(0x10, 0x6000, 0); @@ -285,26 +309,24 @@ static void GenMMC1Close(void) { CHRRAM = WRAM = NULL; } -static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) { +static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) { is155 = 0; info->Close = GenMMC1Close; MMC1PRGHook16 = MMC1CHRHook4 = 0; - mmc1opts = 0; + WRAMSIZE = wram * 1024; + NONSaveRAMSIZE = (wram - saveram) * 1024; PRGmask16[0] &= (prg >> 14) - 1; CHRmask4[0] &= (chr >> 12) - 1; CHRmask8[0] &= (chr >> 13) - 1; - if (wram) { - WRAM = (uint8*)FCEU_gmalloc(wram * 1024); - mmc1opts |= 1; - if (wram > 8) mmc1opts |= 4; - SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1); - AddExState(WRAM, wram * 1024, 0, "WRAM"); - if (battery) { - mmc1opts |= 2; - info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0); - info->SaveGameLen[0] = 8192; + if (WRAMSIZE) { + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (saveram) { + info->SaveGame[0] = WRAM + NONSaveRAMSIZE; + info->SaveGameLen[0] = saveram * 1024; } } if (!chr) { @@ -322,13 +344,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) } void Mapper1_Init(CartInfo *info) { - int ws = DetectMMC1WRAMSize(info->CRC32); - GenMMC1Init(info, 512, 256, ws, info->battery); + int bs = info->battery ? 8 : 0; + int ws = DetectMMC1WRAMSize(info, &bs); + GenMMC1Init(info, 512, 256, ws, bs); } /* Same as mapper 1, without respect for WRAM enable bit. */ void Mapper155_Init(CartInfo *info) { - GenMMC1Init(info, 512, 256, 8, info->battery); + GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0); is155 = 1; } @@ -340,7 +363,7 @@ void Mapper171_Init(CartInfo *info) { } void SAROM_Init(CartInfo *info) { - GenMMC1Init(info, 128, 64, 8, info->battery); + GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0); } void SBROM_Init(CartInfo *info) { @@ -360,7 +383,7 @@ void SGROM_Init(CartInfo *info) { } void SKROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 64, 8, info->battery); + GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0); } void SLROM_Init(CartInfo *info) { @@ -392,11 +415,11 @@ void SHROM_Init(CartInfo *info) { /* */ void SNROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 0, 8, info->battery); + GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0); } void SOROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 0, 16, info->battery); + GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0); } /* ----------------------- FARID_SLROM_8-IN-1 -----------------------*/ @@ -490,7 +513,7 @@ static void Sync(void) { MMC1PRG(); MMC1CHR(); MMC1MIRROR(); - } else { + } else { /* Mapper 70 */ setprg16(0x8000, ((mode & 2) << 1) | ((latch >> 4) & 3)); setprg16(0xC000, ((mode & 2) << 1) | 3); diff --git a/src/ines.c b/src/ines.c index f0b8b07..0ae0367 100644 --- a/src/ines.c +++ b/src/ines.c @@ -676,6 +676,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"830928C", 382, Mapper382_Init}, {(uint8_t*)"NJ064", 534, Mapper534_Init}, {(uint8_t*)"Kid Ikarus (FDS)", 539, Mapper539_Init}, +/* {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, */ /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index 997a8ef..1a498d9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -258,5 +258,6 @@ void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper541_Init(CartInfo *); +void Mapper543_Init(CartInfo *); #endif