mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Fix poorly documented window case with windows that wrap around
This commit is contained in:
parent
881dc1d8a3
commit
a1712f038d
|
@ -65,6 +65,9 @@ static inline unsigned _brighten(unsigned color, int y);
|
||||||
static inline unsigned _darken(unsigned color, int y);
|
static inline unsigned _darken(unsigned color, int y);
|
||||||
static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB);
|
static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB);
|
||||||
|
|
||||||
|
static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win);
|
||||||
|
static void _breakWindowInner(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win);
|
||||||
|
|
||||||
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
|
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
|
||||||
renderer->d.init = GBAVideoSoftwareRendererInit;
|
renderer->d.init = GBAVideoSoftwareRendererInit;
|
||||||
renderer->d.reset = GBAVideoSoftwareRendererInit;
|
renderer->d.reset = GBAVideoSoftwareRendererInit;
|
||||||
|
@ -264,7 +267,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
if (softwareRenderer->winN[0].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[0].h.start > softwareRenderer->winN[0].h.end) {
|
if (softwareRenderer->winN[0].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[0].h.start > softwareRenderer->winN[0].h.end) {
|
||||||
softwareRenderer->winN[0].h.start = 0;
|
softwareRenderer->winN[0].h.start = 0;
|
||||||
}
|
}
|
||||||
if (softwareRenderer->winN[0].h.start > softwareRenderer->winN[0].h.end || softwareRenderer->winN[0].h.end > VIDEO_HORIZONTAL_PIXELS) {
|
if (softwareRenderer->winN[0].h.end > VIDEO_HORIZONTAL_PIXELS) {
|
||||||
softwareRenderer->winN[0].h.end = VIDEO_HORIZONTAL_PIXELS;
|
softwareRenderer->winN[0].h.end = VIDEO_HORIZONTAL_PIXELS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -274,7 +277,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
if (softwareRenderer->winN[1].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[1].h.start > softwareRenderer->winN[1].h.end) {
|
if (softwareRenderer->winN[1].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[1].h.start > softwareRenderer->winN[1].h.end) {
|
||||||
softwareRenderer->winN[1].h.start = 0;
|
softwareRenderer->winN[1].h.start = 0;
|
||||||
}
|
}
|
||||||
if (softwareRenderer->winN[1].h.start > softwareRenderer->winN[1].h.end || softwareRenderer->winN[1].h.end > VIDEO_HORIZONTAL_PIXELS) {
|
if (softwareRenderer->winN[1].h.end > VIDEO_HORIZONTAL_PIXELS) {
|
||||||
softwareRenderer->winN[1].h.end = VIDEO_HORIZONTAL_PIXELS;
|
softwareRenderer->winN[1].h.end = VIDEO_HORIZONTAL_PIXELS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -284,7 +287,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
if (softwareRenderer->winN[0].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[0].v.start > softwareRenderer->winN[0].v.end) {
|
if (softwareRenderer->winN[0].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[0].v.start > softwareRenderer->winN[0].v.end) {
|
||||||
softwareRenderer->winN[0].v.start = 0;
|
softwareRenderer->winN[0].v.start = 0;
|
||||||
}
|
}
|
||||||
if (softwareRenderer->winN[0].v.start > softwareRenderer->winN[0].v.end || softwareRenderer->winN[0].v.end > VIDEO_HORIZONTAL_PIXELS) {
|
if (softwareRenderer->winN[0].v.end > VIDEO_VERTICAL_PIXELS) {
|
||||||
softwareRenderer->winN[0].v.end = VIDEO_VERTICAL_PIXELS;
|
softwareRenderer->winN[0].v.end = VIDEO_VERTICAL_PIXELS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -294,7 +297,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
if (softwareRenderer->winN[1].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[1].v.start > softwareRenderer->winN[1].v.end) {
|
if (softwareRenderer->winN[1].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[1].v.start > softwareRenderer->winN[1].v.end) {
|
||||||
softwareRenderer->winN[1].v.start = 0;
|
softwareRenderer->winN[1].v.start = 0;
|
||||||
}
|
}
|
||||||
if (softwareRenderer->winN[1].v.start > softwareRenderer->winN[1].v.end || softwareRenderer->winN[1].v.end > VIDEO_HORIZONTAL_PIXELS) {
|
if (softwareRenderer->winN[1].v.end > VIDEO_VERTICAL_PIXELS) {
|
||||||
softwareRenderer->winN[1].v.end = VIDEO_VERTICAL_PIXELS;
|
softwareRenderer->winN[1].v.end = VIDEO_VERTICAL_PIXELS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -350,6 +353,18 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win) {
|
static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win) {
|
||||||
|
if (win->h.end > VIDEO_HORIZONTAL_PIXELS || win->h.end < win->h.start) {
|
||||||
|
struct WindowN splits[2] = { *win, *win };
|
||||||
|
splits[0].h.start = 0;
|
||||||
|
splits[1].h.end = VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
_breakWindowInner(softwareRenderer, &splits[0]);
|
||||||
|
_breakWindowInner(softwareRenderer, &splits[1]);
|
||||||
|
} else {
|
||||||
|
_breakWindowInner(softwareRenderer, win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _breakWindowInner(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win) {
|
||||||
int activeWindow;
|
int activeWindow;
|
||||||
int startX = 0;
|
int startX = 0;
|
||||||
if (win->h.end > 0) {
|
if (win->h.end > 0) {
|
||||||
|
@ -372,6 +387,12 @@ static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, stru
|
||||||
if (win->h.end >= oldWindow.endX) {
|
if (win->h.end >= oldWindow.endX) {
|
||||||
// Trim off extra windows we've overwritten
|
// Trim off extra windows we've overwritten
|
||||||
for (++activeWindow; softwareRenderer->nWindows > activeWindow + 1 && win->h.end >= softwareRenderer->windows[activeWindow].endX; ++activeWindow) {
|
for (++activeWindow; softwareRenderer->nWindows > activeWindow + 1 && win->h.end >= softwareRenderer->windows[activeWindow].endX; ++activeWindow) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (activeWindow >= MAX_WINDOW) {
|
||||||
|
GBALog(0, GBA_LOG_DANGER, "Out of bounds window write will occur");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
softwareRenderer->windows[activeWindow] = softwareRenderer->windows[activeWindow + 1];
|
softwareRenderer->windows[activeWindow] = softwareRenderer->windows[activeWindow + 1];
|
||||||
--softwareRenderer->nWindows;
|
--softwareRenderer->nWindows;
|
||||||
}
|
}
|
||||||
|
@ -389,6 +410,11 @@ static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, stru
|
||||||
startX = softwareRenderer->windows[activeWindow].endX;
|
startX = softwareRenderer->windows[activeWindow].endX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (softwareRenderer->nWindows > MAX_WINDOW) {
|
||||||
|
GBALog(0, GBA_LOG_ABORT, "Out of bounds window write occurred!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
|
static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
|
||||||
|
|
Loading…
Reference in New Issue