Permalink
Browse files

GB Video: Fix SCX timing

  • Loading branch information...
endrift committed Jun 28, 2018
1 parent 80472c9 commit 781f2fbb90fa02494e40b8444a452331d843c1aa
Showing with 14 additions and 11 deletions.
  1. +1 −0 CHANGES
  2. +1 −1 include/mgba/internal/gb/video.h
  3. +12 −10 src/gb/video.c
View
@@ -40,6 +40,7 @@ Bugfixes:
- 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)
@@ -128,7 +128,7 @@ struct GBVideo {
struct mTimingEvent modeEvent;
struct mTimingEvent frameEvent;
- uint32_t dotClock;
+ int32_t dotClock;
uint8_t* vram;
uint8_t* vramBank;
View
@@ -224,8 +224,7 @@ void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
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 @@ void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) {
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 _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) {
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 @@ void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) {
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 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) {
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);

0 comments on commit 781f2fb

Please sign in to comment.