diff --git a/CHANGES b/CHANGES index 8ff0d9afb..1bce17f89 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Bugfixes: - GBA Video: Don't mask out high bits of BLDY (fixes mgba.io/i/899) - GBA Video: Force align 256-color tiles - GBA DMA: ROM reads are forced to increment + - GB Video: Fix loading states while in mode 3 Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index a19fa928e..90cfd7bbb 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -159,7 +159,7 @@ void GBVideoInit(struct GBVideo* video); void GBVideoReset(struct GBVideo* video); void GBVideoDeinit(struct GBVideo* video); void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer); -void GBVideoProcessDots(struct GBVideo* video); +void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate); void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value); void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value); diff --git a/src/gb/io.c b/src/gb/io.c index 2db5d8c6e..8010e6a8a 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -392,7 +392,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { return; case REG_LCDC: // TODO: handle GBC differences - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); GBVideoWriteLCDC(&gb->video, value); break; @@ -406,13 +406,13 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { case REG_SCX: case REG_WY: case REG_WX: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); break; case REG_BGP: case REG_OBP0: case REG_OBP1: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); GBVideoWritePalette(&gb->video, address, value); break; case REG_STAT: @@ -459,7 +459,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1)); break; case REG_BCPD: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); GBVideoWritePalette(&gb->video, address, value); return; case REG_OCPS: @@ -468,7 +468,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1)); break; case REG_OCPD: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); GBVideoWritePalette(&gb->video, address, value); return; case REG_SVBK: diff --git a/src/gb/video.c b/src/gb/video.c index 4478b079e..952b51322 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -310,7 +310,7 @@ void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) { void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBVideo* video = context; - GBVideoProcessDots(video); + GBVideoProcessDots(video, cyclesLate); if (video->ly < GB_VIDEO_VERTICAL_PIXELS && video->p->memory.isHdma && video->p->memory.io[REG_HDMA5] != 0xFF) { video->p->memory.hdmaRemaining = 0x10; video->p->cpuBlocked = true; @@ -400,12 +400,12 @@ static void _cleanOAM(struct GBVideo* video, int y) { video->objMax = o; } -void GBVideoProcessDots(struct GBVideo* video) { +void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) { if (video->mode != 3) { return; } int oldX = video->x; - video->x = (video->p->timing.masterCycles - video->dotClock + video->p->cpu->cycles) >> video->p->doubleSpeed; + video->x = (mTimingCurrentTime(&video->p->timing) - video->dotClock - cyclesLate) >> video->p->doubleSpeed; if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) { video->x = GB_VIDEO_HORIZONTAL_PIXELS; } else if (video->x < 0) { @@ -786,6 +786,7 @@ void GBVideoSerialize(const struct GBVideo* video, struct GBSerializedState* sta STORE_16LE(video->x, 0, &state->video.x); STORE_16LE(video->ly, 0, &state->video.ly); STORE_32LE(video->frameCounter, 0, &state->video.frameCounter); + STORE_32LE(video->dotClock, 0, &state->video.dotCounter); state->video.vramCurrentBank = video->vramCurrentBank; GBSerializedVideoFlags flags = 0; @@ -814,6 +815,7 @@ void GBVideoDeserialize(struct GBVideo* video, const struct GBSerializedState* s LOAD_16LE(video->x, 0, &state->video.x); LOAD_16LE(video->ly, 0, &state->video.ly); LOAD_32LE(video->frameCounter, 0, &state->video.frameCounter); + LOAD_32LE(video->dotClock, 0, &state->video.dotCounter); video->vramCurrentBank = state->video.vramCurrentBank; GBSerializedVideoFlags flags = state->video.flags;