GB Video: Fix window being enabled mid-scanline (fixes #1328)

This commit is contained in:
Vicki Pfau 2019-03-03 17:27:53 -08:00
parent b78825738e
commit a3c79c92d7
3 changed files with 19 additions and 4 deletions

View File

@ -8,6 +8,7 @@ Emulation fixes:
- GBA: Reset now reloads multiboot ROMs - GBA: Reset now reloads multiboot ROMs
- GBA BIOS: Fix multiboot entry point (fixes Magic Floor) - GBA BIOS: Fix multiboot entry point (fixes Magic Floor)
- GB Video: Delay LYC STAT check (fixes mgba.io/i/1331) - GB Video: Delay LYC STAT check (fixes mgba.io/i/1331)
- GB Video: Fix window being enabled mid-scanline (fixes mgba.io/i/1328)
Other fixes: Other fixes:
- Qt: More app metadata fixes - Qt: More app metadata fixes
- Qt: Fix load recent from archive (fixes mgba.io/i/1325) - Qt: Fix load recent from archive (fixes mgba.io/i/1325)

View File

@ -32,7 +32,9 @@ struct GBVideoSoftwareRenderer {
uint8_t wy; uint8_t wy;
uint8_t wx; uint8_t wx;
uint8_t currentWy; uint8_t currentWy;
uint8_t currentWx;
int lastY; int lastY;
int lastX;
bool hasWindow; bool hasWindow;
GBRegisterLCDC lcdc; GBRegisterLCDC lcdc;

View File

@ -190,7 +190,9 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
softwareRenderer->scx = 0; softwareRenderer->scx = 0;
softwareRenderer->wy = 0; softwareRenderer->wy = 0;
softwareRenderer->currentWy = 0; softwareRenderer->currentWy = 0;
softwareRenderer->currentWx = 0;
softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS;
softwareRenderer->lastX = 0;
softwareRenderer->hasWindow = false; softwareRenderer->hasWindow = false;
softwareRenderer->wx = 0; softwareRenderer->wx = 0;
softwareRenderer->model = model; softwareRenderer->model = model;
@ -232,6 +234,9 @@ static void GBVideoSoftwareRendererUpdateWindow(struct GBVideoSoftwareRenderer*
renderer->currentWy = GB_VIDEO_VERTICAL_PIXELS; renderer->currentWy = GB_VIDEO_VERTICAL_PIXELS;
} else { } else {
renderer->currentWy = renderer->lastY - renderer->wy; renderer->currentWy = renderer->lastY - renderer->wy;
if (renderer->lastY == renderer->wy && renderer->lastX > renderer->wx) {
++renderer->currentWy;
}
} }
} else { } else {
renderer->currentWy += renderer->lastY; renderer->currentWy += renderer->lastY;
@ -489,6 +494,7 @@ static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, ui
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) { static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
softwareRenderer->lastY = y; softwareRenderer->lastY = y;
softwareRenderer->lastX = endX;
uint8_t* maps = &softwareRenderer->d.vram[GB_BASE_MAP]; uint8_t* maps = &softwareRenderer->d.vram[GB_BASE_MAP];
if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) { if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) {
maps += GB_SIZE_MAP; maps += GB_SIZE_MAP;
@ -498,9 +504,10 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
} }
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) { if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) {
int wy = softwareRenderer->wy + softwareRenderer->currentWy; int wy = softwareRenderer->wy + softwareRenderer->currentWy;
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) { int wx = softwareRenderer->wx + softwareRenderer->currentWx - 7;
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) { if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && wx <= endX) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); if (wx > 0 && !softwareRenderer->d.disableBG) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, wx, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
} }
maps = &softwareRenderer->d.vram[GB_BASE_MAP]; maps = &softwareRenderer->d.vram[GB_BASE_MAP];
@ -508,7 +515,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
maps += GB_SIZE_MAP; maps += GB_SIZE_MAP;
} }
if (!softwareRenderer->d.disableWIN) { if (!softwareRenderer->d.disableWIN) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy); GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, wx, endX, -wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy);
} }
} else if (!softwareRenderer->d.disableBG) { } else if (!softwareRenderer->d.disableBG) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
@ -612,6 +619,9 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y) { static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
softwareRenderer->lastX = 0;
softwareRenderer->currentWx = 0;
if (softwareRenderer->sgbTransfer == 1) { if (softwareRenderer->sgbTransfer == 1) {
size_t offset = 2 * ((y & 7) + (y >> 3) * GB_VIDEO_HORIZONTAL_PIXELS); size_t offset = 2 * ((y & 7) + (y >> 3) * GB_VIDEO_HORIZONTAL_PIXELS);
if (offset >= 0x1000) { if (offset >= 0x1000) {
@ -702,7 +712,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
} }
} }
softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS;
softwareRenderer->lastX = 0;
softwareRenderer->currentWy = 0; softwareRenderer->currentWy = 0;
softwareRenderer->currentWx = 0;
softwareRenderer->hasWindow = false; softwareRenderer->hasWindow = false;
} }