GB Video: Fix loading states while in mode 3

This commit is contained in:
Vicki Pfau 2017-10-17 21:25:35 -07:00
parent 65665324ef
commit 7ebd2d6e75
4 changed files with 12 additions and 9 deletions

View File

@ -19,6 +19,7 @@ Bugfixes:
- GBA Video: Don't mask out high bits of BLDY (fixes mgba.io/i/899) - GBA Video: Don't mask out high bits of BLDY (fixes mgba.io/i/899)
- GBA Video: Force align 256-color tiles - GBA Video: Force align 256-color tiles
- GBA DMA: ROM reads are forced to increment - GBA DMA: ROM reads are forced to increment
- GB Video: Fix loading states while in mode 3
Misc: Misc:
- GBA Timer: Use global cycles for timers - GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)

View File

@ -159,7 +159,7 @@ void GBVideoInit(struct GBVideo* video);
void GBVideoReset(struct GBVideo* video); void GBVideoReset(struct GBVideo* video);
void GBVideoDeinit(struct GBVideo* video); void GBVideoDeinit(struct GBVideo* video);
void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer); 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 GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value);
void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value); void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value);

View File

@ -392,7 +392,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
return; return;
case REG_LCDC: case REG_LCDC:
// TODO: handle GBC differences // TODO: handle GBC differences
GBVideoProcessDots(&gb->video); GBVideoProcessDots(&gb->video, 0);
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
GBVideoWriteLCDC(&gb->video, value); GBVideoWriteLCDC(&gb->video, value);
break; break;
@ -406,13 +406,13 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
case REG_SCX: case REG_SCX:
case REG_WY: case REG_WY:
case REG_WX: case REG_WX:
GBVideoProcessDots(&gb->video); GBVideoProcessDots(&gb->video, 0);
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
break; break;
case REG_BGP: case REG_BGP:
case REG_OBP0: case REG_OBP0:
case REG_OBP1: case REG_OBP1:
GBVideoProcessDots(&gb->video); GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value); GBVideoWritePalette(&gb->video, address, value);
break; break;
case REG_STAT: 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)); gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1));
break; break;
case REG_BCPD: case REG_BCPD:
GBVideoProcessDots(&gb->video); GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value); GBVideoWritePalette(&gb->video, address, value);
return; return;
case REG_OCPS: 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)); gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1));
break; break;
case REG_OCPD: case REG_OCPD:
GBVideoProcessDots(&gb->video); GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value); GBVideoWritePalette(&gb->video, address, value);
return; return;
case REG_SVBK: case REG_SVBK:

View File

@ -310,7 +310,7 @@ void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) {
void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GBVideo* video = context; 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) { 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->memory.hdmaRemaining = 0x10;
video->p->cpuBlocked = true; video->p->cpuBlocked = true;
@ -400,12 +400,12 @@ static void _cleanOAM(struct GBVideo* video, int y) {
video->objMax = o; video->objMax = o;
} }
void GBVideoProcessDots(struct GBVideo* video) { void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) {
if (video->mode != 3) { if (video->mode != 3) {
return; return;
} }
int oldX = video->x; 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) { if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) {
video->x = GB_VIDEO_HORIZONTAL_PIXELS; video->x = GB_VIDEO_HORIZONTAL_PIXELS;
} else if (video->x < 0) { } 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->x, 0, &state->video.x);
STORE_16LE(video->ly, 0, &state->video.ly); STORE_16LE(video->ly, 0, &state->video.ly);
STORE_32LE(video->frameCounter, 0, &state->video.frameCounter); STORE_32LE(video->frameCounter, 0, &state->video.frameCounter);
STORE_32LE(video->dotClock, 0, &state->video.dotCounter);
state->video.vramCurrentBank = video->vramCurrentBank; state->video.vramCurrentBank = video->vramCurrentBank;
GBSerializedVideoFlags flags = 0; 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->x, 0, &state->video.x);
LOAD_16LE(video->ly, 0, &state->video.ly); LOAD_16LE(video->ly, 0, &state->video.ly);
LOAD_32LE(video->frameCounter, 0, &state->video.frameCounter); LOAD_32LE(video->frameCounter, 0, &state->video.frameCounter);
LOAD_32LE(video->dotClock, 0, &state->video.dotCounter);
video->vramCurrentBank = state->video.vramCurrentBank; video->vramCurrentBank = state->video.vramCurrentBank;
GBSerializedVideoFlags flags = state->video.flags; GBSerializedVideoFlags flags = state->video.flags;