mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-10-13 07:25:54 -04:00
Carry sound font ids in 16 bits (#7260)
Each streamed track brings its own sound font, so a pack with more than ~217 of them pushes font ids past 255. Stored in 8 bits they wrapped onto vanilla fonts or onto 0xFF, which reads as "no font": the track played vanilla instruments or nothing at all. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Sequence> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user