This commit is contained in:
CreateSource 2023-12-03 12:53:22 -05:00
commit 501423f03e
11 changed files with 1321 additions and 90 deletions

712
src/game/sprman.c Normal file
View file

@ -0,0 +1,712 @@
#include "common.h"
#include "dolphin/mtx.h"
SpriteData HuSprData[384];
SpriteGroupData HuSprGrpData[256];
static SpriteOrderData HuSprOrder[384*2];
static short HuSprOrderNum;
static short HuSprOrderNo;
static BOOL HuSprPauseF;
static void HuSprOrderEntry(short group, short sprite);
void mtxTransCat(Mtx matrix, float x, float y, int z); //Last argument should be a float
void HuSprInit(void)
{
short i;
SpriteData *sprite;
SpriteGroupData *group;
for(sprite = &HuSprData[1], i=1; i<384; i++, sprite++) {
sprite->data = NULL;
}
for(group = HuSprGrpData, i=0; i<256; i++, group++) {
group->capacity = 0;
}
sprite = &HuSprData[0];
sprite->prio = 0;
sprite->data = (void *)1;
HuSprPauseF = FALSE;
}
void HuSprClose(void)
{
short i;
SpriteGroupData *group;
SpriteData *sprite;
for(group = HuSprGrpData, i=0; i<256; i++, group++) {
if(group->capacity != 0) {
HuSprGrpKill(i);
}
}
for(sprite = &HuSprData[1], i=1; i<384; i++, sprite++) {
if(sprite->data) {
HuSprKill(i);
}
}
HuSprPauseF = FALSE;
}
void HuSprExec(short draw_no)
{
SpriteData *sprite;
while(sprite = HuSprCall()) {
if(!(sprite->attr & 0x4) && sprite->draw_no == draw_no) {
HuSprDisp(sprite);
}
}
}
void HuSprBegin(void)
{
Mtx temp, rot;
short i, j;
Vec axis = {0, 0, 1};
SpriteGroupData *group;
group = HuSprGrpData;
HuSprOrderNum = 1;
HuSprOrder[0].next = 0;
HuSprOrder[0].prio = -1;
for(i=0; i<256; i++, group++) {
if(group->capacity != 0) {
MTXTrans(temp, group->center_x*group->scale_x, group->center_y*group->scale_y, 0.0f);
MTXRotAxisDeg(rot, &axis, group->z_rot);
MTXConcat(rot, temp, group->mtx);
MTXScale(temp, group->scale_x, group->scale_y, 1.0f);
MTXConcat(group->mtx, temp, group->mtx);
mtxTransCat(group->mtx, group->x, group->y, 0);
for(j=0; j<group->capacity; j++) {
if(group->members[j] != -1) {
HuSprOrderEntry(i, group->members[j]);
}
}
}
}
HuSprOrderNo = 0;
}
static void HuSprOrderEntry(short group, short sprite)
{
SpriteOrderData *order = &HuSprOrder[HuSprOrderNum];
short prio = HuSprData[sprite].prio;
short prev, next;
if(HuSprOrderNum >= 384*2) {
OSReport("Order Max Over!\n");
return;
}
next = HuSprOrder[0].next;
for(prev = 0; next != 0; prev = next, next = HuSprOrder[next].next) {
if(HuSprOrder[next].prio < prio) {
break;
}
}
order->next = HuSprOrder[prev].next;
HuSprOrder[prev].next = HuSprOrderNum;
order->prio = prio;
order->group = group;
order->sprite = sprite;
HuSprOrderNum++;
}
SpriteData *HuSprCall(void)
{
HuSprOrderNo = HuSprOrder[HuSprOrderNo].next;
if(HuSprOrderNo != 0) {
SpriteOrderData *order = &HuSprOrder[HuSprOrderNo];
SpriteData *sprite = &HuSprData[order->sprite];
sprite->group_mtx = &HuSprGrpData[order->group].mtx;
if(sprite->attr & 0x10) {
return sprite;
}
sprite->frame_data = &sprite->data->bank[sprite->bank].frame[sprite->frame];
sprite->pat_data = &sprite->data->pat[sprite->frame_data->pat];
return sprite;
} else {
return NULL;
}
}
static inline void SpriteCalcFrame(SpriteData *sprite, AnimBankData *bank, AnimFrameData **frame, short wrap)
{
if(sprite->time >= (*frame)->time) {
sprite->frame++;
sprite->time -= (*frame)->time;
if(sprite->frame >= bank->timeNum || (*frame)[1].time == -1) {
if(wrap) {
sprite->frame = 0;
} else {
sprite->frame = bank->timeNum-1;
}
}
*frame = &bank->frame[sprite->frame];
} else if(sprite->time < 0) {
sprite->frame--;
if(sprite->frame < 0) {
if(wrap) {
sprite->frame = bank->timeNum-1;
} else {
sprite->frame = 0;
}
}
*frame = &bank->frame[sprite->frame];
sprite->time += (*frame)->time;
}
}
void HuSprFinish(void)
{
AnimData *anim;
AnimBankData *bank;
AnimFrameData *frame;
SpriteData *sprite;
short i;
short j;
short wrap;
short dir;
for(sprite = &HuSprData[1], i=1; i<384; i++, sprite++) {
if(sprite->data && !(sprite->attr & 0x10)) {
if(!HuSprPauseF || (sprite->attr & 0x20)) {
anim = sprite->data;
bank = &anim->bank[sprite->bank];
frame = &bank->frame[sprite->frame];
wrap = (sprite->attr & 0x2) ? 0 : 1;
if(!(sprite->attr & 0x1)) {
dir = (sprite->attr & 0x40) ? -1 : 1;
for(j=0; j<(int)sprite->speed*minimumVcount; j++) {
sprite->time += dir;
SpriteCalcFrame(sprite, bank, &frame, wrap);
}
sprite->time += (sprite->speed*(float)minimumVcount)-j;
SpriteCalcFrame(sprite, bank, &frame, wrap);
}
sprite->dirty_flag = 0;
}
}
}
}
void HuSprPauseSet(BOOL value)
{
HuSprPauseF = value;
}
AnimData *HuSprAnimRead(void *data)
{
short i;
AnimBmpData *bmp;
AnimBankData *bank;
AnimPatData *pat;
AnimData *anim = (AnimData *)data;
if((u32)anim->bank & 0xFFFF0000) {
anim->useNum++;
return anim;
}
bank = (AnimBankData *)((u32)anim->bank+(u32)data);
anim->bank = bank;
pat = (AnimPatData *)((u32)anim->pat+(u32)data);
anim->pat = pat;
bmp = (AnimBmpData *)((u32)anim->bmp+(u32)data);
anim->bmp = bmp;
for(i=0; i<anim->bankNum; i++, bank++) {
bank->frame = (AnimFrameData *)((u32)bank->frame+(u32)data);
}
for(i=0; i<anim->patNum; i++, pat++) {
pat->layer = (AnimLayerData *)((u32)pat->layer+(u32)data);
}
for(i=0; i<anim->bmpNum; i++, bmp++) {
bmp->palData = (void *)((u32)bmp->palData+(u32)data);
bmp->data = (void *)((u32)bmp->data+(u32)data);
}
anim->useNum = 0;
return anim;
}
void HuSprAnimLock(AnimData *anim)
{
anim->useNum++;
}
short HuSprCreate(AnimData *anim, short prio, short bank)
{
SpriteData *sprite;
short i;
for(sprite = &HuSprData[1], i=1; i<384; i++, sprite++) {
if(!sprite->data) {
break;
}
}
if(i == 384) {
return -1;
}
sprite->data = anim;
sprite->speed = 1.0f;
sprite->frame = 0;
sprite->bank = bank;
sprite->time = 0.0f;
sprite->attr = 0;
sprite->draw_no = 0;
sprite->r = sprite->g = sprite->b = sprite->a = 255;
sprite->x = sprite->y = sprite->z_rot = 0.0f;
sprite->prio = prio;
sprite->scale_x = sprite->scale_y = 1.0f;
sprite->wrap_s = sprite->wrap_t = GX_CLAMP;
sprite->tex_scale_x = sprite->tex_scale_y = 1;
sprite->bg = NULL;
sprite->scissor_x = sprite->scissor_y = 0;
sprite->scissor_w = 640;
sprite->scissor_h = 480;
if(anim) {
HuSprAnimLock(anim);
}
return i;
}
short HuSprFuncCreate(void (*func)(SpriteData *sprite), short prio)
{
SpriteData *sprite;
short index = HuSprCreate(NULL, prio, 0);
if(index == -1) {
return -1;
}
sprite = &HuSprData[index];
sprite->func = func;
sprite->attr |= 0x10;
return index;
}
short HuSprGrpCreate(short capacity)
{
SpriteGroupData *group;
short i, j;
for(group = HuSprGrpData, i=0; i<256; i++, group++) {
if(group->capacity == 0) {
break;
}
}
if(i == 256) {
return -1;
}
group->members = HuMemDirectMalloc(HEAP_SYSTEM, sizeof(short)*capacity);
for(j=0; j<capacity; j++) {
group->members[j] = -1;
}
group->capacity = capacity;
group->x = group->y = group->z_rot = group->center_x = group->center_y = 0.0f;
group->scale_x = group->scale_y = 1.0f;
return i;
}
short HuSprGrpCopy(short group)
{
SpriteGroupData *new_group_ptr;
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short new_group = HuSprGrpCreate(group_ptr->capacity);
short i;
if(new_group == -1) {
return -1;
}
new_group_ptr = &HuSprGrpData[new_group];
new_group_ptr->x = group_ptr->x;
new_group_ptr->y = group_ptr->y;
new_group_ptr->z_rot = group_ptr->z_rot;
new_group_ptr->scale_x = group_ptr->scale_x;
new_group_ptr->scale_y = group_ptr->scale_y;
new_group_ptr->center_x = group_ptr->center_x;
new_group_ptr->center_y = group_ptr->center_y;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
SpriteData *old_sprite = &HuSprData[group_ptr->members[i]];
short new_sprite = HuSprCreate(old_sprite->data, old_sprite->prio, old_sprite->bank);
HuSprData[new_sprite] = *old_sprite;
HuSprGrpMemberSet(new_group, i, new_sprite);
}
}
return new_group;
}
void HuSprGrpMemberSet(short group, short member, short sprite)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
SpriteData *sprite_ptr = &HuSprData[sprite];
if(group_ptr->capacity == 0 || group_ptr->capacity <= member || group_ptr->members[member] != -1) {
return;
}
group_ptr->members[member] = sprite;
}
void HuSprGrpMemberKill(short group, short member)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
if(group_ptr->capacity == 0 || group_ptr->capacity <= member || group_ptr->members[member] == -1) {
return;
}
HuSprKill(group_ptr->members[member]);
group_ptr->members[member] = -1;
}
void HuSprGrpKill(short group)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprKill(group_ptr->members[i]);
}
}
group_ptr->capacity = 0;
HuMemDirectFree(group_ptr->members);
}
void HuSprKill(short sprite)
{
SpriteData *sprite_ptr = &HuSprData[sprite];
if(!sprite_ptr->data) {
return;
}
if(!(sprite_ptr->attr & 0x10)) {
HuSprAnimKill(sprite_ptr->data);
if(sprite_ptr->bg) {
HuSprAnimKill(sprite_ptr->bg);
sprite_ptr->bg = NULL;
}
}
sprite_ptr->data = NULL;
}
void HuSprAnimKill(AnimData *anim)
{
if(--anim->useNum <= 0) {
if(anim->bmpNum & 0x8000) {
if(anim->bmp->data) {
HuMemDirectFree(anim->bmp->data);
}
if(anim->bmp->palData) {
HuMemDirectFree(anim->bmp->palData);
}
}
HuMemDirectFree(anim);
}
}
void HuSprAttrSet(short group, short member, int attr)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
SpriteData *sprite_ptr;
if(group_ptr->capacity == 0 || group_ptr->capacity <= member || group_ptr->members[member] == -1) {
return;
}
sprite_ptr = &HuSprData[group_ptr->members[member]];
sprite_ptr->attr |= attr;
sprite_ptr->dirty_flag |= 0x1;
}
void HuSprAttrReset(short group, short member, int attr)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
SpriteData *sprite_ptr;
if(group_ptr->capacity == 0 || group_ptr->capacity <= member || group_ptr->members[member] == -1) {
return;
}
sprite_ptr = &HuSprData[group_ptr->members[member]];
sprite_ptr->attr &= ~attr;
sprite_ptr->dirty_flag |= 0x1;
}
void HuSprPosSet(short group, short member, float x, float y)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->x = x;
sprite_ptr->y = y;
sprite_ptr->dirty_flag |= 0x2;
}
void HuSprZRotSet(short group, short member, float z_rot)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->z_rot = z_rot;
sprite_ptr->dirty_flag |= 0x2;
}
void HuSprScaleSet(short group, short member, float x, float y)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->scale_x = x;
sprite_ptr->scale_y = y;
sprite_ptr->dirty_flag |= 0x2;
}
void HuSprTPLvlSet(short group, short member, float tp_lvl)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->a = tp_lvl*255;
sprite_ptr->dirty_flag |= 0x4;
}
void HuSprColorSet(short group, short member, u8 r, u8 g, u8 b)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->r = r;
sprite_ptr->g = g;
sprite_ptr->b = b;
sprite_ptr->dirty_flag |= 0x4;
}
void HuSprSpeedSet(short group, short member, float speed)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
HuSprData[group_ptr->members[member]].speed = speed;
}
void HuSprBankSet(short group, short member, short bank)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
AnimData *anim = sprite_ptr->data;
AnimBankData *bank_ptr = &anim->bank[sprite_ptr->bank];
AnimFrameData *frame_ptr = &bank_ptr->frame[sprite_ptr->frame];
sprite_ptr->bank = bank;
if(sprite_ptr->attr & 0x40) {
sprite_ptr->frame = bank_ptr->timeNum-1;
frame_ptr = &bank_ptr->frame[sprite_ptr->frame];
sprite_ptr->time = frame_ptr->time;
} else {
sprite_ptr->time = 0;
sprite_ptr->frame = 0;
}
}
void HuSprGrpPosSet(short group, float x, float y)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
group_ptr->x = x;
group_ptr->y = y;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].dirty_flag |= 0x2;
}
}
}
void HuSprGrpCenterSet(short group, float x, float y)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
group_ptr->center_x = x;
group_ptr->center_y = y;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].dirty_flag |= 0x2;
}
}
}
void HuSprGrpZRotSet(short group, float z_rot)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
group_ptr->z_rot = z_rot;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].dirty_flag |= 0x2;
}
}
}
void HuSprGrpScaleSet(short group, float x, float y)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
group_ptr->scale_x = x;
group_ptr->scale_y = y;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].dirty_flag |= 0x2;
}
}
}
void HuSprGrpTPLvlSet(short group, float tp_lvl)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].a = tp_lvl*255;
HuSprData[group_ptr->members[i]].dirty_flag |= 0x4;
}
}
}
void HuSprGrpDrawNoSet(short group, int draw_no)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprData[group_ptr->members[i]].draw_no = draw_no;
}
}
}
void HuSprDrawNoSet(short group, short member, int draw_no)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->draw_no = draw_no;
}
void HuSprPriSet(short group, short member, short prio)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->prio = prio;
}
void HuSprGrpScissorSet(short group, short x, short y, short w, short h)
{
SpriteGroupData *group_ptr = &HuSprGrpData[group];
short i;
for(i=0; i<group_ptr->capacity; i++) {
if(group_ptr->members[i] != -1) {
HuSprScissorSet(group, i, x, y, w, h);
}
}
}
void HuSprScissorSet(short group, short member, short x, short y, short w, short h)
{
SpriteData *sprite_ptr = &HuSprData[HuSprGrpData[group].members[member]];
sprite_ptr->scissor_x = x;
sprite_ptr->scissor_y = y;
sprite_ptr->scissor_w = w;
sprite_ptr->scissor_h = h;
}
static short bitSizeTbl[11] = { 32, 24, 16, 8, 4, 16, 8, 8, 4, 8, 4 };
AnimData *HuSprAnimMake(short sizeX, short sizeY, short dataFmt)
{
AnimLayerData *layer;
AnimBmpData *bmp;
AnimData *anim;
AnimPatData *pat;
AnimFrameData *frame;
void *temp;
AnimBankData *bank;
AnimData *new_anim;
anim = new_anim = HuMemDirectMalloc(HEAP_DATA, sizeof(AnimData)+sizeof(AnimBankData)+sizeof(AnimFrameData)
+sizeof(AnimPatData)+sizeof(AnimLayerData)+sizeof(AnimBmpData));
bank = temp = &new_anim[1];
anim->bank = bank;
frame = temp = ((char *)temp+sizeof(AnimBankData));
bank->frame = frame;
pat = temp = ((char *)temp+sizeof(AnimFrameData));
anim->pat = pat;
layer = temp = ((char *)temp+sizeof(AnimPatData));
pat->layer = layer;
bmp = temp = ((char *)temp+sizeof(AnimLayerData));
anim->bmp = bmp;
anim->useNum = 0;
anim->bankNum = 1;
anim->patNum = 1;
anim->bmpNum = (1|0x8000);
bank->timeNum = 1;
bank->unk = 10;
frame->pat = 0;
frame->time = 10;
frame->shiftX = frame->shiftY = frame->flip = 0;
pat->layerNum = 1;
pat->centerX = sizeX/2;
pat->centerY = sizeY/2;
pat->sizeX = sizeX;
pat->sizeY = sizeY;
layer->alpha = 255;
layer->flip = 0;
layer->bmpNo = 0;
layer->startX = layer->startY = 0;
layer->sizeX = sizeX;
layer->sizeY = sizeY;
layer->shiftX = layer->shiftY = 0;
layer->vtx[0] = layer->vtx[1] = 0;
layer->vtx[2] = sizeX;
layer->vtx[3] = 0;
layer->vtx[4] = sizeX;
layer->vtx[5] = sizeY;
layer->vtx[6] = 0;
layer->vtx[7] = sizeY;
bmp->pixSize = bitSizeTbl[dataFmt];
bmp->dataFmt = dataFmt;
bmp->palNum = 0;
bmp->sizeX = sizeX;
bmp->sizeY = sizeY;
bmp->dataSize = sizeX*sizeY*bitSizeTbl[dataFmt]/8;
bmp->palData = NULL;
bmp->data = NULL;
return anim;
}
void HuSprBGSet(short group, short member, AnimData *bg, short bg_bank)
{
short sprite = HuSprGrpData[group].members[member];
HuSprSprBGSet(sprite, bg, bg_bank);
}
void HuSprSprBGSet(short sprite, AnimData *bg, short bg_bank)
{
SpriteData *sprite_ptr = &HuSprData[sprite];
sprite_ptr->bg = bg;
sprite_ptr->bg_bank = bg_bank;
sprite_ptr->wrap_t = sprite_ptr->wrap_s = GX_REPEAT;
sprite_ptr->attr &= ~0x8;
}
void AnimDebug(AnimData *anim)
{
AnimPatData *pat;
AnimLayerData *layer;
s16 i;
s16 j;
AnimFrameData *frame;
AnimBankData *bank;
AnimBmpData *bmp;
OSReport("patNum %d,bankNum %d,bmpNum %d\n", anim->patNum, anim->bankNum, anim->bmpNum & 0x7FFF);
pat = anim->pat;
for(i=0; i<anim->patNum; i++) {
OSReport("PATTERN%d:\n", i);
OSReport("\tlayerNum %d,center (%d,%d),size (%d,%d)\n", pat->layerNum, pat->centerX, pat->centerX, pat->sizeX, pat->sizeY);
layer = pat->layer;
for(j=0; j<pat->layerNum; j++) {
OSReport("\t\tfileNo %d,flip %x\n", layer->bmpNo, layer->flip);
OSReport("\t\tstart (%d,%d),size (%d,%d),shift (%d,%d)\n", layer->startX, layer->startY, layer->sizeX, layer->sizeY, layer->shiftX, layer->shiftY);
if(j != pat->layerNum-1) {
OSReport("\n");
}
layer++;
}
pat++;
}
bank = anim->bank;
for(i=0; i<anim->bankNum; i++) {
OSReport("BANK%d:\n", i);
OSReport("\ttimeNum %d\n", bank->timeNum);
frame = bank->frame;
for(j=0; j<bank->timeNum; j++) {
OSReport("\t\tpat %d,time %d,shift(%d,%d),flip %x\n", frame->pat, frame->time, frame->shiftX, frame->shiftY, frame->flip);
frame++;
}
bank++;
}
bmp = anim->bmp;
for(i=0; i<anim->bmpNum & 0x7FFF; i++) {
OSReport("BMP%d:\n", i);
OSReport("\tpixSize %d,palNum %d,size (%d,%d)\n", bmp->pixSize, bmp->palNum, bmp->sizeX, bmp->sizeY);
bmp++;
}
}

