sm64

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

seq_channel_layer_process_script_copt.inc.c (18731B)


      1 //! Copt inlining for US/JP. Here be dragons
      2 // This version is basically identical to EU
      3 
      4 #include <ultra64.h>
      5 #include <macros.h>
      6 
      7 #include "audio/heap.h"
      8 #include "audio/data.h"
      9 #include "audio/load.h"
     10 #include "audio/seqplayer.h"
     11 #include "audio/external.h"
     12 #include "audio/effects.h"
     13 
     14 #define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
     15 #define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
     16 #define PORTAMENTO_MODE_1 1
     17 #define PORTAMENTO_MODE_2 2
     18 #define PORTAMENTO_MODE_3 3
     19 #define PORTAMENTO_MODE_4 4
     20 #define PORTAMENTO_MODE_5 5
     21 
     22 #define COPT 0
     23 #if COPT
     24 #define M64_READ_U8(state, dst) \
     25     dst = m64_read_u8(state);
     26 #else
     27 #define M64_READ_U8(state, dst) \
     28 {                               \
     29     u8 * _ptr_pc;               \
     30     u8  _pc;                    \
     31     _ptr_pc = (*state).pc;      \
     32     ((*state).pc)++;            \
     33     _pc = *_ptr_pc;             \
     34     dst = _pc;                  \
     35 }
     36 #endif
     37 
     38 
     39 #if COPT
     40 #define M64_READ_S16(state, dst) \
     41     dst = m64_read_s16(state);
     42 #else
     43 #define M64_READ_S16(state, dst)    \
     44 {                                   \
     45     s16 _ret;                       \
     46     _ret = *(*state).pc << 8;       \
     47     ((*state).pc)++;                \
     48     _ret = *(*state).pc | _ret;     \
     49     ((*state).pc)++;                \
     50     dst = _ret;                     \
     51 }
     52 #endif
     53 #if COPT
     54 #define M64_READ_COMPRESSED_U16(state, dst) \
     55     dst = m64_read_compressed_u16(state);
     56 #else
     57 #define M64_READ_COMPRESSED_U16(state, dst) \
     58 {                                           \
     59     u16 ret = *(state->pc++);               \
     60     if (ret & 0x80) {                       \
     61         ret = (ret << 8) & 0x7f00;          \
     62         ret = *(state->pc++) | ret;         \
     63     }                                       \
     64     dst = ret;                              \
     65 }
     66 #endif
     67 
     68 #if COPT
     69 #define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
     70     dst = get_instrument(seqChannel, instId, _instOut, _adsr);
     71 #else
     72 #define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
     73 { \
     74 struct AdsrSettings *adsr = _adsr; \
     75 struct Instrument **instOut = _instOut;\
     76     u8 _instId = instId; \
     77     struct Instrument *inst; \
     78     UNUSED u32 pad; \
     79         /* copt inlines instId here  */ \
     80     if (instId >= gCtlEntries[(*seqChannel).bankId].numInstruments) { \
     81         _instId = gCtlEntries[(*seqChannel).bankId].numInstruments; \
     82         if (_instId == 0) { \
     83             dst = 0; \
     84             goto ret ## l; \
     85         } \
     86         _instId--; \
     87     } \
     88     inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
     89     if (inst == NULL) { \
     90         while (_instId != 0xff) { \
     91             inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
     92             if (inst != NULL) { \
     93                 goto gi ## l; \
     94             } \
     95             _instId--; \
     96         } \
     97         gi ## l:; \
     98     } \
     99     if (((uintptr_t) gBankLoadedPool.persistent.pool.start <= (uintptr_t) inst \
    100          && (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.persistent.pool.start \
    101                                           + gBankLoadedPool.persistent.pool.size)) \
    102         || ((uintptr_t) gBankLoadedPool.temporary.pool.start <= (uintptr_t) inst \
    103             && (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.temporary.pool.start \
    104                                              + gBankLoadedPool.temporary.pool.size))) { \
    105         (*adsr).envelope = (*inst).envelope; \
    106         (*adsr).releaseRate = (*inst).releaseRate; \
    107         *instOut = inst; \
    108         _instId++; \
    109         goto ret ## l; \
    110     } \
    111     gAudioErrorFlags = _instId + 0x20000; \
    112     *instOut = NULL; \
    113     ret ## l: ; \
    114 }
    115 #endif
    116 
    117 void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) {
    118     struct SequencePlayer *seqPlayer;   // sp5C, t4
    119     struct SequenceChannel *seqChannel; // sp58, t5
    120     struct M64ScriptState *state;
    121     struct Portamento *portamento;
    122     struct AudioBankSound *sound;
    123     struct Instrument *instrument;
    124     struct Drum *drum;
    125     s32 temp_a0_5;
    126     u8 sameSound;
    127     u8 cmd;                             // a0 sp3E, EU s2
    128     u8 cmdSemitone;                     // sp3D, t0
    129     u16 sp3A;                           // t2, a0, a1
    130     f32 tuning;                         // f0
    131     s32 vel;                            // sp30, t3
    132     s32 usedSemitone;                   // a1
    133     f32 freqScale;                      // sp28, f0
    134     f32 sp24;
    135     f32 temp_f12;
    136     f32 temp_f2;
    137 
    138 //! Copt: manually inline these functions in the scope of this routine
    139 #ifdef __sgi
    140 #pragma inline routine(m64_read_u8)
    141 #pragma inline routine(m64_read_compressed_u16)
    142 #pragma inline routine(m64_read_s16)
    143 #pragma inline routine(get_instrument)
    144 #endif
    145 
    146     sameSound = TRUE;
    147     if ((*layer).enabled == FALSE) {
    148         return;
    149     }
    150 
    151     if ((*layer).delay > 1) {
    152         (*layer).delay--;
    153         if (!layer->stopSomething && layer->delay <= layer->duration) {
    154             seq_channel_layer_note_decay(layer);
    155             layer->stopSomething = TRUE;
    156         }
    157         return;
    158     }
    159 
    160     if (!layer->continuousNotes) {
    161         seq_channel_layer_note_decay(layer);
    162     }
    163 
    164     if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1 ||
    165         PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2) {
    166         layer->portamento.mode = 0;
    167     }
    168 
    169     seqChannel = (*layer).seqChannel;
    170     seqPlayer = (*seqChannel).seqPlayer;
    171     for (;;) {
    172         state = &layer->scriptState;
    173         //M64_READ_U8(state, cmd);
    174         {
    175             u8 *_ptr_pc;
    176             _ptr_pc = (*state).pc++;
    177             cmd = *_ptr_pc;
    178         }
    179 
    180         if (cmd <= 0xc0) {
    181             break;
    182         }
    183 
    184         switch (cmd) {
    185             case 0xff: // layer_end; function return or end of script
    186                 if (state->depth == 0) {
    187                     // N.B. this function call is *not* inlined even though it's
    188                     // within the same file, unlike in the rest of this function.
    189                     seq_channel_layer_disable(layer);
    190                     return;
    191                 }
    192                 state->depth--, state->pc = state->stack[state->depth];
    193                 break;
    194 
    195             case 0xfc: // layer_call
    196                 M64_READ_S16(state, sp3A);
    197                 state->depth++, state->stack[state->depth - 1] = state->pc;
    198                 state->pc = seqPlayer->seqData + sp3A;
    199                 break;
    200 
    201             case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0)
    202                 M64_READ_U8(state, state->remLoopIters[state->depth]);
    203                 state->depth++, state->stack[state->depth - 1] = state->pc;
    204                 break;
    205 
    206             case 0xf7: // layer_loopend
    207                 if (--state->remLoopIters[state->depth - 1] != 0) {
    208                     state->pc = state->stack[state->depth - 1];
    209                 } else {
    210                     state->depth--;
    211                 }
    212                 break;
    213 
    214             case 0xfb: // layer_jump
    215                 M64_READ_S16(state, sp3A);
    216                 state->pc = seqPlayer->seqData + sp3A;
    217                 break;
    218 
    219             case 0xc1: // layer_setshortnotevelocity
    220             case 0xca: // layer_setpan
    221                 temp_a0_5 = *(state->pc++);
    222                 if (cmd == 0xc1) {
    223                     layer->velocitySquare = (f32)(temp_a0_5 * temp_a0_5);
    224                 } else {
    225                     layer->pan = (f32) temp_a0_5 / US_FLOAT(128.0);
    226                 }
    227                 break;
    228 
    229             case 0xc2: // layer_transpose; set transposition in semitones
    230             case 0xc9: // layer_setshortnoteduration
    231                 temp_a0_5 = *(state->pc++);
    232                 if (cmd == 0xc9) {
    233                     layer->noteDuration = temp_a0_5;
    234                 } else {
    235                     layer->transposition = temp_a0_5;
    236                 }
    237                 break;
    238 
    239             case 0xc4: // layer_somethingon
    240             case 0xc5: // layer_somethingoff
    241                 //! copt needs a ternary:
    242                 //layer->continuousNotes = (cmd == 0xc4) ? TRUE : FALSE;
    243                 {
    244                     u8 setting;
    245                     if (cmd == 0xc4) {
    246                         setting = TRUE;
    247                     } else {
    248                         setting = FALSE;
    249                     }
    250                     layer->continuousNotes = setting;
    251                     seq_channel_layer_note_decay(layer);
    252                 }
    253                 break;
    254 
    255             case 0xc3: // layer_setshortnotedefaultplaypercentage
    256                 M64_READ_COMPRESSED_U16(state, sp3A);
    257                 layer->shortNoteDefaultPlayPercentage = sp3A;
    258                 break;
    259 
    260             case 0xc6: // layer_setinstr
    261                 M64_READ_U8(state, cmdSemitone);
    262 
    263                 if (cmdSemitone < 127) {
    264                     GET_INSTRUMENT(seqChannel, cmdSemitone, &(*layer).instrument, &(*layer).adsr, cmdSemitone, 1);
    265                 }
    266                 break;
    267 
    268             case 0xc7: // layer_portamento
    269                 M64_READ_U8(state, (*layer).portamento.mode);
    270                 M64_READ_U8(state, cmdSemitone);
    271 
    272                 cmdSemitone = cmdSemitone + (*seqChannel).transposition;
    273                 cmdSemitone += (*layer).transposition;
    274                 cmdSemitone += (*seqPlayer).transposition;
    275 
    276                 if (cmdSemitone >= 0x80) {
    277                     cmdSemitone = 0;
    278                 }
    279                 layer->portamentoTargetNote = cmdSemitone;
    280 
    281                 // If special, the next param is u8 instead of var
    282                 if (PORTAMENTO_IS_SPECIAL((*layer).portamento)) {
    283                     layer->portamentoTime = *((state)->pc++);
    284                     break;
    285                 }
    286 
    287                 M64_READ_COMPRESSED_U16(state, sp3A);
    288                 layer->portamentoTime = sp3A;
    289                 break;
    290 
    291             case 0xc8: // layer_disableportamento
    292                 layer->portamento.mode = 0;
    293                 break;
    294 
    295             default:
    296                 switch (cmd & 0xf0) {
    297                     case 0xd0: // layer_setshortnotevelocityfromtable
    298                         sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xf];
    299                         (*layer).velocitySquare = (f32)(sp3A * sp3A);
    300                         break;
    301                     case 0xe0: // layer_setshortnotedurationfromtable
    302                         (*layer).noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf];
    303                         break;
    304                 }
    305         }
    306     }
    307 
    308     if (cmd == 0xc0) { // layer_delay
    309         M64_READ_COMPRESSED_U16(state, layer->delay);
    310         layer->stopSomething = TRUE;
    311     } else {
    312         layer->stopSomething = FALSE;
    313 
    314         if (seqChannel->largeNotes == TRUE) {
    315             switch (cmd & 0xc0) {
    316                 case 0x00: // layer_note0 (play percentage, velocity, duration)
    317                     M64_READ_COMPRESSED_U16(state, sp3A);
    318                     vel = *((*state).pc++);
    319                     layer->noteDuration = *((*state).pc++);
    320                     layer->playPercentage = sp3A;
    321                     goto l1090;
    322 
    323                 case 0x40: // layer_note1 (play percentage, velocity)
    324                     M64_READ_COMPRESSED_U16(state, sp3A);
    325                     vel = *((*state).pc++);
    326                     layer->noteDuration = 0;
    327                     layer->playPercentage = sp3A;
    328                     goto l1090;
    329 
    330                 case 0x80: // layer_note2 (velocity, duration; uses last play percentage)
    331                     sp3A = layer->playPercentage;
    332                     vel = *((*state).pc++);
    333                     layer->noteDuration = *((*state).pc++);
    334                     goto l1090;
    335             }
    336 l1090:
    337             cmdSemitone = cmd - (cmd & 0xc0);
    338             layer->velocitySquare = vel * vel;
    339         } else {
    340             switch (cmd & 0xc0) {
    341                 case 0x00: // play note, type 0 (play percentage)
    342                     M64_READ_COMPRESSED_U16(state, sp3A);
    343                     layer->playPercentage = sp3A;
    344                     goto l1138;
    345 
    346                 case 0x40: // play note, type 1 (uses default play percentage)
    347                     sp3A = layer->shortNoteDefaultPlayPercentage;
    348                     goto l1138;
    349 
    350                 case 0x80: // play note, type 2 (uses last play percentage)
    351                     sp3A = layer->playPercentage;
    352                     goto l1138;
    353             }
    354 l1138:
    355 
    356             cmdSemitone = cmd - (cmd & 0xc0);
    357         }
    358 
    359         layer->delay = sp3A;
    360         layer->duration = layer->noteDuration * sp3A / 256;
    361         if ((seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES) != 0)
    362             || seqChannel->stopSomething2
    363             || !seqChannel->hasInstrument
    364         ) {
    365             layer->stopSomething = TRUE;
    366         } else {
    367             if (seqChannel->instOrWave == 0) { // drum
    368                 cmdSemitone += (*seqChannel).transposition + (*layer).transposition;
    369                 if (cmdSemitone >= gCtlEntries[seqChannel->bankId].numDrums) {
    370                     cmdSemitone = gCtlEntries[seqChannel->bankId].numDrums;
    371                     if (cmdSemitone == 0) {
    372                         // this goto looks a bit like a function return...
    373                         layer->stopSomething = TRUE;
    374                         goto skip;
    375                     }
    376 
    377                     cmdSemitone--;
    378                 }
    379 
    380                 drum = gCtlEntries[seqChannel->bankId].drums[cmdSemitone];
    381                 if (drum == NULL) {
    382                     layer->stopSomething = TRUE;
    383                 } else {
    384                     layer->adsr.envelope = drum->envelope;
    385                     layer->adsr.releaseRate = drum->releaseRate;
    386                     layer->pan = FLOAT_CAST(drum->pan) / US_FLOAT(128.0);
    387                     layer->sound = &drum->sound;
    388                     layer->freqScale = layer->sound->tuning;
    389                 }
    390 
    391             skip:;
    392             } else { // instrument
    393                 cmdSemitone += (*seqPlayer).transposition + (*seqChannel).transposition + (*layer).transposition;
    394                 if (cmdSemitone >= 0x80) {
    395                     layer->stopSomething = TRUE;
    396                 } else {
    397                     instrument = layer->instrument;
    398                     if (instrument == NULL) {
    399                         instrument = seqChannel->instrument;
    400                     }
    401 
    402                     if (layer->portamento.mode != 0) {
    403                         //! copt needs a ternary:
    404                         //usedSemitone = (layer->portamentoTargetNote < cmdSemitone) ? cmdSemitone : layer->portamentoTargetNote;
    405                         if (layer->portamentoTargetNote < cmdSemitone) {
    406                             usedSemitone = cmdSemitone;
    407                         } else {
    408                             usedSemitone = layer->portamentoTargetNote;
    409                         }
    410 
    411                         if (instrument != NULL) {
    412                             sound = (u8) usedSemitone < instrument->normalRangeLo ? &instrument->lowNotesSound
    413                                   : (u8) usedSemitone <= instrument->normalRangeHi ?
    414                                         &instrument->normalNotesSound : &instrument->highNotesSound;
    415 
    416                             sameSound = (sound == (*layer).sound);
    417                             layer->sound = sound;
    418                             tuning = (*sound).tuning;
    419                         } else {
    420                             layer->sound = NULL;
    421                             tuning = 1.0f;
    422                         }
    423 
    424                         temp_f2 = gNoteFrequencies[cmdSemitone] * tuning;
    425                         temp_f12 = gNoteFrequencies[layer->portamentoTargetNote] * tuning;
    426 
    427                         portamento = &layer->portamento;
    428                         switch (PORTAMENTO_MODE(layer->portamento)) {
    429                             case PORTAMENTO_MODE_1:
    430                             case PORTAMENTO_MODE_3:
    431                             case PORTAMENTO_MODE_5:
    432                                 sp24 = temp_f2;
    433                                 freqScale = temp_f12;
    434                                 goto l13cc;
    435 
    436                             case PORTAMENTO_MODE_2:
    437                             case PORTAMENTO_MODE_4:
    438                                 freqScale = temp_f2;
    439                                 sp24 = temp_f12;
    440                                 goto l13cc;
    441                         }
    442 l13cc:
    443                         portamento->extent = sp24 / freqScale - US_FLOAT(1.0);
    444                         if (PORTAMENTO_IS_SPECIAL((*layer).portamento)) {
    445                             portamento->speed = US_FLOAT(32512.0) * FLOAT_CAST((*seqPlayer).tempo)
    446                                                 / ((f32)(*layer).delay * (f32) gTempoInternalToExternal
    447                                                    * FLOAT_CAST((*layer).portamentoTime));
    448                         } else {
    449                             portamento->speed = US_FLOAT(127.0) / FLOAT_CAST((*layer).portamentoTime);
    450                         }
    451                         portamento->cur = 0.0f;
    452                         layer->freqScale = freqScale;
    453                         if (PORTAMENTO_MODE((*layer).portamento) == PORTAMENTO_MODE_5) {
    454                             layer->portamentoTargetNote = cmdSemitone;
    455                         }
    456                     } else if (instrument != NULL) {
    457                         sound = cmdSemitone < instrument->normalRangeLo ?
    458                                          &instrument->lowNotesSound : cmdSemitone <= instrument->normalRangeHi ?
    459                                          &instrument->normalNotesSound : &instrument->highNotesSound;
    460 
    461                         sameSound = (sound == (*layer).sound);
    462                         layer->sound = sound;
    463                         layer->freqScale = gNoteFrequencies[cmdSemitone] * (*sound).tuning;
    464                     } else {
    465                         layer->sound = NULL;
    466                         layer->freqScale = gNoteFrequencies[cmdSemitone];
    467                     }
    468                 }
    469             }
    470             layer->delayUnused = layer->delay;
    471         }
    472     }
    473 
    474     if (layer->stopSomething == TRUE) {
    475         if (layer->note != NULL || layer->continuousNotes) {
    476             seq_channel_layer_note_decay(layer);
    477         }
    478         return;
    479     }
    480 
    481     cmdSemitone = FALSE;
    482     if (!layer->continuousNotes) {
    483         cmdSemitone = TRUE;
    484     } else if (layer->note == NULL || layer->status == SOUND_LOAD_STATUS_NOT_LOADED) {
    485         cmdSemitone = TRUE;
    486     } else if (sameSound == FALSE) {
    487         seq_channel_layer_note_decay(layer);
    488         cmdSemitone = TRUE;
    489     } else if (layer->sound == NULL) {
    490         init_synthetic_wave(layer->note, layer);
    491     }
    492 
    493     if (cmdSemitone != FALSE) {
    494         (*layer).note = alloc_note(layer);
    495     }
    496 
    497     if (layer->note != NULL && layer->note->parentLayer == layer) {
    498         note_vibrato_init(layer->note);
    499     }
    500 }