From a16667b2c0dd7ffa800479ca7357f036af340859 Mon Sep 17 00:00:00 2001 From: bluisblu <53455507+bluisblu@users.noreply.github.com> Date: Fri, 28 Nov 2025 01:58:05 -0500 Subject: [PATCH 1/2] zNPCSndTable work --- src/SB/Core/gc/iSnd.h | 25 ++++ src/SB/Game/zNPCSndTable.cpp | 205 ++++++++++++++++++++++++++++-- src/SB/Game/zNPCTypeBossSandy.cpp | 37 +++--- 3 files changed, 234 insertions(+), 33 deletions(-) diff --git a/src/SB/Core/gc/iSnd.h b/src/SB/Core/gc/iSnd.h index 0455a3e54..c89738492 100644 --- a/src/SB/Core/gc/iSnd.h +++ b/src/SB/Core/gc/iSnd.h @@ -21,6 +21,30 @@ struct iSndInfo S32 lastStreamBuffer; }; +struct iSndFileInfo +{ + U32 ID; // offset 0x0 + U32 assetID; // offset 0x4 + U16 sample_rate; // offset 0x8 + U8 is_streamed; // offset 0xA + union + { + struct + { + U32 address; // offset 0x0 + U32 size; // offset 0x4 + } nonstream; // offset 0xC + struct + { + S32 file_index; // offset 0x0 + U32 lsn; // offset 0x4 + U32 data_size; // offset 0x8 + U16 stream_interleave_size; // offset 0xC + U16 stream_interleave_count; // offset 0xE + } stream; // offset 0xC + }; +}; + // Size: 0x20 // This was not in dwarf data struct vinfo @@ -62,6 +86,7 @@ U32 SampleToNybbleAddress(U32 sample); void iSndInitSceneLoaded(); S32 iSndIsPlaying(U32 assetID); S32 iSndIsPlaying(U32 assetID, U32 parid); +iSndFileInfo* iSndLookup(U32 id); void iSndWaitForDeadSounds(); void iSndSceneExit(); void sndloadcb(tag_xFile* tag); diff --git a/src/SB/Game/zNPCSndTable.cpp b/src/SB/Game/zNPCSndTable.cpp index d573fa05a..e6da1d80d 100644 --- a/src/SB/Game/zNPCSndTable.cpp +++ b/src/SB/Game/zNPCSndTable.cpp @@ -1,17 +1,25 @@ #include "zNPCSndTable.h" -#include "zNPCGoalVillager.h" +#include "iSnd.h" #include "xString.h" +#include "xutil.h" +#include "zGameExtras.h" +#include "zNPCSndLists.h" -#include +#define SND_COUNT 26 -static char* g_strz_sndgroup[26]; -static unsigned int g_hash_sndgroup[26]; -static float g_tmrz_sndplay[26]; +static U32 g_hash_sndgroup[SND_COUNT]; +static F32 g_tmrz_sndplay[SND_COUNT] = {}; +static char* g_strz_sndgroup[SND_COUNT] = { + "ListEnd", "Encounter", "Clanking", "Exclaim", "Ouch", "Cheering", "Respawn", + "Alert", "Dizzy", "Dance", "Laugh", "Attack", "Punch", "WepLaunch", + "Lightning", "WarnBang", "Death", "DeathJelly", "Bonked", "Unbonked", "TikiStack", + "TikiExplode", "TikiThunder", "XSfxTalk", "OneLiner", "OneLinerToo" +}; void NPCS_Startup() { - for (int i = 0; i < (int)(sizeof(g_strz_sndgroup) / sizeof(char*)); i++) + for (S32 i = 0; i < (S32)(sizeof(g_strz_sndgroup) / sizeof(char*)); i++) { g_hash_sndgroup[i] = xStrHash(g_strz_sndgroup[i]); } @@ -21,22 +29,26 @@ void NPCS_Shutdown() { } -int NPCS_SndOkToPlay(en_NPC_SOUND sndtype) +void NPCS_SndTimersUpdate(F32 dt) { - if (sndtype == NPC_STYP_BOGUS) + // non-matching: only producing one lfs instruction for -1.0f + for (S32 i = 0; i < SND_COUNT; i++) { - return 1; + g_tmrz_sndplay[i] = MAX(g_tmrz_sndplay[i] - dt, -1.0f); } - if (sndtype == NPC_STYP_LISTEND) +} + +void NPCS_SndTimersReset() +{ + for (S32 i = 0; i < SND_COUNT; i++) { - return 0; + g_tmrz_sndplay[i] = -1.0f; } - return g_tmrz_sndplay[sndtype] < 0.0f; } -void NPCS_SndTypePlayed(en_NPC_SOUND sndtype, float delayNext) +void NPCS_SndTypePlayed(en_NPC_SOUND sndtype, F32 delayNext) { - float tym = 2.0f; + F32 tym = 2.0f; switch (sndtype) { @@ -58,3 +70,168 @@ void NPCS_SndTypePlayed(en_NPC_SOUND sndtype, float delayNext) g_tmrz_sndplay[sndtype] = tym; } + +S32 NPCS_SndOkToPlay(en_NPC_SOUND sndtype) +{ + if (sndtype == NPC_STYP_BOGUS) + { + return 1; + } + if (sndtype == NPC_STYP_LISTEND) + { + return 0; + } + return g_tmrz_sndplay[sndtype] < 0.0f; +} + +void NPCS_SndTablePrepare(NPCSndTrax* trax) +{ + while (trax->typ_sound != NPC_STYP_LISTEND) + { + U32 sound_hash = xStrHash(trax->nam_sound); + if (sound_hash != 0 && iSndLookup(sound_hash) != NULL) + { + trax->aid_sound = sound_hash; + } + else + { + trax->aid_sound = 0; + } + trax++; + } +} + +NPCSndProp* NPCS_SndFindProps(en_NPC_SOUND sndtype) +{ + NPCSndProp* sprop = g_sndProps; + while (sprop->sndtype != NPC_STYP_LISTEND) + { + if (sprop->sndtype == sndtype) + { + break; + } + sprop++; + } + return sprop; +} + +en_NPC_SOUND NPCS_SndTypeFromHash(U32 aid_snd, NPCSndTrax* cust, NPCSndTrax* share) +{ + en_NPC_SOUND da_type = NPC_STYP_BOGUS; + NPCSndTrax* trax; + + for (S32 i = 0; i <= 3; i++) + { + if (i == 0) + { + trax = cust; + } + else if (i == 1) + { + trax = share; + } + else if (i == 2) + { + trax = g_sndTrax_General; + } + else + { + trax = g_sndTrax_Universal; + } + + if (trax != NULL) + { + for (; trax->typ_sound != NPC_STYP_LISTEND; trax = trax + 1) + { + if (trax->aid_sound == aid_snd) + { + da_type = trax->typ_sound; + + return da_type; + } + } + } + } + + return da_type; +} + +// WIP +U32 NPCS_SndPickSimilar(en_NPC_SOUND sndtype, NPCSndTrax* cust, NPCSndTrax* share) +{ + S32 cnt = 0; + S32 list[32] = {}; + F32 wts[32] = { 1.0f }; + + for (S32 si = 0; si < 4; si++) + { + NPCSndTrax* trax; + F32 weight; + + if (si == 0) + { + trax = cust; + weight = 2.0f; + } + else if (si == 1) + { + trax = share; + weight = 1.5f; + } + else + { + if (cnt >= 5) + { + trax = NULL; + weight = 0.0f; + } + else if (si == 2) + { + trax = g_sndTrax_General; + weight = 1.0f; + } + else + { + trax = g_sndTrax_Universal; + weight = 1.0f; + } + } + + if (trax == NULL) + { + continue; + } + + bool in_group = false; + for (; trax->typ_sound != NPC_STYP_LISTEND; trax++) + { + if (trax->typ_sound == sndtype) + { + in_group = true; + if (trax->aid_sound != 0 && cnt < 32) + { + wts[cnt] = weight; + list[cnt] = trax->aid_sound; + cnt++; + } + } + else if (in_group) + { + break; + } + + if (cnt >= 32) + { + break; + } + } + } + + if (cnt > 0) + { + xUtil_wtadjust(wts, cnt, 1.0f); + return xUtil_choose(list, cnt, wts); + } + + return 0; +} diff --git a/src/SB/Game/zNPCTypeBossSandy.cpp b/src/SB/Game/zNPCTypeBossSandy.cpp index c2a4452de..722fae16e 100644 --- a/src/SB/Game/zNPCTypeBossSandy.cpp +++ b/src/SB/Game/zNPCTypeBossSandy.cpp @@ -17,7 +17,6 @@ #include "xMarkerAsset.h" #include "zCamera.h" #include "zGrid.h" -#include "zAssetTypes.h" extern const char bossSandyStrings[]; @@ -146,30 +145,30 @@ xAnimTable* ZNPC_AnimTable_BossSandy() { // clang-format off S32 ourAnims[25] = { - Idle01, - Idle02, - Taunt01, - Run01, - Walk01, - Melee01, - Hit01, - Hit02, + Idle01, + Idle02, + Taunt01, + Run01, + Walk01, + Melee01, + Hit01, + Hit02, GetUp01, - Dizzy01, - ElbowDrop01, - Leap01, - Leap02, + Dizzy01, + ElbowDrop01, + Leap01, + Leap02, Leap03 , - Leap04, - Sit01, + Leap04, + Sit01, SitShock01, - CLBegin01, - CLLoop01, + CLBegin01, + CLLoop01, CLEnd01, NoHeadIdle01, - NoHeadWaving01, + NoHeadWaving01, NoHeadGetUp01, - NoHeadShotUp01, + NoHeadShotUp01, NoHeadShock01, }; // clang-format on From 1a66b43ae5657e3fd4e82c88f9ed54ea8b6f7795 Mon Sep 17 00:00:00 2001 From: bluisblu <53455507+bluisblu@users.noreply.github.com> Date: Fri, 28 Nov 2025 02:31:26 -0500 Subject: [PATCH 2/2] cleanup --- src/SB/Game/zNPCSndTable.cpp | 2 ++ src/SB/Game/zNPCSndTable.h | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/SB/Game/zNPCSndTable.cpp b/src/SB/Game/zNPCSndTable.cpp index e6da1d80d..1ad4f080f 100644 --- a/src/SB/Game/zNPCSndTable.cpp +++ b/src/SB/Game/zNPCSndTable.cpp @@ -40,6 +40,7 @@ void NPCS_SndTimersUpdate(F32 dt) void NPCS_SndTimersReset() { + // non-matching: missing lfs for -1.0f for (S32 i = 0; i < SND_COUNT; i++) { g_tmrz_sndplay[i] = -1.0f; @@ -117,6 +118,7 @@ NPCSndProp* NPCS_SndFindProps(en_NPC_SOUND sndtype) en_NPC_SOUND NPCS_SndTypeFromHash(U32 aid_snd, NPCSndTrax* cust, NPCSndTrax* share) { + // non-matching en_NPC_SOUND da_type = NPC_STYP_BOGUS; NPCSndTrax* trax; diff --git a/src/SB/Game/zNPCSndTable.h b/src/SB/Game/zNPCSndTable.h index aac481227..0a0df0d36 100644 --- a/src/SB/Game/zNPCSndTable.h +++ b/src/SB/Game/zNPCSndTable.h @@ -15,9 +15,13 @@ struct NPCSndQueue //0x14 }; void NPCS_Startup(); -void NPCS_SndTimersReset(); void NPCS_SndTimersUpdate(F32 dt); +void NPCS_SndTimersReset(); +void NPCS_SndTypePlayed(en_NPC_SOUND sndtype, F32 delayNext); +S32 NPCS_SndOkToPlay(en_NPC_SOUND sndtype); void NPCS_SndTablePrepare(NPCSndTrax* trax); +NPCSndProp* NPCS_SndFindProps(en_NPC_SOUND sndtype); +en_NPC_SOUND NPCS_SndTypeFromHash(U32 aid_snd, NPCSndTrax* cust, NPCSndTrax* share); void NPCS_Shutdown(); #endif