From f6e5303ea2b8f0b8aa78d03492575c072af65aca Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 15 Jun 2025 21:22:07 +0200 Subject: [PATCH] d_snd_anim_sound OK --- config/SOUE01/symbols.txt | 66 ++++----- configure.py | 2 +- include/d/snd/d_snd_anim_sound.h | 30 +++++ include/d/snd/d_snd_small_effect_mgr.h | 19 ++- include/d/snd/d_snd_source.h | 4 +- include/d/snd/d_snd_source_mgr.h | 3 + include/d/snd/d_snd_state_mgr.h | 9 ++ include/nw4r/snd/snd_AnimSound.h | 67 +++++++-- src/d/snd/d_snd_anim_sound.cpp | 73 ++++++++++ src/d/snd/{mgr => }/d_snd_mgr_unk_11.cpp | 0 src/d/snd/d_snd_small_effect_mgr.cpp | 164 +++++++++++++++++++++++ src/nw4r/snd/snd_AnimSound.cpp | 112 ++++++++-------- 12 files changed, 449 insertions(+), 100 deletions(-) create mode 100644 include/d/snd/d_snd_anim_sound.h create mode 100644 src/d/snd/d_snd_anim_sound.cpp rename src/d/snd/{mgr => }/d_snd_mgr_unk_11.cpp (100%) diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 963c921e..3e7a3786 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -20121,7 +20121,7 @@ setFlowEvent__14dSndStateMgr_cFUl = .text:0x80364FD0; // type:function size:0x50 fn_80365020 = .text:0x80365020; // type:function size:0x84 fn_803650B0 = .text:0x803650B0; // type:function size:0x6C getStageMusicDemoName = .text:0x80365120; // type:function size:0x28 -getCurrentStageMusicDemoName = .text:0x80365150; // type:function size:0x8 +getCurrentStageMusicDemoName__14dSndStateMgr_cCFv = .text:0x80365150; // type:function size:0x8 fn_80365160 = .text:0x80365160; // type:function size:0x24 fn_80365190 = .text:0x80365190; // type:function size:0x8 fn_803651A0 = .text:0x803651A0; // type:function size:0xA0 @@ -20833,13 +20833,13 @@ create__38SndMgrDisposer<20dSndSmallEffectMgr_c>Fv = .text:0x8037D880; // type:f remove__38SndMgrDisposer<20dSndSmallEffectMgr_c>Fv = .text:0x8037D8D0; // type:function size:0x10 __ct__20dSndSmallEffectMgr_cFv = .text:0x8037D8E0; // type:function size:0x9C __ct__Q34nw4r3snd11SoundHandleFv = .text:0x8037D980; // type:function size:0xC -fn_8037D990 = .text:0x8037D990; // type:function size:0x4 +initialize__20dSndSmallEffectMgr_cFv = .text:0x8037D990; // type:function size:0x4 calc__20dSndSmallEffectMgr_cFv = .text:0x8037D9A0; // type:function size:0xA0 -fn_8037DA40 = .text:0x8037DA40; // type:function size:0x18 -fn_8037DA60 = .text:0x8037DA60; // type:function size:0x70 -fn_8037DAD0 = .text:0x8037DAD0; // type:function size:0xDC -fn_8037DBB0 = .text:0x8037DBB0; // type:function size:0x98 -fn_8037DC50 = .text:0x8037DC50; // type:function size:0x70 +calcTimer__20dSndSmallEffectMgr_cFv = .text:0x8037DA40; // type:function size:0x18 +stopAllSound__20dSndSmallEffectMgr_cFl = .text:0x8037DA60; // type:function size:0x70 +stopAllSoundDemoRelated__20dSndSmallEffectMgr_cFl = .text:0x8037DAD0; // type:function size:0xDC +stopAllSoundExceptEvent__20dSndSmallEffectMgr_cFl = .text:0x8037DBB0; // type:function size:0x98 +stopAllSoundExceptEffectOrLink__20dSndSmallEffectMgr_cFl = .text:0x8037DC50; // type:function size:0x70 playSoundInternalChecked__20dSndSmallEffectMgr_cFUlPQ34nw4r3snd11SoundHandle = .text:0x8037DCC0; // type:function size:0x48 playSoundInternal__20dSndSmallEffectMgr_cFUlPQ34nw4r3snd11SoundHandle = .text:0x8037DD10; // type:function size:0x1BC playSound__20dSndSmallEffectMgr_cFUl = .text:0x8037DED0; // type:function size:0x2D0 @@ -20855,16 +20855,16 @@ playSoundAtPosition2__20dSndSmallEffectMgr_cFUlPCQ34nw4r4math4VEC3 = .text:0x803 holdBowChargeSound__20dSndSmallEffectMgr_cFf = .text:0x8037E720; // type:function size:0xEC holdFinisherPromptSound__20dSndSmallEffectMgr_cFPCQ34nw4r4math4VEC3 = .text:0x8037E810; // type:function size:0x50 playDowsingPingSound__20dSndSmallEffectMgr_cFff = .text:0x8037E860; // type:function size:0x148 -fn_8037E9B0 = .text:0x8037E9B0; // type:function size:0xC -fn_8037E9C0 = .text:0x8037E9C0; // type:function size:0x90 -fn_8037EA50 = .text:0x8037EA50; // type:function size:0x8 -fn_8037EA60 = .text:0x8037EA60; // type:function size:0x14 -fn_8037EA80 = .text:0x8037EA80; // type:function size:0x8 -fn_8037EA90 = .text:0x8037EA90; // type:function size:0x40 -fn_8037EAD0 = .text:0x8037EAD0; // type:function size:0x40 -fn_8037EB10 = .text:0x8037EB10; // type:function size:0x11C -fn_8037EC30 = .text:0x8037EC30; // type:function size:0x8 -fn_8037EC40 = .text:0x8037EC40; // type:function size:0x3C +holdDowsingNearestSound__20dSndSmallEffectMgr_cFv = .text:0x8037E9B0; // type:function size:0xC +playSirenCountdownSound__20dSndSmallEffectMgr_cFl = .text:0x8037E9C0; // type:function size:0x90 +playMinigameCountdownSound__20dSndSmallEffectMgr_cFv = .text:0x8037EA50; // type:function size:0x8 +playMinigameTimeUpSound__20dSndSmallEffectMgr_cFl = .text:0x8037EA60; // type:function size:0x14 +playMinigameStartSound__20dSndSmallEffectMgr_cFv = .text:0x8037EA80; // type:function size:0x8 +playMinigameFinishSound__20dSndSmallEffectMgr_cFv = .text:0x8037EA90; // type:function size:0x40 +playMinigameFinishWhistleSound__20dSndSmallEffectMgr_cFv = .text:0x8037EAD0; // type:function size:0x40 +playMinigameScoreUpSound__20dSndSmallEffectMgr_cFl = .text:0x8037EB10; // type:function size:0x11C +playMinigameScoreDownSound__20dSndSmallEffectMgr_cFv = .text:0x8037EC30; // type:function size:0x8 +playMinigameMusasabiSound__20dSndSmallEffectMgr_cFl = .text:0x8037EC40; // type:function size:0x3C playSkbSound__20dSndSmallEffectMgr_cFUl = .text:0x8037EC80; // type:function size:0xB0 fn_8037ED30 = .text:0x8037ED30; // type:function size:0x68 stopSounds__20dSndSmallEffectMgr_cFUlUll = .text:0x8037EDA0; // type:function size:0xA0 @@ -20936,15 +20936,15 @@ fn_80382040 = .text:0x80382040; // type:function size:0x48 fn_80382090 = .text:0x80382090; // type:function size:0x3C fn_803820D0 = .text:0x803820D0; // type:function size:0x40 fn_80382110 = .text:0x80382110; // type:function size:0x40 -fn_80382150 = .text:0x80382150; // type:function size:0x78 -fn_803821D0 = .text:0x803821D0; // type:function size:0x3C -fn_80382210 = .text:0x80382210; // type:function size:0xE8 -fn_80382300 = .text:0x80382300; // type:function size:0x28 -fn_80382330 = .text:0x80382330; // type:function size:0x7C -fn_803823B0 = .text:0x803823B0; // type:function size:0x18 -d_s_vt_0x1E0__14dSoundSource_cFv = .text:0x803823D0; // type:function size:0x8 -fn_803823E0 = .text:0x803823E0; // type:function size:0x14 -fn_80382400 = .text:0x80382400; // type:function size:0xC +__ct__15dSndAnimSound_cFP14dSoundSource_c = .text:0x80382150; // type:function size:0x78 +setData__15dSndAnimSound_cFPCv = .text:0x803821D0; // type:function size:0x3C +setFrame__15dSndAnimSound_cFf = .text:0x80382210; // type:function size:0xE8 +setRate__15dSndAnimSound_cFf = .text:0x80382300; // type:function size:0x28 +resetFrame__15dSndAnimSound_cFf = .text:0x80382330; // type:function size:0x7C +animCallback__15dSndAnimSound_cFilPCciPv = .text:0x803823B0; // type:function size:0x18 +onAnimSoundEvent__14dSoundSource_cFi = .text:0x803823D0; // type:function size:0x8 scope:weak +setCallback__15dSndAnimSound_cFP14dSoundSource_c = .text:0x803823E0; // type:function size:0x14 +setCallback__15dSndAnimSound_cFPFilPCciPv_vPv = .text:0x80382400; // type:function size:0xC fn_80382410 = .text:0x80382410; // type:function size:0xC0 fn_803824D0 = .text:0x803824D0; // type:function size:0x24 fn_80382500 = .text:0x80382500; // type:function size:0x90 @@ -21003,8 +21003,8 @@ fn_803852B0 = .text:0x803852B0; // type:function size:0x3C fn_803852F0 = .text:0x803852F0; // type:function size:0x3C fn_80385330 = .text:0x80385330; // type:function size:0x94 fn_803853D0 = .text:0x803853D0; // type:function size:0xA0 -fn_80385470 = .text:0x80385470; // type:function size:0x78 -fn_803854F0 = .text:0x803854F0; // type:function size:0x94 +stopAllSound__15dSndSourceMgr_cFv = .text:0x80385470; // type:function size:0x78 +stopAllNonPlayerSound__15dSndSourceMgr_cFv = .text:0x803854F0; // type:function size:0x94 fn_80385590 = .text:0x80385590; // type:function size:0x74 fn_80385610 = .text:0x80385610; // type:function size:0x4 fn_80385620 = .text:0x80385620; // type:function size:0x4 @@ -21656,7 +21656,7 @@ fn_8039A7E0 = .text:0x8039A7E0; // type:function size:0x38 fn_8039A820 = .text:0x8039A820; // type:function size:0x8 fn_8039A830 = .text:0x8039A830; // type:function size:0x8 fn_8039A840 = .text:0x8039A840; // type:function size:0x8 -pitchScaleForPitchIdx = .text:0x8039A850; // type:function size:0x2C +pitchScaleForPitchIdx__Fl = .text:0x8039A850; // type:function size:0x2C pitchScaleForPitchIdxTenths__Ff = .text:0x8039A880; // type:function size:0x58 pitchIdxTenthsForPitchScale__Ff = .text:0x8039A8E0; // type:function size:0x80 KPRInitRegionUS = .text:0x8039A960; // type:function size:0x10 @@ -49103,10 +49103,10 @@ lbl_8057DB3C = .sdata2:0x8057DB3C; // type:object size:0x4 align:4 data:float lbl_8057DB40 = .sdata2:0x8057DB40; // type:object size:0x4 align:4 data:float lbl_8057DB48 = .sdata2:0x8057DB48; // type:object size:0x4 data:4byte lbl_8057DB4C = .sdata2:0x8057DB4C; // type:object size:0x4 align:4 data:float -lbl_8057DB50 = .sdata2:0x8057DB50; // type:object size:0x4 align:4 data:float -lbl_8057DB54 = .sdata2:0x8057DB54; // type:object size:0x4 align:4 data:float -lbl_8057DB58 = .sdata2:0x8057DB58; // type:object size:0x4 align:4 data:float -lbl_8057DB60 = .sdata2:0x8057DB60; // type:object size:0x8 align:8 data:double +@2557 = .sdata2:0x8057DB50; // type:object size:0x4 scope:local align:4 data:float +@2558 = .sdata2:0x8057DB54; // type:object size:0x4 scope:local align:4 data:float +@2582 = .sdata2:0x8057DB58; // type:object size:0x4 scope:local align:4 data:float +@2585 = .sdata2:0x8057DB60; // type:object size:0x8 scope:local align:8 data:double lbl_8057DB68 = .sdata2:0x8057DB68; // type:object size:0x8 lbl_8057DB70 = .sdata2:0x8057DB70; // type:object size:0x8 lbl_8057DB78 = .sdata2:0x8057DB78; // type:object size:0x8 diff --git a/configure.py b/configure.py index f6585aee..a6af268e 100644 --- a/configure.py +++ b/configure.py @@ -761,7 +761,7 @@ config.libs = [ Object(NonMatching, "d/snd/d_snd_bgm_mml_parsers.cpp"), Object(NonMatching, "d/snd/d_snd_small_effect_mgr.cpp"), Object(NonMatching, "d/snd/d_snd_harp_mgr.cpp"), - Object(NonMatching, "d/snd/d_snd_anim_sound.cpp"), + Object(Matching, "d/snd/d_snd_anim_sound.cpp"), Object(NonMatching, "d/snd/d_snd_source_mgr.cpp"), Object(NonMatching, "d/snd/d_snd_source_group.cpp"), Object(NonMatching, "d/snd/d_snd_source.cpp"), diff --git a/include/d/snd/d_snd_anim_sound.h b/include/d/snd/d_snd_anim_sound.h new file mode 100644 index 00000000..c54a49e9 --- /dev/null +++ b/include/d/snd/d_snd_anim_sound.h @@ -0,0 +1,30 @@ +#ifndef D_SND_ANIM_SOUND_H +#define D_SND_ANIM_SOUND_H + +#include "d/snd/d_snd_types.h" +#include "nw4r/snd/snd_AnimSound.h" + +// Could also inherit from AnimSound +class dSndAnimSound_c { +public: + dSndAnimSound_c(dSoundSource_c *source); + void setData(const void *data); + void setFrame(f32 frame); + void resetFrame(f32 frame); + void setRate(f32 rate); + + void setCallback(dSoundSource_c *source); + void setCallback(nw4r::snd::AnimSound::Callback cb, void *userData); + +private: + static void animCallback(int, s32, const char *, UNKWORD, void *userData); + + /* 0x00 */ nw4r::snd::AnimSound mSound; + /* 0x90 */ const void *mpData; + /* 0x94 */ f32 field_0x94; + /* 0x98 */ f32 field_0x98; + /* 0x9C */ bool mNeedFrameReset; + /* 0xA0 */ nw4r::snd::AnimSound::PlayDirection mDirection; +}; + +#endif diff --git a/include/d/snd/d_snd_small_effect_mgr.h b/include/d/snd/d_snd_small_effect_mgr.h index b77ec967..cb40ed80 100644 --- a/include/d/snd/d_snd_small_effect_mgr.h +++ b/include/d/snd/d_snd_small_effect_mgr.h @@ -29,7 +29,14 @@ public: dSndSmallEffectMgr_c(); + void initialize(); void calc(); + void calcTimer(); + + void stopAllSound(s32 fadeFrames); + void stopAllSoundDemoRelated(s32 fadeFrames); // TODO: better name + void stopAllSoundExceptEvent(s32 fadeFrames); + void stopAllSoundExceptEffectOrLink(s32 fadeFrames); bool playSound(u32 soundId); // used for clawshots cursor, pan depends on where on the screen @@ -47,7 +54,17 @@ public: bool playDowsingPingSound(f32 volume, f32 pitch); bool holdDowsingNearestSound(); - + + bool playSirenCountdownSound(s32 timer); + bool playMinigameCountdownSound(); + bool playMinigameTimeUpSound(s32 timer); + bool playMinigameStartSound(); + bool playMinigameFinishSound(); + bool playMinigameFinishWhistleSound(); + bool playMinigameScoreUpSound(s32 param); + bool playMinigameScoreDownSound(); + bool playMinigameMusasabiSound(s32 count); + bool playSkbSound(u32 soundId); bool playButtonPressSoundWhenAdvancingTextBoxes(f32); diff --git a/include/d/snd/d_snd_source.h b/include/d/snd/d_snd_source.h index a2851e76..68429f14 100644 --- a/include/d/snd/d_snd_source.h +++ b/include/d/snd/d_snd_source.h @@ -63,7 +63,9 @@ public: virtual void d_s_vt_0x1D4(); virtual void d_s_vt_0x1D8(); virtual void d_s_vt_0x1DC(); - virtual void d_s_vt_0x1E0(); + virtual void onAnimSoundEvent(UNKWORD arg) { + field_0x154 = arg; + } virtual void d_s_vt_0x1E4(); virtual u32 d_s_vt_0x1E8(u32 soundId); diff --git a/include/d/snd/d_snd_source_mgr.h b/include/d/snd/d_snd_source_mgr.h index 272c75a2..fa890401 100644 --- a/include/d/snd/d_snd_source_mgr.h +++ b/include/d/snd/d_snd_source_mgr.h @@ -26,6 +26,9 @@ public: return GetInstance()->mpBoomerangSource; } + void stopAllSound(); + void stopAllNonPlayerSound(); + private: static bool isCertainEnemyType(dSoundSource_c *source); void removeSourceFromList(dSoundSource_c *source, nw4r::ut::List *list); diff --git a/include/d/snd/d_snd_state_mgr.h b/include/d/snd/d_snd_state_mgr.h index 7a5356a4..bb068732 100644 --- a/include/d/snd/d_snd_state_mgr.h +++ b/include/d/snd/d_snd_state_mgr.h @@ -36,6 +36,10 @@ public: static bool isInStage(const char *stageName); + s32 getStageId_0x044() const { + return field_0x044; + } + u32 getField_0x11C() const { return field_0x11C; } @@ -62,6 +66,11 @@ public: void setFlowEvent(u32 eventId); + const char *getCurrentStageMusicDemoName() const; + bool isInDemo() const { + return getCurrentStageMusicDemoName() != nullptr; + } + private: u32 getStageTypeFlags(const char *stageName) const; // ET, FS, or corresponding Sky Keep rooms diff --git a/include/nw4r/snd/snd_AnimSound.h b/include/nw4r/snd/snd_AnimSound.h index 37d66c2f..e8c6627b 100644 --- a/include/nw4r/snd/snd_AnimSound.h +++ b/include/nw4r/snd/snd_AnimSound.h @@ -91,7 +91,7 @@ public: bool Setup(const void *data); void Shutdown(); - void ResetFrame(f32, int); + void ResetFrame(f32, int cycle); void UpdateFrame(f32 frame, PlayDirection dir); void UpdateForward(f32 frame); void UpdateBackward(f32 frame); @@ -103,27 +103,78 @@ public: void StartEvent(const AnimEvent *, bool); void HoldEvent(const AnimEvent *, bool); void StopEvent(const AnimEvent *); - bool IsPlayableLoopCount(const nw4r::snd::detail::AnimEventFrameInfo&); + bool IsPlayableLoopCount(const nw4r::snd::detail::AnimEventFrameInfo &); + typedef void (*Callback)(int, s32, const char *, UNKWORD, void *userData); - typedef void (*Callback)(int, s32, const char *, UNKWORD, UNKWORD); + void SetCallback(Callback cb, void *userData) { + mCallback = cb; + mUserData = userData; + } + + u32 GetAnimDuration() const { + return mReader.GetAnimDuration(); + } private: /* 0x00 */ SoundStartable &mStartable; /* 0x04 */ AnimSoundFileReader mReader; - /* 0x0C */ f32 field_0x0C; + /* 0x0C */ f32 mCurrentFrame; /* 0x10 */ AnimEventPlayer *mpSounds; /* 0x14 */ int mNumSounds; /* 0x18 */ bool mIsActive; - /* 0x19 */ u8 field_0x19; - /* 0x1A */ u8 field_0x1A; - /* 0x1C */ UNKWORD field_0x1C; + /* 0x19 */ bool mNeedFrameReset; + /* 0x1A */ bool mNeedTriggerEventsAtCurrentFrame; + /* 0x1C */ int mCycleCounter; /* 0x20 */ Callback mCallback; - /* 0x24 */ UNKWORD field_0x24; + /* 0x24 */ void *mUserData; /* 0x28 */ f32 field_0x28; /* 0x2C */ f32 mVariableValue; }; } // namespace detail + +// Not sure about this one but it appears game code isn't meant to access the "detail" +// namespace so I guess some way for game code to use the above things need to exist +class AnimSound { +public: + AnimSound(SoundStartable &startable) : mImpl(startable, mPlayers, 8) {} + + enum PlayDirection { + FORWARD, + BACKWARD, + }; + + typedef void (*Callback)(int, s32, const char *, UNKWORD, void *userData); + + bool Setup(const void *data) { + return mImpl.Setup(data); + } + + void UpdateFrame(f32 frame, PlayDirection dir) { + mImpl.UpdateFrame(frame, (detail::AnimSoundImpl::PlayDirection)dir); + } + + void ResetFrame(f32 frame, int cycle) { + mImpl.ResetFrame(frame, cycle); + } + + void Shutdown() { + mImpl.Shutdown(); + } + + void SetCallback(Callback cb, void *userData) { + mImpl.SetCallback(cb, userData); + } + + u32 GetAnimDuration() const { + return mImpl.GetAnimDuration(); + } + +private: + /* 0x00 */ detail::AnimSoundImpl mImpl; + /* 0x30 */ detail::AnimEventPlayer mPlayers[8]; +}; + } // namespace snd } // namespace nw4r diff --git a/src/d/snd/d_snd_anim_sound.cpp b/src/d/snd/d_snd_anim_sound.cpp new file mode 100644 index 00000000..3353a9ee --- /dev/null +++ b/src/d/snd/d_snd_anim_sound.cpp @@ -0,0 +1,73 @@ +#include "d/snd/d_snd_anim_sound.h" + +#include "common.h" +#include "d/snd/d_snd_source.h" + +#include + +dSndAnimSound_c::dSndAnimSound_c(dSoundSource_c *source) + : mSound(*source), mpData(nullptr), field_0x94(1.0f), field_0x98(INFINITY), mNeedFrameReset(false) {} + +void dSndAnimSound_c::setData(const void *data) { + mDirection = nw4r::snd::AnimSound::FORWARD; + field_0x94 = 1.0f; + if (data == mpData) { + return; + } + + mpData = data; + if (mpData != nullptr) { + mNeedFrameReset = true; + mSound.Setup(data); + } else { + mSound.Shutdown(); + } +} + +void dSndAnimSound_c::setFrame(f32 frame) { + if (mpData == nullptr) { + mSound.Shutdown(); + return; + } + if (frame >= mSound.GetAnimDuration()) { + return; + } + if (mNeedFrameReset) { + if (frame <= field_0x98) { + mSound.ResetFrame(0.0f, 0); + } else { + mSound.ResetFrame(frame, 0); + } + mNeedFrameReset = false; + } + mSound.UpdateFrame(frame, mDirection); +} + +void dSndAnimSound_c::setRate(f32 rate) { + if (rate < 0.0f) { + mDirection = nw4r::snd::AnimSound::BACKWARD; + } else { + mDirection = nw4r::snd::AnimSound::FORWARD; + } + field_0x94 = rate; +} + +void dSndAnimSound_c::resetFrame(f32 frame) { + if (mpData == nullptr || mSound.GetAnimDuration() <= frame) { + return; + } + mNeedFrameReset = false; + mSound.ResetFrame(frame, 0); +} + +void dSndAnimSound_c::animCallback(int, s32, const char *, UNKWORD arg, void *userData) { + reinterpret_cast(userData)->onAnimSoundEvent(arg); +} + +void dSndAnimSound_c::setCallback(dSoundSource_c *source) { + mSound.SetCallback(&animCallback, source); +} + +void dSndAnimSound_c::setCallback(nw4r::snd::AnimSound::Callback cb, void *userData) { + mSound.SetCallback(cb, userData); +} diff --git a/src/d/snd/mgr/d_snd_mgr_unk_11.cpp b/src/d/snd/d_snd_mgr_unk_11.cpp similarity index 100% rename from src/d/snd/mgr/d_snd_mgr_unk_11.cpp rename to src/d/snd/d_snd_mgr_unk_11.cpp diff --git a/src/d/snd/d_snd_small_effect_mgr.cpp b/src/d/snd/d_snd_small_effect_mgr.cpp index b100b8e8..eaf02c1b 100644 --- a/src/d/snd/d_snd_small_effect_mgr.cpp +++ b/src/d/snd/d_snd_small_effect_mgr.cpp @@ -2,6 +2,7 @@ #include "common.h" #include "d/snd/d_snd_bgm_mgr.h" +#include "d/snd/d_snd_calc_pitch.h" #include "d/snd/d_snd_checkers.h" #include "d/snd/d_snd_control_player_mgr.h" #include "d/snd/d_snd_distant_sound_actor_pool.h" @@ -9,6 +10,9 @@ #include "d/snd/d_snd_player_mgr.h" #include "d/snd/d_snd_source.h" #include "d/snd/d_snd_source_enums.h" +#include "d/snd/d_snd_source_mgr.h" +#include "d/snd/d_snd_stage_data.h" +#include "d/snd/d_snd_state_mgr.h" #include "d/snd/d_snd_util.h" #include "d/snd/d_snd_wzsound.h" #include "egg/audio/eggAudioRmtSpeakerMgr.h" @@ -29,6 +33,10 @@ dSndSmallEffectMgr_c::dSndSmallEffectMgr_c() } } +void dSndSmallEffectMgr_c::initialize() { + resetButtonPressSound(); +} + void dSndSmallEffectMgr_c::calc() { if (!dSndPlayerMgr_c::GetInstance()->checkFlag(0x4)) { for (int i = 0; i < NUM_DELAYED_SOUNDS; i++) { @@ -43,6 +51,72 @@ void dSndSmallEffectMgr_c::calc() { } } +void dSndSmallEffectMgr_c::calcTimer() { + if (field_0x10 <= 0) { + return; + } + field_0x10--; +} + +void dSndSmallEffectMgr_c::stopAllSound(s32 fadeFrames) { + field_0x10 = fadeFrames; + for (s32 i = dSndPlayerMgr_c::PLAYER_SMALL_IMPORTANT; i <= dSndControlPlayerMgr_c::sPlayerMax; i++) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(fadeFrames); + } + dSndSourceMgr_c::GetInstance()->stopAllSound(); +} + +void dSndSmallEffectMgr_c::stopAllSoundDemoRelated(s32 fadeFrames) { + field_0x10 = fadeFrames; + if (dSndStateMgr_c::GetInstance()->isInDemo()) { + for (s32 i = dSndPlayerMgr_c::PLAYER_SMALL_NORMAL; i <= dSndControlPlayerMgr_c::sPlayerMax; i++) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(fadeFrames); + } + dSndSourceMgr_c::GetInstance()->stopAllSound(); + } else { + dSndControlPlayerMgr_c::GetInstance() + ->getPlayer1(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL) + ->StopAllSound(fadeFrames); + + for (s32 i = dSndPlayerMgr_c::PLAYER_LINK_EQUIPMENT; i <= dSndControlPlayerMgr_c::sPlayerMax; i++) { + if ((u32)i != dSndPlayerMgr_c::PLAYER_AREA) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(fadeFrames); + } + } + dSndSourceMgr_c::GetInstance()->stopAllNonPlayerSound(); + } +} + +void dSndSmallEffectMgr_c::stopAllSoundExceptEvent(s32 fadeFrames) { + field_0x10 = fadeFrames; + for (u32 i = dSndPlayerMgr_c::PLAYER_SMALL_NORMAL; (s32)i <= dSndControlPlayerMgr_c::sPlayerMax; i++) { + if (i == dSndPlayerMgr_c::PLAYER_LINK_VOICE) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(20); + } else if (i != dSndPlayerMgr_c::PLAYER_EVENT) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(fadeFrames); + } + } + dSndSourceMgr_c::GetInstance()->stopAllSound(); +} + +void dSndSmallEffectMgr_c::stopAllSoundExceptEffectOrLink(s32 fadeFrames) { + field_0x10 = fadeFrames; + for (s32 i = dSndPlayerMgr_c::PLAYER_LINK_EQUIPMENT; i <= dSndControlPlayerMgr_c::sPlayerMax; i++) { + dSndControlPlayerMgr_c::GetInstance()->getPlayer1(i)->StopAllSound(field_0x10); + } + dSndSourceMgr_c::GetInstance()->stopAllNonPlayerSound(); +} + +bool dSndSmallEffectMgr_c::playSoundInternalChecked(u32 soundId, nw4r::snd::SoundHandle *pHandle) { + // TODO + return false; +} + +bool dSndSmallEffectMgr_c::playSoundInternal(u32 soundId, nw4r::snd::SoundHandle *pHandle) { + // TODO + return false; +} + bool dSndSmallEffectMgr_c::playSound(u32 soundId) { if (soundId >= SE_S_BUTTON_CALL_L && soundId <= SE_S_PLAY_GUIDE_BUTTON_BLINK) { soundId = SE_S_BUTTON_CALL_L; @@ -153,6 +227,11 @@ bool dSndSmallEffectMgr_c::playSoundWithPan(u32 soundId, f32 pan) { return ok; } +bool dSndSmallEffectMgr_c::playSoundInternal(u32 soundId) { + // TODO + return false; +} + nw4r::snd::SoundHandle *dSndSmallEffectMgr_c::getHoldSoundHandle(u32 soundId) { // Find an existing handle holding this sound for (int i = 0; i < NUM_HOLD_SOUNDS; i++) { @@ -309,6 +388,91 @@ bool dSndSmallEffectMgr_c::holdDowsingNearestSound() { return holdSound(SE_S_DOWSING_SOUND_NEAREST, &mDowsingSoundHandle); } +bool dSndSmallEffectMgr_c::playSirenCountdownSound(s32 timer) { + bool ok = playSoundInternal(SE_S_SIREN_COUNT_DOWN); + if (ok) { + f32 pitch = 1.0f - (timer * 0.01f); + mNormalSound.SetPitch(pitch); + } + return ok; +} + +bool dSndSmallEffectMgr_c::playMinigameCountdownSound() { + return playSoundInternal(SE_S_MG_COUNT_DOWN_1); +} + +bool dSndSmallEffectMgr_c::playMinigameTimeUpSound(s32 timer) { + return playSoundInternal(timer <= 3 ? SE_S_MG_TIMEUP_COUNT_02 : SE_S_MG_TIMEUP_COUNT_01); +} + +bool dSndSmallEffectMgr_c::playMinigameStartSound() { + return playSoundInternal(SE_S_MG_START); +} + +bool dSndSmallEffectMgr_c::playMinigameFinishSound() { + dSndBgmMgr_c::GetInstance()->stopAllBgm(10); + return playSoundInternal(SE_S_MG_FINISH); +} + +bool dSndSmallEffectMgr_c::playMinigameFinishWhistleSound() { + dSndBgmMgr_c::GetInstance()->stopAllBgm(10); + return playSoundInternal(SE_S_MG_FINISH_WHISTLE); +} + +bool dSndSmallEffectMgr_c::playMinigameScoreUpSound(s32 param) { + u32 soundId = SE_S_MG_SCORE_UP; + bool ok; + switch (dSndStateMgr_c::GetInstance()->getStageId_0x044()) { + case SND_STAGE_F019r: + // Bamboo Island + ok = playSoundInternal(SE_S_MG_TAKE_SCORE_UP); + if (ok) { + f32 pitch = pitchScaleForPitchIdx(param); + mNormalSound.SetPitch(pitch); + } + return ok; + case SND_STAGE_F020: + // Sky Field + soundId = dSndMgr_c::GetInstance()->getArchive() != nullptr ? (param >> 1) + SE_S_MG_TAKE_SCORE_UP : + SE_S_MG_DIVING_SCORE_01; + break; + case SND_STAGE_F211: + // Thrill Digger + soundId = SE_S_BE_GET_RUPEE; + break; + case SND_STAGE_F000: + // Skyloft (Pumpkin Archery) + if (param >= 50) { + soundId = SE_S_MG_PUMP_SHOT_SCORE_UP_50; + } else if (param >= 40) { + soundId = SE_S_MG_PUMP_SHOT_SCORE_UP_40; + } else if (param >= 30) { + soundId = SE_S_MG_PUMP_SHOT_SCORE_UP_30; + } else if (param >= 20) { + soundId = SE_S_MG_PUMP_SHOT_SCORE_UP_20; + } else { + soundId = SE_S_MG_PUMP_SHOT_SCORE_UP_10; + } + break; + } + return playSoundInternal(soundId); +} + +bool dSndSmallEffectMgr_c::playMinigameScoreDownSound() { + return playSoundInternal(SE_S_MG_SCORE_DOWN); +} + +bool dSndSmallEffectMgr_c::playMinigameMusasabiSound(s32 count) { + if (count < 0) { + count = 0; + } else if (count > 10) { + count = 10; + } + return playSoundInternal( + dSndMgr_c::GetInstance()->getArchive() != nullptr ? count + SE_S_MG_MUSASABI_01 : SE_S_MG_MUSASABI_01 + ); +} + bool dSndSmallEffectMgr_c::playSkbSound(u32 soundId) { switch (soundId) { case SE_S_SK_POINT: diff --git a/src/nw4r/snd/snd_AnimSound.cpp b/src/nw4r/snd/snd_AnimSound.cpp index 91f80368..05ec3ef8 100644 --- a/src/nw4r/snd/snd_AnimSound.cpp +++ b/src/nw4r/snd/snd_AnimSound.cpp @@ -19,11 +19,11 @@ AnimSoundImpl::AnimSoundImpl(SoundStartable &startable, AnimEventPlayer *player, : mStartable(startable), mpSounds(player), mNumSounds(numSounds), - field_0x0C(0.0f), + mCurrentFrame(0.0f), mIsActive(false), - field_0x19(0), - field_0x1A(0), - field_0x1C(0), + mNeedFrameReset(false), + mNeedTriggerEventsAtCurrentFrame(false), + mCycleCounter(0), mCallback(NULL), field_0x28(1.0f) {} @@ -37,10 +37,10 @@ bool AnimSoundImpl::Setup(const void *data) { return false; } - field_0x19 = 1; + mNeedFrameReset = true; mIsActive = true; - field_0x0C = 0.0f; - field_0x1C = 0; + mCurrentFrame = 0.0f; + mCycleCounter = 0; return true; } @@ -58,10 +58,10 @@ void AnimSoundImpl::Shutdown() { } void AnimSoundImpl::ResetFrame(f32 f, int i) { - field_0x0C = f; - field_0x1C = i; - field_0x1A = 1; - field_0x19 = 0; + mCurrentFrame = f; + mCycleCounter = i; + mNeedTriggerEventsAtCurrentFrame = true; + mNeedFrameReset = false; } void AnimSoundImpl::UpdateFrame(f32 frame, PlayDirection dir) { @@ -69,48 +69,48 @@ void AnimSoundImpl::UpdateFrame(f32 frame, PlayDirection dir) { mpSounds[i].UpdateFrame(); } - if (field_0x19) { + if (mNeedFrameReset) { if (dir == FORWARD) { ResetFrame(0.0f, 0); } else { u32 duration = mReader.GetAnimDuration(); ResetFrame(duration - 1.0f, 0); } - field_0x19 = false; + mNeedFrameReset = false; } - mVariableValue = (frame - field_0x0C) / field_0x28; + mVariableValue = (frame - mCurrentFrame) / field_0x28; if (dir == FORWARD) { UpdateForward(frame); } else { UpdateBackward(frame); } - field_0x0C = frame; - field_0x1A = false; + mCurrentFrame = frame; + mNeedTriggerEventsAtCurrentFrame = false; } void AnimSoundImpl::UpdateForward(f32 frame) { - s32 duration = std::floorf(field_0x0C); - s32 iFrame = std::floorf(frame); + s32 currFrameFloor = std::floorf(mCurrentFrame); + s32 targetFrame = std::floorf(frame); - if (field_0x1A && field_0x0C == duration) { - duration -= 1; + if (mNeedTriggerEventsAtCurrentFrame && mCurrentFrame == currFrameFloor) { + currFrameFloor -= 1; } - if (duration == iFrame) { + if (currFrameFloor == targetFrame) { return; } - s32 loopFrame = duration + 1; + s32 loopFrame = currFrameFloor + 1; while (true) { if (loopFrame == mReader.GetAnimDuration()) { loopFrame -= mReader.GetAnimDuration(); - field_0x1C++; + mCycleCounter++; } UpdateOneFrame(loopFrame, FORWARD); - if (loopFrame == iFrame) { + if (loopFrame == targetFrame) { break; } loopFrame++; @@ -118,35 +118,35 @@ void AnimSoundImpl::UpdateForward(f32 frame) { } void AnimSoundImpl::UpdateBackward(f32 frame) { - s32 duration = std::ceilf(field_0x0C); - s32 iFrame = std::ceilf(frame); + s32 currFrameCeil = std::ceilf(mCurrentFrame); + s32 targetFrame = std::ceilf(frame); - if (duration >= mReader.GetAnimDuration()) { - duration -= mReader.GetAnimDuration(); + if (currFrameCeil >= mReader.GetAnimDuration()) { + currFrameCeil -= mReader.GetAnimDuration(); } - if (iFrame >= mReader.GetAnimDuration()) { - iFrame -= mReader.GetAnimDuration(); + if (targetFrame >= mReader.GetAnimDuration()) { + targetFrame -= mReader.GetAnimDuration(); } - if (field_0x1A && field_0x0C == duration) { - duration += 1; + if (mNeedTriggerEventsAtCurrentFrame && mCurrentFrame == currFrameCeil) { + currFrameCeil += 1; } - if (duration == iFrame) { + if (currFrameCeil == targetFrame) { return; } - s32 loopFrame = duration - 1; + s32 loopFrame = currFrameCeil - 1; while (true) { if (loopFrame == -1) { loopFrame += mReader.GetAnimDuration(); - field_0x1C--; + mCycleCounter--; } UpdateOneFrame(loopFrame, BACKWARD); - if (loopFrame == iFrame) { + if (loopFrame == targetFrame) { break; } loopFrame--; @@ -191,7 +191,7 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect if (ref->mInfo.field_0x00 == frame) { StopEvent(event); if (mCallback != NULL) { - (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } StartEvent(event, true); } @@ -199,7 +199,7 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect if (ref->mInfo.field_0x00 == frame) { StopEvent(event); if (mCallback != NULL) { - (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } StartEvent(event, true); } @@ -213,7 +213,7 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect if (u == frame) { if (mCallback != NULL) { - (mCallback)(1, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(1, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } StopEvent(event); } @@ -233,11 +233,11 @@ void AnimSoundImpl::UpdateForwardRange(const AnimEventRef *ref, s32 frame) { if (ref->mInfo.flags & 4) { if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { - (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } - if (field_0x1C < ref->mInfo.field_0x09) { + if (mCycleCounter < ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->mInfo.field_0x09) { + } else if (mCycleCounter == ref->mInfo.field_0x09) { if (frame < ref->mInfo.field_0x04) { HoldEvent(event, true); } else { @@ -246,19 +246,19 @@ void AnimSoundImpl::UpdateForwardRange(const AnimEventRef *ref, s32 frame) { } } else if ((ref->mInfo.flags & 2)) { if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { - (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } - if (field_0x1C > ref->mInfo.field_0x09) { + if (mCycleCounter > ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->mInfo.field_0x09 && ref->mInfo.field_0x00 <= frame) { + } else if (mCycleCounter == ref->mInfo.field_0x09 && ref->mInfo.field_0x00 <= frame) { HoldEvent(event, true); } } else { if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { - (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { - (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } if (ref->mInfo.field_0x00 <= frame && frame < ref->mInfo.field_0x04) { HoldEvent(event, true); @@ -281,20 +281,20 @@ void AnimSoundImpl::UpdateBackwardRange(const AnimEventRef *ref, s32 frame) { if (ref->mInfo.flags & 4) { if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { - (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } - if (field_0x1C < ref->mInfo.field_0x09) { + if (mCycleCounter < ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->mInfo.field_0x09 && frame <= ref->mInfo.field_0x04) { + } else if (mCycleCounter == ref->mInfo.field_0x09 && frame <= ref->mInfo.field_0x04) { HoldEvent(event, true); } } else if ((ref->mInfo.flags & 2)) { if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { - (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } - if (field_0x1C > ref->mInfo.field_0x09) { + if (mCycleCounter > ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->mInfo.field_0x09) { + } else if (mCycleCounter == ref->mInfo.field_0x09) { if (ref->mInfo.field_0x00 < frame) { HoldEvent(event, true); } else { @@ -303,10 +303,10 @@ void AnimSoundImpl::UpdateBackwardRange(const AnimEventRef *ref, s32 frame) { } } else { if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { - (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { - (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); + (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, mUserData); } if (ref->mInfo.field_0x00 < frame && frame <= ref->mInfo.field_0x04) { HoldEvent(event, true); @@ -388,7 +388,7 @@ bool AnimSoundImpl::IsPlayableLoopCount(const nw4r::snd::detail::AnimEventFrameI return true; } int i1 = ut::Max((int)ref.field_0x09, 0); - int i2 = ut::Abs(field_0x1C); + int i2 = ut::Abs(mCycleCounter); if (ref.field_0x0A == 0) { if (i2 < i1) { return false;