From 1fbcf6833c9f8767c98f72f4d05af37ca9d807f6 Mon Sep 17 00:00:00 2001 From: bismurphy Date: Fri, 20 Sep 2024 21:16:21 -0400 Subject: [PATCH] Decompile ST0 EntityRelicOrb (#1633) First working version of this. Next steps will involve doing #ifdef to unify the function, but wanted to start by getting something in that matches by itself. --- config/splat.us.stst0.yaml | 5 +- config/symbols.us.stst0.txt | 1 - src/st/entity_relic_orb.h | 2 +- src/st/st0/37308.c | 238 +++++++++++++++++++++++++++++++++++- 4 files changed, 242 insertions(+), 4 deletions(-) diff --git a/config/splat.us.stst0.yaml b/config/splat.us.stst0.yaml index 65decfc72..a638187da 100644 --- a/config/splat.us.stst0.yaml +++ b/config/splat.us.stst0.yaml @@ -50,6 +50,8 @@ segments: - [0x1990, .data, st_common] - [0x1B90, .data, e_collect] - [0x1E3C, data] + - [0x1E5C, .data, 37308] + - [0x1EA0, data] - [0x2060, .data, rooms] - [0x2084, data] - [0x26B8, .data, e_layout] # layout entries data @@ -81,7 +83,8 @@ segments: - [0x27C84, .rodata, e_collect] # c_HeartPrizes - [0x27C8C, .rodata, e_collect] - [0x27CAC, .rodata, e_collect] # EntityEquipItemDrop - - [0x27CC4, rodata] + - [0x27CC4, .rodata, 37308] + - [0x27CFC, rodata] - [0x27D3C, .rodata, prim_helpers] - [0x27D44, .rodata, 3D8F0] - [0x27D64, c] diff --git a/config/symbols.us.stst0.txt b/config/symbols.us.stst0.txt index ac24f77d8..9aa2f3405 100644 --- a/config/symbols.us.stst0.txt +++ b/config/symbols.us.stst0.txt @@ -67,4 +67,3 @@ EntityClockTower3D = 0x801BB2AC; EntityCutscenePhotograph = 0x801BB764; EntityCutscenePhotographFire = 0x801BC4D0; EntityBackgroundVortex = 0x801BE1B4; -g_ItemIconSlots = 0x801C2584; diff --git a/src/st/entity_relic_orb.h b/src/st/entity_relic_orb.h index 380cc4c40..0ca51653d 100644 --- a/src/st/entity_relic_orb.h +++ b/src/st/entity_relic_orb.h @@ -236,7 +236,7 @@ void EntityRelicOrb(Entity* self) { msg = g_RelicOrbTexts[0]; } else { ch = (ch << 8) | *msg++; - chPixSrc = g_api_func_80106A28(ch, 1); + chPixSrc = g_api.func_80106A28(ch, 1); if (chPixSrc != NULL) { chPixDst = &D_801997E8[msgLen * 0x30]; for (i = 0; i < 0x30; i++) { diff --git a/src/st/st0/37308.c b/src/st/st0/37308.c index a59bd0843..d7b05ba2a 100644 --- a/src/st/st0/37308.c +++ b/src/st/st0/37308.c @@ -3,7 +3,243 @@ #include "st0.h" #include "sfx.h" -INCLUDE_ASM("st/st0/nonmatchings/37308", func_801B7308); +const char* g_RelicOrbTexts[] = {"を入手した"}; +s16 g_RelicOrbTextBg1EY[] = {16, 12, 8, 4, 0, -4, -8, -12}; +s16 g_RelicOrbTextBg1SY[] = {-32, -26, -20, -13, -7, -1, 5, 12}; +s16 g_RelicOrbTextBg2SY[] = {-16, -12, -8, -4, 0, 4, 8, 12}; +s16 g_RelicOrbTextBg2EY[] = {32, 26, 20, 13, 7, 1, -5, -12}; + +extern u16 D_801C00B0[0x600]; + +void EntityRelicOrb(Entity* self) { + // prim 0: green rectangle for Obtained text bg + // prim 1: blue rectangle for Obtained text bg + + const int MaxItemSlots = LEN(g_ItemIconSlots); + + u16 relicId; + u16 temp; + + RECT rect; + Primitive* prim; + const char* msg; + s32 primIndex; + s16 iconSlot; + s32 i; + u8* chPix; + u16 var_s8; + u16 msgLen; + + u16 vramX; + u16* chPixSrc; + u16* chPixDst; + u16 ch; + s16 left, top, right, bottom; + + relicId = self->params & 0x7FFF; + if (self->step && self->step < 5 && self->hitFlags) { + self->step = 5; + } + + switch (self->step) { + case 0: + InitializeEntity(g_InitializeData0); + for (iconSlot = 0; iconSlot < MaxItemSlots; iconSlot++) { + if (!g_ItemIconSlots[iconSlot]) { + break; + } + } + + if (iconSlot >= MaxItemSlots) { + self->step = 0; + return; + } + + primIndex = g_api.AllocPrimitives(PRIM_GT4, 3); + if (primIndex == -1) { + self->step = 0; + return; + } + self->flags |= FLAG_HAS_PRIMS; + self->primIndex = primIndex; + g_api.LoadEquipIcon(g_api.equipDefs[relicId].icon, + g_api.equipDefs[relicId].iconPalette, iconSlot); + prim = &g_PrimBuf[primIndex]; + for (i = 0; prim != NULL; i++) { + if (i != 0) { + prim->type = PRIM_G4; + prim->drawMode = DRAW_HIDE; + } else { + prim->tpage = 0x1A; + prim->clut = iconSlot + 0x1D0; + // Pulls iconSlot & 0b00111 + prim->u0 = prim->u2 = ((iconSlot & 7) << 4) + 1; + prim->u1 = prim->u3 = prim->u0 + 14; + // Pulls iconSlot & 0b11000 + prim->v0 = prim->v1 = ((iconSlot & 24) << 1) + 0x81; + prim->v2 = prim->v3 = prim->v0 + 14; + prim->drawMode = DRAW_UNK02; + } + prim->priority = 0xC0; + prim = prim->next; + } + + break; + + case 5: + g_api.PlaySfx(SFX_UNK_618); + + g_Status.relics[relicId] = 3; + + // Reserve space in the VRAM to store the pre-render texture with the + // "obtained" relic message + rect.x = 0; + rect.y = 256; + rect.w = 64; + rect.h = 16; + ClearImage(&rect, 0, 0, 0); + + prim = &g_PrimBuf[self->primIndex]; + for (i = 0; prim != NULL; prim = prim->next, i++) { + if (i == 0) { + prim->type = PRIM_SPRT; + prim->tpage = 0x10; + prim->x0 = 0x10; + prim->y0 = 0xA0; + prim->u0 = 0; + prim->v0 = 0; + prim->u1 = 0xF0; + prim->v1 = 0x10; + prim->clut = 0x1F8; + prim->priority = 0x1FE; + + prim->drawMode = DRAW_HIDE; + } else { + prim->x0 = prim->x1 = prim->x2 = prim->x3 = 0x80; + prim->y0 = prim->y1 = prim->y2 = prim->y3 = 0xA7; + prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0; + prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0; + prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0; + + if (i == 1) { + prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0x80; + } else { + prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0x80; + } + prim->priority = 0x1FD; + prim->drawMode = DRAW_TPAGE | DRAW_TRANSP; + } + } + + self->step++; + break; + + case 6: + msgLen = 0; + temp = false; + vramX = 0; + msg = g_api.relicDefs[relicId].name; + while (true) { + ch = *msg++; + if (ch == 0) { + if (temp) { + break; + } + temp = true; + msg = g_RelicOrbTexts[0]; + } else { + ch = (ch << 8) | *msg++; + chPixSrc = g_api.func_80106A28(ch, 1); + if (chPixSrc != NULL) { + chPixDst = &D_801C00B0[msgLen * 0x30]; + for (i = 0; i < 0x30; i++) { + *chPixDst++ = *chPixSrc++; + } + LoadTPage(&D_801C00B0[msgLen * 0x30], 0, 0, vramX, 0x100, + 0xC, 0x10); + vramX += 3; + msgLen++; + } + } + } + self->ext.relicOrb.unk7E = msgLen; + self->ext.relicOrb.unk7C = 0; + self->step++; + break; + case 7: + // Animates the blue/green rectangle for the Obtain text bg + prim = &g_PrimBuf[self->primIndex]; + prim = prim->next; + for (i = 0; prim != NULL; prim = prim->next, i++) { + if (i == 0) { + prim->x2 -= 3; + prim->x3 += 3; + prim->y0 = prim->y1 -= 4; + prim->y2 = prim->y3 += 2; + } else { + prim->x0 -= 3; + prim->x1 += 3; + prim->y0 = prim->y1 -= 2; + prim->y2 = prim->y3 += 4; + } + } + + if (++self->ext.relicOrb.unk7C == 8) { + self->ext.relicOrb.unk7C = 0; + self->step++; + } + break; + + case 8: + temp = self->ext.relicOrb.unk7C; + prim = &g_PrimBuf[self->primIndex]; + prim = prim->next; + for (i = 0; prim != NULL; prim = prim->next, i++) { + if (i == 0) { + prim->x1 = 0x80 - (temp + 1) * 0xC; + prim->x0 = 0x80 + (temp + 1) * 0xC; + prim->x2 = 0x68 + (temp * 0x78) / 7; + prim->x3 = 0x98 - (temp * 0x78) / 7; + prim->y0 = prim->y1 = g_RelicOrbTextBg1SY[temp] + 0xA7; + prim->y2 = prim->y3 = g_RelicOrbTextBg1EY[temp] + 0xA7; + prim->b2 = prim->b3 -= 0x10; + } else { + prim->x0 = 0x68 + (temp * 0x78) / 7; + prim->x1 = 0x98 - (temp * 0x78) / 7; + prim->x3 = 0x80 - (temp + 1) * 0xC; + prim->x2 = 0x80 + (temp + 1) * 0xC; + prim->y0 = prim->y1 = g_RelicOrbTextBg2SY[temp] + 0xA7; + prim->y2 = prim->y3 = g_RelicOrbTextBg2EY[temp] + 0xA7; + prim->g0 = prim->g1 -= 0x10; + } + } + + if (++self->ext.relicOrb.unk7C == 8) { + self->step++; + self->ext.relicOrb.unk7C = 0; + } + break; + + case 9: + prim = &g_PrimBuf[self->primIndex]; + prim->x0 = 0x80 - self->ext.relicOrb.unk7E * 6; + prim->drawMode = DRAW_DEFAULT; + self->ext.relicOrb.unk7C++; + if (self->ext.relicOrb.unk7C > 0x100) { + DestroyEntity(self); + return; + } + break; + } + + if (self->step < 2) { + prim = &g_PrimBuf[self->primIndex]; + prim->x0 = prim->x2 = self->posX.i.hi - 7; + prim->x1 = prim->x3 = prim->x0 + 14; + prim->y0 = prim->y1 = self->posY.i.hi - 7; + prim->y2 = prim->y3 = prim->y0 + 14; + } +} #include "../check_coll_offsets.h"