mirror of https://github.com/mgba-emu/mgba.git
Sloppy first implementation of windows
This commit is contained in:
parent
7291fcfe9e
commit
453939fc8d
|
@ -323,29 +323,76 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
||||||
softwareRenderer->row = row;
|
softwareRenderer->row = row;
|
||||||
memset(softwareRenderer->spriteLayer, 0, sizeof(softwareRenderer->spriteLayer));
|
memset(softwareRenderer->spriteLayer, 0, sizeof(softwareRenderer->spriteLayer));
|
||||||
|
|
||||||
|
softwareRenderer->windows[0].endX = VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
softwareRenderer->nWindows = 1;
|
||||||
if (softwareRenderer->dispcnt.win0Enable || softwareRenderer->dispcnt.win1Enable) {
|
if (softwareRenderer->dispcnt.win0Enable || softwareRenderer->dispcnt.win1Enable) {
|
||||||
if (softwareRenderer->dispcnt.win0Enable) {
|
softwareRenderer->windows[0].control = softwareRenderer->winout;
|
||||||
softwareRenderer->currentWindow = softwareRenderer->win0;
|
|
||||||
softwareRenderer->start = softwareRenderer->win0H.start;
|
|
||||||
softwareRenderer->end = softwareRenderer->win0H.end;
|
|
||||||
_drawScanline(softwareRenderer, y);
|
|
||||||
}
|
|
||||||
if (softwareRenderer->dispcnt.win1Enable) {
|
if (softwareRenderer->dispcnt.win1Enable) {
|
||||||
softwareRenderer->currentWindow = softwareRenderer->win1;
|
if (softwareRenderer->win1H.start > 0) {
|
||||||
softwareRenderer->start = softwareRenderer->win1H.start;
|
softwareRenderer->windows[softwareRenderer->nWindows].control = softwareRenderer->win1;
|
||||||
softwareRenderer->end = softwareRenderer->win1H.end;
|
softwareRenderer->windows[softwareRenderer->nWindows].endX = softwareRenderer->win1H.start;
|
||||||
_drawScanline(softwareRenderer, y);
|
++softwareRenderer->nWindows;
|
||||||
}
|
softwareRenderer->windows[softwareRenderer->nWindows].endX = VIDEO_HORIZONTAL_PIXELS;
|
||||||
softwareRenderer->currentWindow = softwareRenderer->winout;
|
|
||||||
softwareRenderer->start = 0;
|
|
||||||
softwareRenderer->end = VIDEO_HORIZONTAL_PIXELS;
|
|
||||||
_drawScanline(softwareRenderer, y);
|
|
||||||
} else {
|
} else {
|
||||||
softwareRenderer->currentWindow.packed = 0xFF;
|
softwareRenderer->windows[softwareRenderer->nWindows - 1].control = softwareRenderer->win1;
|
||||||
softwareRenderer->start = 0;
|
|
||||||
softwareRenderer->end = VIDEO_HORIZONTAL_PIXELS;
|
|
||||||
_drawScanline(softwareRenderer, y);
|
|
||||||
}
|
}
|
||||||
|
if (softwareRenderer->win1H.end < VIDEO_HORIZONTAL_PIXELS) {
|
||||||
|
softwareRenderer->windows[softwareRenderer->nWindows].control = softwareRenderer->winout;
|
||||||
|
softwareRenderer->windows[softwareRenderer->nWindows].endX = softwareRenderer->win1H.end;
|
||||||
|
++softwareRenderer->nWindows;
|
||||||
|
softwareRenderer->windows[softwareRenderer->nWindows].endX = VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
} else {
|
||||||
|
softwareRenderer->windows[softwareRenderer->nWindows - 1].endX = softwareRenderer->win1H.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (softwareRenderer->dispcnt.win0Enable) {
|
||||||
|
int activeWindow;
|
||||||
|
int startX = 0;
|
||||||
|
for (activeWindow = 0; activeWindow < softwareRenderer->nWindows; ++activeWindow) {
|
||||||
|
if (softwareRenderer->win0H.start < softwareRenderer->windows[activeWindow].endX) {
|
||||||
|
// We start in this region
|
||||||
|
struct Window oldWindow = softwareRenderer->windows[activeWindow];
|
||||||
|
if (softwareRenderer->win0H.start > startX) {
|
||||||
|
// We need to split the region
|
||||||
|
int nextWindow = softwareRenderer->nWindows;
|
||||||
|
++softwareRenderer->nWindows;
|
||||||
|
for (; nextWindow > activeWindow; --nextWindow) {
|
||||||
|
softwareRenderer->windows[nextWindow] = softwareRenderer->windows[nextWindow - 1];
|
||||||
|
}
|
||||||
|
softwareRenderer->windows[activeWindow].endX = softwareRenderer->win0H.start;
|
||||||
|
++activeWindow;
|
||||||
|
}
|
||||||
|
softwareRenderer->windows[activeWindow].control = softwareRenderer->win0;
|
||||||
|
softwareRenderer->windows[activeWindow].endX = softwareRenderer->win0H.end;
|
||||||
|
if (softwareRenderer->win0H.end >= oldWindow.endX) {
|
||||||
|
// Consume subsequent regions
|
||||||
|
for (++activeWindow; softwareRenderer->win0H.end >= softwareRenderer->windows[activeWindow].endX; ++activeWindow) {
|
||||||
|
softwareRenderer->windows[activeWindow] = softwareRenderer->windows[activeWindow + 1];
|
||||||
|
--softwareRenderer->nWindows;
|
||||||
|
if (softwareRenderer->nWindows <= 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ...and the other end
|
||||||
|
++activeWindow;
|
||||||
|
int nextWindow = softwareRenderer->nWindows;
|
||||||
|
++softwareRenderer->nWindows;
|
||||||
|
for (; nextWindow > activeWindow; --nextWindow) {
|
||||||
|
softwareRenderer->windows[nextWindow] = softwareRenderer->windows[nextWindow - 1];
|
||||||
|
}
|
||||||
|
softwareRenderer->windows[activeWindow] = oldWindow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startX = softwareRenderer->windows[activeWindow].endX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
softwareRenderer->windows[0].control.packed = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawScanline(softwareRenderer, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
||||||
|
@ -471,7 +518,16 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer*
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
if (renderer->dispcnt.objEnable && renderer->currentWindow.objEnable) {
|
int w;
|
||||||
|
renderer->end = 0;
|
||||||
|
if (renderer->dispcnt.objEnable) {
|
||||||
|
for (w = 0; w < renderer->nWindows; ++w) {
|
||||||
|
renderer->start = renderer->end;
|
||||||
|
renderer->end = renderer->windows[w].endX;
|
||||||
|
renderer->currentWindow = renderer->windows[w].control;
|
||||||
|
if (!renderer->currentWindow.objEnable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int i, j;
|
int i, j;
|
||||||
for (j = 0; j < 4; ++j) {
|
for (j = 0; j < 4; ++j) {
|
||||||
uint32_t bitmap = renderer->enabledBitmap[j];
|
uint32_t bitmap = renderer->enabledBitmap[j];
|
||||||
|
@ -491,12 +547,16 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderer->start = 0;
|
|
||||||
renderer->end = VIDEO_HORIZONTAL_PIXELS;
|
|
||||||
int priority;
|
int priority;
|
||||||
for (priority = 0; priority < 4; ++priority) {
|
for (priority = 0; priority < 4; ++priority) {
|
||||||
_postprocessSprite(renderer, priority);
|
_postprocessSprite(renderer, priority);
|
||||||
|
renderer->end = 0;
|
||||||
|
for (w = 0; w < renderer->nWindows; ++w) {
|
||||||
|
renderer->start = renderer->end;
|
||||||
|
renderer->end = renderer->windows[w].endX;
|
||||||
|
renderer->currentWindow = renderer->windows[w].control;
|
||||||
if (renderer->bg[0].enabled && renderer->currentWindow.bg0Enable && renderer->bg[0].priority == priority && renderer->dispcnt.mode < 2) {
|
if (renderer->bg[0].enabled && renderer->currentWindow.bg0Enable && renderer->bg[0].priority == priority && renderer->dispcnt.mode < 2) {
|
||||||
_drawBackgroundMode0(renderer, &renderer->bg[0], y);
|
_drawBackgroundMode0(renderer, &renderer->bg[0], y);
|
||||||
}
|
}
|
||||||
|
@ -538,6 +598,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
renderer->bg[3].sy += renderer->bg[3].dmy;
|
renderer->bg[3].sy += renderer->bg[3].dmy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, uint32_t color) {
|
static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, uint32_t color) {
|
||||||
|
@ -607,7 +668,7 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, ui
|
||||||
#define BACKGROUND_MODE_0_TILE_16_LOOP(TYPE) \
|
#define BACKGROUND_MODE_0_TILE_16_LOOP(TYPE) \
|
||||||
uint32_t tileData; \
|
uint32_t tileData; \
|
||||||
int paletteData, pixelData; \
|
int paletteData, pixelData; \
|
||||||
for (; tileX < 30; ++tileX) { \
|
for (; tileX < tileEnd; ++tileX) { \
|
||||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||||
paletteData = mapData.palette << 4; \
|
paletteData = mapData.palette << 4; \
|
||||||
charBase = ((background->charBase + (mapData.tile << 5)) >> 2) + localY; \
|
charBase = ((background->charBase + (mapData.tile << 5)) >> 2) + localY; \
|
||||||
|
@ -657,7 +718,7 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, ui
|
||||||
#define BACKGROUND_MODE_0_TILE_256_LOOP(TYPE) \
|
#define BACKGROUND_MODE_0_TILE_256_LOOP(TYPE) \
|
||||||
uint32_t tileData; \
|
uint32_t tileData; \
|
||||||
int pixelData; \
|
int pixelData; \
|
||||||
for (; tileX < 30; ++tileX) { \
|
for (; tileX < tileEnd; ++tileX) { \
|
||||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||||
charBase = ((background->charBase + (mapData.tile << 6)) >> 2) + (localY << 1); \
|
charBase = ((background->charBase + (mapData.tile << 6)) >> 2) + (localY << 1); \
|
||||||
if (!mapData.hflip) { \
|
if (!mapData.hflip) { \
|
||||||
|
@ -744,8 +805,9 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
uint32_t charBase;
|
uint32_t charBase;
|
||||||
int variant = background->target1 && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
int variant = background->target1 && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
||||||
|
|
||||||
int outX = 0;
|
int outX = renderer->start;
|
||||||
int tileX = renderer->start >> 3;
|
int tileX = outX >> 3;
|
||||||
|
int tileEnd = renderer->end >> 3;
|
||||||
if (inX & 0x7) {
|
if (inX & 0x7) {
|
||||||
uint32_t tileData;
|
uint32_t tileData;
|
||||||
int pixelData, paletteData;
|
int pixelData, paletteData;
|
||||||
|
@ -759,11 +821,11 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
if (!mapData.hflip) {
|
if (!mapData.hflip) {
|
||||||
tileData >>= 4 * (inX & 0x7);
|
tileData >>= 4 * (inX & 0x7);
|
||||||
if (!variant) {
|
if (!variant) {
|
||||||
for (outX = 0; outX < end; ++outX) {
|
for (; outX < end; ++outX) {
|
||||||
BACKGROUND_DRAW_PIXEL_16_NORMAL;
|
BACKGROUND_DRAW_PIXEL_16_NORMAL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (outX = 0; outX < end; ++outX) {
|
for (; outX < end; ++outX) {
|
||||||
BACKGROUND_DRAW_PIXEL_16_VARIANT;
|
BACKGROUND_DRAW_PIXEL_16_VARIANT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -781,7 +843,6 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
} else {
|
} else {
|
||||||
// TODO: hflip
|
// TODO: hflip
|
||||||
charBase = ((background->charBase + (mapData.tile << 6)) >> 2) + (localY << 1);
|
charBase = ((background->charBase + (mapData.tile << 6)) >> 2) + (localY << 1);
|
||||||
outX = 0;
|
|
||||||
int end2 = end - 4;
|
int end2 = end - 4;
|
||||||
int shift = inX & 0x3;
|
int shift = inX & 0x3;
|
||||||
if (end2 > 0) {
|
if (end2 > 0) {
|
||||||
|
@ -812,7 +873,7 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tileX = 30;
|
tileX = tileEnd;
|
||||||
BACKGROUND_TEXT_SELECT_CHARACTER;
|
BACKGROUND_TEXT_SELECT_CHARACTER;
|
||||||
if (!background->multipalette) {
|
if (!background->multipalette) {
|
||||||
charBase = ((background->charBase + (mapData.tile << 5)) >> 2) + localY;
|
charBase = ((background->charBase + (mapData.tile << 5)) >> 2) + localY;
|
||||||
|
@ -924,7 +985,7 @@ static void _drawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
uint8_t tileData;
|
uint8_t tileData;
|
||||||
|
|
||||||
int outX;
|
int outX;
|
||||||
for (outX = 0; outX < VIDEO_HORIZONTAL_PIXELS; ++outX) {
|
for (outX = renderer->start; outX < VIDEO_HORIZONTAL_PIXELS; ++outX) {
|
||||||
x += background->dx;
|
x += background->dx;
|
||||||
y += background->dy;
|
y += background->dy;
|
||||||
|
|
||||||
|
@ -1199,7 +1260,7 @@ static void _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* render
|
||||||
|
|
||||||
static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, int priority) {
|
static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, int priority) {
|
||||||
int x;
|
int x;
|
||||||
for (x = renderer->start; x < renderer->end; ++x) {
|
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
|
||||||
uint32_t color = renderer->spriteLayer[x];
|
uint32_t color = renderer->spriteLayer[x];
|
||||||
if ((color & FLAG_FINALIZED) && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority && !(renderer->row[x] & FLAG_FINALIZED)) {
|
if ((color & FLAG_FINALIZED) && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority && !(renderer->row[x] & FLAG_FINALIZED)) {
|
||||||
_composite(renderer, x, color & ~FLAG_FINALIZED);
|
_composite(renderer, x, color & ~FLAG_FINALIZED);
|
||||||
|
|
|
@ -50,7 +50,7 @@ enum PixelFlags {
|
||||||
FLAG_TARGET_2 = 0x02000000
|
FLAG_TARGET_2 = 0x02000000
|
||||||
};
|
};
|
||||||
|
|
||||||
union Window {
|
union WindowRegion {
|
||||||
struct {
|
struct {
|
||||||
uint8_t end;
|
uint8_t end;
|
||||||
uint8_t start;
|
uint8_t start;
|
||||||
|
@ -71,6 +71,13 @@ union WindowControl {
|
||||||
uint8_t packed;
|
uint8_t packed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_WINDOW 5
|
||||||
|
|
||||||
|
struct Window {
|
||||||
|
uint8_t endX;
|
||||||
|
union WindowControl control;
|
||||||
|
};
|
||||||
|
|
||||||
struct GBAVideoSoftwareRenderer {
|
struct GBAVideoSoftwareRenderer {
|
||||||
struct GBAVideoRenderer d;
|
struct GBAVideoRenderer d;
|
||||||
|
|
||||||
|
@ -94,10 +101,10 @@ struct GBAVideoSoftwareRenderer {
|
||||||
uint16_t bldb;
|
uint16_t bldb;
|
||||||
uint16_t bldy;
|
uint16_t bldy;
|
||||||
|
|
||||||
union Window win0H;
|
union WindowRegion win0H;
|
||||||
union Window win0V;
|
union WindowRegion win0V;
|
||||||
union Window win1H;
|
union WindowRegion win1H;
|
||||||
union Window win1V;
|
union WindowRegion win1V;
|
||||||
|
|
||||||
union WindowControl win0;
|
union WindowControl win0;
|
||||||
union WindowControl win1;
|
union WindowControl win1;
|
||||||
|
@ -106,6 +113,9 @@ struct GBAVideoSoftwareRenderer {
|
||||||
|
|
||||||
union WindowControl currentWindow;
|
union WindowControl currentWindow;
|
||||||
|
|
||||||
|
int nWindows;
|
||||||
|
struct Window windows[MAX_WINDOW];
|
||||||
|
|
||||||
struct GBAVideoSoftwareBackground bg[4];
|
struct GBAVideoSoftwareBackground bg[4];
|
||||||
|
|
||||||
uint32_t* row;
|
uint32_t* row;
|
||||||
|
|
Loading…
Reference in New Issue