mirror of
https://github.com/pmret/papermario.git
synced 2024-09-19 16:01:48 +02:00
4145cccd86
* prep * player anims * consistency * extra space * slight adjustment * suggest_player_anim func names --------- Co-authored-by: HailSanta <Hail2Santa@gmail.com>
1341 lines
44 KiB
C
1341 lines
44 KiB
C
#include "sprite.h"
|
|
|
|
extern HeapNode heap_generalHead;
|
|
extern HeapNode heap_spriteHead;
|
|
|
|
BSS s32 D_802DF520; // unused?
|
|
BSS s32 spr_allocateBtlComponentsOnWorldHeap;
|
|
BSS s32 D_802DF528[2]; // unused?
|
|
BSS s32 MaxLoadedSpriteInstanceID;
|
|
BSS s32 D_802DF534[3]; // unused?
|
|
BSS s32 D_802DF540;
|
|
BSS s32 D_802DF544; // unused?
|
|
BSS SpriteAnimData* spr_playerSprites[13];
|
|
BSS s32 D_802DF57C;
|
|
BSS s32 spr_playerMaxComponents;
|
|
BSS s32 D_802DF584; // unused?
|
|
BSS PlayerCurrentAnimInfo spr_playerCurrentAnimInfo[3];
|
|
BSS s32 D_802DF5AC; // unused?
|
|
BSS SpriteAnimData* NpcSpriteData[234];
|
|
BSS u8 NpcSpriteInstanceCount[234];
|
|
BSS s32 D_802DFA44; // unused?
|
|
BSS SpriteInstance SpriteInstances[51];
|
|
BSS Quad* D_802DFE44;
|
|
BSS s32 D_802DFE48[22];
|
|
BSS s32 D_802DFEA0[3];
|
|
BSS s32 SpriteUpdateNotifyValue;
|
|
|
|
SpriteComponent** spr_allocate_components(s32);
|
|
void spr_load_npc_extra_anims(SpriteAnimData*, u32*);
|
|
void spr_init_player_raster_cache(s32 cacheSize, s32 maxRasterSize);
|
|
|
|
Quad spr_defaultQuad = {
|
|
{
|
|
{{{ -16, 56, 0 }, FALSE, { 0, 0 }, { 240, 240, 240, 255 }}},
|
|
{{{ 16, 56, 0 }, FALSE, { 1024, 0 }, { 120, 120, 120, 255 }}},
|
|
{{{ 16, 0, 0 }, FALSE, { 1024, 1792 }, { 0, 0, 0, 255 }}},
|
|
{{{ -16, 0, 0 }, FALSE, { 0, 1792 }, { 120, 120, 120, 255 }}},
|
|
}
|
|
};
|
|
|
|
Vp D_802DF3D0 = {{
|
|
{ 640, 480, 511, 0 },
|
|
{ 640, 480, 511, 0 },
|
|
}
|
|
};
|
|
|
|
Vp D_802DF3E0 = {{
|
|
{ 640, 480, 511, 0 },
|
|
{ 640, 480, 512, 0 },
|
|
}
|
|
};
|
|
|
|
Gfx D_802DF3F0[] = {
|
|
gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
|
|
gsDPSetCombineMode(G_CC_DECALRGBA, G_CC_DECALRGBA),
|
|
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
|
|
gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH),
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM), AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)),
|
|
gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_RGBA16 | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
Gfx D_802DF428[] = {
|
|
gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
|
|
gsDPSetCombineLERP(0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0),
|
|
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
|
|
gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH),
|
|
gsDPSetRenderMode(G_RM_ZB_CLD_SURF, G_RM_ZB_CLD_SURF2),
|
|
gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_RGBA16 | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
Gfx D_802DF460[] = {
|
|
gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
|
|
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
|
|
gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH),
|
|
gsDPSetRenderMode(AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | G_RM_PASS, AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)),
|
|
gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_RGBA16 | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_2CYCLE | G_PM_NPRIMITIVE),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
Gfx D_802DF490[] = {
|
|
gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
|
|
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
|
|
gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH),
|
|
gsDPSetRenderMode(G_RM_PASS, G_RM_ZB_CLD_SURF2),
|
|
gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_RGBA16 | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_2CYCLE | G_PM_NPRIMITIVE),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
f32 spr_animUpdateTimeScale = 1.0f;
|
|
|
|
#define MARIO_SPRITE_COMMON_BITS \
|
|
1 << SPR_Mario1 \
|
|
| 1 << SPR_Mario1_Back \
|
|
|
|
#define MARIO_SPRITE_WORLD_BITS \
|
|
MARIO_SPRITE_COMMON_BITS \
|
|
| 1 << SPR_MarioW1 \
|
|
| 1 << SPR_MarioW1_Back \
|
|
| 1 << SPR_MarioW2 \
|
|
| 1 << SPR_MarioW3
|
|
|
|
#define MARIO_SPRITE_BATTLE_BITS \
|
|
MARIO_SPRITE_COMMON_BITS \
|
|
| 1 << SPR_MarioB1 \
|
|
| 1 << SPR_MarioB2 \
|
|
| 1 << SPR_MarioB3
|
|
|
|
#define PEACH_SPRITE_BITS \
|
|
1 << SPR_Peach1 \
|
|
| 1 << SPR_Peach1_Back \
|
|
| 1 << SPR_Peach2 \
|
|
| 1 << SPR_Peach3 \
|
|
|
|
// TODO(player raster splat header generation):
|
|
// - macroify rasterSize based on the biggest raster
|
|
PlayerSpriteSet spr_playerSpriteSets[] = {
|
|
[PLAYER_SPRITES_MARIO_WORLD] { 6, 0x700, MARIO_SPRITE_WORLD_BITS },
|
|
[PLAYER_SPRITES_MARIO_REFLECT_FLOOR] { 18, 0x700, MARIO_SPRITE_WORLD_BITS },
|
|
[PLAYER_SPRITES_COMBINED_EPILOGUE] { 10, 0x900, MARIO_SPRITE_WORLD_BITS | PEACH_SPRITE_BITS },
|
|
[PLAYER_SPRITES_MARIO_PARADE] { 3, 0x700, MARIO_SPRITE_COMMON_BITS },
|
|
[PLAYER_SPRITES_PEACH_WORLD] { 6, 0x900, PEACH_SPRITE_BITS },
|
|
[PLAYER_SPRITES_MARIO_BATTLE] { 6, 0x700, MARIO_SPRITE_BATTLE_BITS },
|
|
[PLAYER_SPRITES_PEACH_BATTLE] { 6, 0x900, PEACH_SPRITE_BITS},
|
|
};
|
|
|
|
void spr_init_quad_cache(void) {
|
|
s32 i;
|
|
|
|
D_802DFE44 = _heap_malloc(&heap_spriteHead, ARRAY_COUNT(D_802DFE48) * sizeof(*D_802DFE44));
|
|
|
|
for (i = 0; i < ARRAY_COUNT(D_802DFE48); i++) {
|
|
D_802DFE48[i] = -1;
|
|
}
|
|
}
|
|
|
|
Quad* spr_get_cached_quad(s32 quadIndex) {
|
|
s32* temp_v1 = &D_802DFE48[quadIndex];
|
|
|
|
*temp_v1 |= 0x1F;
|
|
return &D_802DFE44[quadIndex];
|
|
}
|
|
|
|
void spr_make_quad_for_size(Quad* quad, s32 width, s32 height) {
|
|
Vtx* vtx = &quad->v[0];
|
|
s32 w = width; // required to match
|
|
|
|
*quad = spr_defaultQuad;
|
|
|
|
vtx->v.ob[0] = -w / 2;
|
|
vtx->v.ob[1] = height;
|
|
vtx->v.tc[0] = 0x2000;
|
|
vtx->v.tc[1] = 0x2000;
|
|
|
|
vtx++;
|
|
vtx->v.ob[0] = w / 2;
|
|
vtx->v.ob[1] = height;
|
|
vtx->v.tc[0] = (w + 256) * 32;
|
|
vtx->v.tc[1] = 0x2000;
|
|
|
|
vtx++;
|
|
vtx->v.tc[0] = (w + 256) * 32;
|
|
vtx->v.ob[0] = w / 2;
|
|
vtx->v.tc[1] = (height + 256) * 32;
|
|
|
|
vtx++;
|
|
vtx->v.ob[0] = -w / 2;
|
|
vtx->v.tc[0] = 0x2000;
|
|
vtx->v.tc[1] = (height + 256) * 32;
|
|
}
|
|
|
|
Quad* spr_get_quad_for_size(s32* quadIndex, s32 width, s32 height) {
|
|
Quad* quad;
|
|
s32 qi;
|
|
s32 dimensions;
|
|
s32 i;
|
|
|
|
if ((width * height) / 2 <= 0x800) {
|
|
dimensions = (width << 0x18) + (height << 0x10);
|
|
qi = *quadIndex;
|
|
if (qi != -1 && (dimensions == (D_802DFE48[qi] & 0xFFFF0000))) {
|
|
return spr_get_cached_quad(qi);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(D_802DFE48); i++) {
|
|
if (dimensions == (D_802DFE48[i] & 0xFFFF0000)) {
|
|
*quadIndex = i;
|
|
return spr_get_cached_quad(i);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(D_802DFE48); i++) {
|
|
if (D_802DFE48[i] == -1) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i != ARRAY_COUNT(D_802DFE48)) {
|
|
*quadIndex = i;
|
|
D_802DFE48[i] = dimensions;
|
|
quad = spr_get_cached_quad(i);
|
|
spr_make_quad_for_size(quad, width, height);
|
|
return quad;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void spr_clear_quad_cache(void) {
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(D_802DFE48); i++) {
|
|
if (D_802DFE48[i] != -1) {
|
|
D_802DFE48[i]--;
|
|
if (!(D_802DFE48[i] & 0xFFFF)) {
|
|
D_802DFE48[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void spr_appendGfx_component_flat(
|
|
Quad* vertices,
|
|
IMG_PTR raster, PAL_PTR palette,
|
|
s32 width, s32 height,
|
|
f32 arg5,
|
|
Matrix4f mtx,
|
|
s32 alpha
|
|
) {
|
|
gDPLoadTLUT_pal16(gMasterGfxPos++, 0, palette);
|
|
if (gSpriteShadingProfile->flags & 1) {
|
|
gDPScrollMultiTile2_4b(gMasterGfxPos++, raster, G_IM_FMT_CI, width, height,
|
|
0, 0, width - 1, height - 1, 0,
|
|
G_TX_CLAMP, G_TX_CLAMP, 8, 8, G_TX_NOLOD, G_TX_NOLOD,
|
|
256, 256);
|
|
gDPSetTile(gMasterGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0x0100, 2, 0, G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
|
gDPSetTileSize(gMasterGfxPos++, 2, 0, 0, 63 << 2, 0);
|
|
if (gSpriteShadingProfile->flags & 2) {
|
|
Camera* camera = &gCameras[gCurrentCamID];
|
|
if (gGameStatusPtr->isBattle == 2) {
|
|
gSPViewport(gMasterGfxPos++, &D_802DF3E0);
|
|
} else {
|
|
gSPViewport(gMasterGfxPos++, &camera->vpAlt);
|
|
}
|
|
|
|
if (alpha == 255) {
|
|
gDPSetRenderMode(gMasterGfxPos++, AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA |
|
|
G_RM_PASS, AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA |
|
|
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM));
|
|
} else {
|
|
gDPSetRenderMode(gMasterGfxPos++, G_RM_PASS, G_RM_ZB_CLD_SURF2);
|
|
}
|
|
|
|
gDPSetEnvColor(gMasterGfxPos++, 0, 0, 0, alpha);
|
|
gDPSetCombineLERP(gMasterGfxPos++, 0, 0, 0, 0, ENVIRONMENT, 0, TEXEL1, 0, 0, 0, 0, 0, 0, 0, 0, COMBINED);
|
|
gSPVertex(gMasterGfxPos++, vertices, 4, 0);
|
|
gSP2Triangles(gMasterGfxPos++, 0, 2, 1, 0, 0, 3, 2, 0);
|
|
gDPPipeSync(gMasterGfxPos++);
|
|
}
|
|
create_shading_palette(mtx, 0, 0, width, height, alpha, alpha == 255 ? 0x111238 : 0x104B50); // TODO make macro for render mode
|
|
} else {
|
|
gDPScrollTextureBlock_4b(gMasterGfxPos++, raster, G_IM_FMT_CI, width, height, 0,
|
|
G_TX_CLAMP, G_TX_CLAMP, 8, 8, G_TX_NOLOD, G_TX_NOLOD,
|
|
256, 256);
|
|
if (gSpriteShadingProfile->flags & 2) {
|
|
Camera* camera = &gCameras[gCurrentCamID];
|
|
if (gGameStatusPtr->isBattle == 2) {
|
|
gSPViewport(gMasterGfxPos++, &D_802DF3E0);
|
|
} else {
|
|
gSPViewport(gMasterGfxPos++, &camera->vpAlt);
|
|
}
|
|
if (alpha == 255) {
|
|
gDPSetRenderMode(gMasterGfxPos++, AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM), AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM));
|
|
} else {
|
|
gDPSetRenderMode(gMasterGfxPos++, G_RM_ZB_CLD_SURF, G_RM_ZB_CLD_SURF2);
|
|
}
|
|
|
|
gDPSetEnvColor(gMasterGfxPos++, 0, 0, 0, alpha);
|
|
gDPSetCombineLERP(gMasterGfxPos++, 0, 0, 0, 0, ENVIRONMENT, 0, TEXEL0, 0, 0, 0, 0, 0, ENVIRONMENT, 0,
|
|
TEXEL0, 0);
|
|
gSPVertex(gMasterGfxPos++, vertices, 4, 0);
|
|
gSP2Triangles(gMasterGfxPos++, 0, 2, 1, 0, 0, 3, 2, 0);
|
|
gDPPipeSync(gMasterGfxPos++);
|
|
|
|
if (alpha == 255) {
|
|
gDPSetRenderMode(gMasterGfxPos++, AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA |
|
|
GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM),
|
|
AA_EN | Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | CVG_X_ALPHA |
|
|
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM));
|
|
} else {
|
|
gDPSetRenderMode(gMasterGfxPos++, G_RM_ZB_CLD_SURF, G_RM_ZB_CLD_SURF2);
|
|
}
|
|
|
|
gDPSetEnvColor(gMasterGfxPos++, 100, 100, 100, 255);
|
|
gDPSetPrimColor(gMasterGfxPos++, 0, 0, 0, 0, 0, alpha);
|
|
gDPSetCombineLERP(gMasterGfxPos++, SHADE, ENVIRONMENT, TEXEL0, TEXEL0, PRIMITIVE, 0, TEXEL0, 0, SHADE,
|
|
ENVIRONMENT, TEXEL0, TEXEL0, PRIMITIVE, 0, TEXEL0, 0);
|
|
gDPSetColorDither(gMasterGfxPos++, G_CD_MAGICSQ);
|
|
}
|
|
}
|
|
|
|
if (gSpriteShadingProfile->flags & 2) {
|
|
Camera* camera = &gCameras[gCurrentCamID];
|
|
|
|
if (gGameStatusPtr->isBattle == 2) {
|
|
gSPViewport(gMasterGfxPos++, &D_802DF3D0);
|
|
D_802DF3E0.vp.vtrans[0] = D_802DF3D0.vp.vtrans[0] + gGameStatusPtr->unk_82;
|
|
D_802DF3E0.vp.vtrans[1] = D_802DF3D0.vp.vtrans[1] + gGameStatusPtr->unk_83;
|
|
} else {
|
|
gSPViewport(gMasterGfxPos++, &camera->vp);
|
|
}
|
|
}
|
|
|
|
gSPVertex(gMasterGfxPos++, vertices, 4, 0);
|
|
gSP2Triangles(gMasterGfxPos++, 0, 2, 1, 0, 0, 3, 2, 0);
|
|
gDPPipeSync(gMasterGfxPos++);
|
|
}
|
|
|
|
void spr_appendGfx_component(
|
|
SpriteRasterCacheEntry* cache,
|
|
f32 dx, f32 dy, f32 dz,
|
|
f32 rotX, f32 rotY, f32 rotZ,
|
|
f32 scaleX, f32 scaleY, f32 scaleZ,
|
|
s32 opacity, PAL_PTR palette, Matrix4f mtx)
|
|
{
|
|
Matrix4f mtxTransform;
|
|
Matrix4f mtxTemp;
|
|
FoldImageRecPart foldImg;
|
|
s32 quadIndex;
|
|
Quad* quad;
|
|
s32 width;
|
|
s32 height;
|
|
|
|
guTranslateF(mtxTemp, dx, dy, dz);
|
|
guMtxCatF(mtxTemp, mtx, mtxTransform);
|
|
|
|
if (rotY != 0.0f) {
|
|
guRotateF(mtxTemp, rotY, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
}
|
|
if (rotZ != 0.0f) {
|
|
guRotateF(mtxTemp, rotZ, 0.0f, 0.0f, 1.0f);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
}
|
|
if (rotX != 0.0f) {
|
|
guRotateF(mtxTemp, rotX, 1.0f, 0.0f, 0.0f);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
}
|
|
|
|
if (scaleX != 1.0f || scaleY != 1.0f || scaleZ != 1.0f) {
|
|
guScaleF(mtxTemp, scaleX, scaleY, scaleZ);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
}
|
|
|
|
guMtxF2L(mtxTransform, &gDisplayContext->matrixStack[gMatrixListPos]);
|
|
gSPMatrix(gMasterGfxPos++, VIRTUAL_TO_PHYSICAL(&gDisplayContext->matrixStack[gMatrixListPos++]),
|
|
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
|
|
if (gSpriteShadingProfile->flags & 1) {
|
|
if ((u8) opacity == 255) {
|
|
gSPDisplayList(gMasterGfxPos++, D_802DF460);
|
|
} else {
|
|
gSPDisplayList(gMasterGfxPos++, D_802DF490);
|
|
}
|
|
} else {
|
|
if ((u8) opacity == 255) {
|
|
gSPDisplayList(gMasterGfxPos++, D_802DF3F0);
|
|
} else {
|
|
gDPSetPrimColor(gMasterGfxPos++, 0, 0, 0, 0, 0, (u8) opacity);
|
|
gSPDisplayList(gMasterGfxPos++, D_802DF428);
|
|
}
|
|
}
|
|
|
|
width = cache->width;
|
|
height = cache->height;
|
|
quadIndex = cache->quadCacheIndex;
|
|
quad = NULL;
|
|
if (!(D_802DF540 & (0x80000000 | 0x40000000 | 0x20000000 | 0x10000000))) {
|
|
quad = spr_get_quad_for_size(&quadIndex, width, height);
|
|
cache->quadCacheIndex = quadIndex;
|
|
}
|
|
|
|
if (quad != NULL) {
|
|
spr_appendGfx_component_flat(quad, cache->image, palette, width, height, rotY, mtxTransform, (u8) opacity);
|
|
} else {
|
|
foldImg.raster = cache->image;
|
|
foldImg.palette = palette;
|
|
foldImg.width = width;
|
|
foldImg.height = height;
|
|
foldImg.xOffset = -(width / 2);
|
|
foldImg.yOffset = height;
|
|
foldImg.opacity = opacity;
|
|
if (fold_appendGfx_component((u8) (u16) D_802DF540, &foldImg, 0x80000, mtxTransform) == 1) { // todo bitfield?
|
|
D_802DF540 &= ~(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000);
|
|
}
|
|
}
|
|
gSPPopMatrix(gMasterGfxPos++, G_MTX_MODELVIEW);
|
|
}
|
|
|
|
void spr_transform_point(s32 rotX, s32 rotY, s32 rotZ, f32 inX, f32 inY, f32 inZ, f32* outX, f32* outY, f32* outZ) {
|
|
if (rotX == 0 && rotY == 0 && rotZ == 0) {
|
|
*outX = inX;
|
|
*outY = inY;
|
|
*outZ = inZ;
|
|
} else {
|
|
Matrix4f mtxTransform, mtxTemp;
|
|
f32 xx, yx, zx, xy, yy, zy, xz, yz, zz;
|
|
|
|
guRotateF(mtxTransform, rotY, 0.0f, 1.0f, 0.0f);
|
|
guRotateF(mtxTemp, rotZ, 0.0f, 0.0f, 1.0f);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
guRotateF(mtxTemp, rotX, 1.0f, 0.0f, 0.0f);
|
|
guMtxCatF(mtxTemp, mtxTransform, mtxTransform);
|
|
|
|
xx = (mtxTransform[0][0] * inX);
|
|
yx = (mtxTransform[1][0] * inY);
|
|
zx = (mtxTransform[2][0] * inZ);
|
|
xy = (mtxTransform[0][1] * inX);
|
|
yy = (mtxTransform[1][1] * inY);
|
|
zy = (mtxTransform[2][1] * inZ);
|
|
xz = (mtxTransform[0][2] * inX);
|
|
yz = (mtxTransform[1][2] * inY);
|
|
zz = (mtxTransform[2][2] * inZ);
|
|
|
|
*outX = xx + yx + zx;
|
|
*outY = xy + yy + zy;
|
|
*outZ = xz + yz + zz;
|
|
}
|
|
}
|
|
|
|
void spr_draw_component(s32 drawOpts, SpriteComponent* component, SpriteAnimComponent* anim,
|
|
SpriteRasterCacheEntry** cache, PAL_PTR* palettes, f32 zscale, Matrix4f mtx) {
|
|
SpriteRasterCacheEntry* cacheEntry;
|
|
s32 paletteIdx;
|
|
PAL_PTR pal;
|
|
f32 dx, dy, dz;
|
|
f32 rotX, rotY, rotZ;
|
|
f32 inX, inY, inZ;
|
|
|
|
if (component->initialized && component->currentRaster != -1) {
|
|
rotX = D_802DFEA0[0];
|
|
rotY = D_802DFEA0[1];
|
|
rotZ = D_802DFEA0[2];
|
|
inX = component->compPos.x + anim->compOffset.x;
|
|
inY = component->compPos.y + anim->compOffset.y;
|
|
inZ = component->compPos.z + anim->compOffset.z;
|
|
|
|
spr_transform_point(rotX, rotY, rotZ, inX, inY, inZ * zscale, &dx, &dy, &dz);
|
|
cacheEntry = cache[component->currentRaster];
|
|
paletteIdx = component->currentPalette;
|
|
if (drawOpts & DRAW_SPRITE_USE_PLAYER_RASTERS) {
|
|
cacheEntry->image = spr_get_player_raster(component->currentRaster & 0xFFF, D_802DF57C);
|
|
}
|
|
D_802DF540 = component->unk_4C;
|
|
pal = palettes[paletteIdx];
|
|
|
|
spr_appendGfx_component(
|
|
cacheEntry,
|
|
dx, dy, dz,
|
|
rotX + component->rotation.x,
|
|
rotY + component->rotation.y,
|
|
rotZ + component->rotation.z,
|
|
component->scale.x,
|
|
component->scale.y,
|
|
component->scale.z,
|
|
drawOpts, pal, mtx
|
|
);
|
|
component->unk_4C = D_802DF540;
|
|
}
|
|
}
|
|
|
|
s32 spr_unpack_signed_12bit(u16 val) {
|
|
s32 temp = val & 0xFFF;
|
|
|
|
if (temp & 0x800) {
|
|
return temp | ~0xFFF;
|
|
} else {
|
|
return temp;
|
|
}
|
|
}
|
|
|
|
s32 spr_unpack_signed_16bit(u16 val) {
|
|
s32 temp = val & 0xFFFF;
|
|
|
|
if (temp & 0x8000) {
|
|
return temp | ~0xFFFF;
|
|
} else {
|
|
return temp;
|
|
}
|
|
}
|
|
|
|
void spr_component_update_commands(SpriteComponent* comp, SpriteAnimComponent* anim) {
|
|
f32 posX, posY, posZ;
|
|
f32 rotX, rotY, rotZ;
|
|
f32 scaleX, scaleY, scaleZ;
|
|
s32 changedFlags;
|
|
|
|
u16* bufPos;
|
|
u16* gotoPos;
|
|
s32 cmdValue;
|
|
|
|
if (comp->initialized) {
|
|
scaleZ = 1.0f;
|
|
scaleY = 1.0f;
|
|
scaleX = 1.0f;
|
|
changedFlags = 0;
|
|
|
|
bufPos = comp->readPos;
|
|
gotoPos = (u16*) -1;
|
|
|
|
comp->waitTime -= spr_animUpdateTimeScale;
|
|
|
|
while (comp->waitTime <= 0.0f) {
|
|
// overflow check
|
|
if (bufPos >= &anim->cmdList[anim->cmdListSize / 2]) {
|
|
bufPos = anim->cmdList;
|
|
break;
|
|
}
|
|
|
|
switch (*bufPos & 0xF000) {
|
|
// 0VVV
|
|
// Wait
|
|
case 0x0000:
|
|
comp->waitTime = *bufPos++ & 0xFFF;
|
|
if (comp->waitTime == 0.0f) {
|
|
comp->waitTime = 4095.0f;
|
|
}
|
|
comp->posOffset.z = 0.0f;
|
|
comp->posOffset.y = 0.0f;
|
|
comp->posOffset.x = 0.0f;
|
|
comp->rotation.z = 0;
|
|
comp->rotation.y = 0;
|
|
comp->rotation.x = 0;
|
|
comp->scale.z = 1.0f;
|
|
comp->scale.y = 1.0f;
|
|
comp->scale.x = 1.0f;
|
|
break;
|
|
// 2VVV
|
|
// Goto -- jump to another position in the list
|
|
case 0x2000:
|
|
bufPos = &anim->cmdList[spr_unpack_signed_12bit(*bufPos)];
|
|
if (bufPos == gotoPos) {
|
|
bufPos = anim->cmdList;
|
|
comp->waitTime = 1.0f;
|
|
}
|
|
gotoPos = bufPos;
|
|
break;
|
|
// 1VVV
|
|
// SetImage -- FFF is valid value for "no image"
|
|
case 0x1000:
|
|
cmdValue = *bufPos++ & 0xFFF;
|
|
if (cmdValue != 0xFFF) {
|
|
comp->currentRaster = cmdValue;
|
|
} else {
|
|
comp->currentRaster = -1;
|
|
}
|
|
comp->currentPalette = -1;
|
|
break;
|
|
// 6VVV
|
|
// SetPalette -- FFF to clear
|
|
case 0x6000:
|
|
cmdValue = *bufPos++ & 0xFFF;
|
|
if (cmdValue != 0xFFF) {
|
|
comp->currentPalette = cmdValue;
|
|
} else {
|
|
comp->currentPalette = -1;
|
|
}
|
|
break;
|
|
// 8VUU
|
|
// SetProperty
|
|
// 81-XX parent to component XX
|
|
// 82-YY set notify value to YY
|
|
case 0x8000:
|
|
cmdValue = *bufPos++;
|
|
switch (cmdValue & 0xF00) {
|
|
case 0x100: // set parent
|
|
comp->properties = (comp->properties & 0xFFFF0000) | cmdValue;
|
|
break;
|
|
case 0x200: // set notify value
|
|
SpriteUpdateNotifyValue = cmdValue & 0xFF;
|
|
comp->properties = (comp->properties & 0xFF00FFFF) | (SpriteUpdateNotifyValue << 0x10);
|
|
break;
|
|
}
|
|
break;
|
|
// 3VVV XXXX YYYY ZZZZ
|
|
// SetPosition -- what does the flag do?
|
|
case 0x3000:
|
|
switch (*bufPos++ & 0xF) {
|
|
case 0:
|
|
case 1:
|
|
posX = spr_unpack_signed_16bit(*bufPos++);
|
|
posY = spr_unpack_signed_16bit(*bufPos++);
|
|
posZ = spr_unpack_signed_16bit(*bufPos++);
|
|
changedFlags |= 1;
|
|
break;
|
|
}
|
|
break;
|
|
// 4XXX YYYY ZZZZ
|
|
// SetRotation (euler angles)
|
|
case 0x4000:
|
|
rotX = spr_unpack_signed_12bit(*bufPos++);
|
|
rotY = spr_unpack_signed_16bit(*bufPos++);
|
|
rotZ = spr_unpack_signed_16bit(*bufPos++);
|
|
changedFlags |= 2;
|
|
break;
|
|
// 5VVV UUUU
|
|
// SetScale (%)
|
|
case 0x5000:
|
|
switch (*bufPos++ & 0xF) {
|
|
case 0:
|
|
scaleZ = *bufPos++ / 100.0f;
|
|
scaleY = scaleZ;
|
|
scaleX = scaleZ;
|
|
break;
|
|
case 1:
|
|
scaleX = *bufPos++ / 100.0f;
|
|
break;
|
|
case 2:
|
|
scaleY = *bufPos++ / 100.0f;
|
|
break;
|
|
case 3:
|
|
scaleZ = *bufPos++ / 100.0f;
|
|
break;
|
|
}
|
|
changedFlags |= 4;
|
|
break;
|
|
// 7VVV UUUU
|
|
// Loop -- VV iterations jumping back to UUUU
|
|
case 0x7000:
|
|
if (comp->loopCounter != 0) {
|
|
comp->loopCounter--;
|
|
if (comp->loopCounter == 0) {
|
|
bufPos += 2;
|
|
break;
|
|
}
|
|
} else {
|
|
comp->loopCounter = bufPos[1];
|
|
}
|
|
bufPos = &anim->cmdList[spr_unpack_signed_12bit(*bufPos)];
|
|
break;
|
|
// invalid command
|
|
default:
|
|
bufPos = anim->cmdList;
|
|
comp->waitTime = 1.0f;
|
|
break;
|
|
}
|
|
} // end loop
|
|
|
|
comp->readPos = bufPos;
|
|
if (changedFlags & 1) {
|
|
comp->posOffset.x = posX;
|
|
comp->posOffset.y = posY;
|
|
comp->posOffset.z = posZ;
|
|
}
|
|
if (changedFlags & 2) {
|
|
comp->rotation.x = rotX;
|
|
comp->rotation.y = rotY;
|
|
comp->rotation.z = rotZ;
|
|
}
|
|
if (changedFlags & 4) {
|
|
comp->scale.x = scaleX;
|
|
comp->scale.y = scaleY;
|
|
comp->scale.z = scaleZ;
|
|
}
|
|
}
|
|
}
|
|
|
|
void spr_component_update_finish(SpriteComponent* comp, SpriteComponent** compList,
|
|
SpriteRasterCacheEntry** rasterCacheEntry, s32 overridePalette)
|
|
{
|
|
SpriteComponent* listComp;
|
|
SpriteRasterCacheEntry* cache;
|
|
|
|
if (comp->initialized) {
|
|
comp->compPos.x = comp->posOffset.x;
|
|
comp->compPos.y = comp->posOffset.y;
|
|
comp->compPos.z = comp->posOffset.z;
|
|
|
|
if ((comp->properties & 0xF00) == 0x100) {
|
|
listComp = compList[comp->properties & 0xFF];
|
|
comp->compPos.x += listComp->compPos.x;
|
|
comp->compPos.y += listComp->compPos.y;
|
|
comp->compPos.z += listComp->compPos.z;
|
|
}
|
|
|
|
if (comp->currentRaster != -1) {
|
|
cache = rasterCacheEntry[comp->currentRaster];
|
|
if (comp->currentPalette == -1) {
|
|
comp->currentPalette = cache->palette;
|
|
if (overridePalette != 0 && comp->currentPalette == 0) {
|
|
comp->currentPalette = overridePalette;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 spr_component_update(s32 curNotifyValue, SpriteComponent** compList, SpriteAnimComponent** animList,
|
|
SpriteRasterCacheEntry** rasterCache, s32 overridePalette) {
|
|
SpriteComponent** compListIt;
|
|
|
|
SpriteUpdateNotifyValue = curNotifyValue;
|
|
|
|
compListIt = compList;
|
|
while (*compListIt != PTR_LIST_END) {
|
|
spr_component_update_commands(*compListIt++, *animList);
|
|
if (*animList != PTR_LIST_END) {
|
|
animList++;
|
|
}
|
|
}
|
|
|
|
compListIt = compList;
|
|
while (*compListIt != PTR_LIST_END) {
|
|
spr_component_update_finish(*compListIt++, compList, rasterCache, overridePalette);
|
|
}
|
|
|
|
return SpriteUpdateNotifyValue;
|
|
}
|
|
|
|
void spr_init_component_anim_state(SpriteComponent* comp, SpriteAnimComponent* anim) {
|
|
if (anim == PTR_LIST_END) {
|
|
comp->initialized = FALSE;
|
|
return;
|
|
}
|
|
|
|
comp->initialized = TRUE;
|
|
comp->properties = 0;
|
|
comp->readPos = anim->cmdList;
|
|
comp->waitTime = 0;
|
|
comp->loopCounter = 0;
|
|
comp->currentRaster = -1;
|
|
comp->currentPalette = -1;
|
|
comp->posOffset.x = 0.0f;
|
|
comp->posOffset.y = 0.0f;
|
|
comp->posOffset.z = 0.0f;
|
|
comp->compPos.x = 0.0f;
|
|
comp->compPos.y = 0.0f;
|
|
comp->compPos.z = 0.0f;
|
|
comp->rotation.x = 0.0f;
|
|
comp->rotation.y = 0.0f;
|
|
comp->rotation.z = 0.0f;
|
|
comp->scale.x = 1.0f;
|
|
comp->scale.y = 1.0f;
|
|
comp->scale.z = 1.0f;
|
|
}
|
|
|
|
void spr_init_anim_state(SpriteComponent** compList, SpriteAnimComponent** animList) {
|
|
while (*compList != PTR_LIST_END) {
|
|
SpriteComponent* component = *compList++;
|
|
spr_init_component_anim_state(component, *animList);
|
|
if (*animList != PTR_LIST_END) {
|
|
animList++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void spr_set_anim_timescale(f32 timescale) {
|
|
spr_animUpdateTimeScale = timescale * 2.0f;
|
|
}
|
|
|
|
void spr_load_player_sprite(s32 spriteIndex) {
|
|
SpriteAnimData* playerSprite = spr_load_sprite(spriteIndex - 1, TRUE, FALSE);
|
|
|
|
spr_playerSprites[spriteIndex - 1] = playerSprite;
|
|
if (spr_playerMaxComponents < playerSprite->maxComponents) {
|
|
spr_playerMaxComponents = playerSprite->maxComponents;
|
|
}
|
|
}
|
|
|
|
void spr_init_sprites(s32 playerSpriteSet) {
|
|
s32 loadedFlags;
|
|
s32 i;
|
|
|
|
spr_allocateBtlComponentsOnWorldHeap = FALSE;
|
|
_heap_create(&heap_spriteHead, 0x40000);
|
|
fold_init();
|
|
|
|
for (i = 0; i < ARRAY_COUNT(spr_playerSprites); i++) {
|
|
SpriteAnimData** playerSprites = spr_playerSprites;
|
|
playerSprites[i] = 0;
|
|
}
|
|
|
|
spr_playerMaxComponents = 0;
|
|
|
|
if (gGameStatusPtr->peachFlags & PEACH_STATUS_FLAG_IS_PEACH) {
|
|
playerSpriteSet = PLAYER_SPRITES_PEACH_WORLD;
|
|
}
|
|
|
|
loadedFlags = (&spr_playerSpriteSets[playerSpriteSet])->initiallyLoaded;
|
|
spr_init_player_raster_cache((&spr_playerSpriteSets[playerSpriteSet])->cacheSize,
|
|
(&spr_playerSpriteSets[playerSpriteSet])->rasterSize);
|
|
|
|
for (i = 1; i <= SPR_Peach3; i++) {
|
|
if ((loadedFlags >> i) & 1) {
|
|
spr_load_player_sprite(i);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(spr_playerCurrentAnimInfo); i++) {
|
|
spr_playerCurrentAnimInfo[i].componentList = NULL;
|
|
spr_playerCurrentAnimInfo[i].animID = -1;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(NpcSpriteData); i++) {
|
|
NpcSpriteData[i] = NULL;
|
|
NpcSpriteInstanceCount[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(SpriteInstances); i++) {
|
|
SpriteInstances[i].spriteIndex = 0;
|
|
SpriteInstances[i].componentList = NULL;
|
|
SpriteInstances[i].spriteData = NULL;
|
|
SpriteInstances[i].currentAnimID = -1;
|
|
SpriteInstances[i].notifyValue = 0;
|
|
}
|
|
|
|
spr_init_quad_cache();
|
|
}
|
|
|
|
void spr_render_init(void) {
|
|
spr_update_player_raster_cache();
|
|
spr_clear_quad_cache();
|
|
}
|
|
|
|
s32 func_802DDA84(void) {
|
|
return 0;
|
|
}
|
|
|
|
s32 spr_update_player_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale) {
|
|
u32* spriteData;
|
|
SpriteComponent** compList;
|
|
SpriteComponent* component;
|
|
SpriteAnimComponent** animList;
|
|
SpriteRasterCacheEntry** rasterList;
|
|
s32 spriteId = ((animID >> 16) & 0xFF) - 1;
|
|
s32 instanceIdx = spriteInstanceID & 0xFF;
|
|
s32 animIndex = animID & 0xFF;
|
|
D_802DF57C = spriteId;
|
|
|
|
if (spr_playerCurrentAnimInfo[instanceIdx].componentList == NULL) {
|
|
compList = spr_allocate_components(spr_playerMaxComponents);
|
|
spr_playerCurrentAnimInfo[instanceIdx].componentList = compList;
|
|
while (*compList != PTR_LIST_END) {
|
|
component = *compList;
|
|
component->unk_4C = func_8013A704(1);
|
|
compList++;
|
|
}
|
|
}
|
|
|
|
spriteData = (u32*)spr_playerSprites[spriteId];
|
|
compList = spr_playerCurrentAnimInfo[instanceIdx].componentList;
|
|
|
|
if (spriteData == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
rasterList = (SpriteRasterCacheEntry**)*spriteData;
|
|
spriteData += 4 + animIndex;
|
|
animList = (SpriteAnimComponent**)*spriteData;
|
|
|
|
spr_set_anim_timescale(timeScale);
|
|
if ((spriteInstanceID & DRAW_SPRITE_OVERRIDE_ALPHA) ||
|
|
(animID & ~SPRITE_ID_BACK_FACING) != (spr_playerCurrentAnimInfo[instanceIdx].animID & ~SPRITE_ID_BACK_FACING))
|
|
{
|
|
spr_init_anim_state(compList, animList);
|
|
spr_playerCurrentAnimInfo[instanceIdx].notifyValue = 0;
|
|
}
|
|
|
|
spr_playerCurrentAnimInfo[instanceIdx].animID = animID;
|
|
|
|
if (!(spriteInstanceID & DRAW_SPRITE_OVERRIDE_YAW)) {
|
|
spr_playerCurrentAnimInfo[instanceIdx].notifyValue = spr_component_update(spr_playerCurrentAnimInfo[instanceIdx].notifyValue,
|
|
compList, animList, rasterList, 0);
|
|
}
|
|
return spr_playerCurrentAnimInfo[instanceIdx].notifyValue;
|
|
}
|
|
|
|
s32 spr_draw_player_sprite(s32 spriteInstanceID, s32 yaw, s32 alphaIn, PAL_PTR* paletteList, Matrix4f mtx) {
|
|
s32 instanceIdx = spriteInstanceID & 0xFF;
|
|
s32 animID = spr_playerCurrentAnimInfo[instanceIdx].animID;
|
|
SpriteRasterCacheEntry** rasters;
|
|
PAL_PTR* palettes;
|
|
SpriteAnimComponent** animComponents;
|
|
SpriteComponent** components;
|
|
f32 zscale;
|
|
u32 alpha;
|
|
u32* spriteData;
|
|
s32 spriteId;
|
|
s32 spriteIdBackFacing;
|
|
|
|
if (animID == ANIM_LIST_END) {
|
|
return FALSE;
|
|
}
|
|
|
|
D_802DF57C = spriteId = ((animID >> 0x10) & 0xFF) - 1;
|
|
spriteData = (u32*)spr_playerSprites[spriteId];
|
|
if (spriteData == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
// TODO: fake match or not?
|
|
rasters = (SpriteRasterCacheEntry**)*spriteData++;
|
|
palettes = (PAL_PTR*)*spriteData++;
|
|
spriteData++;
|
|
spriteData++;
|
|
animComponents = (SpriteAnimComponent**)spriteData[animID & 0xFF];
|
|
|
|
if (animID & SPRITE_ID_BACK_FACING) {
|
|
switch (spriteId) {
|
|
case 0:
|
|
case 5:
|
|
case 9:
|
|
spriteIdBackFacing = spriteId + 1;
|
|
// TODO find better match
|
|
rasters = (SpriteRasterCacheEntry**)spr_playerSprites[spriteIdBackFacing];
|
|
D_802DF57C = spriteIdBackFacing;
|
|
rasters = (SpriteRasterCacheEntry**)*rasters;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!(spriteInstanceID & DRAW_SPRITE_OVERRIDE_YAW)) {
|
|
yaw += (s32)-gCameras[gCurrentCamID].currentYaw;
|
|
if (yaw > 360) {
|
|
yaw -= 360;
|
|
}
|
|
if (yaw < -360) {
|
|
yaw += 360;
|
|
}
|
|
}
|
|
|
|
if (yaw > 90 && yaw <= 270 || yaw >= -270 && yaw < -90) {
|
|
zscale = -1.5f;
|
|
} else {
|
|
zscale = 1.5f;
|
|
}
|
|
|
|
if (spriteInstanceID & DRAW_SPRITE_UPSIDE_DOWN) {
|
|
zscale = 0.0f - zscale;
|
|
}
|
|
|
|
D_802DFEA0[0] = 0;
|
|
D_802DFEA0[1] = yaw;
|
|
D_802DFEA0[2] = 0;
|
|
|
|
|
|
if (spriteInstanceID & DRAW_SPRITE_OVERRIDE_ALPHA) {
|
|
alpha = alphaIn & 0xFF;
|
|
if (alphaIn == 0) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
alpha = 255;
|
|
}
|
|
|
|
components = spr_playerCurrentAnimInfo[instanceIdx].componentList;
|
|
if (spriteInstanceID & DRAW_SPRITE_OVERRIDE_PALETTES) {
|
|
palettes = paletteList;
|
|
}
|
|
|
|
while (*components != PTR_LIST_END) {
|
|
spr_draw_component(alpha | DRAW_SPRITE_USE_PLAYER_RASTERS, *components++, *animComponents, rasters, palettes, zscale, mtx);
|
|
if (*animComponents != PTR_LIST_END) {
|
|
animComponents++;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
s32 func_802DDEC4(s32 arg0) {
|
|
return spr_playerCurrentAnimInfo[arg0].notifyValue;
|
|
}
|
|
|
|
void func_802DDEE4(s32 spriteIdx, s32 compIdx, FoldType foldType, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7) {
|
|
SpriteComponent* component;
|
|
SpriteComponent** componentListIt;
|
|
s32 i;
|
|
|
|
if (spr_playerCurrentAnimInfo[spriteIdx].componentList != NULL) {
|
|
componentListIt = spr_playerCurrentAnimInfo[spriteIdx].componentList;
|
|
i = 0;
|
|
|
|
while (*componentListIt != PTR_LIST_END) {
|
|
component = *componentListIt;
|
|
if (compIdx == -1 || i == compIdx) {
|
|
fold_update(component->unk_4C & 0xFF, foldType, arg3, arg4, arg5, arg6, arg7);
|
|
if (foldType != 0) {
|
|
component->unk_4C |= 0x10000000;
|
|
} else {
|
|
component->unk_4C &= ~0xF0000000;
|
|
}
|
|
}
|
|
componentListIt++;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_802DDFF8(s32 animID, FoldType foldType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6) {
|
|
func_802DDEE4(PLAYER_SPRITE_MAIN, -1, foldType, arg2, arg3, arg4, arg5, arg6);
|
|
}
|
|
|
|
void spr_get_player_raster_info(SpriteRasterInfo* out, s32 playerSpriteID, s32 rasterIndex) {
|
|
SpriteAnimData* sprite;
|
|
SpriteRasterCacheEntry* cache;
|
|
u16** paletteOffsetCopy;
|
|
|
|
playerSpriteID--;
|
|
sprite = spr_playerSprites[playerSpriteID];
|
|
if (sprite != NULL) {
|
|
paletteOffsetCopy = sprite->palettesOffset;
|
|
cache = sprite->rastersOffset[rasterIndex];
|
|
out->width = cache->width;
|
|
out->height = cache->height;
|
|
out->defaultPal = paletteOffsetCopy[cache->palette];
|
|
out->raster = spr_get_player_raster(rasterIndex, playerSpriteID);
|
|
}
|
|
}
|
|
|
|
PAL_PTR* spr_get_player_palettes(s32 spriteIndex) {
|
|
SpriteAnimData* sprites = spr_playerSprites[spriteIndex - 1];
|
|
|
|
if (sprites == NULL) {
|
|
return NULL;
|
|
} else {
|
|
return sprites->palettesOffset;
|
|
}
|
|
}
|
|
|
|
s32 spr_load_npc_sprite(s32 animID, u32* extraAnimList) {
|
|
SpriteAnimData* header;
|
|
SpriteComponent** compList;
|
|
s32 listIndex;
|
|
s32 i;
|
|
|
|
s32 spriteIndex = (animID >> 0x10) & 0x7FFF;
|
|
s32 useTailAlloc = (u32)animID >> 0x1F;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(SpriteInstances); i++) {
|
|
if (SpriteInstances[i].spriteIndex == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (MaxLoadedSpriteInstanceID < i) {
|
|
MaxLoadedSpriteInstanceID = i;
|
|
}
|
|
if (i == ARRAY_COUNT(SpriteInstances)) {
|
|
return -1;
|
|
}
|
|
listIndex = i;
|
|
if (NpcSpriteData[spriteIndex] != NULL) {
|
|
NpcSpriteInstanceCount[spriteIndex]++;
|
|
header = NpcSpriteData[spriteIndex];
|
|
SpriteInstances[listIndex].spriteData = header;
|
|
} else {
|
|
NpcSpriteInstanceCount[spriteIndex] = 1;
|
|
header = spr_load_sprite(spriteIndex - 1, FALSE, useTailAlloc);
|
|
SpriteInstances[listIndex].spriteData = header;
|
|
NpcSpriteData[spriteIndex] = header;
|
|
if (extraAnimList != NULL) {
|
|
spr_load_npc_extra_anims(header, extraAnimList);
|
|
}
|
|
}
|
|
compList = spr_allocate_components(header->maxComponents);
|
|
SpriteInstances[listIndex].componentList = compList;
|
|
while (*compList != PTR_LIST_END) {
|
|
SpriteComponent* comp = *compList;
|
|
comp->unk_4C = func_8013A704(1);
|
|
compList++;
|
|
}
|
|
SpriteInstances[listIndex].spriteIndex = spriteIndex;
|
|
SpriteInstances[listIndex].currentAnimID = -1;
|
|
return listIndex;
|
|
}
|
|
|
|
s32 spr_update_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale) {
|
|
u32* spriteData;
|
|
SpriteComponent** compList;
|
|
SpriteAnimComponent** animList;
|
|
SpriteRasterCacheEntry** rasterList;
|
|
|
|
s32 palID;
|
|
s32 i = spriteInstanceID & 0xFF;
|
|
s32 animIndex = animID & 0xFF;
|
|
|
|
compList = SpriteInstances[i].componentList;
|
|
spriteData = (u32*)SpriteInstances[i].spriteData;
|
|
|
|
rasterList = (SpriteRasterCacheEntry**)*spriteData;
|
|
spriteData += 4 + animIndex;
|
|
animList = (SpriteAnimComponent**)*spriteData;
|
|
|
|
palID = (animID >> 8) & 0xFF;
|
|
spr_set_anim_timescale(timeScale);
|
|
if ((spriteInstanceID & DRAW_SPRITE_OVERRIDE_ALPHA) || ((SpriteInstances[i].currentAnimID & 0xFF) != animIndex)) {
|
|
spr_init_anim_state(compList, animList);
|
|
SpriteInstances[i].currentAnimID = (palID << 8) | animIndex;
|
|
SpriteInstances[i].notifyValue = 0;
|
|
}
|
|
if (!(spriteInstanceID & DRAW_SPRITE_OVERRIDE_YAW)) {
|
|
SpriteInstances[i].notifyValue = spr_component_update(SpriteInstances[i].notifyValue,
|
|
compList, animList, rasterList, palID);
|
|
}
|
|
return SpriteInstances[i].notifyValue;
|
|
}
|
|
|
|
s32 spr_draw_npc_sprite(s32 spriteInstanceID, s32 yaw, s32 arg2, PAL_PTR* paletteList, Matrix4f mtx) {
|
|
s32 i = spriteInstanceID & 0xFF;
|
|
s32 animID = SpriteInstances[i].currentAnimID;
|
|
SpriteRasterCacheEntry** rasters;
|
|
PAL_PTR* palettes;
|
|
SpriteAnimComponent** animComponents;
|
|
SpriteComponent** components;
|
|
f32 zscale;
|
|
u32 alpha;
|
|
u32* spriteData;
|
|
|
|
if (animID == ANIM_LIST_END) {
|
|
return FALSE;
|
|
}
|
|
|
|
spriteData = (u32*)SpriteInstances[i].spriteData;
|
|
|
|
// TODO: fake match or not?
|
|
rasters = (SpriteRasterCacheEntry**)*spriteData++;
|
|
palettes = (PAL_PTR*)*spriteData++;
|
|
spriteData++;
|
|
spriteData++;
|
|
animComponents = (SpriteAnimComponent**)spriteData[animID & 0xFF];
|
|
|
|
D_802DFEA0[0] = 0;
|
|
D_802DFEA0[1] = yaw;
|
|
D_802DFEA0[2] = 0;
|
|
|
|
if (!(spriteInstanceID & DRAW_SPRITE_OVERRIDE_YAW)) {
|
|
yaw += gCameras[gCurrentCamID].currentYaw;
|
|
if (yaw > 360) {
|
|
yaw -= 360;
|
|
}
|
|
if (yaw < -360) {
|
|
yaw += 360;
|
|
}
|
|
}
|
|
|
|
if (yaw > 90 && yaw <= 270 || yaw >= -270 && yaw < -90) {
|
|
zscale = -1.5f;
|
|
} else {
|
|
zscale = 1.5f;
|
|
}
|
|
|
|
if (spriteInstanceID & DRAW_SPRITE_OVERRIDE_ALPHA) {
|
|
alpha = arg2 & 0xFF;
|
|
if (arg2 == 0) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
alpha = 255;
|
|
}
|
|
|
|
components = SpriteInstances[i].componentList;
|
|
if (spriteInstanceID & DRAW_SPRITE_OVERRIDE_PALETTES) {
|
|
palettes = paletteList;
|
|
}
|
|
|
|
while (*components != PTR_LIST_END) {
|
|
spr_draw_component(alpha, *components++, *animComponents, rasters, palettes, zscale, mtx);
|
|
if (*animComponents != PTR_LIST_END) {
|
|
animComponents++;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
s32 spr_get_notify_value(s32 spriteIndex) {
|
|
return SpriteInstances[spriteIndex].notifyValue;
|
|
}
|
|
|
|
s32 spr_free_sprite(s32 spriteInstanceID) {
|
|
SpriteInstance* sprite = &SpriteInstances[spriteInstanceID];
|
|
SpriteAnimData* spriteData;
|
|
SpriteComponent** compList;
|
|
s32 spriteIndex = sprite->spriteIndex;
|
|
|
|
if (spriteIndex == 0 || spriteIndex >= ARRAY_COUNT(NpcSpriteData)) {
|
|
return spriteInstanceID;
|
|
}
|
|
|
|
NpcSpriteInstanceCount[spriteIndex]--;
|
|
spriteData = sprite->spriteData;
|
|
|
|
compList = sprite->componentList;
|
|
while (*compList != PTR_LIST_END) {
|
|
SpriteComponent* comp = *compList;
|
|
func_8013A854(comp->unk_4C & 0xFF);
|
|
compList++;
|
|
}
|
|
|
|
compList = SpriteInstances[spriteInstanceID].componentList;
|
|
|
|
if (NpcSpriteInstanceCount[spriteIndex] == 0) {
|
|
NpcSpriteData[spriteIndex] = NULL;
|
|
_heap_free(&heap_spriteHead, spriteData);
|
|
}
|
|
|
|
if (spr_allocateBtlComponentsOnWorldHeap) {
|
|
_heap_free(&heap_generalHead, compList);
|
|
} else {
|
|
_heap_free(&heap_spriteHead, compList);
|
|
}
|
|
|
|
SpriteInstances[spriteInstanceID].spriteIndex = 0;
|
|
SpriteInstances[spriteInstanceID].componentList = NULL;
|
|
SpriteInstances[spriteInstanceID].spriteData = NULL;
|
|
SpriteInstances[spriteInstanceID].currentAnimID = -1;
|
|
return 0;
|
|
}
|
|
|
|
s32 func_802DE748(s32 spriteIdx, s32 compIdx) {
|
|
SpriteComponent** componentList = SpriteInstances[spriteIdx].componentList;
|
|
|
|
if (componentList == NULL) {
|
|
return -1;
|
|
} else {
|
|
return componentList[compIdx]->unk_4C & 0xFF;
|
|
}
|
|
}
|
|
|
|
void func_802DE780(s32 spriteIdx, s32 compIdx, FoldType foldType, s32 foldArg0, s32 foldArg1, s32 foldArg2, s32 foldArg3, s32 foldArg4) {
|
|
SpriteInstance* sprite = &SpriteInstances[spriteIdx];
|
|
SpriteComponent** componentList;
|
|
s32 i;
|
|
|
|
if (sprite->componentList != NULL) {
|
|
componentList = sprite->componentList;
|
|
i = 0;
|
|
|
|
while (*componentList != PTR_LIST_END) {
|
|
SpriteComponent* comp = *componentList;
|
|
|
|
if (compIdx == -1 || i == compIdx) {
|
|
fold_update((u8)comp->unk_4C, foldType, foldArg0, foldArg1, foldArg2, foldArg3, foldArg4);
|
|
if (foldType != FOLD_TYPE_NONE) {
|
|
comp->unk_4C |= 0x10000000;
|
|
} else {
|
|
comp->unk_4C &= ~0xF0000000;
|
|
}
|
|
}
|
|
componentList++;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_802DE894(s32 spriteIdx, FoldType foldType, s32 foldArg0, s32 foldArg1, s32 foldArg2, s32 foldArg3, s32 foldArg4) {
|
|
func_802DE780(spriteIdx, -1, foldType, foldArg0, foldArg1, foldArg2, foldArg3, foldArg4);
|
|
}
|
|
|
|
s32 func_802DE8DC(s32 spriteIdx, s32 compListIdx, s32* outX, s32* outY, s32* outZ) {
|
|
SpriteInstance* sprite = &SpriteInstances[spriteIdx];
|
|
SpriteAnimComponent** animCompList;
|
|
SpriteAnimComponent* anim;
|
|
SpriteComponent** compList;
|
|
SpriteComponent* comp;
|
|
u8 animID;
|
|
s32 i;
|
|
u32* spriteData;
|
|
|
|
if (sprite->componentList == NULL) {
|
|
return;
|
|
}
|
|
|
|
animID = sprite->currentAnimID;
|
|
if (animID != 255) {
|
|
// following 3 lines equivalent to:
|
|
// animCompList = sprite->spriteData->animListStart[animID];
|
|
spriteData = (u32*)sprite->spriteData;
|
|
spriteData += 4 + animID;
|
|
animCompList = (SpriteAnimComponent**)*spriteData;
|
|
compList = sprite->componentList;
|
|
i = 0;
|
|
while (*compList != PTR_LIST_END) {
|
|
if (i == compListIdx) {
|
|
anim = *animCompList;
|
|
comp = *compList;
|
|
*outX = comp->compPos.x + anim->compOffset.x;
|
|
*outY = comp->compPos.y + anim->compOffset.y;
|
|
*outZ = comp->compPos.z + anim->compOffset.z;
|
|
return 0;
|
|
}
|
|
i++;
|
|
compList++;
|
|
if (*animCompList != PTR_LIST_END) {
|
|
animCompList++;
|
|
}
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
s32 spr_get_npc_raster_info(SpriteRasterInfo* out, s32 npcSpriteID, s32 rasterIndex) {
|
|
SpriteAnimData* sprite = NpcSpriteData[npcSpriteID];
|
|
SpriteRasterCacheEntry* cache;
|
|
PAL_PTR* paletteOffsetCopy;
|
|
|
|
if (sprite != NULL) {
|
|
paletteOffsetCopy = sprite->palettesOffset;
|
|
cache = sprite->rastersOffset[rasterIndex];
|
|
out->raster = cache->image;
|
|
out->width = cache->width;
|
|
out->height = cache->height;
|
|
out->defaultPal = paletteOffsetCopy[cache->palette];
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
PAL_PTR* spr_get_npc_palettes(s32 npcSpriteID) {
|
|
SpriteAnimData* sprite = NpcSpriteData[npcSpriteID];
|
|
|
|
if (sprite != NULL) {
|
|
return sprite->palettesOffset;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
s32 spr_get_npc_color_variations(s32 npcSpriteID) {
|
|
SpriteAnimData* sprite = NpcSpriteData[npcSpriteID];
|
|
|
|
if (sprite != NULL) {
|
|
return sprite->colorVariations;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|