Use bitfields for windows

This commit is contained in:
Jeffrey Pfau 2014-10-06 00:16:33 -07:00
parent 3a09353ff8
commit 0c18e415e8
2 changed files with 45 additions and 55 deletions

View File

@ -105,18 +105,10 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) {
softwareRenderer->bldb = 0; softwareRenderer->bldb = 0;
softwareRenderer->bldy = 0; softwareRenderer->bldy = 0;
softwareRenderer->winN[0].h.packed = 0; softwareRenderer->winN[0] = (struct WindowN) { .control = { .priority = 0 } };
softwareRenderer->winN[0].v.packed = 0; softwareRenderer->winN[1] = (struct WindowN) { .control = { .priority = 1 } };
softwareRenderer->winN[0].control.packed = 0; softwareRenderer->objwin = (struct WindowControl) { .priority = 2 };
softwareRenderer->winN[0].control.priority = 0; softwareRenderer->winout = (struct WindowControl) { .priority = 3 };
softwareRenderer->winN[1].h.packed = 0;
softwareRenderer->winN[1].v.packed = 0;
softwareRenderer->winN[1].control.packed = 0;
softwareRenderer->winN[1].control.priority = 1;
softwareRenderer->objwin.packed = 0;
softwareRenderer->objwin.priority = 2;
softwareRenderer->winout.packed = 0;
softwareRenderer->winout.priority = 3;
softwareRenderer->oamMax = 0; softwareRenderer->oamMax = 0;
softwareRenderer->mosaic.packed = 0; softwareRenderer->mosaic.packed = 0;
@ -276,7 +268,8 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
_updatePalettes(softwareRenderer); _updatePalettes(softwareRenderer);
break; break;
case REG_WIN0H: case REG_WIN0H:
softwareRenderer->winN[0].h.packed = value; softwareRenderer->winN[0].h.end = value;
softwareRenderer->winN[0].h.start = value >> 8;
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;
} }
@ -285,7 +278,8 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
} }
break; break;
case REG_WIN1H: case REG_WIN1H:
softwareRenderer->winN[1].h.packed = value; softwareRenderer->winN[1].h.end = value;
softwareRenderer->winN[1].h.start = value >> 8;
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;
} }
@ -294,7 +288,8 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
} }
break; break;
case REG_WIN0V: case REG_WIN0V:
softwareRenderer->winN[0].v.packed = value; softwareRenderer->winN[0].v.end = value;
softwareRenderer->winN[0].v.start = value >> 8;
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;
} }
@ -303,7 +298,8 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
} }
break; break;
case REG_WIN1V: case REG_WIN1V:
softwareRenderer->winN[1].v.packed = value; softwareRenderer->winN[1].v.end = value;
softwareRenderer->winN[1].v.start = value >> 8;
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;
} }
@ -469,7 +465,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
for (w = 0; w < softwareRenderer->nWindows; ++w) { for (w = 0; w < softwareRenderer->nWindows; ++w) {
// TOOD: handle objwin on backdrop // TOOD: handle objwin on backdrop
uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND; uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !softwareRenderer->windows[w].control.blendEnable) { if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0]; backdrop |= softwareRenderer->normalPalette[0];
} else { } else {
backdrop |= softwareRenderer->variantPalette[0]; backdrop |= softwareRenderer->variantPalette[0];
@ -486,7 +482,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
x = 0; x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) { for (w = 0; w < softwareRenderer->nWindows; ++w) {
uint32_t backdrop = FLAG_UNWRITTEN; uint32_t backdrop = FLAG_UNWRITTEN;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !softwareRenderer->windows[w].control.blendEnable) { if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0]; backdrop |= softwareRenderer->normalPalette[0];
} else { } else {
backdrop |= softwareRenderer->variantPalette[0]; backdrop |= softwareRenderer->variantPalette[0];
@ -625,8 +621,8 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer*
#define TEST_LAYER_ENABLED(X) \ #define TEST_LAYER_ENABLED(X) \
(renderer->bg[X].enabled && \ (renderer->bg[X].enabled && \
(renderer->currentWindow.bg ## X ## Enable || \ (GBAWindowControlIsBg ## X ## Enable(renderer->currentWindow.packed) || \
(GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && renderer->objwin.bg ## X ## Enable)) && \ (GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlIsBg ## X ## Enable (renderer->objwin.packed))) && \
renderer->bg[X].priority == priority) renderer->bg[X].priority == priority)
static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) { static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
@ -643,7 +639,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
renderer->start = renderer->end; renderer->start = renderer->end;
renderer->end = renderer->windows[w].endX; renderer->end = renderer->windows[w].endX;
renderer->currentWindow = renderer->windows[w].control; renderer->currentWindow = renderer->windows[w].control;
if (!renderer->currentWindow.objEnable) { if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed)) {
continue; continue;
} }
int i; int i;
@ -817,27 +813,27 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
int objwinForceEnable = 0; \ int objwinForceEnable = 0; \
color_t* objwinPalette; \ color_t* objwinPalette; \
if (objwinSlowPath) { \ if (objwinSlowPath) { \
if (background->target1 && renderer->objwin.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN)) { \ if (background->target1 && GBAWindowControlIsBlendEnable(renderer->objwin.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN)) { \
objwinPalette = renderer->variantPalette; \ objwinPalette = renderer->variantPalette; \
} else { \ } else { \
objwinPalette = renderer->normalPalette; \ objwinPalette = renderer->normalPalette; \
} \ } \
switch (background->index) { \ switch (background->index) { \
case 0: \ case 0: \
objwinForceEnable = renderer->objwin.bg0Enable && renderer->currentWindow.bg0Enable; \ objwinForceEnable = GBAWindowControlIsBg0Enable(renderer->objwin.packed) && GBAWindowControlIsBg0Enable(renderer->currentWindow.packed); \
objwinOnly = !renderer->objwin.bg0Enable; \ objwinOnly = !GBAWindowControlIsBg0Enable(renderer->objwin.packed); \
break; \ break; \
case 1: \ case 1: \
objwinForceEnable = renderer->objwin.bg1Enable && renderer->currentWindow.bg1Enable; \ objwinForceEnable = GBAWindowControlIsBg1Enable(renderer->objwin.packed) && GBAWindowControlIsBg1Enable(renderer->currentWindow.packed); \
objwinOnly = !renderer->objwin.bg1Enable; \ objwinOnly = !GBAWindowControlIsBg1Enable(renderer->objwin.packed); \
break; \ break; \
case 2: \ case 2: \
objwinForceEnable = renderer->objwin.bg2Enable && renderer->currentWindow.bg2Enable; \ objwinForceEnable = GBAWindowControlIsBg2Enable(renderer->objwin.packed) && GBAWindowControlIsBg2Enable(renderer->currentWindow.packed); \
objwinOnly = !renderer->objwin.bg2Enable; \ objwinOnly = !GBAWindowControlIsBg2Enable(renderer->objwin.packed); \
break; \ break; \
case 3: \ case 3: \
objwinForceEnable = renderer->objwin.bg3Enable && renderer->currentWindow.bg3Enable; \ objwinForceEnable = GBAWindowControlIsBg3Enable(renderer->objwin.packed) && GBAWindowControlIsBg3Enable(renderer->currentWindow.packed); \
objwinOnly = !renderer->objwin.bg3Enable; \ objwinOnly = !GBAWindowControlIsBg3Enable(renderer->objwin.packed); \
break; \ break; \
} \ } \
} }
@ -1215,7 +1211,7 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
uint32_t screenBase; uint32_t screenBase;
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 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
color_t* mainPalette = renderer->normalPalette; color_t* mainPalette = renderer->normalPalette;
if (variant) { if (variant) {
mainPalette = renderer->variantPalette; mainPalette = renderer->variantPalette;
@ -1274,7 +1270,7 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
int flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \ int flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \
flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA); \ flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA); \
flags |= FLAG_TARGET_2 * background->target2; \ flags |= FLAG_TARGET_2 * background->target2; \
int variant = background->target1 && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \ int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \
color_t* palette = renderer->normalPalette; \ color_t* palette = renderer->normalPalette; \
if (variant) { \ if (variant) { \
palette = renderer->variantPalette; \ palette = renderer->variantPalette; \
@ -1516,13 +1512,13 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
int start = renderer->start; int start = renderer->start;
int end = renderer->end; int end = renderer->end;
uint32_t flags = GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY; uint32_t flags = GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY;
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT); flags |= FLAG_TARGET_1 * ((GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT);
flags |= FLAG_OBJWIN * (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN); flags |= FLAG_OBJWIN * (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN);
int32_t x = GBAObjAttributesBGetX(sprite->b) << 23; int32_t x = GBAObjAttributesBGetX(sprite->b) << 23;
x >>= 23; x >>= 23;
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1]; uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * 0x20; unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * 0x20;
int variant = renderer->target1Obj && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); int variant = renderer->target1Obj && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT && renderer->target2Bd) { if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT && renderer->target2Bd) {
// Hack: if a sprite is blended, then the variant palette is not used, but we don't know if it's blended in advance // Hack: if a sprite is blended, then the variant palette is not used, but we don't know if it's blended in advance
variant = 0; variant = 0;
@ -1620,7 +1616,7 @@ static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsign
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt); int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt);
int objwinDisable = 0; int objwinDisable = 0;
if (objwinSlowPath) { if (objwinSlowPath) {
objwinDisable = !renderer->objwin.objEnable; objwinDisable = !GBAWindowControlIsObjEnable(renderer->objwin.packed);
} }
if (objwinSlowPath && objwinDisable) { if (objwinSlowPath && objwinDisable) {
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x, ++pixel) { for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x, ++pixel) {

View File

@ -73,27 +73,21 @@ enum {
#define IS_WRITABLE(PIXEL) ((PIXEL) & 0xFE000000) #define IS_WRITABLE(PIXEL) ((PIXEL) & 0xFE000000)
union WindowRegion { struct WindowRegion {
struct { uint8_t end;
uint8_t end; uint8_t start;
uint8_t start;
};
uint16_t packed;
}; };
DECL_BITFIELD(GBAWindowControl, uint8_t);
DECL_BIT(GBAWindowControl, Bg0Enable, 0);
DECL_BIT(GBAWindowControl, Bg1Enable, 1);
DECL_BIT(GBAWindowControl, Bg2Enable, 2);
DECL_BIT(GBAWindowControl, Bg3Enable, 3);
DECL_BIT(GBAWindowControl, ObjEnable, 4);
DECL_BIT(GBAWindowControl, BlendEnable, 5);
struct WindowControl { struct WindowControl {
union { GBAWindowControl packed;
struct {
unsigned bg0Enable : 1;
unsigned bg1Enable : 1;
unsigned bg2Enable : 1;
unsigned bg3Enable : 1;
unsigned objEnable : 1;
unsigned blendEnable : 1;
unsigned : 2;
};
uint8_t packed;
};
int8_t priority; int8_t priority;
}; };
@ -140,8 +134,8 @@ struct GBAVideoSoftwareRenderer {
} mosaic; } mosaic;
struct WindowN { struct WindowN {
union WindowRegion h; struct WindowRegion h;
union WindowRegion v; struct WindowRegion v;
struct WindowControl control; struct WindowControl control;
} winN[2]; } winN[2];