Files
SpaghettiKart/src/audio/load.c
T
2024-11-30 22:46:29 -06:00

820 lines
28 KiB
C

#include <libultraship.h>
#include <macros.h>
#include "audio/load.h"
#include "audio/data.h"
#include "audio/heap.h"
#include "audio/internal.h"
#include "audio/external.h"
#include "audio/playback.h"
#include "audio/synthesis.h"
#include "audio/seqplayer.h"
#include "audio/port_eu.h"
#include "port/Engine.h"
#include "buffers/gfx_output_buffer.h"
#include <string.h>
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
struct SequencePlayer gSequencePlayers[SEQUENCE_PLAYERS];
struct SequenceChannel gSequenceChannels[SEQUENCE_CHANNELS];
struct SequenceChannelLayer gSequenceLayers[SEQUENCE_LAYERS];
struct SequenceChannel gSequenceChannelNone;
// D_803B5F5C
struct AudioListItem gLayerFreeList;
struct NotePool gNoteFreeLists;
OSMesgQueue gCurrAudioFrameDmaQueue;
OSMesg gCurrAudioFrameDmaMesgBufs[AUDIO_FRAME_DMA_QUEUE_SIZE];
OSIoMesg gCurrAudioFrameDmaIoMesgBufs[AUDIO_FRAME_DMA_QUEUE_SIZE];
OSMesgQueue D_803B6720;
OSMesg D_803B6738;
OSIoMesg D_803B6740;
struct SharedDma sSampleDmas[0x70];
u32 gSampleDmaNumListItems;
u32 sSampleDmaListSize1;
s32 D_803B6E60;
s32 load_bss_pad;
u8 sSampleDmaReuseQueue1[256]; // sSampleDmaReuseQueue1
u8 sSampleDmaReuseQueue2[256]; // sSampleDmaReuseQueue2
u8 sSampleDmaReuseQueueTail1; // sSampleDmaReuseQueueTail1
u8 sSampleDmaReuseQueueTail2; // sSampleDmaReuseQueueTail2
u8 sSampleDmaReuseQueueHead1; // sSampleDmaReuseQueueHead1
u8 sSampleDmaReuseQueueHead2; // sSampleDmaReuseQueueHead2
ALSeqFile* gSeqFileHeader;
ALSeqFile* gAlCtlHeader;
ALSeqFile* gAlTbl;
u8* gAlBankSets;
u16 gSequenceCount;
struct CtlEntry* gCtlEntries;
struct AudioBufferParametersEU gAudioBufferParameters;
u32 D_803B70A8;
s32 gMaxAudioCmds;
s32 gMaxSimultaneousNotes;
s16 gTempoInternalToExternal;
s8 gAudioLibSoundMode;
// If we take SM64 as gospel, these should be in data.c, but that doesn't match
volatile s32 gAudioFrameCount;
s32 gCurrAudioFrameDmaCount;
/**
* 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 loadAudioString00[] = "Romcopy %x -> %x ,size %x\n";
char loadAudioString01[] = "Romcopyend\n";
char loadAudioString02[] = "CAUTION:WAVE CACHE FULL %d";
char loadAudioString03[] = "LOAD Rom :%x -> Ram :%x Len:%x\n";
char loadAudioString04[] = "BASE %x %x\n";
char loadAudioString05[] = "LOAD %x %x %x\n";
char loadAudioString06[] = "INSTTOP %x\n";
char loadAudioString07[] = "INSTMAP[0] %x\n";
char loadAudioString08[] = "already flags %d\n";
char loadAudioString09[] = "already flags %d\n";
char loadAudioString10[] = "ERR:SLOW BANK DMA BUSY\n";
char loadAudioString11[] = "ERR:SLOW DMA BUSY\n";
char loadAudioString12[] = "Check %d bank %d\n";
char loadAudioString13[] = "Cache Check\n";
char loadAudioString14[] = "NO BANK ERROR\n";
char loadAudioString15[] = "BANK %d LOADING START\n";
char loadAudioString16[] = "BANK %d LOAD MISS (NO MEMORY)!\n";
char loadAudioString17[] = "BANK %d ALREADY CACHED\n";
char loadAudioString18[] = "BANK LOAD MISS! FOR %d\n";
char loadAudioString19[] = "Seq %d Loading Start\n";
char loadAudioString20[] = "Heap Overflow Error\n";
char loadAudioString21[] = "SEQ %d ALREADY CACHED\n";
char loadAudioString22[] = "Ok,one bank slow load Start \n";
char loadAudioString23[] = "Sorry,too many %d bank is none.fast load Start \n";
char loadAudioString24[] = "Seq %d:Default Load Id is %d\n";
char loadAudioString25[] = "Seq Loading Start\n";
char loadAudioString26[] = "Error:Before Sequence-SlowDma remain.\n";
char loadAudioString27[] = " Cancel Seq Start.\n";
char loadAudioString28[] = "SEQ %d ALREADY CACHED\n";
char loadAudioString29[] = "Clear Workarea %x -%x size %x \n";
char loadAudioString30[] = "AudioHeap is %x\n";
char loadAudioString31[] = "Heap reset.Synth Change %x \n";
char loadAudioString32[] = "Heap %x %x %x\n";
char loadAudioString33[] = "Main Heap Initialize.\n";
char loadAudioString34[] = "---------- Init Completed. ------------\n";
char loadAudioString35[] = " Syndrv :[%6d]\n";
char loadAudioString36[] = " Seqdrv :[%6d]\n";
char loadAudioString37[] = " audiodata :[%6d]\n";
char loadAudioString38[] = "---------------------------------------\n";
/**
* Performs an immediate DMA copy
*/
void audio_dma_copy_immediate(u8* devAddr, void* vAddr, size_t nbytes) {
// eu_stubbed_printf_3("Romcopy %x -> %x ,size %x\n", devAddr, vAddr, nbytes);
osInvalDCache(vAddr, nbytes);
osPiStartDma(&D_803B6740, OS_MESG_PRI_HIGH, OS_READ, (uintptr_t) devAddr, vAddr, nbytes, &D_803B6720);
osRecvMesg(&D_803B6720, NULL, OS_MESG_BLOCK);
// eu_stubbed_printf_0("Romcopyend\n");
}
/**
* Performs an asynchronus (normal priority) DMA copy
*/
void audio_dma_copy_async(uintptr_t devAddr, void* vAddr, size_t nbytes, OSMesgQueue* queue, OSIoMesg* mesg) {
osInvalDCache(vAddr, nbytes);
osPiStartDma(mesg, OS_MESG_PRI_NORMAL, OS_READ, devAddr, vAddr, nbytes, queue);
}
/**
* Performs a partial asynchronous (normal priority) DMA copy. This is limited
* to 0x1000 bytes transfer at once.
*/
void audio_dma_partial_copy_async(uintptr_t* devAddr, u8** vAddr, size_t* remaining, OSMesgQueue* queue,
OSIoMesg* mesg) {
size_t transfer = (*remaining >= 0x1000 ? 0x1000 : *remaining);
*remaining -= transfer;
osInvalDCache(*vAddr, transfer);
osPiStartDma(mesg, OS_MESG_PRI_NORMAL, OS_READ, *devAddr, *vAddr, transfer, queue);
*devAddr += transfer;
*vAddr += transfer;
}
void decrease_sample_dma_ttls() {
u32 i;
for (i = 0; i < sSampleDmaListSize1; i++) {
struct SharedDma* temp = &sSampleDmas[i];
if (temp->ttl != 0) {
temp->ttl--;
if (temp->ttl == 0) {
temp->reuseIndex = sSampleDmaReuseQueueHead1;
sSampleDmaReuseQueue1[sSampleDmaReuseQueueHead1++] = (u8) i;
}
}
}
for (i = sSampleDmaListSize1; i < gSampleDmaNumListItems; i++) {
struct SharedDma* temp = &sSampleDmas[i];
if (temp->ttl != 0) {
temp->ttl--;
if (temp->ttl == 0) {
temp->reuseIndex = sSampleDmaReuseQueueHead2;
sSampleDmaReuseQueue2[sSampleDmaReuseQueueHead2++] = (u8) i;
}
}
}
D_803B6E60 = 0;
}
void* dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8* dmaIndexRef) {
s32 hasDma = false;
struct SharedDma* dma;
uintptr_t dmaDevAddr;
u32 transfer;
u32 i;
u32 dmaIndex;
size_t bufferPos;
UNUSED u32 pad;
if (arg2 != 0 || *dmaIndexRef >= sSampleDmaListSize1) {
for (i = sSampleDmaListSize1; i < gSampleDmaNumListItems; i++) {
dma = &sSampleDmas[i];
bufferPos = devAddr - dma->source;
if (0 <= bufferPos && (size_t) bufferPos <= dma->bufSize - size) {
// We already have a DMA request for this memory range.
if (dma->ttl == 0 && sSampleDmaReuseQueueTail2 != sSampleDmaReuseQueueHead2) {
// Move the DMA out of the reuse queue, by swapping it with the
// tail, and then incrementing the tail.
if (dma->reuseIndex != sSampleDmaReuseQueueTail2) {
sSampleDmaReuseQueue2[dma->reuseIndex] = sSampleDmaReuseQueue2[sSampleDmaReuseQueueTail2];
sSampleDmas[sSampleDmaReuseQueue2[sSampleDmaReuseQueueTail2]].reuseIndex = dma->reuseIndex;
}
sSampleDmaReuseQueueTail2++;
}
dma->ttl = 60;
*dmaIndexRef = (u8) i;
return &dma->buffer[(devAddr - dma->source)];
}
}
if ((sSampleDmaReuseQueueTail2 != sSampleDmaReuseQueueHead2) && (arg2 != 0)) {
// Allocate a DMA from reuse queue 2. This queue can be empty, since
// TTL 60 is pretty large.
dmaIndex = sSampleDmaReuseQueue2[sSampleDmaReuseQueueTail2++];
dma = &sSampleDmas[dmaIndex];
hasDma = true;
}
} else {
dma = &sSampleDmas[*dmaIndexRef];
for (i = 0; i < sSampleDmaListSize1; dma = &sSampleDmas[i++]) {
bufferPos = devAddr - dma->source;
if (0 <= bufferPos && (size_t) bufferPos <= dma->bufSize - 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
// tail, and then incrementing the tail.
if (dma->reuseIndex != sSampleDmaReuseQueueTail1) {
if (1) {}
sSampleDmaReuseQueue1[dma->reuseIndex] = sSampleDmaReuseQueue1[sSampleDmaReuseQueueTail1];
sSampleDmas[sSampleDmaReuseQueue1[sSampleDmaReuseQueueTail1]].reuseIndex = dma->reuseIndex;
}
sSampleDmaReuseQueueTail1++;
}
dma->ttl = 2;
return dma->buffer + (devAddr - dma->source);
}
}
}
if (!hasDma) {
// Allocate a DMA from reuse queue 1. This queue will hopefully never
// be empty, since TTL 2 is so small.
dmaIndex = sSampleDmaReuseQueue1[sSampleDmaReuseQueueTail1++];
dma = &sSampleDmas[dmaIndex];
hasDma = true;
}
transfer = dma->bufSize;
dmaDevAddr = devAddr & ~0xF;
dma->ttl = 2;
dma->source = dmaDevAddr;
dma->sizeUnused = transfer;
osPiStartDma(&gCurrAudioFrameDmaIoMesgBufs[gCurrAudioFrameDmaCount++], OS_MESG_PRI_NORMAL, OS_READ, dmaDevAddr,
dma->buffer, transfer, &gCurrAudioFrameDmaQueue);
*dmaIndexRef = dmaIndex;
return (devAddr - dmaDevAddr) + dma->buffer;
}
// init_sample_dma_buffers
void func_800BB030(UNUSED s32 arg0) {
s32 i;
#define j i
D_803B70A8 = 0x5A0;
for (i = 0; i < gMaxSimultaneousNotes * 3 * gAudioBufferParameters.presetUnk4; i++) {
sSampleDmas[gSampleDmaNumListItems].buffer = soundAlloc(&gNotesAndBuffersPool, D_803B70A8);
if (sSampleDmas[gSampleDmaNumListItems].buffer == NULL) {
break;
}
sSampleDmas[gSampleDmaNumListItems].bufSize = D_803B70A8;
sSampleDmas[gSampleDmaNumListItems].source = 0;
sSampleDmas[gSampleDmaNumListItems].sizeUnused = 0;
sSampleDmas[gSampleDmaNumListItems].unused2 = 0;
sSampleDmas[gSampleDmaNumListItems].ttl = 0;
gSampleDmaNumListItems++;
}
for (i = 0; (u32) i < gSampleDmaNumListItems; i++) {
sSampleDmaReuseQueue1[i] = (u8) i;
sSampleDmas[i].reuseIndex = (u8) i;
}
for (j = gSampleDmaNumListItems; j < 0x100; j++) {
sSampleDmaReuseQueue1[j] = 0;
}
sSampleDmaReuseQueueTail1 = 0;
sSampleDmaReuseQueueHead1 = (u8) gSampleDmaNumListItems;
sSampleDmaListSize1 = gSampleDmaNumListItems;
D_803B70A8 = 0x180;
for (i = 0; i < gMaxSimultaneousNotes; i++) {
sSampleDmas[gSampleDmaNumListItems].buffer = soundAlloc(&gNotesAndBuffersPool, D_803B70A8);
if (sSampleDmas[gSampleDmaNumListItems].buffer == NULL) {
break;
}
sSampleDmas[gSampleDmaNumListItems].bufSize = D_803B70A8;
sSampleDmas[gSampleDmaNumListItems].source = 0;
sSampleDmas[gSampleDmaNumListItems].sizeUnused = 0;
sSampleDmas[gSampleDmaNumListItems].unused2 = 0;
sSampleDmas[gSampleDmaNumListItems].ttl = 0;
gSampleDmaNumListItems++;
}
for (i = sSampleDmaListSize1; (u32) i < gSampleDmaNumListItems; i++) {
sSampleDmaReuseQueue2[i - sSampleDmaListSize1] = (u8) i;
sSampleDmas[i].reuseIndex = (u8) (i - sSampleDmaListSize1);
}
// This probably meant to touch the range size1..size2 as well... but it
// doesn't matter, since these values are never read anyway.
for (j = gSampleDmaNumListItems; j < 0x100; j++) {
sSampleDmaReuseQueue2[j] = sSampleDmaListSize1;
}
sSampleDmaReuseQueueTail2 = 0;
sSampleDmaReuseQueueHead2 = gSampleDmaNumListItems - sSampleDmaListSize1;
#undef j
}
// Similar to patch_sound, but not really
s32 func_800BB304(struct AudioBankSample* sample) {
// struct AudioBankSample *sample = sound->sample;
UNUSED u8* mem;
if (sample == (void*) NULL) {
return -1;
}
if (sample->loaded == 1) {
// temp_a1 = sound->sampleAddr // unk10;
mem = soundAlloc(&gNotesAndBuffersPool, sample->sampleSize);
// temp_a1_2 = temp_v0;
if (mem == (void*) NULL) {
return -1;
}
audio_dma_copy_immediate(sample->sampleAddr, mem, sample->sampleSize);
sample->loaded = 0x81;
sample->sampleAddr = mem; // sound->unk4
}
}
s32 func_800BB388(s32 bankId, s32 instId, s32 arg2) {
struct Instrument* instr;
struct Drum* drum;
if (instId < 0x7F) {
instr = get_instrument_inner(bankId, instId);
if (instr == NULL) {
return -1;
}
if (instr->normalRangeLo != 0) {
func_800BB304(instr->lowNotesSound.sample);
}
func_800BB304(instr->normalNotesSound.sample);
if (instr->normalRangeHi != 0x7F) {
func_800BB304(instr->highNotesSound.sample);
}
//! @bug missing return
} else if (instId == 0x7F) {
drum = get_drum(bankId, arg2);
if (drum == NULL) {
return -1;
}
func_800BB304(drum->sound.sample);
return 0;
}
#ifdef AVOID_UB
return 0;
#endif
}
// This appears to be a modified version of alSeqFileNew
// from src/os/alBankNew.c
// Or maybe its patch_seq_file from SM64's load_sh.c?
void func_800BB43C(ALSeqFile* f, u8* base) {
#define PATCH(SRC, BASE, TYPE) SRC = (TYPE) ((uintptr_t) SRC + (uintptr_t) BASE)
int i;
u8* wut = base;
for (i = 0; i < f->seqCount; i++) {
if (f->seqArray[i].len != 0) {
PATCH(f->seqArray[i].offset, wut, u8*);
}
}
#undef PATCH
}
void patch_sound(struct AudioBankSound* sound, u8* memBase, u8* offsetBase) {
struct AudioBankSample* sample;
void* patched;
u8* mem;
#define PATCH(x, base) (patched = (void*) ((uintptr_t) (x) + (uintptr_t) base))
if (sound->sample != NULL) {
sample = sound->sample = (struct AudioBankSample*) PATCH(sound->sample, memBase);
if (sample->loaded == 0) {
sample->sampleAddr = (u8*) PATCH(sample->sampleAddr, offsetBase);
sample->loop = (struct AdpcmLoop*) PATCH(sample->loop, memBase);
sample->book = (struct AdpcmBook*) PATCH(sample->book, memBase);
sample->loaded = 1;
} else if (sample->loaded == 0x80) {
PATCH(sample->sampleAddr, offsetBase);
mem = soundAlloc(&gNotesAndBuffersPool, sample->sampleSize);
if (mem == NULL) {
sample->sampleAddr = (u8*) patched;
sample->loaded = 1;
} else {
audio_dma_copy_immediate((u8*) patched, mem, sample->sampleSize);
sample->loaded = 0x81;
sample->sampleAddr = mem;
}
sample->loop = (struct AdpcmLoop*) PATCH(sample->loop, memBase);
sample->book = (struct AdpcmBook*) PATCH(sample->book, memBase);
}
}
#undef PATCH
}
// There does not appear to an SM64 counterpart to this function
void func_800BB584(s32 bankId) {
u8* var_a1;
if (gAlTbl->seqArray[bankId].len == 0) {
var_a1 = gAlTbl->seqArray[(s32) gAlTbl->seqArray[bankId].offset].offset;
} else {
var_a1 = gAlTbl->seqArray[bankId].offset;
}
// wtf is up with the `gCtlEntries[bankId].instruments - 1` stuff?
patch_audio_bank((struct AudioBank*) (gCtlEntries[bankId].instruments - 1), var_a1,
gCtlEntries[bankId].numInstruments, gCtlEntries[bankId].numDrums);
gCtlEntries[bankId].drums = (struct Drum**) *(gCtlEntries[bankId].instruments - 1);
}
void patch_audio_bank(struct AudioBank* mem, u8* offset, u32 numInstruments, u32 numDrums) {
struct Instrument* instrument;
struct Instrument** itInstrs;
struct Instrument** end;
struct AudioBank* temp;
u32 i;
void* patched;
struct Drum* drum;
struct Drum** drums;
u32 numDrums2;
#define BASE_OFFSET_REAL(x, base) (void*) ((uintptr_t) (x) + (uintptr_t) base)
#define PATCH(x, base) (patched = BASE_OFFSET_REAL(x, base))
#define PATCH_MEM(x) x = PATCH(x, mem)
#define BASE_OFFSET(x, base) BASE_OFFSET_REAL(base, x)
drums = mem->drums;
numDrums2 = numDrums;
if (drums != NULL && numDrums2 > 0) {
mem->drums = PATCH(drums, mem);
for (i = 0; i < numDrums2; i++) {
patched = mem->drums[i];
if (patched != NULL) {
drum = PATCH(patched, mem);
mem->drums[i] = drum;
if (drum->loaded == 0) {
patch_sound(&drum->sound, (u8*) mem, offset);
patched = drum->envelope;
drum->envelope = BASE_OFFSET(mem, patched);
drum->loaded = 1;
}
}
}
}
//! Doesn't affect EU, but required for US/JP
temp = &*mem;
if (numInstruments > 0) {
//! Doesn't affect EU, but required for US/JP
struct Instrument** tempInst;
itInstrs = temp->instruments;
tempInst = temp->instruments;
end = numInstruments + tempInst;
do {
if (*itInstrs != NULL) {
*itInstrs = BASE_OFFSET(*itInstrs, mem);
instrument = *itInstrs;
if (instrument->loaded == 0) {
patch_sound(&instrument->lowNotesSound, (u8*) mem, offset);
patch_sound(&instrument->normalNotesSound, (u8*) mem, offset);
patch_sound(&instrument->highNotesSound, (u8*) mem, offset);
patched = instrument->envelope;
instrument->envelope = BASE_OFFSET(mem, patched);
instrument->loaded = 1;
}
}
itInstrs++;
} while (end != itInstrs);
}
#undef PATCH_MEM
#undef PATCH
#undef BASE_OFFSET_REAL
#undef BASE_OFFSET
}
struct AudioBank* bank_load_immediate(s32 bankId, s32 arg1) {
s32 alloc;
UNUSED s32 stackPadding0[9];
struct AudioBank* ret;
u8* ctlData;
alloc = gAlCtlHeader->seqArray[bankId].len + 0xf;
alloc = ALIGN16(alloc);
alloc -= 0x10;
ctlData = gAlCtlHeader->seqArray[bankId].offset;
ret = alloc_bank_or_seq(&gBankLoadedPool, 1, alloc, arg1, bankId);
if (ret == NULL) {
return NULL;
}
audio_dma_copy_immediate(ctlData + 0x10, ret, (u32) alloc);
gCtlEntries[bankId].instruments = ret->instruments;
func_800BB584(bankId);
if (gBankLoadStatus[bankId] != 5) {
gBankLoadStatus[bankId] = 2;
}
return ret;
}
struct AudioBank* bank_load_async(s32 bankId, s32 arg1, struct SequencePlayer* seqPlayer) {
size_t alloc;
UNUSED s32 stackPadding0[9];
struct AudioBank* ret;
u8* ctlData;
UNUSED s32 stackPadding1[2];
alloc = gAlCtlHeader->seqArray[bankId].len + 0xF;
alloc = ALIGN16(alloc);
alloc -= 0x10;
ctlData = gAlCtlHeader->seqArray[bankId].offset;
ret = alloc_bank_or_seq(&gBankLoadedPool, 1, alloc, arg1, bankId);
if (ret == NULL) {
return NULL;
}
seqPlayer->loadingBankId = bankId;
gCtlEntries[bankId].instruments = ret->instruments;
gCtlEntries[bankId].drums = NULL;
seqPlayer->bankDmaCurrMemAddr = (u8*) ret;
seqPlayer->bankDmaCurrDevAddr = (uintptr_t) (ctlData + 0x10);
seqPlayer->bankDmaRemaining = alloc;
if (1) {}
osCreateMesgQueue(&seqPlayer->bankDmaMesgQueue, &seqPlayer->bankDmaMesg, 1);
seqPlayer->bankDmaInProgress = true;
audio_dma_partial_copy_async(&seqPlayer->bankDmaCurrDevAddr, &seqPlayer->bankDmaCurrMemAddr,
&seqPlayer->bankDmaRemaining, &seqPlayer->bankDmaMesgQueue, &seqPlayer->bankDmaIoMesg);
if (gBankLoadStatus[bankId] != 5) {
gBankLoadStatus[bankId] = 1;
}
return ret;
}
void* sequence_dma_immediate(s32 seqId, s32 arg1) {
s32 seqLength;
void* ptr;
u8* seqData;
seqLength = gSeqFileHeader->seqArray[seqId].len;
seqLength = ALIGN16(seqLength);
seqData = gSeqFileHeader->seqArray[seqId].offset;
ptr = alloc_bank_or_seq(&gSeqLoadedPool, 1, seqLength, arg1, seqId);
if (ptr == NULL) {
return NULL;
}
audio_dma_copy_immediate(seqData, ptr, seqLength);
if (gSeqLoadStatus[seqId] != 5) {
gSeqLoadStatus[seqId] = 2;
}
return ptr;
}
void* sequence_dma_async(s32 seqId, s32 arg1, struct SequencePlayer* seqPlayer) {
s32 seqLength;
void* ptr;
u8* seqData;
OSMesgQueue* mesgQueue;
seqLength = gSeqFileHeader->seqArray[seqId].len;
seqLength = ALIGN16(seqLength);
seqData = gSeqFileHeader->seqArray[seqId].offset;
ptr = alloc_bank_or_seq(&gSeqLoadedPool, 1, seqLength, arg1, seqId);
if (ptr == NULL) {
return NULL;
}
if (seqLength < 0x41) {
audio_dma_copy_immediate(seqData, ptr, (u32) seqLength);
if (1) {}
if (gSeqLoadStatus[seqId] != 5) {
gSeqLoadStatus[seqId] = 2;
}
} else {
audio_dma_copy_immediate(seqData, ptr, 0x00000040U);
mesgQueue = &seqPlayer->seqDmaMesgQueue;
osCreateMesgQueue(mesgQueue, &seqPlayer->seqDmaMesg, 1);
seqPlayer->seqDmaInProgress = true;
audio_dma_copy_async((uintptr_t) (seqData + 0x40), (u8*) ptr + 0x40, seqLength - 0x40, mesgQueue,
&seqPlayer->seqDmaIoMesg);
if (gSeqLoadStatus[seqId] != 5) {
gSeqLoadStatus[seqId] = 1;
}
}
return ptr;
}
uint8_t* load_sequence_immediate(s32 seqId, s32 arg1) {
return GameEngine_LoadSequence(seqId)->data;
}
struct CtlEntry* load_banks_immediate(s32 seqId, u8 *outDefaultBank) {
u32 bankId;
struct AudioSequenceData *seqData = GameEngine_LoadSequence(seqId);
struct CtlEntry *output;
for(size_t i = 0; i < seqData->bankCount; i++) {
output = GameEngine_LoadBank(bankId = seqData->banks[i]);
}
*outDefaultBank = bankId;
return output;
}
void preload_sequence(u32 seqId, u8 preloadMask) {
void* sequenceData;
u8 temp;
if (seqId >= gSequenceCount) {
return;
}
// if (gSeqFileHeader->seqArray[seqId].len == 0) {
// seqId = (u32) gSeqFileHeader->seqArray[seqId].offset;
// }
gAudioLoadLock = AUDIO_LOCK_LOADING;
if (preloadMask & PRELOAD_BANKS) {
load_banks_immediate(seqId, &temp);
}
if (preloadMask & PRELOAD_SEQUENCE) {
//! @bug should be IS_SEQ_LOAD_COMPLETE
if (IS_SEQ_LOAD_COMPLETE(seqId) == true) {
sequenceData = load_sequence_immediate(seqId, 2);
} else {
sequenceData = NULL;
}
if (sequenceData == NULL && sequence_dma_immediate(seqId, 2) == NULL) {
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
return;
}
}
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
}
void load_sequence(u32 player, u32 seqId, s32 loadAsync) {
if (!loadAsync) {
gAudioLoadLock = AUDIO_LOCK_LOADING;
}
load_sequence_internal(player, seqId, loadAsync);
if (!loadAsync) {
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
}
}
void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) {
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
if (seqId >= gSequenceCount) {
return;
}
sequence_player_disable(seqPlayer);
struct CtlEntry* bank = load_banks_immediate(seqId, &seqPlayer->defaultBank[0]);
if (bank == NULL) {
return;
}
eu_stubbed_printf_2("Seq %d:Default Load Id is %d\n", seqId, seqPlayer->defaultBank[0]);
eu_stubbed_printf_0("Seq Loading Start\n");
uint8_t* sequenceData = load_sequence_immediate(seqId, 2);
if (sequenceData == NULL) {
return;
}
seqPlayer->seqId = seqId;
init_sequence_player(player);
seqPlayer->scriptState.depth = 0;
seqPlayer->delay = 0;
seqPlayer->enabled = 1;
seqPlayer->seqData = sequenceData;
seqPlayer->scriptState.pc = sequenceData;
}
#ifdef NON_MATCHING
// https://decomp.me/scratch/5FBUM
// There is some wild bullshit going on in this function
// It is an unholy cross between SM64's EU and Shindou
// verions of this function, with the for loop towards
// the bottom resembling stuff from bank_load_async
extern u8 _audio_banksSegmentRomStart;
extern u8 _audio_tablesSegmentRomStart;
extern u8 _instrument_setsSegmentRomStart;
extern u8 _sequencesSegmentRomStart;
void audio_init(void) {
s32 i;
UNUSED s32 pad[2];
s32 j;
UNUSED s32 pad2[6];
u32 sp60[2];
UNUSED s32 pad1[2];
s32 aaa;
s32 size;
UNUSED u64* ptr64;
UNUSED s32 one = 1;
u8* test;
gAudioLoadLock = 0;
#ifdef TARGET_N64
for (i = 0; i < gAudioHeapSize / 8; i++) {
((u64*) gAudioHeap)[i] = 0;
}
// It seems boot.s doesn't clear the .bss area for audio, so do it here.
ptr64 = (u64*) ((u8*) gGfxSPTaskOutputBuffer + sizeof(gGfxSPTaskOutputBuffer));
for (i = ((uintptr_t) &gAudioGlobalsEndMarker -
(uintptr_t) ((u64*) ((u8*) gGfxSPTaskOutputBuffer + sizeof(gGfxSPTaskOutputBuffer)))) /
8;
i >= 0; i--) {
*ptr64++ = 0;
}
#else
memset(gAudioHeap, 0, gAudioHeapSize);
#endif
// UTODO: Which is the correct one?
D_803B7178 = 16.713f;
gRefreshRate = 60;
port_eu_init();
for (i = 0; i < NUMAIBUFFERS; i++) {
gAiBufferLengths[i] = 0xa0;
}
gAudioTaskIndex = gAudioFrameCount = 0;
gCurrAiBufferIndex = 0;
gAudioLibSoundMode = 0;
gAudioTask = NULL;
gAudioTasks[0].task.t.data_size = 0;
gAudioTasks[1].task.t.data_size = 0;
osCreateMesgQueue(&D_803B6720, &D_803B6738, 1);
osCreateMesgQueue(&gCurrAudioFrameDmaQueue, gCurrAudioFrameDmaMesgBufs, ARRAY_COUNT(gCurrAudioFrameDmaMesgBufs));
gCurrAudioFrameDmaCount = 0;
gSampleDmaNumListItems = 0;
sound_init_main_pools(gAudioInitPoolSize);
for (i = 0; i < NUMAIBUFFERS; i++) {
gAiBuffers[i] = soundAlloc(&gAudioInitPool, AIBUFFER_LEN);
for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) {
gAiBuffers[i][j] = 0;
}
}
gAudioResetPresetIdToLoad = 0;
gAudioResetStatus = one;
audio_shut_down_and_reset_step();
gSequenceCount = GameEngine_GetSequenceCount();
#ifdef TARGET_N64
gSeqFileHeader = (ALSeqFile*) sp60;
test = &_sequencesSegmentRomStart;
audio_dma_copy_immediate(test, gSeqFileHeader, 0x00000010U);
gSequenceCount = gSeqFileHeader->seqCount;
size = gSequenceCount * sizeof(ALSeqData) + 4;
size = ALIGN16(size);
gSeqFileHeader = soundAlloc(&gAudioInitPool, size);
audio_dma_copy_immediate(test, gSeqFileHeader, size);
func_800BB43C(gSeqFileHeader, test);
gAlCtlHeader = (ALSeqFile*) sp60;
test = &_audio_banksSegmentRomStart;
audio_dma_copy_immediate(test, gAlCtlHeader, 0x00000010U);
aaa = gAlCtlHeader->seqCount;
size = ALIGN16(aaa * sizeof(ALSeqData) + 4);
gAlCtlHeader = soundAlloc(&gAudioInitPool, size);
audio_dma_copy_immediate(test, gAlCtlHeader, size);
func_800BB43C(gAlCtlHeader, test);
gCtlEntries = soundAlloc(&gAudioInitPool, aaa * 0xC);
for (i = 0; i < aaa; i++) {
audio_dma_copy_immediate(gAlCtlHeader->seqArray[i].offset, sp60, 0x00000010U);
gCtlEntries[i].numInstruments = sp60[0];
gCtlEntries[i].numDrums = sp60[1];
}
gAlTbl = (ALSeqFile*) sp60;
test = &_audio_tablesSegmentRomStart;
audio_dma_copy_immediate(test, gAlTbl, 0x00000010U);
size = gAlTbl->seqCount * sizeof(ALSeqData) + 4;
size = ALIGN16(size);
gAlTbl = soundAlloc(&gAudioInitPool, size);
audio_dma_copy_immediate(test, gAlTbl, size);
func_800BB43C(gAlTbl, test);
gAlBankSets = soundAlloc(&gAudioInitPool, 0x00000100U);
audio_dma_copy_immediate((u32) &_instrument_setsSegmentRomStart, gAlBankSets, 0x00000100U);
#endif
sound_alloc_pool_init(&gUnkPool1.pool, soundAlloc(&gAudioInitPool, (u32) D_800EA5D8), (u32) D_800EA5D8);
init_sequence_players();
gAudioLoadLock = 0x76557364;
audio_set_player_volume(SEQ_PLAYER_LEVEL, CVarGetFloat("gMainMusicVolume", 1.0f));
audio_set_player_volume(SEQ_PLAYER_ENV, CVarGetFloat("gEnvironmentVolume", 1.0f));
audio_set_player_volume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f));
}
#else
#ifdef VERSION_EU
GLOBAL_ASM("asm/eu_nonmatchings/audio_init.s")
#else
GLOBAL_ASM("asm/non_matchings/audio/load/audio_init.s")
#endif
#endif