summaryrefslogtreecommitdiff
path: root/src/code/audio
diff options
context:
space:
mode:
authorengineer124 <47598039+engineer124@users.noreply.github.com>2022-03-24 12:22:13 +1100
committerGitHub <noreply@github.com>2022-03-23 21:22:13 -0400
commitb852a9a9300c05de4e01e71a578ca355b6793f91 (patch)
tree0be976ba1a139f319e8b634953067b90fa8e43f0 /src/code/audio
parent92c4d42f446cc12c79de9b441b9afa341cf294e8 (diff)
Audio_Load OK and Documented (#620)
* Copy audio_load progress from main branch * Fix warning * fix UB * cleanup WIP * Add docs, bss still broken * bss fix * bytesRemaining with size_t * PR Suggestions * PR Suggestions * Fix bss * Fix bss * PR Suggestions
Diffstat (limited to 'src/code/audio')
-rw-r--r--src/code/audio/audio_heap.c28
-rw-r--r--src/code/audio/audio_load.c2318
-rw-r--r--src/code/audio/audio_playback.c4
-rw-r--r--src/code/audio/audio_seqplayer.c2
-rw-r--r--src/code/audio/code_80192BE0.c2
5 files changed, 2177 insertions, 177 deletions
diff --git a/src/code/audio/audio_heap.c b/src/code/audio/audio_heap.c
index b3d83c1f9..70c737930 100644
--- a/src/code/audio/audio_heap.c
+++ b/src/code/audio/audio_heap.c
@@ -6,29 +6,29 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B250.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B318.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_DiscardFont.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B3FC.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B474.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B4F8.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_WritebackDCache.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B520.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B578.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocAttemptExternal.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocDmaMemory.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B608.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B640.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocZeroed.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B69C.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B6E8.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_Alloc.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B740.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocPoolInit.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B768.s")
@@ -38,7 +38,7 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B7BC.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B8FC.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_InitMainPool.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018B95C.s")
@@ -48,9 +48,9 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018BB28.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018BBEC.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocCached.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018C380.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_SearchCaches.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018C3D8.s")
@@ -70,15 +70,15 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018CC3C.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018CCA8.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_ResetStep.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018CFAC.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018D57C.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_SearchPermanentCache.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018D5D4.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocPermanent.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018D658.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_AllocSampleCache.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018D6C8.s")
@@ -100,7 +100,7 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018DFE0.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018E00C.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/AudioHeap_ApplySampleBankCache.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_heap/func_8018E03C.s")
diff --git a/src/code/audio/audio_load.c b/src/code/audio/audio_load.c
index 497f9d47a..b63f8192b 100644
--- a/src/code/audio/audio_load.c
+++ b/src/code/audio/audio_load.c
@@ -1,161 +1,2161 @@
-#include "global.h"
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018EB60.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018EC4C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/D_801E030C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018EF88.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/AudioLoad_IsFontLoadComplete.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F298.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F310.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F388.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F3B8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F3E8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F448.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F478.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F4D8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F588.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F604.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F6F0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F7C0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F7F8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F83C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F880.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F8C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F908.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018F9B8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FA60.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FAD0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FB20.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FB78.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FCCC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FD20.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FD40.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FE5C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8018FF60.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190204.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190240.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190294.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801902D8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190544.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190668.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019067C.s")
+/**
+ * @file audio_load.c
+ *
+ * Implements the transfer of audio data from the cartridge to the audio heap.
+ *
+ * The audio data in ROM consists of:
+ * 1) Sequences stored as a midi-based script called the music-macro language (.mus files)
+ * 2) SoundFonts stored as various sound-font structs bundled togther in a custom way
+ * that is extracted through relocs (See SoundFontData, generic .o files)
+ * 3) Samples consisting of raw soundbytes stored using a compressed ADPCM algorithm (.aifc files)
+ */
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190754.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019075C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019077C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190B08.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190B38.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190B44.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190B50.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190BB0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190F50.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80190F64.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191134.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801911C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801911CC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191240.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801913C8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019144C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191460.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191568.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191598.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019161C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191740.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191864.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191870.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801919AC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191B40.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191BD0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191C40.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191C54.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80191D94.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_8019218C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192340.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192388.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_801924BC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192514.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192990.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192AD0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192AD8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192AE0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192AE8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192B54.s")
+#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_load/func_80192BAC.s")
+/**
+ * SoundFont Notes:
+ *
+ */
+// opaque type for unpatched sound font data (should maybe get rid of this?)
+typedef void SoundFontData;
+
+typedef struct {
+ /* 0x00 */ s32 sampleBankId1;
+ /* 0x04 */ s32 sampleBankId2;
+ /* 0x08 */ uintptr_t baseAddr1;
+ /* 0x0C */ uintptr_t baseAddr2;
+ /* 0x10 */ u32 medium1;
+ /* 0x14 */ u32 medium2;
+} AudioRelocInfo; // size = 0x18
+
+void AudioLoad_DiscardFont(s32 fontId);
+s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2);
+u8* AudioLoad_SyncLoadSeq(s32 seqId);
+u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad);
+SoundFontData* AudioLoad_SyncLoadFont(u32 fontId);
+void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate);
+u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id);
+void* AudioLoad_SearchCaches(s32 tableType, s32 id);
+AudioTable* AudioLoad_GetLoadTable(s32 tableType);
+void AudioLoad_SyncDma(uintptr_t devAddr, u8* addr, size_t size, s32 medium);
+void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* addr, size_t size, s32 unkMediumParam);
+s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, uintptr_t devAddr, void* ramAddr, size_t size,
+ OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType);
+void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, OSMesgQueue* retQueue);
+SoundFontSample* AudioLoad_GetFontSample(s32 fontId, s32 instId);
+void AudioLoad_ProcessSlowLoads(s32 resetStatus);
+void AudioLoad_DmaSlowCopy(AudioSlowLoad* slowLoad, size_t size);
+void AudioLoad_DmaSlowCopyUnkMedium(intptr_t devAddr, intptr_t ramAddr, size_t size, s32 arg3);
+AudioAsyncLoad* AudioLoad_StartAsyncLoadUnkMedium(s32 unkMediumParam, uintptr_t devAddr, void* ramAddr, size_t size,
+ s32 medium, s32 nChunks, OSMesgQueue* retQueue, s32 retMsg);
+AudioAsyncLoad* AudioLoad_StartAsyncLoad(uintptr_t devAddr, void* ramAddr, size_t size, s32 medium, s32 nChunks,
+ OSMesgQueue* retQueue, s32 retMsg);
+void AudioLoad_ProcessAsyncLoads(s32 resetStatus);
+void AudioLoad_ProcessAsyncLoadUnkMedium(AudioAsyncLoad* asyncLoad, s32 resetStatus);
+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(SoundFontSound* sound, SoundFontData* fontData, AudioRelocInfo* relocInfo);
+void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData, AudioRelocInfo* relocInfo, s32 async);
+s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus);
+
+#define MK_ASYNC_MSG(retData, tableType, id, loadStatus) \
+ (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (loadStatus))
+
+#define ASYNC_TBLTYPE(v) ((u8)(v >> 16))
+#define ASYNC_ID(v) ((u8)(v >> 8))
+#define ASYNC_STATUS(v) ((u8)(v >> 0))
+
+typedef enum {
+ /* 0 */ LOAD_STATUS_WAITING,
+ /* 1 */ LOAD_STATUS_START,
+ /* 2 */ LOAD_STATUS_LOADING,
+ /* 3 */ LOAD_STATUS_DONE
+} SlowLoadStatus;
+
+#define OS_MESG_PRI_NORMAL 0
+#define OS_MESG_PRI_HIGH 1
+
+typedef struct {
+ u16 numInstruments;
+ u16 numDrums;
+ u16 numSfx;
+} UnloadedFonts;
+
+OSMesgQueue sScriptLoadQueue;
+OSMesg sScriptLoadMesgBuf[0x10];
+s8* sScriptLoadDonePointers[0x10];
+s32 sAudioLoadPad1[2]; // file padding
+s32 D_801FD1E0;
+
+DmaHandler sDmaHandler = osEPiStartDma;
+void* sUnusedHandler = NULL;
+s32 gAudioContextInitalized = false;
+
+void AudioLoad_DecreaseSampleDmaTtls(void) {
+ u32 i;
+
+ for (i = 0; i < gAudioContext.sampleDmaListSize1; i++) {
+ SampleDma* dma = &gAudioContext.sampleDmas[i];
+
+ if (dma->ttl != 0) {
+ dma->ttl--;
+ if (dma->ttl == 0) {
+ dma->reuseIndex = gAudioContext.sampleDmaReuseQueue1WrPos;
+ gAudioContext.sampleDmaReuseQueue1[gAudioContext.sampleDmaReuseQueue1WrPos] = i;
+ gAudioContext.sampleDmaReuseQueue1WrPos++;
+ }
+ }
+ }
+
+ for (i = gAudioContext.sampleDmaListSize1; i < gAudioContext.sampleDmaCount; i++) {
+ SampleDma* dma = &gAudioContext.sampleDmas[i];
+
+ if (dma->ttl != 0) {
+ dma->ttl--;
+ if (dma->ttl == 0) {
+ dma->reuseIndex = gAudioContext.sampleDmaReuseQueue2WrPos;
+ gAudioContext.sampleDmaReuseQueue2[gAudioContext.sampleDmaReuseQueue2WrPos] = i;
+ gAudioContext.sampleDmaReuseQueue2WrPos++;
+ }
+ }
+ }
+
+ gAudioContext.unused2648 = 0;
+}
+
+void* AudioLoad_DmaSampleData(uintptr_t devAddr, size_t size, s32 arg2, u8* dmaIndexRef, s32 medium) {
+ s32 pad1;
+ SampleDma* dma;
+ s32 hasDma = false;
+ uintptr_t dmaDevAddr;
+ u32 pad2;
+ u32 dmaIndex;
+ u32 transfer;
+ s32 bufferPos;
+ u32 i;
+
+ if (arg2 != 0 || *dmaIndexRef >= gAudioContext.sampleDmaListSize1) {
+ for (i = gAudioContext.sampleDmaListSize1; i < gAudioContext.sampleDmaCount; i++) {
+ dma = &gAudioContext.sampleDmas[i];
+ bufferPos = devAddr - dma->devAddr;
+ if (0 <= bufferPos && ((u32)bufferPos <= dma->size - size)) {
+ // We already have a DMA request for this memory range.
+ if (dma->ttl == 0 &&
+ gAudioContext.sampleDmaReuseQueue2RdPos != gAudioContext.sampleDmaReuseQueue2WrPos) {
+ // Move the DMA out of the reuse queue, by swapping it with the
+ // read pos, and then incrementing the read pos.
+ if (dma->reuseIndex != gAudioContext.sampleDmaReuseQueue2RdPos) {
+ gAudioContext.sampleDmaReuseQueue2[dma->reuseIndex] =
+ gAudioContext.sampleDmaReuseQueue2[gAudioContext.sampleDmaReuseQueue2RdPos];
+ gAudioContext
+ .sampleDmas[gAudioContext.sampleDmaReuseQueue2[gAudioContext.sampleDmaReuseQueue2RdPos]]
+ .reuseIndex = dma->reuseIndex;
+ }
+ gAudioContext.sampleDmaReuseQueue2RdPos++;
+ }
+ dma->ttl = 32;
+ *dmaIndexRef = (u8)i;
+ return dma->ramAddr + (devAddr - dma->devAddr);
+ }
+ }
+
+ if (arg2 == 0) {
+ goto search_short_lived;
+ }
+
+ if (gAudioContext.sampleDmaReuseQueue2RdPos != gAudioContext.sampleDmaReuseQueue2WrPos && arg2 != 0) {
+ // Allocate a DMA from reuse queue 2, unless full.
+ dmaIndex = gAudioContext.sampleDmaReuseQueue2[gAudioContext.sampleDmaReuseQueue2RdPos];
+ gAudioContext.sampleDmaReuseQueue2RdPos++;
+ dma = gAudioContext.sampleDmas + dmaIndex;
+ hasDma = true;
+ }
+ } else {
+ search_short_lived:
+ dma = gAudioContext.sampleDmas + *dmaIndexRef;
+ i = 0;
+ again:
+ bufferPos = devAddr - dma->devAddr;
+ if (0 <= bufferPos && (u32)bufferPos <= dma->size - size) {
+ // We already have DMA for this memory range.
+ if (dma->ttl == 0) {
+ // Move the DMA out of the reuse queue, by swapping it with the
+ // read pos, and then incrementing the read pos.
+ if (dma->reuseIndex != gAudioContext.sampleDmaReuseQueue1RdPos) {
+ gAudioContext.sampleDmaReuseQueue1[dma->reuseIndex] =
+ gAudioContext.sampleDmaReuseQueue1[gAudioContext.sampleDmaReuseQueue1RdPos];
+ gAudioContext
+ .sampleDmas[gAudioContext.sampleDmaReuseQueue1[gAudioContext.sampleDmaReuseQueue1RdPos]]
+ .reuseIndex = dma->reuseIndex;
+ }
+ gAudioContext.sampleDmaReuseQueue1RdPos++;
+ }
+ dma->ttl = 2;
+ return dma->ramAddr + (devAddr - dma->devAddr);
+ }
+ dma = gAudioContext.sampleDmas + i++;
+ if (i <= gAudioContext.sampleDmaListSize1) {
+ goto again;
+ }
+ }
+
+ if (!hasDma) {
+ if (gAudioContext.sampleDmaReuseQueue1RdPos == gAudioContext.sampleDmaReuseQueue1WrPos) {
+ return NULL;
+ }
+ // Allocate a DMA from reuse queue 1.
+ dmaIndex = gAudioContext.sampleDmaReuseQueue1[gAudioContext.sampleDmaReuseQueue1RdPos++];
+ dma = gAudioContext.sampleDmas + dmaIndex;
+ hasDma = true;
+ }
+
+ transfer = dma->size;
+ dmaDevAddr = devAddr & ~0xF;
+ dma->ttl = 3;
+ dma->devAddr = dmaDevAddr;
+ dma->sizeUnused = transfer;
+ AudioLoad_Dma(&gAudioContext.currAudioFrameDmaIoMesgBuf[gAudioContext.curAudioFrameDmaCount++], OS_MESG_PRI_NORMAL,
+ OS_READ, dmaDevAddr, dma->ramAddr, transfer, &gAudioContext.currAudioFrameDmaQueue, medium,
+ "SUPERDMA");
+ *dmaIndexRef = dmaIndex;
+ return (devAddr - dmaDevAddr) + dma->ramAddr;
+}
+
+// This string does not appear to belong in context to any function between the previous string and the next string
+const char D_801E030C[] = "TYPE %d:ID %d is not External Map.\n";
+
+void AudioLoad_InitSampleDmaBuffers(s32 numNotes) {
+ SampleDma* dma;
+ s32 i;
+ s32 t2;
+ s32 j;
+
+ gAudioContext.sampleDmaBufSize = gAudioContext.sampleDmaBufSize1;
+ gAudioContext.sampleDmas =
+ AudioHeap_Alloc(&gAudioContext.miscPool,
+ 4 * gAudioContext.numNotes * sizeof(SampleDma) * gAudioContext.audioBufferParameters.specUnk4);
+ t2 = 3 * gAudioContext.numNotes * gAudioContext.audioBufferParameters.specUnk4;
+
+ // First 3/4 sampleDmas
+ for (i = 0; i < t2; i++) {
+ dma = &gAudioContext.sampleDmas[gAudioContext.sampleDmaCount];
+ dma->ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, gAudioContext.sampleDmaBufSize);
+ if (dma->ramAddr == NULL) {
+ break;
+ } else {
+ AudioHeap_WritebackDCache(dma->ramAddr, gAudioContext.sampleDmaBufSize);
+ dma->size = gAudioContext.sampleDmaBufSize;
+ dma->devAddr = 0;
+ dma->sizeUnused = 0;
+ dma->unused = 0;
+ dma->ttl = 0;
+ gAudioContext.sampleDmaCount++;
+ }
+ }
+
+ for (i = 0; (u32)i < gAudioContext.sampleDmaCount; i++) {
+ gAudioContext.sampleDmaReuseQueue1[i] = i;
+ gAudioContext.sampleDmas[i].reuseIndex = i;
+ }
+
+ for (i = gAudioContext.sampleDmaCount; i < 0x100; i++) {
+ gAudioContext.sampleDmaReuseQueue1[i] = 0;
+ }
+
+ gAudioContext.sampleDmaReuseQueue1RdPos = 0;
+ gAudioContext.sampleDmaReuseQueue1WrPos = gAudioContext.sampleDmaCount;
+ gAudioContext.sampleDmaListSize1 = gAudioContext.sampleDmaCount;
+ gAudioContext.sampleDmaBufSize = gAudioContext.sampleDmaBufSize2;
+
+ for (j = 0; j < gAudioContext.numNotes; j++) {
+ dma = &gAudioContext.sampleDmas[gAudioContext.sampleDmaCount];
+ dma->ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, gAudioContext.sampleDmaBufSize);
+ if (dma->ramAddr == NULL) {
+ break;
+ } else {
+ AudioHeap_WritebackDCache(dma->ramAddr, gAudioContext.sampleDmaBufSize);
+ dma->size = gAudioContext.sampleDmaBufSize;
+ dma->devAddr = 0U;
+ dma->sizeUnused = 0;
+ dma->unused = 0;
+ dma->ttl = 0;
+ gAudioContext.sampleDmaCount++;
+ }
+ }
+
+ for (i = gAudioContext.sampleDmaListSize1; (u32)i < gAudioContext.sampleDmaCount; i++) {
+ gAudioContext.sampleDmaReuseQueue2[i - gAudioContext.sampleDmaListSize1] = i;
+ gAudioContext.sampleDmas[i].reuseIndex = i - gAudioContext.sampleDmaListSize1;
+ }
+
+ for (i = gAudioContext.sampleDmaCount; i < 0x100; i++) {
+ gAudioContext.sampleDmaReuseQueue2[i] = gAudioContext.sampleDmaListSize1;
+ }
+
+ gAudioContext.sampleDmaReuseQueue2RdPos = 0;
+ gAudioContext.sampleDmaReuseQueue2WrPos = gAudioContext.sampleDmaCount - gAudioContext.sampleDmaListSize1;
+}
+
+s32 AudioLoad_IsFontLoadComplete(s32 fontId) {
+ if (fontId == 0xFF) {
+ return true;
+ } else if (gAudioContext.fontLoadStatus[fontId] >= LOAD_STATUS_2) {
+ return true;
+ } else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= LOAD_STATUS_2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+s32 AudioLoad_IsSeqLoadComplete(s32 seqId) {
+ if (seqId == 0xFF) {
+ return true;
+ } else if (gAudioContext.seqLoadStatus[seqId] >= LOAD_STATUS_2) {
+ return true;
+ } else if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] >= LOAD_STATUS_2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+s32 AudioLoad_IsSampleLoadComplete(s32 sampleBankId) {
+ if (sampleBankId == 0xFF) {
+ return true;
+ } else if (gAudioContext.sampleFontLoadStatus[sampleBankId] >= LOAD_STATUS_2) {
+ return true;
+ } else if (gAudioContext.sampleFontLoadStatus[AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId)] >=
+ LOAD_STATUS_2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void AudioLoad_SetFontLoadStatus(s32 fontId, s32 loadStatus) {
+ if ((fontId != 0xFF) && (gAudioContext.fontLoadStatus[fontId] != LOAD_STATUS_5)) {
+ gAudioContext.fontLoadStatus[fontId] = loadStatus;
+ }
+}
+
+void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 loadStatus) {
+ if ((seqId != 0xFF) && (gAudioContext.seqLoadStatus[seqId] != LOAD_STATUS_5)) {
+ gAudioContext.seqLoadStatus[seqId] = loadStatus;
+ }
+}
+
+void AudioLoad_SetSampleFontLoadStatusAndApplyCaches(s32 sampleBankId, s32 loadStatus) {
+ if (sampleBankId != 0xFF) {
+ if (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_5) {
+ gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus;
+ }
+
+ if ((gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_5) ||
+ (gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_2)) {
+ AudioHeap_ApplySampleBankCache(sampleBankId);
+ }
+ }
+}
+
+void AudioLoad_SetSampleFontLoadStatus(s32 sampleBankId, s32 loadStatus) {
+ if ((sampleBankId != 0xFF) && (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_5)) {
+ gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus;
+ }
+}
+
+void AudioLoad_InitTable(AudioTable* table, uintptr_t romAddr, u16 unkMediumParam) {
+ s32 i;
+
+ table->unkMediumParam = unkMediumParam;
+ table->romAddr = romAddr;
+
+ for (i = 0; i < table->numEntries; i++) {
+ if ((table->entries[i].size != 0) && (table->entries[i].medium == MEDIUM_CART)) {
+ table->entries[i].romAddr += romAddr;
+ }
+ }
+}
+
+SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) {
+ s32 pad[2];
+ s32 index;
+ SoundFontData* fontData;
+ s32 numFonts;
+ s32 fontId;
+ s32 i;
+
+ if (seqId >= gAudioContext.numSequences) {
+ return NULL;
+ }
+
+ fontId = 0xFF;
+ index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
+ numFonts = gAudioContext.sequenceFontTable[index++];
+
+ while (numFonts > 0) {
+ fontId = gAudioContext.sequenceFontTable[index++];
+ fontData = AudioLoad_SyncLoadFont(fontId);
+ numFonts--;
+ }
+
+ *outDefaultFontId = fontId;
+ return fontData;
+}
+
+void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1, s32 arg2, OSMesgQueue* arg3) {
+ s32 pad;
+ u32 defaultFontId;
+
+ if (seqId < gAudioContext.numSequences) {
+ if (arg1 & 2) {
+ AudioLoad_SyncLoadSeqFonts(seqId, &defaultFontId);
+ }
+ if (arg1 & 1) {
+ AudioLoad_SyncLoadSeq(seqId);
+ }
+ if (arg2 != 0) {
+ osSendMesg(arg3, arg2 << 0x18, OS_MESG_NOBLOCK);
+ }
+ }
+}
+
+s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
+ void* sampleAddr;
+
+ if (sample->unk_bit25 == true) {
+ if (sample->medium != MEDIUM_RAM) {
+ sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
+ CACHE_PERSISTENT);
+ if (sampleAddr == NULL) {
+ return -1;
+ }
+
+ if (sample->medium == MEDIUM_UNK) {
+ AudioLoad_SyncDmaUnkMedium(sample->sampleAddr, sampleAddr, sample->size,
+ gAudioContext.sampleBankTable->unkMediumParam);
+ } else {
+ AudioLoad_SyncDma(sample->sampleAddr, sampleAddr, sample->size, sample->medium);
+ }
+ sample->medium = MEDIUM_RAM;
+ sample->sampleAddr = sampleAddr;
+ }
+ }
+}
+
+s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId) {
+ if (instId < 0x7F) {
+ Instrument* instrument = AudioPlayback_GetInstrumentInner(fontId, instId);
+
+ if (instrument == NULL) {
+ return -1;
+ }
+ if (instrument->normalRangeLo != 0) {
+ AudioLoad_SyncLoadSample(instrument->lowNotesSound.sample, fontId);
+ }
+ AudioLoad_SyncLoadSample(instrument->normalNotesSound.sample, fontId);
+ if (instrument->normalRangeHi != 0x7F) {
+ return AudioLoad_SyncLoadSample(instrument->highNotesSound.sample, fontId);
+ }
+ } else if (instId == 0x7F) {
+ Drum* drum = AudioPlayback_GetDrum(fontId, drumId);
+
+ if (drum == NULL) {
+ return -1;
+ }
+ AudioLoad_SyncLoadSample(drum->sound.sample, fontId);
+ return 0;
+ }
+}
+
+void AudioLoad_AsyncLoad(s32 tableType, s32 id, s32 nChunks, s32 retData, OSMesgQueue* retQueue) {
+ if (AudioLoad_AsyncLoadInner(tableType, id, nChunks, retData, retQueue) == NULL) {
+ osSendMesg(retQueue, 0xFFFFFFFF, OS_MESG_NOBLOCK);
+ }
+}
+
+void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue) {
+ AudioLoad_AsyncLoad(SEQUENCE_TABLE, seqId, 0, retData, retQueue);
+}
+
+void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue) {
+ AudioLoad_AsyncLoad(SAMPLE_TABLE, sampleBankId, 0, retData, retQueue);
+}
+
+void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* retQueue) {
+ AudioLoad_AsyncLoad(FONT_TABLE, fontId, 0, retData, retQueue);
+}
+
+u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
+ s32 index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
+
+ *outNumFonts = gAudioContext.sequenceFontTable[index++];
+ if (*outNumFonts == 0) {
+ return NULL;
+ }
+ return &gAudioContext.sequenceFontTable[index];
+}
+
+void AudioLoad_DiscardSeqFonts(s32 seqId) {
+ s32 fontId;
+ s32 index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
+ s32 numFonts = gAudioContext.sequenceFontTable[index++];
+
+ while (numFonts > 0) {
+ numFonts--;
+ fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.sequenceFontTable[index++]);
+ if (AudioHeap_SearchPermanentCache(FONT_TABLE, fontId) == NULL) {
+ AudioLoad_DiscardFont(fontId);
+ AudioLoad_SetFontLoadStatus(fontId, LOAD_STATUS_0);
+ }
+ }
+}
+
+void AudioLoad_DiscardFont(s32 fontId) {
+ u32 i;
+ AudioCache* pool = &gAudioContext.fontCache;
+ AudioPersistentCache* persistent;
+
+ if (fontId == pool->temporary.entries[0].id) {
+ pool->temporary.entries[0].id = -1;
+ } else if (fontId == pool->temporary.entries[1].id) {
+ pool->temporary.entries[1].id = -1;
+ }
+
+ persistent = &pool->persistent;
+ for (i = 0; i < persistent->numEntries; i++) {
+ if (fontId == persistent->entries[i].id) {
+ persistent->entries[i].id = -1;
+ }
+ }
+
+ AudioHeap_DiscardFont(fontId);
+}
+
+void func_8018FA60(u32 tableType, u32 id, s32 type, s32 data) {
+ AudioTable* table = AudioLoad_GetLoadTable(tableType);
+
+ if (table->entries[id].medium == MEDIUM_RAM_UNLOADED) {
+ switch (type) {
+ case 0:
+ table->entries[id].romAddr = data;
+ break;
+ case 1:
+ table->entries[id].size = data;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+s32 AudioLoad_SyncInitSeqPlayer(s32 playerIdx, s32 seqId, s32 arg2) {
+ if (gAudioContext.resetTimer != 0) {
+ return 0;
+ }
+
+ gAudioContext.seqPlayers[playerIdx].skipTicks = 0;
+ AudioLoad_SyncInitSeqPlayerInternal(playerIdx, 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.
+}
+
+s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIdx, s32 seqId, s32 skipTicks) {
+ if (gAudioContext.resetTimer != 0) {
+ return 0;
+ }
+
+ gAudioContext.seqPlayers[playerIdx].skipTicks = skipTicks;
+ AudioLoad_SyncInitSeqPlayerInternal(playerIdx, seqId, 0);
+ // Missing return, see above.
+}
+
+s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) {
+ SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIdx];
+ u8* seqData;
+ s32 index;
+ s32 numFonts;
+ s32 fontId;
+
+ if (seqId >= gAudioContext.numSequences) {
+ return 0;
+ }
+
+ AudioSeq_SequencePlayerDisable(seqPlayer);
+
+ if (1) {}
+ fontId = 0xFF;
+ index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
+ numFonts = gAudioContext.sequenceFontTable[index++];
+
+ while (numFonts > 0) {
+ fontId = gAudioContext.sequenceFontTable[index++];
+ AudioLoad_SyncLoadFont(fontId);
+ numFonts--;
+ }
+
+ seqData = AudioLoad_SyncLoadSeq(seqId);
+ if (seqData == NULL) {
+ return 0;
+ }
+
+ AudioSeq_ResetSequencePlayer(seqPlayer);
+ seqPlayer->seqId = seqId;
+
+ if (fontId != 0xFF) {
+ seqPlayer->defaultFont = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId);
+ } else {
+ seqPlayer->defaultFont = 0xFF;
+ }
+
+ seqPlayer->seqData = seqData;
+ seqPlayer->enabled = true;
+ seqPlayer->scriptState.pc = seqData;
+ seqPlayer->scriptState.depth = 0;
+ seqPlayer->delay = 0;
+ seqPlayer->finished = false;
+ seqPlayer->playerIdx = playerIdx;
+ //! @bug missing return (but the return value is not used so it's not UB)
+}
+
+u8* AudioLoad_SyncLoadSeq(s32 seqId) {
+ s32 pad;
+ s32 didAllocate;
+
+ if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] == LOAD_STATUS_1) {
+ return NULL;
+ }
+
+ return AudioLoad_SyncLoad(SEQUENCE_TABLE, seqId, &didAllocate);
+}
+
+u32 AudioLoad_GetSampleBank(u32 sampleBankId, u32* outMedium) {
+ return AudioLoad_TrySyncLoadSampleBank(sampleBankId, outMedium, true);
+}
+
+u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad) {
+ void* addr;
+ AudioTable* sampleBankTable;
+ u32 realTableId = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId);
+ s8 cachePolicy;
+
+ sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE);
+
+ addr = AudioLoad_SearchCaches(SAMPLE_TABLE, realTableId);
+ if (addr != NULL) {
+ if (gAudioContext.sampleFontLoadStatus[realTableId] != LOAD_STATUS_1) {
+ AudioLoad_SetSampleFontLoadStatus(realTableId, LOAD_STATUS_2);
+ }
+
+ *outMedium = MEDIUM_RAM;
+ return addr;
+ }
+
+ cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy;
+
+ if ((cachePolicy == CACHE_LOAD_EITHER_NOSYNC) || (noLoad == true)) {
+ *outMedium = sampleBankTable->entries[sampleBankId].medium;
+ return sampleBankTable->entries[realTableId].romAddr;
+ }
+
+ addr = AudioLoad_SyncLoad(SAMPLE_TABLE, sampleBankId, &noLoad);
+ if (addr != NULL) {
+ *outMedium = MEDIUM_RAM;
+ return addr;
+ }
+
+ *outMedium = sampleBankTable->entries[sampleBankId].medium;
+ return sampleBankTable->entries[realTableId].romAddr;
+}
+
+SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
+ SoundFontData* fontData;
+ s32 sampleBankId1;
+ s32 sampleBankId2;
+ s32 didAllocate;
+ AudioRelocInfo relocInfo;
+ s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId);
+
+ if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_1) {
+ return NULL;
+ }
+
+ sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1;
+ sampleBankId2 = gAudioContext.soundFonts[realFontId].sampleBankId2;
+
+ relocInfo.sampleBankId1 = sampleBankId1;
+ relocInfo.sampleBankId2 = sampleBankId2;
+ if (relocInfo.sampleBankId1 != 0xFF) {
+ relocInfo.baseAddr1 = AudioLoad_TrySyncLoadSampleBank(relocInfo.sampleBankId1, &relocInfo.medium1, false);
+ } else {
+ relocInfo.baseAddr1 = 0;
+ }
+
+ if (sampleBankId2 != 0xFF) {
+ relocInfo.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &relocInfo.medium2, false);
+ } else {
+ relocInfo.baseAddr2 = 0;
+ }
+
+ fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate);
+ if (fontData == NULL) {
+ return NULL;
+ }
+ if (didAllocate == true) {
+ AudioLoad_RelocateFontAndPreloadSamples(realFontId, fontData, &relocInfo, false);
+ }
+
+ return fontData;
+}
+
+void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) {
+ size_t size;
+ AudioTable* table;
+ s32 medium2;
+ u32 medium;
+ s32 loadStatus;
+ uintptr_t romAddr;
+ s32 cachePolicy;
+ void* ramAddr;
+ u32 realId;
+ s32 mediumUnk = MEDIUM_UNK;
+
+ realId = AudioLoad_GetRealTableIndex(tableType, id);
+ ramAddr = AudioLoad_SearchCaches(tableType, realId);
+ if (ramAddr != NULL) {
+ *didAllocate = false;
+ loadStatus = LOAD_STATUS_2;
+ } 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;
+ switch (cachePolicy) {
+ case CACHE_LOAD_PERMANENT:
+ ramAddr = AudioHeap_AllocPermanent(tableType, realId, size);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+
+ case CACHE_LOAD_PERSISTENT:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+ case CACHE_LOAD_TEMPORARY:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+
+ case CACHE_LOAD_EITHER:
+ case CACHE_LOAD_EITHER_NOSYNC:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+ }
+
+ *didAllocate = true;
+
+ medium2 = medium;
+ if (medium == MEDIUM_RAM_UNLOADED) {
+ if (romAddr == 0) {
+ return NULL;
+ }
+
+ if (tableType == FONT_TABLE) {
+ SoundFont* soundFont = &gAudioContext.soundFonts[realId];
+
+ soundFont->numInstruments = ((UnloadedFonts*)romAddr)->numInstruments;
+ soundFont->numDrums = ((UnloadedFonts*)romAddr)->numDrums;
+ soundFont->numSfx = ((UnloadedFonts*)romAddr)->numSfx;
+ romAddr += 0x10;
+ size -= 0x10;
+ }
+
+ bcopy(romAddr, ramAddr, size);
+ } else if (medium2 == mediumUnk) {
+ AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->unkMediumParam);
+ } else {
+ AudioLoad_SyncDma(romAddr, ramAddr, size, medium);
+ }
+
+ loadStatus = (cachePolicy == CACHE_LOAD_PERMANENT) ? LOAD_STATUS_5 : LOAD_STATUS_2;
+ }
+
+ switch (tableType) {
+ case SEQUENCE_TABLE:
+ AudioLoad_SetSeqLoadStatus(realId, loadStatus);
+ break;
+ case FONT_TABLE:
+ AudioLoad_SetFontLoadStatus(realId, loadStatus);
+ break;
+ case SAMPLE_TABLE:
+ AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, loadStatus);
+ break;
+ default:
+ break;
+ }
+
+ return ramAddr;
+}
+
+u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) {
+ AudioTable* table = AudioLoad_GetLoadTable(tableType);
+
+ if (table->entries[id].size == 0) {
+ id = table->entries[id].romAddr;
+ }
+
+ return id;
+}
+
+void* AudioLoad_SearchCaches(s32 tableType, s32 id) {
+ void* addr;
+
+ addr = AudioHeap_SearchPermanentCache(tableType, id);
+ if (addr != NULL) {
+ return addr;
+ }
+
+ addr = AudioHeap_SearchCaches(tableType, CACHE_EITHER, id);
+ if (addr != NULL) {
+ return addr;
+ }
+
+ return NULL;
+}
+
+AudioTable* AudioLoad_GetLoadTable(s32 tableType) {
+ AudioTable* table;
+
+ switch (tableType) {
+ case SEQUENCE_TABLE:
+ table = gAudioContext.sequenceTable;
+ break;
+ case FONT_TABLE:
+ table = gAudioContext.soundFontTable;
+ break;
+ default:
+ table = NULL;
+ break;
+ case SAMPLE_TABLE:
+ table = gAudioContext.sampleBankTable;
+ break;
+ }
+ return table;
+}
+
+/**
+ *
+ * SoundFontData* mem -> the address of the soundFont as stored in memory
+ */
+void AudioLoad_RelocateFont(s32 fontId, SoundFontData* fontData, AudioRelocInfo* relocInfo) {
+ uintptr_t reloc;
+ uintptr_t reloc2;
+ Instrument* inst;
+ Drum* drum;
+ SoundFontSound* sfx;
+ s32 i;
+ s32 numDrums = gAudioContext.soundFonts[fontId].numDrums;
+ s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
+ s32 numSfx = gAudioContext.soundFonts[fontId].numSfx;
+ void** ptrs = (void**)fontData;
+
+#define BASE_OFFSET(x) (void*)((uintptr_t)(x) + (uintptr_t)(fontData))
+
+ // relocate drums
+ reloc2 = ptrs[0];
+ if (1) {}
+ if ((reloc2 != 0) && (numDrums != 0)) {
+ ptrs[0] = BASE_OFFSET(reloc2);
+ for (i = 0; i < numDrums; i++) {
+ reloc = ((Drum**)ptrs[0])[i];
+ if (reloc != 0) {
+ reloc = BASE_OFFSET(reloc);
+ ((Drum**)ptrs[0])[i] = drum = reloc;
+ if (!drum->loaded) {
+ AudioLoad_RelocateSample(&drum->sound, fontData, relocInfo);
+ reloc = drum->envelope;
+ drum->envelope = BASE_OFFSET(reloc);
+ drum->loaded = true;
+ }
+ }
+ }
+ }
+
+ // relocate sfxs
+ reloc2 = ptrs[1];
+ if (1) {}
+ if ((reloc2 != 0) && (numSfx != 0)) {
+ ptrs[1] = BASE_OFFSET(reloc2);
+ for (i = 0; i < numSfx; i++) {
+ reloc = (SoundFontSound*)ptrs[1] + i;
+ if (reloc != 0) {
+ sfx = reloc;
+ if (sfx->sample != NULL) {
+ AudioLoad_RelocateSample(sfx, fontData, relocInfo);
+ }
+ }
+ }
+ }
+
+ if (numInstruments > 0x7E) {
+ numInstruments = 0x7E;
+ }
+
+ // relocate instruments
+ for (i = 2; i <= 2 + numInstruments - 1; i++) {
+ if (ptrs[i] != NULL) {
+ ptrs[i] = BASE_OFFSET(ptrs[i]);
+ inst = ptrs[i];
+ if (!inst->loaded) {
+ if (inst->normalRangeLo != 0) {
+ AudioLoad_RelocateSample(&inst->lowNotesSound, fontData, relocInfo);
+ }
+ AudioLoad_RelocateSample(&inst->normalNotesSound, fontData, relocInfo);
+ if (inst->normalRangeHi != 0x7F) {
+ AudioLoad_RelocateSample(&inst->highNotesSound, fontData, relocInfo);
+ }
+
+ reloc = inst->envelope;
+ inst->envelope = BASE_OFFSET(reloc);
+ inst->loaded = true;
+ }
+ }
+ }
+
+#undef BASE_OFFSET
+
+ gAudioContext.soundFonts[fontId].drums = ptrs[0];
+ gAudioContext.soundFonts[fontId].soundEffects = ptrs[1];
+ gAudioContext.soundFonts[fontId].instruments = (Instrument**)(&ptrs[2]);
+}
+
+void AudioLoad_SyncDma(uintptr_t devAddr, u8* ramAddr, size_t size, s32 medium) {
+ OSMesgQueue* msgQueue = &gAudioContext.syncDmaQueue;
+ OSIoMesg* ioMesg = &gAudioContext.syncDmaIoMesg;
+ size = ALIGN16(size);
+
+ Audio_InvalDCache(ramAddr, size);
+
+ while (true) {
+ if (size < 0x400) {
+ break;
+ }
+ AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, ramAddr, 0x400, msgQueue, medium, "FastCopy");
+ osRecvMesg(msgQueue, NULL, OS_MESG_BLOCK);
+ size -= 0x400;
+ devAddr += 0x400;
+ ramAddr += 0x400;
+ }
+
+ if (size != 0) {
+ AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, ramAddr, size, msgQueue, medium, "FastCopy");
+ osRecvMesg(msgQueue, NULL, OS_MESG_BLOCK);
+ }
+}
+
+void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, size_t size, s32 unkMediumParam) {
+}
+
+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 (gAudioContext.resetTimer > 16) {
+ return -1;
+ }
+
+ switch (medium) {
+ case MEDIUM_CART:
+ handle = gAudioContext.cartHandle;
+ break;
+
+ case MEDIUM_DISK_DRIVE:
+ // driveHandle is uninitialized and corresponds to stubbed-out disk drive support.
+ // SM64 Shindou called osDriveRomInit here.
+ handle = gAudioContext.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);
+ return 0;
+}
+
+void AudioLoad_Unused1(void) {
+}
+
+void AudioLoad_SyncLoadSimple(u32 tableType, u32 fontId) {
+ s32 didAllocate;
+
+ AudioLoad_SyncLoad(tableType, fontId, &didAllocate);
+}
+
+void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, OSMesgQueue* retQueue) {
+ size_t size;
+ AudioTable* table;
+ void* ramAddr;
+ s32 medium;
+ s8 cachePolicy;
+ uintptr_t romAddr;
+ s32 loadStatus;
+ SoundFont* soundFont;
+ u32 realId = AudioLoad_GetRealTableIndex(tableType, id);
+ u32 pad;
+
+ switch (tableType) {
+ case SEQUENCE_TABLE:
+ if (gAudioContext.seqLoadStatus[realId] == LOAD_STATUS_1) {
+ return NULL;
+ }
+ break;
+
+ case FONT_TABLE:
+ if (gAudioContext.fontLoadStatus[realId] == LOAD_STATUS_1) {
+ return NULL;
+ }
+ break;
+
+ case SAMPLE_TABLE:
+ if (gAudioContext.sampleFontLoadStatus[realId] == LOAD_STATUS_1) {
+ return NULL;
+ }
+ break;
+ }
+
+ ramAddr = AudioLoad_SearchCaches(tableType, realId);
+ if (ramAddr != NULL) {
+ loadStatus = LOAD_STATUS_2;
+ osSendMesg(retQueue, MK_ASYNC_MSG(retData, 0, 0, LOAD_STATUS_0), OS_MESG_NOBLOCK);
+ } 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;
+ loadStatus = LOAD_STATUS_2;
+
+ switch (cachePolicy) {
+ case CACHE_LOAD_PERMANENT:
+ ramAddr = AudioHeap_AllocPermanent(tableType, realId, size);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ loadStatus = LOAD_STATUS_5;
+ break;
+
+ case CACHE_LOAD_PERSISTENT:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+
+ case CACHE_LOAD_TEMPORARY:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+
+ case CACHE_LOAD_EITHER:
+ case CACHE_LOAD_EITHER_NOSYNC:
+ ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId);
+ if (ramAddr == NULL) {
+ return ramAddr;
+ }
+ break;
+ }
+
+ if (medium == MEDIUM_RAM_UNLOADED) {
+ if (romAddr == 0) {
+ return NULL;
+ }
+
+ if (tableType == FONT_TABLE) {
+ soundFont = &gAudioContext.soundFonts[realId];
+
+ soundFont->numInstruments = ((UnloadedFonts*)romAddr)->numInstruments;
+ soundFont->numDrums = ((UnloadedFonts*)romAddr)->numDrums;
+ soundFont->numSfx = ((UnloadedFonts*)romAddr)->numSfx;
+ romAddr += 0x10;
+ size += -0x10;
+ }
+ }
+
+ if (medium == MEDIUM_UNK) {
+ AudioLoad_StartAsyncLoadUnkMedium((s16)table->unkMediumParam, romAddr, ramAddr, size, medium, nChunks,
+ retQueue, MK_ASYNC_MSG(retData, tableType, realId, loadStatus));
+ } else {
+ AudioLoad_StartAsyncLoad(romAddr, ramAddr, size, medium, nChunks, retQueue,
+ MK_ASYNC_MSG(retData, tableType, realId, loadStatus));
+ }
+
+ loadStatus = LOAD_STATUS_1;
+ }
+
+ switch (tableType) {
+ case SEQUENCE_TABLE:
+ AudioLoad_SetSeqLoadStatus(realId, loadStatus);
+ break;
+ case FONT_TABLE:
+ AudioLoad_SetFontLoadStatus(realId, loadStatus);
+ break;
+ case SAMPLE_TABLE:
+ AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, loadStatus);
+ break;
+ default:
+ break;
+ }
+
+ return ramAddr;
+}
+
+void AudioLoad_ProcessLoads(s32 resetStatus) {
+ AudioLoad_ProcessSlowLoads(resetStatus);
+ AudioLoad_ProcessSamplePreloads(resetStatus);
+ AudioLoad_ProcessAsyncLoads(resetStatus);
+}
+
+void AudioLoad_SetDmaHandler(DmaHandler callback) {
+ sDmaHandler = callback;
+}
+
+void AudioLoad_SetUnusedHandler(void* callback) {
+ sUnusedHandler = callback;
+}
+
+void AudioLoad_InitSoundFontMeta(s32 fontId) {
+ SoundFont* font = &gAudioContext.soundFonts[fontId];
+ AudioTableEntry* entry = &gAudioContext.soundFontTable->entries[fontId];
+
+ font->sampleBankId1 = (entry->shortData1 >> 8) & 0xFF;
+ font->sampleBankId2 = (entry->shortData1) & 0xFF;
+ font->numInstruments = (entry->shortData2 >> 8) & 0xFF;
+ font->numDrums = entry->shortData2 & 0xFF;
+ font->numSfx = entry->shortData3;
+}
+
+void AudioLoad_Init(void* heap, size_t heapSize) {
+ s32 pad1[9];
+ s32 numFonts;
+ s32 pad2[2];
+ u8* audioContextPtr;
+ void* addr;
+ s32 i;
+ s32 j;
+
+ D_80208E68 = NULL;
+ D_80208E70 = NULL;
+ D_80208E74 = NULL;
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.unk_29A8); i++) {
+ gAudioContext.unk_29A8[i] = NULL;
+ }
+
+ gAudioContext.resetTimer = 0;
+ gAudioContext.unk_29B8 = false;
+
+ // Set all of gAudioContext to 0
+ audioContextPtr = (u8*)&gAudioContext;
+ for (j = sizeof(gAudioContext); j >= 0; j--) {
+ *audioContextPtr++ = 0;
+ }
+
+ switch (osTvType) {
+ case OS_TV_PAL:
+ gAudioContext.unk_2960 = 20.03042f;
+ gAudioContext.refreshRate = 50;
+ break;
+
+ case OS_TV_MPAL:
+ gAudioContext.unk_2960 = 16.546f;
+ gAudioContext.refreshRate = 60;
+ break;
+
+ case OS_TV_NTSC:
+ default:
+ gAudioContext.unk_2960 = 16.713f;
+ gAudioContext.refreshRate = 60;
+ }
+
+ Audio_InitMesgQueues();
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufLengths); i++) {
+ gAudioContext.aiBufLengths[i] = 0xA0;
+ }
+
+ gAudioContext.totalTaskCount = 0;
+ gAudioContext.rspTaskIndex = 0;
+ gAudioContext.curAiBuffferIndex = 0;
+ gAudioContext.soundMode = AUDIO_MODE_STEREO;
+ gAudioContext.curTask = NULL;
+ gAudioContext.rspTask[0].task.t.dataSize = 0;
+ gAudioContext.rspTask[1].task.t.dataSize = 0;
+
+ osCreateMesgQueue(&gAudioContext.syncDmaQueue, &gAudioContext.syncDmaMesg, 1);
+ osCreateMesgQueue(&gAudioContext.currAudioFrameDmaQueue, gAudioContext.currAudioFrameDmaMesgBuf,
+ ARRAY_COUNT(gAudioContext.currAudioFrameDmaMesgBuf));
+ osCreateMesgQueue(&gAudioContext.externalLoadQueue, gAudioContext.externalLoadMesgBuf,
+ ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
+ osCreateMesgQueue(&gAudioContext.preloadSampleQueue, gAudioContext.preloadSampleMesgBuf,
+ ARRAY_COUNT(gAudioContext.preloadSampleMesgBuf));
+ gAudioContext.curAudioFrameDmaCount = 0;
+ gAudioContext.sampleDmaCount = 0;
+ gAudioContext.cartHandle = osCartRomInit();
+
+ if (heap == NULL) {
+ gAudioContext.audioHeap = gAudioHeap;
+ gAudioContext.audioHeapSize = gAudioContextInitSizes.heapSize;
+ } else {
+ void** hp = &heap;
+ gAudioContext.audioHeap = *hp;
+ gAudioContext.audioHeapSize = heapSize;
+ }
+
+ for (i = 0; i < (s32)gAudioContext.audioHeapSize / 8; i++) {
+ ((u64*)gAudioContext.audioHeap)[i] = 0;
+ }
+
+ // Main Pool Split (split entirety of audio heap into initPool and sessionPool)
+ AudioHeap_InitMainPool(gAudioContextInitSizes.mainPoolSplitSize);
+
+ // Initialize the audio interface buffer
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBuffers); i++) {
+ gAudioContext.aiBuffers[i] = AudioHeap_AllocZeroed(&gAudioContext.audioInitPool, AIBUF_LEN * sizeof(s16));
+ }
+
+ // Connect audio tables to their tables in memory
+ gAudioContext.sequenceTable = (AudioTable*)gSequenceTable;
+ gAudioContext.soundFontTable = (AudioTable*)gSoundFontTable;
+ gAudioContext.sampleBankTable = (AudioTable*)gSampleBankTable;
+ gAudioContext.sequenceFontTable = gSequenceFontTable;
+
+ gAudioContext.numSequences = gAudioContext.sequenceTable->numEntries;
+
+ gAudioContext.audioResetSpecIdToLoad = 0;
+ gAudioContext.resetStatus = 1; // Set reset to immediately initialize the audio heap
+ AudioHeap_ResetStep();
+
+ // Initialize audio tables
+ AudioLoad_InitTable(gAudioContext.sequenceTable, SEGMENT_ROM_START(Audioseq), 0);
+ AudioLoad_InitTable(gAudioContext.soundFontTable, SEGMENT_ROM_START(Audiobank), 0);
+ AudioLoad_InitTable(gAudioContext.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0);
+
+ numFonts = gAudioContext.soundFontTable->numEntries;
+ gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
+
+ for (i = 0; i < numFonts; i++) {
+ AudioLoad_InitSoundFontMeta(i);
+ }
+
+ if (addr = AudioHeap_Alloc(&gAudioContext.audioInitPool, gAudioContextInitSizes.permanentPoolSize), addr == NULL) {
+ // cast away const from D_8014A6C4
+ *((u32*)&gAudioContextInitSizes.permanentPoolSize) = 0;
+ }
+
+ AudioHeap_AllocPoolInit(&gAudioContext.permanentPool, addr, gAudioContextInitSizes.permanentPoolSize);
+ gAudioContextInitalized = true;
+ osSendMesg(gAudioContext.taskStartQueueP, (void*)gAudioContext.totalTaskCount, OS_MESG_NOBLOCK);
+}
+
+void AudioLoad_InitSlowLoads(void) {
+ gAudioContext.slowLoads[0].status = 0;
+ gAudioContext.slowLoads[1].status = 0;
+}
+
+s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) {
+ SoundFontSample* sample;
+ AudioSlowLoad* slowLoad;
+
+ sample = AudioLoad_GetFontSample(fontId, instId);
+ if (sample == NULL) {
+ *isDone = 0;
+ return -1;
+ }
+
+ if (sample->medium == MEDIUM_RAM) {
+ *isDone = 2;
+ return 0;
+ }
+
+ slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos];
+ if (slowLoad->status == LOAD_STATUS_DONE) {
+ slowLoad->status = LOAD_STATUS_WAITING;
+ }
+
+ slowLoad->sample = *sample;
+ slowLoad->isDone = isDone;
+ slowLoad->curRamAddr =
+ AudioHeap_AllocSampleCache(sample->size, fontId, sample->sampleAddr, (s32)sample->medium, CACHE_TEMPORARY);
+
+ if (slowLoad->curRamAddr == NULL) {
+ if (sample->medium == MEDIUM_UNK || sample->codec == CODEC_S16_INMEMORY) {
+ *isDone = 0;
+ return -1;
+ } else {
+ *isDone = 3;
+ return -1;
+ }
+ }
+
+ slowLoad->status = LOAD_STATUS_START;
+ slowLoad->bytesRemaining = ALIGN16(sample->size);
+ slowLoad->ramAddr = slowLoad->curRamAddr;
+ slowLoad->curDevAddr = sample->sampleAddr;
+ slowLoad->medium = sample->medium;
+ slowLoad->seqOrFontId = fontId;
+ slowLoad->instId = instId;
+
+ if (slowLoad->medium == MEDIUM_UNK) {
+ slowLoad->unkMediumParam = gAudioContext.sampleBankTable->unkMediumParam;
+ }
+
+ gAudioContext.slowLoadPos ^= 1;
+ return 0;
+}
+
+SoundFontSample* AudioLoad_GetFontSample(s32 fontId, s32 instId) {
+ SoundFontSample* sample;
+
+ if (instId < 0x80) {
+ Instrument* instrument = AudioPlayback_GetInstrumentInner(fontId, instId);
+
+ if (instrument == NULL) {
+ return NULL;
+ }
+ sample = instrument->normalNotesSound.sample;
+ } else if (instId < 0x100) {
+ Drum* drum = AudioPlayback_GetDrum(fontId, instId - 0x80);
+
+ if (drum == NULL) {
+ return NULL;
+ }
+ sample = drum->sound.sample;
+ } else {
+ SoundFontSound* sound = AudioPlayback_GetSfx(fontId, instId - 0x100);
+
+ if (sound == NULL) {
+ return NULL;
+ }
+ sample = sound->sample;
+ }
+
+ return sample;
+}
+
+void AudioLoad_Unused2(void) {
+}
+
+void AudioLoad_FinishSlowLoad(AudioSlowLoad* slowLoad) {
+ SoundFontSample* sample;
+
+ if (slowLoad->sample.sampleAddr == NULL) {
+ return;
+ }
+
+ sample = AudioLoad_GetFontSample(slowLoad->seqOrFontId, slowLoad->instId);
+ if (sample == NULL) {
+ return;
+ }
+
+ slowLoad->sample = *sample;
+ sample->sampleAddr = slowLoad->ramAddr;
+ sample->medium = MEDIUM_RAM;
+}
+
+void AudioLoad_ProcessSlowLoads(s32 resetStatus) {
+ AudioSlowLoad* slowLoad;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.slowLoads); i++) {
+ slowLoad = &gAudioContext.slowLoads[i];
+ switch (gAudioContext.slowLoads[i].status) {
+ case LOAD_STATUS_LOADING:
+ if (slowLoad->medium != MEDIUM_UNK) {
+ osRecvMesg(&slowLoad->msgqueue, NULL, OS_MESG_BLOCK);
+ }
+
+ if (resetStatus != 0) {
+ slowLoad->status = LOAD_STATUS_DONE;
+ continue;
+ }
+ case LOAD_STATUS_START:
+ slowLoad->status = LOAD_STATUS_LOADING;
+ if (slowLoad->bytesRemaining == 0) {
+ AudioLoad_FinishSlowLoad(slowLoad);
+ slowLoad->status = LOAD_STATUS_DONE;
+ *slowLoad->isDone = 1;
+ } else if ((s32)slowLoad->bytesRemaining < 0x400) {
+ if (slowLoad->medium == MEDIUM_UNK) {
+ size_t size = slowLoad->bytesRemaining;
+
+ AudioLoad_DmaSlowCopyUnkMedium(slowLoad->curDevAddr, slowLoad->curRamAddr, size,
+ slowLoad->unkMediumParam);
+ } else {
+ AudioLoad_DmaSlowCopy(slowLoad, slowLoad->bytesRemaining);
+ }
+ slowLoad->bytesRemaining = 0;
+ } else {
+ if (slowLoad->medium == MEDIUM_UNK) {
+ AudioLoad_DmaSlowCopyUnkMedium(slowLoad->curDevAddr, slowLoad->curRamAddr, 0x400,
+ slowLoad->unkMediumParam);
+ } else {
+ AudioLoad_DmaSlowCopy(slowLoad, 0x400);
+ }
+ slowLoad->bytesRemaining -= 0x400;
+ slowLoad->curRamAddr += 0x400;
+ slowLoad->curDevAddr += 0x400;
+ }
+ break;
+ }
+ }
+}
+
+void AudioLoad_DmaSlowCopy(AudioSlowLoad* slowLoad, size_t size) {
+ Audio_InvalDCache(slowLoad->curRamAddr, size);
+ osCreateMesgQueue(&slowLoad->msgqueue, &slowLoad->msg, 1);
+ AudioLoad_Dma(&slowLoad->ioMesg, OS_MESG_PRI_NORMAL, OS_READ, slowLoad->curDevAddr, slowLoad->curRamAddr, size,
+ &slowLoad->msgqueue, slowLoad->medium, "SLOWCOPY");
+}
+
+void AudioLoad_DmaSlowCopyUnkMedium(intptr_t devAddr, intptr_t ramAddr, size_t size, s32 arg3) {
+}
+
+s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) {
+ AudioSlowLoad* slowLoad;
+ AudioTable* seqTable;
+ size_t size;
+
+ if (seqId >= gAudioContext.numSequences) {
+ *isDone = 0;
+ return -1;
+ }
+
+ seqId = AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId);
+ seqTable = AudioLoad_GetLoadTable(SEQUENCE_TABLE);
+ slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos];
+ if (slowLoad->status == LOAD_STATUS_DONE) {
+ slowLoad->status = LOAD_STATUS_WAITING;
+ }
+
+ slowLoad->sample.sampleAddr = NULL;
+ slowLoad->isDone = isDone;
+ size = seqTable->entries[seqId].size;
+ size = ALIGN16(size);
+ 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) {
+ slowLoad->unkMediumParam = seqTable->unkMediumParam;
+ }
+
+ gAudioContext.slowLoadPos ^= 1;
+ return 0;
+}
+
+void AudioLoad_InitAsyncLoads(void) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.asyncLoads); i++) {
+ gAudioContext.asyncLoads[i].status = 0;
+ }
+}
+
+AudioAsyncLoad* AudioLoad_StartAsyncLoadUnkMedium(s32 unkMediumParam, uintptr_t devAddr, void* ramAddr, size_t size,
+ s32 medium, s32 nChunks, OSMesgQueue* retQueue, s32 retMsg) {
+ AudioAsyncLoad* asyncLoad;
+
+ asyncLoad = AudioLoad_StartAsyncLoad(devAddr, ramAddr, size, medium, nChunks, retQueue, retMsg);
+ if (asyncLoad == NULL) {
+ return NULL;
+ }
+
+ osSendMesg(&gAudioContext.asyncLoadUnkMediumQueue, asyncLoad, OS_MESG_NOBLOCK);
+ asyncLoad->unkMediumParam = unkMediumParam;
+ return asyncLoad;
+}
+
+AudioAsyncLoad* AudioLoad_StartAsyncLoad(uintptr_t devAddr, void* ramAddr, size_t size, s32 medium, s32 nChunks,
+ OSMesgQueue* retQueue, s32 retMsg) {
+ AudioAsyncLoad* asyncLoad;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.asyncLoads); i++) {
+ if (gAudioContext.asyncLoads[i].status == 0) {
+ asyncLoad = &gAudioContext.asyncLoads[i];
+ break;
+ }
+ }
+
+ // no more available async loads
+ if (i == ARRAY_COUNT(gAudioContext.asyncLoads)) {
+ return NULL;
+ }
+
+ asyncLoad->status = LOAD_STATUS_START;
+ asyncLoad->curDevAddr = devAddr;
+ asyncLoad->ramAddr = ramAddr;
+ asyncLoad->curRamAddr = ramAddr;
+ asyncLoad->bytesRemaining = size;
+
+ if (nChunks == 0) {
+ asyncLoad->chunkSize = 0x1000;
+ } else if (nChunks == 1) {
+ asyncLoad->chunkSize = size;
+ } else {
+ asyncLoad->chunkSize = ALIGN256((s32)size / nChunks);
+ if (asyncLoad->chunkSize < 0x100) {
+ asyncLoad->chunkSize = 0x100;
+ }
+ }
+
+ asyncLoad->retQueue = retQueue;
+ asyncLoad->delay = 3;
+ asyncLoad->medium = medium;
+ asyncLoad->retMsg = retMsg;
+ osCreateMesgQueue(&asyncLoad->msgQueue, &asyncLoad->msg, 1);
+ return asyncLoad;
+}
+
+void AudioLoad_ProcessAsyncLoads(s32 resetStatus) {
+ AudioAsyncLoad* asyncLoad;
+ s32 i;
+
+ if (gAudioContext.resetTimer == 1) {
+ return;
+ }
+
+ if (gAudioContext.curUnkMediumLoad == NULL) {
+ if (resetStatus != 0) {
+ // Clear and ignore queue if resetting.
+ do {
+ } while (osRecvMesg(&gAudioContext.asyncLoadUnkMediumQueue, (OSMesg*)&asyncLoad, OS_MESG_NOBLOCK) != -1);
+ } else if (osRecvMesg(&gAudioContext.asyncLoadUnkMediumQueue, (OSMesg*)&asyncLoad, OS_MESG_NOBLOCK) == -1) {
+ gAudioContext.curUnkMediumLoad = NULL;
+ } else {
+ gAudioContext.curUnkMediumLoad = asyncLoad;
+ }
+ }
+
+ if (gAudioContext.curUnkMediumLoad != NULL) {
+ AudioLoad_ProcessAsyncLoadUnkMedium(gAudioContext.curUnkMediumLoad, resetStatus);
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.asyncLoads); i++) {
+ if (gAudioContext.asyncLoads[i].status == 1) {
+ asyncLoad = &gAudioContext.asyncLoads[i];
+ if (asyncLoad->medium != MEDIUM_UNK) {
+ AudioLoad_ProcessAsyncLoad(asyncLoad, resetStatus);
+ }
+ }
+ }
+}
+
+void AudioLoad_ProcessAsyncLoadUnkMedium(AudioAsyncLoad* asyncLoad, s32 resetStatus) {
+}
+
+void AudioLoad_FinishAsyncLoad(AudioAsyncLoad* asyncLoad) {
+ u32 retMsg = asyncLoad->retMsg;
+ u32 fontId;
+ u32 pad;
+ OSMesg doneMsg;
+ u32 sampleBankId1;
+ u32 sampleBankId2;
+ AudioRelocInfo relocInfo;
+
+ if (1) {}
+ switch (ASYNC_TBLTYPE(retMsg)) {
+ case SEQUENCE_TABLE:
+ AudioLoad_SetSeqLoadStatus(ASYNC_ID(retMsg), ASYNC_STATUS(retMsg));
+ break;
+ case SAMPLE_TABLE:
+ AudioLoad_SetSampleFontLoadStatusAndApplyCaches(ASYNC_ID(retMsg), ASYNC_STATUS(retMsg));
+ break;
+ case FONT_TABLE:
+ fontId = ASYNC_ID(retMsg);
+ sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
+ sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
+ relocInfo.sampleBankId1 = sampleBankId1;
+ relocInfo.sampleBankId2 = sampleBankId2;
+ relocInfo.baseAddr1 =
+ sampleBankId1 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId1, &relocInfo.medium1) : 0;
+ relocInfo.baseAddr2 =
+ sampleBankId2 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId2, &relocInfo.medium2) : 0;
+ AudioLoad_SetFontLoadStatus(fontId, ASYNC_STATUS(retMsg));
+ AudioLoad_RelocateFontAndPreloadSamples(fontId, asyncLoad->ramAddr, &relocInfo, true);
+ break;
+ }
+
+ doneMsg = asyncLoad->retMsg;
+ if (1) {}
+ asyncLoad->status = LOAD_STATUS_WAITING;
+ osSendMesg(asyncLoad->retQueue, doneMsg, OS_MESG_NOBLOCK);
+}
+
+void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus) {
+ AudioTable* sampleBankTable = gAudioContext.sampleBankTable;
+
+ if (asyncLoad->delay >= 2) {
+ asyncLoad->delay--;
+ return;
+ }
+
+ if (asyncLoad->delay == 1) {
+ asyncLoad->delay = 0;
+ } else if (resetStatus != 0) {
+ // Await the previous DMA response synchronously, then return.
+ osRecvMesg(&asyncLoad->msgQueue, NULL, OS_MESG_BLOCK);
+ asyncLoad->status = LOAD_STATUS_WAITING;
+ return;
+ } else if (osRecvMesg(&asyncLoad->msgQueue, NULL, OS_MESG_NOBLOCK) == -1) {
+ // If the previous DMA step isn't done, return.
+ return;
+ }
+
+ if (asyncLoad->bytesRemaining == 0) {
+ AudioLoad_FinishAsyncLoad(asyncLoad);
+ return;
+ }
+
+ if (asyncLoad->bytesRemaining < asyncLoad->chunkSize) {
+ if (asyncLoad->medium == MEDIUM_UNK) {
+ AudioLoad_AsyncDmaUnkMedium(asyncLoad->curDevAddr, asyncLoad->curRamAddr, asyncLoad->bytesRemaining,
+ sampleBankTable->unkMediumParam);
+ } else if (asyncLoad->medium == MEDIUM_RAM_UNLOADED) {
+ AudioLoad_AsyncDmaRamUnloaded(asyncLoad, asyncLoad->bytesRemaining);
+ } else {
+ AudioLoad_AsyncDma(asyncLoad, asyncLoad->bytesRemaining);
+ }
+ asyncLoad->bytesRemaining = 0;
+ return;
+ }
+
+ if (asyncLoad->medium == MEDIUM_UNK) {
+ AudioLoad_AsyncDmaUnkMedium(asyncLoad->curDevAddr, asyncLoad->curRamAddr, asyncLoad->chunkSize,
+ sampleBankTable->unkMediumParam);
+ } else if (asyncLoad->medium == MEDIUM_RAM_UNLOADED) {
+ AudioLoad_AsyncDmaRamUnloaded(asyncLoad, asyncLoad->chunkSize);
+ } else {
+ AudioLoad_AsyncDma(asyncLoad, asyncLoad->chunkSize);
+ }
+
+ asyncLoad->bytesRemaining -= asyncLoad->chunkSize;
+ asyncLoad->curDevAddr += asyncLoad->chunkSize;
+ asyncLoad->curRamAddr = asyncLoad->curRamAddr + asyncLoad->chunkSize;
+}
+
+void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, size_t size) {
+ if (size) {}
+ size = ALIGN16(size);
+ Audio_InvalDCache(asyncLoad->curRamAddr, size);
+ osCreateMesgQueue(&asyncLoad->msgQueue, &asyncLoad->msg, 1);
+ AudioLoad_Dma(&asyncLoad->ioMesg, OS_MESG_PRI_NORMAL, OS_READ, asyncLoad->curDevAddr, asyncLoad->curRamAddr, size,
+ &asyncLoad->msgQueue, asyncLoad->medium, "BGCOPY");
+}
+
+void AudioLoad_AsyncDmaRamUnloaded(AudioAsyncLoad* asyncLoad, size_t size) {
+ if (size) {}
+ size = ALIGN16(size);
+ Audio_InvalDCache(asyncLoad->curRamAddr, size);
+ osCreateMesgQueue(&asyncLoad->msgQueue, &asyncLoad->msg, 1);
+ bcopy(asyncLoad->curDevAddr, asyncLoad->curRamAddr, size);
+ osSendMesg(&asyncLoad->msgQueue, NULL, OS_MESG_NOBLOCK);
+}
+
+void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, void* ramAddr, size_t size, s16 arg3) {
+}
+
+#define RELOC(v, base) (reloc = (void*)((uintptr_t)(v) + (uintptr_t)(base)))
+
+void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, AudioRelocInfo* relocInfo) {
+ SoundFontSample* sample;
+ void* reloc;
+
+ if ((uintptr_t)sound->sample <= 0x80000000) {
+ sample = sound->sample = RELOC(sound->sample, mem);
+ if (sample->size != 0 && sample->unk_bit25 != true) {
+ sample->loop = RELOC(sample->loop, mem);
+ sample->book = RELOC(sample->book, mem);
+
+ // Resolve the sample medium 2-bit bitfield into a real value based on relocInfo.
+ switch (sample->medium) {
+ case 0:
+ sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr1);
+ sample->medium = relocInfo->medium1;
+ break;
+ case 1:
+ sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr2);
+ sample->medium = relocInfo->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->unk_bit25 = true;
+ if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
+ gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
+ }
+ }
+ }
+}
+
+#undef RELOC
+
+void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, AudioRelocInfo* relocInfo, s32 async) {
+ AudioPreloadReq* preload;
+ AudioPreloadReq* topPreload;
+ SoundFontSample* sample;
+ size_t size;
+ s32 nChunks;
+ u8* sampleRamAddr;
+ s32 preloadInProgress;
+ s32 i;
+
+ preloadInProgress = false;
+ if (gAudioContext.preloadSampleStackTop != 0) {
+ preloadInProgress = true;
+ } else {
+ D_801FD1E0 = 0;
+ }
+
+ gAudioContext.numUsedSamples = 0;
+ AudioLoad_RelocateFont(fontId, mem, relocInfo);
+
+ size = 0;
+ for (i = 0; i < gAudioContext.numUsedSamples; i++) {
+ size += ALIGN16(gAudioContext.usedSamples[i]->size);
+ }
+ if (size && size) {}
+
+ for (i = 0; i < gAudioContext.numUsedSamples; i++) {
+ if (gAudioContext.preloadSampleStackTop == 120) {
+ break;
+ }
+
+ sample = gAudioContext.usedSamples[i];
+ sampleRamAddr = NULL;
+ switch (async) {
+ case false:
+ if (sample->medium == relocInfo->medium1) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1,
+ sample->sampleAddr, sample->medium, CACHE_PERSISTENT);
+ } else if (sample->medium == relocInfo->medium2) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2,
+ sample->sampleAddr, sample->medium, CACHE_PERSISTENT);
+ } else if (sample->medium == MEDIUM_DISK_DRIVE) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium,
+ CACHE_PERSISTENT);
+ }
+ break;
+
+ case true:
+ if (sample->medium == relocInfo->medium1) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1,
+ sample->sampleAddr, sample->medium, CACHE_TEMPORARY);
+ } else if (sample->medium == relocInfo->medium2) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2,
+ sample->sampleAddr, sample->medium, CACHE_TEMPORARY);
+ } else if (sample->medium == MEDIUM_DISK_DRIVE) {
+ sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium,
+ CACHE_TEMPORARY);
+ }
+ break;
+ }
+ if (sampleRamAddr == NULL) {
+ continue;
+ }
+
+ switch (async) {
+ case false:
+ if (sample->medium == MEDIUM_UNK) {
+ AudioLoad_SyncDmaUnkMedium((uintptr_t)sample->sampleAddr, sampleRamAddr, sample->size,
+ gAudioContext.sampleBankTable->unkMediumParam);
+ sample->sampleAddr = sampleRamAddr;
+ sample->medium = MEDIUM_RAM;
+ } else {
+ AudioLoad_SyncDma((uintptr_t)sample->sampleAddr, sampleRamAddr, sample->size, sample->medium);
+ sample->sampleAddr = sampleRamAddr;
+ sample->medium = MEDIUM_RAM;
+ }
+ if (sample->medium == MEDIUM_DISK_DRIVE) {}
+ break;
+
+ case true:
+ preload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop];
+ preload->sample = sample;
+ preload->ramAddr = sampleRamAddr;
+ preload->encodedInfo = (gAudioContext.preloadSampleStackTop << 24) | 0xFFFFFF;
+ preload->isFree = false;
+ preload->endAndMediumKey = (uintptr_t)sample->sampleAddr + sample->size + sample->medium;
+ gAudioContext.preloadSampleStackTop++;
+ break;
+ }
+ }
+ gAudioContext.numUsedSamples = 0;
+
+ if (gAudioContext.preloadSampleStackTop != 0 && !preloadInProgress) {
+ topPreload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop - 1];
+ sample = topPreload->sample;
+ nChunks = (sample->size >> 12) + 1;
+ AudioLoad_StartAsyncLoad((uintptr_t)sample->sampleAddr, topPreload->ramAddr, sample->size, sample->medium,
+ nChunks, &gAudioContext.preloadSampleQueue, topPreload->encodedInfo);
+ }
+}
+
+s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus) {
+ SoundFontSample* sample;
+ AudioPreloadReq* preload;
+ u32 preloadIndex;
+ u32 key;
+ u32 nChunks;
+ s32 pad;
+
+ if (gAudioContext.preloadSampleStackTop > 0) {
+ if (resetStatus != 0) {
+ // Clear result queue and preload stack and return.
+ osRecvMesg(&gAudioContext.preloadSampleQueue, (OSMesg*)&preloadIndex, OS_MESG_NOBLOCK);
+ gAudioContext.preloadSampleStackTop = 0;
+ return false;
+ }
+ if (osRecvMesg(&gAudioContext.preloadSampleQueue, (OSMesg*)&preloadIndex, OS_MESG_NOBLOCK) == -1) {
+ // Previous preload is not done yet.
+ return false;
+ }
+
+ preloadIndex >>= 24;
+ preload = &gAudioContext.preloadSampleStack[preloadIndex];
+
+ if (preload->isFree == false) {
+ sample = preload->sample;
+ key = (uintptr_t)sample->sampleAddr + sample->size + sample->medium;
+ if (key == preload->endAndMediumKey) {
+ // Change storage for sample to the preloaded version.
+ sample->sampleAddr = preload->ramAddr;
+ sample->medium = MEDIUM_RAM;
+ }
+ preload->isFree = true;
+ }
+
+ // Pop requests with isFree = true off the stack, as far as possible,
+ // and dispatch the next DMA.
+ for (;;) {
+ if (gAudioContext.preloadSampleStackTop <= 0) {
+ break;
+ }
+ preload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop - 1];
+ if (preload->isFree == true) {
+ gAudioContext.preloadSampleStackTop--;
+ continue;
+ }
+
+ sample = preload->sample;
+ nChunks = (sample->size >> 12) + 1;
+ key = (uintptr_t)sample->sampleAddr + sample->size + sample->medium;
+ if (key != preload->endAndMediumKey) {
+ preload->isFree = true;
+ gAudioContext.preloadSampleStackTop--;
+ } else {
+ AudioLoad_StartAsyncLoad((uintptr_t)sample->sampleAddr, preload->ramAddr, sample->size, sample->medium,
+ nChunks, &gAudioContext.preloadSampleQueue, preload->encodedInfo);
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+s32 AudioLoad_AddToSampleSet(SoundFontSample* sample, s32 numSamples, SoundFontSample** sampleSet) {
+ s32 i;
+
+ for (i = 0; i < numSamples; i++) {
+ if (sample->sampleAddr == sampleSet[i]->sampleAddr) {
+ break;
+ }
+ }
+
+ if (i == numSamples) {
+ sampleSet[numSamples] = sample;
+ numSamples++;
+ }
+
+ return numSamples;
+}
+
+s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) {
+ s32 i;
+ s32 numSamples = 0;
+ s32 numDrums = gAudioContext.soundFonts[fontId].numDrums;
+ s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
+
+ for (i = 0; i < numDrums; i++) {
+ Drum* drum = AudioPlayback_GetDrum(fontId, i);
+
+ if (1) {}
+ if (drum != NULL) {
+ numSamples = AudioLoad_AddToSampleSet(drum->sound.sample, numSamples, sampleSet);
+ }
+ }
+
+ for (i = 0; i < numInstruments; i++) {
+ Instrument* instrument = AudioPlayback_GetInstrumentInner(fontId, i);
+
+ if (instrument != NULL) {
+ if (instrument->normalRangeLo != 0) {
+ numSamples = AudioLoad_AddToSampleSet(instrument->lowNotesSound.sample, numSamples, sampleSet);
+ }
+ if (instrument->normalRangeHi != 0x7F) {
+ numSamples = AudioLoad_AddToSampleSet(instrument->highNotesSound.sample, numSamples, sampleSet);
+ }
+ numSamples = AudioLoad_AddToSampleSet(instrument->normalNotesSound.sample, numSamples, sampleSet);
+ }
+ }
+
+ // Should really also process sfx, but this method is never called
+ return numSamples;
+}
+
+void AudioLoad_AddUsedSample(SoundFontSound* sound) {
+ SoundFontSample* sample = sound->sample;
+
+ if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) {
+ gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
+ }
+}
+
+void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, AudioRelocInfo* relocInfo) {
+ s32 numDrums;
+ s32 numInstruments;
+ s32 numSfx;
+ Drum* drum;
+ Instrument* instrument;
+ SoundFontSound* sound;
+ AudioPreloadReq* preload;
+ AudioPreloadReq* topPreload;
+ u8* addr;
+ size_t size;
+ s32 i;
+ SoundFontSample* sample;
+ s32 preloadInProgress;
+ s32 nChunks;
+
+ preloadInProgress = false;
+ if (gAudioContext.preloadSampleStackTop != 0) {
+ preloadInProgress = true;
+ }
+
+ gAudioContext.numUsedSamples = 0;
+
+ numDrums = gAudioContext.soundFonts[fontId].numDrums;
+ numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
+ numSfx = gAudioContext.soundFonts[fontId].numSfx;
+
+ for (i = 0; i < numInstruments; i++) {
+ instrument = AudioPlayback_GetInstrumentInner(fontId, i);
+ if (instrument != NULL) {
+ if (instrument->normalRangeLo != 0) {
+ AudioLoad_AddUsedSample(&instrument->lowNotesSound);
+ }
+ if (instrument->normalRangeHi != 0x7F) {
+ AudioLoad_AddUsedSample(&instrument->highNotesSound);
+ }
+ AudioLoad_AddUsedSample(&instrument->normalNotesSound);
+ }
+ }
+
+ for (i = 0; i < numDrums; i++) {
+ drum = AudioPlayback_GetDrum(fontId, i);
+ if (drum != NULL) {
+ AudioLoad_AddUsedSample(&drum->sound);
+ }
+ }
+
+ for (i = 0; i < numSfx; i++) {
+ sound = AudioPlayback_GetSfx(fontId, i);
+ if (sound != NULL) {
+ AudioLoad_AddUsedSample(sound);
+ }
+ }
+
+ if (gAudioContext.numUsedSamples == 0) {
+ return;
+ }
+
+ size = 0;
+ for (i = 0; i < gAudioContext.numUsedSamples; i++) {
+ size += ALIGN16(gAudioContext.usedSamples[i]->size);
+ }
+ if (size) {}
+
+ for (i = 0; i < gAudioContext.numUsedSamples; i++) {
+ if (gAudioContext.preloadSampleStackTop == 120) {
+ break;
+ }
+
+ sample = gAudioContext.usedSamples[i];
+ if (sample->medium == MEDIUM_RAM) {
+ continue;
+ }
+
+ switch (async) {
+ case false:
+ if (sample->medium == relocInfo->medium1) {
+ addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr,
+ sample->medium, CACHE_PERSISTENT);
+ } else if (sample->medium == relocInfo->medium2) {
+ addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr,
+ sample->medium, CACHE_PERSISTENT);
+ }
+ break;
+
+ case true:
+ if (sample->medium == relocInfo->medium1) {
+ addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr,
+ sample->medium, CACHE_TEMPORARY);
+ } else if (sample->medium == relocInfo->medium2) {
+ addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr,
+ sample->medium, CACHE_TEMPORARY);
+ }
+ break;
+ }
+ if (addr == NULL) {
+ continue;
+ }
+
+ switch (async) {
+ case false:
+ if (sample->medium == MEDIUM_UNK) {
+ AudioLoad_SyncDmaUnkMedium((uintptr_t)sample->sampleAddr, addr, sample->size,
+ gAudioContext.sampleBankTable->unkMediumParam);
+ sample->sampleAddr = addr;
+ sample->medium = MEDIUM_RAM;
+ } else {
+ AudioLoad_SyncDma((uintptr_t)sample->sampleAddr, addr, sample->size, sample->medium);
+ sample->sampleAddr = addr;
+ sample->medium = MEDIUM_RAM;
+ }
+ break;
+
+ case true:
+ preload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop];
+ preload->sample = sample;
+ preload->ramAddr = addr;
+ preload->encodedInfo = (gAudioContext.preloadSampleStackTop << 24) | 0xFFFFFF;
+ preload->isFree = false;
+ preload->endAndMediumKey = (uintptr_t)sample->sampleAddr + sample->size + sample->medium;
+ gAudioContext.preloadSampleStackTop++;
+ break;
+ }
+ }
+ gAudioContext.numUsedSamples = 0;
+
+ if (gAudioContext.preloadSampleStackTop != 0 && !preloadInProgress) {
+ topPreload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop - 1];
+ sample = topPreload->sample;
+ nChunks = (sample->size >> 12) + 1;
+ AudioLoad_StartAsyncLoad((uintptr_t)sample->sampleAddr, topPreload->ramAddr, sample->size, sample->medium,
+ nChunks, &gAudioContext.preloadSampleQueue, topPreload->encodedInfo);
+ }
+}
+
+void AudioLoad_LoadPermanentSamples(void) {
+ s32 pad;
+ u32 fontId;
+ AudioTable* sampleBankTable;
+ s32 pad2;
+ s32 i;
+
+ sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE);
+ for (i = 0; i < gAudioContext.permanentPool.count; i++) {
+ AudioRelocInfo relocInfo;
+
+ if (gAudioContext.permanentEntries[i].tableType == FONT_TABLE) {
+ fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentEntries[i].id);
+ relocInfo.sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
+ relocInfo.sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
+
+ if (relocInfo.sampleBankId1 != 0xFF) {
+ relocInfo.sampleBankId1 = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, relocInfo.sampleBankId1);
+ relocInfo.medium1 = sampleBankTable->entries[relocInfo.sampleBankId1].medium;
+ }
+
+ if (relocInfo.sampleBankId2 != 0xFF) {
+ relocInfo.sampleBankId2 = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, relocInfo.sampleBankId2);
+ relocInfo.medium2 = sampleBankTable->entries[relocInfo.sampleBankId2].medium;
+ }
+ AudioLoad_PreloadSamplesForFont(fontId, false, &relocInfo);
+ }
+ }
+}
+
+void AudioLoad_Unused3(void) {
+}
+
+void AudioLoad_Unused4(void) {
+}
+
+void AudioLoad_Unused5(void) {
+}
+
+void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* isDone) {
+ static u32 sLoadIndex = 0;
+
+ sScriptLoadDonePointers[sLoadIndex] = isDone;
+ AudioLoad_AsyncLoad(tableType, id, 0, sLoadIndex, &sScriptLoadQueue);
+ sLoadIndex++;
+ if (sLoadIndex == 0x10) {
+ sLoadIndex = 0;
+ }
+}
+
+void AudioLoad_ProcessScriptLoads(void) {
+ u32 temp;
+ u32 sp20;
+ s8* isDone;
+
+ if (osRecvMesg(&sScriptLoadQueue, (OSMesg*)&sp20, OS_MESG_NOBLOCK) != -1) {
+ temp = sp20 >> 24;
+ isDone = sScriptLoadDonePointers[temp];
+ if (isDone != NULL) {
+ *isDone = false;
+ }
+ }
+}
+
+void AudioLoad_InitScriptLoads(void) {
+ osCreateMesgQueue(&sScriptLoadQueue, sScriptLoadMesgBuf, ARRAY_COUNT(sScriptLoadMesgBuf));
+}
diff --git a/src/code/audio/audio_playback.c b/src/code/audio/audio_playback.c
index 78161943c..6ae5696f1 100644
--- a/src/code/audio/audio_playback.c
+++ b/src/code/audio/audio_playback.c
@@ -982,7 +982,7 @@ void AudioPlayback_NoteInitAll(void) {
note->playbackState.portamento.speed = 0;
note->playbackState.stereoHeadsetEffects = false;
note->playbackState.unk_84 = 0;
- note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 0x2E0);
- note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 0x10);
+ note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x2E0);
+ note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
}
}
diff --git a/src/code/audio/audio_seqplayer.c b/src/code/audio/audio_seqplayer.c
index 56d8ac951..c132ba6a6 100644
--- a/src/code/audio/audio_seqplayer.c
+++ b/src/code/audio/audio_seqplayer.c
@@ -64,7 +64,7 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019AAF0.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019AB40.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_ResetSequencePlayer.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019AC10.s")
diff --git a/src/code/audio/code_80192BE0.c b/src/code/audio/code_80192BE0.c
index d408361c7..cd430b5ce 100644
--- a/src/code/audio/code_80192BE0.c
+++ b/src/code/audio/code_80192BE0.c
@@ -78,4 +78,4 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80194668.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_801946E4.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_InitMesgQueues.s")