mirror of
https://github.com/zeldaret/oot.git
synced 2024-12-27 07:07:09 +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:
parent
62df74991d
commit
c952fd4490
3 changed files with 844 additions and 34 deletions
|
@ -2069,7 +2069,7 @@ void Audio_SetSeqLoadStatus(s32 seqId, u8 status);
|
|||
// ? func_800E1F38(?);
|
||||
// ? func_800E1F7C(?);
|
||||
// ? func_800E202C(?);
|
||||
// ? func_800E20D4(?);
|
||||
void func_800E20D4(s32, s32, s32);
|
||||
// ? func_800E2124(?);
|
||||
// ? func_800E217C(?);
|
||||
// ? func_800E22C4(?);
|
||||
|
@ -2096,7 +2096,7 @@ void func_800E3400(void);
|
|||
// ? func_800E36EC(?);
|
||||
// ? func_800E3874(?);
|
||||
// ? func_800E38F8(?);
|
||||
// ? func_800E390C(?);
|
||||
void func_800E390C(s32, void*, void*);
|
||||
void func_800E3A14(void);
|
||||
// ? func_800E3A44(?);
|
||||
// ? func_800E3AC8(?);
|
||||
|
@ -2113,7 +2113,7 @@ void func_800E3A14(void);
|
|||
// ? func_800E48C0(?);
|
||||
// ? func_800E4918(?);
|
||||
void func_800E4D94(void);
|
||||
// ? func_800E4EEC(?);
|
||||
void func_800E4EEC(u32, u32, s8*);
|
||||
// ? func_800E4F58(?);
|
||||
void func_800E4FB0(void);
|
||||
Sub_AudioMgr_18* func_800E4FE0(void);
|
||||
|
|
|
@ -190,21 +190,38 @@ typedef struct {
|
|||
|
||||
// Also known as a Group, according to sm64 debug strings.
|
||||
typedef struct {
|
||||
/* 0x000 */ u8 enabled : 1;
|
||||
/*?0x000 */ u8 finished : 1;
|
||||
/* 0x000 */ u8 muted : 1;
|
||||
/* 0x000 */ u8 seqDmaInProgress : 1;
|
||||
/* 0x000 */ u8 bankDmaInProgress : 1;
|
||||
/*?0x000 */ u8 recalculateVolume : 1;
|
||||
/* 0x000 */ u8 unk_0b2 : 1;
|
||||
/* 0x000 */ u8 unk_0b1 : 1;
|
||||
/* 0x001 */ u8 state;
|
||||
/* 0x002 */ u8 noteAllocPolicy;
|
||||
/* 0x003 */ u8 muteBehavior;
|
||||
union {
|
||||
s32 playerState;
|
||||
struct {
|
||||
/* 0x000 */ u8 enabled : 1;
|
||||
/*?0x000 */ u8 finished : 1;
|
||||
/* 0x000 */ u8 muted : 1;
|
||||
/* 0x000 */ u8 seqDmaInProgress : 1;
|
||||
/* 0x000 */ u8 bankDmaInProgress : 1;
|
||||
/*?0x000 */ u8 recalculateVolume : 1;
|
||||
/* 0x000 */ u8 unk_0b2 : 1;
|
||||
/* 0x000 */ u8 unk_0b1 : 1;
|
||||
/* 0x001 */ u8 state;
|
||||
/* 0x002 */ u8 noteAllocPolicy;
|
||||
union {
|
||||
/* 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;
|
||||
/* 0x005 */ u8 defaultBank;
|
||||
/*?0x006 */ u8 loadingBankId;
|
||||
/*?0x007 */ s8 seqVariationEu[1];
|
||||
/*?0x007 */ s8 seqVariationEu;
|
||||
/* 0x008 */ u16 tempo; // tatums per minute
|
||||
/* 0x00A */ u16 tempoAcc;
|
||||
/* 0x00C */ u16 unk_0C;
|
||||
|
@ -227,7 +244,7 @@ typedef struct {
|
|||
/* 0x098 */ u8* shortNoteDurationTable;
|
||||
/* 0x09C */ NotePool notePool;
|
||||
/* 0x0DC */ s32 unk_DC;
|
||||
/* 0x0D0 */ u32 unk_E0;
|
||||
/* 0x0E0 */ u32 unk_E0;
|
||||
/* 0x0E4 */ u8 pad_E4[0x10]; // OSMesgQueue seqDmaMesgQueue;
|
||||
/*?0x0F4 */ OSMesg seqDmaMesg;
|
||||
/*?0x0F8 */ OSIoMesg seqDmaIoMesg;
|
||||
|
@ -300,24 +317,29 @@ typedef struct {
|
|||
// Also known as a SubTrack, according to sm64 debug strings.
|
||||
// Confusingly, a SubTrack is a container of Tracks.
|
||||
typedef struct SequenceChannel {
|
||||
/* 0x00 */ u8 enabled : 1;
|
||||
/* 0x00 */ u8 finished : 1;
|
||||
/* 0x00 */ u8 stopScript : 1;
|
||||
/* 0x00 */ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
|
||||
/* 0x00 */ u8 hasInstrument : 1;
|
||||
/* 0x00 */ u8 stereoHeadsetEffects : 1;
|
||||
/* 0x00 */ u8 largeNotes : 1; // notes specify duration and velocity
|
||||
/* 0x00 */ u8 unused : 1; // still unused?
|
||||
union {
|
||||
s32 channelState;
|
||||
struct {
|
||||
/* 0x01 */ u8 freqScale : 1;
|
||||
/* 0x01 */ u8 volume : 1;
|
||||
/* 0x01 */ u8 pan : 1;
|
||||
} s;
|
||||
/* 0x01 */ u8 asByte;
|
||||
} changes;
|
||||
/* 0x02 */ u8 noteAllocPolicy;
|
||||
/* 0x03 */ u8 muteBehavior;
|
||||
/* 0x00 */ u8 enabled : 1;
|
||||
/* 0x00 */ u8 finished : 1;
|
||||
/* 0x00 */ u8 stopScript : 1;
|
||||
/* 0x00 */ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
|
||||
/* 0x00 */ u8 hasInstrument : 1;
|
||||
/* 0x00 */ u8 stereoHeadsetEffects : 1;
|
||||
/* 0x00 */ u8 largeNotes : 1; // notes specify duration and velocity
|
||||
/* 0x00 */ u8 unused : 1; // still unused?
|
||||
union {
|
||||
struct {
|
||||
/* 0x01 */ u8 freqScale : 1;
|
||||
/* 0x01 */ u8 volume : 1;
|
||||
/* 0x01 */ u8 pan : 1;
|
||||
} s;
|
||||
/* 0x01 */ u8 asByte;
|
||||
} changes;
|
||||
/* 0x02 */ u8 noteAllocPolicy;
|
||||
/* 0x03 */ u8 muteBehavior;
|
||||
};
|
||||
};
|
||||
/* 0x04 */ u8 reverb; // or dry/wet mix
|
||||
/* 0x05 */ u8 notePriority; // 0-3
|
||||
/* 0x06 */ u8 someOtherPriority;
|
||||
|
@ -339,7 +361,7 @@ typedef struct SequenceChannel {
|
|||
/* 0x1C */ u16 vibratoDelay;
|
||||
/* 0x1E */ u16 delay;
|
||||
/* 0x20 */ u16 unk_20;
|
||||
/* 0x22 */ u16 pad_22;
|
||||
/* 0x22 */ u16 unk_22;
|
||||
/* 0x24 */ s16 instOrWave; // either 0 (none), instrument index + 1, or
|
||||
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
|
||||
/* 0x26 */ s16 transposition;
|
||||
|
@ -671,7 +693,8 @@ typedef struct {
|
|||
/* 0x2624 */ char unk_2624[0x210];
|
||||
/* 0x2834 */ s16* unk_2834;
|
||||
/* 0x2838 */ ManyStruct_800E0E0C_2* unk_2838;
|
||||
/* 0x283C */ char unk_283C[0x8];
|
||||
/* 0x283C */ u8* unk_283C;
|
||||
/* 0x2840 */ char unk_2840[0x4];
|
||||
/* 0x2844 */ CtlEntry* gCtlEntries;
|
||||
/* 0x2848 */ AudioBufferParameters gAudioBufferParameters;
|
||||
/* 0x2870 */ f32 unk_2870;
|
||||
|
|
|
@ -374,6 +374,7 @@ s32 func_800E9F64(SequenceChannelLayer* layer, s32 arg1);
|
|||
s32 func_800EA0C0(SequenceChannelLayer* layer);
|
||||
s32 func_800EA440(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) {
|
||||
s32 val;
|
||||
|
@ -956,11 +957,797 @@ void Audio_SequenceChannelSetVolume(SequenceChannel* seqChannel, u8 volume) {
|
|||
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);
|
||||
#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);
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequencePlayerProcessSequence.s")
|
||||
#endif
|
||||
|
||||
void Audio_ProcessSequences(s32 arg0) {
|
||||
SequencePlayer* seqPlayer;
|
||||
|
|
Loading…
Reference in a new issue