mirror of https://github.com/mgba-emu/mgba.git
Begin sprites
This commit is contained in:
parent
00dd5bdaa8
commit
07b96cddef
|
@ -296,6 +296,7 @@ void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BASE_OAM:
|
case BASE_OAM:
|
||||||
|
((int32_t*) gbaMemory->p->video.oam.raw)[(address & (SIZE_OAM - 1)) >> 2] = value;
|
||||||
break;
|
break;
|
||||||
case BASE_CART0:
|
case BASE_CART0:
|
||||||
break;
|
break;
|
||||||
|
@ -330,6 +331,7 @@ void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BASE_OAM:
|
case BASE_OAM:
|
||||||
|
gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1] = value;
|
||||||
break;
|
break;
|
||||||
case BASE_CART0:
|
case BASE_CART0:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -20,7 +20,9 @@ enum {
|
||||||
|
|
||||||
VIDEO_TOTAL_LENGTH = 280896,
|
VIDEO_TOTAL_LENGTH = 280896,
|
||||||
|
|
||||||
REG_DISPSTAT_MASK = 0xFF38
|
REG_DISPSTAT_MASK = 0xFF38,
|
||||||
|
|
||||||
|
BASE_TILE = 0x00010000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ObjMode {
|
enum ObjMode {
|
||||||
|
@ -45,27 +47,19 @@ union GBAColor {
|
||||||
};
|
};
|
||||||
|
|
||||||
union GBAOAM {
|
union GBAOAM {
|
||||||
struct {
|
struct GBAObj {
|
||||||
int y : 8;
|
int y : 8;
|
||||||
unsigned transformed : 1;
|
unsigned transformed : 1;
|
||||||
union {
|
|
||||||
unsigned doublesize : 1;
|
|
||||||
unsigned disable : 1;
|
unsigned disable : 1;
|
||||||
};
|
|
||||||
enum ObjMode mode : 2;
|
enum ObjMode mode : 2;
|
||||||
unsigned mosaic : 1;
|
unsigned mosaic : 1;
|
||||||
unsigned multipalette : 1;
|
unsigned multipalette : 1;
|
||||||
enum ObjShape shape : 2;
|
enum ObjShape shape : 2;
|
||||||
|
|
||||||
int x : 9;
|
int x : 9;
|
||||||
union {
|
|
||||||
unsigned matIndex : 5;
|
|
||||||
struct {
|
|
||||||
int : 3;
|
int : 3;
|
||||||
unsigned hflip : 1;
|
unsigned hflip : 1;
|
||||||
unsigned vflip : 1;
|
unsigned vflip : 1;
|
||||||
};
|
|
||||||
};
|
|
||||||
unsigned size : 2;
|
unsigned size : 2;
|
||||||
|
|
||||||
unsigned tile : 10;
|
unsigned tile : 10;
|
||||||
|
@ -75,6 +69,26 @@ union GBAOAM {
|
||||||
int : 16;
|
int : 16;
|
||||||
} obj[128];
|
} obj[128];
|
||||||
|
|
||||||
|
struct GBATransformedObj {
|
||||||
|
int 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;
|
||||||
|
} tobj[128];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int : 16;
|
int : 16;
|
||||||
int : 16;
|
int : 16;
|
||||||
|
|
|
@ -16,8 +16,9 @@ static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRendere
|
||||||
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value);
|
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value);
|
||||||
static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* renderer, uint16_t value);
|
static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* renderer, uint16_t value);
|
||||||
|
|
||||||
static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, int entry, struct PixelFlags flags);
|
static void _compositeBackground(struct GBAVideoSoftwareRenderer* renderer, int offset, int entry, struct PixelFlags flags);
|
||||||
static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y);
|
||||||
|
static void _drawSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* spritem, int y);
|
||||||
|
|
||||||
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer);
|
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer);
|
||||||
static inline uint16_t _brighten(uint16_t color, int y);
|
static inline uint16_t _brighten(uint16_t color, int y);
|
||||||
|
@ -201,6 +202,19 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
||||||
memset(softwareRenderer->flags, 0, sizeof(softwareRenderer->flags));
|
memset(softwareRenderer->flags, 0, sizeof(softwareRenderer->flags));
|
||||||
softwareRenderer->row = row;
|
softwareRenderer->row = row;
|
||||||
|
|
||||||
|
if (softwareRenderer->dispcnt.objEnable) {
|
||||||
|
for (int i = 0; i < 128; ++i) {
|
||||||
|
struct GBAObj* sprite = &renderer->oam->obj[i];
|
||||||
|
if (sprite->transformed) {
|
||||||
|
// TODO
|
||||||
|
} else if (!sprite->disable) {
|
||||||
|
if (sprite->y <= y) {
|
||||||
|
_drawSprite(softwareRenderer, sprite, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
if (softwareRenderer->sortedBg[i]->enabled) {
|
if (softwareRenderer->sortedBg[i]->enabled) {
|
||||||
_drawBackgroundMode0(softwareRenderer, softwareRenderer->sortedBg[i], y);
|
_drawBackgroundMode0(softwareRenderer, softwareRenderer->sortedBg[i], y);
|
||||||
|
@ -282,7 +296,10 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, int entry, struct PixelFlags flags) {
|
static void _compositeBackground(struct GBAVideoSoftwareRenderer* renderer, int offset, int entry, struct PixelFlags flags) {
|
||||||
|
if (renderer->flags[offset].isSprite && flags.priority >= renderer->flags[offset].priority) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (renderer->blendEffect == BLEND_NONE || (!flags.target1 && !flags.target2)) {
|
if (renderer->blendEffect == BLEND_NONE || (!flags.target1 && !flags.target2)) {
|
||||||
renderer->row[offset] = renderer->d.palette[entry];
|
renderer->row[offset] = renderer->d.palette[entry];
|
||||||
renderer->flags[offset].finalized = 1;
|
renderer->flags[offset].finalized = 1;
|
||||||
|
@ -339,11 +356,62 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
|
||||||
tileData >>= ((outX + inX) & 0x3) << 2;
|
tileData >>= ((outX + inX) & 0x3) << 2;
|
||||||
if (tileData & 0xF) {
|
if (tileData & 0xF) {
|
||||||
struct PixelFlags flags = {
|
struct PixelFlags flags = {
|
||||||
.finalized = 1,
|
|
||||||
.target1 = background->target1,
|
.target1 = background->target1,
|
||||||
.target2 = background->target2
|
.target2 = background->target2,
|
||||||
|
.priority = background->priority
|
||||||
};
|
};
|
||||||
_composite(renderer, outX, (tileData & 0xF) | (mapData.palette << 4), flags);
|
_compositeBackground(renderer, outX, (tileData & 0xF) | (mapData.palette << 4), flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int _objSizes[32] = {
|
||||||
|
8, 8,
|
||||||
|
16, 16,
|
||||||
|
32, 32,
|
||||||
|
64, 64,
|
||||||
|
16, 8,
|
||||||
|
32, 8,
|
||||||
|
32, 16,
|
||||||
|
64, 32,
|
||||||
|
8, 16,
|
||||||
|
8, 32,
|
||||||
|
16, 32,
|
||||||
|
32, 64,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _drawSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y) {
|
||||||
|
int width = _objSizes[sprite->shape * 8 + sprite->size * 2];
|
||||||
|
int height = _objSizes[sprite->shape * 8 + sprite->size * 2 + 1];
|
||||||
|
if (y >= sprite->y + height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void)(renderer);
|
||||||
|
struct PixelFlags flags = {
|
||||||
|
.priority = sprite->priority,
|
||||||
|
.isSprite = 1,
|
||||||
|
.target1 = renderer->target1Obj,
|
||||||
|
.target2 = renderer->target1Obj || sprite->mode == OBJ_MODE_SEMITRANSPARENT
|
||||||
|
};
|
||||||
|
int inX = sprite->x;
|
||||||
|
int inY = y - sprite->y;
|
||||||
|
unsigned charBase = BASE_TILE + sprite->tile * 0x20;
|
||||||
|
unsigned yBase = (inY & ~0x7) * 0x80 + (inY & 0x7) * 4;
|
||||||
|
for (int outX = inX >= 0 ? inX : 0; outX < inX + width && outX < VIDEO_HORIZONTAL_PIXELS; ++outX) {
|
||||||
|
int x = outX - inX;
|
||||||
|
if (renderer->flags[outX].isSprite) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unsigned xBase = (x & ~0x7) * 4 + ((x >> 1) & 2);
|
||||||
|
uint16_t tileData = renderer->d.vram[(yBase + charBase + xBase) >> 1];
|
||||||
|
tileData = (tileData >> ((x & 3) << 2)) & 0xF;
|
||||||
|
if (tileData) {
|
||||||
|
renderer->row[outX] = renderer->d.palette[0x100 | tileData | (sprite->palette << 4)];
|
||||||
|
renderer->flags[outX] = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ enum BlendEffect {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PixelFlags {
|
struct PixelFlags {
|
||||||
|
unsigned priority : 2;
|
||||||
|
unsigned isSprite : 1;
|
||||||
unsigned written : 1;
|
unsigned written : 1;
|
||||||
unsigned finalized : 1;
|
unsigned finalized : 1;
|
||||||
unsigned target1 : 1;
|
unsigned target1 : 1;
|
||||||
|
|
Loading…
Reference in New Issue