mirror of https://github.com/mgba-emu/mgba.git
GB Video: Improved window implementation
This commit is contained in:
parent
b25ac9147d
commit
e7407770cb
|
@ -31,6 +31,8 @@ struct GBVideoSoftwareRenderer {
|
||||||
uint8_t wy;
|
uint8_t wy;
|
||||||
uint8_t wx;
|
uint8_t wx;
|
||||||
uint8_t currentWy;
|
uint8_t currentWy;
|
||||||
|
int lastY;
|
||||||
|
bool hasWindow;
|
||||||
|
|
||||||
GBRegisterLCDC lcdc;
|
GBRegisterLCDC lcdc;
|
||||||
enum GBModel model;
|
enum GBModel model;
|
||||||
|
|
|
@ -38,6 +38,10 @@ static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _inWindow(struct GBVideoSoftwareRenderer* renderer) {
|
||||||
|
return GBRegisterLCDCIsWindow(renderer->lcdc) && GB_VIDEO_HORIZONTAL_PIXELS + 7 > renderer->wx;
|
||||||
|
}
|
||||||
|
|
||||||
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
|
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
|
||||||
renderer->d.init = GBVideoSoftwareRendererInit;
|
renderer->d.init = GBVideoSoftwareRendererInit;
|
||||||
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
|
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
|
||||||
|
@ -65,6 +69,8 @@ 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->lastY = 0;
|
||||||
|
softwareRenderer->hasWindow = false;
|
||||||
softwareRenderer->wx = 0;
|
softwareRenderer->wx = 0;
|
||||||
softwareRenderer->model = model;
|
softwareRenderer->model = model;
|
||||||
}
|
}
|
||||||
|
@ -74,11 +80,31 @@ static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) {
|
||||||
UNUSED(softwareRenderer);
|
UNUSED(softwareRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GBVideoSoftwareRendererUpdateWindow(struct GBVideoSoftwareRenderer* renderer, bool before, bool after) {
|
||||||
|
if (renderer->lastY >= GB_VIDEO_VERTICAL_PIXELS || after == before) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (renderer->lastY >= renderer->wy) {
|
||||||
|
if (!after) {
|
||||||
|
renderer->currentWy -= renderer->lastY;
|
||||||
|
renderer->hasWindow = true;
|
||||||
|
} else {
|
||||||
|
if (!renderer->hasWindow) {
|
||||||
|
renderer->currentWy = renderer->lastY + 1 - renderer->wy;
|
||||||
|
} else {
|
||||||
|
renderer->currentWy += renderer->lastY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) {
|
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) {
|
||||||
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
||||||
|
bool wasWindow = _inWindow(softwareRenderer);
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case REG_LCDC:
|
case REG_LCDC:
|
||||||
softwareRenderer->lcdc = value;
|
softwareRenderer->lcdc = value;
|
||||||
|
GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
|
||||||
break;
|
break;
|
||||||
case REG_SCY:
|
case REG_SCY:
|
||||||
softwareRenderer->scy = value;
|
softwareRenderer->scy = value;
|
||||||
|
@ -88,9 +114,11 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer*
|
||||||
break;
|
break;
|
||||||
case REG_WY:
|
case REG_WY:
|
||||||
softwareRenderer->wy = value;
|
softwareRenderer->wy = value;
|
||||||
|
GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
|
||||||
break;
|
break;
|
||||||
case REG_WX:
|
case REG_WX:
|
||||||
softwareRenderer->wx = value;
|
softwareRenderer->wx = value;
|
||||||
|
GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
@ -134,6 +162,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;
|
||||||
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;
|
||||||
|
@ -142,7 +171,8 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
||||||
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
||||||
}
|
}
|
||||||
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) {
|
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) {
|
||||||
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && endX >= softwareRenderer->wx - 7) {
|
int wy = softwareRenderer->wy + softwareRenderer->currentWy;
|
||||||
|
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) {
|
||||||
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +182,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->currentWy);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, y - wy);
|
||||||
}
|
}
|
||||||
} else if (!softwareRenderer->d.disableBG) {
|
} else if (!softwareRenderer->d.disableBG) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||||
|
@ -201,7 +231,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
|
||||||
if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
|
if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
|
||||||
_clearScreen(softwareRenderer);
|
_clearScreen(softwareRenderer);
|
||||||
}
|
}
|
||||||
|
softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS;
|
||||||
softwareRenderer->currentWy = 0;
|
softwareRenderer->currentWy = 0;
|
||||||
|
softwareRenderer->hasWindow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy) {
|
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy) {
|
||||||
|
|
Loading…
Reference in New Issue