diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index f57e2ffa..dbe46c8b 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -2763,8 +2763,11 @@ d/snd/d_snd_mgr_unk_8.cpp: .text start:0x8038F2B0 end:0x8038FF18 align:16 .ctors start:0x804DB928 end:0x804DB92C -d/snd/d_snd_mgr_unk_9.cpp: +d/snd/d_snd_source_npc_head.cpp: .text start:0x8038FF20 end:0x80390298 align:16 + .data start:0x8054C3A0 end:0x8054C5A0 + .sdata start:0x805747D0 end:0x805747E8 + .sdata2 start:0x8057DDD0 end:0x8057DDD8 d/snd/d_snd_source_py_bird.cpp: .text start:0x803902A0 end:0x80390508 align:16 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index c9534025..685f5753 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -21031,7 +21031,7 @@ isPlayingActionSound__14dSoundSource_cCFv = .text:0x80385AD0; // type:function s isCurrentActionSound__14dSoundSource_cCFUl = .text:0x80385AE0; // type:function size:0x8 stopCurrentActionSound__14dSoundSource_cFv = .text:0x80385AF0; // type:function size:0x4 stopActionSound__14dSoundSource_cFUl = .text:0x80385B00; // type:function size:0x4 -vt_0xDC__14dSoundSource_cFv = .text:0x80385B10; // type:function size:0x8 +vt_0xDC__14dSoundSource_cFUl = .text:0x80385B10; // type:function size:0x8 startVoiceLine__14dSoundSource_cFUl = .text:0x80385B20; // type:function size:0x8 setCtxParam__14dSoundSource_cFPC17dSndSoundCtxParam = .text:0x80385B30; // type:function size:0x8 stopAllSound__14dSoundSource_cFl = .text:0x80385B40; // type:function size:0x8 @@ -21352,13 +21352,13 @@ fn_8038FEF0 = .text:0x8038FEF0; // type:function size:0x8 fn_8038FF00 = .text:0x8038FF00; // type:function size:0x8 fn_8038FF10 = .text:0x8038FF10; // type:function size:0x8 __ct__19dSndSourceNpcHead_cFlP9dAcBase_cPCcP17dSndSourceGroup_c = .text:0x8038FF20; // type:function size:0xC0 -fn_8038FFE0 = .text:0x8038FFE0; // type:function size:0x1E8 -fn_803901D0 = .text:0x803901D0; // type:function size:0x18 -fn_803901F0 = .text:0x803901F0; // type:function size:0x18 -fn_80390210 = .text:0x80390210; // type:function size:0xC -fn_80390220 = .text:0x80390220; // type:function size:0x58 -fn_80390280 = .text:0x80390280; // type:function size:0x8 -fn_80390290 = .text:0x80390290; // type:function size:0x8 +npcSpeak__19dSndSourceNpcHead_cFUl = .text:0x8038FFE0; // type:function size:0x1E8 +startVoiceLine__19dSndSourceNpcHead_cFUl = .text:0x803901D0; // type:function size:0x18 +vt_0xDC__19dSndSourceNpcHead_cFUl = .text:0x803901F0; // type:function size:0x18 +setOrigName__19dSndSourceNpcHead_cFPCc = .text:0x80390210; // type:function size:0xC +__dt__19dSndSourceNpcHead_cFv = .text:0x80390220; // type:function size:0x58 scope:weak +@88@__dt__19dSndSourceNpcHead_cFv = .text:0x80390280; // type:function size:0x8 scope:weak +@4@__dt__19dSndSourceNpcHead_cFv = .text:0x80390290; // type:function size:0x8 scope:weak load__18dSndSourcePyBird_cFPvPCc = .text:0x803902A0; // type:function size:0x1B0 __dt__18dSndSourcePyBird_cFv = .text:0x80390450; // type:function size:0x98 scope:weak @88@__dt__18dSndSourcePyBird_cFv = .text:0x803904F0; // type:function size:0x8 scope:weak @@ -21598,7 +21598,7 @@ postSetupSound__18dSndSourcePyBird_cFUlUlP13dSndSeSound_c = .text:0x80398DE0; // fn_80398E20 = .text:0x80398E20; // type:function size:0x4C fn_80398E70 = .text:0x80398E70; // type:function size:0x84 fn_80398F00 = .text:0x80398F00; // type:function size:0x5C -fn_80398F60 = .text:0x80398F60; // type:function size:0x9C +postSetupSound__19dSndSourceNpcHead_cFUlUlP13dSndSeSound_c = .text:0x80398F60; // type:function size:0x9C fn_80399000 = .text:0x80399000; // type:function size:0x28 fn_80399030 = .text:0x80399030; // type:function size:0x5C fn_80399090 = .text:0x80399090; // type:function size:0x84 @@ -38078,8 +38078,8 @@ __vt__25dSndSourceEquipmentWhip_c = .data:0x8054BBE8; // type:object size:0x1EC __vt__21dSndSourceEquipment_c = .data:0x8054BDD4; // type:object size:0x1EC lbl_8054BFC0 = .data:0x8054BFC0; // type:object size:0x1F0 lbl_8054C1B0 = .data:0x8054C1B0; // type:object size:0x1F0 -lbl_8054C3A0 = .data:0x8054C3A0; // type:object size:0x10 -lbl_8054C3B0 = .data:0x8054C3B0; // type:object size:0x1F0 +@9360 = .data:0x8054C3A0; // type:object size:0xC scope:local data:string +__vt__19dSndSourceNpcHead_c = .data:0x8054C3B0; // type:object size:0x1F0 @6581 = .data:0x8054C5A0; // type:object size:0xA scope:local data:string ...data.0 = .data:0x8054C5A0; // type:label scope:local @6582 = .data:0x8054C5AC; // type:object size:0xD scope:local data:string @@ -41245,16 +41245,16 @@ lbl_8057478C = .sdata:0x8057478C; // type:object size:0xC @5036 = .sdata:0x805747B8; // type:object size:0x5 scope:local data:string lbl_805747C0 = .sdata:0x805747C0; // type:object size:0x8 lbl_805747C8 = .sdata:0x805747C8; // type:object size:0x8 -lbl_805747D0 = .sdata:0x805747D0; // type:object size:0x8 -lbl_805747D8 = .sdata:0x805747D8; // type:object size:0x8 -lbl_805747E0 = .sdata:0x805747E0; // type:object size:0x4 -lbl_805747E4 = .sdata:0x805747E4; // type:object size:0x4 +@9359 = .sdata:0x805747D0; // type:object size:0x6 scope:local data:string +@9470 = .sdata:0x805747D8; // type:object size:0x6 scope:local data:string +@9471 = .sdata:0x805747E0; // type:object size:0x3 scope:local data:string +@9472 = .sdata:0x805747E4; // type:object size:0x3 scope:local data:string @6583 = .sdata:0x805747E8; // type:object size:0x6 scope:local data:string @6585 = .sdata:0x805747F0; // type:object size:0x7 scope:local data:string @6586 = .sdata:0x805747F8; // type:object size:0x6 scope:local data:string lbl_80574800 = .sdata:0x80574800; // type:object size:0x8 lbl_80574808 = .sdata:0x80574808; // type:object size:0x8 -@7595 = .sdata:0x80574810; // type:object size:0x6 scope:local +@7595 = .sdata:0x80574810; // type:object size:0x6 scope:local data:string lbl_80574818 = .sdata:0x80574818; // type:object size:0x8 lbl_80574820 = .sdata:0x80574820; // type:object size:0x8 lbl_80574828 = .sdata:0x80574828; // type:object size:0x8 @@ -49238,8 +49238,8 @@ lbl_8057DDC0 = .sdata2:0x8057DDC0; // type:object size:0x4 align:4 data:float lbl_8057DDC4 = .sdata2:0x8057DDC4; // type:object size:0x4 align:4 data:float lbl_8057DDC8 = .sdata2:0x8057DDC8; // type:object size:0x4 align:4 data:float lbl_8057DDCC = .sdata2:0x8057DDCC; // type:object size:0x4 align:4 data:float -lbl_8057DDD0 = .sdata2:0x8057DDD0; // type:object size:0x4 align:4 data:float -lbl_8057DDD4 = .sdata2:0x8057DDD4; // type:object size:0x4 align:4 data:float +@9361 = .sdata2:0x8057DDD0; // type:object size:0x4 scope:local align:4 data:float +@9362 = .sdata2:0x8057DDD4; // type:object size:0x4 scope:local align:4 data:float lbl_8057DDD8 = .sdata2:0x8057DDD8; // type:object size:0x4 align:4 data:float lbl_8057DDDC = .sdata2:0x8057DDDC; // type:object size:0x4 align:4 data:float lbl_8057DDE0 = .sdata2:0x8057DDE0; // type:object size:0x4 align:4 data:float diff --git a/configure.py b/configure.py index 1d7b39e4..0771c21c 100644 --- a/configure.py +++ b/configure.py @@ -772,7 +772,7 @@ config.libs = [ Object(Matching, "d/snd/d_snd_source_obj_clef.cpp"), Object(Matching, "d/snd/d_snd_source_equipment.cpp"), Object(NonMatching, "d/snd/d_snd_mgr_unk_8.cpp"), - Object(NonMatching, "d/snd/d_snd_mgr_unk_9.cpp"), + Object(Matching, "d/snd/d_snd_source_npc_head.cpp"), Object(Matching, "d/snd/d_snd_source_py_bird.cpp"), Object(NonMatching, "d/snd/d_snd_source_demo.cpp"), Object(NonMatching, "d/snd/d_snd_source_harp_related.cpp"), diff --git a/include/d/snd/d_snd_source.h b/include/d/snd/d_snd_source.h index 0795c848..b2a1ee49 100644 --- a/include/d/snd/d_snd_source.h +++ b/include/d/snd/d_snd_source.h @@ -173,7 +173,7 @@ public: return false; } /* 0x0D8 */ virtual bool startVoiceLine(const char *label) override; - /* 0x0DC */ virtual bool vt_0xDC() override { + /* 0x0DC */ virtual bool vt_0xDC(u32 id) override { return false; } /* 0x0E0 */ virtual void stopCurrentActionSound() override {} diff --git a/include/d/snd/d_snd_source_if.h b/include/d/snd/d_snd_source_if.h index 36244d10..2ff36728 100644 --- a/include/d/snd/d_snd_source_if.h +++ b/include/d/snd/d_snd_source_if.h @@ -87,7 +87,7 @@ public: /* 0x0D0 */ virtual bool holdSoundAtPosition(const char *label, const nw4r::math::VEC3 *position) = 0; /* 0x0D4 */ virtual bool startVoiceLine(u32 id) = 0; /* 0x0D8 */ virtual bool startVoiceLine(const char *label) = 0; - /* 0x0DC */ virtual bool vt_0xDC() = 0; + /* 0x0DC */ virtual bool vt_0xDC(u32 id) = 0; /* 0x0E0 */ virtual void stopCurrentActionSound() = 0; /* 0x0E4 */ virtual void stopActionSound(u32 id) = 0; /* 0x0E8 */ virtual bool isPlayingActionSound() const = 0; diff --git a/include/d/snd/d_snd_source_npc_head.h b/include/d/snd/d_snd_source_npc_head.h index a1da3d49..b033af2d 100644 --- a/include/d/snd/d_snd_source_npc_head.h +++ b/include/d/snd/d_snd_source_npc_head.h @@ -12,6 +12,16 @@ public: mpMainName = name; } + /* 0x0D4 */ virtual bool startVoiceLine(u32 id) override; + /* 0x0DC */ virtual bool vt_0xDC(u32 id) override; + + /* 0x180 */ virtual void setOrigName(const char *arg) override; + + // id can be a WZSound ID or an offset from LABEL_NV_START + /* 0x1EC */ virtual bool npcSpeak(u32 id); + + /* 0x1CC */ virtual void postSetupSound(u32 playingId, u32 requestedId, dSndSeSound_c *seSound) override; + private: /* 0x15C */ UNKWORD field_0x15C; /* 0x160 */ const char *mpMainName; diff --git a/src/d/snd/d_snd_source_npc_head.cpp b/src/d/snd/d_snd_source_npc_head.cpp new file mode 100644 index 00000000..33fab0a6 --- /dev/null +++ b/src/d/snd/d_snd_source_npc_head.cpp @@ -0,0 +1,80 @@ +#include "d/snd/d_snd_source_npc_head.h" + +#include "common.h" +#include "d/a/d_a_base.h" +#include "d/snd/d_snd_mgr.h" +#include "d/snd/d_snd_player_mgr.h" +#include "d/snd/d_snd_rng_mgr.h" +#include "d/snd/d_snd_source.h" +#include "d/snd/d_snd_source_group.h" +#include "d/snd/d_snd_state_mgr.h" +#include "d/snd/d_snd_util.h" +#include "d/snd/d_snd_wzsound.h" +#include "sized_string.h" + +dSndSourceNpcHead_c::dSndSourceNpcHead_c( + s32 sourceType, dAcBase_c *ac, const char *name, dSndSourceGroup_c *pOwnerGroup +) + : dSoundSource_c(sourceType, ac, name, pOwnerGroup), field_0x15C(0) { + if (dSndStateMgr_c::isInStage("F001r") && streq(name, "NpcCbFdHead") && ac->roomid == 1) { + // Fledge in Knight's Academy + pOwnerGroup->getAmbientParam()->field_0x00 = 100.0f; + pOwnerGroup->getAmbientParam()->field_0x04 = 300.0f; + } +} + +bool dSndSourceNpcHead_c::npcSpeak(u32 id) { + if (id == -1) { + return false; + } + + if (id < (LABEL_NV_END - LABEL_NV_START)) { + // turn SE_NV_123 into SE_NV_123_NpcZld + SizedString<64> nvVariantLabel; + const char *baseLabel = dSndMgr_c::getSoundLabelString(id + LABEL_NV_START); + nvVariantLabel.sprintf("%s_%s", baseLabel, mpMainName); + id = dSndPlayerMgr_c::GetInstance()->convertLabelStringToSoundId(nvVariantLabel); + if (id == -1) { + return false; + } + } else if (id < LABEL_NV_START || id >= LABEL_SE_AMBIENT_START) { + // This condition allows all the SE_TgSound sounds... + return false; + } + + // if there are _R1, _R2 variants, pick a random one + SizedString<64> label; + if (checkUserParamMask(id, 0x20)) { + label.sprintf("%s_%s", dSndMgr_c::getSoundLabelString(id), "R1"); + + if (label == dSndMgr_c::getSoundLabelString(id + 1)) { + // _R1 variant directly follows base variant + u32 randRange = 2; + + label.sprintf("%s_%s", dSndMgr_c::getSoundLabelString(id), "R2"); + if (label == dSndMgr_c::getSoundLabelString(id + 2)) { + // base, base_R1, base_R2 + randRange = 3; + } + id += dSndRngMgr_c::GetInstance()->rndInt(randRange); + } + } + + return startSound(id, nullptr); +} + +bool dSndSourceNpcHead_c::startVoiceLine(u32 id) { + a_field_0x7D = false; + return npcSpeak(id); +} + +bool dSndSourceNpcHead_c::vt_0xDC(u32 id) { + a_field_0x7D = true; + return npcSpeak(id); +} + + +void dSndSourceNpcHead_c::setOrigName(const char *arg) { + mpOrigName = arg; + mpMainName = arg; +}