Begin sprites

This commit is contained in:
Jeffrey Pfau 2013-04-24 23:40:22 -07:00
parent 00dd5bdaa8
commit 07b96cddef
4 changed files with 105 additions and 19 deletions

View File

@ -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;

View File

@ -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 disable : 1;
unsigned doublesize : 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 { int : 3;
unsigned matIndex : 5; unsigned hflip : 1;
struct { unsigned vflip : 1;
int : 3;
unsigned hflip : 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;

View File

@ -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;
} }
} }
} }

View File

@ -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;