GBA: Fix 1 MiB ROM mirroring to only mirror 4 times

This commit is contained in:
Vicki Pfau 2022-09-07 20:26:35 -07:00
parent e0b07a6446
commit 4b0ea00ba1
4 changed files with 15 additions and 20 deletions

View File

@ -33,6 +33,7 @@ Emulation fixes:
- GBA: Improve timing when not booting from BIOS - GBA: Improve timing when not booting from BIOS
- GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450) - GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450)
- GBA: Fix booting multiboot ROMs with no JOY entrypoint - GBA: Fix booting multiboot ROMs with no JOY entrypoint
- GBA: Fix 1 MiB ROM mirroring to only mirror 4 times
- GBA Audio: Adjust PSG sampling rate with SOUNDBIAS - GBA Audio: Adjust PSG sampling rate with SOUNDBIAS
- GBA Audio: Sample FIFOs at SOUNDBIAS-set frequency - GBA Audio: Sample FIFOs at SOUNDBIAS-set frequency
- GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059) - GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059)

View File

@ -364,7 +364,6 @@ bool GBALoadNull(struct GBA* gba) {
gba->yankedRomSize = 0; gba->yankedRomSize = 0;
gba->memory.romSize = SIZE_CART0; gba->memory.romSize = SIZE_CART0;
gba->memory.romMask = SIZE_CART0 - 1; gba->memory.romMask = SIZE_CART0 - 1;
gba->memory.mirroring = false;
gba->romCrc32 = 0; gba->romCrc32 = 0;
if (gba->cpu) { if (gba->cpu) {
@ -419,6 +418,19 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
gba->memory.romSize = SIZE_CART0; gba->memory.romSize = SIZE_CART0;
} }
gba->pristineRomSize = SIZE_CART0; gba->pristineRomSize = SIZE_CART0;
} else if (gba->pristineRomSize == 0x00100000) {
// 1 MiB ROMs (e.g. Classic NES) all appear as 4x mirrored, but not more
gba->isPristine = false;
gba->memory.romSize = 0x00400000;
#ifdef FIXED_ROM_BUFFER
gba->memory.rom = romBuffer;
#else
gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
#endif
vf->read(vf, gba->memory.rom, gba->pristineRomSize);
memcpy(&gba->memory.rom[0x40000], gba->memory.rom, 0x00100000);
memcpy(&gba->memory.rom[0x80000], gba->memory.rom, 0x00100000);
memcpy(&gba->memory.rom[0xC0000], gba->memory.rom, 0x00100000);
} else { } else {
gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ);
gba->memory.romSize = gba->pristineRomSize; gba->memory.romSize = gba->pristineRomSize;
@ -430,8 +442,7 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
} }
gba->yankedRomSize = 0; gba->yankedRomSize = 0;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
gba->memory.mirroring = false; gba->romCrc32 = doCrc32(gba->memory.rom, gba->pristineRomSize);
gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
if (popcount32(gba->memory.romSize) != 1) { if (popcount32(gba->memory.romSize) != 1) {
// This ROM is either a bad dump or homebrew. Emulate flash cart behavior. // This ROM is either a bad dump or homebrew. Emulate flash cart behavior.
#ifndef FIXED_ROM_BUFFER #ifndef FIXED_ROM_BUFFER

View File

@ -83,7 +83,6 @@ void GBAMemoryInit(struct GBA* gba) {
cpu->memory.activeNonseqCycles32 = 0; cpu->memory.activeNonseqCycles32 = 0;
cpu->memory.activeNonseqCycles16 = 0; cpu->memory.activeNonseqCycles16 = 0;
gba->memory.biosPrefetch = 0; gba->memory.biosPrefetch = 0;
gba->memory.mirroring = false;
gba->memory.agbPrintProtect = 0; gba->memory.agbPrintProtect = 0;
memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx)); memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx));
@ -277,9 +276,6 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) { if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) {
return; return;
} }
if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
return;
}
} }
if (memory->activeRegion == REGION_BIOS) { if (memory->activeRegion == REGION_BIOS) {
@ -411,8 +407,6 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
wait += waitstatesRegion[address >> BASE_OFFSET]; \ wait += waitstatesRegion[address >> BASE_OFFSET]; \
if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \ if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \ LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) { \
LOAD_32(value, address & memory->romMask & -4, memory->rom); \
} else if (memory->vfame.cartType) { \ } else if (memory->vfame.cartType) { \
value = GBAVFameGetPatternValue(address, 32); \ value = GBAVFameGetPatternValue(address, 32); \
} else { \ } else { \
@ -578,8 +572,6 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < memory->romSize) { if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom); LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
LOAD_16(value, address & memory->romMask, memory->rom);
} else if (memory->vfame.cartType) { } else if (memory->vfame.cartType) {
value = GBAVFameGetPatternValue(address, 16); value = GBAVFameGetPatternValue(address, 16);
} else if ((address & (SIZE_CART0 - 1)) >= AGB_PRINT_BASE) { } else if ((address & (SIZE_CART0 - 1)) >= AGB_PRINT_BASE) {
@ -605,8 +597,6 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
value = GBACartEReaderRead(&memory->ereader, address); value = GBACartEReaderRead(&memory->ereader, address);
} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) { } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom); LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
LOAD_16(value, address & memory->romMask, memory->rom);
} else if (memory->vfame.cartType) { } else if (memory->vfame.cartType) {
value = GBAVFameGetPatternValue(address, 16); value = GBAVFameGetPatternValue(address, 16);
} else { } else {
@ -698,8 +688,6 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < memory->romSize) { if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)]; value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
value = ((uint8_t*) memory->rom)[address & memory->romMask];
} else if (memory->vfame.cartType) { } else if (memory->vfame.cartType) {
value = GBAVFameGetPatternValue(address, 8); value = GBAVFameGetPatternValue(address, 8);
} else { } else {

View File

@ -229,7 +229,6 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver
if (!found && override->id[0] == 'F') { if (!found && override->id[0] == 'F') {
// Classic NES Series // Classic NES Series
override->savetype = SAVEDATA_EEPROM; override->savetype = SAVEDATA_EEPROM;
override->mirroring = true;
found = true; found = true;
} }
@ -377,10 +376,6 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri
gba->idleOptimization = IDLE_LOOP_REMOVE; gba->idleOptimization = IDLE_LOOP_REMOVE;
} }
} }
if (override->mirroring) {
gba->memory.mirroring = true;
}
} }
void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) { void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) {