GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301, fixes mgba.io/i/1320)

This commit is contained in:
Vicki Pfau 2020-01-24 18:06:23 -08:00
parent 38613e1c78
commit 93633ea605
7 changed files with 9 additions and 2 deletions

View File

@ -2,6 +2,7 @@
Emulation fixes: Emulation fixes:
- ARM: Fix ALU reading PC after shifting - ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation - ARM: Fix STR storing PC after address calculation
- GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320)
- GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Misaligned SRAM writes are ignored
- GBA Serialize: Fix serializing DMA transfer register - GBA Serialize: Fix serializing DMA transfer register
Other fixes: Other fixes:

View File

@ -109,6 +109,7 @@ struct GBA {
bool haltPending; bool haltPending;
bool cpuBlocked; bool cpuBlocked;
bool earlyExit; bool earlyExit;
uint32_t dmaPC;
int idleDetectionStep; int idleDetectionStep;
int idleDetectionFailures; int idleDetectionFailures;
int32_t cachedRegisters[16]; int32_t cachedRegisters[16];

View File

@ -300,8 +300,9 @@ struct GBASerializedState {
} hw; } hw;
uint32_t dmaTransferRegister; uint32_t dmaTransferRegister;
uint32_t dmaBlockPC;
uint32_t reservedHardware[5]; uint32_t reservedHardware[4];
struct { struct {
uint8_t type; uint8_t type;

View File

@ -219,6 +219,7 @@ void GBADMAUpdate(struct GBA* gba) {
} }
if (memory->activeDMA >= 0) { if (memory->activeDMA >= 0) {
gba->dmaPC = gba->cpu->gprs[ARM_PC];
mTimingDeschedule(&gba->timing, &memory->dmaEvent); mTimingDeschedule(&gba->timing, &memory->dmaEvent);
mTimingSchedule(&gba->timing, &memory->dmaEvent, memory->dma[memory->activeDMA].when - currentTime); mTimingSchedule(&gba->timing, &memory->dmaEvent, memory->dma[memory->activeDMA].when - currentTime);
} else { } else {

View File

@ -203,6 +203,7 @@ void GBAReset(struct ARMCore* cpu) {
gba->cpuBlocked = false; gba->cpuBlocked = false;
gba->earlyExit = false; gba->earlyExit = false;
gba->dmaPC = 0;
if (gba->yankedRomSize) { if (gba->yankedRomSize) {
gba->memory.romSize = gba->yankedRomSize; gba->memory.romSize = gba->yankedRomSize;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->memory.romMask = toPow2(gba->memory.romSize) - 1;

View File

@ -951,6 +951,7 @@ void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
} }
STORE_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister); STORE_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister);
STORE_32(gba->dmaPC, 0, &state->dmaBlockPC);
GBAHardwareSerialize(&gba->memory.hw, state); GBAHardwareSerialize(&gba->memory.hw, state);
} }
@ -995,6 +996,7 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]); GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
LOAD_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister); LOAD_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister);
LOAD_32(gba->dmaPC, 0, &state->dmaBlockPC);
GBADMAUpdate(gba); GBADMAUpdate(gba);
GBAHardwareDeserialize(&gba->memory.hw, state); GBAHardwareDeserialize(&gba->memory.hw, state);

View File

@ -337,7 +337,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
} }
#define LOAD_BAD \ #define LOAD_BAD \
if (gba->performingDMA) { \ if (gba->performingDMA || cpu->gprs[ARM_PC] - gba->dmaPC == (gba->cpu->executionMode == MODE_THUMB ? WORD_SIZE_THUMB : WORD_SIZE_ARM)) { \
value = gba->bus; \ value = gba->bus; \
} else { \ } else { \
value = cpu->prefetch[1]; \ value = cpu->prefetch[1]; \