From 912d46761b7750b8291ca7172f9e9fb140cd268b Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Sun, 14 Apr 2024 16:36:58 -0400 Subject: [PATCH] Audio Works (#180) * initial audio work * Implements caching and fixes a ton of issues with audio * Uses correct memory sizes in mixer.c * Resets mixer values * Actually correct dmem buff values in mixer.c * Remove breakpoints * Fix sequences not playing * The forbidden type. * Forbidden TYPES?! * Thanks Louis * Thanks Louis Part 2 * Fix garbled audio * Fixed ADSR bugs * Fixes ASAN crash in loading samples. This code is causing the game to attempt to read sample data beyond the actual sample data. * Comments out the sample clamping since we aren't affecting the rest of the calculations in the function. * Fixes crashing while loading audio samples. Additionally, lowers the log level for audio commands. * Textbox SFX UB Fix * Decreases priority of more debug messages * Fixed a couple uintptr_t issues * Adds context to Jack's hack of shortcutting later loading sequences. * Audio corruption fix * Few uintptr_t fixes * Fix build on linux * Fix build on mac * call audio exit * fix sfx in dialog * unstub more audio funcs --------- Co-authored-by: Random06457 <28494085+Random06457@users.noreply.github.com> Co-authored-by: Nicholas Estelami Co-authored-by: louis <35883445+louist103@users.noreply.github.com> Co-authored-by: Adam Bird --- Dockerfile | 4 + mm/2s2h/BenPort.cpp | 160 +- mm/2s2h/mixer.c | 535 +++ mm/2s2h/mixer.h | 88 + mm/2s2h/resource/type/AudioSample.h | 4 +- mm/assets/xml/audio/Audio.xml | 3363 +++++++++++++++++ mm/include/audio/heap.h | 2 +- mm/include/audio/load.h | 9 +- mm/include/audio/soundfont.h | 24 +- mm/include/audiothread_cmd.h | 16 +- mm/include/functions.h | 3 +- mm/include/z64audio.h | 37 +- mm/src/audio/code_8019AF00.c | 21 +- mm/src/audio/lib/aisetnextbuf.c | 6 +- mm/src/audio/lib/data.c | 9 +- mm/src/audio/lib/effects.c | 8 +- mm/src/audio/lib/heap.c | 13 +- mm/src/audio/lib/load.c | 481 ++- mm/src/audio/lib/playback.c | 49 +- mm/src/audio/lib/seqplayer.c | 25 +- mm/src/audio/lib/synthesis.c | 52 +- mm/src/audio/lib/thread.c | 308 +- mm/src/audio/sequence.c | 21 +- mm/src/audio/session_config.c | 52 +- mm/src/audio/sfx.c | 6 - mm/src/code/audio_thread_manager.c | 42 +- mm/src/code/game.c | 4 +- mm/src/code/graph.c | 14 +- mm/src/code/main.c | 2 + mm/src/code/stubs.c | 40 +- mm/src/code/z_actor.c | 4 +- mm/src/code/z_actor_dlftbls.c | 2 +- mm/src/code/z_message_nes.c | 12 +- mm/src/code/z_scene.c | 2 +- .../actors/ovl_Obj_Sound/z_obj_sound.c | 3 - .../actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c | 9 +- .../actors/ovl_player_actor/z_player.c | 2 - 37 files changed, 4714 insertions(+), 718 deletions(-) create mode 100644 mm/2s2h/mixer.c create mode 100644 mm/2s2h/mixer.h create mode 100644 mm/assets/xml/audio/Audio.xml diff --git a/Dockerfile b/Dockerfile index 806cae1f6..6e7477887 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,6 +48,10 @@ RUN git clone https://github.com/libsdl-org/SDL_net.git -b SDL2 && \ cmake --build SDL_net/build --config Release --parallel && \ cmake --install SDL_net/build --config Release +RUN git clone https://github.com/libsdl-org/SDL.git -b SDL2 && \ + cmake -B SDL/build -S SDL -DCMAKE_BUILD_TYPE=Release && \ + cmake --build SDL/build --config Release --parallel && \ + cmake --install SDL/build --config Release RUN touch /root/.Xauthority && \ xauth add $MY_XAUTH_COOKIE diff --git a/mm/2s2h/BenPort.cpp b/mm/2s2h/BenPort.cpp index 08cd85350..d00509caa 100644 --- a/mm/2s2h/BenPort.cpp +++ b/mm/2s2h/BenPort.cpp @@ -1,4 +1,4 @@ -#include "BenPort.h" +#include "BenPort.h" #include #include #include @@ -267,6 +267,84 @@ extern "C" int AudioPlayer_GetDesiredBuffered(void); extern "C" void ResourceMgr_LoadDirectory(const char* resName); std::unordered_map ExtensionCache; +static struct { + std::thread thread; + std::condition_variable cv_to_thread, cv_from_thread; + std::mutex mutex; + bool running; + bool processing; +} audio; + + +void OTRAudio_Thread() { + while (audio.running) { + { + std::unique_lock Lock(audio.mutex); + while (!audio.processing && audio.running) { + audio.cv_to_thread.wait(Lock); + } + + if (!audio.running) { + break; + } + } + std::unique_lock Lock(audio.mutex); + //AudioMgr_ThreadEntry(&gAudioMgr); + // 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333.. + // in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528 + //#define SAMPLES_HIGH 560 + //#define SAMPLES_LOW 528 + // PAL values + //#define SAMPLES_HIGH 656 + //#define SAMPLES_LOW 624 + + // 44KHZ values + #define SAMPLES_HIGH 752 + #define SAMPLES_LOW 720 + + #define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 ) + #define NUM_AUDIO_CHANNELS 2 + + int samples_left = AudioPlayer_Buffered(); + u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW; + + // 3 is the maximum authentic frame divisor. + s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3]; + for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) { + AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples); + } + + AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE)); + + audio.processing = false; + audio.cv_from_thread.notify_one(); + } +} + +// C->C++ Bridge +extern "C" void OTRAudio_Init() +{ + // Precache all our samples, sequences, etc... + ResourceMgr_LoadDirectory("audio"); + + if (!audio.running) { + audio.running = true; + audio.thread = std::thread(OTRAudio_Thread); + } +} + +extern "C" void OTRAudio_Exit() { + // Tell the audio thread to stop + { + std::unique_lock Lock(audio.mutex); + audio.running = false; + } + audio.cv_to_thread.notify_all(); + + // Wait until the audio thread quit + audio.thread.join(); +} + extern "C" void OTRExtScanner() { auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*").get(); @@ -321,6 +399,7 @@ extern "C" void InitOTR() { clearMtx = (uintptr_t)&gMtxClear; //OTRMessage_Init(); + OTRAudio_Init(); //OTRExtScanner(); time_t now = time(NULL); tm* tm_now = localtime(&now); @@ -351,6 +430,7 @@ extern "C" void SaveManager_ThreadPoolWait() { extern "C" void DeinitOTR() { SaveManager_ThreadPoolWait(); + OTRAudio_Exit(); #ifdef ENABLE_CROWD_CONTROL CrowdControl::Instance->Disable(); CrowdControl::Instance->Shutdown(); @@ -509,57 +589,12 @@ void RunCommands(Gfx* Commands, const std::vector // C->C++ Bridge extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { - #if 0 - if (!audio.initialized) { - audio.initialized = true; - std::thread([]() { - for (;;) { - { - std::unique_lock Lock(audio.mutex); - while (!audio.processing) { - audio.cv_to_thread.wait(Lock); - } - } - std::unique_lock Lock(audio.mutex); -// AudioMgr_ThreadEntry(&gAudioMgr); -// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333.. -// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528 -#define SAMPLES_HIGH 560 -#define SAMPLES_LOW 528 -// PAL values -//#define SAMPLES_HIGH 656 -//#define SAMPLES_LOW 624 -#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1) -#define NUM_AUDIO_CHANNELS 2 - int samples_left = AudioPlayer_Buffered(); - u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW; - // printf("Audio samples: %d %u\n", samples_left, num_audio_samples); - - // 3 is the maximum authentic frame divisor. - s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3]; - for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) { - AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), - num_audio_samples); - } - // for (uint32_t i = 0; i < 2 * num_audio_samples; i++) { - // audio_buffer[i] = Rand_Next() & 0xFF; - //} - // printf("Audio samples before submitting: %d\n", audio_api->buffered()); - AudioPlayer_Play((u8*)audio_buffer, - num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE)); - - audio.processing = false; - audio.cv_from_thread.notify_one(); - } - }).detach(); - } { std::unique_lock Lock(audio.mutex); audio.processing = true; } - audio.cv_to_thread.notify_one(); - #endif + audio.cv_to_thread.notify_one(); std::vector> mtx_replacements; int target_fps = CVarGetInteger("gInterpolationFPS", 20); static int last_fps; @@ -607,11 +642,17 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { last_fps = fps; last_update_rate = R_UPDATE_RATE; - //{ - // std::unique_lock Lock(audio.mutex); - // while (audio.processing) { - // audio.cv_from_thread.wait(Lock); - // } + { + std::unique_lock Lock(audio.mutex); + while (audio.processing) { + audio.cv_from_thread.wait(Lock); + } + } + // + //if (ShouldClearTextureCacheAtEndOfFrame) { + // gfx_texture_cache_clear(); + // LUS::SkeletonPatcher::UpdateSkeletons(); + // ShouldClearTextureCacheAtEndOfFrame = false; //} // OTRTODO: FIGURE OUT END FRAME POINT @@ -1029,6 +1070,10 @@ extern "C" Vtx* ResourceMgr_LoadVtxByName(char* path) { return (Vtx*)ResourceGetDataByName(path); } +extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) { + SequenceData* sequence = (SequenceData*)ResourceGetDataByName(path); + return *sequence; +} extern "C" KeyFrameSkeleton* ResourceMgr_LoadKeyFrameSkelByName(const char* path) { return (KeyFrameSkeleton*)ResourceGetDataByName(path); } @@ -1036,13 +1081,6 @@ extern "C" KeyFrameSkeleton* ResourceMgr_LoadKeyFrameSkelByName(const char* path extern "C" KeyFrameAnimation* ResourceMgr_LoadKeyFrameAnimByName(const char* path) { return (KeyFrameAnimation*)ResourceGetDataByName(path); } - - -//extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) { -// SequenceData* sequence = (SequenceData*)ResourceGetDataByName(path); -// return *sequence; -//} -// //std::map cachedCustomSFs; #if 0 extern "C" SoundFontSample* ReadCustomSample(const char* path) { @@ -1104,11 +1142,11 @@ extern "C" SoundFontSample* ReadCustomSample(const char* path) { extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path) { return (SoundFontSample*)ResourceGetDataByName(path); } +#endif extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) { return (SoundFont*)ResourceGetDataByName(path); } -#endif extern "C" int ResourceMgr_OTRSigCheck(char* imgData) { uintptr_t i = (uintptr_t)(imgData); @@ -1570,7 +1608,7 @@ extern "C" void BenSysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u32 pageCo std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav"; if (isBackup) fileName += ".bak"; - + if (IS_VALID_FILE(save)) { WriteSaveFile(fileName, save); } else { diff --git a/mm/2s2h/mixer.c b/mm/2s2h/mixer.c new file mode 100644 index 000000000..66dc8f179 --- /dev/null +++ b/mm/2s2h/mixer.c @@ -0,0 +1,535 @@ +#include +#include +#include +#include + +#include "mixer.h" + +#ifndef __clang__ +#pragma GCC optimize ("unroll-loops") +#endif + +#define ROUND_UP_64(v) (((v) + 63) & ~63) +#define ROUND_UP_32(v) (((v) + 31) & ~31) +#define ROUND_UP_16(v) (((v) + 15) & ~15) +#define ROUND_UP_8(v) (((v) + 7) & ~7) +#define ROUND_DOWN_16(v) ((v) & ~0xf) + +//#define DMEM_BUF_SIZE (0x1000 - 0x0330 - 0x10 - 0x40) +#define DMEM_BUF_SIZE 0xC80 +#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x0330)) +#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x0330) / sizeof(int16_t)) + +static struct { + uint16_t in; + uint16_t out; + uint16_t nbytes; + + uint16_t vol[2]; + uint16_t rate[2]; + uint16_t vol_wet; + uint16_t rate_wet; + + ADPCM_STATE *adpcm_loop_state; + + int16_t adpcm_table[8][2][8]; + + uint16_t filter_count; + int16_t filter[8]; + + union { + int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)]; + uint8_t as_u8[DMEM_BUF_SIZE]; + } buf; +} rspa; + +static int16_t resample_table[64][4] = { + {0x0c39, 0x66ad, 0x0d46, 0xffdf}, {0x0b39, 0x6696, 0x0e5f, 0xffd8}, + {0x0a44, 0x6669, 0x0f83, 0xffd0}, {0x095a, 0x6626, 0x10b4, 0xffc8}, + {0x087d, 0x65cd, 0x11f0, 0xffbf}, {0x07ab, 0x655e, 0x1338, 0xffb6}, + {0x06e4, 0x64d9, 0x148c, 0xffac}, {0x0628, 0x643f, 0x15eb, 0xffa1}, + {0x0577, 0x638f, 0x1756, 0xff96}, {0x04d1, 0x62cb, 0x18cb, 0xff8a}, + {0x0435, 0x61f3, 0x1a4c, 0xff7e}, {0x03a4, 0x6106, 0x1bd7, 0xff71}, + {0x031c, 0x6007, 0x1d6c, 0xff64}, {0x029f, 0x5ef5, 0x1f0b, 0xff56}, + {0x022a, 0x5dd0, 0x20b3, 0xff48}, {0x01be, 0x5c9a, 0x2264, 0xff3a}, + {0x015b, 0x5b53, 0x241e, 0xff2c}, {0x0101, 0x59fc, 0x25e0, 0xff1e}, + {0x00ae, 0x5896, 0x27a9, 0xff10}, {0x0063, 0x5720, 0x297a, 0xff02}, + {0x001f, 0x559d, 0x2b50, 0xfef4}, {0xffe2, 0x540d, 0x2d2c, 0xfee8}, + {0xffac, 0x5270, 0x2f0d, 0xfedb}, {0xff7c, 0x50c7, 0x30f3, 0xfed0}, + {0xff53, 0x4f14, 0x32dc, 0xfec6}, {0xff2e, 0x4d57, 0x34c8, 0xfebd}, + {0xff0f, 0x4b91, 0x36b6, 0xfeb6}, {0xfef5, 0x49c2, 0x38a5, 0xfeb0}, + {0xfedf, 0x47ed, 0x3a95, 0xfeac}, {0xfece, 0x4611, 0x3c85, 0xfeab}, + {0xfec0, 0x4430, 0x3e74, 0xfeac}, {0xfeb6, 0x424a, 0x4060, 0xfeaf}, + {0xfeaf, 0x4060, 0x424a, 0xfeb6}, {0xfeac, 0x3e74, 0x4430, 0xfec0}, + {0xfeab, 0x3c85, 0x4611, 0xfece}, {0xfeac, 0x3a95, 0x47ed, 0xfedf}, + {0xfeb0, 0x38a5, 0x49c2, 0xfef5}, {0xfeb6, 0x36b6, 0x4b91, 0xff0f}, + {0xfebd, 0x34c8, 0x4d57, 0xff2e}, {0xfec6, 0x32dc, 0x4f14, 0xff53}, + {0xfed0, 0x30f3, 0x50c7, 0xff7c}, {0xfedb, 0x2f0d, 0x5270, 0xffac}, + {0xfee8, 0x2d2c, 0x540d, 0xffe2}, {0xfef4, 0x2b50, 0x559d, 0x001f}, + {0xff02, 0x297a, 0x5720, 0x0063}, {0xff10, 0x27a9, 0x5896, 0x00ae}, + {0xff1e, 0x25e0, 0x59fc, 0x0101}, {0xff2c, 0x241e, 0x5b53, 0x015b}, + {0xff3a, 0x2264, 0x5c9a, 0x01be}, {0xff48, 0x20b3, 0x5dd0, 0x022a}, + {0xff56, 0x1f0b, 0x5ef5, 0x029f}, {0xff64, 0x1d6c, 0x6007, 0x031c}, + {0xff71, 0x1bd7, 0x6106, 0x03a4}, {0xff7e, 0x1a4c, 0x61f3, 0x0435}, + {0xff8a, 0x18cb, 0x62cb, 0x04d1}, {0xff96, 0x1756, 0x638f, 0x0577}, + {0xffa1, 0x15eb, 0x643f, 0x0628}, {0xffac, 0x148c, 0x64d9, 0x06e4}, + {0xffb6, 0x1338, 0x655e, 0x07ab}, {0xffbf, 0x11f0, 0x65cd, 0x087d}, + {0xffc8, 0x10b4, 0x6626, 0x095a}, {0xffd0, 0x0f83, 0x6669, 0x0a44}, + {0xffd8, 0x0e5f, 0x6696, 0x0b39}, {0xffdf, 0x0d46, 0x66ad, 0x0c39} +}; + +static inline int16_t clamp16(int32_t v) { + if (v < -0x8000) { + return -0x8000; + } else if (v > 0x7fff) { + return 0x7fff; + } + return (int16_t)v; +} + +static inline int32_t clamp32(int64_t v) { + if (v < -0x7fffffff - 1) { + return -0x7fffffff - 1; + } else if (v > 0x7fffffff) { + return 0x7fffffff; + } + return (int32_t)v; +} + +void aClearBufferImpl(uint16_t addr, int nbytes) { + nbytes = ROUND_UP_16(nbytes); + memset(BUF_U8(addr), 0, nbytes); +} + +void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) { +#if __SANITIZE_ADDRESS__ + for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) { + BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i]; + } +#else + memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes)); +#endif +} + +void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) { + memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes)); +} + +void aLoadADPCMImpl(int num_entries_times_16, const int16_t *book_source_addr) { + memcpy(rspa.adpcm_table, book_source_addr, num_entries_times_16); +} + +void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes) { + rspa.in = in; + rspa.out = out; + rspa.nbytes = nbytes; +} + +void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c) { + int count = ROUND_UP_8(c) / sizeof(int16_t) / 4; + int16_t *l = BUF_S16(left); + int16_t *r = BUF_S16(right); + int16_t *d = BUF_S16(dest); + while (count > 0) { + int16_t l0 = *l++; + int16_t l1 = *l++; + int16_t l2 = *l++; + int16_t l3 = *l++; + int16_t r0 = *r++; + int16_t r1 = *r++; + int16_t r2 = *r++; + int16_t r3 = *r++; + *d++ = l0; + *d++ = r0; + *d++ = l1; + *d++ = r1; + *d++ = l2; + *d++ = r2; + *d++ = l3; + *d++ = r3; + --count; + } +} + +void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes) { + nbytes = ROUND_UP_16(nbytes); + memmove(BUF_U8(out_addr), BUF_U8(in_addr), nbytes); +} + +void aSetLoopImpl(ADPCM_STATE *adpcm_loop_state) { + rspa.adpcm_loop_state = adpcm_loop_state; +} + +void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state) { + uint8_t *in = BUF_U8(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_32(rspa.nbytes); + if (flags & A_INIT) { + memset(out, 0, 16 * sizeof(int16_t)); + } else if (flags & A_LOOP) { + memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t)); + } else { + memcpy(out, state, 16 * sizeof(int16_t)); + } + out += 16; + + while (nbytes > 0) { + int shift = *in >> 4; // should be in 0..12 or 0..14 + int table_index = *in++ & 0xf; // should be in 0..7 + int16_t (*tbl)[8] = rspa.adpcm_table[table_index]; + int i; + + for (i = 0; i < 2; i++) { + int16_t ins[8]; + int16_t prev1 = out[-1]; + int16_t prev2 = out[-2]; + int j, k; + if (flags & 4) { + for (j = 0; j < 2; j++) { + ins[j * 4] = (((*in >> 6) << 30) >> 30) << shift; + ins[j * 4 + 1] = ((((*in >> 4) & 0x3) << 30) >> 30) << shift; + ins[j * 4 + 2] = ((((*in >> 2) & 0x3) << 30) >> 30) << shift; + ins[j * 4 + 3] = (((*in++ & 0x3) << 30) >> 30) << shift; + } + } else { + for (j = 0; j < 4; j++) { + ins[j * 2] = (((*in >> 4) << 28) >> 28) << shift; + ins[j * 2 + 1] = (((*in++ & 0xf) << 28) >> 28) << shift; + } + } + for (j = 0; j < 8; j++) { + int32_t acc = tbl[0][j] * prev2 + tbl[1][j] * prev1 + (ins[j] << 11); + for (k = 0; k < j; k++) { + acc += tbl[1][((j - k) - 1)] * ins[k]; + } + acc >>= 11; + *out++ = clamp16(acc); + } + } + nbytes -= 16 * sizeof(int16_t); + } + memcpy(state, out - 16, 16 * sizeof(int16_t)); +} + +void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state) { + int16_t tmp[16]; + int16_t *in_initial = BUF_S16(rspa.in); + int16_t *in = in_initial; + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_16(rspa.nbytes); + uint32_t pitch_accumulator; + int i; + int16_t *tbl; + int32_t sample; + + if (flags & A_INIT) { + memset(tmp, 0, 5 * sizeof(int16_t)); + } else { + memcpy(tmp, state, 16 * sizeof(int16_t)); + } + if (flags & 2) { + memcpy(in - 8, tmp + 8, 8 * sizeof(int16_t)); + in -= tmp[5] / sizeof(int16_t); + } + in -= 4; + pitch_accumulator = (uint16_t)tmp[4]; + memcpy(in, tmp, 4 * sizeof(int16_t)); + + do { + for (i = 0; i < 8; i++) { + tbl = resample_table[pitch_accumulator * 64 >> 16]; + sample = ((in[0] * tbl[0] + 0x4000) >> 15) + + ((in[1] * tbl[1] + 0x4000) >> 15) + + ((in[2] * tbl[2] + 0x4000) >> 15) + + ((in[3] * tbl[3] + 0x4000) >> 15); + *out++ = clamp16(sample); + + pitch_accumulator += (pitch << 1); + in += pitch_accumulator >> 16; + pitch_accumulator %= 0x10000; + } + nbytes -= 8 * sizeof(int16_t); + } while (nbytes > 0); + + state[4] = (int16_t)pitch_accumulator; + memcpy(state, in, 4 * sizeof(int16_t)); + i = (in - in_initial + 4) & 7; + in -= i; + if (i != 0) { + i = -8 - i; + } + state[5] = i; + memcpy(state + 8, in, 8 * sizeof(int16_t)); +} + +void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right) { + rspa.vol_wet = (uint16_t)(initial_vol_wet << 8); + rspa.rate_wet = rate_wet; + rspa.rate[0] = rate_left; + rspa.rate[1] = rate_right; +} + +void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right) { + rspa.vol[0] = initial_vol_left; + rspa.vol[1] = initial_vol_right; +} + +void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, + bool neg_3, bool neg_2, + bool neg_left, bool neg_right, + int32_t wet_dry_addr, u32 unk) +{ + int16_t *in = BUF_S16(in_addr); + int16_t *dry[2] = {BUF_S16(((wet_dry_addr >> 24) & 0xFF) << 4), BUF_S16(((wet_dry_addr >> 16) & 0xFF) << 4)}; + int16_t *wet[2] = {BUF_S16(((wet_dry_addr >> 8) & 0xFF) << 4), BUF_S16(((wet_dry_addr) & 0xFF) << 4)}; + int16_t negs[4] = {neg_left ? -1 : 0, neg_right ? -1 : 0, neg_3 ? -4 : 0, neg_2 ? -2 : 0}; + int swapped[2] = {swap_reverb ? 1 : 0, swap_reverb ? 0 : 1}; + int n = ROUND_UP_16(n_samples); + + uint16_t vols[2] = {rspa.vol[0], rspa.vol[1]}; + uint16_t rates[2] = {rspa.rate[0], rspa.rate[1]}; + uint16_t vol_wet = rspa.vol_wet; + uint16_t rate_wet = rspa.rate_wet; + + do { + for (int i = 0; i < 8; i++) { + int16_t samples[2] = {*in, *in}; in++; + for (int j = 0; j < 2; j++) { + samples[j] = (samples[j] * vols[j] >> 16) ^ negs[j]; + } + for (int j = 0; j < 2; j++) { + *dry[j] = clamp16(*dry[j] + samples[j]); dry[j]++; + *wet[j] = clamp16(*wet[j] + ((samples[swapped[j]] * vol_wet >> 16) ^ negs[2 + j])); wet[j]++; + } + } + vols[0] += rates[0]; + vols[1] += rates[1]; + vol_wet += rate_wet; + + n -= 8; + } while (n > 0); +} + +void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) { + int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4)); + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int i; + int32_t sample; + + if (gain == -0x8000) { + while (nbytes > 0) { + for (i = 0; i < 16; i++) { + sample = *out - *in++; + *out++ = clamp16(sample); + } + nbytes -= 16 * sizeof(int16_t); + } + } + + while (nbytes > 0) { + for (i = 0; i < 16; i++) { + sample = ((*out * 0x7fff + *in++ * gain) + 0x4000) >> 15; + *out++ = clamp16(sample); + } + + nbytes -= 16 * sizeof(int16_t); + } +} + +void aS8DecImpl(uint8_t flags, ADPCM_STATE state) { + uint8_t *in = BUF_U8(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_32(rspa.nbytes); + if (flags & A_INIT) { + memset(out, 0, 16 * sizeof(int16_t)); + } else if (flags & A_LOOP) { + memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t)); + } else { + memcpy(out, state, 16 * sizeof(int16_t)); + } + out += 16; + + while (nbytes > 0) { + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + + nbytes -= 16 * sizeof(int16_t); + } + + memcpy(state, out - 16, 16 * sizeof(int16_t)); +} + +void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) { + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int nbytes = ROUND_UP_64(ROUND_DOWN_16(count)); + + do { + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + + nbytes -= 16 * sizeof(int16_t); + } while (nbytes > 0); +} + +void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) { + uint8_t* in = BUF_U8(in_addr); + uint8_t *out = BUF_U8(out_addr); + + uint8_t tmp[128]; + memcpy(tmp, in, 128); + do { + memcpy(out, tmp, 128); + out += 128; + } while (count-- > 0); +} + +void aResampleZohImpl(uint16_t pitch, uint16_t start_fract) { + int16_t *in = BUF_S16(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_8(rspa.nbytes); + uint32_t pos = start_fract; + uint32_t pitch_add = pitch << 2; + + do { + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + + nbytes -= 4 * sizeof(int16_t); + } while (nbytes > 0); +} + +void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples) { + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int n = ROUND_UP_8(n_samples); + + do { + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + + n -= 8; + } while (n > 0); +} + +void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t *state_or_filter) { + if (flags > A_INIT) { + rspa.filter_count = ROUND_UP_16(count_or_buf); + memcpy(rspa.filter, state_or_filter, sizeof(rspa.filter)); + } else { + int16_t tmp[16], tmp2[8]; + int count = rspa.filter_count; + int16_t *buf = BUF_S16(count_or_buf); + + if (flags == A_INIT) { +#ifndef __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmemset-elt-size" +#endif + memset(tmp, 0, 8 * sizeof(int16_t)); +#ifndef __clang__ +#pragma GCC diagnostic pop +#endif + memset(tmp2, 0, 8 * sizeof(int16_t)); + } else { + memcpy(tmp, state_or_filter, 8 * sizeof(int16_t)); + memcpy(tmp2, state_or_filter + 8, 8 * sizeof(int16_t)); + } + + for (int i = 0; i < 8; i++) { + rspa.filter[i] = (tmp2[i] + rspa.filter[i]) / 2; + } + + do { + memcpy(tmp + 8, buf, 8 * sizeof(int16_t)); + for (int i = 0; i < 8; i++) { + int64_t sample = 0x4000; // round term + for (int j = 0; j < 8; j++) { + sample += tmp[i + j] * rspa.filter[7 - j]; + } + buf[i] = clamp16((int32_t)(sample >> 15)); + } + memcpy(tmp, tmp + 8, 8 * sizeof(int16_t)); + + buf += 8; + count -= 8 * sizeof(int16_t); + } while (count > 0); + + memcpy(state_or_filter, tmp, 8 * sizeof(int16_t)); + memcpy(state_or_filter + 8, rspa.filter, 8 * sizeof(int16_t)); + } +} + +void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr) { + int16_t *samples = BUF_S16(addr); + int nbytes = ROUND_UP_32(count); + + do { + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + + nbytes -= 8; + } while (nbytes > 0); +} + +void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c) { +} + +void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr) { + int nbytes = ROUND_UP_64(count); + int16_t *in = BUF_S16(in_addr + f); + int16_t *out = BUF_S16(out_addr); + int16_t tbl[32]; + + memcpy(tbl, in, 32 * sizeof(int16_t)); + do { + for (int i = 0; i < 32; i++) { + out[i] = clamp16(out[i] * tbl[i]); + } + out += 32; + nbytes -= 32 * sizeof(int16_t); + } while (nbytes > 0); +} diff --git a/mm/2s2h/mixer.h b/mm/2s2h/mixer.h new file mode 100644 index 000000000..6bde9621e --- /dev/null +++ b/mm/2s2h/mixer.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include "libultraship/libultra/abi.h" + +#undef aSegment +#undef aClearBuffer +#undef aSetBuffer +#undef aLoadBuffer +#undef aSaveBuffer +#undef aDMEMMove +#undef aMix +#undef aEnvMixer +#undef aResample +#undef aInterleave +#undef aSetVolume +#undef aSetVolume32 +#undef aSetLoop +#undef aLoadADPCM +#undef aADPCMdec +#undef aS8Dec +#undef aAddMixer +#undef aDuplicate +#undef aDMEMMove2 +#undef aResampleZoh +#undef aEnvSetup1 +#undef aEnvSetup2 +#undef aFilter +#undef aHiLoGain +#undef aInterl +#undef aUnkCmd3 +#undef aUnkCmd19 + +void aClearBufferImpl(uint16_t addr, int nbytes); +void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes); +void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes); +void aLoadADPCMImpl(int num_entries_times_16, const int16_t* book_source_addr); +void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes); +void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c); +void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes); +void aSetLoopImpl(ADPCM_STATE* adpcm_loop_state); +void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state); +void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state); +void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right); +void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right); +void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, bool neg_3, bool neg_2, bool neg_left, + bool neg_right, int32_t wet_dry_addr, u32 unk); +void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr); +void aS8DecImpl(uint8_t flags, ADPCM_STATE state); +void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr); +void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr); +void aResampleZohImpl(uint16_t pitch, uint16_t start_fract); +void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples); +void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t* state_or_filter); +void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr); +void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c); +void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr); + +#define aSegment(pkt, s, b) \ + do { \ + } while (0) +#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c) +#define aLoadBuffer(pkt, s, d, c) aLoadBufferImpl(s, d, c) +#define aSaveBuffer(pkt, s, d, c) aSaveBufferImpl(s, d, c) +#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, d) +#define aSetBuffer(pkt, f, i, o, c) aSetBufferImpl(f, i, o, c) +#define aInterleave(pkt, o, l, r, c) aInterleaveImpl(o, l, r, c) +#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c) +#define aSetLoop(pkt, a) aSetLoopImpl(a) +#define aADPCMdec(pkt, f, s) aADPCMdecImpl(f, s) +#define aResample(pkt, f, p, s) aResampleImpl(f, p, s) +#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \ + aEnvSetup1Impl(initialVolReverb, rampReverb, rampLeft, rampRight) +#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) aEnvSetup2Impl(initialVolLeft, initialVolRight) +#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) \ + aEnvMixerImpl(inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) +#define aMix(pkt, c, g, i, o) aMixImpl(c, g, i, o) +#define aS8Dec(pkt, f, s) aS8DecImpl(f, s) +#define aAddMixer(pkt, s, d, c) aAddMixerImpl(s, d, c) +#define aDuplicate(pkt, s, d, c) aDuplicateImpl(s, d, c) +#define aDMEMMove2(pkt, t, i, o, c) aDMEMMove2Impl(t, i, o, c) +#define aResampleZoh(pkt, pitch, startFract) aResampleZohImpl(pitch, startFract) +#define aInterl(pkt, dmemi, dmemo, count) aInterlImpl(dmemi, dmemo, count) +#define aFilter(pkt, f, countOrBuf, addr) aFilterImpl(f, countOrBuf, addr) +#define aHiLoGain(pkt, g, buflen, i, a4) aHiLoGainImpl(g, buflen, i) +#define aUnkCmd3(pkt, a1, a2, a3) aUnkCmd3Impl(a1, a2, a3) +#define aUnkCmd19(pkt, a1, a2, a3, a4) aUnkCmd19Impl(a1, a2, a3, a4) diff --git a/mm/2s2h/resource/type/AudioSample.h b/mm/2s2h/resource/type/AudioSample.h index 8ff320585..76511ece3 100644 --- a/mm/2s2h/resource/type/AudioSample.h +++ b/mm/2s2h/resource/type/AudioSample.h @@ -7,8 +7,8 @@ namespace SOH { typedef struct { - /* 0x00 */ uintptr_t start; - /* 0x04 */ uintptr_t end; + /* 0x00 */ u32 start; + /* 0x04 */ u32 end; /* 0x08 */ u32 count; /* 0x0C */ char unk_0C[0x4]; /* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned diff --git a/mm/assets/xml/audio/Audio.xml b/mm/assets/xml/audio/Audio.xml new file mode 100644 index 000000000..dd1cfefc1 --- /dev/null +++ b/mm/assets/xml/audio/Audio.xml @@ -0,0 +1,3363 @@ + + + + + diff --git a/mm/include/audio/heap.h b/mm/include/audio/heap.h index 33f3dfcd9..7a6d75c6f 100644 --- a/mm/include/audio/heap.h +++ b/mm/include/audio/heap.h @@ -106,6 +106,6 @@ void* AudioHeap_SearchPermanentCache(s32 tableType, s32 id); void* AudioHeap_AllocPermanent(s32 tableType, s32 id, size_t size); void* AudioHeap_AllocSampleCache(size_t size, s32 sampleBankId, void* sampleAddr, s8 medium, s32 cache); void AudioHeap_ApplySampleBankCache(s32 sampleBankId); -void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit); +void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, uintptr_t data, s32 isFirstInit); #endif diff --git a/mm/include/audio/load.h b/mm/include/audio/load.h index eccdc2db2..aeeb82aee 100644 --- a/mm/include/audio/load.h +++ b/mm/include/audio/load.h @@ -35,7 +35,7 @@ typedef struct { /* 0x04 */ uintptr_t romAddr; /* 0x08 */ char pad[0x8]; /* 0x10 */ AudioTableEntry entries[1]; // (dynamic size) -} AudioTable; // size >= 0x20 +} AudioTable; // size >= 0x20 typedef enum { /* 0 */ LOAD_STATUS_NOT_LOADED, @@ -88,7 +88,8 @@ typedef struct { /* 0x10 */ u8* ramAddr; /* 0x14 */ s32 status; /* 0x18 */ size_t bytesRemaining; - /* 0x1C */ s8* isDone; // TODO: rename in OoT and sync up here. This is an external status while (s32 status) is an internal status + /* 0x1C */ s8* isDone; // TODO: rename in OoT and sync up here. This is an external status while (s32 status) is an + // internal status /* 0x20 */ struct Sample sample; /* 0x30 */ OSMesgQueue msgqueue; /* 0x48 */ OSMesg msg; @@ -103,7 +104,7 @@ typedef struct { /* 0xC */ u8 unused; /* 0xD */ u8 reuseIndex; // position in sSampleDmaReuseQueue1/2, if ttl == 0 /* 0xE */ u8 ttl; // Time To Live: duration after which the DMA can be discarded -} SampleDma; // size = 0x10 +} SampleDma; // size = 0x10 typedef struct { /* 0x00 */ u32 endAndMediumKey; @@ -125,7 +126,7 @@ s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId); void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue); void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue); void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* retQueue); -u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts); +u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff); void AudioLoad_DiscardSeqFonts(s32 seqId); void func_8018FA60(u32 tableType, u32 id, s32 type, s32 data); s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2); diff --git a/mm/include/audio/soundfont.h b/mm/include/audio/soundfont.h index 0141d9f8c..8ace4eb14 100644 --- a/mm/include/audio/soundfont.h +++ b/mm/include/audio/soundfont.h @@ -7,7 +7,7 @@ struct EnvelopePoint; typedef struct AdpcmLoop { /* 0x00 */ u32 start; - /* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends + /* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends /* 0x08 */ u32 count; // The number of times the loop is played before the sound completes. Setting count to -1 indicates that the loop should play indefinitely. /* 0x0C */ u32 sampleEnd; // total number of s16-samples in the sample audio clip /* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned @@ -20,7 +20,7 @@ typedef struct AdpcmLoop { typedef struct AdpcmBook { /* 0x0 */ s32 order; /* 0x4 */ s32 numPredictors; - /* 0x8 */ s16 codeBook[1]; // a table of prediction coefficients that the coder selects from to optimize sound quality. + /* 0x8 */ s16* codeBook; // a table of prediction coefficients that the coder selects from to optimize sound quality. } AdpcmBook; // size >= 0x8 typedef enum SampleCodec { @@ -43,15 +43,22 @@ typedef enum SampleMedium { } SampleMedium; typedef struct Sample { - /* 0x0 */ u32 unk_0 : 1; - /* 0x0 */ u32 codec : 3; // The state of compression or decompression, See `SampleCodec` - /* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium` - /* 0x0 */ u32 unk_bit26 : 1; - /* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers) - /* 0x1 */ u32 size : 24; // Size of the sample + union { + struct { + ///* 0x0 */ u32 unk_0 : 1; + /* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec` + /* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium` + /* 0x0 */ u32 unk_bit26 : 1; + /* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers) + /* 0x1 */ u32 size : 24; // Size of the sample + }; + u32 asU32; + }; /* 0x4 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram /* 0x8 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram /* 0xC */ AdpcmBook* book; // Adpcm book parameters used by the sample. Offset from the start of the sound font / pointer to ram + u32 sampleRateMagicValue; // For wav samples only... + s32 sampleRate; // For wav samples only... } Sample; // size = 0x10 typedef struct TunedSample { @@ -96,6 +103,7 @@ typedef struct SoundFont { /* 0x08 */ Instrument** instruments; /* 0x0C */ Drum** drums; /* 0x10 */ SoundEffect* soundEffects; + s32 fntIndex; } SoundFont; // size = 0x14 #endif diff --git a/mm/include/audiothread_cmd.h b/mm/include/audiothread_cmd.h index 5fe7021fc..8e3f3b2cd 100644 --- a/mm/include/audiothread_cmd.h +++ b/mm/include/audiothread_cmd.h @@ -248,7 +248,7 @@ typedef enum { * @param sfxState */ #define AUDIOCMD_CHANNEL_SET_SFX_STATE(seqPlayerIndex, channelIndex, sfxState) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE, seqPlayerIndex, channelIndex, 0), (s32)sfxState) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE, seqPlayerIndex, channelIndex, 0), (void*)sfxState) /** * Set the reverb index. @@ -282,7 +282,7 @@ typedef enum { * @param filter */ #define AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, channelIndex, filterCutoff, filter) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_FILTER, seqPlayerIndex, channelIndex, filterCutoff), \ + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_FILTER, seqPlayerIndex, channelIndex, filterCutoff), \ filter) /** @@ -456,7 +456,7 @@ typedef enum { * @param drumPtr (s32) the ptr to the `Drum` struct */ #define AUDIOCMD_GLOBAL_SET_DRUM_FONT(fontId, drumId, drumPtr) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT, 0, fontId, drumId), drumPtr) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT, 0, fontId, drumId), drumPtr) /** * Set a soundeffect ptr within a soundfont @@ -466,7 +466,7 @@ typedef enum { * @param soundEffectPtr (s32) the ptr to the `SoundEffect` struct */ #define AUDIOCMD_GLOBAL_SET_SFX_FONT(fontId, soundEffectId, soundEffectPtr) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT, 0, fontId, soundEffectId), soundEffectPtr) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT, 0, fontId, soundEffectId), soundEffectPtr) /** * Set an instrument ptr within a soundfont @@ -476,7 +476,7 @@ typedef enum { * @param instPtr (s32) the ptr to the `Instrument` struct */ #define AUDIOCMD_GLOBAL_SET_INSTRUMENT_FONT(fontId, instId, instPtr) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT, 0, fontId, instId), instPtr) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT, 0, fontId, instId), instPtr) /** * Pop the persistent cache of the specified table @@ -493,7 +493,7 @@ typedef enum { * @param functionPtr */ #define AUDIOCMD_GLOBAL_SET_CUSTOM_FUNCTION(functionType, functionPtr) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION, 0, 0, functionType), (s32)functionPtr) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION, 0, 0, functionType), functionPtr) /** * Do something related to the unloaded-type audio data in the heap. @@ -514,7 +514,7 @@ typedef enum { * @param data */ #define AUDIOCMD_GLOBAL_SET_REVERB_DATA(reverbIndex, dataType, data) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA, dataType, reverbIndex, 0), (s32)data) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA, dataType, reverbIndex, 0), (uintptr_t)data) /** * Change the sound mode of audio @@ -608,7 +608,7 @@ typedef enum { * @param functionPtr (s32) address of the function to run once every audio frame */ #define AUDIOCMD_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION(functionPtr) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION, 0, 0, 0), functionPtr) + AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION, 0, 0, 0), functionPtr) /** * Asynchronously load a sequence diff --git a/mm/include/functions.h b/mm/include/functions.h index 5a319577a..4f9da7113 100644 --- a/mm/include/functions.h +++ b/mm/include/functions.h @@ -1161,9 +1161,10 @@ void AudioThread_QueueCmdF32(u32 opArgs, f32 data); void AudioThread_QueueCmdS32(u32 opArgs, s32 data); void AudioThread_QueueCmdS8(u32 opArgs, s8 data); void AudioThread_QueueCmdU16(u32 opArgs, u16 data); +void AudioThread_QueueCmdPtr(u32 opArgs, void* data); s32 AudioThread_ScheduleProcessCmds(void); u32 AudioThread_GetExternalLoadQueueMsg(u32* retMsg); -u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts); +u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff); s32 func_80193C5C(void); s32 AudioThread_ResetAudioHeap(s32 specId); void AudioThread_PreNMIInternal(void); diff --git a/mm/include/z64audio.h b/mm/include/z64audio.h index 7beabf7e8..5834c5890 100644 --- a/mm/include/z64audio.h +++ b/mm/include/z64audio.h @@ -581,12 +581,19 @@ typedef struct { typedef struct { union { - /* 0x0 */ u32 opArgs; + u32 opArgs; struct { - /* 0x0 */ u8 op; - /* 0x1 */ u8 arg0; - /* 0x2 */ u8 arg1; - /* 0x3 */ u8 arg2; +#ifdef IS_BIGENDIAN + u8 op; + u8 arg0; + u8 arg1; + u8 arg2; +#else + u8 arg2; + u8 arg1; + u8 arg0; + u8 op; +#endif }; }; union { @@ -597,9 +604,9 @@ typedef struct { /* 0x4 */ s8 asSbyte; /* 0x4 */ u8 asUbyte; /* 0x4 */ u32 asUInt; - /* 0x4 */ void* asPtr; + /* 0x4 */ uintptr_t asPtr; }; -} AudioCmd; // size = 0x8 +} AudioCmd; typedef struct { /* 0x00 */ OSTask task; @@ -706,7 +713,7 @@ typedef struct { /* 0x435C */ AudioCommonPoolSplit temporaryCommonPoolSplit; // splits temporary common pool into caches for sequences, soundFonts, sample banks /* 0x4368 */ u8 sampleFontLoadStatus[0x30]; /* 0x4398 */ u8 fontLoadStatus[0x30]; - /* 0x43C8 */ u8 seqLoadStatus[0x80]; + /* 0x43C8 */ u8* seqLoadStatus; /* 0x4448 */ volatile u8 resetStatus; /* 0x4449 */ u8 specId; /* 0x444C */ s32 audioResetFadeOutFramesLeft; @@ -735,6 +742,8 @@ typedef struct { /* 0x79E4 */ OSMesg threadCmdProcMsgBuf[4]; /* 0x79F4 */ AudioCmd threadCmdBuf[0x100]; // Audio commands used to transfer audio requests from the graph thread to the audio thread /* 0x81F4 */ UNK_TYPE1 unk_81F4[4]; + u16 seqToPlay[4]; + u8 seqReplaced[4]; } AudioContext; // size = 0x81F8 typedef struct { @@ -924,6 +933,8 @@ typedef struct { // Apply a low-pass filter with a lowPassCutoff of 4 #define SFX_FLAG2_APPLY_LOWPASS_FILTER (1 << 7) +#define MAX_AUTHENTIC_SEQID 128 + typedef struct { /* 0x0 */ u8 importance; /* 0x1 */ u8 flags; @@ -937,4 +948,14 @@ typedef Acmd* (*AudioCustomSynthFunction)(Acmd*, s32, s32); extern OSVoiceHandle gVoiceHandle; +typedef struct { + char* seqData; + int32_t seqDataSize; + uint16_t seqNumber; + uint8_t medium; + uint8_t cachePolicy; + int32_t numFonts; + uint8_t fonts[16]; +} SequenceData; + #endif diff --git a/mm/src/audio/code_8019AF00.c b/mm/src/audio/code_8019AF00.c index 2dfa2342c..4b4d50899 100644 --- a/mm/src/audio/code_8019AF00.c +++ b/mm/src/audio/code_8019AF00.c @@ -1674,7 +1674,7 @@ u8 sCustomSequenceScript[400] = { /* 40 */ 0x80, // testlayer 0 // (no end or loop; channel script seems to run into the note layers?) - + // .layer layer0 /* 41 */ 0xF3, -4, // rbeqz chan_loop @@ -1683,8 +1683,8 @@ u8 sCustomSequenceScript[400] = { // .layer layer2? /* 44 */ 0xC2, -5, // transpose -5 - /* 46 */ 0xC0, 0, // ldelay 0 - /* 48 */ 0xC1, 87, // shortvel 87 + /* 46 */ 0xC0, 0, // ldelay 0 + /* 48 */ 0xC1, 87, // shortvel 87 /* 50 */ 0xC9, 0, // shortgate 0 /* 52 */ 0, // empty until the end }; @@ -2744,8 +2744,6 @@ void AudioOcarina_SetOcarinaDisableTimer(u8 unused, u8 timer) { } void AudioOcarina_SetInstrument(u8 ocarinaInstrumentId) { - // BENTODO: Crashes on kaleido when moving back and forth between songs - return; if ((sOcarinaInstrumentId != ocarinaInstrumentId) || (ocarinaInstrumentId == OCARINA_INSTRUMENT_DEFAULT)) { SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 1, ocarinaInstrumentId); sOcarinaInstrumentId = ocarinaInstrumentId; @@ -4933,10 +4931,11 @@ void Audio_SetSequenceProperties(u8 seqPlayerIndex, Vec3f* projectedPos, s16 fla if (flags & 8) { // Uses new filter gBandPassFilterData AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x54, - ((u32)&sSequenceFilter[0] & ~0xF) + 0x10); + ((uintptr_t)&sSequenceFilter[0] & ~0xF) + 0x10); } else { // Identity Filter - AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0, ((u32)&sSequenceFilter[0] & ~0xF) + 0x10); + AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0, + ((uintptr_t)&sSequenceFilter[0] & ~0xF) + 0x10); } if (flags & 0x10) { @@ -5649,15 +5648,17 @@ void Audio_MuteBgmPlayersForFanfare(void) { * Sets up seqId to play on seqPlayerIndex 1 */ void Audio_PlayFanfare(u16 seqId) { + u8 prevFontBuff[16]; + u8 fontBuff[16]; u16 prevSeqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE); u32 outNumFonts; - u8* prevFontId = AudioThread_GetFontsForSequence(prevSeqId & 0xFF, &outNumFonts); - u8* fontId = AudioThread_GetFontsForSequence(seqId & 0xFF, &outNumFonts); + u8* prevFontId = AudioThread_GetFontsForSequence(prevSeqId & 0xFF, &outNumFonts, prevFontBuff); + u8* fontId = AudioThread_GetFontsForSequence(seqId & 0xFF, &outNumFonts, fontBuff); // BENTODO // #region 2S2H [Audio] TODO: Fixes fanfare crash, should/can be removed after audio is done // if ((prevSeqId == NA_BGM_DISABLED) || (*prevFontId == *fontId)) { if ((prevSeqId == NA_BGM_DISABLED) || (prevFontId != NULL && fontId != NULL && *prevFontId == *fontId)) { - // #endregion + // #endregion sFanfareState = 1; } else { sFanfareState = 5; diff --git a/mm/src/audio/lib/aisetnextbuf.c b/mm/src/audio/lib/aisetnextbuf.c index 57f8ade57..d58421161 100644 --- a/mm/src/audio/lib/aisetnextbuf.c +++ b/mm/src/audio/lib/aisetnextbuf.c @@ -5,13 +5,13 @@ s32 osAiSetNextBuffer(void* buf, u32 size) { static u8 D_801D6010 = false; - u32 bufAdjusted = (u32)buf; + uintptr_t bufAdjusted = (uintptr_t)buf; s32 status; if (D_801D6010) { - bufAdjusted = (u32)buf - 0x2000; + bufAdjusted = (uintptr_t)buf - 0x2000; } - if ((((u32)buf + size) & 0x1FFF) == 0) { + if ((((uintptr_t)buf + size) & 0x1FFF) == 0) { D_801D6010 = true; } else { D_801D6010 = false; diff --git a/mm/src/audio/lib/data.c b/mm/src/audio/lib/data.c index ee56e5d10..814e9ab80 100644 --- a/mm/src/audio/lib/data.c +++ b/mm/src/audio/lib/data.c @@ -1,4 +1,5 @@ #include "global.h" +#include "endianness.h" s16 gLowPassFilterData[16 * 8] ALIGNED(16) = { /* 0x0 */ 0, 0, 0, 32767, 0, 0, 0, 0, // Identity filter (delta function) @@ -851,10 +852,10 @@ u8 gDefaultShortNoteGateTimeTable[] = { }; EnvelopePoint gDefaultEnvelope[] = { - { 1, 32000 }, - { 1000, 32000 }, - { ADSR_HANG, 0 }, - { ADSR_DISABLE, 0 }, + { BE16SWAP_CONST(1), BE16SWAP_CONST(32000) }, + { BE16SWAP_CONST(1000), BE16SWAP_CONST(32000) }, + { BE16SWAP_CONST(ADSR_HANG), BE16SWAP_CONST(0) }, + { BE16SWAP_CONST(ADSR_DISABLE), BE16SWAP_CONST(0) }, }; NoteSampleState gZeroedSampleState = { 0 }; diff --git a/mm/src/audio/lib/effects.c b/mm/src/audio/lib/effects.c index 93d895514..0fd631462 100644 --- a/mm/src/audio/lib/effects.c +++ b/mm/src/audio/lib/effects.c @@ -11,6 +11,7 @@ */ #include "global.h" #include "audio/effects.h" +#include "endianness.h" void AudioScript_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculateVolume, s32 applyBend) { f32 channelVolume; @@ -273,7 +274,7 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) { // fallthrough retry: case ADSR_STATUS_LOOP: - adsr->delay = adsr->envelope[adsr->envelopeIndex].delay; + adsr->delay = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].delay); switch (adsr->delay) { case ADSR_DISABLE: adsr->action.s.status = ADSR_STATUS_DISABLED; @@ -284,7 +285,7 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) { break; case ADSR_GOTO: - adsr->envelopeIndex = adsr->envelope[adsr->envelopeIndex].arg; + adsr->envelopeIndex = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].arg); goto retry; case ADSR_RESTART: @@ -296,7 +297,8 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) { if (adsr->delay == 0) { adsr->delay = 1; } - adsr->target = adsr->envelope[adsr->envelopeIndex].arg / 32767.0f; + + adsr->target = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].arg) / 32767.0f; adsr->target = SQ(adsr->target); adsr->velocity = (adsr->target - adsr->current) / adsr->delay; adsr->action.s.status = ADSR_STATUS_FADE; diff --git a/mm/src/audio/lib/heap.c b/mm/src/audio/lib/heap.c index e4412bc94..709cfa873 100644 --- a/mm/src/audio/lib/heap.c +++ b/mm/src/audio/lib/heap.c @@ -13,6 +13,8 @@ void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId); void AudioHeap_DiscardSampleBanks(void); void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit); +extern size_t gSequenceToResourceSize; + #define gTatumsPerBeat (gAudioTatumInit[1]) /** @@ -66,7 +68,7 @@ void AudioHeap_ResetLoadStatus(void) { } } - for (i = 0; i < ARRAY_COUNT(gAudioCtx.seqLoadStatus); i++) { + for (i = 0; i < gSequenceToResourceSize; i++) { if (gAudioCtx.seqLoadStatus[i] != LOAD_STATUS_PERMANENT) { gAudioCtx.seqLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } @@ -123,6 +125,7 @@ void AudioHeap_DiscardSequence(s32 seqId) { * Perform a writeback from the L1 data cache to the ram. */ void* AudioHeap_WritebackDCache(void* addr, size_t size) { + return addr; Audio_WritebackDCache(addr, size); if (addr) {} @@ -1110,9 +1113,9 @@ void* AudioHeap_AllocPermanent(s32 tableType, s32 id, size_t size) { gAudioCtx.permanentEntries[index].size = size; //! @bug UB: missing return. "addr" is in v0 at this point, but doing an // explicit return uses an additional register. -#ifdef AVOID_UB + // #ifdef AVOID_UB return addr; -#endif + // #endif } void* AudioHeap_AllocSampleCache(size_t size, s32 sampleBankId, void* sampleAddr, s8 medium, s32 cache) { @@ -1359,6 +1362,8 @@ void AudioHeap_DiscardSampleCacheForFont(SampleCacheEntry* entry, s32 sampleBank } void AudioHeap_DiscardSampleCaches(void) { + return; + s32 numFonts; s32 sampleBankId1; s32 sampleBankId2; @@ -1529,7 +1534,7 @@ void AudioHeap_DiscardSampleBanks(void) { } } -void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit) { +void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, uintptr_t data, s32 isFirstInit) { s32 delayNumSamples; SynthesisReverb* reverb = &gAudioCtx.synthesisReverbs[reverbIndex]; diff --git a/mm/src/audio/lib/load.c b/mm/src/audio/lib/load.c index 563762cc1..229fa315a 100644 --- a/mm/src/audio/lib/load.c +++ b/mm/src/audio/lib/load.c @@ -13,6 +13,8 @@ #include "global.h" #include "buffers.h" #include +#include + /** * SoundFont Notes: * @@ -57,11 +59,18 @@ void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus); void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, size_t size); void AudioLoad_AsyncDmaRamUnloaded(AudioAsyncLoad* asyncLoad, size_t size); void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, void* ramAddr, size_t size, s16 arg3); -void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc); +void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc, + int fontId); void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc, s32 isAsync); s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus); +SequenceData ResourceMgr_LoadSeqByName(const char* path); +SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path); + +// TODO: what's that for? it seems to rely on an uninitizalied variable in soh +static uint32_t fontOffsets[8192]; + #define MK_ASYNC_MSG(retData, tableType, id, loadStatus) \ (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (loadStatus)) @@ -95,6 +104,11 @@ DmaHandler sDmaHandler; //= osEPiStartDma; void* sUnusedHandler = NULL; s32 gAudioCtxInitalized = false; +char** gSequenceToResource; +size_t gSequenceToResourceSize; +u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID]; +char* gFontToResource[256]; + void AudioLoad_DecreaseSampleDmaTtls(void) { u32 i; @@ -487,17 +501,26 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret AudioLoad_AsyncLoad(FONT_TABLE, fontId, 0, retData, retQueue); } -u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { - // BENTODO - *outNumFonts = 0; - return NULL; - s32 index = ((u16*)gAudioCtx.sequenceFontTable)[seqId]; - - *outNumFonts = gAudioCtx.sequenceFontTable[index++]; - if (*outNumFonts == 0) { +u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff) { + if (seqId == NA_BGM_DISABLED || seqId == 0xFF) { return NULL; } - return &gAudioCtx.sequenceFontTable[index]; + + // TODO: Sequence Remplacements + + if (seqId > gSequenceToResourceSize || !gSequenceToResource[seqId]) { + return NULL; + } + + SequenceData seqData = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]); + + *outNumFonts = seqData.numFonts; + if (seqData.numFonts == 0) + return NULL; + + memcpy(buff, seqData.fonts, sizeof(seqData.fonts)); + + return buff; } void AudioLoad_DiscardSeqFonts(s32 seqId) { @@ -559,11 +582,7 @@ s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2) { } gAudioCtx.seqPlayers[playerIndex].skipTicks = 0; - AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, arg2); - // Intentionally missing return. Returning the result of the above function - // call matches but is UB because it too is missing a return, and using the - // result of a non-void function that has failed to return a value is UB. - // The callers of this function do not use the return value, so it's fine. + return AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, arg2); } s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTicks) { @@ -572,8 +591,7 @@ s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTic } gAudioCtx.seqPlayers[playerIndex].skipTicks = skipTicks; - AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, 0); - // Missing return, see above. + return AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, 0); } s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) { @@ -582,22 +600,23 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) { s32 index; s32 numFonts; s32 fontId; - - if (seqId >= gAudioCtx.numSequences) { - return 0; - } + s8 authCachePolicy = -1; // since 0 is a valid cache policy value AudioScript_SequencePlayerDisable(seqPlayer); - if (1) {} fontId = 0xFF; - index = ((u16*)gAudioCtx.sequenceFontTable)[seqId]; - numFonts = gAudioCtx.sequenceFontTable[index++]; + if (gAudioCtx.seqReplaced[playerIndex]) { + authCachePolicy = seqCachePolicyMap[seqId]; + seqId = gAudioCtx.seqToPlay[playerIndex]; + } + SequenceData seqData2 = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]); + if (authCachePolicy != -1) { + seqData2.cachePolicy = authCachePolicy; + } - while (numFonts > 0) { - fontId = gAudioCtx.sequenceFontTable[index++]; + for (int i = 0; i < seqData2.numFonts; i++) { + fontId = seqData2.fonts[i]; AudioLoad_SyncLoadFont(fontId); - numFonts--; } seqData = AudioLoad_SyncLoadSeq(seqId); @@ -621,6 +640,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) { seqPlayer->delay = 0; seqPlayer->finished = false; seqPlayer->playerIndex = playerIndex; + return 1; //! @bug missing return (but the return value is not used so it's not UB) } @@ -657,9 +677,9 @@ u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad return addr; } - cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy; + // cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy; - if ((cachePolicy == CACHE_LOAD_EITHER_NOSYNC) || (noLoad == true)) { + if (/*(cachePolicy == CACHE_LOAD_EITHER_NOSYNC) ||*/ (noLoad == true)) { *outMedium = sampleBankTable->entries[sampleBankId].medium; return sampleBankTable->entries[realTableId].romAddr; } @@ -686,23 +706,24 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) { return NULL; } - sampleBankId1 = gAudioCtx.soundFontList[realFontId].sampleBankId1; - sampleBankId2 = gAudioCtx.soundFontList[realFontId].sampleBankId2; + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + sampleBankId1 = sf->sampleBankId1; + sampleBankId2 = sf->sampleBankId2; sampleBankReloc.sampleBankId1 = sampleBankId1; sampleBankReloc.sampleBankId2 = sampleBankId2; - if (sampleBankReloc.sampleBankId1 != 0xFF) { - sampleBankReloc.baseAddr1 = - AudioLoad_TrySyncLoadSampleBank(sampleBankReloc.sampleBankId1, &sampleBankReloc.medium1, false); - } else { - sampleBankReloc.baseAddr1 = 0; - } + // if (sampleBankReloc.sampleBankId1 != 0xFF) { + // sampleBankReloc.baseAddr1 = + // AudioLoad_TrySyncLoadSampleBank(sampleBankReloc.sampleBankId1, &sampleBankReloc.medium1, false); + // } else { + sampleBankReloc.baseAddr1 = 0; + // } - if (sampleBankId2 != 0xFF) { - sampleBankReloc.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &sampleBankReloc.medium2, false); - } else { - sampleBankReloc.baseAddr2 = 0; - } + // if (sampleBankId2 != 0xFF) { + // sampleBankReloc.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &sampleBankReloc.medium2, false); + // } else { + sampleBankReloc.baseAddr2 = 0; + // } fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate); if (fontData == NULL) { @@ -733,12 +754,31 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) { *didAllocate = false; loadStatus = LOAD_STATUS_COMPLETE; } else { - table = AudioLoad_GetLoadTable(tableType); - size = table->entries[realId].size; - size = ALIGN16(size); - medium = table->entries[id].medium; - cachePolicy = table->entries[id].cachePolicy; - romAddr = table->entries[realId].romAddr; + // table = AudioLoad_GetLoadTable(tableType); + // size = table->entries[realId].size; + // size = ALIGN16(size); + // medium = table->entries[id].medium; + // cachePolicy = table->entries[id].cachePolicy; + // romAddr = table->entries[realId].romAddr; + + char* seqData = 0; + SoundFont* fnt; + + if (tableType == SEQUENCE_TABLE) { + SequenceData sData = ResourceMgr_LoadSeqByName(gSequenceToResource[id]); + seqData = sData.seqData; + size = sData.seqDataSize; + medium = sData.medium; + cachePolicy = sData.cachePolicy; + romAddr = 0; + } else if (tableType == FONT_TABLE) { + fnt = ResourceMgr_LoadAudioSoundFont(gFontToResource[id]); + size = sizeof(SoundFont); + medium = 2; + cachePolicy = 0; + romAddr = 0; + } + switch (cachePolicy) { case CACHE_LOAD_PERMANENT: //! @bug UB: triggers an UB because this function is missing a return value. @@ -792,7 +832,13 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) { } else if (medium2 == mediumUnk) { AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->unkMediumParam); } else { - AudioLoad_SyncDma(romAddr, ramAddr, size, medium); + if (tableType == SEQUENCE_TABLE && seqData != NULL) { + AudioLoad_SyncDma(seqData, ramAddr, size, medium); + } else if (tableType == FONT_TABLE) { + AudioLoad_SyncDma(fnt, ramAddr, size, medium); + } else { + // AudioLoad_SyncDma(romAddr, ret, size, medium); + } } loadStatus = (cachePolicy == CACHE_LOAD_PERMANENT) ? LOAD_STATUS_PERMANENT : LOAD_STATUS_COMPLETE; @@ -816,11 +862,11 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) { } u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) { - AudioTable* table = AudioLoad_GetLoadTable(tableType); + // AudioTable* table = AudioLoad_GetLoadTable(tableType); - if (table->entries[id].size == 0) { - id = table->entries[id].romAddr; - } + // if (table->entries[id].size == 0) { + // id = table->entries[id].romAddr; + // } return id; } @@ -869,133 +915,81 @@ AudioTable* AudioLoad_GetLoadTable(s32 tableType) { * @param fontDataStartAddr ram address of raw soundfont binary loaded into cache * @param sampleBankReloc information on the sampleBank containing raw audio samples */ -void AudioLoad_RelocateFont(s32 fontId, SoundFontData* fontDataStartAddr, SampleBankRelocInfo* sampleBankReloc) { - uintptr_t soundOffset; - uintptr_t soundListOffset; + +void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, SampleBankRelocInfo* relocInfo) { + uintptr_t reloc; + uintptr_t reloc2; Instrument* inst; Drum* drum; - SoundEffect* soundEffect; + TunedSample* sfx; s32 i; - s32 numDrums = gAudioCtx.soundFontList[fontId].numDrums; - s32 numInstruments = gAudioCtx.soundFontList[fontId].numInstruments; - s32 numSfx = gAudioCtx.soundFontList[fontId].numSfx; - u32* fontData = (u32*)fontDataStartAddr; + SoundFont* sf = NULL; + s32 numDrums = 0; + s32 numInstruments = 0; + s32 numSfx = 0; - // Relocate an offset (relative to the start of the font data) to a pointer (a ram address) -#define RELOC_TO_RAM(x) (void*)((uintptr_t)(x) + (uintptr_t)(fontDataStartAddr)) + sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + numDrums = sf->numDrums; + numInstruments = sf->numInstruments; + numSfx = sf->numSfx; - // Drums relocation + void** ptrs = (void**)mem; - // The first u32 in fontData is an offset to a list of offsets to the drums - soundListOffset = fontData[0]; +#define BASE_OFFSET(x) (void*)((uintptr_t)(x) + (uintptr_t)(mem)) - // If the soundFont has drums - if ((soundListOffset != 0) && (numDrums != 0)) { - - fontData[0] = RELOC_TO_RAM(soundListOffset); - - // Loop through the drum offsets + reloc2 = ptrs[0]; + if ((numDrums != 0)) { + ptrs[0] = BASE_OFFSET(reloc2); for (i = 0; i < numDrums; i++) { - // Get the i'th drum offset - soundOffset = ((Drum**)fontData[0])[i]; + drum = sf->drums[i]; - // Some drum data entries are empty, represented by an offset of 0 in the list of drum offsets - if (soundOffset == 0) { - continue; + if (!drum->isRelocated) { + AudioLoad_RelocateSample(&sf->drums[i]->tunedSample, mem, relocInfo, fontOffsets[fontId]); + drum->isRelocated = 1; } - soundOffset = RELOC_TO_RAM(soundOffset); - ((Drum**)fontData[0])[i] = drum = soundOffset; - - // The drum may be in the list multiple times and already relocated - if (drum->isRelocated) { - continue; - } - - AudioLoad_RelocateSample(&drum->tunedSample, fontDataStartAddr, sampleBankReloc); - - soundOffset = drum->envelope; - drum->envelope = RELOC_TO_RAM(soundOffset); - - drum->isRelocated = true; } } - // Sound effects relocation - - // The second u32 in fontData is an offset to the first sound effect entry - soundListOffset = fontData[1]; - - // If the soundFont has sound effects - if ((soundListOffset != 0) && (numSfx != 0)) { - - fontData[1] = RELOC_TO_RAM(soundListOffset); - - // Loop through the sound effects + reloc2 = ptrs[1]; + if (numSfx != 0) { + ptrs[1] = BASE_OFFSET(reloc2); for (i = 0; i < numSfx; i++) { - // Get a pointer to the i'th sound effect - soundOffset = (TunedSample*)fontData[1] + i; - soundEffect = (SoundEffect*)soundOffset; - - // Check for NULL (note: the pointer is guaranteed to be in fontData and can never be NULL) - if ((soundEffect == NULL) || (soundEffect->tunedSample.sample == NULL)) { - continue; - } - - AudioLoad_RelocateSample(&soundEffect->tunedSample, fontDataStartAddr, sampleBankReloc); + reloc = (TunedSample*)ptrs[1] + i; + AudioLoad_RelocateSample(&sf->soundEffects[i].tunedSample, mem, relocInfo, fontOffsets[fontId]); } } - // Instruments relocation - - // Instrument Id 126 and above is reserved. - // There can only be 126 instruments, indexed from 0 to 125 - if (numInstruments > 126) { - numInstruments = 126; + if (numInstruments > 0x7E) { + numInstruments = 0x7E; } - // Starting from the 3rd u32 in fontData is the list of offsets to the instruments - // Loop through the instruments - for (i = 2; i <= 2 + numInstruments - 1; i++) { - // Some instrument data entries are empty, represented by an offset of 0 in the list of instrument offsets - if (fontData[i] != 0) { - fontData[i] = RELOC_TO_RAM(fontData[i]); - inst = (Instrument*)fontData[i]; + int startI = 0; + int startEC = numInstruments - 1; + for (i = startI; i <= startEC; i++) { + ptrs[i] = BASE_OFFSET(ptrs[i]); + inst = sf->instruments[i]; - // The instrument may be in the list multiple times and already relocated - if (!inst->isRelocated) { - // Some instruments have a different sample for low pitches - if (inst->normalRangeLo != 0) { - AudioLoad_RelocateSample(&inst->lowPitchTunedSample, fontDataStartAddr, sampleBankReloc); - } - - // Every instrument has a sample for the default range - AudioLoad_RelocateSample(&inst->normalPitchTunedSample, fontDataStartAddr, sampleBankReloc); - - // Some instruments have a different sample for high pitches - if (inst->normalRangeHi != 0x7F) { - AudioLoad_RelocateSample(&inst->highPitchTunedSample, fontDataStartAddr, sampleBankReloc); - } - - soundOffset = inst->envelope; - inst->envelope = (EnvelopePoint*)RELOC_TO_RAM(soundOffset); - - inst->isRelocated = true; + if (inst != NULL && !inst->isRelocated) { + if (inst->normalRangeLo != 0) { + AudioLoad_RelocateSample(&inst->lowPitchTunedSample, mem, relocInfo, fontOffsets[fontId]); } + AudioLoad_RelocateSample(&inst->normalPitchTunedSample, mem, relocInfo, fontOffsets[fontId]); + if (inst->normalRangeHi != 0x7F) { + AudioLoad_RelocateSample(&inst->highPitchTunedSample, mem, relocInfo, fontOffsets[fontId]); + } + + reloc = inst->envelope; + inst->isRelocated = 1; } } -#undef RELOC_TO_RAM - - // Store the relocated pointers - gAudioCtx.soundFontList[fontId].drums = (Drum**)fontData[0]; - gAudioCtx.soundFontList[fontId].soundEffects = (SoundEffect*)fontData[1]; - gAudioCtx.soundFontList[fontId].instruments = (Instrument**)(&fontData[2]); +#undef BASE_OFFSET } void AudioLoad_SyncDma(uintptr_t devAddr, u8* ramAddr, size_t size, s32 medium) { OSMesgQueue* msgQueue = &gAudioCtx.syncDmaQueue; OSIoMesg* ioMesg = &gAudioCtx.syncDmaIoMesg; - size = ALIGN16(size); + //size = ALIGN16(size); Audio_InvalDCache(ramAddr, size); @@ -1021,38 +1015,12 @@ void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, size_t size, s32 s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, uintptr_t devAddr, void* ramAddr, size_t size, OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType) { - OSPiHandle* handle; - if (gAudioCtx.resetTimer > 16) { + // TODO: what's that for? + if (gAudioCtx.resetTimer > 0x10) { return -1; } - - switch (medium) { - case MEDIUM_CART: - handle = gAudioCtx.cartHandle; - break; - - case MEDIUM_DISK_DRIVE: - // driveHandle is uninitialized and corresponds to stubbed-out disk drive support. - // SM64 Shindou called osDriveRomInit here. - handle = gAudioCtx.driveHandle; - break; - - default: - return 0; - } - - if ((size % 0x10) != 0) { - size = ALIGN16(size); - } - - mesg->hdr.pri = priority; - mesg->hdr.retQueue = reqQueue; - mesg->dramAddr = ramAddr; - mesg->devAddr = devAddr; - mesg->size = size; - handle->transferInfo.cmdType = 2; - sDmaHandler(handle, mesg, direction); + memcpy(ramAddr, devAddr, size); return 0; } @@ -1232,11 +1200,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) { gAudioCtx.resetTimer = 0; gAudioCtx.unk_29B8 = false; - // Set all of gAudioCtx to 0 - audioCtxPtr = (u8*)&gAudioCtx; - for (j = sizeof(gAudioCtx); j >= 0; j--) { - *audioCtxPtr++ = 0; - } + memset(&gAudioCtx, 0, sizeof(gAudioCtx)); switch (osTvType) { case OS_TV_PAL: @@ -1303,28 +1267,52 @@ void AudioLoad_Init(void* heap, size_t heapSize) { } // Connect audio tables to their tables in memory - gAudioCtx.sequenceTable = (AudioTable*)gSequenceTable; - gAudioCtx.soundFontTable = (AudioTable*)gSoundFontTable; - gAudioCtx.sampleBankTable = (AudioTable*)gSampleBankTable; - gAudioCtx.sequenceFontTable = gSequenceFontTable; - - gAudioCtx.numSequences = gAudioCtx.sequenceTable->numEntries; + // gAudioCtx.sequenceTable = (AudioTable*)gSequenceTable; + // gAudioCtx.soundFontTable = (AudioTable*)gSoundFontTable; + // gAudioCtx.sampleBankTable = (AudioTable*)gSampleBankTable; + // gAudioCtx.sequenceFontTable = gSequenceFontTable; + // gAudioCtx.numSequences = gAudioCtx.sequenceTable->numEntries; gAudioCtx.specId = 0; gAudioCtx.resetStatus = 1; // Set reset to immediately initialize the audio heap AudioHeap_ResetStep(); // Initialize audio tables - AudioLoad_InitTable(gAudioCtx.sequenceTable, SEGMENT_ROM_START(Audioseq), 0); - AudioLoad_InitTable(gAudioCtx.soundFontTable, SEGMENT_ROM_START(Audiobank), 0); - AudioLoad_InitTable(gAudioCtx.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0); + // AudioLoad_InitTable(gAudioCtx.sequenceTable, SEGMENT_ROM_START(Audioseq), 0); + // AudioLoad_InitTable(gAudioCtx.soundFontTable, SEGMENT_ROM_START(Audiobank), 0); + // AudioLoad_InitTable(gAudioCtx.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0); - numFonts = gAudioCtx.soundFontTable->numEntries; + int seqListSize = 0; + char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize); + gSequenceToResourceSize = seqListSize; + gSequenceToResource = malloc(gSequenceToResourceSize * sizeof(*gSequenceToResource)); + gAudioCtx.seqLoadStatus = malloc(gSequenceToResourceSize * sizeof(*gAudioCtx.seqLoadStatus)); + + for (size_t i = 0; i < seqListSize; i++) { + SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]); + char* seqName = strdup(seqList[i]); + gSequenceToResource[sDat.seqNumber] = seqName; + seqCachePolicyMap[sDat.seqNumber] = sDat.cachePolicy; + } + + free(seqList); + + int fntListSize = 0; + char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize); + + for (int i = 0; i < fntListSize; i++) { + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fntList[i]); + gFontToResource[sf->fntIndex] = strdup(fntList[i]); + } + + free(fntList); + + numFonts = fntListSize; gAudioCtx.soundFontList = AudioHeap_Alloc(&gAudioCtx.initPool, numFonts * sizeof(SoundFont)); - for (i = 0; i < numFonts; i++) { - AudioLoad_InitSoundFont(i); - } + // for (i = 0; i < numFonts; i++) { + // AudioLoad_InitSoundFont(i); + // } if (addr = AudioHeap_Alloc(&gAudioCtx.initPool, gAudioHeapInitSizes.permanentPoolSize), addr == NULL) { // cast away const from gAudioHeapInitSizes @@ -1518,14 +1506,16 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) { slowLoad->sample.sampleAddr = NULL; slowLoad->isDone = isDone; - size = seqTable->entries[seqId].size; - size = ALIGN16(size); + + SequenceData sData = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]); + size = sData.seqDataSize; + slowLoad->curDevAddr = sData.seqData; + slowLoad->medium = seqTable->entries[seqId].medium; + slowLoad->curRamAddr = ramAddr; slowLoad->status = LOAD_STATUS_START; slowLoad->bytesRemaining = size; slowLoad->ramAddr = ramAddr; - slowLoad->curDevAddr = seqTable->entries[seqId].romAddr; - slowLoad->medium = seqTable->entries[seqId].medium; slowLoad->seqOrFontId = seqId; if (slowLoad->medium == MEDIUM_UNK) { @@ -1763,52 +1753,8 @@ void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, void* ramAddr, size_t size, * @param fontData ram address of raw soundfont binary loaded into cache * @param sampleBankReloc information on the sampleBank containing raw audio samples */ -void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc) { - Sample* sample; - void* reloc; - - // Relocate an offset (relative to data loaded in ram at `base`) to a pointer (a ram address) -#define AUDIO_RELOC(v, base) (reloc = (void*)((uintptr_t)(v) + (uintptr_t)(base))) - - if ((uintptr_t)tunedSample->sample <= AUDIO_RELOCATED_ADDRESS_START) { - - sample = tunedSample->sample = AUDIO_RELOC(tunedSample->sample, fontData); - - // If the sample exists and has not already been relocated - // Note: this is important, as the same sample can be used by different drums, sound effects, instruments - if ((sample->size != 0) && (sample->isRelocated != true)) { - sample->loop = AUDIO_RELOC(sample->loop, fontData); - sample->book = AUDIO_RELOC(sample->book, fontData); - - // Resolve the sample medium 2-bit bitfield into a real value based on sampleBankReloc. - // Then relocate the offset sample within the sampleBank (not the fontData) into absolute address. - // sampleAddr can be either rom or ram depending on sampleBank cache policy - // in practice, this is always in rom - switch (sample->medium) { - case 0: - sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr1); - sample->medium = sampleBankReloc->medium1; - break; - - case 1: - sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr2); - sample->medium = sampleBankReloc->medium2; - break; - - case 2: - case 3: - // Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE - // respectively, and the sampleAddr unrelocated. - break; - } - - sample->isRelocated = true; - - if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) { - gAudioCtx.usedSamples[gAudioCtx.numUsedSamples++] = sample; - } - } - } +void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc, + int fontId) { } #undef AUDIO_RELOC @@ -2047,7 +1993,7 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, Sample** sampleSet) { void AudioLoad_AddUsedSample(TunedSample* tunedSample) { Sample* sample = tunedSample->sample; - if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) { + if (sample && (sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) { gAudioCtx.usedSamples[gAudioCtx.numUsedSamples++] = sample; } } @@ -2075,9 +2021,10 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, SampleBankRelocInfo* gAudioCtx.numUsedSamples = 0; - numDrums = gAudioCtx.soundFontList[fontId].numDrums; - numInstruments = gAudioCtx.soundFontList[fontId].numInstruments; - numSfx = gAudioCtx.soundFontList[fontId].numSfx; + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + numDrums = sf->numDrums; + numInstruments = sf->numInstruments; + numSfx = sf->numSfx; for (i = 0; i < numInstruments; i++) { instrument = AudioPlayback_GetInstrumentInner(fontId, i); @@ -2194,26 +2141,30 @@ void AudioLoad_LoadPermanentSamples(void) { s32 pad2; s32 i; - sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE); + // sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE); for (i = 0; i < gAudioCtx.permanentPool.count; i++) { SampleBankRelocInfo sampleBankReloc; if (gAudioCtx.permanentEntries[i].tableType == FONT_TABLE) { fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioCtx.permanentEntries[i].id); - sampleBankReloc.sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1; - sampleBankReloc.sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2; - if (sampleBankReloc.sampleBankId1 != 0xFF) { - sampleBankReloc.sampleBankId1 = - AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId1); - sampleBankReloc.medium1 = sampleBankTable->entries[sampleBankReloc.sampleBankId1].medium; - } + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + sampleBankReloc.sampleBankId1 = sf->sampleBankId1; + sampleBankReloc.sampleBankId2 = sf->sampleBankId2; + // sampleBankReloc.sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1; + // sampleBankReloc.sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2; - if (sampleBankReloc.sampleBankId2 != 0xFF) { - sampleBankReloc.sampleBankId2 = - AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId2); - sampleBankReloc.medium2 = sampleBankTable->entries[sampleBankReloc.sampleBankId2].medium; - } + // if (sampleBankReloc.sampleBankId1 != 0xFF) { + // sampleBankReloc.sampleBankId1 = + // AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId1); + // sampleBankReloc.medium1 = sampleBankTable->entries[sampleBankReloc.sampleBankId1].medium; + // } + + // if (sampleBankReloc.sampleBankId2 != 0xFF) { + // sampleBankReloc.sampleBankId2 = + // AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId2); + // sampleBankReloc.medium2 = sampleBankTable->entries[sampleBankReloc.sampleBankId2].medium; + // } AudioLoad_PreloadSamplesForFont(fontId, false, &sampleBankReloc); } } diff --git a/mm/src/audio/lib/playback.c b/mm/src/audio/lib/playback.c index 6bc5e3943..d947954d2 100644 --- a/mm/src/audio/lib/playback.c +++ b/mm/src/audio/lib/playback.c @@ -5,6 +5,10 @@ void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resam void AudioPlayback_AudioListPushFront(AudioListItem* list, AudioListItem* item); void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer); +SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path); + +extern char* gFontToResource[256]; + void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, NoteSubAttributes* subAttrs) { f32 volLeft; f32 volRight; @@ -104,8 +108,9 @@ void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, Not vel = 0.0f > vel ? 0.0f : vel; vel = 1.0f < vel ? 1.0f : vel; - sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)); - sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)); + float master_vol = CVarGetFloat("gGameMasterVolume", 1.0f); + sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)) * master_vol; + sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)) * master_vol; sampleState->gain = subAttrs->gain; sampleState->filter = subAttrs->filter; @@ -179,7 +184,11 @@ void AudioPlayback_ProcessNotes(void) { sampleState = &gAudioCtx.sampleStateList[gAudioCtx.sampleStateOffset + i]; playbackState = ¬e->playbackState; if (playbackState->parentLayer != NO_LAYER) { - if ((u32)playbackState->parentLayer < 0x7FFFFFFF) { + + // OTRTODO: This skips playback if the pointer is below where memory on the N64 normally would be. + // This does not translate well to modern platforms and how they map memory. + // Considering that this check is not present in OoT/SoH, we may be able to remove this altogether. + if ((uintptr_t)playbackState->parentLayer < 0x7FFFFFFF) { continue; } @@ -355,12 +364,14 @@ Instrument* AudioPlayback_GetInstrumentInner(s32 fontId, s32 instId) { return NULL; } - if (instId >= gAudioCtx.soundFontList[fontId].numInstruments) { - gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, instId, AUDIO_ERROR_INVALID_INST_ID); + int instCnt = 0; + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + + if (instId >= sf->numInstruments) return NULL; - } + + inst = sf->instruments[instId]; - inst = gAudioCtx.soundFontList[fontId].instruments[instId]; if (inst == NULL) { gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, instId, AUDIO_ERROR_NO_INST); return inst; @@ -381,14 +392,10 @@ Drum* AudioPlayback_GetDrum(s32 fontId, s32 drumId) { return NULL; } - if (drumId >= gAudioCtx.soundFontList[fontId].numDrums) { - gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, drumId, AUDIO_ERROR_INVALID_DRUM_SFX_ID); - return NULL; + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + if (drumId < sf->numDrums) { + drum = sf->drums[drumId]; } - if ((u32)gAudioCtx.soundFontList[fontId].drums < AUDIO_RELOCATED_ADDRESS_START) { - return NULL; - } - drum = gAudioCtx.soundFontList[fontId].drums[drumId]; if (drum == NULL) { gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, drumId, AUDIO_ERROR_NO_DRUM_SFX); @@ -409,22 +416,16 @@ SoundEffect* AudioPlayback_GetSoundEffect(s32 fontId, s32 sfxId) { return NULL; } - if (sfxId >= gAudioCtx.soundFontList[fontId].numSfx) { - gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, sfxId, AUDIO_ERROR_INVALID_DRUM_SFX_ID); - return NULL; + SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]); + if (sfxId < sf->numSfx) { + soundEffect = &sf->soundEffects[sfxId]; } - if ((u32)gAudioCtx.soundFontList[fontId].soundEffects < AUDIO_RELOCATED_ADDRESS_START) { - return NULL; - } - - soundEffect = &gAudioCtx.soundFontList[fontId].soundEffects[sfxId]; - if (soundEffect == NULL) { gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, sfxId, AUDIO_ERROR_NO_DRUM_SFX); } - if (soundEffect->tunedSample.sample == NULL) { + if (soundEffect != NULL && soundEffect->tunedSample.sample == NULL) { return NULL; } diff --git a/mm/src/audio/lib/seqplayer.c b/mm/src/audio/lib/seqplayer.c index 34ec93a7b..84ae38237 100644 --- a/mm/src/audio/lib/seqplayer.c +++ b/mm/src/audio/lib/seqplayer.c @@ -13,6 +13,8 @@ * - All three sets share a common pool of control flow instructions (>= 0xF2). * Otherwise, each set of instructions has its own command interpreter */ + +#include "endianness.h" #include "global.h" #define PROCESS_SCRIPT_END -1 @@ -27,6 +29,9 @@ s32 AudioScript_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd); s32 AudioScript_SeqLayerProcessScriptStep3(SequenceLayer* layer, s32 cmd); u8 AudioScript_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** instOut, AdsrSettings* adsr); +SequenceData ResourceMgr_LoadSeqByName(const char* path); +extern char** gSequenceToResource; + /** * sSeqInstructionArgsTable is a table for each sequence instruction * that contains both how many arguments an instruction takes, as well @@ -1414,9 +1419,19 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) { cmd = (u8)cmdArgs[0]; if (seqPlayer->defaultFont != 0xFF) { - cmdArgU16 = ((u16*)gAudioCtx.sequenceFontTable)[seqPlayer->seqId]; - lowBits = gAudioCtx.sequenceFontTable[cmdArgU16]; - cmd = gAudioCtx.sequenceFontTable[cmdArgU16 + lowBits - cmd]; + if (gAudioCtx.seqReplaced[seqPlayer->playerIndex]) { + seqPlayer->seqId = gAudioCtx.seqToPlay[seqPlayer->playerIndex]; + gAudioCtx.seqReplaced[seqPlayer->playerIndex] = 0; + } + u16 seqId = seqPlayer->seqId; // AudioEditor_GetReplacementSeq(seqPlayer->seqId); + SequenceData sDat = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]); + + // The game apparantely would sometimes do negative array lookups, the result of which would get + // rejected by AudioHeap_SearchCaches, never changing the actual fontid. + if (cmd > sDat.numFonts) + break; + + cmd = sDat.fonts[(sDat.numFonts - cmd - 1)]; } if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, cmd)) { @@ -1597,7 +1612,7 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) { case 0xB2: // channel: dynread sequence large cmdArgU16 = (u16)cmdArgs[0]; - channel->unk_22 = *(u16*)(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value * 2)); + channel->unk_22 = BE16SWAP(*(u16*)(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value * 2))); break; case 0xB4: // channel: set dyntable large @@ -1605,7 +1620,7 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xB5: // channel: read dyntable large - channel->unk_22 = ((u16*)(channel->dynTable))[scriptState->value]; + channel->unk_22 = BE16SWAP(((u16*)(channel->dynTable))[scriptState->value]); break; case 0xB6: // channel: read dyntable diff --git a/mm/src/audio/lib/synthesis.c b/mm/src/audio/lib/synthesis.c index 0e95b4a99..aa68ad369 100644 --- a/mm/src/audio/lib/synthesis.c +++ b/mm/src/audio/lib/synthesis.c @@ -1,4 +1,6 @@ #include "global.h" +#include "resourcebridge.h" +#include "2s2h/mixer.h" // DMEM Addresses for the RSP #define DMEM_TEMP 0x3B0 @@ -353,9 +355,9 @@ void AudioSynth_Noop9(void) { } void AudioSynth_DMemMove(Acmd* cmd, s32 dmemIn, s32 dmemOut, size_t size) { - // aDMEMMove(cmd, dmemIn, dmemOut, size); - cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24); - cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16); + aDMEMMove(cmd, dmemIn, dmemOut, size); + //cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24); + //cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16); } void AudioSynth_Noop10(void) { @@ -371,9 +373,9 @@ void AudioSynth_Noop13(void) { } void AudioSynth_InterL(Acmd* cmd, s32 dmemIn, s32 dmemOut, s32 numSamples) { - // aInterl(cmd, dmemIn, dmemOut, numSamples); - cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16); - cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); + aInterl(cmd, dmemIn, dmemOut, numSamples); + // cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16); + // cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); } void AudioSynth_EnvSetup1(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampLeft, s32 rampRight) { @@ -392,9 +394,9 @@ void AudioSynth_SaveBuffer(Acmd* cmd, s32 dmemSrc, s32 size, void* addrDest) { } void AudioSynth_EnvSetup2(Acmd* cmd, s32 volLeft, s32 volRight) { - // aEnvSetup2(cmd, volLeft, volRight); - cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); - cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16); + aEnvSetup2(cmd, volLeft, volRight); + // cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); + // cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16); } void AudioSynth_Noop15(void) { @@ -411,15 +413,16 @@ void AudioSynth_S8Dec(Acmd* cmd, s32 flags, s16* state) { } void AudioSynth_HiLoGain(Acmd* cmd, s32 gain, s32 dmemIn, s32 dmemOut, s32 size) { - // aHiLoGain(cmd, gain, size, dmemIn, dmemOut); - cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16); - cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); + aHiLoGain(cmd, gain, size, dmemIn, dmemOut); + // cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16); + // cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); } // Remnant of OoT void AudioSynth_UnkCmd19(Acmd* cmd, s32 dmem1, s32 dmem2, s32 size, s32 arg4) { - cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16); - cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16); + aUnkCmd19(cmd, dmem1, dmem2, size, arg4); + // cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16); + // cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16); } void AudioSynth_Noop18(void) { @@ -614,7 +617,7 @@ Acmd* AudioSynth_LoadSubReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, Synthe Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 size, uintptr_t startAddr) { s32 startAddrAlignDropped; - u32 endAddr; + uintptr_t endAddr; s32 endAddrAlignDropped; endAddr = startAddr + size; @@ -1028,6 +1031,7 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note } numEntries = SAMPLES_PER_FRAME * sample->book->order * sample->book->numPredictors; + //ResourceCheckSample(sample->sampleAddr, sample->book->codeBook); aLoadADPCM(cmd++, numEntries, gAudioCtx.adpcmCodeBook); } } @@ -1169,10 +1173,8 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note return cmd; } else { // This medium is not in ram, so dma the requested sample into ram - samplesToLoadAddr = - AudioLoad_DmaSampleData((uintptr_t)(sampleAddr + (zeroOffset + sampleAddrOffset)), - ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME), flags, - &synthState->sampleDmaIndex, sample->medium); + // BEN: Assume all samples are in RAM... because they are. + samplesToLoadAddr = sampleAddr + (zeroOffset + sampleAddrOffset); } if (samplesToLoadAddr == NULL) { @@ -1182,9 +1184,16 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note // Move the raw sample chunk from ram to the rsp // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF; + sampleDataChunkAlignPad = (uintptr_t)samplesToLoadAddr & 0xF; sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME); sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + + // BEN: This will crash the asan. We can just ignore alignment since we don't have those strictures. + //if (sampleDataChunkSize + sampleAddrOffset > sample->size) { + // sampleDataChunkSize = sample->size - sampleAddrOffset; + // sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + //} + aLoadBuffer(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr, sampleDataChunkSize); } else { @@ -1691,7 +1700,8 @@ Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSy ALIGN16(haasEffectDelaySize)); } - aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF); + aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest); + // aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF); return cmd; } diff --git a/mm/src/audio/lib/thread.c b/mm/src/audio/lib/thread.c index 632906b8a..94a0d4585 100644 --- a/mm/src/audio/lib/thread.c +++ b/mm/src/audio/lib/thread.c @@ -5,6 +5,7 @@ */ #include "global.h" #include "audio/effects.h" +#include "audio/load.h" AudioTask* AudioThread_UpdateImpl(void); void AudioThread_SetFadeOutTimer(s32 seqPlayerIndex, s32 fadeTimer); @@ -14,83 +15,31 @@ void AudioThread_ProcessSeqPlayerCmd(SequencePlayer* seqPlayer, AudioCmd* cmd); void AudioThread_ProcessChannelCmd(SequenceChannel* channel, AudioCmd* cmd); s32 AudioThread_GetSamplePos(s32 seqPlayerIndex, s32 channelIndex, s32 layerIndex, s32* loopEnd, s32* samplePosInt); s32 AudioThread_CountAndReleaseNotes(s32 flags); +s32 AudioThread_ScheduleProcessCmds(void); AudioTask* AudioThread_Update(void) { return AudioThread_UpdateImpl(); } -AudioTask* AudioThread_UpdateImpl(void) { - // BENTODO - #if 0 - static AudioTask* sWaitingAudioTask = NULL; - u32 numSamplesRemainingInAi; - s32 numAbiCmds; - s32 pad; - s32 j; - s32 dmaCount; - s16* curAiBuffer; - OSTask_t* task; - s32 index; - u32 msg; - s32 validCount; - s32 i; +void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples) { + // static size_t off = 0; + // f32 sample_rate = 44100; + // f32 note_freq = 440; // A4 + // size_t note_period_in_samples = sample_rate / note_freq; + // for (size_t i = 0; i < num_samples; i++) + // { + // bool hi = off >= (note_period_in_samples / 2); + // s16 value = hi ? INT16_MAX / 2 : INT16_MIN / 2; + // *samples++ = value; // left + // *samples++ = value; // right + // off = (off + 1) % note_period_in_samples; + // } + // return; + + OSMesg sp4C; gAudioCtx.totalTaskCount++; - if ((gAudioCtx.totalTaskCount % gAudioCtx.audioBufferParameters.specUnk4) != 0) { - if (gAudioCustomUpdateFunction != NULL) { - gAudioCustomUpdateFunction(); - } - if (((gAudioCtx.totalTaskCount % gAudioCtx.audioBufferParameters.specUnk4) + 1) == - gAudioCtx.audioBufferParameters.specUnk4) { - return sWaitingAudioTask; - } - - return NULL; - } - - osSendMesg(gAudioCtx.taskStartQueueP, OS_MESG_32(gAudioCtx.totalTaskCount), OS_MESG_NOBLOCK); - gAudioCtx.rspTaskIndex ^= 1; - gAudioCtx.curAiBufferIndex++; - gAudioCtx.curAiBufferIndex %= 3; - index = (gAudioCtx.curAiBufferIndex + 1) % 3; - - // Division converts size to numSamples: 2 channels (left/right) * 2 bytes per sample - numSamplesRemainingInAi = osAiGetLength() / (2 * SAMPLE_SIZE); - - if (gAudioCtx.resetTimer < 16) { - if (gAudioCtx.numSamplesPerFrame[index] != 0) { - osAiSetNextBuffer(gAudioCtx.aiBuffers[index], 2 * gAudioCtx.numSamplesPerFrame[index] * (s32)SAMPLE_SIZE); - if (gAudioCtx.aiBuffers[index]) {} - if (gAudioCtx.numSamplesPerFrame[index]) {} - } - } - - if (gAudioCustomUpdateFunction != NULL) { - gAudioCustomUpdateFunction(); - } - - dmaCount = gAudioCtx.curAudioFrameDmaCount; - for (i = 0; i < gAudioCtx.curAudioFrameDmaCount; i++) { - if (osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK) == 0) { - dmaCount--; - } - } - - if (dmaCount != 0) { - for (i = 0; i < dmaCount; i++) { - osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_BLOCK); - } - } - - validCount = gAudioCtx.curAudioFrameDmaQueue.validCount; - if (validCount != 0) { - for (i = 0; i < validCount; i++) { - osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK); - } - } - - gAudioCtx.curAudioFrameDmaCount = 0; AudioLoad_DecreaseSampleDmaTtls(); AudioLoad_ProcessLoads(gAudioCtx.resetStatus); AudioLoad_ProcessScriptLoads(); @@ -98,105 +47,29 @@ AudioTask* AudioThread_UpdateImpl(void) { if (gAudioCtx.resetStatus != 0) { if (AudioHeap_ResetStep() == 0) { if (gAudioCtx.resetStatus == 0) { - osSendMesg(gAudioCtx.audioResetQueueP, OS_MESG_8(gAudioCtx.specId), OS_MESG_NOBLOCK); + osSendMesg8(gAudioCtx.audioResetQueueP, gAudioCtx.specId, OS_MESG_NOBLOCK); } - - sWaitingAudioTask = NULL; - return NULL; } } - if (gAudioCtx.resetTimer > 16) { - return NULL; - } - if (gAudioCtx.resetTimer != 0) { - gAudioCtx.resetTimer++; - } - - gAudioCtx.curTask = &gAudioCtx.rspTask[gAudioCtx.rspTaskIndex]; - gAudioCtx.curAbiCmdBuf = gAudioCtx.abiCmdBufs[gAudioCtx.rspTaskIndex]; - - index = gAudioCtx.curAiBufferIndex; - curAiBuffer = gAudioCtx.aiBuffers[index]; - - gAudioCtx.numSamplesPerFrame[index] = - (s16)((((gAudioCtx.audioBufferParameters.numSamplesPerFrameTarget - numSamplesRemainingInAi) + - (8 * SAMPLES_PER_FRAME)) & - ~0xF) + - (1 * SAMPLES_PER_FRAME)); - - // Clamp numSamplesPerFrame between numSamplesPerFrameMin and numSamplesPerFrameMax - if (gAudioCtx.numSamplesPerFrame[index] < gAudioCtx.audioBufferParameters.numSamplesPerFrameMin) { - gAudioCtx.numSamplesPerFrame[index] = gAudioCtx.audioBufferParameters.numSamplesPerFrameMin; - } - if (gAudioCtx.numSamplesPerFrame[index] > gAudioCtx.audioBufferParameters.numSamplesPerFrameMax) { - gAudioCtx.numSamplesPerFrame[index] = gAudioCtx.audioBufferParameters.numSamplesPerFrameMax; - } - - j = 0; + int j = 0; if (gAudioCtx.resetStatus == 0) { // msg = 0000RREE R = read pos, E = End Pos - while (osRecvMesg(gAudioCtx.threadCmdProcQueueP, (OSMesg*)&msg, OS_MESG_NOBLOCK) != -1) { - //! FAKE: - if (1) {} - AudioThread_ProcessCmds(msg); + while (osRecvMesg(gAudioCtx.threadCmdProcQueueP, &sp4C, OS_MESG_NOBLOCK) != -1) { + AudioThread_ProcessCmds(sp4C.data32); j++; } - if ((j == 0) && gAudioCtx.threadCmdQueueFinished) { + if ((j == 0) && (gAudioCtx.threadCmdQueueFinished)) { AudioThread_ScheduleProcessCmds(); } } - - if (gAudioSPDataPtr == (u64*)gAudioCtx.curAbiCmdBuf) { - return (void*)-1; - } - - gAudioCtx.curAbiCmdBuf = - AudioSynth_Update(gAudioCtx.curAbiCmdBuf, &numAbiCmds, curAiBuffer, gAudioCtx.numSamplesPerFrame[index]); - - // Update audioRandom to the next random number + s32 writtenCmds; + AudioSynth_Update(gAudioCtx.curAbiCmdBuf, &writtenCmds, samples, num_samples); gAudioCtx.audioRandom = (gAudioCtx.audioRandom + gAudioCtx.totalTaskCount) * osGetCount(); - gAudioCtx.audioRandom = gAudioCtx.audioRandom + gAudioCtx.aiBuffers[index][gAudioCtx.totalTaskCount & 0xFF]; +} - // gWaveSamples[8] interprets compiled assembly code as s16 samples as a way to generate sound with noise. - // Start with the address of AudioThread_Update(), and offset it by a random number between 0 - 0xFFF0 - // Use the resulting address as the starting address to interpret an array of samples i.e. `s16 samples[]` - gWaveSamples[8] = (s16*)((u8*)AudioThread_Update + (gAudioCtx.audioRandom & 0xFFF0)); - - index = gAudioCtx.rspTaskIndex; - gAudioCtx.curTask->taskQueue = NULL; - gAudioCtx.curTask->unk_44 = NULL; - - task = &gAudioCtx.curTask->task.t; - task->type = M_AUDTASK; - task->flags = 0; - task->ucode_boot = aspMainTextStart; - task->ucode_boot_size = SP_UCODE_SIZE; - task->ucode_data_size = ((aspMainDataEnd - aspMainDataStart) * sizeof(u64)) - 1; - task->ucode = aspMainTextStart; - task->ucode_data = aspMainDataStart; - task->ucode_size = SP_UCODE_SIZE; - task->dram_stack = (u64*)D_801D6200; - task->dram_stack_size = 0; - task->output_buff = NULL; - task->output_buff_size = NULL; - if (1) {} - task->data_ptr = (u64*)gAudioCtx.abiCmdBufs[index]; - task->data_size = numAbiCmds * sizeof(Acmd); - task->yield_data_ptr = NULL; - task->yield_data_size = 0; - - if (gAudioCtx.numAbiCmdsMax < numAbiCmds) { - gAudioCtx.numAbiCmdsMax = numAbiCmds; - } - - if (gAudioCtx.audioBufferParameters.specUnk4 == 1) { - return gAudioCtx.curTask; - } else { - sWaitingAudioTask = gAudioCtx.curTask; - return NULL; - } - #endif +AudioTask* AudioThread_UpdateImpl(void) { + return NULL; } void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) { @@ -343,7 +216,7 @@ void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) { break; case AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA: - AudioHeap_SetReverbData(cmd->arg1, cmd->arg0, cmd->asInt, false); + AudioHeap_SetReverbData(cmd->arg1, cmd->arg0, cmd->asPtr, false); break; default: @@ -391,11 +264,13 @@ void AudioThread_InitMesgQueuesInternal(void) { osCreateMesgQueue(gAudioCtx.audioResetQueueP, gAudioCtx.audioResetMesgs, ARRAY_COUNT(gAudioCtx.audioResetMesgs)); } -void AudioThread_QueueCmd(u32 opArgs, void** data) { - AudioCmd* cmd = &gAudioCtx.threadCmdBuf[gAudioCtx.threadCmdWritePos & 0xFF]; +const char* cmd_op_to_str(u8 op); - cmd->opArgs = opArgs; - cmd->data = *data; +void AudioThread_QueueCmd(AudioCmd cmdData) { + AudioCmd* cmd = &gAudioCtx.threadCmdBuf[gAudioCtx.threadCmdWritePos & 0xFF]; + *cmd = cmdData; + + LUSLOG_TRACE("Queueing Command: %s", cmd_op_to_str(cmd->op)); gAudioCtx.threadCmdWritePos++; @@ -404,24 +279,44 @@ void AudioThread_QueueCmd(u32 opArgs, void** data) { } } +void AudioThread_QueueCmdPtr(u32 opArgs, void* data) { + AudioCmd cmd = { + .opArgs = opArgs, + .asPtr = data, + }; + AudioThread_QueueCmd(cmd); +} + void AudioThread_QueueCmdF32(u32 opArgs, f32 data) { - AudioThread_QueueCmd(opArgs, (void**)&data); + AudioCmd cmd = { + .opArgs = opArgs, + .asFloat = data, + }; + AudioThread_QueueCmd(cmd); } void AudioThread_QueueCmdS32(u32 opArgs, s32 data) { - AudioThread_QueueCmd(opArgs, (void**)&data); + AudioCmd cmd = { + .opArgs = opArgs, + .asInt = data, + }; + AudioThread_QueueCmd(cmd); } void AudioThread_QueueCmdS8(u32 opArgs, s8 data) { - u32 uData = data << 0x18; - - AudioThread_QueueCmd(opArgs, (void**)&uData); + AudioCmd cmd = { + .opArgs = opArgs, + .asSbyte = data, + }; + AudioThread_QueueCmd(cmd); } void AudioThread_QueueCmdU16(u32 opArgs, u16 data) { - u32 uData = data << 0x10; - - AudioThread_QueueCmd(opArgs, (void**)&uData); + AudioCmd cmd = { + .opArgs = opArgs, + .asUShort = data, + }; + AudioThread_QueueCmd(cmd); } s32 AudioThread_ScheduleProcessCmds(void) { @@ -489,6 +384,72 @@ void AudioThread_ProcessCmd(AudioCmd* cmd) { } } +const char* cmd_op_to_str(u8 op) { +#define CASE(x) \ + case x: \ + return #x + switch (op) { + CASE(AUDIOCMD_OP_NOOP); + CASE(AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE); + CASE(AUDIOCMD_OP_CHANNEL_SET_VOL); + CASE(AUDIOCMD_OP_CHANNEL_SET_PAN); + CASE(AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE); + CASE(AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME); + CASE(AUDIOCMD_OP_CHANNEL_SET_IO); + CASE(AUDIOCMD_OP_CHANNEL_SET_PAN_WEIGHT); + CASE(AUDIOCMD_OP_CHANNEL_SET_MUTE); + CASE(AUDIOCMD_OP_CHANNEL_SET_MUTE_FLAGS); + CASE(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_DEPTH); + CASE(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_RATE); + CASE(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_SIZE); + CASE(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_GAIN); + CASE(AUDIOCMD_OP_CHANNEL_SET_STEREO); + CASE(AUDIOCMD_OP_CHANNEL_SET_SET_START_POS); + CASE(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE); + CASE(AUDIOCMD_OP_CHANNEL_SET_REVERB_INDEX); + CASE(AUDIOCMD_OP_CHANNEL_SET_SURROUND_EFFECT_INDEX); + CASE(AUDIOCMD_OP_CHANNEL_SET_FILTER); + CASE(AUDIOCMD_OP_CHANNEL_SET_GAIN); + CASE(AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE); + CASE(AUDIOCMD_OP_SEQPLAYER_SET_IO); + CASE(AUDIOCMD_OP_SEQPLAYER_SET_TEMPO); + CASE(AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION); + CASE(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO); + CASE(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SET_VOLUME); + CASE(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SCALED_VOLUME); + CASE(AUDIOCMD_OP_SEQPLAYER_RESET_VOLUME); + CASE(AUDIOCMD_OP_SEQPLAYER_SET_BEND); + CASE(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO_TICKS); + CASE(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS); + CASE(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER); + CASE(AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER); + CASE(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER_SKIP_TICKS); + CASE(AUDIOCMD_OP_GLOBAL_SET_CHANNEL_MASK); + CASE(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT); + CASE(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT); + CASE(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT); + CASE(AUDIOCMD_OP_GLOBAL_POP_PERSISTENT_CACHE); + CASE(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION); + CASE(AUDIOCMD_OP_GLOBAL_E5); + CASE(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA); + CASE(AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE); + CASE(AUDIOCMD_OP_GLOBAL_MUTE); + CASE(AUDIOCMD_OP_GLOBAL_UNMUTE); + CASE(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT); + CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK); + CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT); + CASE(AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS); + CASE(AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS); + CASE(AUDIOCMD_OP_GLOBAL_RESET_AUDIO_HEAP); + CASE(AUDIOCMD_OP_GLOBAL_NOOP_1); + CASE(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION); + CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SEQ); + CASE(AUDIOCMD_OP_GLOBAL_NOOP_2); + CASE(AUDIOCMD_OP_GLOBAL_DISABLE_ALL_SEQPLAYERS); + } +#undef CASE +} + void AudioThread_ProcessCmds(u32 msg) { static u8 sCurCmdRdPos = 0; AudioCmd* cmd; @@ -506,6 +467,7 @@ void AudioThread_ProcessCmds(u32 msg) { } cmd = &gAudioCtx.threadCmdBuf[sCurCmdRdPos++ & 0xFF]; + LUSLOG_TRACE("Process Command: %s", cmd_op_to_str(cmd->op)); if (cmd->op == AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS) { gAudioCtx.threadCmdQueueFinished = true; break; @@ -528,8 +490,8 @@ u32 AudioThread_GetExternalLoadQueueMsg(u32* retMsg) { return msg >> 0x18; } -u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts) { - return AudioLoad_GetFontsForSequence(seqId, outNumFonts); +u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff) { + return AudioLoad_GetFontsForSequence(seqId, outNumFonts, buff); } void AudioThread_GetSampleBankIdsOfFont(s32 fontId, u32* sampleBankId1, u32* sampleBankId2) { @@ -539,11 +501,11 @@ void AudioThread_GetSampleBankIdsOfFont(s32 fontId, u32* sampleBankId1, u32* sam s32 func_80193C5C(void) { s32 pad; - s32 specId; + OSMesg specId; - if (osRecvMesg(gAudioCtx.audioResetQueueP, (OSMesg*)&specId, OS_MESG_NOBLOCK) == -1) { + if (osRecvMesg(gAudioCtx.audioResetQueueP, &specId, OS_MESG_NOBLOCK) == -1) { return 0; - } else if (gAudioCtx.specId != specId) { + } else if (gAudioCtx.specId != specId.data8) { return -1; } else { return 1; diff --git a/mm/src/audio/sequence.c b/mm/src/audio/sequence.c index 7d37a0ae9..834bb8f0b 100644 --- a/mm/src/audio/sequence.c +++ b/mm/src/audio/sequence.c @@ -115,7 +115,11 @@ void AudioSeq_ProcessSeqCmd(u32 cmd) { // `fadeTimer` continues to be scaled in `AudioSeq_StartSequence` fadeTimer = (cmd & 0xFF0000) >> 13; if (!gActiveSeqs[seqPlayerIndex].isWaitingForFonts && !sStartSeqDisabled) { - if (seqArgs < 0x80) { + // BEN: The code block to later load a sequence doesn't exist in OOT. + // BEN: The thing preventing this code block from running is actually the fact that we killed the audio tables. + // BEN: This delayed loading method actually utilizes some functions that OOT is no longer utilizing. + // BEN: The short of it ends up being the short circuit here is fine since it works and the stuff is loaded anyway. + if (seqArgs < 0x80 || 1) { AudioSeq_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer); } else { // Store the cmd to be called again once the fonts are loaded @@ -123,19 +127,22 @@ void AudioSeq_ProcessSeqCmd(u32 cmd) { gActiveSeqs[seqPlayerIndex].startAsyncSeqCmd = (cmd & ~(SEQ_FLAG_ASYNC | SEQCMD_ASYNC_ACTIVE)) + SEQCMD_ASYNC_ACTIVE; gActiveSeqs[seqPlayerIndex].isWaitingForFonts = true; - gActiveSeqs[seqPlayerIndex].fontId = *AudioThread_GetFontsForSequence(seqId, &outNumFonts); + u8* fontBuff[16]; + u8* prevFontBuff[16]; + u8* font = AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff); + gActiveSeqs[seqPlayerIndex].fontId = *font; AudioSeq_StopSequence(seqPlayerIndex, 1); if (gActiveSeqs[seqPlayerIndex].prevSeqId != NA_BGM_DISABLED) { - if (*AudioThread_GetFontsForSequence(seqId, &outNumFonts) != - *AudioThread_GetFontsForSequence(gActiveSeqs[seqPlayerIndex].prevSeqId & 0xFF, - &outNumFonts)) { + if (*AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff) != + *AudioThread_GetFontsForSequence(gActiveSeqs[seqPlayerIndex].prevSeqId & 0xFF, &outNumFonts, + prevFontBuff)) { // Discard Seq Fonts AUDIOCMD_GLOBAL_DISCARD_SEQ_FONTS((s32)seqId); } } - AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(*AudioThread_GetFontsForSequence(seqId, &outNumFonts), + AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(*AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff), (u8)((seqPlayerIndex + 1) & 0xFF)); } } @@ -861,7 +868,7 @@ u8 AudioSeq_ResetReverb(void) { if (fadeReverb & 1) { AUDIOCMD_GLOBAL_SET_REVERB_DATA( reverbIndex, REVERB_DATA_TYPE_SETTINGS, - (s32)(gReverbSettingsTable[(u8)(sResetAudioHeapSeqCmd & 0xFF)] + reverbIndex)); + (uintptr_t)(gReverbSettingsTable[(u8)(sResetAudioHeapSeqCmd & 0xFF)] + reverbIndex)); AudioThread_ScheduleProcessCmds(); } reverbIndex++; diff --git a/mm/src/audio/session_config.c b/mm/src/audio/session_config.c index e0881913b..81d7a280e 100644 --- a/mm/src/audio/session_config.c +++ b/mm/src/audio/session_config.c @@ -22,11 +22,13 @@ const s16 gAudioTatumInit[] = { #define PERMANENT_POOL_SIZE \ (SFX_SEQ_SIZE + AMBIENCE_SEQ_SIZE + SOUNDFONT_0_SIZE + SOUNDFONT_1_SIZE + SOUNDFONT_2_SIZE + 0x430) -const AudioHeapInitSizes gAudioHeapInitSizes = { - ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size - ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size - ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size -}; +// const AudioHeapInitSizes gAudioHeapInitSizes = { +// ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size +// ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size +// ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size +// }; + +const AudioHeapInitSizes gAudioHeapInitSizes = { 0x37F000, 0xE0E00, 0xBCE00 }; #define REVERB_INDEX_0_SETTINGS \ { 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 } @@ -120,66 +122,66 @@ ReverbSettings* gReverbSettingsTable[] = { AudioSpec gAudioSpecs[21] = { /* 0x0 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x1 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x2 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x3 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x4 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x5 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x6 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x7 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x8 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x9 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0xA */ - { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0, + { 44100, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0, 0xDC800 }, /* 0xB */ - { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0xC */ - { 32000, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xCC800 }, /* 0xD */ - { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0xE */ - { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0xF */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0, 0xDC800 }, /* 0x10 */ - { 32000, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x11 */ - { 32000, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x12 */ - { 32000, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + { 44100, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x13 */ { 22050, 1, 24, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, 0xDC800 }, /* 0x14 */ - { 32000, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0, + { 44100, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0, 0xDC800 }, }; diff --git a/mm/src/audio/sfx.c b/mm/src/audio/sfx.c index 79d10804b..f66747999 100644 --- a/mm/src/audio/sfx.c +++ b/mm/src/audio/sfx.c @@ -741,8 +741,6 @@ void AudioSfx_StopByPosAndBank(u8 bankId, Vec3f* pos) { } void AudioSfx_StopByPos(Vec3f* pos) { -// BENTODO: infinite loop -#if 0 u8 bankId; SfxBankEntry entryToRemove; @@ -752,7 +750,6 @@ void AudioSfx_StopByPos(Vec3f* pos) { entryToRemove.posX = &pos->x; AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_POS, &entryToRemove); -#endif } void AudioSfx_StopByPosAndId(Vec3f* pos, u16 sfxId) { @@ -817,8 +814,6 @@ void AudioSfx_StopByTokenAndId(u8 token, u16 sfxId) { } void AudioSfx_StopById(u32 sfxId) { - // BENTODO: infinite loop -#if 0 SfxBankEntry* entry; u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next; u8 prevEntryIndex = 0; @@ -842,7 +837,6 @@ void AudioSfx_StopById(u32 sfxId) { entryToRemove.sfxId = sfxId; AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_ID, &entryToRemove); -#endif } void AudioSfx_ProcessRequests(void) { diff --git a/mm/src/code/audio_thread_manager.c b/mm/src/code/audio_thread_manager.c index 78e30624a..ac7ed2e5b 100644 --- a/mm/src/code/audio_thread_manager.c +++ b/mm/src/code/audio_thread_manager.c @@ -9,9 +9,9 @@ void AudioMgr_NotifyTaskDone(AudioMgr* audioMgr) { osSendMesg(task->taskQueue, OS_MESG_PTR(NULL), OS_MESG_BLOCK); } } -// BENTODO + void AudioMgr_HandleRetrace(AudioMgr* audioMgr) { - #if 0 + return; static s32 sRetryCount = 10; AudioTask* rspTask; s32 timerMsgVal = 666; @@ -45,31 +45,9 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr) { rspTask = AudioThread_Update(); } - if (audioMgr->rspTask != NULL) { - while (true) { - osSetTimer(&timer, OS_USEC_TO_CYCLES(32000), 0, &audioMgr->cmdQueue, OS_MESG_32(timerMsgVal)); - osRecvMesg(&audioMgr->cmdQueue, (OSMesg*)&msg, OS_MESG_BLOCK); - osStopTimer(&timer); - if (msg == timerMsgVal) { - osSyncPrintf("AUDIO SP TIMEOUT %08x %08x\n", audioMgr->rspTask, audioMgr->rspTask->task); - if (sRetryCount >= 0) { - sRetryCount--; - Sched_SendAudioCancelMsg(audioMgr->sched); - } else { - osSyncPrintf("audioMgr.c:もうダメ!死ぬ!\n"); - osDestroyThread(NULL); - break; - } - } else { - break; - } - } - - AudioMgr_NotifyTaskDone(audioMgr); - } + AudioMgr_NotifyTaskDone(audioMgr); audioMgr->rspTask = rspTask; - #endif } void AudioMgr_HandlePreNMI(AudioMgr* audioMgr) { @@ -139,6 +117,16 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon osCreateMesgQueue(&audioMgr->interruptQueue, audioMgr->interruptMsgBuf, ARRAY_COUNT(audioMgr->interruptMsgBuf)); osCreateMesgQueue(&audioMgr->lockQueue, audioMgr->lockMsgBuf, ARRAY_COUNT(audioMgr->lockMsgBuf)); - osCreateThread(&audioMgr->thread, id, AudioMgr_ThreadEntry, audioMgr, stack, pri); - osStartThread(&audioMgr->thread); + Audio_Init(); + AudioLoad_SetDmaHandler(DmaMgr_DmaHandler); + Audio_InitSound(); + osSendMesg(&audioMgr->lockQueue, OS_MESG_PTR(NULL), OS_MESG_BLOCK); + + // Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); + // Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); + // Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); + // Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); + + // osCreateThread(&audioMgr->thread, id, AudioMgr_ThreadEntry, audioMgr, stack, pri); + // osStartThread(&audioMgr->thread); } diff --git a/mm/src/code/game.c b/mm/src/code/game.c index 4f653451a..2c94fd314 100644 --- a/mm/src/code/game.c +++ b/mm/src/code/game.c @@ -240,8 +240,8 @@ void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* g void GameState_Destroy(GameState* gameState) { // BENTODO - //AudioMgr_StopAllSfxExceptSystem(); - //Audio_Update(); + AudioMgr_StopAllSfxExceptSystem(); + Audio_Update(); osRecvMesg(&gameState->gfxCtx->queue, NULL, OS_MESG_BLOCK); if (gameState->destroy != NULL) { diff --git a/mm/src/code/graph.c b/mm/src/code/graph.c index 3f529f17d..3004201bb 100644 --- a/mm/src/code/graph.c +++ b/mm/src/code/graph.c @@ -242,9 +242,9 @@ void Graph_UpdateGame(GameState* gameState) { GameState_GetInput(gameState); GameState_IncrementFrameCount(gameState); // BENTODO - // if (SREG(20) < 3) { - // Audio_Update(); - //} + if (SREG(20) < 3) { + Audio_Update(); + } } /** @@ -277,10 +277,10 @@ void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) { Gfx* gfx = gGfxMasterDL->taskStart; gSPSegment(gfx++, 0x0E, gGfxMasterDL); - gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[3])); // Work buffer - gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[0])); // OPA buffer - gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[1])); // XLU buffer - gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[2])); // Overlay buffer + gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[3])); // Work buffer + gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[0])); // OPA buffer + gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[1])); // XLU buffer + gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[2])); // Overlay buffer gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(debugDisp[0])); // Debug buffer gDPPipeSync(gfx++); diff --git a/mm/src/code/main.c b/mm/src/code/main.c index 0b16201b7..3f662e33d 100644 --- a/mm/src/code/main.c +++ b/mm/src/code/main.c @@ -75,6 +75,8 @@ void SDL_main(int argc, char** argv /* void* arg*/) { osCreateMesgQueue(&sIrqMgrMsgQueue, sIrqMgrMsgBuf, ARRAY_COUNT(sIrqMgrMsgBuf)); PadMgr_Init(&sSerialEventQueue, &gIrqMgr, Z_THREAD_ID_PADMGR, Z_PRIORITY_PADMGR, STACK_TOP(sPadMgrStack)); + AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gSchedContext, + &gIrqMgr); #if 0 StackCheck_Init(&sSchedStackInfo, sSchedStack, STACK_TOP(sSchedStack), 0, 0x100, "sched"); Sched_Init(&gSchedContext, STACK_TOP(sSchedStack), Z_PRIORITY_SCHED, gViConfigModeType, 1, &gIrqMgr); diff --git a/mm/src/code/stubs.c b/mm/src/code/stubs.c index cf6952d40..7ca966068 100644 --- a/mm/src/code/stubs.c +++ b/mm/src/code/stubs.c @@ -40,10 +40,10 @@ ActiveSequence gActiveSeqs[5]; AudioContext gAudioCtx; s32 D_801FD120; -u8 gSoundFontTable[5]; -u8 gSequenceFontTable[5]; -u8 gSequenceTable[5]; -u8 gSampleBankTable[5]; +// u8 gSoundFontTable[5]; +// u8 gSequenceFontTable[5]; +// u8 gSequenceTable[5]; +// u8 gSampleBankTable[5]; AudioCustomUpdateFunction gAudioCustomUpdateFunction; AudioCustomSeqFunction gAudioCustomSeqFunction; @@ -170,9 +170,9 @@ char* ResourceMgr_LoadTexOrDListByName(const char* data); void gSPSegment(void* value, int segNum, uintptr_t target) { char* imgData = (char*)target; - + int res = ResourceMgr_OTRSigCheck(imgData); - + // OTRTODO: Disabled for now to fix an issue with HD Textures. // With HD textures, we need to pass the path to F3D, not the raw texture data. // Otherwise the needed metadata is not available for proper rendering... @@ -181,23 +181,23 @@ void gSPSegment(void* value, int segNum, uintptr_t target) { // That should not affect HD textures. if (res) { uintptr_t desiredTarget = (uintptr_t)ResourceMgr_LoadIfDListByName(imgData); - + if (desiredTarget != NULL) target = desiredTarget; } - + __gSPSegment(value, segNum, target); } void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target) { char* imgData = (char*)target; - + int res = ResourceMgr_OTRSigCheck(imgData); - + if (res) { target = (uintptr_t)ResourceMgr_LoadTexOrDListByName(imgData); } - + __gSPSegment(value, segNum, target); } @@ -211,42 +211,42 @@ void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb) { void gSPDisplayList(Gfx* pkt, Gfx* dl) { char* imgData = (char*)dl; - + if (ResourceMgr_OTRSigCheck(imgData) == 1) { - + // ResourceMgr_PushCurrentDirectory(imgData); // gsSPPushCD(pkt++, imgData); dl = ResourceMgr_LoadGfxByName(imgData); } - + __gSPDisplayList(pkt, dl); } void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset) { char* imgData = (char*)dl; - + if (ResourceMgr_OTRSigCheck(imgData) == 1) dl = ResourceMgr_LoadGfxByName(imgData); - + __gSPDisplayList(pkt, dl + offset); } void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0) { if (ResourceMgr_OTRSigCheck((char*)v) == 1) v = (uintptr_t)ResourceMgr_LoadVtxByName((char*)v); - + __gSPVertex(pkt, v, n, v0); } void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr) { char* imgData = (char*)texAddr; - + if (texAddr != 0 && ResourceMgr_OTRSigCheck(imgData)) { // Temporary solution to the mq/nonmq issue, this will be // handled better with LUS 1.0 texAddr = (uintptr_t)ResourceMgr_LoadTexOrDListByName(imgData); } - + __gSPInvalidateTexCache(pkt, texAddr); } void func_801A1290(void) { @@ -758,7 +758,7 @@ void guPerspectiveF(f32 mf[4][4], u16* perspNorm, f32 fovy, f32 aspect, f32 near void guPerspective(Mtx* m, u16* perspNorm, float fovy, float aspect, float near, float far, float scale) { float mf[4][4]; - + guPerspectiveF(mf, perspNorm, fovy, aspect, near, far, scale); Matrix_MtxFToMtx((MtxF*)mf, m); //guPerspectiveF(mf, perspNorm, fovy, aspect, near, far, scale); diff --git a/mm/src/code/z_actor.c b/mm/src/code/z_actor.c index 61673880d..1b79e7542 100644 --- a/mm/src/code/z_actor.c +++ b/mm/src/code/z_actor.c @@ -3507,8 +3507,8 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { if (actor == actorCtx->targetCtx.bgmEnemy) { actorCtx->targetCtx.bgmEnemy = NULL; } - // BENTODO -// AudioSfx_StopByPos(&actor->projectedPos); + + AudioSfx_StopByPos(&actor->projectedPos); Actor_Destroy(actor, play); newHead = Actor_RemoveFromCategory(play, actorCtx, actor); diff --git a/mm/src/code/z_actor_dlftbls.c b/mm/src/code/z_actor_dlftbls.c index 68d96eba6..1a6c3f50f 100644 --- a/mm/src/code/z_actor_dlftbls.c +++ b/mm/src/code/z_actor_dlftbls.c @@ -62,7 +62,7 @@ void ActorOverlayTable_FaultClient(void* arg0, void* arg1) { overlaySize = (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart; if (overlayEntry->loadedRamAddr != NULL) { FaultDrawer_Printf("%3d %08x-%08x %3d %s\n", actorId, overlayEntry->loadedRamAddr, - (u32)overlayEntry->loadedRamAddr + overlaySize, overlayEntry->numLoaded, ""); + (uintptr_t)overlayEntry->loadedRamAddr + overlaySize, overlayEntry->numLoaded, ""); } } } diff --git a/mm/src/code/z_message_nes.c b/mm/src/code/z_message_nes.c index c4839d126..9e75e09ca 100644 --- a/mm/src/code/z_message_nes.c +++ b/mm/src/code/z_message_nes.c @@ -579,7 +579,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) { case 0x1B: // MESSAGE_BOX_BREAK_DELAYED if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8; - stateTimerHi |= msgCtx->decodedBuffer.schar[++i]; + stateTimerHi += msgCtx->decodedBuffer.schar[++i]; msgCtx->stateTimer = stateTimerHi; msgCtx->msgMode = MSGMODE_TEXT_DELAYED_BREAK; } @@ -595,7 +595,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) { msgCtx->textboxEndType = 0x50; } stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8; - stateTimerHi |= msgCtx->decodedBuffer.schar[++i]; + stateTimerHi += msgCtx->decodedBuffer.schar[++i]; msgCtx->stateTimer = stateTimerHi; Font_LoadMessageBoxEndIcon(font, 1); if (play->csCtx.state == CS_STATE_IDLE) { @@ -610,7 +610,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) { msgCtx->msgMode = MSGMODE_TEXT_DONE; msgCtx->textboxEndType = 0x52; stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8; - stateTimerHi |= msgCtx->decodedBuffer.schar[++i]; + stateTimerHi += msgCtx->decodedBuffer.schar[++i]; msgCtx->stateTimer = stateTimerHi; Font_LoadMessageBoxEndIcon(font, 1); if (play->csCtx.state == CS_STATE_IDLE) { @@ -623,7 +623,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) { case 0x1E: // MESSAGE_SFX if (((i + 1) == msgCtx->textDrawPos) && (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING)) { stateTimerHi = msgCtx->decodedBuffer.schar[i + 1] << 8; - stateTimerHi |= msgCtx->decodedBuffer.schar[i + 2]; + stateTimerHi += (uint8_t)msgCtx->decodedBuffer.schar[i + 2]; Audio_PlaySfx(stateTimerHi); } if ((i + 1) == msgCtx->textDrawPos) { @@ -636,7 +636,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) { if (((i + 1) == msgCtx->textDrawPos) && (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING)) { msgCtx->msgMode = MSGMODE_9; stateTimerHi = msgCtx->decodedBuffer.schar[i + 1] << 8; - stateTimerHi |= msgCtx->decodedBuffer.schar[i + 2]; + stateTimerHi += msgCtx->decodedBuffer.schar[i + 2]; msgCtx->textDelayTimer = stateTimerHi; } i += 2; @@ -1878,7 +1878,7 @@ void Message_DecodeNES(PlayState* play) { (msgCtx->textBoxType == TEXTBOX_TYPE_8) || (msgCtx->textBoxType == TEXTBOX_TYPE_9) || (msgCtx->textBoxType == TEXTBOX_TYPE_B) || (msgCtx->unk11F0C == 3)) { sfxHi = msgCtx->decodedBuffer.schar[decodedBufPos - 1] << 8; - sfxHi |= msgCtx->decodedBuffer.schar[decodedBufPos]; + sfxHi += (uint8_t)msgCtx->decodedBuffer.schar[decodedBufPos]; Audio_PlaySfx(sfxHi); } } else if (curChar == 0x1F) { diff --git a/mm/src/code/z_scene.c b/mm/src/code/z_scene.c index 3a7a4dfc9..ae0550daa 100644 --- a/mm/src/code/z_scene.c +++ b/mm/src/code/z_scene.c @@ -62,7 +62,7 @@ void Object_InitContext(GameState* gameState, ObjectContext* objectCtx) { // clang-format on objectCtx->spaceStart = objectCtx->slots[0].segment = THA_AllocTailAlign16(&gameState->tha, spaceSize); - objectCtx->spaceEnd = (void*)((u32)objectCtx->spaceStart + spaceSize); + objectCtx->spaceEnd = (void*)((uintptr_t)objectCtx->spaceStart + spaceSize); objectCtx->mainKeepSlot = Object_SpawnPersistent(objectCtx, GAMEPLAY_KEEP); gSegments[4] = OS_K0_TO_PHYSICAL(objectCtx->slots[objectCtx->mainKeepSlot].segment); diff --git a/mm/src/overlays/actors/ovl_Obj_Sound/z_obj_sound.c b/mm/src/overlays/actors/ovl_Obj_Sound/z_obj_sound.c index d7a285c15..51295590a 100644 --- a/mm/src/overlays/actors/ovl_Obj_Sound/z_obj_sound.c +++ b/mm/src/overlays/actors/ovl_Obj_Sound/z_obj_sound.c @@ -48,8 +48,6 @@ void ObjSound_Destroy(Actor* thisx, PlayState* play) { } void ObjSound_Update(Actor* thisx, PlayState* play) { - // BENTODO: stub audio code that crashes -#if 0 ObjSound* this = THIS; if (this->soundType == OBJ_SOUND_TYPE_SFX) { @@ -67,7 +65,6 @@ void ObjSound_Update(Actor* thisx, PlayState* play) { } else { this->unk_144 = true; } -#endif } void ObjSound_Draw(Actor* thisx, PlayState* play) { diff --git a/mm/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c b/mm/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c index 16609edc5..31d8264fa 100644 --- a/mm/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c +++ b/mm/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c @@ -5,6 +5,7 @@ */ #include "z_oceff_wipe5.h" +#include "assets/overlays/ovl_Oceff_Wipe5/ovl_Oceff_Wipe5.h" #include "BenPort.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_2000000) @@ -29,20 +30,21 @@ ActorInit Oceff_Wipe5_InitVars = { }; UNK_TYPE4 D_80BC9260; +static Vtx* gOceff5VtxData; void OceffWipe5_Init(Actor* thisx, PlayState* play) { OceffWipe5* this = THIS; + gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5Vtx); + Actor_SetScale(&this->actor, 1.0f); this->counter = 0; this->actor.world.pos = play->cameraPtrs[play->activeCamId]->eye; } -static Vtx* gOceff5VtxData; - void OceffWipe5_Destroy(Actor* thisx, PlayState* play) { OceffWipe5* this = THIS; - gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5VtxData); + gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5Vtx); Magic_Reset(play); play->msgCtx.ocarinaSongEffectActive = false; @@ -59,7 +61,6 @@ void OceffWipe5_Update(Actor* thisx, PlayState* play) { } } -#include "assets/overlays/ovl_Oceff_Wipe5/ovl_Oceff_Wipe5.h" static u8 sPrimColors[] = { 255, 255, 200, 255, 255, 200, 200, 255, 255, 255, 255, 200, 255, 200, 255, diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 487ffcd40..4e92961d7 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -1781,8 +1781,6 @@ u16 D_8085C3EC[] = { }; void func_8082E00C(Player* this) { - return; - // BENTODO s32 i; u16* sfxIdPtr = D_8085C3EC;