mirror of https://github.com/mgba-emu/mgba.git
Replace bit packed structs in sprites with bitfields
This commit is contained in:
parent
235141f1f3
commit
b0726d0185
|
@ -43,69 +43,45 @@ enum ObjShape {
|
||||||
OBJ_SHAPE_VERTICAL = 2
|
OBJ_SHAPE_VERTICAL = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECL_BITFIELD(GBAObjAttributes, uint32_t);
|
||||||
|
DECL_BITS(GBAObjAttributes, Y, 0, 8);
|
||||||
|
DECL_BIT(GBAObjAttributes, Transformed, 8);
|
||||||
|
DECL_BIT(GBAObjAttributes, Disable, 9);
|
||||||
|
DECL_BIT(GBAObjAttributes, DoubleSize, 9);
|
||||||
|
DECL_BITS(GBAObjAttributes, Mode, 10, 2);
|
||||||
|
DECL_BIT(GBAObjAttributes, Mosaic, 12);
|
||||||
|
DECL_BIT(GBAObjAttributes, 256Color, 13);
|
||||||
|
DECL_BITS(GBAObjAttributes, Shape, 14, 2);
|
||||||
|
DECL_BITS(GBAObjAttributes, X, 16, 9);
|
||||||
|
DECL_BITS(GBAObjAttributes, MatIndex, 25, 5);
|
||||||
|
DECL_BIT(GBAObjAttributes, HFlip, 28);
|
||||||
|
DECL_BIT(GBAObjAttributes, VFlip, 29);
|
||||||
|
DECL_BITS(GBAObjAttributes, Size, 30, 2);
|
||||||
|
|
||||||
|
DECL_BITFIELD(GBAObjExtraAttributes, uint16_t);
|
||||||
|
DECL_BITS(GBAObjExtraAttributes, Tile, 0, 10);
|
||||||
|
DECL_BITS(GBAObjExtraAttributes, Priority, 10, 2);
|
||||||
|
DECL_BITS(GBAObjExtraAttributes, Palette, 12, 4);
|
||||||
|
|
||||||
struct GBAObj {
|
struct GBAObj {
|
||||||
unsigned y : 8;
|
GBAObjAttributes attr;
|
||||||
unsigned transformed : 1;
|
GBAObjExtraAttributes attr2;
|
||||||
unsigned disable : 1;
|
|
||||||
enum ObjMode mode : 2;
|
|
||||||
unsigned mosaic : 1;
|
|
||||||
unsigned multipalette : 1;
|
|
||||||
enum ObjShape shape : 2;
|
|
||||||
|
|
||||||
int x : 9;
|
uint16_t d;
|
||||||
int : 3;
|
|
||||||
unsigned hflip : 1;
|
|
||||||
unsigned vflip : 1;
|
|
||||||
unsigned size : 2;
|
|
||||||
|
|
||||||
unsigned tile : 10;
|
|
||||||
unsigned priority : 2;
|
|
||||||
unsigned palette : 4;
|
|
||||||
|
|
||||||
int : 16;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GBATransformedObj {
|
|
||||||
unsigned y : 8;
|
|
||||||
unsigned transformed : 1;
|
|
||||||
unsigned doublesize : 1;
|
|
||||||
enum ObjMode mode : 2;
|
|
||||||
unsigned mosaic : 1;
|
|
||||||
unsigned multipalette : 1;
|
|
||||||
enum ObjShape shape : 2;
|
|
||||||
|
|
||||||
int x : 9;
|
|
||||||
unsigned matIndex : 5;
|
|
||||||
unsigned size : 2;
|
|
||||||
|
|
||||||
unsigned tile : 10;
|
|
||||||
unsigned priority : 2;
|
|
||||||
unsigned palette : 4;
|
|
||||||
|
|
||||||
int : 16;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
union GBAOAM {
|
union GBAOAM {
|
||||||
struct GBAObj obj[128];
|
struct GBAObj obj[128];
|
||||||
struct GBATransformedObj tobj[128];
|
|
||||||
|
|
||||||
struct GBAOAMMatrix {
|
struct GBAOAMMatrix {
|
||||||
int : 16;
|
int16_t padding0[3];
|
||||||
int : 16;
|
int16_t a;
|
||||||
int : 16;
|
int16_t padding1[3];
|
||||||
int a : 16;
|
int16_t b;
|
||||||
int : 16;
|
int16_t padding2[3];
|
||||||
int : 16;
|
int16_t c;
|
||||||
int : 16;
|
int16_t padding3[3];
|
||||||
int b : 16;
|
int16_t d;
|
||||||
int : 16;
|
|
||||||
int : 16;
|
|
||||||
int : 16;
|
|
||||||
int c : 16;
|
|
||||||
int : 16;
|
|
||||||
int : 16;
|
|
||||||
int : 16;
|
|
||||||
int d : 16;
|
|
||||||
} mat[32];
|
} mat[32];
|
||||||
|
|
||||||
uint16_t raw[512];
|
uint16_t raw[512];
|
||||||
|
|
|
@ -51,7 +51,7 @@ static void _drawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
||||||
static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
||||||
static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer);
|
static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer);
|
||||||
static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBATransformedObj* sprite, int y);
|
static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y);
|
||||||
static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y);
|
static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y);
|
||||||
static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority);
|
static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority);
|
||||||
|
|
||||||
|
@ -395,14 +395,14 @@ static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
|
||||||
int oamMax = 0;
|
int oamMax = 0;
|
||||||
for (i = 0; i < 128; ++i) {
|
for (i = 0; i < 128; ++i) {
|
||||||
struct GBAObj* obj = &renderer->d.oam->obj[i];
|
struct GBAObj* obj = &renderer->d.oam->obj[i];
|
||||||
if (obj->transformed || !obj->disable) {
|
if (GBAObjAttributesIsTransformed(obj->attr) || !GBAObjAttributesIsDisable(obj->attr)) {
|
||||||
int height = _objSizes[obj->shape * 8 + obj->size * 2 + 1];
|
int height = _objSizes[GBAObjAttributesGetShape(obj->attr) * 8 + GBAObjAttributesGetSize(obj->attr) * 2 + 1];
|
||||||
if (obj->transformed) {
|
if (GBAObjAttributesIsTransformed(obj->attr)) {
|
||||||
height <<= ((struct GBATransformedObj*) obj)->doublesize;
|
height <<= GBAObjAttributesGetDoubleSize(obj->attr);
|
||||||
}
|
}
|
||||||
if (obj->y < VIDEO_VERTICAL_PIXELS || obj->y + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
if (GBAObjAttributesGetY(obj->attr) < VIDEO_VERTICAL_PIXELS || GBAObjAttributesGetY(obj->attr) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
||||||
renderer->sprites[oamMax].y = obj->y;
|
renderer->sprites[oamMax].y = GBAObjAttributesGetY(obj->attr);
|
||||||
renderer->sprites[oamMax].endY = obj->y + height;
|
renderer->sprites[oamMax].endY = GBAObjAttributesGetY(obj->attr) + height;
|
||||||
renderer->sprites[oamMax].obj = *obj;
|
renderer->sprites[oamMax].obj = *obj;
|
||||||
++oamMax;
|
++oamMax;
|
||||||
}
|
}
|
||||||
|
@ -653,18 +653,18 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
for (i = 0; i < renderer->oamMax; ++i) {
|
for (i = 0; i < renderer->oamMax; ++i) {
|
||||||
int localY = y;
|
int localY = y;
|
||||||
struct GBAVideoSoftwareSprite* sprite = &renderer->sprites[i];
|
struct GBAVideoSoftwareSprite* sprite = &renderer->sprites[i];
|
||||||
if (sprite->obj.mosaic) {
|
if (GBAObjAttributesIsMosaic(sprite->obj.attr)) {
|
||||||
localY = mosaicY;
|
localY = mosaicY;
|
||||||
}
|
}
|
||||||
if ((localY < sprite->y && (sprite->endY - 256 < 0 || localY >= sprite->endY - 256)) || localY >= sprite->endY) {
|
if ((localY < sprite->y && (sprite->endY - 256 < 0 || localY >= sprite->endY - 256)) || localY >= sprite->endY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sprite->obj.transformed) {
|
if (GBAObjAttributesIsTransformed(sprite->obj.attr)) {
|
||||||
drawn = _preprocessTransformedSprite(renderer, &sprite->tobj, localY);
|
drawn = _preprocessTransformedSprite(renderer, &sprite->obj, localY);
|
||||||
} else {
|
} else {
|
||||||
drawn = _preprocessSprite(renderer, &sprite->obj, localY);
|
drawn = _preprocessSprite(renderer, &sprite->obj, localY);
|
||||||
}
|
}
|
||||||
spriteLayers |= drawn << sprite->obj.priority;
|
spriteLayers |= drawn << GBAObjExtraAttributesGetPriority(sprite->obj.attr2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1514,18 +1514,18 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y) {
|
static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y) {
|
||||||
int width = _objSizes[sprite->shape * 8 + sprite->size * 2];
|
int width = _objSizes[GBAObjAttributesGetShape(sprite->attr) * 8 + GBAObjAttributesGetSize(sprite->attr) * 2];
|
||||||
int height = _objSizes[sprite->shape * 8 + sprite->size * 2 + 1];
|
int height = _objSizes[GBAObjAttributesGetShape(sprite->attr) * 8 + GBAObjAttributesGetSize(sprite->attr) * 2 + 1];
|
||||||
int start = renderer->start;
|
int start = renderer->start;
|
||||||
int end = renderer->end;
|
int end = renderer->end;
|
||||||
uint32_t flags = sprite->priority << OFFSET_PRIORITY;
|
uint32_t flags = GBAObjExtraAttributesGetPriority(sprite->attr2) << OFFSET_PRIORITY;
|
||||||
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || sprite->mode == OBJ_MODE_SEMITRANSPARENT);
|
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesGetMode(sprite->attr) == OBJ_MODE_SEMITRANSPARENT);
|
||||||
flags |= FLAG_OBJWIN * (sprite->mode == OBJ_MODE_OBJWIN);
|
flags |= FLAG_OBJWIN * (GBAObjAttributesGetMode(sprite->attr) == OBJ_MODE_OBJWIN);
|
||||||
int x = sprite->x;
|
int x = GBAObjAttributesGetX(sprite->attr);
|
||||||
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
||||||
unsigned charBase = sprite->tile * 0x20;
|
unsigned charBase = GBAObjExtraAttributesGetTile(sprite->attr2) * 0x20;
|
||||||
int variant = renderer->target1Obj && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
int variant = renderer->target1Obj && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
||||||
if (sprite->mode == OBJ_MODE_SEMITRANSPARENT && renderer->target2Bd) {
|
if (GBAObjAttributesGetMode(sprite->attr) == 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;
|
||||||
}
|
}
|
||||||
|
@ -1537,17 +1537,17 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
|
||||||
int outX = x >= start ? x : start;
|
int outX = x >= start ? x : start;
|
||||||
int condition = x + width;
|
int condition = x + width;
|
||||||
int mosaicH = 1;
|
int mosaicH = 1;
|
||||||
if (sprite->mosaic) {
|
if (GBAObjAttributesIsMosaic(sprite->attr)) {
|
||||||
mosaicH = renderer->mosaic.objH + 1;
|
mosaicH = renderer->mosaic.objH + 1;
|
||||||
if (condition % mosaicH) {
|
if (condition % mosaicH) {
|
||||||
condition += mosaicH - (condition % mosaicH);
|
condition += mosaicH - (condition % mosaicH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int inY = y - sprite->y;
|
int inY = y - (int) GBAObjAttributesGetY(sprite->attr);
|
||||||
if (sprite->y + height - 256 >= 0) {
|
if ((int) GBAObjAttributesGetY(sprite->attr) + height - 256 >= 0) {
|
||||||
inY += 256;
|
inY += 256;
|
||||||
}
|
}
|
||||||
if (sprite->vflip) {
|
if (GBAObjAttributesIsVFlip(sprite->attr)) {
|
||||||
inY = height - inY - 1;
|
inY = height - inY - 1;
|
||||||
}
|
}
|
||||||
if (end < condition) {
|
if (end < condition) {
|
||||||
|
@ -1555,15 +1555,15 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
|
||||||
}
|
}
|
||||||
int inX = outX - x;
|
int inX = outX - x;
|
||||||
int xOffset = 1;
|
int xOffset = 1;
|
||||||
if (sprite->hflip) {
|
if (GBAObjAttributesIsHFlip(sprite->attr)) {
|
||||||
inX = width - inX - 1;
|
inX = width - inX - 1;
|
||||||
xOffset = -1;
|
xOffset = -1;
|
||||||
}
|
}
|
||||||
if (!sprite->multipalette) {
|
if (!GBAObjAttributesIs256Color(sprite->attr)) {
|
||||||
palette = &palette[sprite->palette << 4];
|
palette = &palette[GBAObjExtraAttributesGetPalette(sprite->attr2) << 4];
|
||||||
if (flags & FLAG_OBJWIN) {
|
if (flags & FLAG_OBJWIN) {
|
||||||
SPRITE_NORMAL_LOOP(16, OBJWIN);
|
SPRITE_NORMAL_LOOP(16, OBJWIN);
|
||||||
} else if (sprite->mosaic) {
|
} else if (GBAObjAttributesIsMosaic(sprite->attr)) {
|
||||||
SPRITE_MOSAIC_LOOP(16, NORMAL);
|
SPRITE_MOSAIC_LOOP(16, NORMAL);
|
||||||
} else {
|
} else {
|
||||||
SPRITE_NORMAL_LOOP(16, NORMAL);
|
SPRITE_NORMAL_LOOP(16, NORMAL);
|
||||||
|
@ -1571,7 +1571,7 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
|
||||||
} else {
|
} else {
|
||||||
if (flags & FLAG_OBJWIN) {
|
if (flags & FLAG_OBJWIN) {
|
||||||
SPRITE_NORMAL_LOOP(256, OBJWIN);
|
SPRITE_NORMAL_LOOP(256, OBJWIN);
|
||||||
} else if (sprite->mosaic) {
|
} else if (GBAObjAttributesIsMosaic(sprite->attr)) {
|
||||||
SPRITE_MOSAIC_LOOP(256, NORMAL);
|
SPRITE_MOSAIC_LOOP(256, NORMAL);
|
||||||
} else {
|
} else {
|
||||||
SPRITE_NORMAL_LOOP(256, NORMAL);
|
SPRITE_NORMAL_LOOP(256, NORMAL);
|
||||||
|
@ -1580,22 +1580,22 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBATransformedObj* sprite, int y) {
|
static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y) {
|
||||||
int width = _objSizes[sprite->shape * 8 + sprite->size * 2];
|
int width = _objSizes[GBAObjAttributesGetShape(sprite->attr) * 8 + GBAObjAttributesGetSize(sprite->attr) * 2];
|
||||||
int height = _objSizes[sprite->shape * 8 + sprite->size * 2 + 1];
|
int height = _objSizes[GBAObjAttributesGetShape(sprite->attr) * 8 + GBAObjAttributesGetSize(sprite->attr) * 2 + 1];
|
||||||
int totalWidth = width << sprite->doublesize;
|
int totalWidth = width << GBAObjAttributesGetDoubleSize(sprite->attr);
|
||||||
int totalHeight = height << sprite->doublesize;
|
int totalHeight = height << GBAObjAttributesGetDoubleSize(sprite->attr);
|
||||||
int start = renderer->start;
|
int start = renderer->start;
|
||||||
int end = renderer->end;
|
int end = renderer->end;
|
||||||
uint32_t flags = sprite->priority << OFFSET_PRIORITY;
|
uint32_t flags = GBAObjExtraAttributesGetPriority(sprite->attr2) << OFFSET_PRIORITY;
|
||||||
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || sprite->mode == OBJ_MODE_SEMITRANSPARENT);
|
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesGetMode(sprite->attr) == OBJ_MODE_SEMITRANSPARENT);
|
||||||
flags |= FLAG_OBJWIN * (sprite->mode == OBJ_MODE_OBJWIN);
|
flags |= FLAG_OBJWIN * (GBAObjAttributesGetMode(sprite->attr) == OBJ_MODE_OBJWIN);
|
||||||
int x = sprite->x;
|
int x = GBAObjAttributesGetX(sprite->attr);
|
||||||
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
||||||
unsigned charBase = sprite->tile * 0x20;
|
unsigned charBase = GBAObjExtraAttributesGetTile(sprite->attr2) * 0x20;
|
||||||
struct GBAOAMMatrix* mat = &renderer->d.oam->mat[sprite->matIndex];
|
struct GBAOAMMatrix* mat = &renderer->d.oam->mat[GBAObjAttributesGetMatIndex(sprite->attr)];
|
||||||
int variant = renderer->target1Obj && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
int variant = renderer->target1Obj && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
||||||
if (sprite->mode == OBJ_MODE_SEMITRANSPARENT && renderer->target2Bd) {
|
if (GBAObjAttributesGetMode(sprite->attr) == 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;
|
||||||
}
|
}
|
||||||
|
@ -1603,12 +1603,12 @@ static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* rendere
|
||||||
if (variant) {
|
if (variant) {
|
||||||
palette = &renderer->variantPalette[0x100];
|
palette = &renderer->variantPalette[0x100];
|
||||||
}
|
}
|
||||||
int inY = y - sprite->y;
|
int inY = y - (int) GBAObjAttributesGetY(sprite->attr);
|
||||||
if (inY < 0) {
|
if (inY < 0) {
|
||||||
inY += 256;
|
inY += 256;
|
||||||
}
|
}
|
||||||
if (!sprite->multipalette) {
|
if (!GBAObjAttributesIs256Color(sprite->attr)) {
|
||||||
palette = &palette[sprite->palette << 4];
|
palette = &palette[GBAObjExtraAttributesGetPalette(sprite->attr2) << 4];
|
||||||
if (flags & FLAG_OBJWIN) {
|
if (flags & FLAG_OBJWIN) {
|
||||||
SPRITE_TRANSFORMED_LOOP(16, OBJWIN);
|
SPRITE_TRANSFORMED_LOOP(16, OBJWIN);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,10 +12,7 @@ typedef uint32_t color_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct GBAVideoSoftwareSprite {
|
struct GBAVideoSoftwareSprite {
|
||||||
union {
|
|
||||||
struct GBAObj obj;
|
struct GBAObj obj;
|
||||||
struct GBATransformedObj tobj;
|
|
||||||
};
|
|
||||||
int y;
|
int y;
|
||||||
int endY;
|
int endY;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue