papermario/src/hud_element.c
AltoXorg 8d5b066b7d
SHIFT_BSS be gone (#1173)
* merge asm in src all versions

* main: refactor and eliminate SHIFT_BSS

* engine1 static BSS

* engine2

* folder move

* fix shift build

* cleanup msg & msg_draw

* wtf?

* un-static-ized

* .

* remove unnecess. rodata pad

* populate dangling common syms
2024-03-05 19:54:53 +09:00

2289 lines
88 KiB
C

#include "common.h"
#include "hud_element.h"
#include "nu/nusys.h"
#include "ld_addrs.h"
#define MAX_HUD_CACHE_ENTRIES 192
typedef struct HudElementSize {
s16 width;
s16 height;
s16 size;
} HudElementSize;
u8* gHudElementAuxCache = NULL;
s32 gHudElementCacheCapacity = 0x11000;
HudScript HES_Empty = {
hs_End
};
HudElementSize gHudElementSizes[] = {
{ 8, 8, 32 },
{ 16, 16, 128 },
{ 24, 24, 288 },
{ 32, 32, 512 },
{ 48, 48, 1152 },
{ 64, 64, 2048 },
{ 8, 16, 64 },
{ 16, 8, 64 },
{ 16, 24, 192 },
{ 16, 32, 256 },
{ 64, 32, 1024 },
{ 32, 16, 256 },
{ 12, 12, 72 },
{ 48, 24, 576 },
{ 32, 8, 128 },
{ 24, 8, 96 },
{ 64, 16, 512 },
{ 16, 64, 512 },
{ 192, 32, 3072 },
{ 40, 40, 800 },
{ 24, 16, 192 },
{ 32, 40, 640 },
{ 40, 16, 320 },
{ 40, 24, 480 },
{ 32, 24, 384 },
{ 20, 32, 0 }
};
s16 D_8014F068[] = { 34, 32, 0, 40, 40, 968, 0, 0 };
Gfx gHudElementsDLBackUI[] = {
gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
gsDPPipeSync(),
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_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE),
gsDPSetAlphaCompare(G_AC_NONE),
gsSPEndDisplayList()
};
Gfx gHudElementsDLFrontUI[] = {
gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
gsDPPipeSync(),
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_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE),
gsDPSetAlphaCompare(G_AC_NONE),
gsSPEndDisplayList()
};
Vtx D_8014F0C8[] = {
{
.v = {
.ob = { -12, 0, 0},
.flag = 0,
.tc = { 0x800, 0x800 },
.cn = { 0, 0, 0, 255}
}
},
{
.v = {
.ob = { 51, 0, 0},
.flag = 0,
.tc = { 0, 0x800 },
.cn = { 0, 0, 0, 255}
}
},
{
.v = {
.ob = { 51, 63, 0},
.flag = 0,
.tc = { 0, 0 },
.cn = { 0, 0, 0, 255}
}
},
{
.v = {
.ob = { -12, 63, 0},
.flag = 0,
.tc = { 0x800, 0 },
.cn = { 0, 0, 0, 255}
}
}
};
Lights1 HudElementLights = gdSPDefLights1(255, 255, 255, 0, 0, 0, 0, 0, 0);
s32 gHudElementsNumber;
HudCacheEntry* gHudElementCacheTableRaster;
HudCacheEntry* gHudElementCacheTablePalette;
s32* gHudElementCacheSize;
u8* gHudElementCacheBuffer;
BSS HudElementList gHudElementsWorld;
BSS HudElementList gHudElementsBattle;
BSS HudElementList* gHudElements;
BSS u8* gHudElementCacheBufferWorld;
BSS s32 gHudElementCacheSizeWorld;
BSS s32 D_8015796C;
BSS HudCacheEntry gHudElementCacheTableRasterWorld[192];
BSS HudCacheEntry gHudElementCacheTablePaletteWorld[192];
BSS u8* gHudElementCacheBufferBattle;
BSS s32 gHudElementCacheSizeBattle;
BSS s32 D_80158578[2];
BSS HudCacheEntry gHudElementCacheTableRasterBattle[192];
BSS HudCacheEntry gHudElementCacheTablePaletteBattle[192];
BSS s32 D_80159180;
void func_801413F8(void);
void hud_element_load_script(HudElement* hudElement, HudScript* anim) {
s32* pos = (s32*)anim;
s32 raster;
s32 palette;
s32 preset;
Vec3s* size;
HudCacheEntry* entry;
s32 i;
s32 capacity;
if (pos == NULL) {
return;
}
preset = 0;
while (TRUE) {
switch (*pos++) {
case HUD_ELEMENT_OP_End:
return;
case HUD_ELEMENT_OP_SetCI:
pos += 3;
break;
case HUD_ELEMENT_OP_SetTileSize:
preset = *pos++;
hudElement->drawSizePreset = hudElement->tileSizePreset = preset;
break;
case HUD_ELEMENT_OP_SetSizesAutoScale:
case HUD_ELEMENT_OP_SetSizesFixedScale:
preset = *pos;
pos += 2;
hudElement->drawSizePreset = hudElement->tileSizePreset = preset;
break;
case HUD_ELEMENT_OP_SetCustomSize:
hudElement->customDrawSize.x = hudElement->customImageSize.x = *pos++;
hudElement->customDrawSize.y = hudElement->customImageSize.y = *pos++;
hudElement->flags |= HUD_ELEMENT_FLAG_CUSTOM_SIZE;
break;
case HUD_ELEMENT_OP_AddTexelOffsetX:
case HUD_ELEMENT_OP_AddTexelOffsetY:
case HUD_ELEMENT_OP_SetScale:
case HUD_ELEMENT_OP_SetAlpha:
case HUD_ELEMENT_OP_op_15:
case HUD_ELEMENT_OP_RandomBranch:
case HUD_ELEMENT_OP_SetFlags:
case HUD_ELEMENT_OP_ClearFlags:
case HUD_ELEMENT_OP_PlaySound:
pos++;
break;
case HUD_ELEMENT_OP_SetRGBA:
case HUD_ELEMENT_OP_SetTexelOffset:
case HUD_ELEMENT_OP_RandomDelay:
case HUD_ELEMENT_OP_RandomRestart:
case HUD_ELEMENT_OP_SetPivot:
pos += 2;
break;
case HUD_ELEMENT_OP_SetImage:
pos++;
raster = *pos++;
palette = *pos++;
i = 0;
entry = gHudElementCacheTableRaster;
while (TRUE) {
if (entry->id == -1) {
entry->id = raster;
entry->data = &gHudElementCacheBuffer[*gHudElementCacheSize];
if (!gGameStatusPtr->isBattle) {
capacity = gHudElementCacheCapacity;
} else {
capacity = gHudElementCacheCapacity / 2;
}
ASSERT(capacity > *gHudElementCacheSize + gHudElementSizes[preset].size);
nuPiReadRom((s32)icon_ROM_START + raster, entry->data, gHudElementSizes[preset].size);
*gHudElementCacheSize += gHudElementSizes[preset].size;
if (!gGameStatusPtr->isBattle) {
*pos = i;
} else {
*pos = (u16)(*pos) | (i << 16);
}
i++;
break;
} else if (entry->id == raster) {
if (!gGameStatusPtr->isBattle) {
*pos = i;
} else {
*pos = (u16)(*pos) | (i << 16);
}
break;
}
entry++;
i++;
}
pos++;
ASSERT(i < MAX_HUD_CACHE_ENTRIES);
entry = gHudElementCacheTablePalette;
i = 0;
while (TRUE) {
if (entry->id == -1) {
entry->id = palette;
entry->data = &gHudElementCacheBuffer[*gHudElementCacheSize];
if (!gGameStatusPtr->isBattle) {
capacity = gHudElementCacheCapacity;
} else {
capacity = gHudElementCacheCapacity / 2;
}
ASSERT(capacity > *gHudElementCacheSize + 32);
nuPiReadRom((s32)icon_ROM_START + palette, entry->data, 32);
*gHudElementCacheSize += 32;
if (!gGameStatusPtr->isBattle) {
*pos = i;
} else {
*pos = (u16)(*pos) | (i << 16);
}
i++;
break;
} else if (entry->id == palette) {
if (!gGameStatusPtr->isBattle) {
*pos = i;
} else {
*pos = (u16)(*pos) | (i << 16);
}
break;
}
entry++;
i++;
}
pos++;
ASSERT(i < MAX_HUD_CACHE_ENTRIES);
break;
}
}
}
void hud_element_draw_rect(HudElement* hudElement, s16 texSizeX, s16 texSizeY, s16 drawSizeX, s16 drawSizeY,
s16 offsetX, s16 offsetY, s32 clamp, s32 dropShadow) {
u32 isFmtCI4;
u32 isFmtIA8;
s32 flipX, flipY;
s32 fmt;
s32 widthScale, heightScale;
s32 texStartX, texStartY;
u32 isLastTileX, isLastTileY;
s32 uls, ult, lrs, lrt;
s32 uly, lry, ulx, lrx;
s32 masks, maskt;
s32 screenPosOffsetScaledX, screenPosOffsetScaledY;
IMG_PTR imageAddr;
PAL_PTR paletteAddr;
s16 baseX, baseY;
s32 tileMode;
u32 flags1, flags2;
u16 renderPosX, renderPosY;
s16 tempX, tempY;
imageAddr = hudElement->imageAddr;
paletteAddr = (u16*) hudElement->paletteAddr;
screenPosOffsetScaledX = hudElement->screenPosOffset.x * 1024;
screenPosOffsetScaledY = hudElement->screenPosOffset.y * 1024;
widthScale = hudElement->widthScale;
screenPosOffsetScaledX /= widthScale;
heightScale = hudElement->heightScale;
screenPosOffsetScaledY /= heightScale;
renderPosX = hudElement->worldPosOffset.x;
renderPosY = hudElement->worldPosOffset.y;
renderPosX += hudElement->renderPosX + screenPosOffsetScaledX;
renderPosY += hudElement->renderPosY + screenPosOffsetScaledY;
tempX = offsetX;
tempY = offsetY;
tempX += renderPosX;
tempY += renderPosY;
baseX = tempX;
baseY = tempY;
if (dropShadow) {
baseX = tempX + 2;
baseY = tempY + 2;
}
flags1 = (hudElement->flags & HUD_ELEMENT_FLAG_FMT_CI4);
isFmtCI4 = flags1 != 0;
flags1 = (hudElement->flags & HUD_ELEMENT_FLAG_FMT_IA8);
isFmtIA8 = flags1 != 0;
flags1 = (hudElement->flags & HUD_ELEMENT_FLAG_FLIPX);
flipX = flags1 != 0;
flags2 = (hudElement->flags & HUD_ELEMENT_FLAG_FLIPY);
flipY = flags2 != 0;
fmt = 0;
if (isFmtCI4 == FALSE && isFmtIA8 == FALSE) {
fmt = 0; // RGBA
}
if (isFmtCI4 == TRUE && isFmtIA8 == FALSE) {
fmt = 1; // CI
}
if (isFmtCI4 == FALSE && isFmtIA8 == TRUE) {
fmt = 2; // IA
}
if (isFmtCI4 == TRUE && isFmtIA8 == TRUE) {
fmt = 2; // IA
}
masks = 6;
maskt = 5;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_SCALED)) {
switch (drawSizeX) {
case 8:
masks = 3;
break;
case 16:
masks = 4;
break;
case 32:
masks = 5;
break;
}
switch (drawSizeY) {
case 8:
maskt = 3;
break;
case 16:
maskt = 4;
break;
case 32:
maskt = 5;
break;
}
}
switch (fmt) {
case 0:
gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
break;
case 1:
if (!(hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_ANTIALIASING)) {
gDPSetRenderMode(gMainGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
} else {
gDPSetRenderMode(gMainGfxPos++, G_RM_AA_TEX_EDGE, G_RM_AA_TEX_EDGE2);
}
} else {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_ANTIALIASING)) {
gDPSetRenderMode(gMainGfxPos++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
} else {
gDPSetRenderMode(gMainGfxPos++, G_RM_CLD_SURF | AA_EN, G_RM_CLD_SURF2 | AA_EN);
}
}
gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
gDPLoadTLUT_pal16(gMainGfxPos++, 0, paletteAddr);
break;
case 2:
gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
break;
}
if (hudElement->flags & HUD_ELEMENT_FLAG_FILTER_TEX) {
gDPSetTextureFilter(gMainGfxPos++, G_TF_AVERAGE);
} else {
gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
}
ult = 0;
isLastTileY = FALSE;
uly = baseY;
while (TRUE) {
lry = uly + 1024.0 / heightScale * 32.0;
lrt = ult + 31;
if (flipY) {
texStartY = texSizeY;
} else {
texStartY = 0;
}
if (lry < 0 || uly > SCREEN_HEIGHT) {
break;
}
if (lry >= SCREEN_HEIGHT) {
s32 temp = ult + SCREEN_HEIGHT + 31;
temp -= baseY + lrt;
lrt = temp - 1;
lry = SCREEN_HEIGHT;
isLastTileY = TRUE;
}
if (lrt + 1 >= texSizeY) {
lrt = texSizeY - 1;
if (texSizeY > 16) {
lry = baseY + drawSizeY - 1;
} else {
lry = baseY + drawSizeY;
}
isLastTileY = TRUE;
}
isLastTileX = FALSE;
uls = 0;
ulx = baseX;
while (TRUE) {
lrx = ulx + 1024.0 / widthScale * 64.0;
lrs = uls + 63;
if (flipX) {
texStartX = texSizeX;
} else {
texStartX = 0;
}
if (lrx < 0 || ulx > SCREEN_WIDTH) {
break;
}
if (lrx >= SCREEN_WIDTH) {
s32 temp = uls + SCREEN_WIDTH + 63;
temp -= baseX + lrs;
lrs = temp - 1;
lrx = SCREEN_WIDTH;
isLastTileX = TRUE;
}
if (lrs + 1 >= texSizeX) {
lrs = texSizeX - 1;
if (texSizeX > 16) {
lrx = baseX + drawSizeX - 1;
} else {
lrx = baseX + drawSizeX;
}
isLastTileX = TRUE;
}
gDPPipeSync(gMainGfxPos++);
if (isLastTileX ) {
tileMode = !isLastTileY;
}
if (!isLastTileX && !isLastTileY) {
tileMode = 0;
}
if (!isLastTileX && isLastTileY) {
tileMode = 2;
}
if (isLastTileX && isLastTileY) {
tileMode = 3;
}
switch (fmt) {
case 0:
gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
if (!(hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT)) {
gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
} else {
gDPSetCombineMode(gMainGfxPos++, PM_CC_01, PM_CC_02);
}
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT) {
gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, hudElement->opacity);
}
if (!flipX && !flipY) {
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_RGBA, G_IM_SIZ_32b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
} else {
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_RGBA, G_IM_SIZ_32b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_MIRROR | G_TX_WRAP, G_TX_MIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
}
break;
case 1:
if (!dropShadow) {
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT) {
gDPSetCombineMode(gMainGfxPos++, PM_CC_2F, PM_CC_32);
} else {
gDPSetCombineMode(gMainGfxPos++, PM_CC_2F, PM_CC_32);
}
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT) {
gDPSetPrimColor(gMainGfxPos++, 0, 0, hudElement->tint.r, hudElement->tint.g, hudElement->tint.b, hudElement->opacity);
} else {
gDPSetPrimColor(gMainGfxPos++, 0, 0, hudElement->tint.r, hudElement->tint.g, hudElement->tint.b, 255);
}
} else {
gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetCombineMode(gMainGfxPos++, PM_CC_07, PM_CC_07);
gDPSetPrimColor(gMainGfxPos++, 0, 0, 40, 40, 40, 72);
}
if (!flipX && !flipY) {
if (!clamp) {
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
} else {
switch (tileMode) {
case 0:
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 1:
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 2:
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 3:
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
}
}
} else {
gDPLoadTextureTile_4b(gMainGfxPos++, imageAddr, G_IM_FMT_CI, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_MIRROR | G_TX_WRAP, G_TX_MIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
}
break;
case 2:
gDPSetCombineMode(gMainGfxPos++, PM_CC_47, PM_CC_47);
gDPSetPrimColor(gMainGfxPos++, 0, 0, hudElement->tint.r, hudElement->tint.g, hudElement->tint.b, hudElement->opacity);
if (!flipX && !flipY) {
if (!clamp) {
switch (tileMode) {
case 0:
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 1:
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 2:
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
case 3:
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
break;
}
} else {
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
}
} else {
gDPLoadTextureTile(gMainGfxPos++, imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, texSizeX, texSizeY, uls, ult, lrs, lrt, 0,
G_TX_MIRROR | G_TX_WRAP, G_TX_MIRROR | G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
}
break;
}
if (hudElement->flags & HUD_ELEMENT_FLAG_FILTER_TEX) {
gSPScisTextureRectangle(gMainGfxPos++, ulx * 4, uly * 4, lrx * 4, lry * 4, 0, texStartX * 32 + 16, texStartY * 32 + 16, widthScale, heightScale);
} else {
gSPScisTextureRectangle(gMainGfxPos++, ulx * 4, uly * 4, lrx * 4, lry * 4, 0, texStartX * 32, texStartY * 32, widthScale, heightScale);
}
if (isLastTileX) {
break;
}
ulx += 1024.0 / widthScale * 64.0;
uls += 64;
}
if (isLastTileY) {
break;
}
ult += 32;
uly += 1024.0 / heightScale * 32.0;
}
gDPPipeSync(gMainGfxPos++);
}
void hud_element_clear_cache(void) {
s32 i;
HudCacheEntry* entryRaster;
HudCacheEntry* entryPalette;
if (!gGameStatusPtr->isBattle) {
gHudElements = &gHudElementsWorld;
gHudElementCacheSize = &gHudElementCacheSizeWorld;
gHudElementCacheTableRaster = gHudElementCacheTableRasterWorld;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteWorld;
} else {
gHudElements = &gHudElementsBattle;
gHudElementCacheSize = &gHudElementCacheSizeBattle;
gHudElementCacheTableRaster = gHudElementCacheTableRasterBattle;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteBattle;
}
if (!gGameStatusPtr->isBattle) {
gHudElementCacheBuffer = general_heap_malloc(gHudElementCacheCapacity);
ASSERT(gHudElementCacheBuffer);
gHudElementCacheBufferWorld = gHudElementCacheBuffer;
*gHudElementCacheSize = 0;
entryRaster = gHudElementCacheTableRaster;
entryPalette = gHudElementCacheTablePalette;
for (i = 0; i < MAX_HUD_CACHE_ENTRIES; i++) {
entryRaster[i].id = -1;
entryPalette[i].id = -1;
}
} else {
if (gHudElementAuxCache == NULL) {
gHudElementCacheBuffer = general_heap_malloc(gHudElementCacheCapacity / 2);
ASSERT(gHudElementCacheBuffer);
} else {
gHudElementCacheBuffer = gHudElementAuxCache;
}
gHudElementCacheBufferBattle = gHudElementCacheBuffer;
*gHudElementCacheSize = 0;
entryRaster = gHudElementCacheTableRaster;
entryPalette = gHudElementCacheTablePalette;
for (i = 0; i < MAX_HUD_CACHE_ENTRIES; i++) {
entryRaster[i].id = -1;
entryPalette[i].id = -1;
}
}
for (i = 0; i < ARRAY_COUNT(*gHudElements); i++) {
(*gHudElements)[i] = NULL;
}
gHudElementsNumber = 0;
D_80159180 = 0;
func_801413F8();
}
#if VERSION_PAL
extern Addr D_80200000;
#endif
void init_hud_element_list(void) {
if (!gGameStatusPtr->isBattle) {
if (gHudElementCacheBufferBattle != NULL) {
#if VERSION_PAL
if (gHudElementCacheBufferBattle != D_80200000) {
general_heap_free(gHudElementCacheBufferBattle);
}
#else
general_heap_free(gHudElementCacheBufferBattle);
#endif
gHudElementCacheBufferBattle = NULL;
}
gHudElements = &gHudElementsWorld;
gHudElementCacheSize = &gHudElementCacheSizeWorld;
gHudElementCacheTableRaster = gHudElementCacheTableRasterWorld;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteWorld;
gHudElementCacheBuffer = gHudElementCacheBufferWorld;
} else {
gHudElements = &gHudElementsBattle;
gHudElementCacheSize = &gHudElementCacheSizeBattle;
gHudElementCacheTableRaster = gHudElementCacheTableRasterBattle;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteBattle;
gHudElementCacheBuffer = gHudElementCacheBufferBattle;
}
gHudElementsNumber = 0;
D_80159180 = 0;
}
void func_801413F8(void) {
set_cam_viewport(CAM_3, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
gCameras[CAM_3].updateMode = CAM_UPDATE_MODE_2;
gCameras[CAM_3].needsInit = TRUE;
gCameras[CAM_3].lookAt_dist = 15551;
gCameras[CAM_3].nearClip = CAM_NEAR_CLIP;
gCameras[CAM_3].auxPitch = 0;
gCameras[CAM_3].auxBoomLength = 0;
gCameras[CAM_3].auxBoomPitch = 0;
gCameras[CAM_3].lookAt_obj_target.z = 0;
gCameras[CAM_3].farClip = 0x4000;
gCameras[CAM_3].bgColor[0] = 0;
gCameras[CAM_3].bgColor[1] = 0;
gCameras[CAM_3].bgColor[2] = 0;
gCameras[CAM_3].lookAt_obj_target.x = 160.0f;
gCameras[CAM_3].lookAt_obj_target.y = -120.0f;
gCameras[CAM_3].vfov = 1.0f;
gCameras[CAM_3].flags &= ~(CAMERA_FLAG_DISABLED | CAMERA_FLAG_LEAD_PLAYER);
}
s32 hud_element_create(HudScript* anim) {
HudElement* hudElement;
s32 id;
for (id = 0; id < ARRAY_COUNT(*gHudElements); id++) {
if ((*gHudElements)[id] == NULL) {
break;
}
}
ASSERT(id < ARRAY_COUNT(*gHudElements));
(*gHudElements)[id] = hudElement = heap_malloc(sizeof(*hudElement));
gHudElementsNumber += 1;
ASSERT(hudElement != NULL);
hudElement->flags = HUD_ELEMENT_FLAG_INITIALIZED;
hudElement->readPos = anim;
if (anim == NULL) {
hudElement->readPos = &HES_Empty;
}
hudElement->updateTimer = 1;
hudElement->drawSizePreset = -1;
hudElement->tileSizePreset = -1;
hudElement->renderPosX = 0;
hudElement->renderPosY = 0;
hudElement->loopStartPos = anim;
hudElement->widthScale = X10(1.0f);
hudElement->heightScale = X10(1.0f);
hudElement->anim = hudElement->readPos;
hudElement->uniformScale = 1.0f;
hudElement->screenPosOffset.x = 0;
hudElement->screenPosOffset.y = 0;
hudElement->worldPosOffset.x = 0;
hudElement->worldPosOffset.y = 0;
hudElement->worldPosOffset.z = 0;
hudElement->opacity = 255;
hudElement->tint.r = 255;
hudElement->tint.g = 255;
hudElement->tint.b = 255;
if (gGameStatusPtr->isBattle) {
hudElement->flags |= HUD_ELEMENT_FLAG_BATTLE;
id |= HUD_ELEMENT_BATTLE_ID_MASK;
}
hud_element_load_script(hudElement, hudElement->readPos);
while (hud_element_update(hudElement) != 0);
return id;
}
// TODO not ideal match - should be able to put loop iterator in the loop def, but can't
void update_hud_elements(void) {
s32 i;
for (i = 0; i < ARRAY_COUNT(*gHudElements);) {
HudElement* elem = (*gHudElements)[i];
if (elem != NULL && elem->flags && !(elem->flags & HUD_ELEMENT_FLAG_DISABLED)) {
if (elem->flags & HUD_ELEMENT_FLAG_DELETE) {
hud_element_free(i);
i++;
} else if (elem->readPos != NULL) {
elem->updateTimer--;
if (elem->updateTimer == 0) {
while (hud_element_update(elem) != 0);
}
if (elem->flags & HUD_ELEMENT_FLAG_FIXEDSCALE) {
elem->unkImgScale[0] += elem->deltaSizeX;
elem->unkImgScale[1] += elem->deltaSizeY;
}
i++;
} else {
break;
}
} else {
i++;
}
}
}
s32 hud_element_update(HudElement* hudElement) {
HudCacheEntry* entryRaster;
HudCacheEntry* entryPalette;
s32 i;
s32 drawSizePreset;
s32 tileSizePreset;
u8 sizePreset;
f32 xScaled, yScaled;
s32 imageWidth, imageHeight, drawWidth, drawHeight;
u32 min, max;
u32 flags;
s32 raster, palette;
s32 s1, s2;
s32 arg1, arg2;
f32 uniformScale;
HudScript* newReadPos;
HudTransform* hudTransform = hudElement->hudTransform;
s32* nextPos = (s32*)hudElement->readPos;
switch (*nextPos++) {
case HUD_ELEMENT_OP_End:
hudElement->updateTimer = 60;
flags = hudElement->flags;
hudElement->flags = flags | HUD_ELEMENT_FLAG_ANIMATION_FINISHED;
break;
case HUD_ELEMENT_OP_Delete:
hudElement->updateTimer = 60;
hudElement->flags |= HUD_ELEMENT_FLAG_DELETE;
break;
case HUD_ELEMENT_OP_UseIA8:
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags |= HUD_ELEMENT_FLAG_FMT_IA8;
return TRUE;
case HUD_ELEMENT_OP_SetVisible:
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags |= HUD_ELEMENT_FLAG_FMT_CI4;
return TRUE;
case HUD_ELEMENT_OP_SetHidden:
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags &= ~HUD_ELEMENT_FLAG_FMT_CI4;
return TRUE;
case HUD_ELEMENT_OP_SetFlags:
s1 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags |= s1;
return TRUE;
case HUD_ELEMENT_OP_ClearFlags:
s1 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags &= ~s1;
return TRUE;
case HUD_ELEMENT_OP_SetRGBA:
hudElement->updateTimer = *nextPos++;
hudElement->imageAddr = (u8*)*nextPos++;
hudElement->readPos = (HudScript*)nextPos;
if (hudElement->flags & HUD_ELEMENT_FLAG_MEMOFFSET) {
hudElement->imageAddr += hudElement->memOffset;
}
if (hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
tileSizePreset = hudElement->tileSizePreset;
drawSizePreset = hudElement->drawSizePreset;
imageWidth = gHudElementSizes[tileSizePreset].width;
imageHeight = gHudElementSizes[tileSizePreset].height;
drawWidth = gHudElementSizes[drawSizePreset].width;
drawHeight = gHudElementSizes[drawSizePreset].height;
} else {
imageWidth = hudElement->customImageSize.x;
imageHeight = hudElement->customImageSize.y;
drawWidth = hudElement->customDrawSize.x;
drawHeight = hudElement->customDrawSize.y;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_200)) {
hudElement->flags |= HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = imageWidth;
hudElement->unkImgScale[1] = imageHeight;
hudElement->deltaSizeX = ((f32)drawWidth - (f32)imageWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)drawHeight - (f32)imageHeight) / (f32)hudElement->updateTimer;
} else {
hudElement->flags &= ~HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = drawWidth;
hudElement->unkImgScale[1] = drawHeight;
hudElement->deltaSizeX = ((f32)imageWidth - (f32)drawWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)imageHeight - (f32)drawHeight) / (f32)hudElement->updateTimer;
}
}
break;
case HUD_ELEMENT_OP_SetCI:
hudElement->updateTimer = *nextPos++;
hudElement->imageAddr = (u8*)*nextPos++;
hudElement->paletteAddr = (u8*)*nextPos++;
hudElement->readPos = (HudScript*)nextPos;
if (hudElement->flags & HUD_ELEMENT_FLAG_MEMOFFSET) {
hudElement->imageAddr += hudElement->memOffset;
hudElement->paletteAddr += hudElement->memOffset;
}
if (hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
tileSizePreset = hudElement->tileSizePreset;
drawSizePreset = hudElement->drawSizePreset;
imageWidth = gHudElementSizes[tileSizePreset].width;
imageHeight = gHudElementSizes[tileSizePreset].height;
drawWidth = gHudElementSizes[drawSizePreset].width;
drawHeight = gHudElementSizes[drawSizePreset].height;
} else {
imageWidth = hudElement->customImageSize.x;
imageHeight = hudElement->customImageSize.y;
drawWidth = hudElement->customDrawSize.x;
drawHeight = hudElement->customDrawSize.y;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_200)) {
hudElement->flags |= HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = imageWidth;
hudElement->unkImgScale[1] = imageHeight;
hudElement->deltaSizeX = ((f32)drawWidth - (f32)imageWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)drawHeight - (f32)imageHeight) / (f32)hudElement->updateTimer;
} else {
hudElement->flags &= ~HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = drawWidth;
hudElement->unkImgScale[1] = drawHeight;
hudElement->deltaSizeX = ((f32)imageWidth - (f32)drawWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)imageHeight - (f32)drawHeight) / (f32)hudElement->updateTimer;
}
}
break;
case HUD_ELEMENT_OP_SetImage:
hudElement->updateTimer = *nextPos++;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_BATTLE)) {
entryRaster = gHudElementCacheTableRasterWorld;
entryPalette = gHudElementCacheTablePaletteWorld;
} else {
entryRaster = gHudElementCacheTableRasterBattle;
entryPalette = gHudElementCacheTablePaletteBattle;
}
i = 0;
while (TRUE) {
if (entryRaster[i].id == *nextPos) {
break;
}
ASSERT(++i < MAX_HUD_CACHE_ENTRIES);
}
nextPos++;
hudElement->imageAddr = entryRaster[i].data;
i = 0;
while (TRUE) {
if (entryPalette[i].id == *nextPos) {
break;
}
ASSERT(++i < MAX_HUD_CACHE_ENTRIES);
}
hudElement->paletteAddr = entryPalette[i].data;
nextPos += 3;
hudElement->readPos = (HudScript*)nextPos;
if (hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
tileSizePreset = hudElement->tileSizePreset;
drawSizePreset = hudElement->drawSizePreset;
imageWidth = gHudElementSizes[tileSizePreset].width;
imageHeight = gHudElementSizes[tileSizePreset].height;
drawWidth = gHudElementSizes[drawSizePreset].width;
drawHeight = gHudElementSizes[drawSizePreset].height;
} else {
imageWidth = hudElement->customImageSize.x;
imageHeight = hudElement->customImageSize.y;
drawWidth = hudElement->customDrawSize.x;
drawHeight = hudElement->customDrawSize.y;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_200)) {
hudElement->flags |= HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = imageWidth;
hudElement->unkImgScale[1] = imageHeight;
hudElement->deltaSizeX = ((f32)drawWidth - (f32)imageWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)drawHeight - (f32)imageHeight) / (f32)hudElement->updateTimer;
} else {
hudElement->flags &= ~HUD_ELEMENT_FLAG_200;
hudElement->unkImgScale[0] = drawWidth;
hudElement->unkImgScale[1] = drawHeight;
hudElement->deltaSizeX = ((f32)imageWidth - (f32)drawWidth) / (f32)hudElement->updateTimer;
hudElement->deltaSizeY = ((f32)imageHeight - (f32)drawHeight) / (f32)hudElement->updateTimer;
}
}
break;
case HUD_ELEMENT_OP_Restart:
hudElement->readPos = hudElement->loopStartPos;
return TRUE;
case HUD_ELEMENT_OP_Loop:
hudElement->loopStartPos = (HudScript*)nextPos;
hudElement->readPos = (HudScript*)nextPos;
return TRUE;
case HUD_ELEMENT_OP_RandomRestart:
s1 = *nextPos++;
s2 = *nextPos++;
if (rand_int(s1) < s2) {
hudElement->readPos = hudElement->loopStartPos;
} else {
hudElement->readPos = (HudScript*)nextPos;
}
return TRUE;
case HUD_ELEMENT_OP_SetTileSize:
sizePreset = *nextPos++;
hudElement->widthScale = X10(1);
hudElement->heightScale = X10(1);
hudElement->readPos = (HudScript*)nextPos;
hudElement->drawSizePreset = sizePreset;
hudElement->tileSizePreset = sizePreset;
hudElement->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags &= ~HUD_ELEMENT_FLAG_REPEATED;
return TRUE;
case HUD_ELEMENT_OP_SetSizesAutoScale:
tileSizePreset = *nextPos++;
arg2 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->tileSizePreset = tileSizePreset;
hudElement->drawSizePreset = arg2;
imageWidth = gHudElementSizes[tileSizePreset].width;
imageHeight = gHudElementSizes[tileSizePreset].height;
drawWidth = gHudElementSizes[arg2].width;
drawHeight = gHudElementSizes[arg2].height;
xScaled = (f32) drawWidth / (f32) imageWidth;
yScaled = (f32) drawHeight / (f32) imageHeight;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
hudElement->widthScale = X10(xScaled);
hudElement->heightScale = X10(yScaled);
hudElement->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags |= HUD_ELEMENT_FLAG_REPEATED;
return TRUE;
case HUD_ELEMENT_OP_SetSizesFixedScale:
tileSizePreset = *nextPos++;
drawSizePreset = *nextPos++;
hudElement->widthScale = X10(1);
hudElement->heightScale = X10(1);
hudElement->readPos = (HudScript*)nextPos;
hudElement->tileSizePreset = tileSizePreset;
hudElement->drawSizePreset = drawSizePreset;
hudElement->flags |= HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags &= ~HUD_ELEMENT_FLAG_REPEATED;
hudElement->flags &= ~HUD_ELEMENT_FLAG_200;
return TRUE;
case HUD_ELEMENT_OP_AddTexelOffsetX:
s1 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->screenPosOffset.x += s1;
return TRUE;
case HUD_ELEMENT_OP_AddTexelOffsetY:
s2 = *nextPos++;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_FLIPY)) {
hudElement->screenPosOffset.y += s2;
} else {
hudElement->screenPosOffset.y -= s2;
}
hudElement->readPos = (HudScript*)nextPos;
return TRUE;
case HUD_ELEMENT_OP_SetTexelOffset:
s1 = *nextPos++;
s2 = *nextPos++;
hudElement->screenPosOffset.x = s1;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_FLIPY)) {
hudElement->screenPosOffset.y = s2;
} else {
hudElement->screenPosOffset.y = -s2;
}
hudElement->readPos = (HudScript*)nextPos;
return TRUE;
case HUD_ELEMENT_OP_SetScale:
uniformScale = (f32)*nextPos++;
uniformScale /= 65536;
hudElement->uniformScale = uniformScale;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
imageWidth = gHudElementSizes[hudElement->tileSizePreset].width;
imageHeight = gHudElementSizes[hudElement->tileSizePreset].height;
drawWidth = gHudElementSizes[hudElement->drawSizePreset].width;
drawHeight = gHudElementSizes[hudElement->drawSizePreset].height;
} else {
imageWidth = hudElement->customImageSize.x;
imageHeight = hudElement->customImageSize.y;
drawWidth = hudElement->customDrawSize.x;
drawHeight = hudElement->customDrawSize.y;
}
hudElement->sizeX = drawWidth * uniformScale;
hudElement->sizeY = drawHeight * uniformScale;
xScaled = (f32) drawWidth / (f32) imageWidth * uniformScale;
yScaled = (f32) drawHeight / (f32) imageHeight * uniformScale;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
hudElement->widthScale = X10(xScaled);
hudElement->heightScale = X10(yScaled);
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags |= HUD_ELEMENT_FLAG_REPEATED | HUD_ELEMENT_FLAG_SCALED;
return TRUE;
case HUD_ELEMENT_OP_SetAlpha:
s1 = *nextPos++;
hudElement->opacity = s1;
hudElement->flags |= HUD_ELEMENT_FLAG_TRANSPARENT;
if (hudElement->opacity == 255) {
hudElement->flags &= ~HUD_ELEMENT_FLAG_TRANSPARENT;
}
hudElement->readPos = (HudScript*)nextPos;
return TRUE;
case HUD_ELEMENT_OP_RandomDelay:
s1 = *nextPos++;
s2 = *nextPos++;
hudElement->updateTimer = rand_int(s2 - s1) + s1;
hudElement->readPos = (HudScript*)nextPos;
break;
case HUD_ELEMENT_OP_SetCustomSize:
hudElement->customDrawSize.x = hudElement->customImageSize.x = *nextPos++;
hudElement->customDrawSize.y = hudElement->customImageSize.y = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->widthScale = X10(1);
hudElement->heightScale = X10(1);
hudElement->drawSizePreset = 0;
hudElement->tileSizePreset = 0;
hudElement->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags &= ~HUD_ELEMENT_FLAG_REPEATED;
hudElement->flags |= HUD_ELEMENT_FLAG_CUSTOM_SIZE;
return TRUE;
case HUD_ELEMENT_OP_op_15:
s1 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
hudElement->flags &= ~(HUD_ELEMENT_FLAG_1000000 | HUD_ELEMENT_FLAG_2000000 | HUD_ELEMENT_FLAG_4000000 | HUD_ELEMENT_FLAG_8000000);
hudElement->flags |= s1 << 24;
return TRUE;
case HUD_ELEMENT_OP_RandomBranch:
s1 = *nextPos++;
newReadPos = (HudScript*)nextPos[rand_int(s1 - 1)];
hudElement->readPos = newReadPos;
hud_element_load_script(hudElement, newReadPos);
return TRUE;
case HUD_ELEMENT_OP_PlaySound:
arg2 = *nextPos++;
sfx_play_sound(arg2);
hudElement->readPos = (HudScript*)nextPos;
return TRUE;
case HUD_ELEMENT_OP_SetPivot:
arg1 = *nextPos++;
arg2 = *nextPos++;
hudElement->readPos = (HudScript*)nextPos;
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
hudTransform->pivot.x = arg1;
// TODO find better match
do {
hudTransform->pivot.y = arg2;
} while (0);
}
return TRUE;
case HUD_ELEMENT_OP_op_16:
break;
}
return FALSE;
}
void render_hud_elements_backUI(void) {
s32 i, count, j;
s32 sortedElements[ARRAY_COUNT(*gHudElements)];
s32 el1, el2;
s32 texSizeX, texSizeY;
s32 drawSizeX, drawSizeY, offsetX, offsetY;
HudElement* hudElement;
D_80159180++;
if (D_80159180 > 2) {
D_80159180 = 0;
}
gSPDisplayList(gMainGfxPos++, VIRTUAL_TO_PHYSICAL(gHudElementsDLBackUI));
count = 0;
for (i = 0; i < ARRAY_COUNT(*gHudElements); i++) {
hudElement = (*gHudElements)[i];
if (hudElement != NULL) {
s32 flags = hudElement->flags;
if (flags && !(flags & HUD_ELEMENT_FLAG_DISABLED)) {
if (!(flags & (HUD_ELEMENT_FLAG_80 | HUD_ELEMENT_FLAG_TRANSFORM | HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000 | HUD_ELEMENT_FLAG_40000000))) {
if (!(flags & HUD_ELEMENT_FLAG_FRONTUI) && hudElement->drawSizePreset >= 0) {
sortedElements[count++] = i;
}
}
}
}
}
for (i = 0; i < count - 1; i++) {
for (j = i + 1; j < count; j++) {
el1 = sortedElements[i];
el2 = sortedElements[j];
if ((*gHudElements)[el1]->worldPosOffset.z < (*gHudElements)[el2]->worldPosOffset.z) {
sortedElements[i] = el2;
sortedElements[j] = el1;
}
}
}
for (i = 0; i < count; i++) {
hudElement = (*gHudElements)[sortedElements[i]];
if (hudElement->readPos == NULL) {
break;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
texSizeX = gHudElementSizes[hudElement->tileSizePreset].width;
texSizeY = gHudElementSizes[hudElement->tileSizePreset].height;
} else {
texSizeX = hudElement->customImageSize.x;
texSizeY = hudElement->customImageSize.y;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_SCALED)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
drawSizeX = gHudElementSizes[hudElement->drawSizePreset].width;
drawSizeY = gHudElementSizes[hudElement->drawSizePreset].height;
offsetX = -drawSizeX / 2;
offsetY = -drawSizeY / 2;
} else {
// TODO find better match
do {
drawSizeX = hudElement->customDrawSize.x;
drawSizeY = hudElement->customDrawSize.y;
offsetX = -drawSizeX / 2;
} while (0);
offsetY = -drawSizeY / 2;
}
} else {
drawSizeX = hudElement->sizeX;
drawSizeY = hudElement->sizeY;
offsetX = -drawSizeX / 2;
offsetY = -drawSizeY / 2;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_REPEATED)) {
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, FALSE);
} else {
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
} else {
f32 xScaled, yScaled;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
texSizeX = gHudElementSizes[hudElement->tileSizePreset].width;
texSizeY = gHudElementSizes[hudElement->tileSizePreset].height;
} else {
texSizeX = hudElement->customImageSize.x;
texSizeY = hudElement->customImageSize.y;
}
drawSizeX = hudElement->unkImgScale[0];
drawSizeY = hudElement->unkImgScale[1];
offsetX = -hudElement->unkImgScale[0] / 2;
offsetY = -hudElement->unkImgScale[1] / 2;
xScaled = (f32) drawSizeX / (f32) texSizeX;
yScaled = (f32) drawSizeY / (f32) texSizeY;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
hudElement->widthScale = X10(xScaled);
hudElement->heightScale = X10(yScaled);
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
}
}
void render_hud_elements_frontUI(void) {
s32 i, count, j;
s32 sortedElements[ARRAY_COUNT(*gHudElements)];
s32 el1, el2;
s32 texSizeX, texSizeY;
s32 drawSizeX, drawSizeY, offsetX, offsetY;
HudElement* hudElement;
gSPDisplayList(gMainGfxPos++, VIRTUAL_TO_PHYSICAL(gHudElementsDLFrontUI));
count = 0;
for (i = 0; i < ARRAY_COUNT(*gHudElements); i++) {
hudElement = (*gHudElements)[i];
if (hudElement != NULL) {
s32 flags = hudElement->flags;
if (flags && !(flags & HUD_ELEMENT_FLAG_DISABLED)) {
if (!(flags & (HUD_ELEMENT_FLAG_80 | HUD_ELEMENT_FLAG_TRANSFORM | HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000))) {
if ((flags & HUD_ELEMENT_FLAG_FRONTUI) && hudElement->drawSizePreset >= 0) {
sortedElements[count++] = i;
}
}
}
}
}
for (i = 0; i < count - 1; i++) {
for (j = i + 1; j < count; j++) {
el1 = sortedElements[i];
el2 = sortedElements[j];
if ((*gHudElements)[el1]->worldPosOffset.z < (*gHudElements)[el2]->worldPosOffset.z) {
sortedElements[i] = el2;
sortedElements[j] = el1;
}
}
}
for (i = 0; i < count; i++) {
hudElement = (*gHudElements)[sortedElements[i]];
if (!(hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
texSizeX = gHudElementSizes[hudElement->tileSizePreset].width;
texSizeY = gHudElementSizes[hudElement->tileSizePreset].height;
} else {
texSizeX = hudElement->customImageSize.x;
texSizeY = hudElement->customImageSize.y;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_SCALED)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
drawSizeX = gHudElementSizes[hudElement->drawSizePreset].width;
drawSizeY = gHudElementSizes[hudElement->drawSizePreset].height;
offsetX = -drawSizeX / 2;
offsetY = -drawSizeY / 2;
} else {
// TODO find better match
do {
drawSizeX = hudElement->customDrawSize.x;
drawSizeY = hudElement->customDrawSize.y;
offsetX = -drawSizeX / 2;
} while (0);
offsetY = -drawSizeY / 2;
}
} else {
drawSizeX = hudElement->sizeX;
drawSizeY = hudElement->sizeY;
offsetX = -drawSizeX / 2;
offsetY = -drawSizeY / 2;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_REPEATED)) {
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, FALSE);
} else {
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
} else {
f32 xScaled, yScaled;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
texSizeX = gHudElementSizes[hudElement->drawSizePreset].width;
texSizeY = gHudElementSizes[hudElement->drawSizePreset].height;
} else {
texSizeX = hudElement->customImageSize.x;
texSizeY = hudElement->customImageSize.y;
}
drawSizeX = hudElement->unkImgScale[0];
drawSizeY = hudElement->unkImgScale[1];
offsetX = -hudElement->unkImgScale[0] / 2;
offsetY = -hudElement->unkImgScale[1] / 2;
xScaled = (f32) drawSizeX / (f32) texSizeX;
yScaled = (f32) drawSizeY / (f32) texSizeY;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
hudElement->widthScale = X10(xScaled);
hudElement->heightScale = X10(yScaled);
if (hudElement->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(hudElement, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
}
}
void render_hud_element(HudElement* hudElement) {
Matrix4f sp20;
Matrix4f sp60;
Matrix4f spA0;
Matrix4f spE0;
Matrix4f sp120;
Matrix4f sp160;
Matrix4f sp1A0;
Matrix4f sp1E0;
Matrix4f sp220;
Matrix4f sp260;
ImgFXTexture ifxImg;
f32 xScaleFactor, yScaleFactor;
s32 height, width;
HudTransform* transform;
s32 mode;
u32 flags;
IMG_PTR raster;
PAL_PTR palette;
u32 a0, v1;
s32 ulx, uly, lrx, lry;
Vtx* vtx;
Vtx* vtx2;
if (hudElement->flags & HUD_ELEMENT_FLAG_FILTER_TEX) {
gDPSetTextureFilter(gMainGfxPos++, G_TF_AVERAGE);
} else {
gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_FIXEDSCALE)) {
xScaleFactor = 1.0f;
yScaleFactor = 1.0f;
} else {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
xScaleFactor = gHudElementSizes[hudElement->tileSizePreset].width;
yScaleFactor = gHudElementSizes[hudElement->tileSizePreset].height;
} else {
xScaleFactor = hudElement->customImageSize.x;
yScaleFactor = hudElement->customImageSize.y;
}
xScaleFactor /= hudElement->unkImgScale[0];
xScaleFactor = 1.0f / xScaleFactor;
yScaleFactor /= hudElement->unkImgScale[1];
yScaleFactor = 1.0f / yScaleFactor;
}
if (!(hudElement->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
width = gHudElementSizes[hudElement->tileSizePreset].width;
height = gHudElementSizes[hudElement->tileSizePreset].height;
} else {
width = hudElement->customImageSize.x;
height = hudElement->customImageSize.y;
}
transform = hudElement->hudTransform;
guTranslateF(sp1E0, transform->pivot.x, -transform->pivot.y, 0.0f);
guTranslateF(sp220, -transform->pivot.x, transform->pivot.y, 0.0f);
guTranslateF(
sp1A0,
hudElement->renderPosX + hudElement->screenPosOffset.x + hudElement->worldPosOffset.x + transform->pos.x,
-hudElement->renderPosY - hudElement->screenPosOffset.y + hudElement->worldPosOffset.y + transform->pos.y,
- (hudElement->worldPosOffset.z / 10.0) + transform->pos.z
);
guScaleF(sp260, hudElement->uniformScale * xScaleFactor * transform->scale.x,
hudElement->uniformScale * yScaleFactor * transform->scale.y,
transform->scale.z);
guRotateF(sp120, transform->rot.y, 0.0f, 1.0f, 0.0f);
guRotateF(sp160, transform->rot.z, 0.0f, 0.0f, 1.0f);
guRotateF(spE0, transform->rot.x, 1.0f, 0.0f, 0.0f);
guMtxCatF(sp160, spE0, sp20);
guMtxCatF(sp20, sp120, spA0);
guMtxCatF(sp260, sp1E0, sp20);
guMtxCatF(sp20, spA0, sp60);
guMtxCatF(sp60, sp220, sp20);
guMtxCatF(sp20, sp1A0, sp60);
guMtxF2L(sp60, &gDisplayContext->matrixStack[gMatrixListPos]);
gSPMatrix(gMainGfxPos++, VIRTUAL_TO_PHYSICAL(&gDisplayContext->matrixStack[gMatrixListPos++]),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
mode = 0;
a0 = mode;
a0 = (hudElement->flags & HUD_ELEMENT_FLAG_FMT_CI4) > a0;
v1 = mode < (hudElement->flags & HUD_ELEMENT_FLAG_FMT_IA8);
if (a0 == TRUE) {
mode = (v1 < 1);
}
if (a0 == FALSE) {
if (v1 == TRUE) {
mode = 2;
}
}
if (a0 == TRUE) {
if (v1 == a0) {
mode = 2;
}
}
switch (mode) {
case 1:
if (hudElement->flags & HUD_ELEMENT_FLAG_NO_FOLD) {
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT) {
imgfx_update(0, IMGFX_SET_ALPHA, 255, 255, 255, hudElement->opacity, 0);
} else {
imgfx_update(0, IMGFX_CLEAR, 0, 0, 0, 0, 0);
}
} else {
if (hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT) {
imgfx_update(transform->imgfxIdx, IMGFX_SET_ALPHA, 255, 255, 255, hudElement->opacity, 0);
} else {
imgfx_update(transform->imgfxIdx, IMGFX_CLEAR, 0, 0, 0, 0, 0);
}
}
ifxImg.raster = hudElement->imageAddr;
palette = (u16*) hudElement->paletteAddr;
ifxImg.width = width;
ifxImg.height = height;
ifxImg.xOffset = -width / 2;
ifxImg.yOffset = height / 2;
ifxImg.alpha = 255;
ifxImg.palette = palette;
if (hudElement->flags & HUD_ELEMENT_FLAG_NO_FOLD) {
if (hudElement->flags & HUD_ELEMENT_FLAG_ANTIALIASING) {
imgfx_appendGfx_component(0, &ifxImg, IMGFX_FLAG_40, sp60);
} else {
imgfx_appendGfx_component(0, &ifxImg, IMGFX_FLAG_40, sp60);
}
} else {
imgfx_appendGfx_component(transform->imgfxIdx, &ifxImg, IMGFX_FLAG_40, sp60);
}
break;
case 2:
transform->unk_30[D_80159180].vtx[0] = D_8014F0C8[0];
transform->unk_30[D_80159180].vtx[1] = D_8014F0C8[1];
transform->unk_30[D_80159180].vtx[2] = D_8014F0C8[2];
transform->unk_30[D_80159180].vtx[3] = D_8014F0C8[3];
vtx2 = transform->unk_30[D_80159180].vtx;
vtx = vtx2;
vtx2->v.ob[0] = -width / 2;
vtx2->v.ob[1] = -height / 2;
vtx2->v.ob[2] = 0;
vtx2->v.tc[0] = 0;
vtx2->v.tc[1] = height * 32;
vtx2 = vtx2 + 1;
vtx2[0].v.ob[0] = (width / 2) - 1;
vtx2[0].v.ob[1] = -height / 2;
vtx2[0].v.ob[2] = 0;
vtx2[0].v.tc[0] = width * 32;
vtx2[0].v.tc[1] = height * 32;
vtx[2].v.ob[0] = (width / 2) - 1;
vtx[2].v.ob[1] = (height / 2) - 1;
vtx[2].v.ob[2] = 0;
vtx[2].v.tc[0] = width * 32;
vtx[2].v.tc[1] = 0;
vtx[3].v.ob[0] = -width / 2;
vtx[3].v.ob[1] = (height / 2) - 1;
vtx[3].v.ob[2] = 0;
vtx[3].v.tc[0] = 0;
vtx[3].v.tc[1] = 0;
gDPPipeSync(gMainGfxPos++);
gDPSetCombineMode(gMainGfxPos++, PM_CC_47, PM_CC_47);
gDPSetPrimColor(gMainGfxPos++, 0, 0,
hudElement->tint.r, hudElement->tint.g, hudElement->tint.b, hudElement->opacity);
if (!(hudElement->flags & HUD_ELEMENT_FLAG_TRANSPARENT)) {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_ANTIALIASING)) {
gDPSetRenderMode(gMainGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
} else {
gDPSetRenderMode(gMainGfxPos++, G_RM_AA_TEX_EDGE, G_RM_AA_TEX_EDGE2);
}
} else {
if (!(hudElement->flags & HUD_ELEMENT_FLAG_ANTIALIASING)) {
gDPSetRenderMode(gMainGfxPos++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
} else {
gDPSetRenderMode(gMainGfxPos++, AA_EN | G_RM_CLD_SURF, AA_EN | G_RM_CLD_SURF2);
}
}
gDPLoadTextureBlock(gMainGfxPos++, hudElement->imageAddr, G_IM_FMT_IA, G_IM_SIZ_8b, width, height, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
gSPVertex(gMainGfxPos++, &transform->unk_30[D_80159180], 4, 0);
gSP1Triangle(gMainGfxPos++, 0, 1, 2, 0);
gSP1Triangle(gMainGfxPos++, 0, 2, 3, 0);
break;
}
gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
gDPPipeSync(gMainGfxPos++);
}
void render_transformed_hud_elements(void) {
s32 i, count, j;
s32 sortedElements[ARRAY_COUNT(*gHudElements)];
s32 el1, el2;
HudElement* hudElement;
s16 tempOffsetZ;
s32 flags;
s32 z1, z2;
// TODO fix this terrible match
do {
do {
count = 0;
if (gCurrentCamID == CAM_3) {
for (i = 0; i < ARRAY_COUNT(*gHudElements); i++) {
hudElement = (*gHudElements)[i];
if (hudElement == NULL) {
continue;
}
flags = hudElement->flags;
if (flags == 0 || flags & HUD_ELEMENT_FLAG_DISABLED) {
continue;
}
if (flags & (HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000)) {
continue;
}
if (!(flags & HUD_ELEMENT_FLAG_TRANSFORM)) {
continue;
}
if (flags & HUD_ELEMENT_FLAG_40000000) {
continue;
}
if (flags & HUD_ELEMENT_FLAG_FRONTUI || hudElement->drawSizePreset < 0 || flags & HUD_ELEMENT_FLAG_80) {
continue;
}
// add element to list
sortedElements[count++] = i;
}
if (count != 0) {
for (i = 0; i < count - 1; i++) {
for (j = i + 1; j < count; j++) {
el1 = sortedElements[i];
el2 = sortedElements[j];
tempOffsetZ = (*gHudElements)[el1]->worldPosOffset.z;
do {} while (0);
if (tempOffsetZ < (*gHudElements)[el2]->worldPosOffset.z) {
sortedElements[i] = el2;
sortedElements[j] = el1;
}
}
}
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 12, 20, 308, 220);
gDPPipeSync(gMainGfxPos++);
gSPClearGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH);
gSPSetGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
gSPSetLights1(gMainGfxPos++, HudElementLights);
gSPTexture(gMainGfxPos++, -1, -1, 0, G_TX_RENDERTILE, G_ON);
gDPSetAlphaCompare(gMainGfxPos++, G_AC_NONE);
gSPSetOtherMode(gMainGfxPos++, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE);
for (i = 0; i < count; i++) {
render_hud_element((*gHudElements)[sortedElements[i]]);
}
}
}
count = 0;
if (gCurrentCamID == CAM_BATTLE) {
for (i = 0; i < ARRAY_COUNT(*gHudElements); i++) {
hudElement = (*gHudElements)[i];
if (hudElement == NULL) {
continue;
}
flags = hudElement->flags;
if (flags == 0 || flags & HUD_ELEMENT_FLAG_DISABLED) {
continue;
}
if (flags & (HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000)) {
continue;
}
if (!(flags & HUD_ELEMENT_FLAG_TRANSFORM)) {
continue;
}
// different from CAM_3 pass
if (!(flags & HUD_ELEMENT_FLAG_40000000)) {
continue;
}
if (flags & HUD_ELEMENT_FLAG_FRONTUI || hudElement->drawSizePreset < 0 || flags & HUD_ELEMENT_FLAG_80) {
continue;
}
// add element to list
sortedElements[count++] = i;
}
if (count != 0) {
for (i = 0; i < count - 1; i++) {
for (j = i + 1; j < count; j++) {
el1 = sortedElements[i];
el2 = sortedElements[j];
tempOffsetZ = (*gHudElements)[el1]->worldPosOffset.z;
do {} while (0);
if ((*gHudElements)[el1]->worldPosOffset.z < (*gHudElements)[el2]->worldPosOffset.z) {
sortedElements[i] = el2;
sortedElements[j] = el1;
}
}
}
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 12, 20, 308, 220);
gDPPipeSync(gMainGfxPos++);
gSPClearGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH);
gSPSetGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
gSPSetLights1(gMainGfxPos++, HudElementLights);
gSPTexture(gMainGfxPos++, -1, -1, 0, G_TX_RENDERTILE, G_ON);
gDPSetAlphaCompare(gMainGfxPos++, G_AC_NONE);
gSPSetOtherMode(gMainGfxPos++, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE);
for (i = 0; i < count; i++) {
render_hud_element((*gHudElements)[sortedElements[i]]);
}
}
}
} while (0);
} while (0);
}
void func_80143C48(s32 elemID, s32 arg1, s32 camID) {
Camera* camera = &gCameras[camID];
if (arg1 > 0) {
if (camera->flags == 0 || (camera->flags & CAMERA_FLAG_DISABLED)) {
return;
}
gCurrentCamID = camID;
gSPViewport(gMainGfxPos++, &camera->vp);
gSPClearGeometryMode(gMainGfxPos++, G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN |
G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH);
gSPTexture(gMainGfxPos++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
gDPPipelineMode(gMainGfxPos++, G_PM_NPRIMITIVE);
gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
gDPSetTextureFilter(gMainGfxPos++, G_TF_BILERP);
gDPSetCombineMode(gMainGfxPos++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gMainGfxPos++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gSPClipRatio(gMainGfxPos++, FRUSTRATIO_2);
gDPPipeSync(gMainGfxPos++);
//clear Z buffer inside camera viewport
gDPSetCycleType(gMainGfxPos++, G_CYC_FILL);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH, osVirtualToPhysical(nuGfxZBuffer));
gDPSetFillColor(gMainGfxPos++, GPACK_ZDZ(G_MAXFBZ, 0)<<16 | GPACK_ZDZ(G_MAXFBZ, 0));
gDPFillRectangle(gMainGfxPos++, camera->viewportStartX, camera->viewportStartY,
camera->viewportStartX + camera->viewportW - 1,
camera->viewportStartY + camera->viewportH - 1);
gDPPipeSync(gMainGfxPos++);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH, osVirtualToPhysical(nuGfxCfb_ptr));
gDPPipeSync(gMainGfxPos++);
guOrthoF(camera->perspectiveMatrix, 0.0f, 320.0f, -240.0f, 0.0f, -1000.0f, 1000.0f, 1.0f);
guMtxF2L(camera->perspectiveMatrix, &gDisplayContext->camPerspMatrix[gCurrentCamID]);
gSPMatrix(gMainGfxPos++, &gDisplayContext->camPerspMatrix[gCurrentCamID], G_MTX_NOPUSH | G_MTX_LOAD |
G_MTX_PROJECTION);
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 12, 20, 308, 220);
gDPPipeSync(gMainGfxPos++);
gDPSetCycleType(gMainGfxPos++, G_CYC_1CYCLE);
gSPClearGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING |
G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH);
gSPSetGeometryMode(gMainGfxPos++, G_ZBUFFER | G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
gSPSetLights1(gMainGfxPos++, HudElementLights);
gSPTexture(gMainGfxPos++, -1, -1, 0, G_TX_RENDERTILE, G_ON);
gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
gDPSetColorDither(gMainGfxPos++, G_CD_DISABLE);
gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
gDPSetTextureConvert(gMainGfxPos++, G_TC_FILT);
gDPSetCombineKey(gMainGfxPos++, G_CK_NONE);
gDPSetAlphaCompare(gMainGfxPos++, G_AC_NONE);
}
if (elemID >= 0) {
HudElement* elem;
elemID &= ~HUD_ELEMENT_BATTLE_ID_MASK;
elem = (*gHudElements)[elemID];
if (elem == NULL) {
return;
}
if (elem->flags == 0 || elem->flags & HUD_ELEMENT_FLAG_DISABLED) {
return;
}
if (elem->flags & (HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000)) {
return;
}
if (!(elem->flags & HUD_ELEMENT_FLAG_TRANSFORM)) {
return;
}
if (elem->flags & HUD_ELEMENT_FLAG_FRONTUI || elem->drawSizePreset < 0 || !(elem->flags & HUD_ELEMENT_FLAG_80)) {
return;
}
render_hud_element(elem);
}
}
void func_80144218(s32 id) {
func_80143C48(id, 1, CAM_3);
}
void func_80144238(s32 id) {
func_80143C48(id, 0, CAM_3);
}
void func_80144258(s32 id) {
func_80143C48(id, 1, CAM_BATTLE);
}
void func_80144278(s32 id) {
func_80143C48(id, 0, CAM_BATTLE);
}
void draw_hud_element_internal(s32 id, s32 clipMode) {
HudElement* elem = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
s32 texSizeX, texSizeY;
s32 drawSizeX, drawSizeY;
s32 offsetX, offsetY;
s32 preset;
if (elem->flags && !(elem->flags & HUD_ELEMENT_FLAG_DISABLED)) {
if (!(elem->flags & (HUD_ELEMENT_FLAG_200000 | HUD_ELEMENT_FLAG_10000000)) && (elem->drawSizePreset >= 0)) {
if (clipMode != HUD_ELEMENT_DRAW_NEXT) {
if (clipMode == HUD_ELEMENT_DRAW_FIRST_WITH_CLIPPING) {
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 12, 20, SCREEN_WIDTH - 12, SCREEN_HEIGHT - 20);
}
gDPPipeSync(gMainGfxPos++);
gDPSetCycleType(gMainGfxPos++, G_CYC_1CYCLE);
gDPSetTexturePersp(gMainGfxPos++, G_TP_NONE);
gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
gDPSetTextureConvert(gMainGfxPos++, G_TC_FILT);
gDPSetCombineKey(gMainGfxPos++, G_CK_NONE);
gDPSetAlphaCompare(gMainGfxPos++, G_AC_NONE);
gDPNoOp(gMainGfxPos++);
gDPSetColorDither(gMainGfxPos++, G_CD_DISABLE);
gDPSetAlphaDither(gMainGfxPos++, G_AD_DISABLE);
gSPTexture(gMainGfxPos++, -1, -1, 0, G_TX_RENDERTILE, G_ON);
}
if (!(elem->flags & HUD_ELEMENT_FLAG_FIXEDSCALE)) {
if (!(elem->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
preset = elem->tileSizePreset;
texSizeX = gHudElementSizes[preset].width;
texSizeY = gHudElementSizes[preset].height;
} else {
texSizeX = elem->customImageSize.x;
texSizeY = elem->customImageSize.y;
}
if (!(elem->flags & HUD_ELEMENT_FLAG_SCALED)) {
if (!(elem->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
drawSizeX = gHudElementSizes[elem->drawSizePreset].width;
drawSizeY = gHudElementSizes[elem->drawSizePreset].height;
} else {
drawSizeX = elem->customDrawSize.x;
drawSizeY = elem->customDrawSize.y;
}
} else {
drawSizeX = elem->sizeX;
drawSizeY = elem->sizeY;
}
do {
offsetX = -drawSizeX / 2;
offsetY = -drawSizeY / 2;
} while (0); // required to match
if (!(elem->flags & HUD_ELEMENT_FLAG_REPEATED)) {
if (elem->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, TRUE);
}
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, TRUE, FALSE);
} else {
if (elem->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
} else {
f32 xScaled, yScaled;
if (!(elem->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
preset = elem->tileSizePreset;
texSizeX = gHudElementSizes[preset].width;
texSizeY = gHudElementSizes[preset].height;
} else {
texSizeX = elem->customImageSize.x;
texSizeY = elem->customImageSize.y;
}
drawSizeX = elem->unkImgScale[0];
drawSizeY = elem->unkImgScale[1];
offsetX = -elem->unkImgScale[0] / 2;
offsetY = -elem->unkImgScale[1] / 2;
xScaled = (f32) drawSizeX / (f32) texSizeX;
yScaled = (f32) drawSizeY / (f32) texSizeY;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
elem->widthScale = X10(xScaled);
elem->heightScale = X10(yScaled);
if (elem->flags & HUD_ELEMENT_FLAG_DROP_SHADOW) {
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, TRUE);
}
hud_element_draw_rect(elem, texSizeX, texSizeY, drawSizeX, drawSizeY, offsetX, offsetY, FALSE, FALSE);
}
}
}
}
void hud_element_draw_clipped(s32 id) {
draw_hud_element_internal(id, HUD_ELEMENT_DRAW_FIRST_WITH_CLIPPING);
}
void hud_element_draw_next(s32 id) {
draw_hud_element_internal(id, HUD_ELEMENT_DRAW_NEXT);
}
void hud_element_draw_without_clipping(s32 id) {
draw_hud_element_internal(id, HUD_ELEMENT_DRAW_FIRST_WITHOUT_CLIPPING);
}
void hud_element_set_script(s32 id, HudScript* anim) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
if (anim == NULL) {
anim = &HES_Empty;
}
hudElement->updateTimer = 1;
hudElement->widthScale = X10(1.0f);
hudElement->heightScale = X10(1.0f);
hudElement->readPos = anim;
hudElement->anim = anim;
hudElement->loopStartPos = anim;
hudElement->screenPosOffset.x = 0;
hudElement->screenPosOffset.y = 0;
hudElement->worldPosOffset.x = 0;
hudElement->worldPosOffset.y = 0;
hudElement->flags &= ~HUD_ELEMENT_FLAG_ANIMATION_FINISHED;
hudElement->uniformScale = 1.0f;
hudElement->flags &= ~(HUD_ELEMENT_FLAG_SCALED | HUD_ELEMENT_FLAG_TRANSPARENT | HUD_ELEMENT_FLAG_FIXEDSCALE | HUD_ELEMENT_FLAG_REPEATED);
hud_element_load_script(hudElement, anim);
while (hud_element_update(hudElement) != 0) {}
}
HudScript* hud_element_get_script(s32 id) {
return (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->anim;
}
HudElement* get_hud_element(s32 id) {
return (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
}
void hud_element_free(s32 id) {
if ((*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
hud_element_free_transform(id & ~HUD_ELEMENT_BATTLE_ID_MASK);
}
heap_free((*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]);
(*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK] = NULL;
gHudElementsNumber--;
}
void hud_element_set_render_pos(s32 id, s32 x, s32 y) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
hudElement->renderPosX = x;
hudElement->renderPosY = y;
}
void hud_element_get_render_pos(s32 id, s32* x, s32* y) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
*x = hudElement->renderPosX;
*y = hudElement->renderPosY;
}
void hud_element_set_render_depth(s32 id, s32 z) {
(*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->worldPosOffset.z = z;
}
void hud_element_set_flags(s32 id, s32 flags) {
(*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->flags |= flags;
}
void hud_element_clear_flags(s32 id, s32 flags) {
(*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->flags &= ~flags;
}
void ALT_clear_hud_element_cache(void) {
s32 i;
if (!gGameStatusPtr->isBattle) {
heap_free(gHudElementCacheBuffer);
gHudElementCacheBuffer = heap_malloc(gHudElementCacheCapacity);
ASSERT(gHudElementCacheBuffer);
gHudElementCacheBufferWorld = gHudElementCacheBuffer;
*gHudElementCacheSize = 0;
gHudElementCacheSize = &gHudElementCacheSizeWorld;
gHudElementCacheTableRaster = gHudElementCacheTableRasterWorld;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteWorld;
gHudElementCacheBuffer = gHudElementCacheBufferWorld;
for (i = 0; i < MAX_HUD_CACHE_ENTRIES; i++) {
gHudElementCacheTableRasterWorld[i].id = -1;
gHudElementCacheTablePaletteWorld[i].id = -1;
}
} else {
if (gHudElementAuxCache == NULL) {
heap_free(gHudElementCacheBuffer);
gHudElementCacheBuffer = heap_malloc(gHudElementCacheCapacity / 2);
ASSERT(gHudElementCacheBuffer);
} else {
gHudElementCacheBuffer = gHudElementAuxCache;
}
gHudElementCacheBufferBattle = gHudElementCacheBuffer;
*gHudElementCacheSize = 0;
gHudElementCacheSize = &gHudElementCacheSizeBattle;
gHudElementCacheTableRaster = gHudElementCacheTableRasterBattle;
gHudElementCacheTablePalette = gHudElementCacheTablePaletteBattle;
gHudElementCacheBuffer = gHudElementCacheBufferBattle;
for (i = 0; i < MAX_HUD_CACHE_ENTRIES; i++) {
gHudElementCacheTableRasterBattle[i].id = -1;
gHudElementCacheTablePaletteBattle[i].id = -1;
}
}
}
void hud_element_set_scale(s32 index, f32 scale) {
HudElement* elem = (*gHudElements)[index & ~HUD_ELEMENT_BATTLE_ID_MASK];
s32 drawSizeX;
s32 drawSizeY;
s32 imgSizeX;
s32 imgSizeY;
f32 xScaled, yScaled;
elem->uniformScale = scale;
if (!(elem->flags & HUD_ELEMENT_FLAG_CUSTOM_SIZE)) {
imgSizeX = gHudElementSizes[elem->tileSizePreset].width;
imgSizeY = gHudElementSizes[elem->tileSizePreset].height;
drawSizeX = gHudElementSizes[elem->drawSizePreset].width;
drawSizeY = gHudElementSizes[elem->drawSizePreset].height;
} else {
imgSizeX = elem->customImageSize.x;
imgSizeY = elem->customImageSize.y;
drawSizeX = elem->customDrawSize.x;
drawSizeY = elem->customDrawSize.y;
}
elem->sizeX = drawSizeX * scale;
elem->sizeY = drawSizeY * scale;
elem->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
elem->flags |= HUD_ELEMENT_FLAG_REPEATED | HUD_ELEMENT_FLAG_SCALED;
xScaled = ((f32) drawSizeX / (f32) imgSizeX) * scale;
yScaled = ((f32) drawSizeY / (f32) imgSizeY) * scale;
xScaled = 1.0f / xScaled;
yScaled = 1.0f / yScaled;
elem->widthScale = X10(xScaled);
elem->heightScale = X10(yScaled);
}
void hud_element_use_preset_size(s32 id, s8 sizePreset) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
hudElement->widthScale = X10(1.0f);
hudElement->heightScale = X10(1.0f);
hudElement->tileSizePreset = sizePreset;
hudElement->drawSizePreset = sizePreset;
hudElement->uniformScale = 1.0f;
hudElement->flags &= ~HUD_ELEMENT_FLAG_FIXEDSCALE;
hudElement->flags &= ~(HUD_ELEMENT_FLAG_SCALED | HUD_ELEMENT_FLAG_REPEATED);
}
s32 func_80144E4C(s32 id) {
return ((*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK]->flags >> 24) & 0xF;
}
void func_80144E74(s32 id, s32 arg1) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
hudElement->flags &= ~(HUD_ELEMENT_FLAG_1000000 | HUD_ELEMENT_FLAG_2000000 | HUD_ELEMENT_FLAG_4000000 | HUD_ELEMENT_FLAG_8000000);
hudElement->flags |= arg1 << 24;
}
void hud_element_set_alpha(s32 id, s32 opacity) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
hudElement->flags |= HUD_ELEMENT_FLAG_TRANSPARENT;
hudElement->opacity = opacity;
if (opacity == 255) {
hudElement->flags &= ~HUD_ELEMENT_FLAG_TRANSPARENT;
}
}
void hud_element_set_tint(s32 id, s32 r, s32 g, s32 b) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
hudElement->tint.r = r;
hudElement->tint.g = g;
hudElement->tint.b = b;
}
void hud_element_create_transform_A(s32 id) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = general_heap_malloc(sizeof(*transform));
element->hudTransform = transform;
ASSERT(transform != NULL);
element->flags |= HUD_ELEMENT_FLAG_TRANSFORM;
transform->imgfxIdx = imgfx_get_free_instances(1);
transform->pos.x = 0.0f;
transform->pos.y = 0.0f;
transform->pos.z = 0.0f;
transform->rot.x = 0.0f;
transform->rot.y = 0.0f;
transform->rot.z = 0.0f;
transform->scale.x = 1.0f;
transform->scale.y = 1.0f;
transform->scale.z = 1.0f;
transform->pivot.x = 0;
transform->pivot.y = 0;
func_801413F8();
}
void hud_element_create_transform_B(s32 id) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = general_heap_malloc(sizeof(*transform));
element->hudTransform = transform;
ASSERT(transform != NULL);
element->flags |= HUD_ELEMENT_FLAG_TRANSFORM | HUD_ELEMENT_FLAG_NO_FOLD;
transform->imgfxIdx = 0;
transform->pos.x = 0.0f;
transform->pos.y = 0.0f;
transform->pos.z = 0.0f;
transform->rot.x = 0.0f;
transform->rot.y = 0.0f;
transform->rot.z = 0.0f;
transform->scale.x = 1.0f;
transform->scale.y = 1.0f;
transform->scale.z = 1.0f;
func_801413F8();
}
void hud_element_create_transform_C(s32 id) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = general_heap_malloc(sizeof(*transform));
element->hudTransform = transform;
ASSERT(transform != NULL);
element->flags |= HUD_ELEMENT_FLAG_40000000 | HUD_ELEMENT_FLAG_NO_FOLD | HUD_ELEMENT_FLAG_TRANSFORM;
transform->imgfxIdx = 0;
transform->pos.x = 0.0f;
transform->pos.y = 0.0f;
transform->pos.z = 0.0f;
transform->rot.x = 0.0f;
transform->rot.y = 0.0f;
transform->rot.z = 0.0f;
transform->scale.x = 1.0f;
transform->scale.y = 1.0f;
transform->scale.z = 1.0f;
func_801413F8();
}
void hud_element_free_transform(s32 id) {
HudElement* hudElement = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* hudTransform = hudElement->hudTransform;
if (!(hudElement->flags & HUD_ELEMENT_FLAG_NO_FOLD)) {
imgfx_release_instance(hudTransform->imgfxIdx);
}
heap_free(hudElement->hudTransform);
hudElement->hudTransform = NULL;
hudElement->flags &= ~(HUD_ELEMENT_FLAG_40000000 | HUD_ELEMENT_FLAG_NO_FOLD | HUD_ELEMENT_FLAG_TRANSFORM);
}
void hud_element_set_transform_pos(s32 id, f32 x, f32 y, f32 z) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = element->hudTransform;
if (element->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
transform->pos.x = x;
transform->pos.y = y;
transform->pos.z = z;
}
}
void hud_element_set_transform_scale(s32 id, f32 x, f32 y, f32 z) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = element->hudTransform;
if (element->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
transform->scale.x = x;
transform->scale.y = y;
transform->scale.z = z;
}
}
void hud_element_set_transform_rotation(s32 id, f32 x, f32 y, f32 z) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = element->hudTransform;
if (element->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
transform->rot.x = x;
transform->rot.y = y;
transform->rot.z = z;
}
}
void hud_element_set_transform_rotation_pivot(s32 id, s32 dx, s32 dy) {
HudElement* element = (*gHudElements)[id & ~HUD_ELEMENT_BATTLE_ID_MASK];
HudTransform* transform = element->hudTransform;
if (element->flags & HUD_ELEMENT_FLAG_TRANSFORM) {
transform->pivot.x = dx;
transform->pivot.y = dy;
}
}
void copy_world_hud_element_ref_to_battle(s32 worldID, s32 battleID) {
gHudElementsBattle[battleID & ~HUD_ELEMENT_BATTLE_ID_MASK] = gHudElementsWorld[worldID & ~HUD_ELEMENT_BATTLE_ID_MASK];
}
void hud_element_set_aux_cache(void* base, s32 size) {
gHudElementAuxCache = (u8*)base;
if (base == NULL) {
gHudElementCacheCapacity = 0x11000;
} else {
gHudElementCacheCapacity = size;
}
}