diff --git a/include/nw4r/snd/snd_AnimSound.h b/include/nw4r/snd/snd_AnimSound.h index 4289d4bb..37d66c2f 100644 --- a/include/nw4r/snd/snd_AnimSound.h +++ b/include/nw4r/snd/snd_AnimSound.h @@ -5,7 +5,8 @@ #include "nw4r/snd/snd_SoundHandle.h" #include "nw4r/snd/snd_SoundStartable.h" -// Class and non-inline function names from InazumaWii, everything else made up +// Class and non-inlined function names from InazumaWii +// Names of automatically inlined functions from BBA namespace nw4r { namespace snd { @@ -39,22 +40,13 @@ public: return mIsRunning; } - void UpdateFrame() { - if (!mHandle.IsAttachedSound()) { - mpEvent = 0; - } - } + void UpdateFrame(); - void Stop() { - if (IsAttachedSound()) { - mHandle.detail_GetAttachedSound()->Stop(0); - } - mpEvent = 0; - } + void ForceStop(); void StopEvent(const AnimEvent *event) { if (mpEvent == event) { - Stop(); + ForceStop(); } } @@ -70,8 +62,14 @@ public: } } - void StartSound(const AnimEvent *event, SoundStartable *startable, bool b); - void HoldSound(const AnimEvent *event, SoundStartable *startable, bool b); + void StartEvent(const AnimEvent *event, SoundStartable *startable, bool b); + void HoldEvent(const AnimEvent *event, SoundStartable *startable, bool b); + + // Not sure about these, this could be related to + // InitParam__Q44nw4r3snd6detail15AnimEventPlayerFPCQ44nw4r3snd6detail9AnimEventb + // from BBA, but SetVariable is almost certainly an inline (duplicated code) + // but the float argument is read from AnimSoundImpl so something seems to have + // changed. void SetVolumePitch(const AnimEvent *event, bool b); void SetVariable(const AnimEvent *event, u32 varNo, f32 f); @@ -97,19 +95,16 @@ public: void UpdateFrame(f32 frame, PlayDirection dir); void UpdateForward(f32 frame); void UpdateBackward(f32 frame); + void UpdateOneFrame(s32 duration, PlayDirection direction); 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 *); + bool IsPlayableLoopCount(const nw4r::snd::detail::AnimEventFrameInfo&); - // Made up inlines - bool ShouldPlayEvent(const AnimEventRef *ref) const; - void UpdateEvents(s32 duration, PlayDirection direction); typedef void (*Callback)(int, s32, const char *, UNKWORD, UNKWORD); diff --git a/include/nw4r/snd/snd_AnimSoundReader.h b/include/nw4r/snd/snd_AnimSoundReader.h index be7422bf..43e9adf1 100644 --- a/include/nw4r/snd/snd_AnimSoundReader.h +++ b/include/nw4r/snd/snd_AnimSoundReader.h @@ -5,6 +5,15 @@ namespace nw4r { namespace snd { namespace detail { +// Type and name revealed by BBA +struct AnimEventFrameInfo { + int field_0x00; // at 0x00 + int field_0x04; // at 0x04 + u8 flags; // at 0x08 + s8 field_0x09; // at 0x09 + u8 field_0x0A; // at 0x0A +}; + struct AnimEvent { u32 flags; // at 0x00 u32 soundId; // at 0x04 @@ -42,15 +51,13 @@ struct AnimEvent { } }; +// Name from Inazuma, BBA struct AnimEventRef { - int field_0x00; // at 0x08 - int field_0x04; // at 0x04 - u8 flags; // at 0x08 - s8 field_0x09; // at 0x09 - u8 field_0x0A; // at 0x0A + AnimEventFrameInfo mInfo; // at 0x00 Util::DataRef event; // at 0x0C }; +// Names unknown struct AnimSoundFile { static u32 const SIGNATURE_FILE = NW4R_FOUR_BYTE('R', 'A', 'S', 'D'); static int const FILE_VERSION = NW4R_FILE_VERSION(1, 0); @@ -71,6 +78,7 @@ struct AnimSoundFile { }; }; +// Name from Inazuma class AnimSoundFileReader { public: AnimSoundFileReader(); diff --git a/src/nw4r/snd/snd_AnimSound.cpp b/src/nw4r/snd/snd_AnimSound.cpp index 6d9219e8..ab8151aa 100644 --- a/src/nw4r/snd/snd_AnimSound.cpp +++ b/src/nw4r/snd/snd_AnimSound.cpp @@ -89,49 +89,6 @@ void AnimSoundImpl::UpdateFrame(f32 frame, PlayDirection dir) { field_0x1A = false; } -bool AnimSoundImpl::ShouldPlayEvent(const AnimEventRef *ref) const { - if (!(ref->flags & 1) && (ref->flags & 4 || ref->flags & 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) & 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); @@ -151,7 +108,7 @@ void AnimSoundImpl::UpdateForward(f32 frame) { field_0x1C++; } - UpdateEvents(loopFrame, FORWARD); + UpdateOneFrame(loopFrame, FORWARD); if (loopFrame == iFrame) { break; @@ -187,7 +144,7 @@ void AnimSoundImpl::UpdateBackward(f32 frame) { field_0x1C--; } - UpdateEvents(loopFrame, BACKWARD); + UpdateOneFrame(loopFrame, BACKWARD); if (loopFrame == iFrame) { break; @@ -196,13 +153,33 @@ void AnimSoundImpl::UpdateBackward(f32 frame) { } } +void AnimSoundImpl::UpdateOneFrame(s32 duration, PlayDirection direction) { + for (u32 eventIdx = 0; eventIdx < mReader.GetEventCount(); eventIdx++) { + const AnimEventRef *ref = mReader.GetEventRef(eventIdx); + if (ref == NULL) { + continue; + } + if (IsPlayableLoopCount(ref->mInfo)) { + if ((ref->mInfo.flags) & 1) { + UpdateTrigger(ref, duration, direction); + } else { + if (direction == FORWARD) { + UpdateForwardRange(ref, duration); + } else { + UpdateBackwardRange(ref, duration); + } + } + } + } +} + void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirection direction) { const AnimEvent *event = mReader.GetEvent(ref); if (event == NULL) { return; } - if (ref->flags & 4) { + if (ref->mInfo.flags & 4) { return; } @@ -210,8 +187,8 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect return; } - if ((ref->flags & 2)) { - if (ref->field_0x00 == frame) { + if ((ref->mInfo.flags & 2)) { + if (ref->mInfo.field_0x00 == frame) { StopEvent(event); if (mCallback != NULL) { (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); @@ -219,7 +196,7 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect StartEvent(event, true); } } else { - if (ref->field_0x00 == frame) { + if (ref->mInfo.field_0x00 == frame) { StopEvent(event); if (mCallback != NULL) { (mCallback)(0, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); @@ -229,9 +206,9 @@ void AnimSoundImpl::UpdateTrigger(const AnimEventRef *ref, s32 frame, PlayDirect s32 u; if (direction == FORWARD) { - u = ref->field_0x04; + u = ref->mInfo.field_0x04; } else { - u = ut::Max(ref->field_0x00 * 2 - ref->field_0x04, 0); + u = ut::Max(ref->mInfo.field_0x00 * 2 - ref->mInfo.field_0x04, 0); } if (u == frame) { @@ -249,41 +226,41 @@ void AnimSoundImpl::UpdateForwardRange(const AnimEventRef *ref, s32 frame) { return; } - if (ref->flags & 4 && ref->flags & 2) { + if (ref->mInfo.flags & 4 && ref->mInfo.flags & 2) { HoldEvent(event, true); return; } - if (ref->flags & 4) { - if (ref->field_0x04 == frame && mCallback != NULL) { + if (ref->mInfo.flags & 4) { + if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (field_0x1C < ref->field_0x09) { + if (field_0x1C < ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->field_0x09) { - if (frame < ref->field_0x04) { + } else if (field_0x1C == ref->mInfo.field_0x09) { + if (frame < ref->mInfo.field_0x04) { HoldEvent(event, true); } else { StopEvent(event); } } - } else if ((ref->flags & 2)) { - if (ref->field_0x00 == frame && mCallback != NULL) { + } else if ((ref->mInfo.flags & 2)) { + if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (field_0x1C > ref->field_0x09) { + if (field_0x1C > ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->field_0x09 && ref->field_0x00 <= frame) { + } else if (field_0x1C == ref->mInfo.field_0x09 && ref->mInfo.field_0x00 <= frame) { HoldEvent(event, true); } } else { - if (ref->field_0x00 == frame && mCallback != NULL) { + if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (ref->field_0x04 == frame && mCallback != NULL) { + if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (ref->field_0x00 <= frame && frame < ref->field_0x04) { + if (ref->mInfo.field_0x00 <= frame && frame < ref->mInfo.field_0x04) { HoldEvent(event, true); } else { StopEvent(event); @@ -297,41 +274,41 @@ void AnimSoundImpl::UpdateBackwardRange(const AnimEventRef *ref, s32 frame) { return; } - if (ref->flags & 4 && ref->flags & 2) { + if (ref->mInfo.flags & 4 && ref->mInfo.flags & 2) { HoldEvent(event, true); return; } - if (ref->flags & 4) { - if (ref->field_0x04 == frame && mCallback != NULL) { + if (ref->mInfo.flags & 4) { + if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (field_0x1C < ref->field_0x09) { + if (field_0x1C < ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->field_0x09 && frame <= ref->field_0x04) { + } else if (field_0x1C == ref->mInfo.field_0x09 && frame <= ref->mInfo.field_0x04) { HoldEvent(event, true); } - } else if ((ref->flags & 2)) { - if (ref->field_0x00 == frame && mCallback != NULL) { + } else if ((ref->mInfo.flags & 2)) { + if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (field_0x1C > ref->field_0x09) { + if (field_0x1C > ref->mInfo.field_0x09) { HoldEvent(event, true); - } else if (field_0x1C == ref->field_0x09) { - if (ref->field_0x00 < frame) { + } else if (field_0x1C == ref->mInfo.field_0x09) { + if (ref->mInfo.field_0x00 < frame) { HoldEvent(event, true); } else { StopEvent(event); } } } else { - if (ref->field_0x00 == frame && mCallback != NULL) { + if (ref->mInfo.field_0x00 == frame && mCallback != NULL) { (mCallback)(3, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (ref->field_0x04 == frame && mCallback != NULL) { + if (ref->mInfo.field_0x04 == frame && mCallback != NULL) { (mCallback)(2, frame, event->GetSoundLabel(), event->field_0x1C, field_0x24); } - if (ref->field_0x00 < frame && frame <= ref->field_0x04) { + if (ref->mInfo.field_0x00 < frame && frame <= ref->mInfo.field_0x04) { HoldEvent(event, true); } else { StopEvent(event); @@ -355,11 +332,11 @@ void AnimSoundImpl::StartEvent(const AnimEvent *event, bool b) { } if (i == mNumSounds) { - mpSounds[leastPriorityIdx].Stop(); + mpSounds[leastPriorityIdx].ForceStop(); i = leastPriorityIdx; } - mpSounds[i].StartSound(event, &mStartable, b); + mpSounds[i].StartEvent(event, &mStartable, b); u32 varNo = 0; if (event->GetVarNo(&varNo)) { @@ -388,11 +365,11 @@ void AnimSoundImpl::HoldEvent(const AnimEvent *event, bool b) { } if (i == mNumSounds) { - mpSounds[leastPriorityIdx].Stop(); + mpSounds[leastPriorityIdx].ForceStop(); i = leastPriorityIdx; } - mpSounds[i].HoldSound(event, &mStartable, b); + mpSounds[i].HoldEvent(event, &mStartable, b); u32 varNo = 0; if (event->GetVarNo(&varNo)) { @@ -406,33 +383,26 @@ void AnimSoundImpl::StopEvent(const AnimEvent *event) { } } -void AnimEventPlayer::StartSound(const AnimEvent *event, SoundStartable *startable, bool b) { - if (event->soundId == 0xFFFFFFFF) { - if (!startable->StartSound(GetHandle(), event->GetSoundLabel())) { - return; +bool AnimSoundImpl::IsPlayableLoopCount(const nw4r::snd::detail::AnimEventFrameInfo &ref) { + if (!(ref.flags & 1) && (ref.flags & 4 || ref.flags & 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 (!startable->StartSound(GetHandle(), event->soundId)) { - return; + if (i2 < i1) { + return false; + } + if ((i2 - i1) % ref.field_0x0A != 0) { + return false; } } - SetVolumePitch(event, b); -} - -void AnimEventPlayer::HoldSound(const AnimEvent *event, SoundStartable *startable, bool b) { - if (event->soundId == 0xFFFFFFFF) { - if (!startable->HoldSound(GetHandle(), event->GetSoundLabel())) { - return; - } - } else { - if (!startable->HoldSound(GetHandle(), event->soundId)) { - return; - } - } - - GetHandle()->detail_GetAttachedSound()->SetAutoStopCounter(0); - SetVolumePitch(event, b); + return true; } void AnimEventPlayer::SetVolumePitch(const AnimEvent *event, bool b) { @@ -472,6 +442,48 @@ AnimEventPlayer::~AnimEventPlayer() { } } +void AnimEventPlayer::StartEvent(const AnimEvent *event, SoundStartable *startable, bool b) { + if (event->soundId == 0xFFFFFFFF) { + if (!startable->StartSound(GetHandle(), event->GetSoundLabel())) { + return; + } + } else { + if (!startable->StartSound(GetHandle(), event->soundId)) { + return; + } + } + + SetVolumePitch(event, b); +} + +void AnimEventPlayer::HoldEvent(const AnimEvent *event, SoundStartable *startable, bool b) { + if (event->soundId == 0xFFFFFFFF) { + if (!startable->HoldSound(GetHandle(), event->GetSoundLabel())) { + return; + } + } else { + if (!startable->HoldSound(GetHandle(), event->soundId)) { + return; + } + } + + GetHandle()->detail_GetAttachedSound()->SetAutoStopCounter(0); + SetVolumePitch(event, b); +} + +void AnimEventPlayer::ForceStop() { + if (IsAttachedSound()) { + mHandle.detail_GetAttachedSound()->Stop(0); + } + mpEvent = 0; +} + +void AnimEventPlayer::UpdateFrame() { + if (!mHandle.IsAttachedSound()) { + mpEvent = 0; + } +} + } // namespace detail } // namespace snd } // namespace nw4r