GB: Fix flickering when screen is strobed quickly

This commit is contained in:
Vicki Pfau 2017-04-03 14:31:40 -07:00
parent 232e67f529
commit f73fd7f3da
4 changed files with 31 additions and 32 deletions

View File

@ -33,6 +33,7 @@ Bugfixes:
- Windows: Fix VDir.rewind - Windows: Fix VDir.rewind
- SDL: Fix game crash check - SDL: Fix game crash check
- SDL: Fix race condition with audio thread when starting - SDL: Fix race condition with audio thread when starting
- GB: Fix flickering when screen is strobed quickly
Misc: Misc:
- SDL: Remove scancode key input - SDL: Remove scancode key input
- GBA Video: Clean up unused timers - GBA Video: Clean up unused timers

View File

@ -119,6 +119,7 @@ struct GBVideo {
int ocpIndex; int ocpIndex;
bool ocpIncrement; bool ocpIncrement;
uint16_t dmgPalette[4];
uint16_t palette[64]; uint16_t palette[64];
int32_t frameCounter; int32_t frameCounter;

View File

@ -24,26 +24,15 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y); static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y);
static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) { static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
// TODO: Dynamic from dmgPalette
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
color_t palette0 = 0xFFDF;
#else
color_t palette0 = 0x7FFF;
#endif
#else
color_t palette0 = 0xFFFFFF;
#endif
int y; int y;
for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS; ++y) { for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS; ++y) {
color_t* row = &renderer->outputBuffer[renderer->outputBufferStride * y]; color_t* row = &renderer->outputBuffer[renderer->outputBufferStride * y];
int x; int x;
for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; x += 4) { for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; x += 4) {
row[x + 0] = palette0; row[x + 0] = renderer->palette[0];
row[x + 1] = palette0; row[x + 1] = renderer->palette[0];
row[x + 2] = palette0; row[x + 2] = renderer->palette[0];
row[x + 3] = palette0; row[x + 3] = renderer->palette[0];
} }
} }
} }
@ -85,9 +74,6 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer*
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
switch (address) { switch (address) {
case REG_LCDC: case REG_LCDC:
if (GBRegisterLCDCIsEnable(softwareRenderer->lcdc) && !GBRegisterLCDCIsEnable(value)) {
_clearScreen(softwareRenderer);
}
softwareRenderer->lcdc = value; softwareRenderer->lcdc = value;
break; break;
case REG_SCY: case REG_SCY:
@ -197,6 +183,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
mappedMemoryFree(softwareRenderer->temporaryBuffer, GB_VIDEO_HORIZONTAL_PIXELS * GB_VIDEO_VERTICAL_PIXELS * 4); mappedMemoryFree(softwareRenderer->temporaryBuffer, GB_VIDEO_HORIZONTAL_PIXELS * GB_VIDEO_VERTICAL_PIXELS * 4);
softwareRenderer->temporaryBuffer = 0; softwareRenderer->temporaryBuffer = 0;
} }
if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
_clearScreen(softwareRenderer);
}
softwareRenderer->currentWy = 0; softwareRenderer->currentWy = 0;
} }

View File

