all repos — mgba @ e429d726dc34958c8dd4e937e784e31d95179554

mGBA Game Boy Advance Emulator

GB Memory: Fix HDMAs
Jeffrey Pfau jeffrey@endrift.com
Thu, 10 Nov 2016 20:05:33 -0800
commit

e429d726dc34958c8dd4e937e784e31d95179554

parent

84844232ecc9175dc90e2ab2ccff380c6edd502d

4 files changed, 12 insertions(+), 2 deletions(-)

jump to
M src/gb/gb.csrc/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.hsrc/gb/gb.h

@@ -78,6 +78,7 @@

struct mCoreCallbacks* coreCallbacks; struct mAVStream* stream; + bool cpuBlocked; int32_t eiPending; unsigned doubleSpeed; };
M src/gb/memory.csrc/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.csrc/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;