mirror of https://github.com/mgba-emu/mgba.git
GB: Fix flickering when screen is strobed quickly
This commit is contained in:
parent
232e67f529
commit
f73fd7f3da
1
CHANGES
1
CHANGES
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
Loading…
Reference in New Issue