summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2025-05-29 15:10:23 +0200
committerrobojumper <robojumper@gmail.com>2025-05-29 15:10:29 +0200
commit8894f73305da296dd7d67036eae97865b5f29876 (patch)
tree5f68ae9cf202fa8921ddacad5a35d0802531ddd2
parent79b20186423b791b8bacb4dfbfc4ea764bbd8051 (diff)
snd_AnimSound OK
-rw-r--r--config/SOUE01/symbols.txt12
-rw-r--r--configure.py2
-rw-r--r--include/nw4r/math/math_arithmetic.h6
-rw-r--r--include/nw4r/snd/snd_AnimSound.h137
-rw-r--r--include/nw4r/snd/snd_AnimSoundReader.h62
-rw-r--r--include/nw4r/snd/snd_BasicSound.h1
-rw-r--r--include/nw4r/snd/snd_RemoteSpeakerManager.h5
-rw-r--r--include/nw4r/snd/snd_SeqSoundHandle.h6
-rw-r--r--include/nw4r/snd/snd_SoundHandle.h6
-rw-r--r--include/nw4r/snd/snd_SoundStartable.h25
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath20
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath.h9
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h2
-rw-r--r--src/REL/d/a/e/d_a_e_sm.cpp2
-rw-r--r--src/nw4r/snd/snd_AnimSound.cpp481
-rw-r--r--src/nw4r/snd/snd_AnimSoundReader.cpp4
16 files changed, 733 insertions, 47 deletions
diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt
index 8779a92f..0dfcce5d 100644
--- a/config/SOUE01/symbols.txt
+++ b/config/SOUE01/symbols.txt
@@ -49635,12 +49635,12 @@ norm_epsilon__Q34nw4r3g3d26@unnamed@g3d_calcview_cpp@ = .sdata2:0x8057EDF0; // t
@11135 = .sdata2:0x8057EEE4; // type:object size:0x4 scope:local align:4 data:float
@11136 = .sdata2:0x8057EEE8; // type:object size:0x4 scope:local align:4 data:float
@11190 = .sdata2:0x8057EEF0; // type:object size:0x4 scope:local align:4 data:float
-lbl_8057EEF8 = .sdata2:0x8057EEF8; // type:object size:0x4 align:4 data:float
-lbl_8057EEFC = .sdata2:0x8057EEFC; // type:object size:0x4 align:4 data:float
-lbl_8057EF00 = .sdata2:0x8057EF00; // type:object size:0x8 align:8 data:double
-lbl_8057EF08 = .sdata2:0x8057EF08; // type:object size:0x8 align:8 data:double
-lbl_8057EF10 = .sdata2:0x8057EF10; // type:object size:0x4 align:4 data:float
-lbl_8057EF14 = .sdata2:0x8057EF14; // type:object size:0x4 align:4 data:float
+@4352 = .sdata2:0x8057EEF8; // type:object size:0x4 scope:local align:4 data:float
+@4353 = .sdata2:0x8057EEFC; // type:object size:0x4 scope:local align:4 data:float
+@4474 = .sdata2:0x8057EF00; // type:object size:0x8 scope:local align:8 data:double
+@4600 = .sdata2:0x8057EF08; // type:object size:0x8 scope:local align:8 data:double
+@5006 = .sdata2:0x8057EF10; // type:object size:0x4 scope:local align:4 data:float
+@5007 = .sdata2:0x8057EF14; // type:object size:0x4 scope:local align:4 data:float
@2457 = .sdata2:0x8057EF18; // type:object size:0x4 scope:local align:4 data:float
@2458 = .sdata2:0x8057EF1C; // type:object size:0x4 scope:local align:4 data:float
@2523 = .sdata2:0x8057EF20; // type:object size:0x8 scope:local align:8 data:double
diff --git a/configure.py b/configure.py
index 7b6c3265..9d62279b 100644
--- a/configure.py
+++ b/configure.py
@@ -1012,7 +1012,7 @@ config.libs = [
nw4rLib(
"snd",
[
- Object(NonMatching, "nw4r/snd/snd_AnimSound.cpp"),
+ Object(Matching, "nw4r/snd/snd_AnimSound.cpp"),
Object(Matching, "nw4r/snd/snd_AnimSoundReader.cpp"),
Object(Matching, "nw4r/snd/snd_AxManager.cpp"),
Object(Matching, "nw4r/snd/snd_AxVoice.cpp"),
diff --git a/include/nw4r/math/math_arithmetic.h b/include/nw4r/math/math_arithmetic.h
index 8bd573cb..2892128b 100644
--- a/include/nw4r/math/math_arithmetic.h
+++ b/include/nw4r/math/math_arithmetic.h
@@ -5,6 +5,8 @@
#include "nw4r/types_nw4r.h" // IWYU pragma: export
#include "rvl/OS.h" // IWYU pragma: export
+#include <cmath>
+
#define NW4R_MATH_QNAN (-(0.0f / 0.0f))
#define NW4R_MATH_FLT_MAX 3.402823466e+38f
@@ -30,7 +32,7 @@ inline f32 FAbs(register f32 x) {
}
inline f32 FCeil(f32 x) {
- return ceilf(x);
+ return std::ceilf(x);
}
inline f32 FExp(f32 x) {
@@ -38,7 +40,7 @@ inline f32 FExp(f32 x) {
}
inline f32 FFloor(f32 x) {
- return floorf(x);
+ return std::floorf(x);
}
inline f32 FInv(register f32 x) {
diff --git a/include/nw4r/snd/snd_AnimSound.h b/include/nw4r/snd/snd_AnimSound.h
index 2b25ea5b..7f60bbec 100644
--- a/include/nw4r/snd/snd_AnimSound.h
+++ b/include/nw4r/snd/snd_AnimSound.h
@@ -1 +1,138 @@
/* Only implemented to the extent necessary to match data sections. */
+
+#include "nw4r/snd/snd_AnimSoundReader.h"
+#include "nw4r/snd/snd_BasicSound.h"
+#include "nw4r/snd/snd_SoundHandle.h"
+#include "nw4r/snd/snd_SoundStartable.h"
+
+// Class and non-inline function names from InazumaWii, everything else made up
+
+namespace nw4r {
+namespace snd {
+namespace detail {
+
+class AnimEventPlayer {
+public:
+ AnimEventPlayer();
+ ~AnimEventPlayer();
+
+ SoundHandle *GetHandle() {
+ return &mHandle;
+ }
+
+ bool IsAttachedSound() const {
+ return mHandle.IsAttachedSound();
+ }
+
+ bool IsCurrentEvent(const AnimEvent *event) const {
+ return event == mpEvent;
+ }
+
+ int GetPriority() const {
+ if (!IsAttachedSound()) {
+ return 0;
+ }
+ return mHandle.detail_GetAttachedSound()->GetPriority();
+ }
+
+ bool IsRunning() const {
+ return mIsRunning;
+ }
+
+ void SetRunning(bool running) {
+ mIsRunning = running;
+ }
+
+ void UpdateFrame() {
+ if (!mHandle.IsAttachedSound()) {
+ mpEvent = 0;
+ }
+ }
+
+ void Stop() {
+ if (IsAttachedSound()) {
+ mHandle.detail_GetAttachedSound()->Stop(0);
+ }
+ mpEvent = 0;
+ }
+
+ void StopEvent(const AnimEvent *event) {
+ if (mpEvent == event) {
+ Stop();
+ }
+ }
+
+ void SetVolume(f32 volume) {
+ if (IsAttachedSound()) {
+ mHandle.detail_GetAttachedSound()->SetVolume(volume, 0);
+ }
+ }
+
+ void SetPitch(f32 pitch) {
+ if (IsAttachedSound()) {
+ mHandle.detail_GetAttachedSound()->SetPitch(pitch);
+ }
+ }
+
+ bool StartSound(const AnimEvent *event, SoundStartable *startable, bool b);
+ bool HoldSound(const AnimEvent *event, SoundStartable *startable, bool b);
+ void SetVolumePitch(const AnimEvent *event, bool b);
+ void SetVariable(const AnimEvent *event, u32 varNo, f32 f);
+
+private:
+ SoundHandle mHandle; // at 0x00
+ const AnimEvent *mpEvent; // at 0x04
+ bool mIsRunning; // at 0x08
+};
+
+class AnimSoundImpl {
+public:
+ enum PlayDirection {
+ FORWARD,
+ BACKWARD,
+ };
+
+ AnimSoundImpl(SoundStartable &startable, AnimEventPlayer *player, int);
+ ~AnimSoundImpl();
+
+ bool Setup(const void *data);
+ void Shutdown();
+ void ResetFrame(f32, int);
+ void UpdateFrame(f32 frame, PlayDirection dir);
+ void UpdateForward(f32 frame);
+ void UpdateBackward(f32 frame);
+ void UpdateTrigger(const AnimEventRef *, s32, PlayDirection);
+ void UpdateForwardRange(const AnimEventRef *, s32);
+ void UpdateBackwardRange(const AnimEventRef *, s32);
+
+ void StartEvent(const AnimEvent *, bool);
+ void HoldEvent(const AnimEvent *, bool);
+ // StartEvent is not inlined, but there seems to be
+ // a corresponding StopEvent function that got inlined
+ void StopEvent(const AnimEvent *);
+
+ // Made up inlines
+ bool ShouldPlayEvent(const AnimEventRef *ref) const;
+ void UpdateEvents(s32 duration, PlayDirection direction);
+
+ typedef void (*Callback)(int, s32, const char *, UNKWORD, UNKWORD);
+
+private:
+ /* 0x00 */ SoundStartable &mStartable;
+ /* 0x04 */ AnimSoundFileReader mReader;
+ /* 0x0C */ f32 field_0x0C;
+ /* 0x10 */ AnimEventPlayer *mpSounds;
+ /* 0x14 */ int mNumSounds;
+ /* 0x18 */ bool mIsActive;
+ /* 0x19 */ u8 field_0x19;
+ /* 0x1A */ u8 field_0x1A;
+ /* 0x1C */ UNKWORD field_0x1C;
+ /* 0x20 */ Callback mCallback;
+ /* 0x24 */ UNKWORD field_0x24;
+ /* 0x28 */ f32 field_0x28;
+ /* 0x2C */ f32 mVariableValue;
+};
+
+} // namespace detail
+} // namespace snd
+} // namespace nw4r
diff --git a/include/nw4r/snd/snd_AnimSoundReader.h b/include/nw4r/snd/snd_AnimSoundReader.h
index 4ab47f21..909ffecd 100644
--- a/include/nw4r/snd/snd_AnimSoundReader.h
+++ b/include/nw4r/snd/snd_AnimSoundReader.h
@@ -5,11 +5,54 @@ namespace nw4r {
namespace snd {
namespace detail {
-struct AnimEvent {};
+struct AnimEvent {
+ u32 flags_0x00; // at 0x00
+ u32 soundId; // at 0x04
+ detail::Util::DataRef<const char> soundLabelRef; // at 0x08
+ u8 volume; // at 0x10
+ u8 field_0x11; // at 0x11
+ u8 varNo; // at 0x12
+ f32 pitch; // at 0x14
+ UNKWORD field_0x18; // at 0x18
+ UNKWORD field_0x1C; // at 0x1C
+
+ bool ShouldPreventStart() const {
+ return flags_0x00 & 1;
+ }
+
+ const char *GetSoundLabel() const {
+ return Util::GetDataRefAddress0(soundLabelRef, this);
+ }
+
+ bool GetVarNo(u32 *var) const {
+ if (ShouldSetVariable()) {
+ *var = varNo;
+ return true;
+ }
+ return false;
+ }
+
+ bool ShouldSetVariable() const {
+ return flags_0x00 & 2;
+ }
+
+ bool MatchesDirection(int playDirection) const {
+ bool ret = 0;
+ u32 config = field_0x11;
+ if ((config == 0 || (playDirection == 0 && config == 1) || (playDirection == 1 && config == 2))) {
+ ret = true;
+ }
+ return ret;
+ }
+};
struct AnimEventRef {
- u8 _0x00[0xC];
- Util::DataRef<AnimEvent> event; // at 0x08
+ int field_0x00; // at 0x08
+ int field_0x04; // at 0x04
+ u8 flags_0x08; // at 0x08
+ s8 field_0x09; // at 0x09
+ u8 field_0x0A; // at 0x0A
+ Util::DataRef<AnimEvent> event; // at 0x0C
};
struct AnimSoundFile {
@@ -27,7 +70,7 @@ struct AnimSoundFile {
struct Block {
ut::BinaryBlockHeader blockHeader; // at 0x00
- UNKWORD _0x08; // at 0x08
+ u32 duration; // at 0x08
Util::DataRef<EventTable> eventTable; // at 0x0C
};
};
@@ -43,6 +86,17 @@ public:
const AnimEventRef *GetEventRef(u32 id) const;
const AnimEvent *GetEvent(const AnimEventRef *ref) const;
+ bool IsValid() const {
+ return mpHeader != NULL;
+ }
+
+ u32 GetAnimDuration() const {
+ if (!IsValid()) {
+ return 0;
+ }
+ return mpBlock->duration;
+ }
+
private:
const AnimSoundFile::Header *mpHeader; // at 0x00
const AnimSoundFile::Block *mpBlock; // at 0x04
diff --git a/include/nw4r/snd/snd_BasicSound.h b/include/nw4r/snd/snd_BasicSound.h
index b36f3cc9..8fc57508 100644
--- a/include/nw4r/snd/snd_BasicSound.h
+++ b/include/nw4r/snd/snd_BasicSound.h
@@ -260,6 +260,7 @@ namespace nw4r { namespace snd { namespace detail
PlayerHeap *GetPlayerHeap() { return mPlayerHeap; }
SoundPlayer *GetSoundPlayer() { return mSoundPlayer; }
int GetVoiceOutCount() const;
+ int GetPriority() const { return mPriority; }
void SetPlayerPriority(int priority);
void SetInitialVolume(f32 volume);
diff --git a/include/nw4r/snd/snd_RemoteSpeakerManager.h b/include/nw4r/snd/snd_RemoteSpeakerManager.h
index 79ebd56d..2793637c 100644
--- a/include/nw4r/snd/snd_RemoteSpeakerManager.h
+++ b/include/nw4r/snd/snd_RemoteSpeakerManager.h
@@ -21,8 +21,9 @@ public:
private:
static const int SPEAKER_ALARM_HZ = 150;
- static const int SPEAKER_ALARM_PERIOD_NSEC = static_cast<int>(1.0f / SPEAKER_ALARM_HZ * 1000 * 1000 * 1000);
-
+ // commented out since it causes compiler warnings
+ // static const int SPEAKER_ALARM_PERIOD_NSEC = static_cast<int>(1.0f / SPEAKER_ALARM_HZ * 1000 * 1000 * 1000);
+ static const int SPEAKER_ALARM_PERIOD_NSEC = 6666667;
private:
RemoteSpeakerManager();
diff --git a/include/nw4r/snd/snd_SeqSoundHandle.h b/include/nw4r/snd/snd_SeqSoundHandle.h
index b5e775b2..709701ed 100644
--- a/include/nw4r/snd/snd_SeqSoundHandle.h
+++ b/include/nw4r/snd/snd_SeqSoundHandle.h
@@ -7,6 +7,7 @@
#include "common.h" // nullptr
+#include "nw4r/snd/snd_SeqSound.h"
#include "nw4r/ut/ut_NonCopyable.h" // ut::NonCopyable
/*******************************************************************************
@@ -33,6 +34,11 @@ namespace nw4r { namespace snd
void DetachSound();
+ void WriteVariable(int varNo, s16 value) {
+ if (IsAttachedSound())
+ mSound->WriteVariable(varNo, value);
+ }
+
// members
private:
/* base ut::NonCopyable */ // size 0x00, offset 0x00
diff --git a/include/nw4r/snd/snd_SoundHandle.h b/include/nw4r/snd/snd_SoundHandle.h
index 19040155..e400a441 100644
--- a/include/nw4r/snd/snd_SoundHandle.h
+++ b/include/nw4r/snd/snd_SoundHandle.h
@@ -31,8 +31,14 @@ namespace nw4r { namespace snd
void detail_AttachSound(detail::BasicSound *sound);
bool IsAttachedSound() const { return mSound != nullptr; }
detail::BasicSound *detail_GetAttachedSound() { return mSound; }
+ const detail::BasicSound *detail_GetAttachedSound() const { return mSound; }
void DetachSound();
+ void Stop() {
+ if (IsAttachedSound())
+ mSound->Stop(0);
+ }
+
u32 GetId() const
{
if (IsAttachedSound())
diff --git a/include/nw4r/snd/snd_SoundStartable.h b/include/nw4r/snd/snd_SoundStartable.h
index 5f0a70df..e92a2d02 100644
--- a/include/nw4r/snd/snd_SoundStartable.h
+++ b/include/nw4r/snd/snd_SoundStartable.h
@@ -144,35 +144,40 @@ namespace nw4r { namespace snd
const StartInfo *pStartInfo
);
- // TODO: Fix after removal of above functions
bool StartSound(SoundHandle *pHandle, u32 id) {
- return detail_StartSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_StartSound(pHandle, id, NULL) == START_SUCCESS;
+ }
+ bool StartSound(SoundHandle *pHandle, const char *label) {
+ return detail_StartSound(pHandle, label, NULL) == START_SUCCESS;
}
bool StartSound(SoundHandle *pHandle, unsigned int id) {
- return detail_StartSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_StartSound(pHandle, id, NULL) == START_SUCCESS;
}
bool StartSound(SoundHandle *pHandle, int id) {
- return detail_StartSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_StartSound(pHandle, id, NULL) == START_SUCCESS;
}
bool HoldSound(SoundHandle *pHandle, u32 id) {
- return detail_HoldSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_HoldSound(pHandle, id, NULL) == START_SUCCESS;
+ }
+ bool HoldSound(SoundHandle *pHandle, const char *label) {
+ return detail_HoldSound(pHandle, label, NULL) == START_SUCCESS;
}
bool HoldSound(SoundHandle *pHandle, unsigned int id) {
- return detail_HoldSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_HoldSound(pHandle, id, NULL) == START_SUCCESS;
}
bool HoldSound(SoundHandle *pHandle, int id) {
- return detail_HoldSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_HoldSound(pHandle, id, NULL) == START_SUCCESS;
}
bool PrepareSound(SoundHandle *pHandle, u32 id) {
- return detail_PrepareSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_PrepareSound(pHandle, id, NULL) == START_SUCCESS;
}
bool PrepareSound(SoundHandle *pHandle, unsigned int id) {
- return detail_PrepareSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_PrepareSound(pHandle, id, NULL) == START_SUCCESS;
}
bool PrepareSound(SoundHandle *pHandle, int id) {
- return detail_PrepareSound(pHandle, id, NULL, NULL, NULL) == START_SUCCESS;
+ return detail_PrepareSound(pHandle, id, NULL) == START_SUCCESS;
}
// members
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath
index 57ceb903..d6685a2a 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath
@@ -15,13 +15,13 @@ using ::atan;
using ::atan2;
using ::atan2f;
using ::ceil;
-using ::ceilf;
+// using ::ceilf;
using ::copysign;
using ::cos;
// using ::cosf;
-using ::fabsf;
+// using ::fabsf;
using ::floor;
-using ::floorf;
+// using ::floorf;
using ::fmod;
using ::fmodf;
using ::frexp;
@@ -35,18 +35,26 @@ using ::scalbn;
using ::sin;
using ::sinf;
using ::sqrt;
-using ::sqrtf;
+// using ::sqrtf;
using ::tan;
using ::tanf;
-inline float sqrt(float x) {
- return ::sqrtf(x);
+inline float ceilf(float x) {
+ return ::ceil(x);
+}
+
+inline float floorf(float x) {
+ return ::floor(x);
}
inline float cosf(float x) {
return cos(x);
}
+inline float sqrtf(float x) {
+ return ::sqrtf(x);
+}
+
// TODO: Very fake!
// inline double fabs_wrapper(double x) {
// return __fabs(x);
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath.h
index 38e4772b..4ab23c36 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath.h
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/cmath.h
@@ -3,21 +3,14 @@
namespace std {
-/* float fabs(float num) {
- return ::fabsf(num);
-} */
inline float fabsf(float num) {
return ::fabsf(num);
}
-inline float sqrt(float x) {
- return ::sqrtf(x);
-}
-
inline float abs(float x) {
return ::fabsf(x);
}
} // namespace std
-#endif \ No newline at end of file
+#endif
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h
index 0d311c0e..58b6b4e7 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h
@@ -29,7 +29,7 @@ double cos(double);
float cosf(float);
double exp(double);
double ceil(double);
-float ceilf(float);
+// float ceilf(float);
double frexp(double, int *);
double ldexp(double, int);
double modf(double, double *);
diff --git a/src/REL/d/a/e/d_a_e_sm.cpp b/src/REL/d/a/e/d_a_e_sm.cpp
index dae7f886..6b6e4131 100644
--- a/src/REL/d/a/e/d_a_e_sm.cpp
+++ b/src/REL/d/a/e/d_a_e_sm.cpp
@@ -41,6 +41,8 @@
#include "toBeSorted/small_sound_mgr.h"
#include "toBeSorted/time_area_mgr.h"
+#include <cmath.h>
+
SPECIAL_ACTOR_PROFILE(E_SM, dAcEsm_c, fProfile::E_SM, 0xEB, 0, 4098);
static dCcD_SrcSph sSphSrc = {
diff --git a/src/nw4r/snd/snd_AnimSound.cpp b/src/nw4r/snd/snd_AnimSound.cpp
index de514c8b..5f98612d 100644
--- a/src/nw4r/snd/snd_AnimSound.cpp
+++ b/src/nw4r/snd/snd_AnimSound.cpp
@@ -1,10 +1,481 @@
/* Only implemented to the extent necessary to match data sections. */
+#include "nw4r/snd/snd_AnimSound.h"
+
#include "common.h" // nullptr
-#include <decomp.h>
+#include "nw4r/snd/snd_BasicSound.h"
+#include "nw4r/snd/snd_SeqSound.h"
+#include "nw4r/snd/snd_SeqSoundHandle.h"
+#include "nw4r/snd/snd_SoundHandle.h"
+#include "nw4r/snd/snd_SoundStartable.h"
+
+#include <cmath>
+
+namespace nw4r {
+namespace snd {
+namespace detail {
+
+AnimSoundImpl::AnimSoundImpl(SoundStartable &startable, AnimEventPlayer *player, int numSounds)
+ : mStartable(startable),
+ mpSounds(player),
+ mNumSounds(numSounds),
+ field_0x0C(0.0f),
+ mIsActive(false),
+ field_0x19(0),
+ field_0x1A(0),
+ field_0x1C(0),
+ mCallback(NULL),
+ field_0x28(1.0f) {}
+
+AnimSoundImpl::~AnimSoundImpl() {
+ Shutdown();
+}
+
+bool AnimSoundImpl::Setup(const void *data) {
+ Shutdown();
+ if (!mReader.Setup(data)) {
+ return false;
+ }
+
+ field_0x19 = 1;
+ mIsActive = true;
+ field_0x0C = 0.0f;
+ field_0x1C = 0;
+ return true;
+}
+
+void AnimSoundImpl::Shutdown() {
+ if (mIsActive) {
+ for (int i = 0; i < mNumSounds; i++) {
+ if (mpSounds[i].GetHandle()->IsAttachedSound() && mpSounds[i].IsRunning()) {
+ mpSounds[i].GetHandle()->Stop();
+ }
+ }
+
+ mReader.Shutdown();
+ mIsActive = false;
+ }
+}
+
+void AnimSoundImpl::ResetFrame(f32 f, int i) {
+ field_0x0C = f;
+ field_0x1C = i;
+ field_0x1A = 1;
+ field_0x19 = 0;
+}
+
+void AnimSoundImpl::UpdateFrame(f32 frame, PlayDirection dir) {
+ for (int i = 0; i < mNumSounds; i++) {
+ mpSounds[i].UpdateFrame();
+ }
+
+ if (field_0x19) {
+ if (dir == FORWARD) {
+ ResetFrame(0.0f, 0);
+ } else {
+ u32 duration = mReader.GetAnimDuration();
+ ResetFrame(duration - 1.0f, 0);
+ }
+ field_0x19 = false;
+ }
+
+ mVariableValue = (frame - field_0x0C) / field_0x28;
+ if (dir == FORWARD) {
+ UpdateForward(frame);
+ } else {
+ UpdateBackward(frame);
+ }
+ field_0x0C = frame;
+ field_0x1A = false;
+}
+
+bool AnimSoundImpl::ShouldPlayEvent(const AnimEventRef *ref) const {
+ if (!(ref->flags_0x08 & 1) && (ref->flags_0x08 & 4 || ref->flags_0x08 & 2)) {
+ return true;
+ }
+ int i1 = ut::Max((int)ref->field_0x09, 0);
+ int i2 = ut::Abs(field_0x1C);
+ if (ref->field_0x0A == 0) {
+ if (i2 < i1) {
+ return false;
+ }
+ } else {
+ if (i2 < i1) {
+ return false;
+ }
+ if ((i2 - i1) % ref->field_0x0A != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void AnimSoundImpl::UpdateEvents(s32 duration, PlayDirection direction) {
+ for (u32 eventIdx = 0; eventIdx < mReader.GetEventCount(); eventIdx++) {
+ const AnimEventRef *ref = mReader.GetEventRef(eventIdx);
+ if (ref == NULL) {
+ continue;
+ }
+ if (ShouldPlayEvent(ref)) {
+ // HACK/Fakematch: Force a reload
+ if ((((AnimEventRef *)ref)->flags_0x08) & 1) {
+ UpdateTrigger(ref, duration, direction);
+ } else {
+ if (direction == FORWARD) {
+ UpdateForwardRange(ref, duration);
+ } else {
+ UpdateBackwardRange(ref, duration);
+ }
+ }
+ }
+ }
+}
+
+void AnimSoundImpl::UpdateForward(f32 frame) {
+ s32 duration = std::floorf(field_0x0C);
+ s32 iFrame = std::floorf(frame);
+
+ if (field_0x1A && field_0x0C == duration) {
+ duration -= 1;
+ }
+
+ if (duration == iFrame) {
+ return;
+ }
+
+ s32 loopFrame = duration + 1;
+ while (true) {
+ if (loopFrame == mReader.GetAnimDuration()) {
+ loopFrame -= mReader.GetAnimDuration();
+ field_0x1C++;
+ }
+
+ UpdateEvents(loopFrame, FORWARD);
+
+ if (loopFrame == iFrame) {
+ break;
+ }
+ loopFrame++;
+ }
+}
+
+void AnimSoundImpl::UpdateBackward(f32 frame) {
+ s32 duration = std::ceilf(field_0x0C);
+ s32 iFrame = std::ceilf(frame);
+
+ if (duration >= mReader.GetAnimDuration()) {
+ duration -= mReader.GetAnimDuration();
+ }
+
+ if (iFrame >= mReader.GetAnimDuration()) {
+ iFrame -= mReader.GetAnimDuration();
+ }
+
+ if (field_0x1A && field_0x0C == duration) {
+ duration += 1;
+ }
+
+ if (duration == iFrame) {
+ return;
+ }
+
+ s32 loopFrame = duration - 1;
+ while (true) {
+ if (loopFrame == -1) {
+ loopFrame += mReader.GetAnimDuration();
+ field_0x1C--;
+ }
+
+ UpdateEvents(loopFrame, BACKWARD);
+
+ if (loopFrame == iFrame) {
+ break;
+ }
+ loopFrame--;
+ }
+}
+
+void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirection direction) {
+ const AnimEvent *event = mReader.GetEvent(ref);
+ if (event == NULL) {
+ return;
+ }
+
+ if (ref->flags_0x08 & 4) {
+ return;
+ }
+
+ if (!event->MatchesDirection(direction)) {
+ return;
+ }
+
+ if ((ref->flags_0x08 & 2)) {
+ if (ref->field_0x00 == frame) {
+ StopEvent(event);
+ if (mCallback != NULL) {
+ (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ StartEvent(event, true);
+ }
+ } else {
+ if (ref->field_0x00 == frame) {
+ StopEvent(event);
+ if (mCallback != NULL) {
+ (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ StartEvent(event, true);
+ }
+
+ s32 u;
+ if (direction == FORWARD) {
+ u = ref->field_0x04;
+ } else {
+ u = ut::Max(ref->field_0x00 * 2 - ref->field_0x04, 0);
+ }
+
+ if (u == frame) {
+ if (mCallback != NULL) {
+ (mCallback)(1, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ StopEvent(event);
+ }
+ }
+}
+
+void AnimSoundImpl::UpdateForwardRange(const AnimEventRef *ref, s32 frame) {
+ const AnimEvent *event = mReader.GetEvent(ref);
+ if (event == NULL) {
+ return;
+ }
+
+ if (ref->flags_0x08 & 4 && ref->flags_0x08 & 2) {
+ HoldEvent(event, true);
+ return;
+ }
+
+ if (ref->flags_0x08 & 4) {
+ if (ref->field_0x04 == frame && mCallback != NULL) {
+ (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (field_0x1C < ref->field_0x09) {
+ HoldEvent(event, true);
+ } else if (field_0x1C == ref->field_0x09) {
+ if (frame < ref->field_0x04) {
+ HoldEvent(event, true);
+ } else {
+ StopEvent(event);
+ }
+ }
+ } else if ((ref->flags_0x08 & 2)) {
+ if (ref->field_0x00 == frame && mCallback != NULL) {
+ (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (field_0x1C > ref->field_0x09) {
+ HoldEvent(event, true);
+ } else if (field_0x1C == ref->field_0x09 && ref->field_0x00 <= frame) {
+ HoldEvent(event, true);
+ }
+ } else {
+ if (ref->field_0x00 == frame && mCallback != NULL) {
+ (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (ref->field_0x04 == frame && mCallback != NULL) {
+ (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (ref->field_0x00 <= frame && frame < ref->field_0x04) {
+ HoldEvent(event, true);
+ } else {
+ StopEvent(event);
+ }
+ }
+}
+
+void AnimSoundImpl::UpdateBackwardRange(const AnimEventRef *ref, s32 frame) {
+ const AnimEvent *event = mReader.GetEvent(ref);
+ if (event == NULL) {
+ return;
+ }
+
+ if (ref->flags_0x08 & 4 && ref->flags_0x08 & 2) {
+ HoldEvent(event, true);
+ return;
+ }
+
+ if (ref->flags_0x08 & 4) {
+ if (ref->field_0x04 == frame && mCallback != NULL) {
+ (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (field_0x1C < ref->field_0x09) {
+ HoldEvent(event, true);
+ } else if (field_0x1C == ref->field_0x09 && frame <= ref->field_0x04) {
+ HoldEvent(event, true);
+ }
+ } else if ((ref->flags_0x08 & 2)) {
+ if (ref->field_0x00 == frame && mCallback != NULL) {
+ (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (field_0x1C > ref->field_0x09) {
+ HoldEvent(event, true);
+ } else if (field_0x1C == ref->field_0x09) {
+ if (ref->field_0x00 < frame) {
+ HoldEvent(event, true);
+ } else {
+ StopEvent(event);
+ }
+ }
+ } else {
+ if (ref->field_0x00 == frame && mCallback != NULL) {
+ (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (ref->field_0x04 == frame && mCallback != NULL) {
+ (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24);
+ }
+ if (ref->field_0x00 < frame && frame <= ref->field_0x04) {
+ HoldEvent(event, true);
+ } else {
+ StopEvent(event);
+ }
+ }
+}
+
+void AnimSoundImpl::StartEvent(const AnimEvent *event, bool b) {
+ int leastPriority = 0x80;
+ int leastPriorityIdx = -1;
+ int i = 0;
+ for (; i < mNumSounds; i++) {
+ if (!mpSounds[i].IsAttachedSound()) {
+ break;
+ }
+ int priority = mpSounds[i].GetPriority();
+ if (leastPriority > priority) {
+ leastPriorityIdx = i;
+ leastPriority = priority;
+ }
+ }
+
+ if (i == mNumSounds) {
+ mpSounds[leastPriorityIdx].Stop();
+ i = leastPriorityIdx;
+ }
+
+ mpSounds[i].StartSound(event, &mStartable, b);
+
+ u32 varNo = 0;
+ if (event->GetVarNo(&varNo)) {
+ mpSounds[i].SetVariable(event, varNo, mVariableValue);
+ }
+}
+
+void AnimSoundImpl::HoldEvent(const AnimEvent *event, bool b) {
+ int leastPriority = 0x80;
+ int leastPriorityIdx = -1;
+ int i = 0;
+ for (; i < mNumSounds; i++) {
+ if (mpSounds[i].IsCurrentEvent(event)) {
+ return;
+ }
+ if (!mpSounds[i].IsAttachedSound()) {
+ leastPriorityIdx = i;
+ leastPriority = -1;
+ } else {
+ int priority = mpSounds[i].GetPriority();
+ if (leastPriority > priority) {
+ leastPriorityIdx = i;
+ leastPriority = priority;
+ }
+ }
+ }
+
+ if (i == mNumSounds) {
+ mpSounds[leastPriorityIdx].Stop();
+ i = leastPriorityIdx;
+ }
+
+ mpSounds[i].HoldSound(event, &mStartable, b);
+
+ u32 varNo = 0;
+ if (event->GetVarNo(&varNo)) {
+ mpSounds[i].SetVariable(event, varNo, mVariableValue);
+ }
+}
+
+void AnimSoundImpl::StopEvent(const AnimEvent *event) {
+ for (int i = 0; i < mNumSounds; i++) {
+ mpSounds[i].StopEvent(event);
+ }
+}
+
+bool AnimEventPlayer::StartSound(const AnimEvent *event, SoundStartable *startable, bool b) {
+ if (event->soundId == 0xFFFFFFFF) {
+ if (!startable->StartSound(GetHandle(), event->GetSoundLabel())) {
+ return false;
+ }
+ } else {
+ if (!startable->StartSound(GetHandle(), event->soundId)) {
+ return false;
+ }
+ }
+
+ SetVolumePitch(event, b);
+
+ return true;
+}
+
+bool AnimEventPlayer::HoldSound(const AnimEvent *event, SoundStartable *startable, bool b) {
+ if (event->soundId == 0xFFFFFFFF) {
+ if (!startable->HoldSound(GetHandle(), event->GetSoundLabel())) {
+ return false;
+ }
+ } else {
+ if (!startable->HoldSound(GetHandle(), event->soundId)) {
+ return false;
+ }
+ }
+
+ GetHandle()->detail_GetAttachedSound()->SetAutoStopCounter(0);
+ SetVolumePitch(event, b);
+
+ return true;
+}
+
+void AnimEventPlayer::SetVolumePitch(const AnimEvent *event, bool b) {
+ if (event->volume < 128) {
+ SetVolume(event->volume / 128.0f);
+ }
+ if (event->pitch != 1.0f) {
+ SetPitch(event->pitch);
+ }
+
+ mpEvent = event;
+ if (b) {
+ b = !event->ShouldPreventStart();
+ }
+ mIsRunning = b;
+}
+
+void AnimEventPlayer::SetVariable(const AnimEvent *event, u32 varNo, f32 f) {
+ if (varNo < 16) {
+ if (GetHandle()->IsAttachedSound()) {
+ SeqSoundHandle handle(GetHandle());
+ int iVal = f * 100.0f;
+ handle.WriteVariable(varNo, ut::Clamp(iVal, -0x8000, 0x7FFF));
+ handle.DetachSound();
+ }
+ } else if (varNo < 32) {
+ int iVal = f * 100.0f;
+ SeqSound::WriteGlobalVariable(varNo - 16, ut::Clamp(iVal, -0x8000, 0x7FFF));
+ }
+}
+
+AnimEventPlayer::AnimEventPlayer() : mpEvent(0), mIsRunning(false) {}
-#include "nw4r/snd/snd_Util.h"
+AnimEventPlayer::~AnimEventPlayer() {
+ if (mHandle.IsAttachedSound() && IsRunning()) {
+ mHandle.Stop();
+ }
+}
-DECOMP_FORCE(nw4r::snd::detail::Util::GetDataRefAddress0(
- *static_cast<nw4r::snd::detail::Util::DataRef<char> const *>(nullptr),
- nullptr));
+} // namespace detail
+} // namespace snd
+} // namespace nw4r
diff --git a/src/nw4r/snd/snd_AnimSoundReader.cpp b/src/nw4r/snd/snd_AnimSoundReader.cpp
index 555e5e94..a003139d 100644
--- a/src/nw4r/snd/snd_AnimSoundReader.cpp
+++ b/src/nw4r/snd/snd_AnimSoundReader.cpp
@@ -58,7 +58,7 @@ const AnimSoundFile::EventTable *AnimSoundFileReader::GetEventTable() const {
if (mpBlock == NULL) {
return NULL;
}
- return Util::GetDataRefAddress0(mpBlock->eventTable, &mpBlock->_0x08);
+ return Util::GetDataRefAddress0(mpBlock->eventTable, &mpBlock->duration);
}
const AnimEvent *AnimSoundFileReader::GetEvent(const AnimEventRef *ref) const {
@@ -66,7 +66,7 @@ const AnimEvent *AnimSoundFileReader::GetEvent(const AnimEventRef *ref) const {
return NULL;
}
const AnimSoundFile::EventTable *event = GetEventTable(); // unused
- return Util::GetDataRefAddress0(ref->event, &mpBlock->_0x08);
+ return Util::GetDataRefAddress0(ref->event, &mpBlock->duration);
}
} // namespace detail