diff --git a/CHANGES b/CHANGES index 047c326c3..ca220e25e 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,7 @@ Emulation fixes: - GBA Memory: Fix misaligned 32-bit I/O loads (fixes mgba.io/i/2307) - GBA Video: Fix OpenGL rendering on M1 Macs - GBA Video: Ignore horizontally off-screen sprite timing (fixes mgba.io/i/2391) + - GBA Video: Fix Hblank timing (fixes mgba.io/i/2131, mgba.io/i/2310) Other fixes: - Core: Don't attempt to restore rewind diffs past start of rewind - FFmpeg: Fix crash when encoding audio with some containers diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 2b7c135ca..5b12d1541 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -18,9 +18,8 @@ mLOG_DECLARE_CATEGORY(GBA_VIDEO); enum { VIDEO_HBLANK_PIXELS = 68, - VIDEO_HDRAW_LENGTH = 960, - VIDEO_HBLANK_LENGTH = 272, - VIDEO_HBLANK_FLIP = 46, + VIDEO_HDRAW_LENGTH = 1008, + VIDEO_HBLANK_LENGTH = 224, VIDEO_HORIZONTAL_LENGTH = 1232, VIDEO_VBLANK_PIXELS = 68, diff --git a/src/gba/video.c b/src/gba/video.c index d78af2468..57099a8c3 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -31,7 +31,6 @@ static void GBAVideoDummyRendererGetPixels(struct GBAVideoRenderer* renderer, si static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); static void _startHblank(struct mTiming*, void* context, uint32_t cyclesLate); -static void _midHblank(struct mTiming*, void* context, uint32_t cyclesLate); static void _startHdraw(struct mTiming*, void* context, uint32_t cyclesLate); MGBA_EXPORT const int GBAVideoObjSizes[16][2] = { @@ -138,15 +137,6 @@ void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer* } } -void _midHblank(struct mTiming* timing, void* context, uint32_t cyclesLate) { - struct GBAVideo* video = context; - GBARegisterDISPSTAT dispstat = video->p->memory.io[REG_DISPSTAT >> 1]; - dispstat = GBARegisterDISPSTATClearInHblank(dispstat); - video->p->memory.io[REG_DISPSTAT >> 1] = dispstat; - video->event.callback = _startHdraw; - mTimingSchedule(timing, &video->event, VIDEO_HBLANK_FLIP - cyclesLate); -} - void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBAVideo* video = context; video->event.callback = _startHblank; @@ -163,6 +153,7 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { } GBARegisterDISPSTAT dispstat = video->p->memory.io[REG_DISPSTAT >> 1]; + dispstat = GBARegisterDISPSTATClearInHblank(dispstat); if (video->vcount == GBARegisterDISPSTATGetVcountSetting(dispstat)) { dispstat = GBARegisterDISPSTATFillVcounter(dispstat); if (GBARegisterDISPSTATIsVcounterIRQ(dispstat)) { @@ -204,8 +195,8 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { void _startHblank(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBAVideo* video = context; - video->event.callback = _midHblank; - mTimingSchedule(timing, &video->event, VIDEO_HBLANK_LENGTH - VIDEO_HBLANK_FLIP - cyclesLate); + video->event.callback = _startHdraw; + mTimingSchedule(timing, &video->event, VIDEO_HBLANK_LENGTH - cyclesLate); // Begin Hblank GBARegisterDISPSTAT dispstat = video->p->memory.io[REG_DISPSTAT >> 1]; @@ -221,7 +212,7 @@ void _startHblank(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBADMARunDisplayStart(video->p, -cyclesLate); } if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { - GBARaiseIRQ(video->p, IRQ_HBLANK, cyclesLate); + GBARaiseIRQ(video->p, IRQ_HBLANK, cyclesLate - 6); // TODO: Where does this fudge factor come from? } video->shouldStall = 0; video->p->memory.io[REG_DISPSTAT >> 1] = dispstat; @@ -343,8 +334,6 @@ void GBAVideoSerialize(const struct GBAVideo* video, struct GBASerializedState* flags = GBASerializedVideoFlagsSetMode(flags, 1); } else if (video->event.callback == _startHblank) { flags = GBASerializedVideoFlagsSetMode(flags, 2); - } else if (video->event.callback == _midHblank) { - flags = GBASerializedVideoFlagsSetMode(flags, 3); } STORE_32(flags, 0, &state->video.flags); STORE_32(video->frameCounter, 0, &state->video.frameCounter); @@ -384,7 +373,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState video->shouldStall = 1; break; case 3: - video->event.callback = _midHblank; + video->event.callback = _startHdraw; break; } uint32_t when;