#include #include #include #include "mk64.h" #include "audio/data.h" #include "audio/effects.h" #include "audio/heap.h" #include "audio/load.h" #include "audio/synthesis.h" #include "audio/playback.h" #include "audio/seqplayer.h" s16 gVolume; s8 gUseReverb; s8 gNumSynthesisReverbs; struct NoteSubEu* gNoteSubsEu; struct SoundAllocPool gAudioSessionPool; struct SoundAllocPool gAudioInitPool; struct SoundAllocPool gNotesAndBuffersPool; u8 sAudioHeapPad[0x20]; // probably two unused pools struct SoundAllocPool gSeqAndBankPool; struct SoundAllocPool gPersistentCommonPool; struct SoundAllocPool gTemporaryCommonPool; struct SoundMultiPool gSeqLoadedPool; struct SoundMultiPool gBankLoadedPool; struct SoundMultiPool gUnusedLoadedPool; struct Unk1Pool gUnkPool1; struct PoolSplit sSessionPoolSplit; struct PoolSplit2 sSeqAndBankPoolSplit; struct PoolSplit sPersistentCommonPoolSplit; struct PoolSplit sTemporaryCommonPoolSplit; u8 gUnkLoadStatus[0x40]; u8 gBankLoadStatus[0x40]; u8 gSeqLoadStatus[0x100]; volatile u8 gAudioResetStatus; u8 gAudioResetPresetIdToLoad; s32 gAudioResetFadeOutFramesLeft; u8 gAudioUnusedBuffer[0x1000]; struct Note* gNotes; /** * Given that (almost) all of these are format strings, it is highly likely * that they are meant to be used in some sort of printf variant. But I don't * care to try and figure out which function gets which string(s) * So I've place them all here instead. **/ char heapAudioString00[] = "Warning:Kill Note %x \n"; char heapAudioString01[] = "Kill Voice %d (ID %d) %d\n"; char heapAudioString02[] = "Warning: Running Sequence's data disappear!\n"; char heapAudioString03[] = "Audio:Memory:Heap OverFlow : Not Allocate %d!\n"; char heapAudioString04[] = "Audio:Memory:DataHeap Not Allocate \n"; char heapAudioString05[] = "StayHeap Not Allocate %d\n"; char heapAudioString06[] = "AutoHeap Not Allocate %d\n"; char heapAudioString07[] = "Status ID0 : %d ID1 : %d\n"; char heapAudioString08[] = "id 0 is Stopping\n"; char heapAudioString09[] = "id 0 is Stop\n"; char heapAudioString10[] = "id 1 is Stopping\n"; char heapAudioString11[] = "id 1 is Stop\n"; char heapAudioString12[] = "WARNING: NO FREE AUTOSEQ AREA.\n"; char heapAudioString13[] = "WARNING: NO STOP AUTO AREA.\n"; char heapAudioString14[] = " AND TRY FORCE TO STOP SIDE \n"; char heapAudioString15[] = "Check ID0 (seq ID %d) Useing ...\n"; char heapAudioString16[] = "Check ID1 (seq ID %d) Useing ...\n"; char heapAudioString17[] = "No Free Seq area.\n"; char heapAudioString18[] = "CH %d: ID %d\n"; char heapAudioString19[] = "TWO SIDES ARE LOADING... ALLOC CANCELED.\n"; char heapAudioString20[] = "WARNING: Before Area Overlaid After."; char heapAudioString21[] = "WARNING: After Area Overlaid Before."; char heapAudioString22[] = "MEMORY:SzHeapAlloc ERROR: sza->side %d\n"; char heapAudioString23[] = "Audio:MEMORY:SzHeap Overflow error. (%d bytes)\n"; char heapAudioString24[] = "Auto Heap Unhit for ID %d\n"; char heapAudioString25[] = "Heap Reconstruct Start %x\n"; char heapAudioString26[] = "AHPBASE %x\n"; char heapAudioString27[] = "AHPCUR %x\n"; char heapAudioString28[] = "HeapTop %x\n"; char heapAudioString29[] = "SynoutRate %d / %d \n"; char heapAudioString30[] = "FXSIZE %d\n"; char heapAudioString31[] = "FXCOMP %d\n"; char heapAudioString32[] = "FXDOWN %d\n"; char heapAudioString33[] = "WaveCacheLen: %d\n"; char heapAudioString34[] = "SpecChange Finished\n"; char heapAudioString35[] = "Fbank Seq %x\n"; char heapAudioString36[] = "Already Load Type %d,ID %d\n"; char heapAudioString37[] = "Warning:Emem Over,not alloc %d\n"; char heapAudioString38[] = "Write %d\n"; extern u8 gUnkLoadStatus[]; void reset_bank_and_seq_load_status(void) { s32 i; for (i = 0; i < 64; i++) { if (gBankLoadStatus[i] != 5) { gBankLoadStatus[i] = 0; } } for (i = 0; i < 64; i++) { if (gUnkLoadStatus[i] != 5) { gUnkLoadStatus[i] = 0; } } for (i = 0; i < 256; i++) { if (gSeqLoadStatus[i] != 5) { gSeqLoadStatus[i] = 0; } } } void discard_bank(s32 bankId) { s32 i; for (i = 0; i < gMaxSimultaneousNotes; i++) { struct Note* note = &gNotes[i]; if (note->noteSubEu.bankId == bankId) { // (These prints are unclear. Arguments are picked semi-randomly.) // eu_stubbed_printf_1("Warning:Kill Note %x \n", i); if (note->priority >= NOTE_PRIORITY_MIN) { // eu_stubbed_printf_3("Kill Voice %d (ID %d) %d\n", note->waveId, bankId, note->priority); // eu_stubbed_printf_0("Warning: Running Sequence's data disappear!\n"); note->parentLayer->enabled = false; // is 0x48, should be 0x44 note->parentLayer->finished = true; } note_disable(note); audio_list_remove(¬e->listItem); audio_list_push_back(&gNoteFreeLists.disabled, ¬e->listItem); } } } void discard_sequence(s32 seqId) { s32 i; for (i = 0; i < SEQUENCE_PLAYERS; i++) { if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == seqId) { sequence_player_disable(&gSequencePlayers[i]); } } } void* soundAlloc(struct SoundAllocPool* pool, u32 size) { u8* start; u8* pos; u32 alignedSize = ALIGN16(size); start = pool->cur; if (start + alignedSize <= pool->start + pool->size) { pool->cur += alignedSize; for (pos = start; pos < pool->cur; pos++) { *pos = 0; } } else { printf("audio/heap.c: Heap OverFlow : Not Allocate %d!\n", size); return NULL; } pool->numAllocatedEntries++; return start; } void sound_alloc_pool_init(struct SoundAllocPool* pool, void* memAddr, u32 size) { pool->cur = pool->start = (u8*) ALIGN16((uintptr_t) memAddr); pool->size = size; pool->numAllocatedEntries = 0; } void persistent_pool_clear(struct PersistentPool* persistent) { persistent->pool.numAllocatedEntries = 0; persistent->pool.cur = persistent->pool.start; persistent->numEntries = 0; } void temporary_pool_clear(struct TemporaryPool* temporary) { temporary->pool.numAllocatedEntries = 0; temporary->pool.cur = temporary->pool.start; temporary->nextSide = 0; temporary->entries[0].ptr = temporary->pool.start; temporary->entries[1].ptr = temporary->pool.start + temporary->pool.size; temporary->entries[0].id = -1; // should be at 1e not 1c temporary->entries[1].id = -1; } void func_800B90E0(struct SoundAllocPool* pool) { pool->numAllocatedEntries = 0; pool->cur = pool->start; } // inspired by sound_init_main_pools in sm64 void sound_init_main_pools(s32 arg0) { sound_alloc_pool_init(&gAudioInitPool, &gAudioHeap, arg0); sound_alloc_pool_init(&gAudioSessionPool, gAudioHeap + arg0, gAudioHeapSize - arg0); } // inspired by session_pools_init in sm64 void func_800B914C(struct PoolSplit* arg0) { gAudioSessionPool.cur = gAudioSessionPool.start; sound_alloc_pool_init(&gNotesAndBuffersPool, soundAlloc(&gAudioSessionPool, arg0->wantSeq), arg0->wantSeq); sound_alloc_pool_init(&gSeqAndBankPool, soundAlloc(&gAudioSessionPool, arg0->wantCustom), arg0->wantCustom); } void seq_and_bank_pool_init(struct PoolSplit2* a) { gSeqAndBankPool.cur = gSeqAndBankPool.start; sound_alloc_pool_init(&gPersistentCommonPool, soundAlloc(&gSeqAndBankPool, a->wantPersistent), a->wantPersistent); sound_alloc_pool_init(&gTemporaryCommonPool, soundAlloc(&gSeqAndBankPool, a->wantTemporary), a->wantTemporary); } void persistent_pools_init(struct PoolSplit* a) { gPersistentCommonPool.cur = gPersistentCommonPool.start; sound_alloc_pool_init(&gSeqLoadedPool.persistent.pool, soundAlloc(&gPersistentCommonPool, a->wantSeq), a->wantSeq); sound_alloc_pool_init(&gBankLoadedPool.persistent.pool, soundAlloc(&gPersistentCommonPool, a->wantBank), a->wantBank); sound_alloc_pool_init(&gUnusedLoadedPool.persistent.pool, soundAlloc(&gPersistentCommonPool, a->wantUnused), a->wantUnused); persistent_pool_clear(&gSeqLoadedPool.persistent); persistent_pool_clear(&gBankLoadedPool.persistent); persistent_pool_clear(&gUnusedLoadedPool.persistent); } void temporary_pools_init(struct PoolSplit* a) { gTemporaryCommonPool.cur = gTemporaryCommonPool.start; sound_alloc_pool_init(&gSeqLoadedPool.temporary.pool, soundAlloc(&gTemporaryCommonPool, a->wantSeq), a->wantSeq); sound_alloc_pool_init(&gBankLoadedPool.temporary.pool, soundAlloc(&gTemporaryCommonPool, a->wantBank), a->wantBank); sound_alloc_pool_init(&gUnusedLoadedPool.temporary.pool, soundAlloc(&gTemporaryCommonPool, a->wantUnused), a->wantUnused); temporary_pool_clear(&gSeqLoadedPool.temporary); temporary_pool_clear(&gBankLoadedPool.temporary); temporary_pool_clear(&gUnusedLoadedPool.temporary); } void* alloc_bank_or_seq(struct SoundMultiPool* arg0, s32 arg1, s32 size, s32 arg3, s32 id) { struct TemporaryPool* tp; struct SoundAllocPool* pool; void* ret; u16 UNUSED _firstVal; u16 UNUSED _secondVal; u16 firstVal; u16 secondVal; s32 var_v1_2; u8* table; u8 isSound; if (arg3 == 0) { tp = &arg0->temporary; // clang-format off if (arg0 == &gSeqLoadedPool) { table = gSeqLoadStatus; isSound = 0; } else { // wtf? firstVal += 0; if (arg0 == &gBankLoadedPool) { isSound = 1; table = gBankLoadStatus; } else if (arg0 == &gUnusedLoadedPool) { table = gUnkLoadStatus; isSound = 2; } } // clang-format on if (tp->entries[0].id == -1) { firstVal = 0; } else { firstVal = table[tp->entries[0].id]; } if (tp->entries[1].id == -1) { secondVal = 0; } else { secondVal = table[tp->entries[1].id]; } if (isSound == 1) { if (firstVal == 4) { for (var_v1_2 = 0; var_v1_2 < gMaxSimultaneousNotes; var_v1_2++) { if (gNotes[var_v1_2].noteSubEu.bankId == tp->entries[0].id && gNotes[var_v1_2].noteSubEu.enabled) { break; } } if (var_v1_2 == gMaxSimultaneousNotes) { if (gBankLoadStatus[tp->entries[0].id] != SOUND_LOAD_STATUS_5) { gBankLoadStatus[tp->entries[0].id] = SOUND_LOAD_STATUS_DISCARDABLE; } firstVal = SOUND_LOAD_STATUS_DISCARDABLE; } } if (secondVal == 4) { for (var_v1_2 = 0; var_v1_2 < gMaxSimultaneousNotes; var_v1_2++) { if (gNotes[var_v1_2].noteSubEu.bankId == tp->entries[1].id && gNotes[var_v1_2].noteSubEu.enabled) { break; } } if (var_v1_2 == gMaxSimultaneousNotes) { if (gBankLoadStatus[tp->entries[1].id] != SOUND_LOAD_STATUS_5) { gBankLoadStatus[tp->entries[1].id] = SOUND_LOAD_STATUS_DISCARDABLE; } secondVal = SOUND_LOAD_STATUS_DISCARDABLE; } } } if (firstVal == 0) { tp->nextSide = 0; } else if (secondVal == 0) { tp->nextSide = 1; } else { if ((firstVal == 3) && (secondVal == 3)) { // ? } else if (firstVal == 3) { tp->nextSide = 0; } else if (secondVal == 3) { tp->nextSide = 1; } else { if (isSound == 0) { if (firstVal == SOUND_LOAD_STATUS_COMPLETE) { for (var_v1_2 = 0; var_v1_2 < SEQUENCE_PLAYERS; var_v1_2++) { if (gSequencePlayers[var_v1_2].enabled && gSequencePlayers[var_v1_2].seqId == tp->entries[0].id) { break; } } if (var_v1_2 == SEQUENCE_PLAYERS) { tp->nextSide = 0; goto out; } } if (secondVal == SOUND_LOAD_STATUS_COMPLETE) { for (var_v1_2 = 0; var_v1_2 < SEQUENCE_PLAYERS; var_v1_2++) { if (gSequencePlayers[var_v1_2].enabled && gSequencePlayers[var_v1_2].seqId == tp->entries[1].id) { break; } } if (var_v1_2 == SEQUENCE_PLAYERS) { tp->nextSide = 1; goto out; } } } else if (isSound == 1) { if (firstVal == SOUND_LOAD_STATUS_COMPLETE) { for (var_v1_2 = 0; var_v1_2 < gMaxSimultaneousNotes; var_v1_2++) { if (gNotes[var_v1_2].noteSubEu.bankId == tp->entries[0].id && gNotes[var_v1_2].noteSubEu.enabled) { break; } } if (var_v1_2 == gMaxSimultaneousNotes) { tp->nextSide = 0; goto out; } } if (secondVal == SOUND_LOAD_STATUS_COMPLETE) { for (var_v1_2 = 0; var_v1_2 < gMaxSimultaneousNotes; var_v1_2++) { if (gNotes[var_v1_2].noteSubEu.bankId == tp->entries[1].id && gNotes[var_v1_2].noteSubEu.enabled) { break; } } if (var_v1_2 == gMaxSimultaneousNotes) { tp->nextSide = 1; goto out; } } } if (tp->nextSide == 0) { if (firstVal == SOUND_LOAD_STATUS_IN_PROGRESS) { if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) { tp->nextSide = 1; goto out; } } else { goto out; } } else { if (secondVal == SOUND_LOAD_STATUS_IN_PROGRESS) { if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) { tp->nextSide = 0; goto out; } } else { goto out; } } return NULL; out:; } } pool = &arg0->temporary.pool; if (tp->entries[tp->nextSide].id != (s8) -1) { table[tp->entries[tp->nextSide].id] = SOUND_LOAD_STATUS_NOT_LOADED; if (isSound == true) { discard_bank(tp->entries[tp->nextSide].id); } } switch (tp->nextSide) { case 0: tp->entries[0].ptr = pool->start; tp->entries[0].id = (s16) id; tp->entries[0].size = (u32) size; pool->cur = pool->start + size; if (tp->entries[1].ptr < pool->cur) { table[tp->entries[1].id] = 0; switch (isSound) { /* irregular */ case 0: discard_sequence((s32) tp->entries[1].id); break; case 1: discard_bank((s32) tp->entries[1].id); break; } tp->entries[1].id = -1; tp->entries[1].ptr = pool->start + pool->size; } ret = tp->entries[0].ptr; break; case 1: tp->entries[1].ptr = pool->start + pool->size - size - 0x10; tp->entries[1].id = (s16) id; tp->entries[1].size = (u32) size; if ((u32) tp->entries[1].ptr < (u32) pool->cur) { table[tp->entries[0].id] = 0; switch (isSound) { /* switch 1; irregular */ case 0: /* switch 1 */ discard_sequence((s32) tp->entries[0].id); break; case 1: /* switch 1 */ discard_bank((s32) tp->entries[0].id); break; } tp->entries[0].id = -1; pool->cur = pool->start; } ret = tp->entries[1].ptr; break; default: return NULL; } tp->nextSide ^= 1; return ret; } ret = soundAlloc(&arg0->persistent.pool, arg1 * size); arg0->persistent.entries[arg0->persistent.numEntries].ptr = ret; if (ret == NULL) { switch (arg3) { case 2: return alloc_bank_or_seq(arg0, arg1, size, 0, id); case 1: case 0: return NULL; } } arg0->persistent.entries[arg0->persistent.numEntries].id = (s16) id; arg0->persistent.entries[arg0->persistent.numEntries].size = (u32) size; return arg0->persistent.entries[arg0->persistent.numEntries++].ptr; } void* get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id) { void* ret; ret = unk_pool1_lookup(poolIdx, id); if (ret != NULL) { return ret; } return get_bank_or_seq_inner(poolIdx, arg1, id); } void* get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId) { u32 i; struct SoundMultiPool* loadedPool; struct TemporaryPool* temporary; struct PersistentPool* persistent; switch (poolIdx) { case 0: loadedPool = &gSeqLoadedPool; break; case 1: loadedPool = &gBankLoadedPool; break; case 2: loadedPool = &gUnusedLoadedPool; break; } temporary = &loadedPool->temporary; if (arg1 == 0) { if (temporary->entries[0].id == bankId) { temporary->nextSide = 1; return temporary->entries[0].ptr; } else if (temporary->entries[1].id == bankId) { temporary->nextSide = 0; return temporary->entries[1].ptr; } else { return NULL; } } persistent = &loadedPool->persistent; for (i = 0; i < persistent->numEntries; i++) { if (persistent->entries[i].id == bankId) { return persistent->entries[i].ptr; } } if (arg1 == 2) { return get_bank_or_seq(poolIdx, 0, bankId); } return NULL; } void func_800B9BE4(f32 arg0, f32 arg1, u16* arg2) { s32 i; f32 tmp[16]; tmp[0] = arg1 * 262159.0f; tmp[8] = arg0 * 262159.0f; tmp[1] = (arg1 * arg0) * 262159.0f; tmp[9] = ((arg0 * arg0) + arg1) * 262159.0f; for (i = 2; i < 8; i++) { //! @bug they probably meant to store the value to tmp[i] and tmp[8 + i] arg2[i] = arg1 * tmp[i - 2] + arg0 * tmp[i - 1]; arg2[8 + i] = arg1 * tmp[6 + i] + arg0 * tmp[7 + i]; } for (i = 0; i < 16; i++) { arg2[i] = tmp[i]; } } void decrease_reverb_gain(void) { s32 i; for (i = 0; i < gNumSynthesisReverbs; i++) { gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 4; } } s32 audio_shut_down_and_reset_step(void) { s32 i; s32 j; switch (gAudioResetStatus) { case 5: for (i = 0; i < SEQUENCE_PLAYERS; i++) { sequence_player_disable(&gSequencePlayers[i]); } gAudioResetFadeOutFramesLeft = 4; gAudioResetStatus--; break; case 4: if (gAudioResetFadeOutFramesLeft != 0) { gAudioResetFadeOutFramesLeft--; decrease_reverb_gain(); } else { for (i = 0; i < gMaxSimultaneousNotes; i++) { if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) { gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv; gNotes[i].adsr.action |= ADSR_ACTION_RELEASE; } } gAudioResetFadeOutFramesLeft = 0x00000010; gAudioResetStatus--; } break; case 3: if (gAudioResetFadeOutFramesLeft != 0) { gAudioResetFadeOutFramesLeft--; decrease_reverb_gain(); } else { for (i = 0; i < NUMAIBUFFERS; i++) { for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { gAiBuffers[i][j] = 0; } } gAudioResetFadeOutFramesLeft = 4; gAudioResetStatus--; } break; case 2: if (gAudioResetFadeOutFramesLeft != 0) { gAudioResetFadeOutFramesLeft--; } else { gAudioResetStatus--; } break; case 1: audio_reset_session(); gAudioResetStatus = 0; break; } if (gAudioResetStatus < 3) { return 0; } return 1; } void audio_reset_session(void) { s32 var_s1; s32 var_s5; s32 temp; s32 totalMem; s32 temporaryMem; s32 persistentMem; s16* mem; struct SynthesisReverb* reverb; struct ReverbSettingsEU* reverbSettings; struct AudioSessionSettingsEU* temp_s6 = &gAudioSessionPresets[gAudioResetPresetIdToLoad]; gSampleDmaNumListItems = 0; gAudioBufferParameters.frequency = temp_s6->frequency; gAudioBufferParameters.aiFrequency = osAiSetFrequency(gAudioBufferParameters.frequency); gAudioBufferParameters.samplesPerFrameTarget = ALIGN16(gAudioBufferParameters.frequency / gRefreshRate); gAudioBufferParameters.minAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget - 0x10; gAudioBufferParameters.maxAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget + 0x10; gAudioBufferParameters.updatesPerFrame = ((gAudioBufferParameters.samplesPerFrameTarget + 0x10) / 192) + 1; gAudioBufferParameters.samplesPerUpdate = (gAudioBufferParameters.samplesPerFrameTarget / gAudioBufferParameters.updatesPerFrame) & ~0x0007; gAudioBufferParameters.samplesPerUpdateMax = gAudioBufferParameters.samplesPerUpdate + 8; gAudioBufferParameters.samplesPerUpdateMin = gAudioBufferParameters.samplesPerUpdate - 8; gAudioBufferParameters.resampleRate = 32000.0f / ((f32) (s32) gAudioBufferParameters.frequency); gAudioBufferParameters.unkUpdatesPerFrameScaled = 0.001171875f / gAudioBufferParameters.updatesPerFrame; gAudioBufferParameters.updatesPerFrameInv = 1.0f / gAudioBufferParameters.updatesPerFrame; gMaxSimultaneousNotes = temp_s6->maxSimultaneousNotes; gVolume = temp_s6->volume; gTempoInternalToExternal = (u32) (((gAudioBufferParameters.updatesPerFrame * 2880000.0f) / gTatumsPerBeat) / D_803B7178); gAudioBufferParameters.presetUnk4 = temp_s6->unk1; gAudioBufferParameters.samplesPerFrameTarget *= gAudioBufferParameters.presetUnk4; gAudioBufferParameters.maxAiBufferLength *= gAudioBufferParameters.presetUnk4; gAudioBufferParameters.minAiBufferLength *= gAudioBufferParameters.presetUnk4; gAudioBufferParameters.updatesPerFrame *= gAudioBufferParameters.presetUnk4; gMaxAudioCmds = (gMaxSimultaneousNotes * 0x14 * gAudioBufferParameters.updatesPerFrame) + (temp_s6->numReverbs * 0x20) + 0x1E0; persistentMem = DOUBLE_SIZE_ON_64_BIT(temp_s6->persistentSeqMem + temp_s6->persistentBankMem + temp_s6->unk_18); temporaryMem = DOUBLE_SIZE_ON_64_BIT(temp_s6->temporarySeqMem + temp_s6->temporaryBankMem + temp_s6->unk_24); totalMem = persistentMem + temporaryMem; temp = (gAudioSessionPool.size - totalMem) - 0x100; sSessionPoolSplit.wantSeq = temp; sSessionPoolSplit.wantCustom = totalMem; func_800B914C(&sSessionPoolSplit); sSeqAndBankPoolSplit.wantPersistent = persistentMem; sSeqAndBankPoolSplit.wantTemporary = temporaryMem; seq_and_bank_pool_init(&sSeqAndBankPoolSplit); sPersistentCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(temp_s6->persistentSeqMem); sPersistentCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(temp_s6->persistentBankMem); sPersistentCommonPoolSplit.wantUnused = temp_s6->unk_18; persistent_pools_init(&sPersistentCommonPoolSplit); sTemporaryCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(temp_s6->temporarySeqMem); sTemporaryCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(temp_s6->temporaryBankMem); sTemporaryCommonPoolSplit.wantUnused = temp_s6->unk_24; temporary_pools_init(&sTemporaryCommonPoolSplit); reset_bank_and_seq_load_status(); gNotes = soundAlloc(&gNotesAndBuffersPool, gMaxSimultaneousNotes * sizeof(struct Note)); note_init_all(); init_note_free_list(); gNoteSubsEu = soundAlloc(&gNotesAndBuffersPool, gAudioBufferParameters.updatesPerFrame * gMaxSimultaneousNotes * 0x10); for (var_s5 = 0; var_s5 != 2; var_s5++) { gAudioCmdBuffers[var_s5] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64)); } for (var_s5 = 0; var_s5 < 4; var_s5++) { gSynthesisReverbs[var_s5].useReverb = 0; } gNumSynthesisReverbs = temp_s6->numReverbs; for (var_s5 = 0; var_s5 < gNumSynthesisReverbs; var_s5++) { reverb = &gSynthesisReverbs[var_s5]; reverbSettings = &temp_s6->reverbSettings[var_s5]; reverb->windowSize = reverbSettings->windowSize * 64; reverb->downsampleRate = reverbSettings->downsampleRate; reverb->reverbGain = reverbSettings->gain; reverb->useReverb = 8; reverb->ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2); reverb->ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2); reverb->nextRingBufferPos = 0; reverb->unkC = 0; reverb->curFrame = 0; reverb->bufSizePerChannel = reverb->windowSize; reverb->framesLeftToIgnore = 2; if (reverb->downsampleRate != 1) { reverb->resampleFlags = 1; reverb->resampleRate = 0x8000 / reverb->downsampleRate; reverb->resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 0x00000020U); reverb->resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 0x00000020U); reverb->unk24 = soundAlloc(&gNotesAndBuffersPool, 0x00000020U); reverb->unk28 = soundAlloc(&gNotesAndBuffersPool, 0x00000020U); for (var_s1 = 0; var_s1 < gAudioBufferParameters.updatesPerFrame; var_s1++) { mem = soundAlloc(&gNotesAndBuffersPool, 0x00000300U); reverb->items[0][var_s1].toDownsampleLeft = mem; reverb->items[0][var_s1].toDownsampleRight = mem + (DEFAULT_LEN_1CH / sizeof(s16)); mem = soundAlloc(&gNotesAndBuffersPool, 0x00000300U); reverb->items[1][var_s1].toDownsampleLeft = mem; reverb->items[1][var_s1].toDownsampleRight = mem + (DEFAULT_LEN_1CH / sizeof(s16)); } } } func_800BB030(gMaxSimultaneousNotes); osWritebackDCacheAll(); } void* unk_pool1_lookup(s32 poolIdx, s32 id) { s32 i; for (i = 0; i < gUnkPool1.pool.numAllocatedEntries; i++) { if (gUnkPool1.entries[i].poolIndex == poolIdx && gUnkPool1.entries[i].id == id) { return gUnkPool1.entries[i].ptr; } } return NULL; } // SM64 does not appear to have a function // comparable to this one, not a clue what // this one is doing. void func_800BA8B0(s32 poolIdx, s32 id) { ALSeqFile* sp3C; s32 temp_a2; u32 temp_a1; u8* var_a3; UNUSED u8* temp_v0; UNUSED s32 pad; switch (poolIdx) { /* irregular */ case 0: sp3C = gSeqFileHeader; break; case 1: sp3C = gAlCtlHeader; break; case 2: sp3C = gAlTbl; break; } if (sp3C->seqArray[id].len == 0) { id = (s32) sp3C->seqArray[id].offset; } if (unk_pool1_lookup(poolIdx, id) == NULL) { temp_a2 = gUnkPool1.pool.numAllocatedEntries; temp_a1 = sp3C->seqArray[id].len; var_a3 = sp3C->seqArray[id].offset; if (poolIdx == 1) { var_a3 += 0x10; } gUnkPool1.entries[temp_a2].ptr = soundAlloc(&gUnkPool1.pool, temp_a1); if (gUnkPool1.entries[temp_a2].ptr != NULL) { audio_dma_copy_immediate(var_a3, gUnkPool1.entries[temp_a2].ptr, temp_a1); gUnkPool1.entries[temp_a2].poolIndex = poolIdx; gUnkPool1.entries[temp_a2].id = id; gUnkPool1.entries[temp_a2].size = temp_a1; switch (poolIdx) { /* switch 1; irregular */ case 0: /* switch 1 */ if (gSeqLoadStatus[id] != 5) { gSeqLoadStatus[id] = 5; } break; case 1: /* switch 1 */ gCtlEntries[id].instruments = (struct Instrument**) (gUnkPool1.entries[temp_a2].ptr + 4); func_800BB584(id); if (gBankLoadStatus[id] != 5) { gBankLoadStatus[id] = 5; } break; case 2: /* switch 1 */ break; } } } }