mirror of https://github.com/mgba-emu/mgba.git
GBA: Fix 1 MiB ROM mirroring to only mirror 4 times
This commit is contained in:
parent
e0b07a6446
commit
4b0ea00ba1
1
CHANGES
1
CHANGES
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue