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;
|
uint32_t nextDest;
|
||||||
int32_t nextCount;
|
int32_t nextCount;
|
||||||
uint32_t when;
|
uint32_t when;
|
||||||
|
int32_t cycles;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GBA;
|
struct GBA;
|
||||||
@ -65,6 +66,7 @@ void GBADMARunHblank(struct GBA* gba, int32_t cycles);
|
|||||||
void GBADMARunVblank(struct GBA* gba, int32_t cycles);
|
void GBADMARunVblank(struct GBA* gba, int32_t cycles);
|
||||||
void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles);
|
void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles);
|
||||||
void GBADMAUpdate(struct GBA* gba);
|
void GBADMAUpdate(struct GBA* gba);
|
||||||
|
void GBADMARecalculateCycles(struct GBA* gba);
|
||||||
|
|
||||||
CXX_GUARD_END
|
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) {
|
if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) {
|
||||||
dma->when = mTimingCurrentTime(&audio->p->timing) - cycles;
|
dma->when = mTimingCurrentTime(&audio->p->timing) - cycles;
|
||||||
dma->nextCount = 4;
|
dma->nextCount = 4;
|
||||||
|
GBADMARecalculateCycles(audio->p);
|
||||||
GBADMASchedule(audio->p, channel->dmaSource, dma);
|
GBADMASchedule(audio->p, channel->dmaSource, dma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,15 +256,21 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||||||
if (info->count == info->nextCount) {
|
if (info->count == info->nextCount) {
|
||||||
if (width == 4) {
|
if (width == 4) {
|
||||||
cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
|
cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
|
||||||
|
info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||||
} else {
|
} else {
|
||||||
cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
|
cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
|
||||||
|
info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (width == 4) {
|
// Crossed region boundary; recalculate cached cycles
|
||||||
cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
if (UNLIKELY(!(source & 0x00FFFFFC) || !(dest & 0x00FFFFFC))) {
|
||||||
} else {
|
if (width == 4) {
|
||||||
cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
|
||||||
|
} else {
|
||||||
|
info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cycles += info->cycles;
|
||||||
}
|
}
|
||||||
info->when += cycles;
|
info->when += cycles;
|
||||||
|
|
||||||
@ -281,7 +287,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||||||
memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0);
|
memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0);
|
||||||
memory->dmaTransferRegister |= memory->dmaTransferRegister << 16;
|
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) {
|
if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) {
|
||||||
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
||||||
GBASavedataInitEEPROM(&memory->savedata);
|
GBASavedataInitEEPROM(&memory->savedata);
|
||||||
@ -327,3 +333,22 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||||||
}
|
}
|
||||||
GBADMAUpdate(gba);
|
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->dmaPC, 0, &state->dmaBlockPC);
|
||||||
LOAD_32(gba->bus, 0, &state->bus);
|
LOAD_32(gba->bus, 0, &state->bus);
|
||||||
|
|
||||||
|
GBADMARecalculateCycles(gba);
|
||||||
GBADMAUpdate(gba);
|
GBADMAUpdate(gba);
|
||||||
GBAHardwareDeserialize(&gba->memory.hw, state);
|
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);
|
STORE_32(memory->agbPrintFuncBackup, AGB_PRINT_FLUSH_ADDR | base, memory->rom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gba->performingDMA) {
|
||||||
|
GBADMARecalculateCycles(gba);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters) {
|
void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user