1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-11 03:39:59 +00:00

Add near-matching decomped functions for SeqPlayer (#729)

* Add nearmatching decomped functions

* improved match

* greatly improved match

* small thing

* almost matching

* small cleanup

* remove commented array

* pad -> unk

Co-authored-by: petrie911 <pmontag@DESKTOP-LG8A167.localdomain>
Co-authored-by: Fig02 <fig02srl@gmail.com>
This commit is contained in:
MNGoldenEagle 2021-04-12 05:20:46 -05:00 committed by GitHub
parent 62df74991d
commit c952fd4490
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 844 additions and 34 deletions

View file

@ -2069,7 +2069,7 @@ void Audio_SetSeqLoadStatus(s32 seqId, u8 status);
// ? func_800E1F38(?); // ? func_800E1F38(?);
// ? func_800E1F7C(?); // ? func_800E1F7C(?);
// ? func_800E202C(?); // ? func_800E202C(?);
// ? func_800E20D4(?); void func_800E20D4(s32, s32, s32);
// ? func_800E2124(?); // ? func_800E2124(?);
// ? func_800E217C(?); // ? func_800E217C(?);
// ? func_800E22C4(?); // ? func_800E22C4(?);
@ -2096,7 +2096,7 @@ void func_800E3400(void);
// ? func_800E36EC(?); // ? func_800E36EC(?);
// ? func_800E3874(?); // ? func_800E3874(?);
// ? func_800E38F8(?); // ? func_800E38F8(?);
// ? func_800E390C(?); void func_800E390C(s32, void*, void*);
void func_800E3A14(void); void func_800E3A14(void);
// ? func_800E3A44(?); // ? func_800E3A44(?);
// ? func_800E3AC8(?); // ? func_800E3AC8(?);
@ -2113,7 +2113,7 @@ void func_800E3A14(void);
// ? func_800E48C0(?); // ? func_800E48C0(?);
// ? func_800E4918(?); // ? func_800E4918(?);
void func_800E4D94(void); void func_800E4D94(void);
// ? func_800E4EEC(?); void func_800E4EEC(u32, u32, s8*);
// ? func_800E4F58(?); // ? func_800E4F58(?);
void func_800E4FB0(void); void func_800E4FB0(void);
Sub_AudioMgr_18* func_800E4FE0(void); Sub_AudioMgr_18* func_800E4FE0(void);

View file

@ -190,6 +190,9 @@ typedef struct {
// Also known as a Group, according to sm64 debug strings. // Also known as a Group, according to sm64 debug strings.
typedef struct { typedef struct {
union {
s32 playerState;
struct {
/* 0x000 */ u8 enabled : 1; /* 0x000 */ u8 enabled : 1;
/*?0x000 */ u8 finished : 1; /*?0x000 */ u8 finished : 1;
/* 0x000 */ u8 muted : 1; /* 0x000 */ u8 muted : 1;
@ -200,11 +203,25 @@ typedef struct {
/* 0x000 */ u8 unk_0b1 : 1; /* 0x000 */ u8 unk_0b1 : 1;
/* 0x001 */ u8 state; /* 0x001 */ u8 state;
/* 0x002 */ u8 noteAllocPolicy; /* 0x002 */ u8 noteAllocPolicy;
union {
/* 0x003 */ u8 muteBehavior; /* 0x003 */ u8 muteBehavior;
struct {
u8 mute_u00 : 1;
u8 mute_u01 : 1;
u8 mute_u02 : 1;
u8 mute_u03 : 1;
u8 mute_u04 : 1;
u8 mute_u05 : 1;
u8 mute_u06 : 1;
u8 mute_u07 : 1;
};
};
};
};
/* 0x004 */ u8 seqId; /* 0x004 */ u8 seqId;
/* 0x005 */ u8 defaultBank; /* 0x005 */ u8 defaultBank;
/*?0x006 */ u8 loadingBankId; /*?0x006 */ u8 loadingBankId;
/*?0x007 */ s8 seqVariationEu[1]; /*?0x007 */ s8 seqVariationEu;
/* 0x008 */ u16 tempo; // tatums per minute /* 0x008 */ u16 tempo; // tatums per minute
/* 0x00A */ u16 tempoAcc; /* 0x00A */ u16 tempoAcc;
/* 0x00C */ u16 unk_0C; /* 0x00C */ u16 unk_0C;
@ -227,7 +244,7 @@ typedef struct {
/* 0x098 */ u8* shortNoteDurationTable; /* 0x098 */ u8* shortNoteDurationTable;
/* 0x09C */ NotePool notePool; /* 0x09C */ NotePool notePool;
/* 0x0DC */ s32 unk_DC; /* 0x0DC */ s32 unk_DC;
/* 0x0D0 */ u32 unk_E0; /* 0x0E0 */ u32 unk_E0;
/* 0x0E4 */ u8 pad_E4[0x10]; // OSMesgQueue seqDmaMesgQueue; /* 0x0E4 */ u8 pad_E4[0x10]; // OSMesgQueue seqDmaMesgQueue;
/*?0x0F4 */ OSMesg seqDmaMesg; /*?0x0F4 */ OSMesg seqDmaMesg;
/*?0x0F8 */ OSIoMesg seqDmaIoMesg; /*?0x0F8 */ OSIoMesg seqDmaIoMesg;
@ -300,6 +317,9 @@ typedef struct {
// Also known as a SubTrack, according to sm64 debug strings. // Also known as a SubTrack, according to sm64 debug strings.
// Confusingly, a SubTrack is a container of Tracks. // Confusingly, a SubTrack is a container of Tracks.
typedef struct SequenceChannel { typedef struct SequenceChannel {
union {
s32 channelState;
struct {
/* 0x00 */ u8 enabled : 1; /* 0x00 */ u8 enabled : 1;
/* 0x00 */ u8 finished : 1; /* 0x00 */ u8 finished : 1;
/* 0x00 */ u8 stopScript : 1; /* 0x00 */ u8 stopScript : 1;
@ -318,6 +338,8 @@ typedef struct SequenceChannel {
} changes; } changes;
/* 0x02 */ u8 noteAllocPolicy; /* 0x02 */ u8 noteAllocPolicy;
/* 0x03 */ u8 muteBehavior; /* 0x03 */ u8 muteBehavior;
};
};
/* 0x04 */ u8 reverb; // or dry/wet mix /* 0x04 */ u8 reverb; // or dry/wet mix
/* 0x05 */ u8 notePriority; // 0-3 /* 0x05 */ u8 notePriority; // 0-3
/* 0x06 */ u8 someOtherPriority; /* 0x06 */ u8 someOtherPriority;
@ -339,7 +361,7 @@ typedef struct SequenceChannel {
/* 0x1C */ u16 vibratoDelay; /* 0x1C */ u16 vibratoDelay;
/* 0x1E */ u16 delay; /* 0x1E */ u16 delay;
/* 0x20 */ u16 unk_20; /* 0x20 */ u16 unk_20;
/* 0x22 */ u16 pad_22; /* 0x22 */ u16 unk_22;
/* 0x24 */ s16 instOrWave; // either 0 (none), instrument index + 1, or /* 0x24 */ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves. // 0x80..0x83 for sawtooth/triangle/sine/square waves.
/* 0x26 */ s16 transposition; /* 0x26 */ s16 transposition;
@ -671,7 +693,8 @@ typedef struct {
/* 0x2624 */ char unk_2624[0x210]; /* 0x2624 */ char unk_2624[0x210];
/* 0x2834 */ s16* unk_2834; /* 0x2834 */ s16* unk_2834;
/* 0x2838 */ ManyStruct_800E0E0C_2* unk_2838; /* 0x2838 */ ManyStruct_800E0E0C_2* unk_2838;
/* 0x283C */ char unk_283C[0x8]; /* 0x283C */ u8* unk_283C;
/* 0x2840 */ char unk_2840[0x4];
/* 0x2844 */ CtlEntry* gCtlEntries; /* 0x2844 */ CtlEntry* gCtlEntries;
/* 0x2848 */ AudioBufferParameters gAudioBufferParameters; /* 0x2848 */ AudioBufferParameters gAudioBufferParameters;
/* 0x2870 */ f32 unk_2870; /* 0x2870 */ f32 unk_2870;

View file

@ -374,6 +374,7 @@ s32 func_800E9F64(SequenceChannelLayer* layer, s32 arg1);
s32 func_800EA0C0(SequenceChannelLayer* layer); s32 func_800EA0C0(SequenceChannelLayer* layer);
s32 func_800EA440(SequenceChannelLayer* layer, s32 arg1); s32 func_800EA440(SequenceChannelLayer* layer, s32 arg1);
s32 func_800EAAE0(SequenceChannelLayer* layer, s32 arg1); s32 func_800EAAE0(SequenceChannelLayer* layer, s32 arg1);
s32 func_800E3414(u8 bankId, s32 value, s8* value2);
void Audio_SeqChannelLayerProcessScript(SequenceChannelLayer* layer) { void Audio_SeqChannelLayerProcessScript(SequenceChannelLayer* layer) {
s32 val; s32 val;
@ -956,11 +957,797 @@ void Audio_SequenceChannelSetVolume(SequenceChannel* seqChannel, u8 volume) {
seqChannel->volume = (f32)(s32)volume / 127.0f; seqChannel->volume = (f32)(s32)volume / 127.0f;
} }
#ifdef NON_MATCHING
// Two reg category errors and lots of t register shifting.
void Audio_SequenceChannelProcessScript(SequenceChannel* channel) {
s32 i;
u8* data;
u8* test;
SequencePlayer* player;
if (channel->stopScript) {
goto exit_loop;
}
player = channel->seqPlayer;
if (player->muted && (channel->muteBehavior & 0x80)) {
return;
}
if (channel->delay >= 2) {
channel->delay--;
goto exit_loop;
}
while (true) {
M64ScriptState* scriptState = &channel->scriptState;
s32 param;
s16 pad1;
u16 offset;
s32 parameters[3];
s8 signedParam;
u8 command = Audio_M64ReadU8(scriptState);
u8 lowBits;
u8 highBits;
s32 result;
s32 pad2;
if (command >= 0xB0) {
highBits = D_80130470[(s32)command];
lowBits = highBits & 3;
for (i = 0; i < lowBits; i++, highBits <<= 1) {
if (!(highBits & 0x80)) {
parameters[i] = Audio_M64ReadU8(scriptState);
} else {
parameters[i] = Audio_M64ReadS16(scriptState);
}
}
if (command >= 0xF2) {
result = Audio_HandleScriptFlowControl(player, scriptState, command, parameters[0]);
if (result != 0) {
if (result == -1) {
Audio_SequenceChannelDisable(channel);
} else {
channel->delay = result;
}
break;
}
} else {
switch (command) {
case 0xEA:
channel->stopScript = true;
goto exit_loop;
case 0xF1:
Audio_NotePoolClear(&channel->notePool);
command = (u8)parameters[0];
Audio_NotePoolFill(&channel->notePool, command);
break;
case 0xF0:
Audio_NotePoolClear(&channel->notePool);
break;
case 0xC2:
offset = (u16)parameters[0];
channel->dynTable = &player->seqData[offset];
break;
case 0xC5:
if (scriptState->value != -1) {
data = (*channel->dynTable)[scriptState->value];
offset = (u16)((data[0] << 8) + data[1]);
channel->dynTable = &player->seqData[offset];
}
break;
case 0xEB:
result = (u8)parameters[0]; // category error: should be t not v
command = result;
if (player->defaultBank != 0xFF) {
offset = ((u16*)gAudioContext.unk_283C)[player->seqId];
lowBits = gAudioContext.unk_283C[offset];
command = gAudioContext.unk_283C[offset + lowBits - result];
}
if (func_800DF074(1, 2, command)) {
channel->bankId = command;
}
parameters[0] = parameters[1];
// NOTE: Intentional fallthrough
case 0xC1:
command = (u8)parameters[0];
Audio_SetInstrument(channel, command);
break;
case 0xC3:
channel->largeNotes = false;
break;
case 0xC4:
channel->largeNotes = true;
break;
case 0xDF:
command = (u8)parameters[0];
Audio_SequenceChannelSetVolume(channel, command);
channel->changes.s.volume = true;
break;
case 0xE0:
command = (u8)parameters[0];
channel->volumeScale = (f32)(s32)command / 128.0f;
channel->changes.s.volume = true;
break;
case 0xDE:
offset = (u16)parameters[0];
channel->freqScale = (f32)(s32)offset / 32768.0f;
channel->changes.s.freqScale = true;
break;
case 0xD3:
command = (u8)parameters[0];
command += 0x80;
channel->freqScale = gPitchBendFrequencyScale[command];
channel->changes.s.freqScale = true;
break;
case 0xEE:
command = (u8)parameters[0];
command += 0x80;
channel->freqScale = D_8012F4B4[command];
channel->changes.s.freqScale = true;
break;
case 0xDD:
command = (u8)parameters[0];
channel->newPan = command;
channel->changes.s.pan = true;
break;
case 0xDC:
command = (u8)parameters[0];
channel->panChannelWeight = command;
channel->changes.s.pan = true;
break;
case 0xDB:
signedParam = (s8) parameters[0];
channel->transposition = signedParam;
break;
case 0xDA:
offset = (u16)parameters[0];
channel->adsr.envelope = &player->seqData[offset];
break;
case 0xD9:
command = (u8)parameters[0];
channel->adsr.releaseRate = command;
break;
case 0xD8:
command = (u8)parameters[0];
channel->vibratoExtentTarget = command * 8;
channel->vibratoExtentStart = 0;
channel->vibratoExtentChangeDelay = 0;
break;
case 0xD7:
command = (u8)parameters[0];
channel->vibratoRateChangeDelay = 0;
channel->vibratoRateTarget = command * 32;
channel->vibratoRateStart = command * 32;
break;
case 0xE2:
command = (u8)parameters[0];
channel->vibratoExtentStart = command * 8;
command = (u8)parameters[1];
channel->vibratoExtentTarget = command * 8;
command = (u8)parameters[2];
channel->vibratoExtentChangeDelay = command * 16;
break;
case 0xE1:
command = (u8)parameters[0];
channel->vibratoRateStart = command * 32;
command = (u8)parameters[1];
channel->vibratoRateTarget = command * 32;
command = (u8)parameters[2];
channel->vibratoRateChangeDelay = command * 16;
break;
case 0xE3:
command = (u8)parameters[0];
channel->vibratoDelay = command * 16;
break;
case 0xD4:
command = (u8)parameters[0];
channel->reverb = command;
break;
case 0xC6:
result = (u8)parameters[0]; // category error: should be t not v
command = result;
if (player->defaultBank != 0xFF) {
offset = ((u16*)gAudioContext.unk_283C)[player->seqId];
lowBits = gAudioContext.unk_283C[offset];
command = gAudioContext.unk_283C[offset + lowBits - result];
}
if (func_800DF074(1, 2, command)) {
channel->bankId = command;
}
break;
case 0xC7:
command = (u8)parameters[0];
offset = (u16)parameters[1];
test = &player->seqData[offset];
test[0] = (u8)scriptState->value + command;
break;
case 0xC8:
case 0xCC:
case 0xC9:
signedParam = (s8)parameters[0];
if (command == 0xC8) {
scriptState->value -= signedParam;
} else if (command == 0xCC) {
scriptState->value = signedParam;
} else {
scriptState->value &= signedParam;
}
break;
case 0xCD:
command = (u8)parameters[0];
Audio_SequenceChannelDisable(player->channels[command]);
break;
case 0xCA:
command = (u8)parameters[0];
channel->muteBehavior = command;
channel->changes.s.volume = true;
break;
case 0xCB:
offset = (u16)parameters[0];
scriptState->value = *(offset + scriptState->value + player->seqData);
break;
case 0xCE:
offset = (u16)parameters[0];
channel->unk_22 = offset;
break;
case 0xCF:
offset = (u16)parameters[0];
test = &player->seqData[offset];
test[0] = (channel->unk_22 >> 8) & 0xFF;
test[1] = channel->unk_22 & 0xFF;
break;
case 0xD0:
command = (u8)parameters[0];
if (command & 0x80) {
channel->stereoHeadsetEffects = true;
} else {
channel->stereoHeadsetEffects = false;
}
channel->reverbBits.asByte = command & 0x7F;
break;
case 0xD1:
command = (u8)parameters[0];
channel->noteAllocPolicy = command;
break;
case 0xD2:
command = (u8)parameters[0];
channel->adsr.sustain = command;
break;
case 0xE5:
command = (u8)parameters[0];
channel->reverbIndex = command;
break;
case 0xE4:
if (scriptState->value != -1) {
data = (*channel->dynTable)[scriptState->value];
// @bug: Missing a stack depth check here
scriptState->stack[scriptState->depth++] = scriptState->pc;
offset = (u16)((data[0] << 8) + data[1]);
scriptState->pc = player->seqData + offset;
}
break;
case 0xE6:
command = (u8)parameters[0];
channel->bookOffset = command;
break;
case 0xE7:
offset = (u16)parameters[0];
data = &player->seqData[offset];
channel->muteBehavior = data[0];
data += 3;
channel->noteAllocPolicy = data[-2];
func_800EAEF4(channel, data[-1]);
channel->transposition = (s8)data[0];
data += 4;
channel->newPan = data[-3];
channel->panChannelWeight = data[-2];
channel->reverb = data[-1];
channel->reverbIndex = data[0];
//@bug: Not marking reverb state as changed
channel->changes.s.pan = true;
break;
case 0xE8:
channel->muteBehavior = parameters[0];
channel->noteAllocPolicy = parameters[1];
command = (u8)parameters[2];
func_800EAEF4(channel, command);
channel->transposition = (s8)Audio_M64ReadU8(scriptState);
channel->newPan = Audio_M64ReadU8(scriptState);
channel->panChannelWeight = Audio_M64ReadU8(scriptState);
channel->reverb = Audio_M64ReadU8(scriptState);
channel->reverbIndex = Audio_M64ReadU8(scriptState);
//@bug: Not marking reverb state as changed
channel->changes.s.pan = true;
break;
case 0xEC:
channel->vibratoExtentTarget = 0;
channel->vibratoExtentStart = 0;
channel->vibratoExtentChangeDelay = 0;
channel->vibratoRateTarget = 0;
channel->vibratoRateStart = 0;
channel->vibratoRateChangeDelay = 0;
channel->unk_CC = NULL;
channel->unk_0C = 0;
channel->adsr.sustain = 0;
channel->velocityRandomVariance = 0;
channel->durationRandomVariance = 0;
channel->unk_0F = 0;
channel->unk_20 = 0;
channel->bookOffset = 0;
channel->freqScale = 1.0f;
break;
case 0xE9:
func_800EAEF4(channel, (u8)parameters[0]);
break;
case 0xED:
command = (u8)parameters[0];
channel->unk_0C = command;
break;
case 0xB0:
offset = (u16)parameters[0];
data = player->seqData + offset;
channel->unk_CC = (s16*)data;
break;
case 0xB1:
channel->unk_CC = NULL;
break;
case 0xB3:
command = parameters[0];
if (channel->unk_CC != NULL) {
lowBits = (command >> 4) & 0xF;
command &= 0xF;
func_800DF688(channel->unk_CC, lowBits, command);
}
break;
case 0xB2:
offset = (u16) parameters[0];
channel->unk_22 = *(u16*)(offset + scriptState->value * 2 + player->seqData);
break;
case 0xB4:
channel->dynTable = (void*)&player->seqData[channel->unk_22];
break;
case 0xB5:
channel->unk_22 = ((u16*)(channel->dynTable))[scriptState->value];
break;
case 0xB6:
data = (*channel->dynTable)[0];
scriptState->value = (*channel->dynTable)[0][scriptState->value];
break;
case 0xB7:
channel->unk_22 = (parameters[0] == 0) ? gAudioContext.gAudioRandom // odd load here
: gAudioContext.gAudioRandom % parameters[0];
break;
case 0xB8:
scriptState->value = (parameters[0] == 0) ? gAudioContext.gAudioRandom
: gAudioContext.gAudioRandom % parameters[0];
break;
case 0xBD: {
result = Audio_NextRandom();
channel->unk_22 = (parameters[0] == 0) ? (u32) result : (u32)result % parameters[0];
channel->unk_22 += parameters[1];
pad2 = (channel->unk_22 / 0x100) + 0x80; // i is wrong here
param = channel->unk_22 % 0x100;
channel->unk_22 = (pad2 << 8) | param;
} break;
case 0xB9:
channel->velocityRandomVariance = parameters[0];
break;
case 0xBA:
channel->durationRandomVariance = parameters[0];
break;
case 0xBB:
channel->unk_0F = parameters[0];
channel->unk_20 = parameters[1];
break;
case 0xBC:
channel->unk_22 += parameters[0];
break;
}
}
} else if (command >= 0x70) {
lowBits = command & 0x7;
if ((command & 0xF8) != 0x70 && lowBits >= 4) {
lowBits = 0;
}
switch (command & 0xF8) {
case 0x80:
if (channel->layers[lowBits] != NULL) {
scriptState->value = channel->layers[lowBits]->finished;
} else {
scriptState->value = -1;
}
break;
case 0x88:
offset = Audio_M64ReadS16(scriptState);
if (!Audio_SeqChannelSetLayer(channel, lowBits)) {
channel->layers[lowBits]->scriptState.pc = &player->seqData[offset];
}
break;
case 0x90:
Audio_SeqChannelLayerFree(channel, lowBits);
break;
case 0x98:
if (scriptState->value == -1 || Audio_SeqChannelSetLayer(channel, lowBits) == -1) {
break;
}
data = (*channel->dynTable)[scriptState->value];
offset = (data[0] << 8) + data[1];
channel->layers[lowBits]->scriptState.pc = &player->seqData[offset];
break;
case 0x70:
channel->soundScriptIO[lowBits] = scriptState->value;
break;
case 0x78:
pad1 = Audio_M64ReadS16(scriptState);
if (!Audio_SeqChannelSetLayer(channel, lowBits)) {
channel->layers[lowBits]->scriptState.pc = &scriptState->pc[pad1];
}
break;
}
} else {
lowBits = command & 0xF;
switch (command & 0xF0) {
case 0: {
channel->delay = lowBits;
goto exit_loop;
}
case 0x10:
if (lowBits < 8) {
channel->soundScriptIO[lowBits] = -1;
if (func_800E3414(channel->bankId, scriptState->value,
&channel->soundScriptIO[lowBits]) == -1) {
break;
}
} else {
lowBits -= 8;
channel->soundScriptIO[lowBits] = -1;
if (func_800E3414(channel->bankId, channel->unk_22 + 0x100,
&channel->soundScriptIO[lowBits]) == -1) {
break;
}
}
break;
case 0x60:
scriptState->value = channel->soundScriptIO[lowBits];
if (lowBits < 2) {
channel->soundScriptIO[lowBits] = -1;
}
break;
case 0x50:
scriptState->value -= channel->soundScriptIO[lowBits];
break;
case 0x20:
offset = Audio_M64ReadS16(scriptState);
Audio_SequenceChannelEnable(player, lowBits,
&player->seqData[offset]);
break;
case 0x30:
command = Audio_M64ReadU8(scriptState);
player->channels[lowBits]->soundScriptIO[command] = scriptState->value;
break;
case 0x40:
command = Audio_M64ReadU8(scriptState);
scriptState->value = player->channels[lowBits]->soundScriptIO[command];
break;
}
}
}
exit_loop:
for (i = 0; i < ARRAY_COUNT(channel->layers); i++) {
if (channel->layers[i] != NULL) {
Audio_SeqChannelLayerProcessScript(channel->layers[i]);
}
}
}
#else
void Audio_SequenceChannelProcessScript(SequenceChannel* seqChannel); void Audio_SequenceChannelProcessScript(SequenceChannel* seqChannel);
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequenceChannelProcessScript.s") #pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequenceChannelProcessScript.s")
#endif
#ifdef NON_MATCHING
// regalloc, redundant branch, and extra cast. The large number of pads suggests cases may have their own temp variables.
void Audio_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
u8 command;
u8 commandLow;
u16 offset;
M64ScriptState* seqScript = &seqPlayer->scriptState;
s16 tempS;
u16 temp;
s32 i;
s32 value;
u8* data;
s32 pad1;
s32 pad2;
s32 pad3;
s32 pad4;
if (!seqPlayer->enabled) {
return;
}
if (!Audio_IsSeqLoadComplete(seqPlayer->seqId) || !Audio_IsBankLoadComplete(seqPlayer->defaultBank)) {
Audio_SequencePlayerDisable(seqPlayer);
return;
}
Audio_SetSeqLoadStatus(seqPlayer->seqId, 2);
Audio_SetBankLoadStatus(seqPlayer->defaultBank, 2);
if (seqPlayer->muted && (seqPlayer->muteBehavior & 0x80)) {
return;
}
seqPlayer->unk_E0++;
seqPlayer->tempoAcc += seqPlayer->tempo;
seqPlayer->tempoAcc += (s16)seqPlayer->unk_0C;
if (seqPlayer->tempoAcc < gAudioContext.gTempoInternalToExternal) {
return;
}
seqPlayer->tempoAcc -= (u16)gAudioContext.gTempoInternalToExternal;
if (seqPlayer->unk_0b2 == true) {
return;
}
if (seqPlayer->delay > 1) {
seqPlayer->delay--;
} else {
seqPlayer->recalculateVolume = true;
while (true) {
command = Audio_M64ReadU8(seqScript);
// 0xF2 and above are "flow control" commands, including termination.
if (command >= 0xF2) {
s32 scriptHandled =
Audio_HandleScriptFlowControl(seqPlayer, seqScript, command,
Audio_GetScriptControlFlowArgument(&seqPlayer->scriptState, command));
if (scriptHandled != 0) {
if (scriptHandled == -1) {
Audio_SequencePlayerDisable(seqPlayer);
} else {
seqPlayer->delay = (u16)scriptHandled;
}
break;
}
} else if (command >= 0xC0) {
switch (command) {
case 0xF1:
Audio_NotePoolClear(&seqPlayer->notePool);
Audio_NotePoolFill(&seqPlayer->notePool, Audio_M64ReadU8(seqScript));
break;
break; // This second break appears in the ASM, but the compiler currently optimizes it out.
case 0xF0:
Audio_NotePoolClear(&seqPlayer->notePool);
break;
case 0xDF:
seqPlayer->transposition = 0;
// Note: intentional fallthrough, also executes below command
case 0xDE:
seqPlayer->transposition += (s8)Audio_M64ReadU8(seqScript);
break;
case 0xDD:
seqPlayer->tempo = Audio_M64ReadU8(seqScript) * 48;
if (seqPlayer->tempo > gAudioContext.gTempoInternalToExternal) {
seqPlayer->tempo = (u16)gAudioContext.gTempoInternalToExternal;
}
if ((s16)seqPlayer->tempo <= 0) {
seqPlayer->tempo = 1;
}
break;
case 0xDC:
seqPlayer->unk_0C = (s8)Audio_M64ReadU8(seqScript) * 48;
break;
case 0xDA:
command = Audio_M64ReadU8(seqScript);
offset = Audio_M64ReadS16(seqScript);
switch (command) {
case 0:
case 1:
if (seqPlayer->state != 2) {
seqPlayer->fadeTimerUnkEu = offset;
seqPlayer->state = command;
}
break;
case 2:
seqPlayer->fadeTimer = offset;
seqPlayer->state = command;
seqPlayer->fadeVelocity = (0 - seqPlayer->fadeVolume) / (s32) seqPlayer->fadeTimer;
break;
}
break;
case 0xDB:
value = Audio_M64ReadU8(seqScript);
switch (seqPlayer->state) {
case 1:
seqPlayer->state = 0;
seqPlayer->fadeVolume = 0.0f;
// NOTE: Intentional fallthrough
case 0:
seqPlayer->fadeTimer = seqPlayer->fadeTimerUnkEu;
if (seqPlayer->fadeTimerUnkEu != 0) {
seqPlayer->fadeVelocity = ((value / 127.0f) - seqPlayer->fadeVolume) /
(s32)(seqPlayer->fadeTimer);
} else {
seqPlayer->fadeVolume = (s32)value / 127.0f;
}
break;
case 2:
break;
}
break;
case 0xD9:
seqPlayer->fadeVolumeScale = (s8)Audio_M64ReadU8(seqScript) / 127.0f;
break;
case 0xD7:
tempS = Audio_M64ReadS16(seqScript);
Audio_SequencePlayerInitChannels(seqPlayer, tempS);
break;
case 0xD6:
Audio_M64ReadS16(seqScript);
break;
case 0xD5:
seqPlayer->muteVolumeScale = (s8)Audio_M64ReadU8(seqScript) / 127.0f;
break;
case 0xD4:
seqPlayer->muted = true;
break;
case 0xD3:
seqPlayer->muteBehavior = Audio_M64ReadU8(seqScript);
break;
case 0xD1:
case 0xD2:
temp = Audio_M64ReadS16(seqScript);
data = &seqPlayer->seqData[temp];
if (command == 0xD2) {
seqPlayer->shortNoteVelocityTable = data;
} else {
seqPlayer->shortNoteDurationTable = data;
}
break;
case 0xD0:
seqPlayer->noteAllocPolicy = Audio_M64ReadU8(seqScript);
break;
case 0xCE: {
command = Audio_M64ReadU8(seqScript);
// t register shift here
if (command == 0) {
seqScript->value = gAudioContext.gAudioRandom / 4;
} else {
seqScript->value = (gAudioContext.gAudioRandom / 4) % command;
}
} break;
case 0xCD: {
temp = Audio_M64ReadS16(seqScript);
if ((seqScript->value != -1) && (seqScript->depth != 3)) {
// a/v registers are wrong here. may need to mess with temps
data = &seqPlayer->seqData[temp + seqScript->value * 2]; // should go in v0
seqScript->stack[seqScript->depth] = seqScript->pc;
seqScript->depth++;
offset = (data[0] << 8) + data[1];
seqScript->pc = &seqPlayer->seqData[offset];
}
} break;
case 0xCC:
seqScript->value = Audio_M64ReadU8(seqScript);
break;
case 0xC9:
seqScript->value &= Audio_M64ReadU8(seqScript);
break;
case 0xC8:
seqScript->value -= Audio_M64ReadU8(seqScript);
break;
case 0xC7:
command = Audio_M64ReadU8(seqScript);
offset = Audio_M64ReadS16(seqScript);
data = &seqPlayer->seqData[offset];
data[0] = (u8)seqScript->value + command;
break;
case 0xC6:
seqPlayer->unk_0b2 = true;
return;
case 0xC5:
seqPlayer->unk_E0 = (u16)Audio_M64ReadS16(seqScript);
break;
case 0xEF:
Audio_M64ReadS16(seqScript);
Audio_M64ReadU8(seqScript);
break;
case 0xC4:
command = Audio_M64ReadU8(seqScript);
if (command == 0xFF) {
command = seqPlayer->seqVariationEu;
}
commandLow = Audio_M64ReadU8(seqScript);
func_800E20D4(command, commandLow, 0);
if (command == (u8)seqPlayer->seqVariationEu) {
return;
}
break;
}
} else {
commandLow = command & 0x0F;
switch (command & 0xF0) {
case 0:
seqScript->value = seqPlayer->channels[commandLow]->enabled ^ 1;
break;
case 0x50:
seqScript->value -= seqPlayer->unk_158[commandLow];
break;
case 0x70:
seqPlayer->unk_158[commandLow] = seqScript->value;
break;
case 0x80:
seqScript->value = seqPlayer->unk_158[commandLow];
if (commandLow < 2) {
seqPlayer->unk_158[commandLow] = -1;
}
break;
case 0x40:
Audio_SequenceChannelDisable(seqPlayer->channels[commandLow]);
break;
case 0x90:
temp = Audio_M64ReadS16(seqScript);
Audio_SequenceChannelEnable(seqPlayer, commandLow,
(void*)&seqPlayer->seqData[temp]);
break;
case 0xA0:
tempS = Audio_M64ReadS16(seqScript);
Audio_SequenceChannelEnable(seqPlayer, commandLow,
(void*)&seqScript->pc[tempS]);
break;
case 0xB0:
command = Audio_M64ReadU8(seqScript);
temp = Audio_M64ReadS16(seqScript);
func_800E390C(command, &seqPlayer->seqData[temp],
&seqPlayer->unk_158[commandLow]);
break;
case 0x60: {
command = Audio_M64ReadU8(seqScript); // This shouldn't be cast to u8 when saved
temp = Audio_M64ReadU8(seqScript);
func_800E4EEC(command, temp, &seqPlayer->unk_158[commandLow]);
break;
}
}
}
}
}
for (i = 0; i < ARRAY_COUNT(seqPlayer->channels); i++) {
if (seqPlayer->channels[i]->enabled) {
Audio_SequenceChannelProcessScript(seqPlayer->channels[i]);
}
}
}
#else
void Audio_SequencePlayerProcessSequence(SequencePlayer* seqPlayer); void Audio_SequencePlayerProcessSequence(SequencePlayer* seqPlayer);
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequencePlayerProcessSequence.s") #pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequencePlayerProcessSequence.s")
#endif
void Audio_ProcessSequences(s32 arg0) { void Audio_ProcessSequences(s32 arg0) {
SequencePlayer* seqPlayer; SequencePlayer* seqPlayer;