mirror of https://github.com/mgba-emu/mgba.git
GBA Memory: Fix DMA timing
This commit is contained in:
parent
82a0088e1e
commit
a1689c80a7
|
@ -68,6 +68,10 @@ int32_t mTimingTick(struct mTiming* timing, int32_t cycles) {
|
|||
return *timing->nextEvent;
|
||||
}
|
||||
|
||||
int32_t mTimingCurrentTime(struct mTiming* timing) {
|
||||
return timing->masterCycles + *timing->relativeCycles;
|
||||
}
|
||||
|
||||
int32_t mTimingNextEvent(struct mTiming* timing) {
|
||||
struct mTimingEvent* next = timing->root;
|
||||
if (!next) {
|
||||
|
|
|
@ -32,6 +32,7 @@ void mTimingClear(struct mTiming* timing);
|
|||
void mTimingSchedule(struct mTiming* timing, struct mTimingEvent*, int32_t when);
|
||||
void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent*);
|
||||
int32_t mTimingTick(struct mTiming* timing, int32_t cycles);
|
||||
int32_t mTimingCurrentTime(struct mTiming* timing);
|
||||
int32_t mTimingNextEvent(struct mTiming* timing);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1555,8 +1555,9 @@ void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
info->hasStarted = 0;
|
||||
switch (GBADMARegisterGetTiming(info->reg)) {
|
||||
case DMA_TIMING_NOW:
|
||||
info->nextEvent = 2;
|
||||
GBAMemoryUpdateDMAs(gba, -1);
|
||||
info->nextEvent = 2 + 1; // XXX: Account for I cycle when writing
|
||||
info->scheduledAt = mTimingCurrentTime(&gba->timing);
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
break;
|
||||
case DMA_TIMING_HBLANK:
|
||||
// Handled implicitly
|
||||
|
@ -1586,27 +1587,43 @@ void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
|
||||
struct GBAMemory* memory = &gba->memory;
|
||||
struct GBADMA* dma;
|
||||
bool dmaSeen = false;
|
||||
if (memory->activeDMA >= 0) {
|
||||
GBAMemoryUpdateDMAs(gba, mTimingCurrentTime(&gba->timing) - memory->dma[memory->activeDMA].scheduledAt);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dma = &memory->dma[i];
|
||||
if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
|
||||
dma->nextEvent = 2 + cycles;
|
||||
dma->scheduledAt = mTimingCurrentTime(&gba->timing);
|
||||
dmaSeen = true;
|
||||
}
|
||||
}
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
if (dmaSeen) {
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
|
||||
struct GBAMemory* memory = &gba->memory;
|
||||
struct GBADMA* dma;
|
||||
bool dmaSeen = false;
|
||||
if (memory->activeDMA >= 0) {
|
||||
GBAMemoryUpdateDMAs(gba, mTimingCurrentTime(&gba->timing) - memory->dma[memory->activeDMA].scheduledAt);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dma = &memory->dma[i];
|
||||
if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
|
||||
dma->nextEvent = 2 + cycles;
|
||||
dma->scheduledAt = mTimingCurrentTime(&gba->timing);
|
||||
dmaSeen = true;
|
||||
}
|
||||
}
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
if (dmaSeen) {
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) {
|
||||
|
@ -1664,6 +1681,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
if (info->hasStarted < 1) {
|
||||
info->hasStarted = wordsRemaining;
|
||||
info->nextEvent = 0;
|
||||
info->scheduledAt = mTimingCurrentTime(&gba->timing);
|
||||
GBAMemoryUpdateDMAs(gba, -cycles);
|
||||
return;
|
||||
}
|
||||
|
@ -1729,6 +1747,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
} else {
|
||||
info->nextDest = dest;
|
||||
info->nextCount = wordsRemaining;
|
||||
info->scheduledAt = mTimingCurrentTime(&gba->timing);
|
||||
}
|
||||
info->nextSource = source;
|
||||
GBAMemoryUpdateDMAs(gba, 0);
|
||||
|
|
|
@ -109,6 +109,7 @@ struct GBADMA {
|
|||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
int32_t nextEvent;
|
||||
uint32_t scheduledAt;
|
||||
int32_t hasStarted;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue