diff --git a/src/gba/context/overrides.c b/src/gba/context/overrides.c index 85e0f8462..ef9632e27 100644 --- a/src/gba/context/overrides.c +++ b/src/gba/context/overrides.c @@ -15,6 +15,10 @@ static const struct GBACartridgeOverride _overrides[] = { { "AWRE", SAVEDATA_FLASH512, HW_NONE, 0x8038810 }, { "AWRP", SAVEDATA_FLASH512, HW_NONE, 0x8038810 }, + // Advance Wars 2: Black Hole Rising + { "AW2E", SAVEDATA_FLASH512, HW_NONE, 0x8036E08 }, + { "AW2P", SAVEDATA_FLASH512, HW_NONE, 0x803719C }, + // Boktai: The Sun is in Your Hand { "U3IJ", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, { "U3IE", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, diff --git a/src/gba/io.c b/src/gba/io.c index db4ee0f95..688805af2 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -565,8 +565,34 @@ void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) { gba->memory.io[(address >> 1) + 1] = value >> 16; } +bool GBAIOIsReadConstant(uint32_t address) { + switch (address) { + default: + return false; + case REG_BG0CNT: + case REG_BG1CNT: + case REG_BG2CNT: + case REG_BG3CNT: + case REG_WININ: + case REG_WINOUT: + case REG_BLDCNT: + case REG_BLDALPHA: + case REG_DMA0CNT_LO: + case REG_DMA1CNT_LO: + case REG_DMA2CNT_LO: + case REG_DMA3CNT_LO: + case REG_KEYINPUT: + case REG_IE: + return true; + } +} + uint16_t GBAIORead(struct GBA* gba, uint32_t address) { - gba->haltPending = false; // IO reads need to invalidate detected idle loops + if (!GBAIOIsReadConstant(address)) { + // Most IO reads need to disable idle removal + gba->haltPending = false; + } + switch (address) { case REG_TM0CNT_LO: GBATimerUpdateRegister(gba, 0); diff --git a/src/gba/io.h b/src/gba/io.h index c6e988097..2c9b80afb 100644 --- a/src/gba/io.h +++ b/src/gba/io.h @@ -159,6 +159,8 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value); void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value); uint16_t GBAIORead(struct GBA* gba, uint32_t address); +bool GBAIOIsReadConstant(uint32_t address); + struct GBASerializedState; void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state); void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state); diff --git a/src/gba/memory.c b/src/gba/memory.c index 056058af2..3a6e11408 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -156,7 +156,7 @@ static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t a } else { loadAddress += offset; } - if ((loadAddress >> BASE_OFFSET) == REGION_IO) { + if ((loadAddress >> BASE_OFFSET) == REGION_IO && !GBAIOIsReadConstant(loadAddress)) { gba->idleDetectionStep = -1; return; }