From 339ee576b58abf191ea7d834dc6e1b06c3dea52b Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 20 Jul 2025 13:14:48 +0200 Subject: [PATCH] d_snd_bgm_mml_parsers OK --- config/SOUE01/symbols.txt | 30 +++---- configure.py | 2 +- include/d/snd/d_snd_bgm_mgr.h | 7 +- include/d/snd/d_snd_bgm_mml_parsers.h | 50 ++++++++++- include/d/snd/d_snd_types.h | 1 + src/d/snd/d_snd_bgm_mgr.cpp | 77 ++++++++++++++++- src/d/snd/d_snd_bgm_mml_parsers.cpp | 117 ++++++++++++++++++++++++++ 7 files changed, 262 insertions(+), 22 deletions(-) diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 767134d4..5a4ac7c9 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -20422,7 +20422,7 @@ fn_8036D0B0 = .text:0x8036D0B0; // type:function size:0x11C loadStageSound__12dSndBgmMgr_cFv = .text:0x8036D1D0; // type:function size:0x208 playBgm__12dSndBgmMgr_cFUllb = .text:0x8036D3E0; // type:function size:0x170 fn_8036D550 = .text:0x8036D550; // type:function size:0x174 -fn_8036D6D0 = .text:0x8036D6D0; // type:function size:0x60 +startBgmMuteSound__12dSndBgmMgr_cFv = .text:0x8036D6D0; // type:function size:0x60 prepareBgmSound__12dSndBgmMgr_cFUlP14dSndBgmSound_cUl = .text:0x8036D730; // type:function size:0x138 fn_8036D870 = .text:0x8036D870; // type:function size:0x1D0 prepareBgm__12dSndBgmMgr_cFUlUl = .text:0x8036DA40; // type:function size:0xA0 @@ -20435,7 +20435,7 @@ fn_8036E020 = .text:0x8036E020; // type:function size:0xC4 fn_8036E0F0 = .text:0x8036E0F0; // type:function size:0x80 stopBgmHandleIdx__12dSndBgmMgr_cFUll = .text:0x8036E170; // type:function size:0x1C fn_8036E190 = .text:0x8036E190; // type:function size:0x60 -fn_8036E1F0 = .text:0x8036E1F0; // type:function size:0x18 +endBgmMuteSound__12dSndBgmMgr_cFv = .text:0x8036E1F0; // type:function size:0x18 fn_8036E210 = .text:0x8036E210; // type:function size:0x78 fn_8036E290 = .text:0x8036E290; // type:function size:0xC0 fn_8036E350 = .text:0x8036E350; // type:function size:0x9C @@ -20819,15 +20819,15 @@ __ct__26dSndBgmMmlParserHarpSong_cFv = .text:0x8037D270; // type:function size:0 parseData__26dSndBgmMmlParserHarpSong_cFUlP18dSndHarpSongData_c = .text:0x8037D2D0; // type:function size:0x68 CommandProc__26dSndBgmMmlParserHarpSong_cCFUliUlll = .text:0x8037D340; // type:function size:0x4 NoteOnCommandProc__26dSndBgmMmlParserHarpSong_cCFUliiil = .text:0x8037D350; // type:function size:0x50 -fn_8037D3A0 = .text:0x8037D3A0; // type:function size:0x5C -fn_8037D400 = .text:0x8037D400; // type:function size:0xB0 -fn_8037D4B0 = .text:0x8037D4B0; // type:function size:0x34 -fn_8037D4F0 = .text:0x8037D4F0; // type:function size:0x64 -fn_8037D560 = .text:0x8037D560; // type:function size:0xE0 -fn_8037D640 = .text:0x8037D640; // type:function size:0x6C -fn_8037D6B0 = .text:0x8037D6B0; // type:function size:0x5C -fn_8037D710 = .text:0x8037D710; // type:function size:0x94 -fn_8037D7B0 = .text:0x8037D7B0; // type:function size:0x50 +__ct__27dSndBgmMmlParserTagBattle_cFv = .text:0x8037D3A0; // type:function size:0x5C +parseData__27dSndBgmMmlParserTagBattle_cFUlPP11dSndTagData = .text:0x8037D400; // type:function size:0xB0 +NoteOnCommandProc__27dSndBgmMmlParserTagBattle_cCFUliiil = .text:0x8037D4B0; // type:function size:0x34 +__ct__28dSndBgmMmlParserTagBgmBoss_cFv = .text:0x8037D4F0; // type:function size:0x64 +parseData__28dSndBgmMmlParserTagBgmBoss_cFPP11dSndTagDataPP11dSndTagData = .text:0x8037D560; // type:function size:0xE0 +NoteOnCommandProc__28dSndBgmMmlParserTagBgmBoss_cCFUliiil = .text:0x8037D640; // type:function size:0x6C +__ct__29dSndBgmMmlParserTagCompNote_cFv = .text:0x8037D6B0; // type:function size:0x5C +parseData__29dSndBgmMmlParserTagCompNote_cFPP11dSndTagData = .text:0x8037D710; // type:function size:0x94 +NoteOnCommandProc__29dSndBgmMmlParserTagCompNote_cCFUliiil = .text:0x8037D7B0; // type:function size:0x50 __dt__38SndMgrDisposer<20dSndSmallEffectMgr_c>Fv = .text:0x8037D800; // type:function size:0x78 create__38SndMgrDisposer<20dSndSmallEffectMgr_c>Fv = .text:0x8037D880; // type:function size:0x48 remove__38SndMgrDisposer<20dSndSmallEffectMgr_c>Fv = .text:0x8037D8D0; // type:function size:0x10 @@ -38043,9 +38043,9 @@ __vt__14dSndBgmSound_c = .data:0x805490BC; // type:object size:0x44 __vt__20dSndBgmBattleSound_c = .data:0x80549100; // type:object size:0x44 __vt__37SndMgrDisposer<19dSndBgmSeqDataMgr_c> = .data:0x80549148; // type:object size:0xC scope:weak __vt__18dSndBgmMmlParser_c = .data:0x80549158; // type:object size:0x10 -lbl_80549168 = .data:0x80549168; // type:object size:0x10 -lbl_80549178 = .data:0x80549178; // type:object size:0x10 -lbl_80549188 = .data:0x80549188; // type:object size:0x10 +__vt__29dSndBgmMmlParserTagCompNote_c = .data:0x80549168; // type:object size:0x10 +__vt__28dSndBgmMmlParserTagBgmBoss_c = .data:0x80549178; // type:object size:0x10 +__vt__27dSndBgmMmlParserTagBattle_c = .data:0x80549188; // type:object size:0x10 __vt__26dSndBgmMmlParserHarpSong_c = .data:0x80549198; // type:object size:0x10 __vt__22dSndBgmMmlParserHarp_c = .data:0x805491A8; // type:object size:0x10 __vt__12SoundStopper = .data:0x805491B8; // type:object size:0xC @@ -41097,7 +41097,7 @@ lbl_805742D8 = .sdata:0x805742D8; // type:object size:0x8 lbl_805742E0 = .sdata:0x805742E0; // type:object size:0x8 lbl_805742E8 = .sdata:0x805742E8; // type:object size:0x8 @7580 = .sdata:0x805742F0; // type:object size:0x6 scope:local data:string -lbl_805742F8 = .sdata:0x805742F8; // type:object size:0x5 data:string +@7402 = .sdata:0x805742F8; // type:object size:0x5 scope:local data:string lbl_80574300 = .sdata:0x80574300; // type:object size:0x8 data:string lbl_80574308 = .sdata:0x80574308; // type:object size:0x8 lbl_80574310 = .sdata:0x80574310; // type:object size:0x4 diff --git a/configure.py b/configure.py index 6c000cfd..4193fda8 100644 --- a/configure.py +++ b/configure.py @@ -764,7 +764,7 @@ config.libs = [ Object(Matching, "d/snd/d_snd_bgm_seq_config.cpp"), Object(Matching, "d/snd/d_snd_bgm_harp_data.cpp"), Object(Matching, "d/snd/d_snd_bgm_mml_parser_base.cpp"), - Object(NonMatching, "d/snd/d_snd_bgm_mml_parsers.cpp"), + Object(Matching, "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_song_mgr.cpp"), Object(NonMatching, "d/snd/d_snd_harp_song_data.cpp"), diff --git a/include/d/snd/d_snd_bgm_mgr.h b/include/d/snd/d_snd_bgm_mgr.h index cce578fc..604524c3 100644 --- a/include/d/snd/d_snd_bgm_mgr.h +++ b/include/d/snd/d_snd_bgm_mgr.h @@ -129,6 +129,9 @@ public: private: dSndBgmBattleSound_c *getBgmBattleSound(); + void startBgmMuteSound(); + void endBgmMuteSound(); + bool stopBgmSound(dSndBgmSound_c *sound, s32 fadeFrames); void checkForPrepareStoppedBgmSound(u32 stoppedSoundId); dSndBgmSound_c *findNewBgmSoundHandle(); @@ -171,7 +174,7 @@ private: /* 0x24C */ u32 mScheduledSoundId; /* 0x250 */ s32 mScheduledSoundDelay; /* 0x254 */ dSndBgmSound_c *mBgmSounds[7]; - /* 0x270 */ dSndBgmSound_c *field_0x270; + /* 0x270 */ dSndBgmSound_c *mpBgmMuteSound; /* 0x274 */ dSndBgmSound_c *mpPrevActiveBgmSound; /* 0x278 */ nw4r::ut::List mBgmSoundLists[BGM_LIST_MAX]; // node offset 0xF0 -> dSndBgmSound_c /* 0x29C */ UNKWORD field_0x29C; @@ -185,7 +188,7 @@ private: /* 0x306 */ u8 field_0x306; /* 0x307 */ u8 field_0x307; /* 0x308 */ u8 field_0x308; - /* 0x30C */ u32 field_0x30C[3]; + /* 0x30C */ dSndTagData *field_0x30C[3]; /* 0x318 */ u32 field_0x318[3]; /* 0x324 */ u32 field_0x324[3]; /* 0x330 */ u8 field_0x330[3]; diff --git a/include/d/snd/d_snd_bgm_mml_parsers.h b/include/d/snd/d_snd_bgm_mml_parsers.h index 0cff96f5..e36932b4 100644 --- a/include/d/snd/d_snd_bgm_mml_parsers.h +++ b/include/d/snd/d_snd_bgm_mml_parsers.h @@ -1,5 +1,5 @@ -#ifndef D_SND_BGM_MML_PARSERS__H -#define D_SND_BGM_MML_PARSERS__H +#ifndef D_SND_BGM_MML_PARSERS_H +#define D_SND_BGM_MML_PARSERS_H #include "d/snd/d_snd_bgm_mml_parser_base.h" #include "d/snd/d_snd_types.h" @@ -32,4 +32,50 @@ private: /* 0x294 */ dSndHarpSongData_c *field_0x294; }; +struct dSndTagData { + /* 0x00 */ u32 size; + /* 0x04 */ u32 data[]; +}; + +class dSndBgmMmlParserTagBattle_c : dSndBgmMmlParser_c { +public: + dSndBgmMmlParserTagBattle_c(); + + virtual void NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const override; + + bool parseData(u32 soundId, dSndTagData **pOutData); + +private: + /* 0x294 */ dSndTagData *mpBuf; + /* 0x298 */ mutable u32 mBufSize; +}; + +class dSndBgmMmlParserTagBgmBoss_c : dSndBgmMmlParser_c { +public: + dSndBgmMmlParserTagBgmBoss_c(); + + virtual void NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const override; + + void parseData(dSndTagData **pOutData1, dSndTagData **pOutData2); + +private: + /* 0x294 */ dSndTagData *mpBuf1; + /* 0x298 */ dSndTagData *mpBuf2; + /* 0x29C */ mutable u32 mBufSize1; + /* 0x2A0 */ mutable u32 mBufSize2; +}; + +class dSndBgmMmlParserTagCompNote_c : dSndBgmMmlParser_c { +public: + dSndBgmMmlParserTagCompNote_c(); + + virtual void NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const override; + + void parseData(dSndTagData **pOutData); + +private: + /* 0x294 */ dSndTagData *mpBuf; + /* 0x298 */ mutable u32 mBufSize; +}; + #endif diff --git a/include/d/snd/d_snd_types.h b/include/d/snd/d_snd_types.h index 85632917..c156c7c1 100644 --- a/include/d/snd/d_snd_types.h +++ b/include/d/snd/d_snd_types.h @@ -29,5 +29,6 @@ class dSndBgmSeqConfig; class dSndBgmBattleConfig; class dSndHarpSongData_c; +class dSndTagData; #endif diff --git a/src/d/snd/d_snd_bgm_mgr.cpp b/src/d/snd/d_snd_bgm_mgr.cpp index 1563c995..029e4c59 100644 --- a/src/d/snd/d_snd_bgm_mgr.cpp +++ b/src/d/snd/d_snd_bgm_mgr.cpp @@ -1,11 +1,14 @@ #include "d/snd/d_snd_bgm_mgr.h" #include "common.h" +#include "d/flag/storyflag_manager.h" #include "d/snd/d_snd_bgm_sound_battle.h" #include "d/snd/d_snd_bgm_sound.h" #include "d/snd/d_snd_mgr.h" +#include "d/snd/d_snd_bgm_mml_parsers.h" #include "d/snd/d_snd_player_mgr.h" #include "d/snd/d_snd_sound.h" +#include "d/snd/d_snd_state_mgr.h" #include "d/snd/d_snd_util.h" #include "d/snd/d_snd_wzsound.h" #include "nw4r/snd/snd_SoundArchive.h" @@ -59,8 +62,8 @@ dSndBgmMgr_c::dSndBgmMgr_c() mBgmSounds[i]->init(mSoundActor, i); } - field_0x270 = new dSndBgmSound_c(); - field_0x270->init(dSndMgr_c::GetInstance()->getPlayer(), 8); + mpBgmMuteSound = new dSndBgmSound_c(); + mpBgmMuteSound->init(dSndMgr_c::GetInstance()->getPlayer(), 8); for (int i = 0; i < 3; i++) { mFanSounds[i] = new dSndSound_c(); @@ -116,6 +119,72 @@ void dSndBgmMgr_c::calcLists() { } } +void dSndBgmMgr_c::loadStageSound() { + for (int i = 0; i < 3; i++) { + field_0x30C[i] = nullptr; + field_0x318[i] = 0; + field_0x324[i] = 0; + field_0x330[i] = 0; + } + + if (dSndStateMgr_c::GetInstance()->isInDemo()) { + return; + } + + if (dSndStateMgr_c::isInStage("F103")) { + // Flooded Faron Woods + if (!StoryflagManager::sInstance->getFlag(18)) { + bool ok = true; + if (!dSndPlayerMgr_c::GetInstance()->isLoadedFileForSound(TAG_BGM_EVENT_COMP_NOTE)) { + ok = dSndPlayerMgr_c::GetInstance()->loadFileForSound(TAG_BGM_EVENT_COMP_NOTE); + } + + if (ok) { + dSndBgmMmlParserTagCompNote_c parser; + parser.parseData(&field_0x30C[0]); + field_0x324[0] = field_0x30C[0]->data[0]; + } + } + } else if (dSndStateMgr_c::isInStage("F403") && dSndStateMgr_c::GetInstance()->getLayer() == 1) { + bool ok = true; + if (!dSndPlayerMgr_c::GetInstance()->isLoadedFileForSound(TAG_BGM_BATTLE_CROWD)) { + ok = dSndPlayerMgr_c::GetInstance()->loadFileForSound(TAG_BGM_BATTLE_CROWD); + } + + if (ok) { + dSndBgmMmlParserTagBattle_c parser; + parser.parseData(TAG_BGM_BATTLE_CROWD, &field_0x30C[0]); + field_0x324[0] = field_0x30C[0]->data[0]; + } + } else { + if (dSndPlayerMgr_c::GetInstance()->isLoadedFileForSound(TAG_BGM_BOSS_A)) { + bool ok = true; + // I am REALLY not sure how TAG_BGM_BOSS_A could spontaneously unload here but better + // double check I guess + if (!dSndPlayerMgr_c::GetInstance()->isLoadedFileForSound(TAG_BGM_BOSS_A)) { + // TODO types + ok = dSndMgr_c::GetInstance()->loadGroup((unsigned int)GRP_BGM_BOSS_A, nullptr, 0); + } + if (ok) { + dSndBgmMmlParserTagBgmBoss_c parser1; + parser1.parseData(&field_0x30C[0], &field_0x30C[1]); + } + + if (ok) { + dSndBgmMmlParserTagBattle_c parser; + parser.parseData(TAG_BGM_BOSS_A_CHANCE, &field_0x30C[2]); + } + } + } +} + +void dSndBgmMgr_c::startBgmMuteSound() { + if (mpBgmMuteSound != nullptr) { + mpBgmMuteSound->stop(0); + mpBgmMuteSound->startBgmSound(BGM_MUTE, 0, 0); + } +} + bool dSndBgmMgr_c::prepareBgm(u32 soundId, u32 startOffset) { if (isPlayingBgmSoundId(soundId)) { return false; @@ -147,6 +216,10 @@ bool dSndBgmMgr_c::stopBgmSound(dSndBgmSound_c *sound, s32 fadeFrames) { return false; } +void dSndBgmMgr_c::endBgmMuteSound() { + mpBgmMuteSound->stop(0); +} + void dSndBgmMgr_c::checkForPrepareStoppedBgmSound(u32 stoppedSoundId) { // TODO ??? u32 id = stoppedSoundId == BGM_SKYFIELD ? BGM_SKYFIELD : -1; diff --git a/src/d/snd/d_snd_bgm_mml_parsers.cpp b/src/d/snd/d_snd_bgm_mml_parsers.cpp index c39624fe..c440c10a 100644 --- a/src/d/snd/d_snd_bgm_mml_parsers.cpp +++ b/src/d/snd/d_snd_bgm_mml_parsers.cpp @@ -6,6 +6,7 @@ #include "d/snd/d_snd_harp_song_data.h" #include "d/snd/d_snd_mgr.h" #include "d/snd/d_snd_player_mgr.h" +#include "d/snd/d_snd_wzsound.h" #include "nw4r/snd/snd_SoundArchive.h" #include "sized_string.h" @@ -106,3 +107,119 @@ void dSndBgmMmlParserHarpSong_c::NoteOnCommandProc(u32 trackNo, int wait, int ke } } } + +dSndBgmMmlParserTagBattle_c::dSndBgmMmlParserTagBattle_c() + : dSndBgmMmlParser_c(&dSndMgr_c::GetInstance()->getPlayer(), dSndMgr_c::GetInstance()->getArchive()), + mpBuf(nullptr), + mBufSize(0) {} + +bool dSndBgmMmlParserTagBattle_c::parseData(u32 soundId, dSndTagData **pOutData) { + if (soundId == -1) { + return false; + } + // First pass, check how much memory we need + loadAndParse(soundId, (1 << 0), true); + // alloc memory + mpBuf = reinterpret_cast( + dSndMgr_c::GetInstance()->getSoundHeap()->Alloc(sizeof(dSndTagData) + mBufSize * sizeof(u32)) + ); + mpBuf->size = mBufSize; + // second pass, actually parse + mBufSize = 0; + bool ok = loadAndParse(soundId, (1 << 0), true); + *pOutData = mpBuf; + return ok; +} + +void dSndBgmMmlParserTagBattle_c::NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const { + if (key < 0x3C) { + return; + } + + if (mpBuf != nullptr) { + mpBuf->data[mBufSize] = wait; + } + mBufSize++; +} + +dSndBgmMmlParserTagBgmBoss_c::dSndBgmMmlParserTagBgmBoss_c() + : dSndBgmMmlParser_c(&dSndMgr_c::GetInstance()->getPlayer(), dSndMgr_c::GetInstance()->getArchive()), + mpBuf1(nullptr), + mpBuf2(nullptr), + mBufSize1(0), + mBufSize2(0) {} + +void dSndBgmMmlParserTagBgmBoss_c::parseData(dSndTagData **pOutData1, dSndTagData **pOutData2) { + // First pass, check how much memory we need + loadAndParse(TAG_BGM_BOSS_A, (1 << 0), true); + // alloc memory + mpBuf1 = reinterpret_cast( + dSndMgr_c::GetInstance()->getSoundHeap()->Alloc(sizeof(dSndTagData) + mBufSize1 * sizeof(u32)) + ); + mpBuf2 = reinterpret_cast( + dSndMgr_c::GetInstance()->getSoundHeap()->Alloc(sizeof(dSndTagData) + mBufSize2 * sizeof(u32)) + ); + mpBuf1->size = mBufSize1; + mpBuf2->size = mBufSize2; + // second pass, actually parse + mBufSize1 = 0; + mBufSize2 = 0; + loadAndParse(TAG_BGM_BOSS_A, (1 << 0), true); + *pOutData1 = mpBuf1; + *pOutData2 = mpBuf2; +} + +void dSndBgmMmlParserTagBgmBoss_c::NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const { + switch (key) { + case 0x3C: { + if (mpBuf1 != nullptr) { + mpBuf1->data[mBufSize1] = wait; + } + mBufSize1++; + break; + } + case 0x48: { + if (mpBuf2 != nullptr) { + mpBuf2->data[mBufSize2] = wait; + } + mBufSize2++; + break; + } + } +} + +dSndBgmMmlParserTagCompNote_c::dSndBgmMmlParserTagCompNote_c() + : dSndBgmMmlParser_c(&dSndMgr_c::GetInstance()->getPlayer(), dSndMgr_c::GetInstance()->getArchive()), + mpBuf(nullptr), + mBufSize(0) {} + +void dSndBgmMmlParserTagCompNote_c::parseData(dSndTagData **pOutData) { + // First pass, check how much memory we need + loadAndParse(TAG_BGM_EVENT_COMP_NOTE, (1 << 0), true); + // alloc memory + mpBuf = reinterpret_cast( + dSndMgr_c::GetInstance()->getSoundHeap()->Alloc(sizeof(dSndTagData) + mBufSize * sizeof(u32)) + ); + mpBuf->size = mBufSize; + // second pass, actually parse + mBufSize = 0; + loadAndParse(TAG_BGM_EVENT_COMP_NOTE, (1 << 0), true); + *pOutData = mpBuf; +} + +void dSndBgmMmlParserTagCompNote_c::NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const { + if (key < 0x3C) { + return; + } + + // TODO - signed/unsigned + u32 w = wait; + if (mpBuf != nullptr) { + if (w != 0) { + w = w < 0xC80 ? 0 : w - 0xC80; + } + mpBuf->data[mBufSize] = w; + } + + mBufSize++; +}