summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--soh/include/z64audio.h3
-rw-r--r--soh/src/code/audio_heap.c22
-rw-r--r--soh/src/code/audio_load.c5
3 files changed, 27 insertions, 3 deletions
diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h
index 42328cd8e..6fed61399 100644
--- a/soh/include/z64audio.h
+++ b/soh/include/z64audio.h
@@ -915,7 +915,8 @@ typedef struct {
/* 0x2B30 */ AudioCache fontCache;
/* 0x2C40 */ AudioCache sampleBankCache;
/* 0x2D50 */ AudioAllocPool permanentPool;
- /* 0x2D60 */ AudioCacheEntry permanentCache[32];
+ // SOH [Bugfix] 32 -> 512: large custom-music packs overflowed this (see AudioHeap_AllocPermanent).
+ /* 0x2D60 */ AudioCacheEntry permanentCache[512];
/* 0x2EE0 */ AudioSampleCache persistentSampleCache;
/* 0x3174 */ AudioSampleCache temporarySampleCache;
/* 0x3408 */ AudioPoolSplit4 sessionPoolSplit;
diff --git a/soh/src/code/audio_heap.c b/soh/src/code/audio_heap.c
index 398946fa9..a6f2dae1e 100644
--- a/soh/src/code/audio_heap.c
+++ b/soh/src/code/audio_heap.c
@@ -534,6 +534,14 @@ void* AudioHeap_AllocCached(s32 tableType, ptrdiff_t size, s32 cache, s32 id) {
return ret;
}
+ // SOH [Bugfix] Bound entries[] (see AudioHeap_AllocPermanent); CACHE_EITHER falls back to temporary.
+ if (loadedPool->persistent.numEntries >= ARRAY_COUNT(loadedPool->persistent.entries)) {
+ if (cache == CACHE_EITHER) {
+ return AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, id);
+ }
+ return NULL;
+ }
+
mem = AudioHeap_Alloc(&loadedPool->persistent.pool, size);
loadedPool->persistent.entries[loadedPool->persistent.numEntries].ptr = mem;
@@ -1011,6 +1019,12 @@ void* AudioHeap_AllocPermanent(s32 tableType, s32 id, size_t size) {
index = gAudioContext.permanentPool.count;
+ // SOH [Bugfix] Bound permanentCache: large custom-music packs overflowed it and corrupted
+ // gAudioContext (crashed the audio thread). Refuse rather than corrupt memory; callers handle NULL.
+ if (index >= ARRAY_COUNT(gAudioContext.permanentCache)) {
+ return NULL;
+ }
+
ret = AudioHeap_Alloc(&gAudioContext.permanentPool, size);
gAudioContext.permanentCache[index].ptr = ret;
if (ret == NULL) {
@@ -1134,6 +1148,10 @@ SampleCacheEntry* AudioHeap_AllocTemporarySampleCacheEntry(size_t size) {
}
if (index == -1) {
+ // SOH [Bugfix] Bound entries[] (see AudioHeap_AllocPermanent); callers treat NULL as uncached.
+ if (pool->size >= ARRAY_COUNT(pool->entries)) {
+ return NULL;
+ }
index = pool->size++;
}
@@ -1210,6 +1228,10 @@ SampleCacheEntry* AudioHeap_AllocPersistentSampleCacheEntry(size_t size) {
void* mem;
pool = &gAudioContext.persistentSampleCache;
+ // SOH [Bugfix] Bound entries[] (see AudioHeap_AllocPermanent).
+ if (pool->size >= ARRAY_COUNT(pool->entries)) {
+ return NULL;
+ }
mem = AudioHeap_Alloc(&pool->pool, size);
if (mem == NULL) {
return NULL;
diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c
index 582cf3a1c..fcebb7104 100644
--- a/soh/src/code/audio_load.c
+++ b/soh/src/code/audio_load.c
@@ -1350,8 +1350,9 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
// calloc: unassigned slots stay NULL for the guard in AudioLoad_SyncInitSeqPlayerInternal().
sequenceMap = calloc(sequenceMapSize + 0xF, sizeof(char*));
- gAudioContext.seqLoadStatus = malloc(sequenceMapSize);
- memset(gAudioContext.seqLoadStatus, 5, sequenceMapSize);
+ // SOH [Bugfix] Size to match sequenceMap (+ 0xF); custom ids can exceed sequenceMapSize.
+ gAudioContext.seqLoadStatus = malloc(sequenceMapSize + 0xF);
+ memset(gAudioContext.seqLoadStatus, 5, sequenceMapSize + 0xF);
for (size_t i = 0; i < seqListSize; i++) {
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
sequenceMap[sDat.seqNumber] = strdup(seqList[i]);