MMC5 arbitrary WRAM size support via iNES 2 (#84)

This commit is contained in:
Brad Smith 2019-11-22 23:22:08 -05:00 committed by GitHub
parent fbabd180eb
commit 88d7f392a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 49 additions and 20 deletions

View File

@ -100,8 +100,9 @@ static uint8 *WRAM = NULL;
static uint8 *MMC5fill = NULL; static uint8 *MMC5fill = NULL;
static uint8 *ExRAM = NULL; static uint8 *ExRAM = NULL;
const int MMC5WRAMMAX = 1<<7; // 7 bits in register interface (real MMC5 has only 4 pins, however)
static uint8 MMC5WRAMsize; //configuration, not state static uint8 MMC5WRAMsize; //configuration, not state
static uint8 MMC5WRAMIndex[8]; //configuration, not state static uint8 MMC5WRAMIndex[MMC5WRAMMAX]; //configuration, not state
static uint8 MMC5ROMWrProtect[4]; static uint8 MMC5ROMWrProtect[4];
static uint8 MMC5MemIn[5]; static uint8 MMC5MemIn[5];
@ -314,6 +315,8 @@ int DetectMMC5WRAMSize(uint32 crc32) {
} }
static void BuildWRAMSizeTable(void) { static void BuildWRAMSizeTable(void) {
bool other = false; // non-standard configuration
// fill first 8 entries
int x; int x;
for (x = 0; x < 8; x++) { for (x = 0; x < 8; x++) {
switch (MMC5WRAMsize) { switch (MMC5WRAMsize) {
@ -322,8 +325,21 @@ static void BuildWRAMSizeTable(void) {
case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1 case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1
case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7 case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
default: MMC5WRAMIndex[x] = x; other = true; break; //0,1,2...
} }
} }
// extend to fill complete table
if (other)
{
for (x = 0; x < MMC5WRAMMAX && x < MMC5WRAMsize; ++x) MMC5WRAMIndex[x] = x; // linear mapping
for (x = MMC5WRAMsize; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x-MMC5WRAMsize]; // repeat to fill table
// theoretically the table fill should decompose into powers of two for possible mismatched SRAM combos,
// but I don't want to complicate the code with unnecessary hypotheticals
}
else
{
for (x = 8; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x & 7]; // fill table, repeating groups of 8
}
} }
static void MMC5CHRA(void) { static void MMC5CHRA(void) {
@ -391,7 +407,7 @@ static void MMC5CHRB(void) {
} }
static void MMC5WRAM(uint32 A, uint32 V) { static void MMC5WRAM(uint32 A, uint32 V) {
V = MMC5WRAMIndex[V & 7]; V = MMC5WRAMIndex[V & (MMC5WRAMMAX-1)];
if (V != 255) { if (V != 255) {
setprg8r(0x10, A, V); setprg8r(0x10, A, V);
FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1)))); FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1))));
@ -416,8 +432,8 @@ static void MMC5PRG(void) {
MMC5MemIn[1] = MMC5MemIn[2] = 1; MMC5MemIn[1] = MMC5MemIn[2] = 1;
} else { } else {
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
} }
MMC5MemIn[3] = MMC5MemIn[4] = 1; MMC5MemIn[3] = MMC5MemIn[4] = 1;
MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1;
@ -430,8 +446,8 @@ static void MMC5PRG(void) {
setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1); setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1);
} else { } else {
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
} }
if (PRGBanks[2] & 0x80) { if (PRGBanks[2] & 0x80) {
MMC5ROMWrProtect[2] = 1; MMC5ROMWrProtect[2] = 1;
@ -439,7 +455,7 @@ static void MMC5PRG(void) {
setprg8(0xC000, PRGBanks[2] & 0x7F); setprg8(0xC000, PRGBanks[2] & 0x7F);
} else { } else {
MMC5ROMWrProtect[2] = 0; MMC5ROMWrProtect[2] = 0;
MMC5WRAM(0xC000, PRGBanks[2] & 7); MMC5WRAM(0xC000, PRGBanks[2] & (MMC5WRAMMAX-1));
} }
MMC5MemIn[4] = 1; MMC5MemIn[4] = 1;
MMC5ROMWrProtect[3] = 1; MMC5ROMWrProtect[3] = 1;
@ -453,7 +469,7 @@ static void MMC5PRG(void) {
MMC5MemIn[1 + x] = 1; MMC5MemIn[1 + x] = 1;
} else { } else {
MMC5ROMWrProtect[x] = 0; MMC5ROMWrProtect[x] = 0;
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7); MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & (MMC5WRAMMAX-1));
} }
MMC5MemIn[4] = 1; MMC5MemIn[4] = 1;
MMC5ROMWrProtect[3] = 1; MMC5ROMWrProtect[3] = 1;
@ -516,7 +532,7 @@ static DECLFW(Mapper5_write) {
break; break;
case 0x5113: case 0x5113:
WRAMPage = V; WRAMPage = V;
MMC5WRAM(0x6000, V & 7); MMC5WRAM(0x6000, V & (MMC5WRAMMAX-1));
break; break;
case 0x5114: case 0x5114:
case 0x5115: case 0x5115:
@ -612,7 +628,7 @@ void MMC5Synco(void) {
case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break; case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break;
} }
} }
MMC5WRAM(0x6000, WRAMPage & 7); MMC5WRAM(0x6000, WRAMPage & (MMC5WRAMMAX-1));
if (!mmc5ABMode) { if (!mmc5ABMode) {
MMC5CHRB(); MMC5CHRB();
MMC5CHRA(); MMC5CHRA();
@ -984,7 +1000,12 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
if (battery) { if (battery) {
info->SaveGame[0] = WRAM; info->SaveGame[0] = WRAM;
if (info->ines2)
{
info->SaveGameLen[0] = info->battery_wram_size;
}
else
{
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you //this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
//I added 64KB for the new 64KB homebrews //I added 64KB for the new 64KB homebrews
if (wsize <= 16) if (wsize <= 16)
@ -994,6 +1015,7 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
else else
info->SaveGameLen[0] = 32768; info->SaveGameLen[0] = 32768;
} }
}
MMC5HackVROMMask = CHRmask4[0]; MMC5HackVROMMask = CHRmask4[0];
MMC5HackExNTARAMPtr = ExRAM; MMC5HackExNTARAMPtr = ExRAM;
@ -1008,7 +1030,14 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
} }
void Mapper5_Init(CartInfo *info) { void Mapper5_Init(CartInfo *info) {
if (info->ines2)
{
WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024;
}
else
{
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32); WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
}
GenMMC5_Init(info, WRAMSIZE, info->battery); GenMMC5_Init(info, WRAMSIZE, info->battery);
} }