mirror of https://github.com/mgba-emu/mgba.git
GB Video: Fix loading states while in mode 3
This commit is contained in:
parent
65665324ef
commit
7ebd2d6e75
1
CHANGES
1
CHANGES
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
10
src/gb/io.c
10
src/gb/io.c
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue