mirror of https://github.com/mgba-emu/mgba.git
GBA DMA: Cache cycle estimation on first DMA
This commit is contained in:
parent
afff68cfc0
commit
4a5a25e90c
|
@ -48,6 +48,7 @@ struct GBADMA {
|
|||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
uint32_t when;
|
||||
int32_t cycles;
|
||||
};
|
||||
|
||||
struct GBA;
|
||||
|
@ -65,6 +66,7 @@ void GBADMARunHblank(struct GBA* gba, int32_t cycles);
|
|||
void GBADMARunVblank(struct GBA* gba, int32_t cycles);
|
||||
void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles);
|
||||
void GBADMAUpdate(struct GBA* gba);
|
||||
void GBADMARecalculateCycles(struct GBA* gba);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -309,6 +309,7 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
|
|||
if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) {
|
||||
dma->when = mTimingCurrentTime(&audio->p->timing) - cycles;
|
||||
dma->nextCount = 4;
|
||||
GBADMARecalculateCycles(audio->p);
|
||||
GBADMASchedule(audio->p, channel->dmaSource, dma);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,16 +256,22 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
if (info->count == info->nextCount) {
|
||||
if (width == 4) {
|
||||
cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
|
||||
info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||
} else {
|
||||
cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
|
||||
info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||
}
|
||||
} else {
|
||||
// Crossed region boundary; recalculate cached cycles
|
||||
if (UNLIKELY(!(source & 0x00FFFFFC) || !(dest & 0x00FFFFFC))) {
|
||||
if (width == 4) {
|
||||
cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||
info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||
} else {
|
||||
cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||
info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||
}
|
||||
}
|
||||
cycles += info->cycles;
|
||||
}
|
||||
info->when += cycles;
|
||||
|
||||
if (width == 4) {
|
||||
|
@ -281,7 +287,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0);
|
||||
memory->dmaTransferRegister |= memory->dmaTransferRegister << 16;
|
||||
}
|
||||
if (destRegion == GBA_REGION_ROM2_EX) {
|
||||
if (UNLIKELY(destRegion == GBA_REGION_ROM2_EX)) {
|
||||
if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) {
|
||||
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
||||
GBASavedataInitEEPROM(&memory->savedata);
|
||||
|
@ -327,3 +333,22 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
}
|
||||
GBADMAUpdate(gba);
|
||||
}
|
||||
|
||||
void GBADMARecalculateCycles(struct GBA* gba) {
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
struct GBADMA* dma = &gba->memory.dma[i];
|
||||
if (!GBADMARegisterIsEnable(dma->reg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t width = GBADMARegisterGetWidth(dma->reg);
|
||||
uint32_t sourceRegion = dma->nextSource >> BASE_OFFSET;
|
||||
uint32_t destRegion = dma->nextDest >> BASE_OFFSET;
|
||||
if (width) {
|
||||
dma->cycles = gba->memory.waitstatesSeq32[sourceRegion] + gba->memory.waitstatesSeq32[destRegion];
|
||||
} else {
|
||||
dma->cycles = gba->memory.waitstatesSeq16[sourceRegion] + gba->memory.waitstatesSeq16[destRegion];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1079,6 +1079,7 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
LOAD_32(gba->dmaPC, 0, &state->dmaBlockPC);
|
||||
LOAD_32(gba->bus, 0, &state->bus);
|
||||
|
||||
GBADMARecalculateCycles(gba);
|
||||
GBADMAUpdate(gba);
|
||||
GBAHardwareDeserialize(&gba->memory.hw, state);
|
||||
}
|
||||
|
|
|
@ -1734,6 +1734,10 @@ void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
|
|||
STORE_32(memory->agbPrintFuncBackup, AGB_PRINT_FLUSH_ADDR | base, memory->rom);
|
||||
}
|
||||
}
|
||||
|
||||
if (gba->performingDMA) {
|
||||
GBADMARecalculateCycles(gba);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters) {
|
||||
|
|
Loading…
Reference in New Issue