sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

heap.c (59455B)


      1 #include <ultra64.h>
      2 
      3 #include "heap.h"
      4 #include "data.h"
      5 #include "load.h"
      6 #include "synthesis.h"
      7 #include "seqplayer.h"
      8 #include "effects.h"
      9 
     10 #define ALIGN16(val) (((val) + 0xF) & ~0xF)
     11 
     12 struct PoolSplit {
     13     u32 wantSeq;
     14     u32 wantBank;
     15     u32 wantUnused;
     16     u32 wantCustom;
     17 }; // size = 0x10
     18 
     19 struct PoolSplit2 {
     20     u32 wantPersistent;
     21     u32 wantTemporary;
     22 }; // size = 0x8
     23 
     24 #if defined(VERSION_JP) || defined(VERSION_US)
     25 s16 gVolume;
     26 s8 gReverbDownsampleRate;
     27 u8 sReverbDownsampleRateLog; // never read
     28 #endif
     29 
     30 struct SoundAllocPool gAudioSessionPool;
     31 struct SoundAllocPool gAudioInitPool;
     32 struct SoundAllocPool gNotesAndBuffersPool;
     33 u8 sAudioHeapPad[0x20]; // probably two unused pools
     34 struct SoundAllocPool gSeqAndBankPool;
     35 struct SoundAllocPool gPersistentCommonPool;
     36 struct SoundAllocPool gTemporaryCommonPool;
     37 
     38 struct SoundMultiPool gSeqLoadedPool;
     39 struct SoundMultiPool gBankLoadedPool;
     40 struct SoundMultiPool gUnusedLoadedPool;
     41 
     42 #if defined(VERSION_SH) || defined(VERSION_CN)
     43 struct Unk1Pool gUnkPool1;
     44 struct UnkPool gUnkPool2;
     45 struct UnkPool gUnkPool3;
     46 #endif
     47 
     48 struct PoolSplit sSessionPoolSplit;
     49 struct PoolSplit2 sSeqAndBankPoolSplit;
     50 struct PoolSplit sPersistentCommonPoolSplit;
     51 struct PoolSplit sTemporaryCommonPoolSplit;
     52 
     53 #if defined(VERSION_SH) || defined(VERSION_CN)
     54 u8 gUnkLoadStatus[0x40];
     55 #endif
     56 u8 gBankLoadStatus[0x40];
     57 u8 gSeqLoadStatus[0x100];
     58 
     59 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
     60 volatile u8 gAudioResetStatus;
     61 u8 gAudioResetPresetIdToLoad;
     62 s32 gAudioResetFadeOutFramesLeft;
     63 #endif
     64 
     65 u8 gAudioUnusedBuffer[0x1000];
     66 
     67 extern s32 gMaxAudioCmds;
     68 
     69 #if defined(VERSION_SH) || defined(VERSION_CN)
     70 void *get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId);
     71 struct UnkEntry *func_sh_802f1ec4(u32 size);
     72 void func_sh_802f2158(struct UnkEntry *entry);
     73 struct UnkEntry *unk_pool2_alloc(u32 size);
     74 void func_sh_802F2320(struct UnkEntry *entry, struct AudioBankSample *sample);
     75 void func_sh_802f23ec(void);
     76 
     77 void unk_pools_init(u32 size1, u32 size2);
     78 #endif
     79 
     80 #if defined(VERSION_EU)
     81 /**
     82  * Assuming 'k' in [9, 24],
     83  * Computes a newton's method step for f(x) = x^k - d
     84  */
     85 f64 root_newton_step(f64 x, s32 k, f64 d) {
     86     f64 deg2 = x * x;
     87     f64 deg4 = deg2 * deg2;
     88     f64 deg8 = deg4 * deg4;
     89     s32 degree = k - 9;
     90     f64 fx;
     91 
     92     f64 deriv = deg8;
     93     if (degree & 1) {
     94         deriv *= x;
     95     }
     96     if (degree & 2) {
     97         deriv *= deg2;
     98     }
     99     if (degree & 4) {
    100         deriv *= deg4;
    101     }
    102     if (degree & 8) {
    103         deriv *= deg8;
    104     }
    105     fx = deriv * x - d;
    106     deriv = k * deriv;
    107     return x - fx / deriv;
    108 }
    109 
    110 /**
    111  * Assuming 'k' in [9, 24],
    112  * Computes d ^ (1/k)
    113  *
    114  * @return the root, or 1.0 if d is 0
    115  */
    116 f64 kth_root(f64 d, s32 k) {
    117     f64 root = 1.5;
    118     f64 next;
    119     f64 diff;
    120     s32 i;
    121     if (d == 0.0) {
    122         root = 1.0;
    123     } else {
    124         for (i = 0; i < 64; i++) {
    125             if (1) {
    126             }
    127             next = root_newton_step(root, k, d);
    128             diff = next - root;
    129 
    130             if (diff < 0) {
    131                 diff = -diff;
    132             }
    133 
    134             if (diff < 1e-07) {
    135                 root = next;
    136                 break;
    137             } else {
    138                 root = next;
    139             }
    140         }
    141     }
    142 
    143     return root;
    144 }
    145 
    146 void build_vol_rampings_table(s32 UNUSED unused, s32 len) {
    147     s32 i;
    148     s32 step;
    149     s32 d;
    150     s32 k = len / 8;
    151 
    152     for (step = 0, i = 0; i < 0x400; step += 32, i++) {
    153         d = step;
    154         if (step == 0) {
    155             d = 1;
    156         }
    157 
    158         gLeftVolRampings[0][i]  = kth_root(      d, k - 1);
    159         gRightVolRampings[0][i] = kth_root(1.0 / d, k - 1) * 65536.0;
    160         gLeftVolRampings[1][i]  = kth_root(      d, k);
    161         gRightVolRampings[1][i] = kth_root(1.0 / d, k) * 65536.0;
    162         gLeftVolRampings[2][i]  = kth_root(      d, k + 1);
    163         gRightVolRampings[2][i] = kth_root(1.0 / d, k + 1) * 65536.0;
    164     }
    165 }
    166 #endif
    167 
    168 void reset_bank_and_seq_load_status(void) {
    169     s32 i;
    170 
    171 #if defined(VERSION_SH) || defined(VERSION_CN)
    172     for (i = 0; i < 64; i++) {
    173         if (gBankLoadStatus[i] != SOUND_LOAD_STATUS_5) {
    174             gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
    175         }
    176     }
    177 
    178     for (i = 0; i < 64; i++) {
    179         if (gUnkLoadStatus[i] != SOUND_LOAD_STATUS_5) {
    180             gUnkLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
    181         }
    182     }
    183 
    184     for (i = 0; i < 256; i++) {
    185         if (gSeqLoadStatus[i] != SOUND_LOAD_STATUS_5) {
    186             gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
    187         }
    188     }
    189 #else
    190     for (i = 0; i < 64; i++) {
    191         gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
    192     }
    193 
    194     for (i = 0; i < 256; i++) {
    195         gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
    196     }
    197 #endif
    198 }
    199 
    200 void discard_bank(s32 bankId) {
    201     s32 i;
    202 
    203     for (i = 0; i < gMaxSimultaneousNotes; i++) {
    204         struct Note *note = &gNotes[i];
    205 
    206 #if defined(VERSION_EU)
    207         if (note->noteSubEu.bankId == bankId)
    208 #else
    209         if (note->bankId == bankId)
    210 #endif
    211         {
    212             // (These prints are unclear. Arguments are picked semi-randomly.)
    213             eu_stubbed_printf_1("Warning:Kill Note  %x \n", i);
    214 #if defined(VERSION_SH) || defined(VERSION_CN)
    215             if (note->unkSH34 == NOTE_PRIORITY_DISABLED && note->priority)
    216 #else
    217             if (note->priority >= NOTE_PRIORITY_MIN)
    218 #endif
    219             {
    220                 eu_stubbed_printf_3("Kill Voice %d (ID %d) %d\n", note->waveId,
    221                         bankId, note->priority);
    222                 eu_stubbed_printf_0("Warning: Running Sequence's data disappear!\n");
    223                 note->parentLayer->enabled = FALSE; // is 0x48, should be 0x44
    224                 note->parentLayer->finished = TRUE;
    225             }
    226             note_disable(note);
    227             audio_list_remove(&note->listItem);
    228             audio_list_push_back(&gNoteFreeLists.disabled, &note->listItem);
    229         }
    230     }
    231 }
    232 
    233 void discard_sequence(s32 seqId) {
    234     s32 i;
    235 
    236     for (i = 0; i < SEQUENCE_PLAYERS; i++) {
    237         if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == seqId) {
    238 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    239             sequence_player_disable(&gSequencePlayers[i]);
    240 #else
    241             sequence_player_disable(gSequencePlayers + i);
    242 #endif
    243         }
    244     }
    245 }
    246 
    247 void *soundAlloc(struct SoundAllocPool *pool, u32 size) {
    248 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    249     u8 *start;
    250     u8 *pos;
    251     u32 alignedSize = ALIGN16(size);
    252 
    253     start = pool->cur;
    254     if (start + alignedSize <= pool->start + pool->size) {
    255         pool->cur += alignedSize;
    256         for (pos = start; pos < pool->cur; pos++) {
    257             *pos = 0;
    258         }
    259     } else {
    260         eu_stubbed_printf_1("Heap OverFlow : Not Allocate %d!\n", size);
    261         return NULL;
    262     }
    263 #if defined(VERSION_SH) || defined(VERSION_CN)
    264     pool->numAllocatedEntries++;
    265 #endif
    266     return start;
    267 #else
    268     u8 *start;
    269     s32 last;
    270     s32 i;
    271 
    272     if ((pool->cur + ALIGN16(size) <= pool->size + pool->start)) {
    273         start = pool->cur;
    274         pool->cur += ALIGN16(size);
    275         last = pool->cur - start - 1;
    276         for (i = 0; i <= last; i++) {
    277             start[i] = 0;
    278         }
    279     } else {
    280         return NULL;
    281     }
    282     return start;
    283 #endif
    284 }
    285 
    286 #if defined(VERSION_SH) || defined(VERSION_CN)
    287 void *sound_alloc_uninitialized(struct SoundAllocPool *pool, u32 size) {
    288     u8 *start;
    289     u32 alignedSize = ALIGN16(size);
    290 
    291     start = pool->cur;
    292     if (start + alignedSize <= pool->start + pool->size) {
    293         pool->cur += alignedSize;
    294     } else {
    295         return NULL;
    296     }
    297 
    298     pool->numAllocatedEntries++;
    299     return start;
    300 }
    301 #endif
    302 
    303 void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size) {
    304     pool->cur = pool->start = (u8 *) ALIGN16((uintptr_t) memAddr);
    305 #if defined(VERSION_SH) || defined(VERSION_CN)
    306     pool->size = size - ((uintptr_t) memAddr & 0xf);
    307 #else
    308     pool->size = size;
    309 #endif
    310     pool->numAllocatedEntries = 0;
    311 }
    312 
    313 void persistent_pool_clear(struct PersistentPool *persistent) {
    314     persistent->pool.numAllocatedEntries = 0;
    315     persistent->pool.cur = persistent->pool.start;
    316     persistent->numEntries = 0;
    317 }
    318 
    319 void temporary_pool_clear(struct TemporaryPool *temporary) {
    320     temporary->pool.numAllocatedEntries = 0;
    321     temporary->pool.cur = temporary->pool.start;
    322     temporary->nextSide = 0;
    323     temporary->entries[0].ptr = temporary->pool.start;
    324 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    325     temporary->entries[1].ptr = temporary->pool.start + temporary->pool.size;
    326 #else
    327     temporary->entries[1].ptr = temporary->pool.size + temporary->pool.start;
    328 #endif
    329     temporary->entries[0].id = -1; // should be at 1e not 1c
    330     temporary->entries[1].id = -1;
    331 }
    332 
    333 void unused_803160F8(struct SoundAllocPool *pool) {
    334     pool->numAllocatedEntries = 0;
    335     pool->cur = pool->start;
    336 }
    337 
    338 extern s32 D_SH_80315EE8;
    339 void sound_init_main_pools(s32 sizeForAudioInitPool) {
    340     sound_alloc_pool_init(&gAudioInitPool, gAudioHeap, sizeForAudioInitPool);
    341     sound_alloc_pool_init(&gAudioSessionPool, gAudioHeap + sizeForAudioInitPool, gAudioHeapSize - sizeForAudioInitPool);
    342 }
    343 
    344 #if defined(VERSION_SH) || defined(VERSION_CN)
    345 #define SOUND_ALLOC_FUNC sound_alloc_uninitialized
    346 #else
    347 #define SOUND_ALLOC_FUNC soundAlloc
    348 #endif
    349 
    350 void session_pools_init(struct PoolSplit *a) {
    351     gAudioSessionPool.cur = gAudioSessionPool.start;
    352     sound_alloc_pool_init(&gNotesAndBuffersPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantSeq), a->wantSeq);
    353     sound_alloc_pool_init(&gSeqAndBankPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantCustom), a->wantCustom);
    354 }
    355 
    356 void seq_and_bank_pool_init(struct PoolSplit2 *a) {
    357     gSeqAndBankPool.cur = gSeqAndBankPool.start;
    358     sound_alloc_pool_init(&gPersistentCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantPersistent), a->wantPersistent);
    359     sound_alloc_pool_init(&gTemporaryCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantTemporary), a->wantTemporary);
    360 }
    361 
    362 void persistent_pools_init(struct PoolSplit *a) {
    363     gPersistentCommonPool.cur = gPersistentCommonPool.start;
    364     sound_alloc_pool_init(&gSeqLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantSeq), a->wantSeq);
    365     sound_alloc_pool_init(&gBankLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantBank), a->wantBank);
    366     sound_alloc_pool_init(&gUnusedLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantUnused),
    367                   a->wantUnused);
    368     persistent_pool_clear(&gSeqLoadedPool.persistent);
    369     persistent_pool_clear(&gBankLoadedPool.persistent);
    370     persistent_pool_clear(&gUnusedLoadedPool.persistent);
    371 }
    372 
    373 void temporary_pools_init(struct PoolSplit *a) {
    374     gTemporaryCommonPool.cur = gTemporaryCommonPool.start;
    375     sound_alloc_pool_init(&gSeqLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantSeq), a->wantSeq);
    376     sound_alloc_pool_init(&gBankLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantBank), a->wantBank);
    377     sound_alloc_pool_init(&gUnusedLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantUnused),
    378                   a->wantUnused);
    379     temporary_pool_clear(&gSeqLoadedPool.temporary);
    380     temporary_pool_clear(&gBankLoadedPool.temporary);
    381     temporary_pool_clear(&gUnusedLoadedPool.temporary);
    382 }
    383 #undef SOUND_ALLOC_FUNC
    384 
    385 #if defined(VERSION_JP) || defined(VERSION_US)
    386 UNUSED static void unused_803163D4(void) {
    387 }
    388 #endif
    389 
    390 #if defined(VERSION_SH) || defined(VERSION_CN)
    391 void *alloc_bank_or_seq(s32 poolIdx, s32 size, s32 arg3, s32 id) {
    392 #else
    393 void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id) {
    394 #endif
    395     // arg3 = 0, 1 or 2?
    396 
    397 #if defined(VERSION_SH) || defined(VERSION_CN)
    398     struct SoundMultiPool *arg0;
    399 #define isSound poolIdx
    400 #endif
    401     struct TemporaryPool *tp;
    402     struct SoundAllocPool *pool;
    403     void *ret;
    404 #if defined(VERSION_JP) || defined(VERSION_US)
    405     u16 UNUSED _firstVal;
    406     u16 UNUSED _secondVal;
    407 #else
    408     u16 firstVal;
    409     u16 secondVal;
    410 #endif
    411     u32 nullID = -1;
    412     UNUSED s32 i;
    413     u8 *table;
    414 #if !defined(VERSION_SH) && !defined(VERSION_CN)
    415     u8 isSound;
    416 #endif
    417 #if defined(VERSION_JP) || defined(VERSION_US)
    418     u16 firstVal;
    419     u16 secondVal;
    420     u32 bothDiscardable;
    421     u32 leftDiscardable, rightDiscardable;
    422     u32 leftNotLoaded, rightNotLoaded;
    423     u32 leftAvail, rightAvail;
    424 #endif
    425 
    426 #if defined(VERSION_SH) || defined(VERSION_CN)
    427     switch (poolIdx) {
    428         case 0:
    429             arg0 = &gSeqLoadedPool;
    430             table = gSeqLoadStatus;
    431             break;
    432 
    433         case 1:
    434             arg0 = &gBankLoadedPool;
    435             table = gBankLoadStatus;
    436             break;
    437 
    438         case 2:
    439             arg0 = &gUnusedLoadedPool;
    440             table = gUnkLoadStatus;
    441             break;
    442     }
    443 #endif
    444 
    445     if (arg3 == 0) {
    446         tp = &arg0->temporary;
    447 #if !defined(VERSION_SH) && !defined(VERSION_CN)
    448         if (arg0 == &gSeqLoadedPool) {
    449             table = gSeqLoadStatus;
    450             isSound = FALSE;
    451         } else if (arg0 == &gBankLoadedPool) {
    452             table = gBankLoadStatus;
    453             isSound = TRUE;
    454         }
    455 #endif
    456 
    457 #if defined(VERSION_SH) || defined(VERSION_CN)
    458         if (tp->entries[0].id == (s8)nullID) {
    459             firstVal = SOUND_LOAD_STATUS_NOT_LOADED;
    460         } else {
    461             firstVal = table[tp->entries[0].id];
    462         }
    463         if (tp->entries[1].id == (s8)nullID) {
    464             secondVal = SOUND_LOAD_STATUS_NOT_LOADED;
    465         } else {
    466             secondVal = table[tp->entries[1].id];
    467         }
    468 #else
    469         firstVal  = (tp->entries[0].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[0].id]);
    470         secondVal = (tp->entries[1].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[1].id]);
    471 #endif
    472 
    473 #if defined(VERSION_JP) || defined(VERSION_US)
    474         leftNotLoaded = (firstVal == SOUND_LOAD_STATUS_NOT_LOADED);
    475         leftDiscardable = (firstVal == SOUND_LOAD_STATUS_DISCARDABLE);
    476         leftAvail = (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS);
    477         rightNotLoaded = (secondVal == SOUND_LOAD_STATUS_NOT_LOADED);
    478         rightDiscardable = (secondVal == SOUND_LOAD_STATUS_DISCARDABLE);
    479         rightAvail = (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS);
    480         bothDiscardable = (leftDiscardable && rightDiscardable);
    481 
    482         if (leftNotLoaded) {
    483             tp->nextSide = 0;
    484         } else if (rightNotLoaded) {
    485             tp->nextSide = 1;
    486         } else if (bothDiscardable) {
    487             // Use the opposite side from last time.
    488         } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { // ??! (I blame copt)
    489             tp->nextSide = 0;
    490         } else if (rightDiscardable) {
    491             tp->nextSide = 1;
    492         } else if (leftAvail) {
    493             tp->nextSide = 0;
    494         } else if (rightAvail) {
    495             tp->nextSide = 1;
    496         } else {
    497             // Both left and right sides are being loaded into.
    498             return NULL;
    499         }
    500 #else
    501 #ifdef VERSION_EU
    502         if (0) {
    503             // It's unclear where these string literals go.
    504             eu_stubbed_printf_0("DataHeap Not Allocate \n");
    505             eu_stubbed_printf_1("StayHeap Not Allocate %d\n", 0);
    506             eu_stubbed_printf_1("AutoHeap Not Allocate %d\n", 0);
    507         }
    508 #endif
    509 
    510 #if defined(VERSION_SH) || defined(VERSION_CN)
    511         if (poolIdx == 1) {
    512             if (firstVal == SOUND_LOAD_STATUS_4) {
    513                 for (i = 0; i < gMaxSimultaneousNotes; i++) {
    514                     if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) {
    515                         break;
    516                     }
    517                 }
    518                 if (i == gMaxSimultaneousNotes) {
    519                     if (gBankLoadStatus[tp->entries[0].id] != SOUND_LOAD_STATUS_5) {
    520                         gBankLoadStatus[tp->entries[0].id] = SOUND_LOAD_STATUS_DISCARDABLE;
    521                     }
    522                     firstVal = SOUND_LOAD_STATUS_DISCARDABLE;
    523                 }
    524             }
    525             if (secondVal == SOUND_LOAD_STATUS_4) {
    526                 for (i = 0; i < gMaxSimultaneousNotes; i++) {
    527                     if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) {
    528                         break;
    529                     }
    530                 }
    531                 if (i == gMaxSimultaneousNotes) {
    532                     if (gBankLoadStatus[tp->entries[1].id] != SOUND_LOAD_STATUS_5) {
    533                         gBankLoadStatus[tp->entries[1].id] = SOUND_LOAD_STATUS_DISCARDABLE;
    534                     }
    535                     secondVal = SOUND_LOAD_STATUS_DISCARDABLE;
    536                 }
    537             }
    538         }
    539 #endif
    540 
    541         if (firstVal == SOUND_LOAD_STATUS_NOT_LOADED) {
    542             tp->nextSide = 0;
    543         } else if (secondVal == SOUND_LOAD_STATUS_NOT_LOADED) {
    544             tp->nextSide = 1;
    545         } else {
    546             eu_stubbed_printf_0("WARNING: NO FREE AUTOSEQ AREA.\n");
    547             if ((firstVal == SOUND_LOAD_STATUS_DISCARDABLE) && (secondVal == SOUND_LOAD_STATUS_DISCARDABLE)) {
    548                 // Use the opposite side from last time.
    549             } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) {
    550                 tp->nextSide = 0;
    551             } else if (secondVal == SOUND_LOAD_STATUS_DISCARDABLE) {
    552                 tp->nextSide = 1;
    553             } else {
    554 #ifdef VERSION_EU
    555                 eu_stubbed_printf_0("WARNING: NO STOP AUTO AREA.\n");
    556                 eu_stubbed_printf_0("         AND TRY FORCE TO STOP SIDE \n");
    557                 if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
    558                     tp->nextSide = 0;
    559                 } else if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
    560                     tp->nextSide = 1;
    561                 } else {
    562                     // Both left and right sides are being loaded into.
    563                     eu_stubbed_printf_0("TWO SIDES ARE LOADING... ALLOC CANCELED.\n");
    564                     return NULL;
    565                 }
    566 #else
    567                 if (poolIdx == 0) {
    568                     if (firstVal == SOUND_LOAD_STATUS_COMPLETE) {
    569                         for (i = 0; i < SEQUENCE_PLAYERS; i++) {
    570                             if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[0].id) {
    571                                 break;
    572                             }
    573                         }
    574                         if (i == SEQUENCE_PLAYERS) {
    575                             tp->nextSide = 0;
    576                             goto out;
    577                         }
    578                     }
    579                     if (secondVal == SOUND_LOAD_STATUS_COMPLETE) {
    580                         for (i = 0; i < SEQUENCE_PLAYERS; i++) {
    581                             if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[1].id) {
    582                                 break;
    583                             }
    584                         }
    585                         if (i == SEQUENCE_PLAYERS) {
    586                             tp->nextSide = 1;
    587                             goto out;
    588                         }
    589                     }
    590                 } else if (poolIdx == 1) {
    591                     if (firstVal == SOUND_LOAD_STATUS_COMPLETE) {
    592                         for (i = 0; i < gMaxSimultaneousNotes; i++) {
    593                             if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) {
    594                                 break;
    595                             }
    596                         }
    597                         if (i == gMaxSimultaneousNotes) {
    598                             tp->nextSide = 0;
    599                             goto out;
    600                         }
    601                     }
    602                     if (secondVal == SOUND_LOAD_STATUS_COMPLETE) {
    603                         for (i = 0; i < gMaxSimultaneousNotes; i++) {
    604                             if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) {
    605                                 break;
    606                             }
    607                         }
    608                         if (i == gMaxSimultaneousNotes) {
    609                             tp->nextSide = 1;
    610                             goto out;
    611                         }
    612                     }
    613                 }
    614                 if (tp->nextSide == 0) {
    615                     if (firstVal == SOUND_LOAD_STATUS_IN_PROGRESS) {
    616                         if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
    617                             tp->nextSide = 1;
    618                             goto out;
    619                         }
    620                     } else {
    621                         goto out;
    622                     }
    623                 } else {
    624                     if (secondVal == SOUND_LOAD_STATUS_IN_PROGRESS) {
    625                         if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
    626                             tp->nextSide = 0;
    627                             goto out;
    628                         }
    629                     } else {
    630                         goto out;
    631                     }
    632                 }
    633                 return NULL;
    634                 out:;
    635 #endif
    636             }
    637         }
    638 #endif
    639 
    640         pool = &arg0->temporary.pool;
    641         if (tp->entries[tp->nextSide].id != (s8)nullID) {
    642             table[tp->entries[tp->nextSide].id] = SOUND_LOAD_STATUS_NOT_LOADED;
    643             if (isSound == TRUE) {
    644                 discard_bank(tp->entries[tp->nextSide].id);
    645             }
    646         }
    647 
    648         switch (tp->nextSide) {
    649             case 0:
    650                 tp->entries[0].ptr = pool->start;
    651                 tp->entries[0].id = id;
    652                 tp->entries[0].size = size;
    653 
    654                 pool->cur = pool->start + size;
    655 
    656 #if defined(VERSION_SH) || defined(VERSION_CN)
    657                 if (tp->entries[1].id != (s32)nullID)
    658 #endif
    659                 if (tp->entries[1].ptr < pool->cur) {
    660                     eu_stubbed_printf_0("WARNING: Before Area Overlaid After.");
    661 
    662                     // Throw out the entry on the other side if it doesn't fit.
    663                     // (possible @bug: what if it's currently being loaded?)
    664                     table[tp->entries[1].id] = SOUND_LOAD_STATUS_NOT_LOADED;
    665 
    666                     switch (isSound) {
    667                         case FALSE:
    668                             discard_sequence(tp->entries[1].id);
    669                             break;
    670                         case TRUE:
    671                             discard_bank(tp->entries[1].id);
    672                             break;
    673                     }
    674 
    675                     tp->entries[1].id = (s32)nullID;
    676 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    677                     tp->entries[1].ptr = pool->start + pool->size;
    678 #else
    679                     tp->entries[1].ptr = pool->size + pool->start;
    680 #endif
    681                 }
    682 
    683                 ret = tp->entries[0].ptr;
    684                 break;
    685 
    686             case 1:
    687 #if defined(VERSION_SH) || defined(VERSION_CN)
    688                 tp->entries[1].ptr = (u8 *) ((uintptr_t) (pool->start + pool->size - size) & ~0x0f);
    689 #elif defined(VERSION_EU)
    690                 tp->entries[1].ptr = pool->start + pool->size - size - 0x10;
    691 #else
    692                 tp->entries[1].ptr = pool->size + pool->start - size - 0x10;
    693 #endif
    694                 tp->entries[1].id = id;
    695                 tp->entries[1].size = size;
    696 
    697 #if defined(VERSION_SH) || defined(VERSION_CN)
    698                 if (tp->entries[0].id != (s32)nullID)
    699 #endif
    700                 if (tp->entries[1].ptr < pool->cur) {
    701                     eu_stubbed_printf_0("WARNING: After Area Overlaid Before.");
    702 
    703                     table[tp->entries[0].id] = SOUND_LOAD_STATUS_NOT_LOADED;
    704 
    705                     switch (isSound) {
    706                         case FALSE:
    707                             discard_sequence(tp->entries[0].id);
    708                             break;
    709                         case TRUE:
    710                             discard_bank(tp->entries[0].id);
    711                             break;
    712                     }
    713 
    714                     tp->entries[0].id = (s32)nullID;
    715                     pool->cur = pool->start;
    716                 }
    717 
    718                 ret = tp->entries[1].ptr;
    719                 break;
    720 
    721             default:
    722                 eu_stubbed_printf_1("MEMORY:SzHeapAlloc ERROR: sza->side %d\n", tp->nextSide);
    723                 return NULL;
    724         }
    725 
    726         // Switch sides for next time in case both entries are
    727         // SOUND_LOAD_STATUS_DISCARDABLE.
    728         tp->nextSide ^= 1;
    729 
    730         return ret;
    731     }
    732 
    733 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    734 #if defined(VERSION_SH) || defined(VERSION_CN)
    735     ret = sound_alloc_uninitialized(&arg0->persistent.pool, size);
    736 #else
    737     ret = soundAlloc(&arg0->persistent.pool, arg1 * size);
    738 #endif
    739     arg0->persistent.entries[arg0->persistent.numEntries].ptr = ret;
    740 
    741     if (ret == NULL)
    742 #else
    743     arg0->persistent.entries[arg0->persistent.numEntries].ptr = soundAlloc(&arg0->persistent.pool, arg1 * size);
    744 
    745     if (arg0->persistent.entries[arg0->persistent.numEntries].ptr == NULL)
    746 #endif
    747     {
    748         switch (arg3) {
    749             case 2:
    750 #if defined(VERSION_EU)
    751                 eu_stubbed_printf_0("MEMORY:StayHeap OVERFLOW.");
    752                 return alloc_bank_or_seq(arg0, arg1, size, 0, id);
    753 #elif defined(VERSION_SH) || defined(VERSION_CN)
    754                 return alloc_bank_or_seq(poolIdx, size, 0, id);
    755 #else
    756                 // Prevent tail call optimization.
    757                 ret = alloc_bank_or_seq(arg0, arg1, size, 0, id);
    758                 return ret;
    759 #endif
    760             case 1:
    761 #if defined(VERSION_SH) || defined(VERSION_CN)
    762             case 0:
    763 #endif
    764                 eu_stubbed_printf_1("MEMORY:StayHeap OVERFLOW (REQ:%d)", arg1 * size);
    765                 return NULL;
    766         }
    767     }
    768 
    769     // TODO: why is this guaranteed to write <= 32 entries...?
    770     // Because the buffer is small enough that more don't fit?
    771     arg0->persistent.entries[arg0->persistent.numEntries].id = id;
    772     arg0->persistent.entries[arg0->persistent.numEntries].size = size;
    773 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    774     return arg0->persistent.entries[arg0->persistent.numEntries++].ptr;
    775 #else
    776     arg0->persistent.numEntries++; return arg0->persistent.entries[arg0->persistent.numEntries - 1].ptr;
    777 #endif
    778 #if defined(VERSION_SH) || defined(VERSION_CN)
    779 #undef isSound
    780 #endif
    781 }
    782 
    783 #if defined(VERSION_SH) || defined(VERSION_CN)
    784 void *get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id) {
    785     void *ret;
    786 
    787     ret = unk_pool1_lookup(poolIdx, id);
    788     if (ret != NULL) {
    789         return ret;
    790     }
    791     if (arg1 == 3) {
    792         return NULL;
    793     }
    794     return get_bank_or_seq_inner(poolIdx, arg1, id);
    795 }
    796 void *get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId) {
    797     u32 i;
    798     struct SoundMultiPool* loadedPool;
    799     struct TemporaryPool* temporary;
    800     struct PersistentPool* persistent;
    801 
    802     switch (poolIdx) {
    803         case 0:
    804             loadedPool = &gSeqLoadedPool;
    805             break;
    806         case 1:
    807             loadedPool = &gBankLoadedPool;
    808             break;
    809         case 2:
    810             loadedPool = &gUnusedLoadedPool;
    811             break;
    812     }
    813 
    814     temporary = &loadedPool->temporary;
    815     if (arg1 == 0) {
    816         if (temporary->entries[0].id == bankId) {
    817             temporary->nextSide = 1;
    818             return temporary->entries[0].ptr;
    819         } else if (temporary->entries[1].id == bankId) {
    820             temporary->nextSide = 0;
    821             return temporary->entries[1].ptr;
    822         } else {
    823             return NULL;
    824         }
    825     }
    826 
    827     persistent = &loadedPool->persistent;
    828     for (i = 0; i < persistent->numEntries; i++) {
    829         if (persistent->entries[i].id == bankId) {
    830             return persistent->entries[i].ptr;
    831         }
    832     }
    833 
    834     if (arg1 == 2) {
    835         return get_bank_or_seq(poolIdx, 0, bankId);
    836     }
    837     return NULL;
    838 }
    839 #endif
    840 #if !defined(VERSION_SH) && !defined(VERSION_CN)
    841 void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) {
    842     u32 i;
    843     UNUSED void *ret;
    844     struct TemporaryPool *temporary = &arg0->temporary;
    845 
    846     if (arg1 == 0) {
    847         // Try not to overwrite sound that we have just accessed, by setting nextSide appropriately.
    848         if (temporary->entries[0].id == id) {
    849             temporary->nextSide = 1;
    850             return temporary->entries[0].ptr;
    851         } else if (temporary->entries[1].id == id) {
    852             temporary->nextSide = 0;
    853             return temporary->entries[1].ptr;
    854         }
    855         eu_stubbed_printf_1("Auto Heap Unhit for ID %d\n", id);
    856         return NULL;
    857     } else {
    858         struct PersistentPool *persistent = &arg0->persistent;
    859         for (i = 0; i < persistent->numEntries; i++) {
    860             if (id == persistent->entries[i].id) {
    861                 eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i);
    862                 return persistent->entries[i].ptr;
    863             }
    864         }
    865 
    866         if (arg1 == 2) {
    867 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    868             return get_bank_or_seq(arg0, 0, id);
    869 #else
    870             // Prevent tail call optimization by using a temporary.
    871             // Either copt or -Wo,-notail.
    872             ret = get_bank_or_seq(arg0, 0, id);
    873             return ret;
    874 #endif
    875         }
    876         return NULL;
    877     }
    878 }
    879 #endif
    880 
    881 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    882 void func_eu_802e27e4_unused(f32 arg0, f32 arg1, u16 *arg2) {
    883     s32 i;
    884     f32 tmp[16];
    885 
    886     tmp[0] = (f32) (arg1 * 262159.0f);
    887     tmp[8] = (f32) (arg0 * 262159.0f);
    888     tmp[1] = (f32) ((arg1 * arg0) * 262159.0f);
    889     tmp[9] = (f32) (((arg0 * arg0) + arg1) * 262159.0f);
    890 
    891     for (i = 2; i < 8; i++) {
    892         //! @bug they probably meant to store the value to tmp[i] and tmp[8 + i]
    893         arg2[i] = arg1 * tmp[i - 2] + arg0 * tmp[i - 1];
    894         arg2[8 + i] = arg1 * tmp[6 + i] + arg0 * tmp[7 + i];
    895     }
    896 
    897     for (i = 0; i < 16; i++) {
    898         arg2[i] = tmp[i];
    899     }
    900 
    901 #ifdef VERSION_EU
    902     for (i = 0; i < 8; i++) {
    903         eu_stubbed_printf_1("%d ", arg2[i]);
    904     }
    905     eu_stubbed_printf_0("\n");
    906 
    907     for (i = 8; i < 16; i++) {
    908         eu_stubbed_printf_1("%d ", arg2[i]);
    909     }
    910     eu_stubbed_printf_0("\n");
    911 #endif
    912 }
    913 #endif
    914 
    915 #if defined(VERSION_SH) || defined(VERSION_CN)
    916 void fill_zero_filter(s16 filter[]) {
    917     s32 i;
    918     for (i = 0; i < 8; i++) {
    919         filter[i] = 0;
    920     }
    921 }
    922 
    923 extern s16 unk_sh_data_3[15 * 8];
    924 extern s16 unk_sh_data_4[15 * 8];
    925 void func_sh_802F0DE8(s16 filter[8], s32 arg1) {
    926     s32 i;
    927     s16 *ptr = &unk_sh_data_3[8 * (arg1 - 1)];
    928     for (i = 0; i < 8; i++) {
    929         filter[i] = ptr[i];
    930     }
    931 }
    932 
    933 void func_sh_802F0E40(s16 filter[8], s32 arg1) { // Unused
    934     s32 i;
    935     s16 *ptr = &unk_sh_data_4[8 * (arg1 - 1)];
    936     for (i = 0; i < 8; i++) {
    937         filter[i] = ptr[i];
    938     }
    939 }
    940 
    941 void fill_filter(s16 filter[8], s32 arg1, s32 arg2) {
    942     s32 i;
    943     s16 *ptr;
    944     if (arg1 != 0) {
    945         func_sh_802F0DE8(filter, arg1);
    946     } else {
    947         fill_zero_filter(filter);
    948     }
    949     if (arg2 != 0) {
    950         ptr = &unk_sh_data_4[8 * (arg2 - 1)];
    951         for (i = 0; i < 8; i++) {
    952             filter[i] += ptr[i];
    953         }
    954     }
    955 }
    956 #endif
    957 
    958 void decrease_reverb_gain(void) {
    959 #if defined(VERSION_EU)
    960     s32 i;
    961     for (i = 0; i < gNumSynthesisReverbs; i++) {
    962         gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 8;
    963     }
    964 #elif defined(VERSION_JP) || defined(VERSION_US)
    965     gSynthesisReverb.reverbGain -= gSynthesisReverb.reverbGain / 4;
    966 #else
    967     s32 i, j;
    968     s32 v0 = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1;
    969     for (i = 0; i < gNumSynthesisReverbs; i++) {
    970         for (j = 0; j < v0; j++) {
    971             gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 3;
    972         }
    973     }
    974 #endif
    975 }
    976 
    977 #if defined(VERSION_SH) || defined(VERSION_CN)
    978 void clear_curr_ai_buffer(void) {
    979     s32 currIndex = gCurrAiBufferIndex;
    980     s32 i;
    981     gAiBufferLengths[currIndex] = gAudioBufferParameters.minAiBufferLength;
    982     for (i = 0; i < (s32) (AIBUFFER_LEN / sizeof(s16)); i++) {
    983         gAiBuffers[currIndex][i] = 0;
    984     }
    985 }
    986 #endif
    987 
    988 
    989 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    990 s32 audio_shut_down_and_reset_step(void) {
    991     s32 i;
    992     s32 j;
    993 #if defined(VERSION_SH) || defined(VERSION_CN)
    994     s32 num = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1;
    995 #endif
    996 
    997     switch (gAudioResetStatus) {
    998         case 5:
    999             for (i = 0; i < SEQUENCE_PLAYERS; i++) {
   1000                 sequence_player_disable(&gSequencePlayers[i]);
   1001             }
   1002 #if defined(VERSION_SH) || defined(VERSION_CN)
   1003             gAudioResetFadeOutFramesLeft = 4 / num;
   1004 #else
   1005             gAudioResetFadeOutFramesLeft = 4;
   1006 #endif
   1007             gAudioResetStatus--;
   1008             break;
   1009         case 4:
   1010             if (gAudioResetFadeOutFramesLeft != 0) {
   1011                 gAudioResetFadeOutFramesLeft--;
   1012                 decrease_reverb_gain();
   1013             } else {
   1014                 for (i = 0; i < gMaxSimultaneousNotes; i++) {
   1015                     if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) {
   1016                         gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv;
   1017                         gNotes[i].adsr.action |= ADSR_ACTION_RELEASE;
   1018                     }
   1019                 }
   1020 #if defined(VERSION_SH) || defined(VERSION_CN)
   1021                 gAudioResetFadeOutFramesLeft = 16 / num;
   1022 #else
   1023                 gAudioResetFadeOutFramesLeft = 16;
   1024 #endif
   1025                 gAudioResetStatus--;
   1026             }
   1027             break;
   1028         case 3:
   1029             if (gAudioResetFadeOutFramesLeft != 0) {
   1030                 gAudioResetFadeOutFramesLeft--;
   1031 #if defined(VERSION_SH) || defined(VERSION_CN)
   1032                 if (1) {
   1033                 }
   1034 #endif
   1035                 decrease_reverb_gain();
   1036             } else {
   1037                 for (i = 0; i < NUMAIBUFFERS; i++) {
   1038                     for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) {
   1039                         gAiBuffers[i][j] = 0;
   1040                     }
   1041                 }
   1042 #if defined(VERSION_SH) || defined(VERSION_CN)
   1043                 gAudioResetFadeOutFramesLeft = 4 / num;
   1044 #else
   1045                 gAudioResetFadeOutFramesLeft = 4;
   1046 #endif
   1047                 gAudioResetStatus--;
   1048             }
   1049             break;
   1050         case 2:
   1051 #if defined(VERSION_SH) || defined(VERSION_CN)
   1052             clear_curr_ai_buffer();
   1053 #endif
   1054             if (gAudioResetFadeOutFramesLeft != 0) {
   1055                 gAudioResetFadeOutFramesLeft--;
   1056             } else {
   1057                 gAudioResetStatus--;
   1058 #if defined(VERSION_SH) || defined(VERSION_CN)
   1059                 func_sh_802f23ec();
   1060 #endif
   1061             }
   1062             break;
   1063         case 1:
   1064             audio_reset_session();
   1065             gAudioResetStatus = 0;
   1066 #if defined(VERSION_SH) || defined(VERSION_CN)
   1067             for (i = 0; i < NUMAIBUFFERS; i++) {
   1068                 gAiBufferLengths[i] = gAudioBufferParameters.maxAiBufferLength;
   1069                 for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) {
   1070                     gAiBuffers[i][j] = 0;
   1071                 }
   1072             }
   1073 #endif
   1074     }
   1075 #if defined(VERSION_SH) || defined(VERSION_CN)
   1076     if (gAudioResetFadeOutFramesLeft) {
   1077     }
   1078 #endif
   1079     if (gAudioResetStatus < 3) {
   1080         return 0;
   1081     }
   1082     return 1;
   1083 }
   1084 #else
   1085 /**
   1086  * Waits until a specified number of audio frames have been created
   1087  */
   1088 void wait_for_audio_frames(s32 frames) {
   1089     gAudioFrameCount = 0;
   1090     // Sound thread will update gAudioFrameCount
   1091     while (gAudioFrameCount < frames) {
   1092         // spin
   1093     }
   1094 }
   1095 #endif
   1096 
   1097 #if defined(VERSION_JP) || defined(VERSION_US)
   1098 void audio_reset_session(struct AudioSessionSettings *preset) {
   1099 #else
   1100 void audio_reset_session(void) {
   1101     struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[gAudioResetPresetIdToLoad];
   1102     struct ReverbSettingsEU *reverbSettings;
   1103 #endif
   1104     s16 *mem;
   1105 #if defined(VERSION_JP) || defined(VERSION_US)
   1106     s8 updatesPerFrame;
   1107     s32 reverbWindowSize;
   1108     s32 k;
   1109 #endif
   1110     s32 i;
   1111     s32 j;
   1112     s32 persistentMem;
   1113     s32 temporaryMem;
   1114     s32 totalMem;
   1115     s32 wantMisc;
   1116 #if defined(VERSION_JP) || defined(VERSION_US)
   1117     s32 frames;
   1118     s32 remainingDmas;
   1119 #else
   1120     struct SynthesisReverb *reverb;
   1121 #endif
   1122     eu_stubbed_printf_1("Heap Reconstruct Start %x\n", gAudioResetPresetIdToLoad);
   1123 
   1124 #if defined(VERSION_JP) || defined(VERSION_US)
   1125     if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) {
   1126         decrease_reverb_gain();
   1127         for (i = 0; i < gMaxSimultaneousNotes; i++) {
   1128             if (gNotes[i].enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) {
   1129                 gNotes[i].adsr.fadeOutVel = 0x8000 / gAudioUpdatesPerFrame;
   1130                 gNotes[i].adsr.action |= ADSR_ACTION_RELEASE;
   1131             }
   1132         }
   1133 
   1134         // Wait for all notes to stop playing
   1135         frames = 0;
   1136         for (;;) {
   1137             wait_for_audio_frames(1);
   1138             frames++;
   1139             if (frames > 4 * 60) {
   1140                 // Break after 4 seconds
   1141                 break;
   1142             }
   1143 
   1144             for (i = 0; i < gMaxSimultaneousNotes; i++) {
   1145                 if (gNotes[i].enabled) {
   1146                     break;
   1147                 }
   1148             }
   1149 
   1150             if (i == gMaxSimultaneousNotes) {
   1151                 // All zero, break early
   1152                 break;
   1153             }
   1154         }
   1155 
   1156         // Wait for the reverb to finish as well
   1157         decrease_reverb_gain();
   1158         wait_for_audio_frames(3);
   1159 
   1160         // The audio interface is double buffered; thus, we have to take the
   1161         // load lock for 2 frames for the buffers to free up before we can
   1162         // repurpose memory. Make that 3 frames, just in case.
   1163         gAudioLoadLock = AUDIO_LOCK_LOADING;
   1164         wait_for_audio_frames(3);
   1165 
   1166         remainingDmas = gCurrAudioFrameDmaCount;
   1167         while (remainingDmas > 0) {
   1168             for (i = 0; i < gCurrAudioFrameDmaCount; i++) {
   1169                 if (osRecvMesg(&gCurrAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK) == 0)
   1170                     remainingDmas--;
   1171             }
   1172         }
   1173         gCurrAudioFrameDmaCount = 0;
   1174 
   1175         for (j = 0; j < NUMAIBUFFERS; j++) {
   1176             for (k = 0; k < (s32) (AIBUFFER_LEN / sizeof(s16)); k++) {
   1177                 gAiBuffers[j][k] = 0;
   1178             }
   1179         }
   1180     }
   1181 #endif
   1182 
   1183     gSampleDmaNumListItems = 0;
   1184 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1185     gAudioBufferParameters.frequency = preset->frequency;
   1186     gAudioBufferParameters.aiFrequency = osAiSetFrequency(gAudioBufferParameters.frequency);
   1187     gAudioBufferParameters.samplesPerFrameTarget = ALIGN16(gAudioBufferParameters.frequency / gRefreshRate);
   1188     gAudioBufferParameters.minAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget - 0x10;
   1189     gAudioBufferParameters.maxAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget + 0x10;
   1190 #if defined(VERSION_SH) || defined(VERSION_CN)
   1191     gAudioBufferParameters.updatesPerFrame = (gAudioBufferParameters.samplesPerFrameTarget + 0x10) / 192 + 1;
   1192     gAudioBufferParameters.samplesPerUpdate = (gAudioBufferParameters.samplesPerFrameTarget / gAudioBufferParameters.updatesPerFrame) & -8;
   1193 #else
   1194     gAudioBufferParameters.updatesPerFrame = (gAudioBufferParameters.samplesPerFrameTarget + 0x10) / 160 + 1;
   1195     gAudioBufferParameters.samplesPerUpdate = (gAudioBufferParameters.samplesPerFrameTarget / gAudioBufferParameters.updatesPerFrame) & 0xfff8;
   1196 #endif
   1197     gAudioBufferParameters.samplesPerUpdateMax = gAudioBufferParameters.samplesPerUpdate + 8;
   1198     gAudioBufferParameters.samplesPerUpdateMin = gAudioBufferParameters.samplesPerUpdate - 8;
   1199     gAudioBufferParameters.resampleRate = 32000.0f / FLOAT_CAST(gAudioBufferParameters.frequency);
   1200 #if defined(VERSION_SH) || defined(VERSION_CN)
   1201     gAudioBufferParameters.unkUpdatesPerFrameScaled = (1.0f / 256.0f) / gAudioBufferParameters.updatesPerFrame;
   1202 #else
   1203     gAudioBufferParameters.unkUpdatesPerFrameScaled = (3.0f / 1280.0f) / gAudioBufferParameters.updatesPerFrame;
   1204 #endif
   1205     gAudioBufferParameters.updatesPerFrameInv = 1.0f / gAudioBufferParameters.updatesPerFrame;
   1206 
   1207     gMaxSimultaneousNotes = preset->maxSimultaneousNotes;
   1208     gVolume = preset->volume;
   1209     gTempoInternalToExternal = (u32) (gAudioBufferParameters.updatesPerFrame * 2880000.0f / gTatumsPerBeat / D_EU_802298D0);
   1210 
   1211     gAudioBufferParameters.presetUnk4 = preset->unk1;
   1212     gAudioBufferParameters.samplesPerFrameTarget *= gAudioBufferParameters.presetUnk4;
   1213     gAudioBufferParameters.maxAiBufferLength *= gAudioBufferParameters.presetUnk4;
   1214     gAudioBufferParameters.minAiBufferLength *= gAudioBufferParameters.presetUnk4;
   1215     gAudioBufferParameters.updatesPerFrame *= gAudioBufferParameters.presetUnk4;
   1216 
   1217 #if defined(VERSION_SH) || defined(VERSION_CN)
   1218     if (gAudioBufferParameters.presetUnk4 >= 2) {
   1219         gAudioBufferParameters.maxAiBufferLength -= 0x10;
   1220     }
   1221     gMaxAudioCmds = gMaxSimultaneousNotes * 0x14 * gAudioBufferParameters.updatesPerFrame + preset->numReverbs * 0x20 + 0x1E0;
   1222 #else
   1223     gMaxAudioCmds = gMaxSimultaneousNotes * 0x10 * gAudioBufferParameters.updatesPerFrame + preset->numReverbs * 0x20 + 0x300;
   1224 #endif
   1225 #else
   1226     reverbWindowSize = preset->reverbWindowSize;
   1227     gAiFrequency = osAiSetFrequency(preset->frequency);
   1228     gMaxSimultaneousNotes = preset->maxSimultaneousNotes;
   1229     gSamplesPerFrameTarget = ALIGN16(gAiFrequency / 60);
   1230     gReverbDownsampleRate = preset->reverbDownsampleRate;
   1231 
   1232     switch (gReverbDownsampleRate) {
   1233         case 1:
   1234             sReverbDownsampleRateLog = 0;
   1235             break;
   1236         case 2:
   1237             sReverbDownsampleRateLog = 1;
   1238             break;
   1239         case 4:
   1240             sReverbDownsampleRateLog = 2;
   1241             break;
   1242         case 8:
   1243             sReverbDownsampleRateLog = 3;
   1244             break;
   1245         case 16:
   1246             sReverbDownsampleRateLog = 4;
   1247             break;
   1248         default:
   1249             sReverbDownsampleRateLog = 0;
   1250     }
   1251 
   1252     gReverbDownsampleRate = preset->reverbDownsampleRate;
   1253     gVolume = preset->volume;
   1254     gMinAiBufferLength = gSamplesPerFrameTarget - 0x10;
   1255     updatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
   1256     gAudioUpdatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
   1257 
   1258     // Compute conversion ratio from the internal unit tatums/tick to the
   1259     // external beats/minute (JP) or tatums/minute (US). In practice this is
   1260     // 300 on JP and 14360 on US.
   1261 #ifdef VERSION_JP
   1262     gTempoInternalToExternal = updatesPerFrame * 3600 / gTatumsPerBeat;
   1263 #else
   1264     gTempoInternalToExternal = (u32)(updatesPerFrame * 2880000.0f / gTatumsPerBeat / 16.713f);
   1265 #endif
   1266     gMaxAudioCmds = gMaxSimultaneousNotes * 20 * updatesPerFrame + 320;
   1267 #endif
   1268 
   1269 #if defined(VERSION_SH) || defined(VERSION_CN)
   1270     persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem + preset->persistentBankMem + preset->unk18 + preset->unkMem28 + 0x10);
   1271     temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem + preset->temporaryBankMem + preset->unk24 + preset->unkMem2C + 0x10);
   1272 #elif defined(VERSION_EU)
   1273     persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem + preset->persistentBankMem);
   1274     temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem + preset->temporaryBankMem);
   1275 #else
   1276     persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentBankMem + preset->persistentSeqMem);
   1277     temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporaryBankMem + preset->temporarySeqMem);
   1278 #endif
   1279     totalMem = persistentMem + temporaryMem;
   1280     wantMisc = gAudioSessionPool.size - totalMem - 0x100;
   1281     sSessionPoolSplit.wantSeq = wantMisc;
   1282     sSessionPoolSplit.wantCustom = totalMem;
   1283     session_pools_init(&sSessionPoolSplit);
   1284     sSeqAndBankPoolSplit.wantPersistent = persistentMem;
   1285     sSeqAndBankPoolSplit.wantTemporary = temporaryMem;
   1286     seq_and_bank_pool_init(&sSeqAndBankPoolSplit);
   1287     sPersistentCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem);
   1288     sPersistentCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(preset->persistentBankMem);
   1289 #if defined(VERSION_SH) || defined(VERSION_CN)
   1290     sPersistentCommonPoolSplit.wantUnused = preset->unk18;
   1291 #else
   1292     sPersistentCommonPoolSplit.wantUnused = 0;
   1293 #endif
   1294     persistent_pools_init(&sPersistentCommonPoolSplit);
   1295     sTemporaryCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem);
   1296     sTemporaryCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(preset->temporaryBankMem);
   1297 #if defined(VERSION_SH) || defined(VERSION_CN)
   1298     sTemporaryCommonPoolSplit.wantUnused = preset->unk24;
   1299 #else
   1300     sTemporaryCommonPoolSplit.wantUnused = 0;
   1301 #endif
   1302     temporary_pools_init(&sTemporaryCommonPoolSplit);
   1303 #if defined(VERSION_SH) || defined(VERSION_CN)
   1304     unk_pools_init(preset->unkMem28, preset->unkMem2C);
   1305 #endif
   1306     reset_bank_and_seq_load_status();
   1307 
   1308 #if defined(VERSION_JP) || defined(VERSION_US)
   1309     for (j = 0; j < 2; j++) {
   1310         gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64));
   1311     }
   1312 #endif
   1313 
   1314     gNotes = soundAlloc(&gNotesAndBuffersPool, gMaxSimultaneousNotes * sizeof(struct Note));
   1315     note_init_all();
   1316     init_note_free_list();
   1317 
   1318 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1319     gNoteSubsEu = soundAlloc(&gNotesAndBuffersPool, (gAudioBufferParameters.updatesPerFrame * gMaxSimultaneousNotes) * sizeof(struct NoteSubEu));
   1320 
   1321     for (j = 0; j != 2; j++) {
   1322         gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64));
   1323     }
   1324 
   1325     for (j = 0; j < 4; j++) {
   1326         gSynthesisReverbs[j].useReverb = 0;
   1327     }
   1328     gNumSynthesisReverbs = preset->numReverbs;
   1329     for (j = 0; j < gNumSynthesisReverbs; j++) {
   1330         reverb = &gSynthesisReverbs[j];
   1331         reverbSettings = &preset->reverbSettings[j];
   1332 #if defined(VERSION_SH) || defined(VERSION_CN)
   1333         reverb->downsampleRate = reverbSettings->downsampleRate;
   1334         reverb->windowSize = reverbSettings->windowSize * 64;
   1335         reverb->windowSize /= reverb->downsampleRate;
   1336 #else
   1337         reverb->windowSize = reverbSettings->windowSize * 64;
   1338         reverb->downsampleRate = reverbSettings->downsampleRate;
   1339 #endif
   1340         reverb->reverbGain = reverbSettings->gain;
   1341 #if defined(VERSION_SH) || defined(VERSION_CN)
   1342         reverb->panRight = reverbSettings->unk4;
   1343         reverb->panLeft = reverbSettings->unk6;
   1344         reverb->unk5 = reverbSettings->unk8;
   1345         reverb->unk08 = reverbSettings->unkA;
   1346 #endif
   1347         reverb->useReverb = 8;
   1348         reverb->ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2);
   1349         reverb->ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2);
   1350         reverb->nextRingBufferPos = 0;
   1351         reverb->unkC = 0;
   1352         reverb->curFrame = 0;
   1353         reverb->bufSizePerChannel = reverb->windowSize;
   1354         reverb->framesLeftToIgnore = 2;
   1355 #if defined(VERSION_SH) || defined(VERSION_CN)
   1356         reverb->resampleFlags = A_INIT;
   1357 #endif
   1358         if (reverb->downsampleRate != 1) {
   1359 #if !defined(VERSION_SH) && !defined(VERSION_CN)
   1360             reverb->resampleFlags = A_INIT;
   1361 #endif
   1362             reverb->resampleRate = 0x8000 / reverb->downsampleRate;
   1363             reverb->resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1364             reverb->resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1365             reverb->unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1366             reverb->unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1367             for (i = 0; i < gAudioBufferParameters.updatesPerFrame; i++) {
   1368                 mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
   1369                 reverb->items[0][i].toDownsampleLeft = mem;
   1370                 reverb->items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
   1371                 mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
   1372                 reverb->items[1][i].toDownsampleLeft = mem;
   1373                 reverb->items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
   1374             }
   1375         }
   1376 #if defined(VERSION_SH) || defined(VERSION_CN)
   1377         if (reverbSettings->unkC != 0) {
   1378             reverb->unk108 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1379             reverb->unk100 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16));
   1380             func_sh_802F0DE8(reverb->unk100, reverbSettings->unkC);
   1381         } else {
   1382             reverb->unk100 = NULL;
   1383         }
   1384         if (reverbSettings->unkE != 0) {
   1385             reverb->unk10C = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1386             reverb->unk104 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16));
   1387             func_sh_802F0DE8(reverb->unk104, reverbSettings->unkE);
   1388         } else {
   1389             reverb->unk104 = NULL;
   1390         }
   1391 #endif
   1392     }
   1393 
   1394 #else
   1395     if (reverbWindowSize == 0) {
   1396         gSynthesisReverb.useReverb = 0;
   1397     } else {
   1398         gSynthesisReverb.useReverb = 8;
   1399         gSynthesisReverb.ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2);
   1400         gSynthesisReverb.ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2);
   1401         gSynthesisReverb.nextRingBufferPos = 0;
   1402         gSynthesisReverb.unkC = 0;
   1403         gSynthesisReverb.curFrame = 0;
   1404         gSynthesisReverb.bufSizePerChannel = reverbWindowSize;
   1405         gSynthesisReverb.reverbGain = preset->reverbGain;
   1406         gSynthesisReverb.framesLeftToIgnore = 2;
   1407         if (gReverbDownsampleRate != 1) {
   1408             gSynthesisReverb.resampleFlags = A_INIT;
   1409             gSynthesisReverb.resampleRate = 0x8000 / gReverbDownsampleRate;
   1410             gSynthesisReverb.resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1411             gSynthesisReverb.resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1412             gSynthesisReverb.unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1413             gSynthesisReverb.unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
   1414             for (i = 0; i < gAudioUpdatesPerFrame; i++) {
   1415                 mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
   1416                 gSynthesisReverb.items[0][i].toDownsampleLeft = mem;
   1417                 gSynthesisReverb.items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
   1418                 mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
   1419                 gSynthesisReverb.items[1][i].toDownsampleLeft = mem;
   1420                 gSynthesisReverb.items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
   1421             }
   1422         }
   1423     }
   1424 #endif
   1425 
   1426     init_sample_dma_buffers(gMaxSimultaneousNotes);
   1427 
   1428 #if defined(VERSION_EU)
   1429     build_vol_rampings_table(0, gAudioBufferParameters.samplesPerUpdate);
   1430 #endif
   1431 
   1432 #if defined(VERSION_SH) || defined(VERSION_CN)
   1433     D_SH_8034F68C = 0;
   1434     D_SH_803479B4 = 4096;
   1435 #endif
   1436 
   1437     osWritebackDCacheAll();
   1438 
   1439 #if defined(VERSION_JP) || defined(VERSION_US)
   1440     if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) {
   1441         gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
   1442     }
   1443 #endif
   1444 }
   1445 
   1446 #if defined(VERSION_SH) || defined(VERSION_CN)
   1447 void *unk_pool1_lookup(s32 poolIdx, s32 id) {
   1448     s32 i;
   1449 
   1450     for (i = 0; i < gUnkPool1.pool.numAllocatedEntries; i++) {
   1451         if (gUnkPool1.entries[i].poolIndex == poolIdx && gUnkPool1.entries[i].id == id) {
   1452             return gUnkPool1.entries[i].ptr;
   1453         }
   1454     }
   1455     return NULL;
   1456 }
   1457 
   1458 void *unk_pool1_alloc(s32 poolIndex, s32 arg1, u32 size) {
   1459     void *ret;
   1460     s32 pos;
   1461 
   1462     pos = gUnkPool1.pool.numAllocatedEntries;
   1463     ret = sound_alloc_uninitialized(&gUnkPool1.pool, size);
   1464     gUnkPool1.entries[pos].ptr = ret;
   1465     if (ret == NULL) {
   1466         return NULL;
   1467     }
   1468     gUnkPool1.entries[pos].poolIndex = poolIndex;
   1469     gUnkPool1.entries[pos].id = arg1;
   1470     gUnkPool1.entries[pos].size = size;
   1471 
   1472 #ifdef AVOID_UB
   1473     //! @bug UB: missing return. "ret" is in v0 at this point, but doing an
   1474     //  explicit return uses an additional register.
   1475     return ret;
   1476 #endif
   1477 }
   1478 
   1479 u8 *func_sh_802f1d40(u32 size, s32 bank, u8 *arg2, s8 medium) {
   1480     struct UnkEntry *ret;
   1481 
   1482     ret = func_sh_802f1ec4(size);
   1483     if (ret != NULL) {
   1484         ret->bankId = bank;
   1485         ret->dstAddr = arg2;
   1486         ret->medium = medium;
   1487         return ret->srcAddr;
   1488     }
   1489     return NULL;
   1490 }
   1491 u8 *func_sh_802f1d90(u32 size, s32 bank, u8 *arg2, s8 medium) {
   1492     struct UnkEntry *ret;
   1493 
   1494     ret = unk_pool2_alloc(size);
   1495     if (ret != NULL) {
   1496         ret->bankId = bank;
   1497         ret->dstAddr = arg2;
   1498         ret->medium = medium;
   1499         return ret->srcAddr;
   1500     }
   1501     return NULL;
   1502 }
   1503 u8 *func_sh_802f1de0(u32 size, s32 bank, u8 *arg2, s8 medium) { // duplicated function?
   1504     struct UnkEntry *ret;
   1505 
   1506     ret = unk_pool2_alloc(size);
   1507     if (ret != NULL) {
   1508         ret->bankId = bank;
   1509         ret->dstAddr = arg2;
   1510         ret->medium = medium;
   1511         return ret->srcAddr;
   1512     }
   1513     return NULL;
   1514 }
   1515 void unk_pools_init(u32 size1, u32 size2) {
   1516     void *mem;
   1517 
   1518     mem = sound_alloc_uninitialized(&gPersistentCommonPool, size1);
   1519     if (mem == NULL) {
   1520         gUnkPool2.pool.size = 0;
   1521     } else {
   1522         sound_alloc_pool_init(&gUnkPool2.pool, mem, size1);
   1523     }
   1524     mem = sound_alloc_uninitialized(&gTemporaryCommonPool, size2);
   1525 
   1526     if (mem == NULL) {
   1527         gUnkPool3.pool.size = 0;
   1528     } else {
   1529         sound_alloc_pool_init(&gUnkPool3.pool, mem, size2);
   1530     }
   1531 
   1532     gUnkPool2.numEntries = 0;
   1533     gUnkPool3.numEntries = 0;
   1534 }
   1535 
   1536 struct UnkEntry *func_sh_802f1ec4(u32 size) {
   1537     u8 *temp_s2;
   1538     u8 *phi_s3;
   1539     u8 *memLocation;
   1540     u8 *cur;
   1541 
   1542     s32 i;
   1543     s32 chosenIndex;
   1544 
   1545     struct UnkStructSH8034EC88 *unkStruct;
   1546     struct UnkPool *pool = &gUnkPool3;
   1547 
   1548     u8 *itemStart;
   1549     u8 *itemEnd;
   1550 
   1551     phi_s3 = pool->pool.cur;
   1552     memLocation = sound_alloc_uninitialized(&pool->pool, size);
   1553     if (memLocation == NULL) {
   1554         cur = pool->pool.cur;
   1555         pool->pool.cur = pool->pool.start;
   1556         memLocation = sound_alloc_uninitialized(&pool->pool, size);
   1557         if (memLocation == NULL) {
   1558             pool->pool.cur = cur;
   1559             return NULL;
   1560         }
   1561         phi_s3 = pool->pool.start;
   1562     }
   1563     temp_s2 = pool->pool.cur;
   1564 
   1565     chosenIndex = -1;
   1566     for (i = 0; i < D_SH_8034F68C; i++) {
   1567         unkStruct = &D_SH_8034EC88[i];
   1568         if (unkStruct->isFree == FALSE) {
   1569             itemStart = unkStruct->ramAddr;
   1570             itemEnd = unkStruct->ramAddr + unkStruct->sample->size - 1;
   1571             if (itemEnd < phi_s3 && itemStart < phi_s3) {
   1572                 continue;
   1573 
   1574             }
   1575             if (itemEnd >= temp_s2 && itemStart >= temp_s2) {
   1576                 continue;
   1577 
   1578             }
   1579 
   1580             unkStruct->isFree = TRUE;
   1581         }
   1582     }
   1583 
   1584     for (i = 0; i < pool->numEntries; i++) {
   1585         if (pool->entries[i].used == FALSE) {
   1586             continue;
   1587         }
   1588         itemStart = pool->entries[i].srcAddr;
   1589         itemEnd = itemStart + pool->entries[i].size - 1;
   1590 
   1591         if (itemEnd < phi_s3 && itemStart < phi_s3) {
   1592             continue;
   1593         }
   1594 
   1595         if (itemEnd >= temp_s2 && itemStart >= temp_s2) {
   1596             continue;
   1597         }
   1598 
   1599         func_sh_802f2158(&pool->entries[i]);
   1600         if (chosenIndex == -1) {
   1601             chosenIndex = i;
   1602         }
   1603     }
   1604 
   1605     if (chosenIndex == -1) {
   1606         chosenIndex = pool->numEntries++;
   1607     }
   1608     pool->entries[chosenIndex].used = TRUE;
   1609     pool->entries[chosenIndex].srcAddr = memLocation;
   1610     pool->entries[chosenIndex].size = size;
   1611 
   1612     return &pool->entries[chosenIndex];
   1613 }
   1614 
   1615 void func_sh_802f2158(struct UnkEntry *entry) {
   1616     s32 idx;
   1617     s32 seqCount;
   1618     s32 bankId1;
   1619     s32 bankId2;
   1620     s32 instId;
   1621     s32 drumId;
   1622     struct Drum *drum;
   1623     struct Instrument *inst;
   1624 
   1625     seqCount = gAlCtlHeader->seqCount;
   1626     for (idx = 0; idx < seqCount; idx++) {
   1627         bankId1 = gCtlEntries[idx].bankId1;
   1628         bankId2 = gCtlEntries[idx].bankId2;
   1629         if ((bankId1 != 0xff && entry->bankId == bankId1) || (bankId2 != 0xff && entry->bankId == bankId2) || entry->bankId == 0) {
   1630             if (get_bank_or_seq(1, 2, idx) != NULL) {
   1631                 if (IS_BANK_LOAD_COMPLETE(idx) != FALSE) {
   1632                     for (instId = 0; instId < gCtlEntries[idx].numInstruments; instId++) {
   1633                         inst = get_instrument_inner(idx, instId);
   1634                         if (inst != NULL) {
   1635                             if (inst->normalRangeLo != 0) {
   1636                                 func_sh_802F2320(entry, inst->lowNotesSound.sample);
   1637                             }
   1638                             if (inst->normalRangeHi != 127) {
   1639                                 func_sh_802F2320(entry, inst->highNotesSound.sample);
   1640                             }
   1641                             func_sh_802F2320(entry, inst->normalNotesSound.sample);
   1642                         }
   1643                     }
   1644                     for (drumId = 0; drumId < gCtlEntries[idx].numDrums; drumId++) {
   1645                         drum = get_drum(idx, drumId);
   1646                         if (drum != NULL) {
   1647                             func_sh_802F2320(entry, drum->sound.sample);
   1648                         }
   1649                     }
   1650                 }
   1651             }
   1652         }
   1653     }
   1654 }
   1655 
   1656 void func_sh_802F2320(struct UnkEntry *entry, struct AudioBankSample *sample) {
   1657     if (sample != NULL && sample->sampleAddr == entry->srcAddr) {
   1658         sample->sampleAddr = entry->dstAddr;
   1659         sample->medium = entry->medium;
   1660     }
   1661 }
   1662 
   1663 struct UnkEntry *unk_pool2_alloc(u32 size) {
   1664     void *data;
   1665     struct UnkEntry *ret;
   1666     s32 *numEntries = &gUnkPool2.numEntries;
   1667 
   1668     data = sound_alloc_uninitialized(&gUnkPool2.pool, size);
   1669     if (data == NULL) {
   1670         return NULL;
   1671     }
   1672     ret = &gUnkPool2.entries[*numEntries];
   1673     ret->used = TRUE;
   1674     ret->srcAddr = data;
   1675     ret->size = size;
   1676     (*numEntries)++;
   1677     return ret;
   1678 }
   1679 
   1680 void func_sh_802f23ec(void) {
   1681     s32 i;
   1682     s32 idx;
   1683     s32 seqCount;
   1684     s32 bankId1;
   1685     s32 bankId2;
   1686     s32 instId;
   1687     s32 drumId;
   1688     struct Drum *drum;
   1689     struct Instrument *inst;
   1690     UNUSED s32 pad;
   1691     struct UnkEntry *entry; //! @bug: not initialized but nevertheless used
   1692 
   1693     seqCount = gAlCtlHeader->seqCount;
   1694     for (idx = 0; idx < seqCount; idx++) {
   1695         bankId1 = gCtlEntries[idx].bankId1;
   1696         bankId2 = gCtlEntries[idx].bankId2;
   1697         if ((bankId1 != 0xffu && entry->bankId == bankId1) || (bankId2 != 0xff && entry->bankId == bankId2) || entry->bankId == 0) {
   1698             if (get_bank_or_seq(1, 3, idx) != NULL) {
   1699                 if (IS_BANK_LOAD_COMPLETE(idx) != FALSE) {
   1700                     for (i = 0; i < gUnkPool2.numEntries; i++) {
   1701                         entry = &gUnkPool2.entries[i];
   1702                         for (instId = 0; instId < gCtlEntries[idx].numInstruments; instId++) {
   1703                             inst = get_instrument_inner(idx, instId);
   1704                             if (inst != NULL) {
   1705                                 if (inst->normalRangeLo != 0) {
   1706                                     func_sh_802F2320(entry, inst->lowNotesSound.sample);
   1707                                 }
   1708                                 if (inst->normalRangeHi != 127) {
   1709                                     func_sh_802F2320(entry, inst->highNotesSound.sample);
   1710                                 }
   1711                                 func_sh_802F2320(entry, inst->normalNotesSound.sample);
   1712                             }
   1713                         }
   1714                         for (drumId = 0; drumId < gCtlEntries[idx].numDrums; drumId++) {
   1715                             drum = get_drum(idx, drumId);
   1716                             if (drum != NULL) {
   1717                                 func_sh_802F2320(entry, drum->sound.sample);
   1718                             }
   1719                         }
   1720                     }
   1721                 }
   1722             }
   1723         }
   1724     }
   1725 }
   1726 #endif
   1727 
   1728 #ifdef VERSION_EU
   1729 u8 audioString22[] = "SFrame Sample %d %d %d\n";
   1730 u8 audioString23[] = "AHPBASE %x\n";
   1731 u8 audioString24[] = "AHPCUR  %x\n";
   1732 u8 audioString25[] = "HeapTop %x\n";
   1733 u8 audioString26[] = "SynoutRate %d / %d \n";
   1734 u8 audioString27[] = "FXSIZE %d\n";
   1735 u8 audioString28[] = "FXCOMP %d\n";
   1736 u8 audioString29[] = "FXDOWN %d\n";
   1737 u8 audioString30[] = "WaveCacheLen: %d\n";
   1738 u8 audioString31[] = "SpecChange Finished\n";
   1739 #endif