mirror of
https://github.com/zeldaret/ss
synced 2026-06-10 12:55:12 -04:00
snd_AnimSound OK
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-1
@@ -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"),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 "nw4r/snd/snd_Util.h"
|
||||
#include <cmath>
|
||||
|
||||
DECOMP_FORCE(nw4r::snd::detail::Util::GetDataRefAddress0(
|
||||
*static_cast<nw4r::snd::detail::Util::DataRef<char> const *>(nullptr),
|
||||
nullptr));
|
||||
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) {}
|
||||
|
||||
AnimEventPlayer::~AnimEventPlayer() {
|
||||
if (mHandle.IsAttachedSound() && IsRunning()) {
|
||||
mHandle.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace snd
|
||||
} // namespace nw4r
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user