252
src/game/sprput.c Normal file
View file

@ -0,0 +1,252 @@
#include "common.h"
#include "dolphin/mtx.h"
#include "dolphin/gx.h"
#include "dolphin/vi.h"
static void *bmpNoCC[8];
static short HuSprLayerDrawNo[8];
static short bmpCCIdx;
void mtxTransCat(Mtx matrix, float x, float y, float z);
static void HuSprLayerHook(short layer);
void HuSprDispInit(void)
{
Mtx44 proj;
short i;
for(i=0; i<8; i++) {
bmpNoCC[i] = NULL;
}
bmpCCIdx = 0;
GXInvalidateTexAll();
MTXOrtho(proj, 0, 480, 0, 576, 0, 10);
GXSetProjection(proj, GX_ORTHOGRAPHIC);
if(RenderMode->field_rendering) {
GXSetViewportJitter(0, 0, 640, 480, 0, 1, VIGetNextField());
} else {
GXSetViewport(0, 0, 640, 480, 0, 1);
}
GXSetScissor(0, 0, 640, 480);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetCullMode(GX_CULL_NONE);
GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
}
void HuSprDisp(SpriteData *sprite)
{
short i;
AnimData *anim = sprite->data;
AnimPatData *pat = sprite->pat_data;
Vec axis = {0, 0, 1};
Mtx modelview, rot;
short color_sum;
void (*func)(SpriteData *);
GXSetScissor(sprite->scissor_x, sprite->scissor_y, sprite->scissor_w, sprite->scissor_h);
if(sprite->attr & 0x10) {
if(sprite->func) {
func = sprite->func;
func(sprite);
HuSprDispInit();
}
} else {
AnimLayerData *layer;
AnimBmpData *bg_bmp;
GXColor color;
GXSetNumTexGens(1);
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
color.r = color.g = color.b = color.a = 255;
GXSetChanAmbColor(GX_COLOR0A0, color);
GXSetChanMatColor(GX_COLOR0A0, color);
color.r = sprite->r;
color.g = sprite->g;
color.b = sprite->b;
color.a = sprite->a;
color_sum = color.r+color.g+color.b+color.a;
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_C0, GX_CC_CPREV, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_APREV, GX_CA_A0, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_CLAMP, GX_AF_SPOT);
if(sprite->attr & 0x80) {
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_NOOP);
} else if(sprite->attr & 0x100) {
GXSetBlendMode(GX_BM_BLEND, GX_BL_ZERO, GX_BL_INVDSTCLR, GX_LO_NOOP);
} else {
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
}
if(sprite->bg) {
AnimPatData *bg_pat;
AnimFrameData *bg_frame;
bg_frame = sprite->bg->bank[sprite->bg_bank].frame;
bg_pat = &sprite->bg->pat[bg_frame->pat];
layer = bg_pat->layer;
bg_bmp = &sprite->bg->bmp[layer->bmpNo];
HuSprTexLoad(sprite->bg, layer->bmpNo, 1, GX_CLAMP, GX_CLAMP, GX_NEAR);
GXSetNumIndStages(1);
GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_TRUE, bg_bmp->sizeX*16, bg_bmp->sizeY*16);
GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP1);
GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_16, GX_ITS_16);
GXSetTevIndTile(GX_TEVSTAGE0, GX_INDTEXSTAGE0, 16, 16, 16, 16, GX_ITF_4, GX_ITM_0, GX_ITB_NONE, GX_ITBA_OFF);
}
GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1);
GXSetZCompLoc(GX_FALSE);
if(0 != sprite->z_rot) {
MTXRotAxisDeg(rot, &axis, sprite->z_rot);
MTXScale(modelview, sprite->scale_x, sprite->scale_y, 1.0f);
MTXConcat(rot, modelview, modelview);
} else {
MTXScale(modelview, sprite->scale_x, sprite->scale_y, 1.0f);
}
mtxTransCat(modelview, sprite->x, sprite->y, 0);
MTXConcat(*sprite->group_mtx, modelview, modelview);
GXLoadPosMtxImm(modelview, GX_PNMTX0);
for(i=pat->layerNum-1; i>=0; i--) {
float pos[4][2];
float texcoord_x1, texcoord_y1, texcoord_x2, texcoord_y2;
AnimBmpData *bmp;
layer = &pat->layer[i];
bmp = &anim->bmp[layer->bmpNo];
if(!bmp) {
continue;
}
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
HuSprTexLoad(anim, layer->bmpNo, 0, sprite->wrap_s, sprite->wrap_t, (sprite->attr & 0x8) ? 1 : 0);
if(layer->alpha != 0xFF || color_sum != 1020) {
color.a = (u16)(sprite->a*layer->alpha) >> 8;
GXSetTevColor(GX_TEVSTAGE1, color);
GXSetNumTevStages(2);
} else {
GXSetNumTevStages(1);
}
if(!sprite->bg) {
pos[0][0] = layer->vtx[0]-pat->centerX;
pos[0][1] = layer->vtx[1]-pat->centerY;
pos[1][0] = layer->vtx[2]-pat->centerX;
pos[1][1] = layer->vtx[3]-pat->centerY;
pos[2][0] = layer->vtx[4]-pat->centerX;
pos[2][1] = layer->vtx[5]-pat->centerY;
pos[3][0] = layer->vtx[6]-pat->centerX;
pos[3][1] = layer->vtx[7]-pat->centerY;
if(layer->flip & 0x1) {
texcoord_x2 = layer->startX/(float)bmp->sizeX;
texcoord_x1 = (layer->startX+layer->sizeX)/(float)bmp->sizeX;
} else {
texcoord_x1 = layer->startX/(float)bmp->sizeX;
texcoord_x2 = (layer->startX+layer->sizeX)/(float)bmp->sizeX;
}
if(layer->flip & 0x2) {
texcoord_y2 = layer->startY/(float)bmp->sizeY;
texcoord_y1 = (layer->startY+layer->sizeY)/(float)bmp->sizeY;
} else {
texcoord_y1 = layer->startY/(float)bmp->sizeY;
texcoord_y2 = (layer->startY+layer->sizeY)/(float)bmp->sizeY;
}
} else {
pos[0][0] = pos[3][0] = -(bg_bmp->sizeX*16)/2;
pos[0][1] = pos[1][1] = -(bg_bmp->sizeY*16)/2;
pos[2][0] = pos[1][0] = pos[0][0]+(bg_bmp->sizeX*16);
pos[2][1] = pos[3][1] = pos[0][1]+(bg_bmp->sizeY*16);
texcoord_x1 = texcoord_y1 = 1.0/(bg_bmp->sizeX*16);
texcoord_x2 = texcoord_y2 = 1.0f;
}
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition3f32(pos[0][0], pos[0][1], 0);
GXTexCoord2f32(texcoord_x1*sprite->tex_scale_x, texcoord_y1*sprite->tex_scale_y);
GXPosition3f32(pos[1][0], pos[1][1], 0);
GXTexCoord2f32(texcoord_x2*sprite->tex_scale_x, texcoord_y1*sprite->tex_scale_y);
GXPosition3f32(pos[2][0], pos[2][1], 0);
GXTexCoord2f32(texcoord_x2*sprite->tex_scale_x, texcoord_y2*sprite->tex_scale_y);
GXPosition3f32(pos[3][0], pos[3][1], 0);
GXTexCoord2f32(texcoord_x1*sprite->tex_scale_x, texcoord_y2*sprite->tex_scale_y);
GXEnd();
}
if(sprite->bg) {
GXSetNumIndStages(0);
GXSetTevDirect(GX_TEVSTAGE0);
GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_FALSE, 0, 0);
}
}
}
void HuSprTexLoad(AnimData *anim, short bmp, short slot, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, GXTexFilter filter)
{
GXTexObj tex_obj;
GXTlutObj tlut_obj;
AnimBmpData *bmp_ptr = &anim->bmp[bmp];
short sizeX = bmp_ptr->sizeX;
short sizeY = bmp_ptr->sizeY;
switch(bmp_ptr->dataFmt & 0xF) {
case 0:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_RGBA8, wrap_s, wrap_t, GX_FALSE);
break;
case 1:
case 2:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_RGB5A3, wrap_s, wrap_t, GX_FALSE);
break;
case 3:
GXInitTlutObj(&tlut_obj, bmp_ptr->palData, GX_TL_RGB5A3, bmp_ptr->palNum);
GXLoadTlut(&tlut_obj, slot);
GXInitTexObjCI(&tex_obj,bmp_ptr->data, sizeX, sizeY, GX_TF_C8, wrap_s, wrap_t, GX_FALSE, slot);
break;
case 4:
GXInitTlutObj(&tlut_obj, bmp_ptr->palData, GX_TL_RGB5A3, bmp_ptr->palNum);
GXLoadTlut(&tlut_obj, slot);
GXInitTexObjCI(&tex_obj,bmp_ptr->data, sizeX, sizeY, GX_TF_C4, wrap_s, wrap_t, GX_FALSE, slot);
break;
case 5:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_IA8, wrap_s, wrap_t, GX_FALSE);
break;
case 6:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_IA4, wrap_s, wrap_t, GX_FALSE);
break;
case 7:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_I8, wrap_s, wrap_t, GX_FALSE);
break;
case 8:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_I4, wrap_s, wrap_t, GX_FALSE);
break;
case 9:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_CTF_A8, wrap_s, wrap_t, GX_FALSE);
break;
case 10:
GXInitTexObj(&tex_obj, bmp_ptr->data, sizeX, sizeY, GX_TF_CMPR, wrap_s, wrap_t, GX_FALSE);
break;
default:
break;
}
GXInitTexObjLOD(&tex_obj, filter, filter, 0, 0, 0, GX_FALSE, GX_FALSE, GX_ANISO_1);
GXLoadTexObj(&tex_obj, slot);
}
void HuSprExecLayerSet(short draw_no, short layer)
{
HuSprLayerDrawNo[layer] = draw_no;
Hu3DLayerHookSet(layer, HuSprLayerHook);
}
static void HuSprLayerHook(short layer)
{
HuSprDispInit();
HuSprExec(HuSprLayerDrawNo[layer]);
}