GB Memory: Fix HDMAs
Jeffrey Pfau jeffrey@endrift.com
Thu, 10 Nov 2016 20:05:33 -0800
4 files changed,
12 insertions(+),
2 deletions(-)
M
src/gb/gb.c
→
src/gb/gb.c
@@ -425,6 +425,7 @@ cpu->sp = 0xFFFE;
cpu->pc = 0x100; } + gb->cpuBlocked = false; gb->eiPending = INT_MAX; gb->doubleSpeed = 0;@@ -546,7 +547,11 @@ nextEvent = gb->eiPending;
} } - cpu->nextEvent = mTimingTick(&gb->timing, cycles); + nextEvent = cycles; + do { + nextEvent = mTimingTick(&gb->timing, nextEvent); + } while (gb->cpuBlocked); + cpu->nextEvent = nextEvent; if (cpu->halted) { cpu->cycles = cpu->nextEvent;
M
src/gb/gb.h
→
src/gb/gb.h
@@ -78,6 +78,7 @@
struct mCoreCallbacks* coreCallbacks; struct mAVStream* stream; + bool cpuBlocked; int32_t eiPending; unsigned doubleSpeed; };
M
src/gb/memory.c
→
src/gb/memory.c
@@ -381,6 +381,7 @@ bool wasHdma = gb->memory.isHdma;
gb->memory.isHdma = value & 0x80; if ((!wasHdma && !gb->memory.isHdma) || gb->video.mode == 0) { gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10; + gb->cpuBlocked = true; mTimingSchedule(&gb->timing, &gb->memory.hdmaEvent, 0); gb->cpu->nextEvent = gb->cpu->cycles; }@@ -404,14 +405,17 @@ }
void _GBMemoryHDMAService(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GB* gb = context; + gb->cpuBlocked = true; uint8_t b = gb->cpu->memory.load8(gb->cpu, gb->memory.hdmaSource); gb->cpu->memory.store8(gb->cpu, gb->memory.hdmaDest, b); ++gb->memory.hdmaSource; ++gb->memory.hdmaDest; --gb->memory.hdmaRemaining; if (gb->memory.hdmaRemaining) { + mTimingDeschedule(timing, &gb->memory.hdmaEvent); mTimingSchedule(timing, &gb->memory.hdmaEvent, 2 - cyclesLate); } else { + gb->cpuBlocked = false; gb->memory.io[REG_HDMA1] = gb->memory.hdmaSource >> 8; gb->memory.io[REG_HDMA2] = gb->memory.hdmaSource; gb->memory.io[REG_HDMA3] = gb->memory.hdmaDest >> 8;@@ -425,7 +429,6 @@ } else {
gb->memory.io[REG_HDMA5] = 0xFF; } } - gb->cpu->cycles += 2; } struct OAMBlock {
M
src/gb/video.c
→
src/gb/video.c
@@ -206,6 +206,7 @@ GBUpdateIRQs(video->p);
} if (video->ly < GB_VIDEO_VERTICAL_PIXELS && video->p->memory.isHdma && video->p->memory.io[REG_HDMA5] != 0xFF) { video->p->memory.hdmaRemaining = 0x10; + mTimingDeschedule(timing, &video->p->memory.hdmaEvent); mTimingSchedule(timing, &video->p->memory.hdmaEvent, 0); } video->mode = 0;