diff --git a/CHANGES b/CHANGES index 5c1599a20..afb21e008 100644 --- a/CHANGES +++ b/CHANGES @@ -33,6 +33,7 @@ Emulation fixes: - GBA: Improve timing when not booting from BIOS - GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450) - 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: Sample FIFOs at SOUNDBIAS-set frequency - GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059) diff --git a/src/gba/gba.c b/src/gba/gba.c index a6df59f4c..70da8e345 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -364,7 +364,6 @@ bool GBALoadNull(struct GBA* gba) { gba->yankedRomSize = 0; gba->memory.romSize = SIZE_CART0; gba->memory.romMask = SIZE_CART0 - 1; - gba->memory.mirroring = false; gba->romCrc32 = 0; if (gba->cpu) { @@ -419,6 +418,19 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) { gba->memory.romSize = 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 { gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); gba->memory.romSize = gba->pristineRomSize; @@ -430,8 +442,7 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) { } gba->yankedRomSize = 0; gba->memory.romMask = toPow2(gba->memory.romSize) - 1; - gba->memory.mirroring = false; - gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize); + gba->romCrc32 = doCrc32(gba->memory.rom, gba->pristineRomSize); if (popcount32(gba->memory.romSize) != 1) { // This ROM is either a bad dump or homebrew. Emulate flash cart behavior. #ifndef FIXED_ROM_BUFFER diff --git a/src/gba/memory.c b/src/gba/memory.c index 1878e7bb2..c9a1f59dd 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -83,7 +83,6 @@ void GBAMemoryInit(struct GBA* gba) { cpu->memory.activeNonseqCycles32 = 0; cpu->memory.activeNonseqCycles16 = 0; gba->memory.biosPrefetch = 0; - gba->memory.mirroring = false; gba->memory.agbPrintProtect = 0; 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) { return; } - if (memory->mirroring && (address & memory->romMask) < memory->romSize) { - return; - } } if (memory->activeRegion == REGION_BIOS) { @@ -411,8 +407,6 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { wait += waitstatesRegion[address >> BASE_OFFSET]; \ if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \ 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) { \ value = GBAVFameGetPatternValue(address, 32); \ } else { \ @@ -578,8 +572,6 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < memory->romSize) { 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) { value = GBAVFameGetPatternValue(address, 16); } 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); } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) { 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) { value = GBAVFameGetPatternValue(address, 16); } else { @@ -698,8 +688,6 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < memory->romSize) { 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) { value = GBAVFameGetPatternValue(address, 8); } else { diff --git a/src/gba/overrides.c b/src/gba/overrides.c index 823957d5c..a0593a90e 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -229,7 +229,6 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver if (!found && override->id[0] == 'F') { // Classic NES Series override->savetype = SAVEDATA_EEPROM; - override->mirroring = true; found = true; } @@ -377,10 +376,6 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri gba->idleOptimization = IDLE_LOOP_REMOVE; } } - - if (override->mirroring) { - gba->memory.mirroring = true; - } } void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) {