diff --git a/soh/include/functions.h b/soh/include/functions.h index 659306dca2..22adf03624 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1973,7 +1973,7 @@ s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId); void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue); void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue); void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* retQueue); -u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* arg1); +u16* AudioLoad_GetFontsForSequence(s32 seqId, u32* arg1); void AudioLoad_DiscardSeqFonts(s32 seqId); s32 AudioLoad_SyncInitSeqPlayer(s32 playerIdx, s32 seqId, s32 arg2); s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIdx, s32 seqId, s32 arg2); @@ -1995,7 +1995,7 @@ void Audio_QueueCmdS8(u32 arg0, s8 arg1); void Audio_QueueCmdU16(u32 arg0, u16 arg1); s32 Audio_ScheduleProcessCmds(void); u32 func_800E5E20(u32* arg0); -u8* func_800E5E84(s32 arg0, u32* arg1); +u16* func_800E5E84(s32 arg0, u32* arg1); s32 func_800E5EDC(void); s32 func_800E5F88(s32 arg0); void Audio_PreNMIInternal(void); diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index 9fb4ba6ea5..6f62e9f23e 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -9,6 +9,8 @@ extern "C" { #define NO_LAYER ((SequenceLayer*)(-1)) +#define FONT_ID_NONE 0xFFFF + #define TATUMS_PER_BEAT 48 #define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gAudioContext.sequenceChannelNone) @@ -268,7 +270,7 @@ typedef struct { /* 0x002 */ u8 noteAllocPolicy; /* 0x003 */ u8 muteBehavior; /* 0x004 */ u16 seqId; - /* 0x005 */ u8 defaultFont; + /* 0x005 */ u16 defaultFont; /* 0x006 */ u8 unk_06[1]; /* 0x007 */ s8 playerIdx; /* 0x008 */ u16 tempo; // tatums per minute @@ -376,7 +378,7 @@ typedef struct SequenceChannel { /* 0x04 */ u8 reverb; // or dry/wet mix /* 0x05 */ u8 notePriority; // 0-3 /* 0x06 */ u8 someOtherPriority; - /* 0x07 */ u8 fontId; + /* 0x07 */ u16 fontId; /* 0x08 */ u8 reverbIndex; /* 0x09 */ u8 bookOffset; /* 0x0A */ u8 newPan; @@ -507,7 +509,7 @@ typedef struct { /* 0x00 */ u8 priority; /* 0x01 */ u8 waveId; /* 0x02 */ u8 sampleCountIndex; - /* 0x03 */ u8 fontId; + /* 0x03 */ u16 fontId; /* 0x04 */ u8 unk_04; /* 0x05 */ u8 stereoHeadsetEffects; /* 0x06 */ s16 adsrVolScaleUnused; @@ -1176,7 +1178,7 @@ typedef struct { uint8_t medium; uint8_t cachePolicy; int32_t numFonts; - uint8_t fonts[16]; + uint16_t fonts[16]; } SequenceData; void Audio_SetGameVolume(int player_id, f32 volume); diff --git a/soh/soh/resource/type/AudioSequence.h b/soh/soh/resource/type/AudioSequence.h index 96f2022807..58994b54a2 100644 --- a/soh/soh/resource/type/AudioSequence.h +++ b/soh/soh/resource/type/AudioSequence.h @@ -12,7 +12,7 @@ typedef struct { uint8_t medium; uint8_t cachePolicy; uint32_t numFonts; - uint8_t fonts[16]; + uint16_t fonts[16]; } Sequence; class AudioSequence : public Ship::Resource { diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c index 239e312f32..d7de0389a9 100644 --- a/soh/src/code/audio_load.c +++ b/soh/src/code/audio_load.c @@ -300,7 +300,7 @@ void AudioLoad_InitSampleDmaBuffers(s32 arg0) { // SOH [Port] Completely reworked from decomp: SAF custom fontIds can exceed the native table; bounds-check against // fontMapSize to avoid OOB reads. s32 AudioLoad_IsFontLoadComplete(s32 fontId) { - if (fontId == 0xFF) { + if (fontId == FONT_ID_NONE) { return true; } // Resolve indirection (identity for FONT_TABLE today, but kept for parity with other tables). @@ -337,7 +337,7 @@ s32 AudioLoad_IsSampleLoadComplete(s32 sampleBankId) { } void AudioLoad_SetFontLoadStatus(s32 fontId, s32 status) { - if ((fontId != 0xFF) && ((size_t)fontId < fontMapSize) && (gAudioContext.fontLoadStatus[fontId] != 5)) { + if ((fontId != FONT_ID_NONE) && ((size_t)fontId < fontMapSize) && (gAudioContext.fontLoadStatus[fontId] != 5)) { gAudioContext.fontLoadStatus[fontId] = status; } } @@ -395,7 +395,7 @@ SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) { return NULL; } - fontId = 0xFF; + fontId = FONT_ID_NONE; index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; numFonts = gAudioContext.sequenceFontTable[index++]; @@ -490,7 +490,7 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret AudioLoad_AsyncLoad(FONT_TABLE, fontId, 0, retData, retQueue); } -u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { +u16* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { s32 index; // Check for NA_BGM_DISABLED and account for seqId that are stripped with `& 0xFF` by the caller @@ -585,7 +585,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { AudioSeq_SequencePlayerDisable(seqPlayer); - fontId = 0xFF; + fontId = FONT_ID_NONE; // seqId is the resolved 16-bit id from func_800F9280(). Reject ids with no loaded sequence; the // map has sequenceMapSize + 0xF slots (custom ids skip the reserved 129-135 range). @@ -1407,9 +1407,13 @@ void AudioLoad_Init(void* heap, size_t heapSize) { SequenceData* sDat = ResourceMgr_LoadSeqPtrByName(customSeqList[j]); if (sDat->numFonts == -1) { + uint8_t crcBytes[sizeof(uint64_t)]; uint64_t crc; - memcpy(&crc, sDat->fonts, sizeof(uint64_t)); + for (size_t b = 0; b < sizeof(crcBytes); b++) { + crcBytes[b] = (uint8_t)sDat->fonts[b]; + } + memcpy(&crc, crcBytes, sizeof(crc)); const char* res = ResourceGetNameByCrc(crc); if (res == NULL) { // Passing a null buffer and length of 0 to snprintf will return the required numbers of characters the @@ -1426,6 +1430,10 @@ void AudioLoad_Init(void* heap, size_t heapSize) { continue; } SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(res); + if (sf->fntIndex >= FONT_ID_NONE) { + LUSLOG_ERROR("Font limit (0xFFFF) exceeded; sequence \"%s\" skipped.", customSeqList[j]); + continue; + } memset(&sDat->fonts[0], 0, sizeof(sDat->fonts)); sDat->fonts[0] = sf->fntIndex; sDat->numFonts = 1; diff --git a/soh/src/code/audio_playback.c b/soh/src/code/audio_playback.c index cffe35e1ca..e4709d76be 100644 --- a/soh/src/code/audio_playback.c +++ b/soh/src/code/audio_playback.c @@ -327,7 +327,7 @@ SoundFontSound* Audio_InstrumentGetSound(Instrument* instrument, s32 semitone) { Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) { Instrument* inst; - if (fontId == 0xFF) { + if (fontId == FONT_ID_NONE) { return NULL; } @@ -355,7 +355,7 @@ Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) { Drum* Audio_GetDrum(s32 fontId, s32 drumId) { Drum* drum = NULL; - if (fontId == 0xFF) { + if (fontId == FONT_ID_NONE) { return NULL; } @@ -379,7 +379,7 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) { SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) { SoundFontSound* sfx = NULL; - if (fontId == 0xFF) { + if (fontId == FONT_ID_NONE) { return NULL; } @@ -405,7 +405,7 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) { } s32 Audio_SetFontInstrument(s32 instrumentType, s32 fontId, s32 index, void* value) { - if (fontId == 0xFF) { + if (fontId == FONT_ID_NONE) { return -1; } diff --git a/soh/src/code/audio_seqplayer.c b/soh/src/code/audio_seqplayer.c index b99d29e1ed..92efecd02e 100644 --- a/soh/src/code/audio_seqplayer.c +++ b/soh/src/code/audio_seqplayer.c @@ -1005,6 +1005,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { u32 parameters[3]; s8 signedParam; u8 command = AudioSeq_ScriptReadU8(scriptState); + u16 fontId; u8 lowBits; u8 highBits; s32 result; @@ -1060,20 +1061,20 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xEB: result = (u8)parameters[0]; - command = (u8)parameters[0]; + fontId = (u8)parameters[0]; - if (seqPlayer->defaultFont != 0xFF) { + if (seqPlayer->defaultFont != FONT_ID_NONE) { if (gAudioContext.seqReplaced[seqPlayer->playerIdx]) { seqPlayer->seqId = gAudioContext.seqToPlay[seqPlayer->playerIdx]; gAudioContext.seqReplaced[seqPlayer->playerIdx] = 0; } u16 seqId = AudioEditor_GetReplacementSeq(seqPlayer->seqId); SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]); - command = sDat.fonts[sDat.numFonts - result - 1]; + fontId = sDat.fonts[sDat.numFonts - result - 1]; } - if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) { - channel->fontId = command; + if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, fontId)) { + channel->fontId = fontId; } parameters[0] = parameters[1]; @@ -1175,9 +1176,9 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xC6: result = (u8)parameters[0]; - command = (u8)parameters[0]; + fontId = (u8)parameters[0]; - if (seqPlayer->defaultFont != 0xFF) { + if (seqPlayer->defaultFont != FONT_ID_NONE) { if (gAudioContext.seqReplaced[seqPlayer->playerIdx]) { seqPlayer->seqId = gAudioContext.seqToPlay[seqPlayer->playerIdx]; gAudioContext.seqReplaced[seqPlayer->playerIdx] = 0; @@ -1190,11 +1191,11 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { if (result > sDat.numFonts) break; - command = sDat.fonts[(sDat.numFonts - result - 1)]; + fontId = sDat.fonts[(sDat.numFonts - result - 1)]; } - if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) { - channel->fontId = command; + if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, fontId)) { + channel->fontId = fontId; } break; diff --git a/soh/src/code/code_800E4FE0.c b/soh/src/code/code_800E4FE0.c index 3d6c9c571c..e9bd7ac649 100644 --- a/soh/src/code/code_800E4FE0.c +++ b/soh/src/code/code_800E4FE0.c @@ -520,7 +520,7 @@ u32 func_800E5E20(u32* out) { return sp1C >> 0x18; } -u8* func_800E5E84(s32 arg0, u32* arg1) { +u16* func_800E5E84(s32 arg0, u32* arg1) { return AudioLoad_GetFontsForSequence(arg0, arg1); } diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index 31fc49de45..a118f33883 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -5016,8 +5016,8 @@ void func_800F5C2C(void) { void Audio_PlayFanfare(u16 seqId) { u16 curSeqId; u32 outNumFonts; - u8* curFontId; - u8* requestedFontId; + u16* curFontId; + u16* requestedFontId; curSeqId = func_800FA0B4(SEQ_PLAYER_FANFARE);