@ -61,6 +61,11 @@ void GBVideoInit(struct GBVideo* video) {
video->frameEvent.name = "GB Video Frame"; video->frameEvent.name = "GB Video Frame";
video->frameEvent.callback = _updateFrameCount; video->frameEvent.callback = _updateFrameCount;
video->frameEvent.priority = 9; video->frameEvent.priority = 9;
video->dmgPalette[0] = 0x7FFF;
video->dmgPalette[1] = 0x56B5;
video->dmgPalette[2] = 0x294A;
video->dmgPalette[3] = 0x0000;
} }
void GBVideoReset(struct GBVideo* video) { void GBVideoReset(struct GBVideo* video) {
@ -157,7 +162,6 @@ void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) {
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT); video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);
GBUpdateIRQs(video->p); GBUpdateIRQs(video->p);
} }
video->renderer->finishFrame(video->renderer);
if (video->p->memory.mbcType == GB_MBC7 && video->p->memory.rotation && video->p->memory.rotation->sample) { if (video->p->memory.mbcType == GB_MBC7 && video->p->memory.rotation && video->p->memory.rotation->sample) {
video->p->memory.rotation->sample(video->p->memory.rotation); video->p->memory.rotation->sample(video->p->memory.rotation);
} }
@ -234,6 +238,7 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
GBFrameEnded(video->p); GBFrameEnded(video->p);
--video->frameskipCounter; --video->frameskipCounter;
if (video->frameskipCounter < 0) { if (video->frameskipCounter < 0) {
video->renderer->finishFrame(video->renderer);
mCoreSyncPostFrame(video->p->sync); mCoreSyncPostFrame(video->p->sync);
video->frameskipCounter = video->frameskip; video->frameskipCounter = video->frameskip;
} }
@ -318,6 +323,8 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
GBUpdateIRQs(video->p); GBUpdateIRQs(video->p);
} }
video->p->memory.io[REG_STAT] = video->stat; video->p->memory.io[REG_STAT] = video->stat;
video->renderer->writePalette(video->renderer, 0, video->palette[0]);
mTimingDeschedule(&video->p->timing, &video->frameEvent); mTimingDeschedule(&video->p->timing, &video->frameEvent);
} }
if (GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC]) && !GBRegisterLCDCIsEnable(value)) { if (GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC]) && !GBRegisterLCDCIsEnable(value)) {
@ -326,6 +333,8 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
video->p->memory.io[REG_STAT] = video->stat; video->p->memory.io[REG_STAT] = video->stat;
video->ly = 0; video->ly = 0;
video->p->memory.io[REG_LY] = 0; video->p->memory.io[REG_LY] = 0;
video->renderer->writePalette(video->renderer, 0, video->dmgPalette[0]);
mTimingDeschedule(&video->p->timing, &video->modeEvent); mTimingDeschedule(&video->p->timing, &video->modeEvent);
mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH);
} }
@ -351,34 +360,33 @@ void GBVideoWriteLYC(struct GBVideo* video, uint8_t value) {
} }
void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value) { void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value) {
static const uint16_t dmgPalette[4] = { 0x7FFF, 0x56B5, 0x294A, 0x0000};
if (video->p->model < GB_MODEL_CGB) { if (video->p->model < GB_MODEL_CGB) {
switch (address) { switch (address) {
case REG_BGP: case REG_BGP:
video->palette[0] = dmgPalette[value & 3]; video->palette[0] = video->dmgPalette[value & 3];
video->palette[1] = dmgPalette[(value >> 2) & 3]; video->palette[1] = video->dmgPalette[(value >> 2) & 3];
video->palette[2] = dmgPalette[(value >> 4) & 3]; video->palette[2] = video->dmgPalette[(value >> 4) & 3];
video->palette[3] = dmgPalette[(value >> 6) & 3]; video->palette[3] = video->dmgPalette[(value >> 6) & 3];
video->renderer->writePalette(video->renderer, 0, video->palette[0]); video->renderer->writePalette(video->renderer, 0, video->palette[0]);
video->renderer->writePalette(video->renderer, 1, video->palette[1]); video->renderer->writePalette(video->renderer, 1, video->palette[1]);
video->renderer->writePalette(video->renderer, 2, video->palette[2]); video->renderer->writePalette(video->renderer, 2, video->palette[2]);
video->renderer->writePalette(video->renderer, 3, video->palette[3]); video->renderer->writePalette(video->renderer, 3, video->palette[3]);
break; break;
case REG_OBP0: case REG_OBP0:
video->palette[8 * 4 + 0] = dmgPalette[value & 3]; video->palette[8 * 4 + 0] = video->dmgPalette[value & 3];
video->palette[8 * 4 + 1] = dmgPalette[(value >> 2) & 3]; video->palette[8 * 4 + 1] = video->dmgPalette[(value >> 2) & 3];
video->palette[8 * 4 + 2] = dmgPalette[(value >> 4) & 3]; video->palette[8 * 4 + 2] = video->dmgPalette[(value >> 4) & 3];
video->palette[8 * 4 + 3] = dmgPalette[(value >> 6) & 3]; video->palette[8 * 4 + 3] = video->dmgPalette[(value >> 6) & 3];
video->renderer->writePalette(video->renderer, 8 * 4 + 0, video->palette[8 * 4 + 0]); video->renderer->writePalette(video->renderer, 8 * 4 + 0, video->palette[8 * 4 + 0]);
video->renderer->writePalette(video->renderer, 8 * 4 + 1, video->palette[8 * 4 + 1]); video->renderer->writePalette(video->renderer, 8 * 4 + 1, video->palette[8 * 4 + 1]);
video->renderer->writePalette(video->renderer, 8 * 4 + 2, video->palette[8 * 4 + 2]); video->renderer->writePalette(video->renderer, 8 * 4 + 2, video->palette[8 * 4 + 2]);
video->renderer->writePalette(video->renderer, 8 * 4 + 3, video->palette[8 * 4 + 3]); video->renderer->writePalette(video->renderer, 8 * 4 + 3, video->palette[8 * 4 + 3]);
break; break;
case REG_OBP1: case REG_OBP1:
video->palette[9 * 4 + 0] = dmgPalette[value & 3]; video->palette[9 * 4 + 0] = video->dmgPalette[value & 3];
video->palette[9 * 4 + 1] = dmgPalette[(value >> 2) & 3]; video->palette[9 * 4 + 1] = video->dmgPalette[(value >> 2) & 3];
video->palette[9 * 4 + 2] = dmgPalette[(value >> 4) & 3]; video->palette[9 * 4 + 2] = video->dmgPalette[(value >> 4) & 3];
video->palette[9 * 4 + 3] = dmgPalette[(value >> 6) & 3]; video->palette[9 * 4 + 3] = video->dmgPalette[(value >> 6) & 3];
video->renderer->writePalette(video->renderer, 9 * 4 + 0, video->palette[9 * 4 + 0]); video->renderer->writePalette(video->renderer, 9 * 4 + 0, video->palette[9 * 4 + 0]);
video->renderer->writePalette(video->renderer, 9 * 4 + 1, video->palette[9 * 4 + 1]); video->renderer->writePalette(video->renderer, 9 * 4 + 1, video->palette[9 * 4 + 1]);
video->renderer->writePalette(video->renderer, 9 * 4 + 2, video->palette[9 * 4 + 2]); video->renderer->writePalette(video->renderer, 9 * 4 + 2, video->palette[9 * 4 + 2]);