From fc33c409ecfbfcff7256cbc87d5642f58350b522 Mon Sep 17 00:00:00 2001 From: Narr the Reg <5944268+german77@users.noreply.github.com> Date: Thu, 12 Mar 2026 16:56:52 -0600 Subject: [PATCH] Library/Audio: Implement `al::trySetAudioInfo` and `al::tryFindAudioInfo` (#951) --- data/file_list.yml | 12 +- lib/al/Library/Audio/AudioEventController.cpp | 34 ++++++ lib/al/Library/Audio/AudioEventController.h | 25 ++++ lib/al/Library/Audio/AudioInfo.h | 113 ++++++++++++------ 4 files changed, 143 insertions(+), 41 deletions(-) diff --git a/data/file_list.yml b/data/file_list.yml index cdeb7619..96c46ca7 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -224041,13 +224041,13 @@ Library/Audio/AudioEventController.o: label: - _ZN2al21AudioSoundArchiveInfoC1Ev - _ZN2al21AudioSoundArchiveInfoC2Ev - status: NotDecompiled + status: Matching - offset: 0x811904 size: 8 label: - _ZN2al24AudioResourceLoadingInfoC1Ev - _ZN2al24AudioResourceLoadingInfoC2Ev - status: NotDecompiled + status: Matching - offset: 0x81190c size: 72 label: _ZN2al26AudioAddonSoundArchiveInfo10createInfoERKNS_9ByamlIterE @@ -224055,16 +224055,16 @@ Library/Audio/AudioEventController.o: - offset: 0x811954 size: 108 label: _ZN2al21AudioSoundArchiveInfo10createInfoERKNS_9ByamlIterE - status: NotDecompiled + status: Matching - offset: 0x8119c0 size: 332 label: _ZN2al19createAudioInfoListINS_26AudioAddonSoundArchiveInfoEEEPNS_22AudioInfoListWithPartsIT_EERKNS_9ByamlIterEi - status: NotDecompiled + status: Matching lazy: true - offset: 0x811b0c size: 344 label: _ZN2al24AudioResourceLoadingInfo10createInfoEPKNS_8ResourceE - status: NotDecompiled + status: Matching - offset: 0x811c64 size: 12 label: _ZN2al26AudioAddonSoundArchiveInfo11compareInfoEPKS0_S2_ @@ -224072,7 +224072,7 @@ Library/Audio/AudioEventController.o: - offset: 0x811c70 size: 104 label: _ZN2al26AudioInfoListCreateFunctorINS_26AudioAddonSoundArchiveInfoEE30tryCreateAudioInfoAndSetToListERKNS_9ByamlIterE - status: NotDecompiled + status: Matching lazy: true - offset: 0x811cd8 size: 76 diff --git a/lib/al/Library/Audio/AudioEventController.cpp b/lib/al/Library/Audio/AudioEventController.cpp index cd4d662b..27bc86df 100644 --- a/lib/al/Library/Audio/AudioEventController.cpp +++ b/lib/al/Library/Audio/AudioEventController.cpp @@ -1,5 +1,7 @@ #include "Library/Audio/AudioEventController.h" +#include "Library/Audio/AudioInfo.h" +#include "Library/Resource/Resource.h" #include "Library/Yaml/ByamlIter.h" namespace al { @@ -20,4 +22,36 @@ s32 AudioAddonSoundArchiveInfo::compareInfo(const AudioAddonSoundArchiveInfo* lh return strcmp(lhs->name, rhs->name); } +AudioSoundArchiveInfo::AudioSoundArchiveInfo() = default; + +AudioSoundArchiveInfo* AudioSoundArchiveInfo::createInfo(const ByamlIter& iter) { + AudioSoundArchiveInfo* info = new AudioSoundArchiveInfo(); + + ByamlIter addonIter; + if (!iter.tryGetIterByKey(&addonIter, "AddonSoundArchiveInfoList")) + info->addonInfo = nullptr; + + // BUG: addonIter can be invalid. It should have returned early on the previous check + info->addonInfo = createAudioInfoList(addonIter, 0); + return info; +} + +AudioResourceLoadingInfo::AudioResourceLoadingInfo() = default; + +AudioResourceLoadingInfo* AudioResourceLoadingInfo::createInfo(const Resource* resource) { + AudioResourceLoadingInfo* info = new AudioResourceLoadingInfo(); + + if (resource->isExistFile("SeSoundArchiveInfo.byml")) { + ByamlIter iter(static_cast(resource->getOtherFile("SeSoundArchiveInfo.byml"))); + info->seInfo = AudioSoundArchiveInfo::createInfo(iter); + } + + if (resource->isExistFile("BgmSoundArchiveInfo.byml")) { + ByamlIter iter(static_cast(resource->getOtherFile("BgmSoundArchiveInfo.byml"))); + info->bgmInfo = AudioSoundArchiveInfo::createInfo(iter); + } + + return info; +} + } // namespace al diff --git a/lib/al/Library/Audio/AudioEventController.h b/lib/al/Library/Audio/AudioEventController.h index 691bc7fb..0339acff 100644 --- a/lib/al/Library/Audio/AudioEventController.h +++ b/lib/al/Library/Audio/AudioEventController.h @@ -4,6 +4,10 @@ namespace al { class ByamlIter; +class Resource; + +template +class AudioInfoListWithParts; struct AudioAddonSoundArchiveInfo { AudioAddonSoundArchiveInfo(); @@ -17,4 +21,25 @@ struct AudioAddonSoundArchiveInfo { static_assert(sizeof(AudioAddonSoundArchiveInfo) == 0x8); +struct AudioSoundArchiveInfo { + AudioSoundArchiveInfo(); + + static AudioSoundArchiveInfo* createInfo(const ByamlIter& iter); + + AudioInfoListWithParts* addonInfo = nullptr; +}; + +static_assert(sizeof(AudioSoundArchiveInfo) == 0x8); + +struct AudioResourceLoadingInfo { + AudioResourceLoadingInfo(); + + static AudioResourceLoadingInfo* createInfo(const Resource* resource); + + AudioSoundArchiveInfo* seInfo = nullptr; + AudioSoundArchiveInfo* bgmInfo = nullptr; +}; + +static_assert(sizeof(AudioResourceLoadingInfo) == 0x10); + } // namespace al diff --git a/lib/al/Library/Audio/AudioInfo.h b/lib/al/Library/Audio/AudioInfo.h index 925dc37f..1d131f28 100644 --- a/lib/al/Library/Audio/AudioInfo.h +++ b/lib/al/Library/Audio/AudioInfo.h @@ -10,7 +10,7 @@ class ByamlIter; class AudioInfoListCreateFunctorBase; template -struct AudioInfoList; +class AudioInfoList; class AudioInfoListCreateFunctorBase { public: @@ -33,7 +33,7 @@ public: if (!info) return false; - return mAudioInfoList->list->pushBack(info); + return mAudioInfoList->setInfo(info); } private: @@ -42,25 +42,65 @@ private: }; template -struct AudioInfoList { +class AudioInfoList { +public: static s32 compareInfoAndKey(const T* info, const char* key) { return strcmp(info->name, key); } - sead::PtrArray* list; + AudioInfoList() = default; + + void init(s32 listSize) { + mIsLinearSearch = false; + mList = new sead::PtrArray(); + mList->allocBuffer((listSize == 0) ? 1 : listSize, nullptr); + } + + bool setInfo(const T* audioInfo) const { return mList->pushBack(audioInfo); } + + void sort() const { + if (mList->size() >= 10) + mList->heapSort(T::compareInfo); + else + mList->sort(T::compareInfo); + } + +private: + sead::PtrArray* mList; + bool mIsLinearSearch; }; template -struct AudioInfoListWithParts : public AudioInfoList { - s32 tryGetInfoIndex(const char*) const; - T* tryFindInfo(const char*) const; +class AudioInfoListWithParts : public AudioInfoList { +public: + AudioInfoListWithParts() = default; - s32 getPartsSize() const { - if (!parts) - return 0; - return parts->size(); + s32 tryGetInfoIndex(const char* key) const; + const T* tryFindInfo(const char* key) const; + + void init(s32 listSize, s32 maxNumParts) { + AudioInfoList::init(listSize); + + mParts = nullptr; + if (maxNumParts != 0) { + mParts = new sead::PtrArray>(); + mParts->allocBuffer(maxNumParts, nullptr); + } } - bool _8; - sead::PtrArray>* parts; + void sort() const { + AudioInfoList::sort(); + + for (s32 i = 0; i < getPartsSize(); i++) + mParts->at(i)->sort(); + } + + s32 getPartsSize() const { + if (!mParts) + return 0; + return mParts->size(); + } + +private: + sead::PtrArray>* mParts; }; template @@ -68,33 +108,36 @@ AudioInfoListWithParts* createAudioInfoList(const ByamlIter& iter, s32 maxNum AudioInfoListWithParts* audioInfoList = new AudioInfoListWithParts; s32 listSize = alAudioInfoListFunction::getCreateAudioInfoListSize(iter, 0); - audioInfoList->_8 = false; - - audioInfoList->list = new sead::PtrArray(); - audioInfoList->list->allocBuffer((listSize == 0) ? 1 : listSize, nullptr); - - audioInfoList->parts = nullptr; - if (maxNumParts != 0) { - audioInfoList->parts = new sead::PtrArray>(); - audioInfoList->parts->allocBuffer(maxNumParts, nullptr); - } + audioInfoList->init(listSize, maxNumParts); AudioInfoListCreateFunctor functor(audioInfoList, T::createInfo); alAudioInfoListFunction::createAudioInfoAndSetToList(&functor, iter); + audioInfoList->sort(); - if (audioInfoList->list->size() >= 10) - audioInfoList->list->heapSort(T::compareInfo); - else - audioInfoList->list->sort(T::compareInfo); - - for (s32 i = 0; i < audioInfoList->getPartsSize(); i++) { - sead::PtrArray* partsList = audioInfoList->parts->at(i)->list; - if (partsList->size() >= 10) - partsList->heapSort(T::compareInfo); - else - partsList->sort(T::compareInfo); - } return audioInfoList; } +template +bool trySetAudioInfo(const AudioInfoListWithParts* audioInfoList, const T* audioInfo, + bool disableSort) { + if (!audioInfoList || !audioInfo) + return false; + + if (!audioInfoList->setInfo(audioInfo)) + return false; + + if (!disableSort) + audioInfoList->sort(); + + return true; +} + +template +const T* tryFindAudioInfo(const AudioInfoListWithParts* audioInfoList, const char* name) { + if (!audioInfoList || !name) + return nullptr; + + return audioInfoList->tryFindInfo(name); +} + } // namespace al