all repos — mgba @ 781f2fbb90fa02494e40b8444a452331d843c1aa

mGBA Game Boy Advance Emulator

GB Video: Fix SCX timing
Vicki Pfau vi@endrift.com
Thu, 28 Jun 2018 13:26:24 -0700
commit

781f2fbb90fa02494e40b8444a452331d843c1aa

parent

80472c9f3a0b39dde23c893010e9b253403e08cb

3 files changed, 14 insertions(+), 11 deletions(-)

jump to
M CHANGESCHANGES

@@ -40,6 +40,7 @@ - GBA Serialize: Fix loading channel 3 volume (fixes mgba.io/i/1107)

- GBA SIO: Fix unconnected SIOCNT for multi mode (fixes mgba.io/i/1105) - GBA BIOS: Fix BitUnPack final byte - GB I/O: DMA register is R/W + - GB Video: Fix SCX timing Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
M include/mgba/internal/gb/video.hinclude/mgba/internal/gb/video.h

@@ -128,7 +128,7 @@

struct mTimingEvent modeEvent; struct mTimingEvent frameEvent; - uint32_t dotClock; + int32_t dotClock; uint8_t* vram; uint8_t* vramBank;
M src/gb/video.csrc/gb/video.c

@@ -224,8 +224,7 @@ video->p->memory.io[REG_LY] = video->ly;

GBRegisterSTAT oldStat = video->stat; video->stat = GBRegisterSTATSetLYC(video->stat, lyc == video->ly); if (video->ly < GB_VIDEO_VERTICAL_PIXELS) { - // TODO: Cache SCX & 7 in case it changes during mode 2 - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else {

@@ -262,7 +261,7 @@ int32_t next;

if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS + 1) { video->ly = 0; video->p->memory.io[REG_LY] = video->ly; - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS) {

@@ -290,9 +289,9 @@

void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBVideo* video = context; _cleanOAM(video, video->ly); - video->x = 0; - video->dotClock = mTimingCurrentTime(timing) - cyclesLate; - int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); + video->x = -(video->p->memory.io[REG_SCX] & 7); + video->dotClock = mTimingCurrentTime(timing) - cyclesLate + 5 - (video->x << video->p->doubleSpeed); + int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - video->x; video->mode = 3; video->modeEvent.callback = _endMode3; GBRegisterSTAT oldStat = video->stat;

@@ -323,7 +322,8 @@ video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);

GBUpdateIRQs(video->p); } video->p->memory.io[REG_STAT] = video->stat; - int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6; + // TODO: Cache SCX & 7 in case it changes + int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); }

@@ -402,12 +402,14 @@ if (video->mode != 3) {

return; } int oldX = video->x; - video->x = (mTimingCurrentTime(&video->p->timing) - video->dotClock - cyclesLate) >> video->p->doubleSpeed; + video->x = (int32_t) (mTimingCurrentTime(&video->p->timing) - cyclesLate - video->dotClock) >> video->p->doubleSpeed; if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) { video->x = GB_VIDEO_HORIZONTAL_PIXELS; } else if (video->x < 0) { - mLOG(GB, FATAL, "Video dot clock went negative!"); - video->x = oldX; + return; + } + if (oldX < 0) { + oldX = 0; } if (video->frameskipCounter <= 0) { video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax);