1
Fork 0
sm64/src/audio/seqplayer.c

2855 lines
101 KiB
C
Raw Normal View History

2020-06-02 12:44:34 -04:00
#include <PR/ultratypes.h>
2019-08-25 00:46:40 -04:00
#include "data.h"
2020-06-02 12:44:34 -04:00
#include "effects.h"
#include "external.h"
#include "heap.h"
2019-08-25 00:46:40 -04:00
#include "load.h"
#include "seqplayer.h"
2019-12-01 21:52:53 -05:00
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
#define PORTAMENTO_MODE_1 1
#define PORTAMENTO_MODE_2 2
#define PORTAMENTO_MODE_3 3
#define PORTAMENTO_MODE_4 4
#define PORTAMENTO_MODE_5 5
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
void seq_channel_layer_process_script_part1(struct SequenceChannelLayer *layer);
s32 seq_channel_layer_process_script_part2(struct SequenceChannelLayer *layer);
s32 seq_channel_layer_process_script_part3(struct SequenceChannelLayer *layer, s32 cmd);
s32 seq_channel_layer_process_script_part4(struct SequenceChannelLayer *layer, s32 cmd);
s32 seq_channel_layer_process_script_part5(struct SequenceChannelLayer *layer, s32 cmd);
#endif
2019-08-25 00:46:40 -04:00
void seq_channel_layer_process_script(struct SequenceChannelLayer *layer);
void sequence_channel_process_script(struct SequenceChannel *seqChannel);
2020-02-03 00:51:26 -05:00
u8 get_instrument(struct SequenceChannel *seqChannel, u8 instId, struct Instrument **instOut,
struct AdsrSettings *adsr);
2019-08-25 00:46:40 -04:00
void sequence_channel_init(struct SequenceChannel *seqChannel) {
s32 i;
seqChannel->enabled = FALSE;
seqChannel->finished = FALSE;
seqChannel->stopScript = FALSE;
2019-12-01 21:52:53 -05:00
seqChannel->stopSomething2 = FALSE;
2019-08-25 00:46:40 -04:00
seqChannel->hasInstrument = FALSE;
seqChannel->stereoHeadsetEffects = FALSE;
seqChannel->transposition = 0;
seqChannel->largeNotes = FALSE;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->bookOffset = 0;
seqChannel->changes.as_u8 = 0xff;
2020-02-03 00:51:26 -05:00
seqChannel->scriptState.depth = 0;
2020-03-01 22:42:52 -05:00
seqChannel->newPan = 0x40;
seqChannel->panChannelWeight = 0x80;
2020-02-03 00:51:26 -05:00
seqChannel->noteUnused = NULL;
seqChannel->reverbIndex = 0;
#else
2019-08-25 00:46:40 -04:00
seqChannel->scriptState.depth = 0;
seqChannel->volume = 1.0f;
seqChannel->volumeScale = 1.0f;
seqChannel->freqScale = 1.0f;
seqChannel->pan = 0.5f;
seqChannel->panChannelWeight = 1.0f;
seqChannel->noteUnused = NULL;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqChannel->reverb = 0;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqChannel->unkSH0C = 0;
#endif
2019-08-25 00:46:40 -04:00
seqChannel->notePriority = NOTE_PRIORITY_DEFAULT;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqChannel->unkSH06 = 1;
#endif
2019-08-25 00:46:40 -04:00
seqChannel->delay = 0;
seqChannel->adsr.envelope = gDefaultEnvelope;
seqChannel->adsr.releaseRate = 0x20;
seqChannel->adsr.sustain = 0;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-08-25 00:46:40 -04:00
seqChannel->updatesPerFrameUnused = gAudioUpdatesPerFrame;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqChannel->vibratoRateTarget = 0x800;
seqChannel->vibratoRateStart = 0x800;
seqChannel->vibratoExtentTarget = 0;
seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoRateChangeDelay = 0;
seqChannel->vibratoExtentChangeDelay = 0;
seqChannel->vibratoDelay = 0;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqChannel->filter = NULL;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
seqChannel->volume = 1.0f;
seqChannel->volumeScale = 1.0f;
seqChannel->freqScale = 1.0f;
#endif
2019-08-25 00:46:40 -04:00
for (i = 0; i < 8; i++) {
seqChannel->soundScriptIO[i] = -1;
}
seqChannel->unused = FALSE;
init_note_lists(&seqChannel->notePool);
}
s32 seq_channel_set_layer(struct SequenceChannel *seqChannel, s32 layerIndex) {
struct SequenceChannelLayer *layer;
if (seqChannel->layers[layerIndex] == NULL) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
struct SequenceChannelLayer *layer;
#endif
2019-08-25 00:46:40 -04:00
layer = audio_list_pop_back(&gLayerFreeList);
seqChannel->layers[layerIndex] = layer;
if (layer == NULL) {
seqChannel->layers[layerIndex] = NULL;
return -1;
}
} else {
seq_channel_layer_note_decay(seqChannel->layers[layerIndex]);
}
layer = seqChannel->layers[layerIndex];
layer->seqChannel = seqChannel;
layer->adsr = seqChannel->adsr;
layer->adsr.releaseRate = 0;
layer->enabled = TRUE;
2019-12-01 21:52:53 -05:00
layer->stopSomething = FALSE;
layer->continuousNotes = FALSE;
2019-08-25 00:46:40 -04:00
layer->finished = FALSE;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
layer->ignoreDrumPan = FALSE;
2020-12-03 14:26:38 -05:00
#endif
#ifdef VERSION_SH
layer->reverbBits.asByte = 0x40;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
layer->portamento.mode = 0;
layer->scriptState.depth = 0;
2019-12-01 21:52:53 -05:00
layer->status = SOUND_LOAD_STATUS_NOT_LOADED;
2019-08-25 00:46:40 -04:00
layer->noteDuration = 0x80;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
layer->pan = 0x40;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
layer->transposition = 0;
layer->delay = 0;
layer->duration = 0;
layer->delayUnused = 0;
layer->note = NULL;
layer->instrument = NULL;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
layer->freqScale = 1.0f;
layer->velocitySquare = 0.0f;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
layer->unkSH28 = 1.0f;
#endif
2020-03-01 22:42:52 -05:00
layer->instOrWave = 0xff;
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
layer->velocitySquare = 0.0f;
layer->pan = 0.5f;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
return 0;
}
void seq_channel_layer_disable(struct SequenceChannelLayer *layer) {
if (layer != NULL) {
seq_channel_layer_note_decay(layer);
layer->enabled = FALSE;
layer->finished = TRUE;
}
}
void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex) {
struct SequenceChannelLayer *layer = seqChannel->layers[layerIndex];
if (layer != NULL) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
audio_list_push_back(&gLayerFreeList, &layer->listItem);
#else
struct AudioListItem *item = &layer->listItem;
2019-08-25 00:46:40 -04:00
if (item->prev == NULL) {
gLayerFreeList.prev->next = item;
item->prev = gLayerFreeList.prev;
item->next = &gLayerFreeList;
gLayerFreeList.prev = item;
gLayerFreeList.u.count++;
item->pool = gLayerFreeList.pool;
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seq_channel_layer_disable(layer);
seqChannel->layers[layerIndex] = NULL;
}
}
void sequence_channel_disable(struct SequenceChannel *seqChannel) {
s32 i;
2019-12-01 21:52:53 -05:00
for (i = 0; i < LAYERS_MAX; i++) {
2019-08-25 00:46:40 -04:00
seq_channel_layer_free(seqChannel, i);
}
note_pool_clear(&seqChannel->notePool);
seqChannel->enabled = FALSE;
seqChannel->finished = TRUE;
}
struct SequenceChannel *allocate_sequence_channel(void) {
s32 i;
for (i = 0; i < ARRAY_COUNT(gSequenceChannels); i++) {
if (gSequenceChannels[i].seqPlayer == NULL) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
return &gSequenceChannels[i];
#else
2019-08-25 00:46:40 -04:00
return gSequenceChannels + i;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
}
return &gSequenceChannelNone;
}
void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
struct SequenceChannel *seqChannel;
s32 i;
for (i = 0; i < CHANNELS_MAX; i++) {
if (channelBits & 1) {
seqChannel = seqPlayer->channels[i];
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == TRUE && seqChannel->seqPlayer == seqPlayer) {
sequence_channel_disable(seqChannel);
seqChannel->seqPlayer = NULL;
}
seqChannel = allocate_sequence_channel();
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) {
2020-09-20 11:15:47 -04:00
eu_stubbed_printf_0("Audio:Track:Warning: No Free Notetrack\n");
2019-08-25 00:46:40 -04:00
gAudioErrorFlags = i + 0x10000;
seqPlayer->channels[i] = seqChannel;
} else {
sequence_channel_init(seqChannel);
seqPlayer->channels[i] = seqChannel;
seqChannel->seqPlayer = seqPlayer;
2019-12-01 21:52:53 -05:00
seqChannel->bankId = seqPlayer->defaultBank[0];
2019-08-25 00:46:40 -04:00
seqChannel->muteBehavior = seqPlayer->muteBehavior;
seqChannel->noteAllocPolicy = seqPlayer->noteAllocPolicy;
}
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
channelBits = channelBits >> 1;
#else
2019-08-25 00:46:40 -04:00
channelBits >>= 1;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
}
void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
struct SequenceChannel *seqChannel;
s32 i;
2020-09-20 11:15:47 -04:00
eu_stubbed_printf_0("SUBTRACK DIM\n");
2019-08-25 00:46:40 -04:00
for (i = 0; i < CHANNELS_MAX; i++) {
if (channelBits & 1) {
seqChannel = seqPlayer->channels[i];
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == TRUE) {
if (seqChannel->seqPlayer == seqPlayer) {
sequence_channel_disable(seqChannel);
seqChannel->seqPlayer = NULL;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-09-20 11:15:47 -04:00
else {
2020-12-03 14:26:38 -05:00
#ifdef VERSION_EU
2020-09-20 11:15:47 -04:00
stubbed_printf("Audio:Track: Warning SUBTRACK PARENT CHANGED\n");
2020-12-03 14:26:38 -05:00
#endif
2020-09-20 11:15:47 -04:00
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->channels[i] = &gSequenceChannelNone;
}
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
channelBits = channelBits >> 1;
#else
2019-08-25 00:46:40 -04:00
channelBits >>= 1;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
}
2020-09-20 11:15:47 -04:00
void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *script) {
2019-08-25 00:46:40 -04:00
struct SequenceChannel *seqChannel = seqPlayer->channels[channelIndex];
s32 i;
2020-02-03 00:51:26 -05:00
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) {
2020-09-20 11:15:47 -04:00
#ifdef VERSION_EU
2020-03-01 22:42:52 -05:00
struct SequencePlayer *bgMusic = &gSequencePlayers[0];
struct SequencePlayer *miscMusic = &gSequencePlayers[1];
if (seqPlayer == bgMusic) {
2020-09-20 11:15:47 -04:00
stubbed_printf("GROUP 0:");
2020-03-01 22:42:52 -05:00
} else if (seqPlayer == miscMusic) {
2020-09-20 11:15:47 -04:00
stubbed_printf("GROUP 1:");
2020-03-01 22:42:52 -05:00
} else {
2020-09-20 11:15:47 -04:00
stubbed_printf("SEQID %d,BANKID %d\n",
seqPlayer->seqId, seqPlayer->defaultBank[0]);
2020-02-03 00:51:26 -05:00
}
2020-09-20 11:15:47 -04:00
stubbed_printf("ERR:SUBTRACK %d NOT ALLOCATED\n", channelIndex);
2020-02-03 00:51:26 -05:00
#endif
2020-09-20 11:15:47 -04:00
} else {
2019-08-25 00:46:40 -04:00
seqChannel->enabled = TRUE;
seqChannel->finished = FALSE;
seqChannel->scriptState.depth = 0;
2020-09-20 11:15:47 -04:00
seqChannel->scriptState.pc = script;
2019-08-25 00:46:40 -04:00
seqChannel->delay = 0;
2019-12-01 21:52:53 -05:00
for (i = 0; i < LAYERS_MAX; i++) {
2019-08-25 00:46:40 -04:00
if (seqChannel->layers[i] != NULL) {
seq_channel_layer_free(seqChannel, i);
}
}
}
}
void sequence_player_disable(struct SequencePlayer *seqPlayer) {
sequence_player_disable_channels(seqPlayer, 0xffff);
note_pool_clear(&seqPlayer->notePool);
seqPlayer->finished = TRUE;
seqPlayer->enabled = FALSE;
2020-12-03 14:26:38 -05:00
if (IS_SEQ_LOAD_COMPLETE(seqPlayer->seqId)
#ifdef VERSION_SH
&& gSeqLoadStatus[seqPlayer->seqId] != 5
#endif
) {
2019-08-25 00:46:40 -04:00
gSeqLoadStatus[seqPlayer->seqId] = SOUND_LOAD_STATUS_DISCARDABLE;
}
2020-12-03 14:26:38 -05:00
if (IS_BANK_LOAD_COMPLETE(seqPlayer->defaultBank[0])
#ifdef VERSION_SH
&& gBankLoadStatus[seqPlayer->defaultBank[0]] != 5
#endif
) {
#ifdef VERSION_SH
gBankLoadStatus[seqPlayer->defaultBank[0]] = 4;
#else
2019-12-01 21:52:53 -05:00
gBankLoadStatus[seqPlayer->defaultBank[0]] = SOUND_LOAD_STATUS_DISCARDABLE;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
// (Note that if this is called from alloc_bank_or_seq, the side will get swapped
// later in that function. Thus, we signal that we want to load into the slot
// of the bank that we no longer need.)
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
if (seqPlayer->defaultBank[0] == gBankLoadedPool.temporary.entries[0].id) {
gBankLoadedPool.temporary.nextSide = 1;
} else if (seqPlayer->defaultBank[0] == gBankLoadedPool.temporary.entries[1].id) {
gBankLoadedPool.temporary.nextSide = 0;
}
#else
2019-12-01 21:52:53 -05:00
if (gBankLoadedPool.temporary.entries[0].id == seqPlayer->defaultBank[0]) {
2019-08-25 00:46:40 -04:00
gBankLoadedPool.temporary.nextSide = 1;
2019-12-01 21:52:53 -05:00
} else if (gBankLoadedPool.temporary.entries[1].id == seqPlayer->defaultBank[0]) {
2019-08-25 00:46:40 -04:00
gBankLoadedPool.temporary.nextSide = 0;
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
/**
* Add an item to the end of a list, if it's not already in any list.
*/
void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item) {
2020-09-20 11:15:47 -04:00
if (item->prev != NULL) {
eu_stubbed_printf_0("Error:Same List Add\n");
} else {
2019-08-25 00:46:40 -04:00
list->prev->next = item;
item->prev = list->prev;
item->next = list;
list->prev = item;
list->u.count++;
item->pool = list->pool;
}
}
/**
* Remove the last item from a list, and return it (or NULL if empty).
*/
void *audio_list_pop_back(struct AudioListItem *list) {
struct AudioListItem *item = list->prev;
if (item == list) {
return NULL;
}
item->prev->next = list;
list->prev = item->prev;
item->prev = NULL;
list->u.count--;
return item->u.value;
}
2019-12-01 21:52:53 -05:00
void init_layer_freelist(void) {
2019-08-25 00:46:40 -04:00
s32 i;
gLayerFreeList.prev = &gLayerFreeList;
gLayerFreeList.next = &gLayerFreeList;
gLayerFreeList.u.count = 0;
gLayerFreeList.pool = NULL;
2019-12-01 21:52:53 -05:00
for (i = 0; i < ARRAY_COUNT(gSequenceLayers); i++) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
gSequenceLayers[i].listItem.u.value = &gSequenceLayers[i];
#else
2019-12-01 21:52:53 -05:00
gSequenceLayers[i].listItem.u.value = gSequenceLayers + i;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
gSequenceLayers[i].listItem.prev = NULL;
audio_list_push_back(&gLayerFreeList, &gSequenceLayers[i].listItem);
2019-08-25 00:46:40 -04:00
}
}
u8 m64_read_u8(struct M64ScriptState *state) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
return *(state->pc++);
#else
2019-08-25 00:46:40 -04:00
u8 *midiArg = state->pc++;
return *midiArg;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
s16 m64_read_s16(struct M64ScriptState *state) {
s16 ret = *(state->pc++) << 8;
ret = *(state->pc++) | ret;
return ret;
}
u16 m64_read_compressed_u16(struct M64ScriptState *state) {
u16 ret = *(state->pc++);
if (ret & 0x80) {
ret = (ret << 8) & 0x7f00;
ret = *(state->pc++) | ret;
}
return ret;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_SH)
void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) {
s32 cmd;
if (layer->enabled == FALSE) {
return;
}
if (layer->delay > 1) {
layer->delay--;
if (!layer->stopSomething && layer->delay <= layer->duration) {
seq_channel_layer_note_decay(layer);
layer->stopSomething = TRUE;
}
return;
}
seq_channel_layer_process_script_part1(layer);
cmd = seq_channel_layer_process_script_part2(layer);
if (cmd != -1) {
cmd = seq_channel_layer_process_script_part3(layer, cmd);
if (cmd != -1) {
cmd = seq_channel_layer_process_script_part4(layer, cmd);
}
if (cmd != -1) {
seq_channel_layer_process_script_part5(layer, cmd);
}
if (layer->stopSomething == TRUE) {
if (layer->note != NULL || layer->continuousNotes) {
seq_channel_layer_note_decay(layer);
}
}
}
}
#elif defined(VERSION_EU)
2019-08-25 00:46:40 -04:00
void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) {
2020-12-03 14:26:38 -05:00
struct SequencePlayer *seqPlayer;
struct SequenceChannel *seqChannel;
2020-06-02 12:44:34 -04:00
#ifdef VERSION_EU
2020-12-03 14:26:38 -05:00
UNUSED u32 pad0;
2020-02-03 00:51:26 -05:00
#endif
2020-12-03 14:26:38 -05:00
struct M64ScriptState *state;
struct Portamento *portamento;
struct AudioBankSound *sound;
struct Instrument *instrument;
2019-08-25 00:46:40 -04:00
struct Drum *drum;
2020-12-03 14:26:38 -05:00
s32 temp_a0_5;
2020-02-03 00:51:26 -05:00
#ifdef VERSION_EU
2020-12-03 14:26:38 -05:00
u16 sp3A;
2020-02-03 00:51:26 -05:00
s32 sameSound;
#endif
2020-12-03 14:26:38 -05:00
UNUSED u32 pad1;
2020-06-02 12:44:34 -04:00
#ifndef VERSION_EU
2020-12-03 14:26:38 -05:00
u8 sameSound;
2020-06-02 12:44:34 -04:00
#endif
2020-12-03 14:26:38 -05:00
u8 cmd;
UNUSED u8 cmdSemitone;
#ifndef VERSION_EU
u16 sp3A;
2020-02-03 00:51:26 -05:00
#endif
2020-12-03 14:26:38 -05:00
f32 tuning;
s32 vel;
UNUSED s32 usedSemitone;
f32 freqScale;
2020-02-03 00:51:26 -05:00
#ifndef VERSION_EU
2020-12-03 14:26:38 -05:00
UNUSED f32 sp24;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
f32 temp_f12;
f32 temp_f2;
sameSound = TRUE;
if (layer->enabled == FALSE) {
return;
}
if (layer->delay > 1) {
layer->delay--;
2019-12-01 21:52:53 -05:00
if (!layer->stopSomething && layer->delay <= layer->duration) {
2019-08-25 00:46:40 -04:00
seq_channel_layer_note_decay(layer);
2019-12-01 21:52:53 -05:00
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
}
return;
}
2019-12-01 21:52:53 -05:00
if (!layer->continuousNotes) {
2019-08-25 00:46:40 -04:00
seq_channel_layer_note_decay(layer);
}
2019-12-01 21:52:53 -05:00
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1 ||
PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2) {
2019-08-25 00:46:40 -04:00
layer->portamento.mode = 0;
}
seqChannel = layer->seqChannel;
seqPlayer = seqChannel->seqPlayer;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
layer->notePropertiesNeedInit = TRUE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
for (;;) {
state = &layer->scriptState;
2020-02-03 00:51:26 -05:00
cmd = m64_read_u8(state);
2020-06-02 12:44:34 -04:00
2019-08-25 00:46:40 -04:00
if (cmd <= 0xc0) {
break;
}
switch (cmd) {
2019-12-01 21:52:53 -05:00
case 0xff: // layer_end; function return or end of script
2019-08-25 00:46:40 -04:00
if (state->depth == 0) {
// N.B. this function call is *not* inlined even though it's
// within the same file, unlike in the rest of this function.
seq_channel_layer_disable(layer);
return;
}
2020-06-02 12:44:34 -04:00
state->pc = state->stack[--state->depth];
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xfc: // layer_call
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
2020-02-03 00:51:26 -05:00
sp3A = m64_read_s16(state);
state->stack[state->depth++] = state->pc;
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + sp3A;
break;
2019-12-01 21:52:53 -05:00
case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0)
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
2020-02-03 00:51:26 -05:00
state->remLoopIters[state->depth] = m64_read_u8(state);
state->stack[state->depth++] = state->pc;
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xf7: // layer_loopend
2020-06-02 12:44:34 -04:00
if (--state->remLoopIters[state->depth - 1] != 0) {
2019-08-25 00:46:40 -04:00
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
2019-12-01 21:52:53 -05:00
case 0xfb: // layer_jump
2020-02-03 00:51:26 -05:00
sp3A = m64_read_s16(state);
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + sp3A;
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf4:
2020-06-02 12:44:34 -04:00
state->pc += (s8)m64_read_u8(state);
2020-02-03 00:51:26 -05:00
break;
#endif
2019-12-01 21:52:53 -05:00
case 0xc1: // layer_setshortnotevelocity
case 0xca: // layer_setpan
2019-08-25 00:46:40 -04:00
temp_a0_5 = *(state->pc++);
if (cmd == 0xc1) {
layer->velocitySquare = (f32)(temp_a0_5 * temp_a0_5);
} else {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
layer->pan = temp_a0_5;
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
layer->pan = (f32) temp_a0_5 / US_FLOAT(128.0);
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
break;
2019-12-01 21:52:53 -05:00
case 0xc2: // layer_transpose; set transposition in semitones
case 0xc9: // layer_setshortnoteduration
2020-12-03 14:26:38 -05:00
temp_a0_5 = *(state->pc++);
2019-08-25 00:46:40 -04:00
if (cmd == 0xc9) {
2020-12-03 14:26:38 -05:00
layer->noteDuration = temp_a0_5;
2019-08-25 00:46:40 -04:00
} else {
2020-12-03 14:26:38 -05:00
layer->transposition = temp_a0_5;
2019-08-25 00:46:40 -04:00
}
break;
2019-12-01 21:52:53 -05:00
case 0xc4: // layer_somethingon
case 0xc5: // layer_somethingoff
2020-02-03 00:51:26 -05:00
if (cmd == 0xc4) {
layer->continuousNotes = TRUE;
} else {
layer->continuousNotes = FALSE;
}
2019-08-25 00:46:40 -04:00
seq_channel_layer_note_decay(layer);
break;
2019-12-01 21:52:53 -05:00
case 0xc3: // layer_setshortnotedefaultplaypercentage
2020-02-03 00:51:26 -05:00
sp3A = m64_read_compressed_u16(state);
2019-08-25 00:46:40 -04:00
layer->shortNoteDefaultPlayPercentage = sp3A;
break;
2019-12-01 21:52:53 -05:00
case 0xc6: // layer_setinstr
2020-06-02 12:44:34 -04:00
cmd = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2020-06-02 12:44:34 -04:00
if (cmd < 127) {
cmd = get_instrument(seqChannel, cmd, &layer->instrument, &layer->adsr);
}
2020-02-03 00:51:26 -05:00
#else
2020-06-02 12:44:34 -04:00
if (cmd >= 0x7f) {
if (cmd == 0x7f) {
2020-03-01 22:42:52 -05:00
layer->instOrWave = 0;
2020-02-03 00:51:26 -05:00
} else {
2020-06-02 12:44:34 -04:00
layer->instOrWave = cmd;
2020-02-03 00:51:26 -05:00
layer->instrument = NULL;
}
2019-08-25 00:46:40 -04:00
2020-06-02 12:44:34 -04:00
if (1) {
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
if (cmd == 0xff) {
layer->adsr.releaseRate = 0;
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
break;
2019-08-25 00:46:40 -04:00
}
2020-09-20 11:15:47 -04:00
if ((layer->instOrWave = get_instrument(seqChannel, cmd, &layer->instrument, &layer->adsr)) == 0) {
eu_stubbed_printf_1("WARNING: NPRG: cannot change %d\n", cmd);
2020-06-02 12:44:34 -04:00
layer->instOrWave = 0xff;
2019-08-25 00:46:40 -04:00
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xc7: // layer_portamento
2020-02-03 00:51:26 -05:00
layer->portamento.mode = m64_read_u8(state);
2020-06-02 12:44:34 -04:00
// cmd is reused for the portamento's semitone
cmd = m64_read_u8(state) + seqChannel->transposition +
2019-12-01 21:52:53 -05:00
layer->transposition + seqPlayer->transposition;
2020-06-02 12:44:34 -04:00
if (cmd >= 0x80) {
cmd = 0;
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
layer->portamentoTargetNote = cmd;
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
// If special, the next param is u8 instead of var
if (PORTAMENTO_IS_SPECIAL(layer->portamento)) {
2020-06-02 12:44:34 -04:00
layer->portamentoTime = *((state)->pc++);
2019-08-25 00:46:40 -04:00
break;
}
2020-02-03 00:51:26 -05:00
sp3A = m64_read_compressed_u16(state);
2019-08-25 00:46:40 -04:00
layer->portamentoTime = sp3A;
break;
2019-12-01 21:52:53 -05:00
case 0xc8: // layer_disableportamento
2019-08-25 00:46:40 -04:00
layer->portamento.mode = 0;
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xcb:
sp3A = m64_read_s16(state);
layer->adsr.envelope = (struct AdsrEnvelope *) (seqPlayer->seqData + sp3A);
layer->adsr.releaseRate = m64_read_u8(state);
break;
case 0xcc:
2020-03-01 22:42:52 -05:00
layer->ignoreDrumPan = TRUE;
2020-02-03 00:51:26 -05:00
break;
#endif
2019-08-25 00:46:40 -04:00
default:
switch (cmd & 0xf0) {
2019-12-01 21:52:53 -05:00
case 0xd0: // layer_setshortnotevelocityfromtable
2020-06-02 12:44:34 -04:00
sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xf];
2019-08-25 00:46:40 -04:00
layer->velocitySquare = (f32)(sp3A * sp3A);
break;
2019-12-01 21:52:53 -05:00
case 0xe0: // layer_setshortnotedurationfromtable
2020-06-02 12:44:34 -04:00
layer->noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf];
2019-08-25 00:46:40 -04:00
break;
2020-09-20 11:15:47 -04:00
default:
eu_stubbed_printf_1("Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n", cmd);
break;
2019-08-25 00:46:40 -04:00
}
}
}
2020-06-02 12:44:34 -04:00
if (cmd == 0xc0) { // layer_delay
layer->delay = m64_read_compressed_u16(state);
2019-12-01 21:52:53 -05:00
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
} else {
2019-12-01 21:52:53 -05:00
layer->stopSomething = FALSE;
2019-08-25 00:46:40 -04:00
if (seqChannel->largeNotes == TRUE) {
2020-06-02 12:44:34 -04:00
switch (cmd & 0xc0) {
2019-12-01 21:52:53 -05:00
case 0x00: // layer_note0 (play percentage, velocity, duration)
2020-02-03 00:51:26 -05:00
sp3A = m64_read_compressed_u16(state);
2019-12-01 21:52:53 -05:00
vel = *(state->pc++);
2019-08-25 00:46:40 -04:00
layer->noteDuration = *(state->pc++);
layer->playPercentage = sp3A;
break;
2019-12-01 21:52:53 -05:00
case 0x40: // layer_note1 (play percentage, velocity)
2020-02-03 00:51:26 -05:00
sp3A = m64_read_compressed_u16(state);
2019-12-01 21:52:53 -05:00
vel = *(state->pc++);
2019-08-25 00:46:40 -04:00
layer->noteDuration = 0;
layer->playPercentage = sp3A;
break;
2019-12-01 21:52:53 -05:00
case 0x80: // layer_note2 (velocity, duration; uses last play percentage)
2020-06-02 12:44:34 -04:00
sp3A = layer->playPercentage;
2019-12-01 21:52:53 -05:00
vel = *(state->pc++);
2019-08-25 00:46:40 -04:00
layer->noteDuration = *(state->pc++);
break;
}
2020-06-02 12:44:34 -04:00
// the remaining bits are used for the semitone
cmd -= (cmd & 0xc0);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-06-02 12:44:34 -04:00
layer->velocitySquare = (f32)(vel) * (f32)vel;
2020-02-03 00:51:26 -05:00
#else
2019-12-01 21:52:53 -05:00
layer->velocitySquare = vel * vel;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
} else {
2020-06-02 12:44:34 -04:00
switch (cmd & 0xc0) {
2019-08-25 00:46:40 -04:00
case 0x00: // play note, type 0 (play percentage)
2020-02-03 00:51:26 -05:00
sp3A = m64_read_compressed_u16(state);
2019-08-25 00:46:40 -04:00
layer->playPercentage = sp3A;
break;
case 0x40: // play note, type 1 (uses default play percentage)
sp3A = layer->shortNoteDefaultPlayPercentage;
break;
case 0x80: // play note, type 2 (uses last play percentage)
sp3A = layer->playPercentage;
break;
}
2020-06-02 12:44:34 -04:00
// the remaining bits are used for the semitone
cmd -= cmd & 0xc0;
2019-08-25 00:46:40 -04:00
}
layer->delay = sp3A;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
layer->duration = layer->noteDuration * sp3A >> 8;
#else
2019-08-25 00:46:40 -04:00
layer->duration = layer->noteDuration * sp3A / 256;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
if ((seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES) != 0)
2020-02-03 00:51:26 -05:00
|| seqChannel->stopSomething2
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2020-02-03 00:51:26 -05:00
|| !seqChannel->hasInstrument
#endif
) {
2019-12-01 21:52:53 -05:00
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
} else {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-06-02 12:44:34 -04:00
s32 temp = layer->instOrWave;
if (temp == 0xff) temp = seqChannel->instOrWave;
if (temp == 0)
2020-02-03 00:51:26 -05:00
#else
2020-06-02 12:44:34 -04:00
if (seqChannel->instOrWave == 0)
#endif
{ // drum
// cmd is reused for the drum semitone
cmd += seqChannel->transposition + layer->transposition;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU)
2020-06-02 12:44:34 -04:00
drum = get_drum(seqChannel->bankId, cmd);
#else
if (cmd >= gCtlEntries[seqChannel->bankId].numDrums) {
cmd = gCtlEntries[seqChannel->bankId].numDrums;
if (cmd == 0) {
2019-12-01 21:52:53 -05:00
// this goto looks a bit like a function return...
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
goto skip;
}
2020-06-02 12:44:34 -04:00
cmd--;
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
drum = gCtlEntries[seqChannel->bankId].drums[cmd];
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
if (drum == NULL) {
2019-12-01 21:52:53 -05:00
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
} else {
layer->adsr.envelope = drum->envelope;
layer->adsr.releaseRate = drum->releaseRate;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
if (!layer->ignoreDrumPan) {
layer->pan = drum->pan;
2020-02-03 00:51:26 -05:00
}
#else
2019-12-01 21:52:53 -05:00
layer->pan = FLOAT_CAST(drum->pan) / US_FLOAT(128.0);
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
layer->sound = &drum->sound;
layer->freqScale = layer->sound->tuning;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US) || defined(VERSION_SH)
2019-08-25 00:46:40 -04:00
skip:;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
} else { // instrument
2020-06-02 12:44:34 -04:00
// cmd is reused for the instrument semitone
cmd += seqPlayer->transposition + seqChannel->transposition + layer->transposition;
if (cmd >= 0x80) {
2019-12-01 21:52:53 -05:00
layer->stopSomething = TRUE;
2019-08-25 00:46:40 -04:00
} else {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-06-02 12:44:34 -04:00
if (layer->instOrWave == 0xffu) {
2020-02-03 00:51:26 -05:00
instrument = seqChannel->instrument;
} else {
instrument = layer->instrument;
}
#else
2019-12-01 21:52:53 -05:00
instrument = layer->instrument;
2020-06-02 12:44:34 -04:00
if (instrument == NULL) {
2019-12-01 21:52:53 -05:00
instrument = seqChannel->instrument;
2019-08-25 00:46:40 -04:00
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
if (layer->portamento.mode != 0) {
2020-06-02 12:44:34 -04:00
if (layer->portamentoTargetNote < cmd) {
vel = cmd;
} else {
vel = layer->portamentoTargetNote;
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
2019-12-01 21:52:53 -05:00
if (instrument != NULL) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU)
2020-06-02 12:44:34 -04:00
sound = instrument_get_audio_bank_sound(instrument, vel);
2020-02-03 00:51:26 -05:00
#else
2020-06-02 12:44:34 -04:00
sound = (u8) vel < instrument->normalRangeLo ? &instrument->lowNotesSound
: (u8) vel <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
sameSound = (sound == layer->sound);
layer->sound = sound;
tuning = sound->tuning;
2019-08-25 00:46:40 -04:00
} else {
layer->sound = NULL;
2019-12-01 21:52:53 -05:00
tuning = 1.0f;
2019-08-25 00:46:40 -04:00
}
2020-06-02 12:44:34 -04:00
temp_f2 = gNoteFrequencies[cmd] * tuning;
2019-12-01 21:52:53 -05:00
temp_f12 = gNoteFrequencies[layer->portamentoTargetNote] * tuning;
2019-08-25 00:46:40 -04:00
portamento = &layer->portamento;
2019-12-01 21:52:53 -05:00
switch (PORTAMENTO_MODE(layer->portamento)) {
case PORTAMENTO_MODE_1:
case PORTAMENTO_MODE_3:
case PORTAMENTO_MODE_5:
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-08-25 00:46:40 -04:00
sp24 = temp_f2;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
freqScale = temp_f12;
2019-08-25 00:46:40 -04:00
break;
2020-06-02 12:44:34 -04:00
2019-12-01 21:52:53 -05:00
case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4:
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-06-02 12:44:34 -04:00
default:
#endif
freqScale = temp_f2;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-08-25 00:46:40 -04:00
sp24 = temp_f12;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
portamento->extent = temp_f2 / freqScale - 1.0f;
#else
2019-12-01 21:52:53 -05:00
portamento->extent = sp24 / freqScale - US_FLOAT(1.0);
2020-02-03 00:51:26 -05:00
#endif
2020-06-02 12:44:34 -04:00
2019-12-01 21:52:53 -05:00
if (PORTAMENTO_IS_SPECIAL(layer->portamento)) {
2019-08-25 00:46:40 -04:00
portamento->speed = US_FLOAT(32512.0) * FLOAT_CAST(seqPlayer->tempo)
/ ((f32) layer->delay * (f32) gTempoInternalToExternal
* FLOAT_CAST(layer->portamentoTime));
} else {
portamento->speed = US_FLOAT(127.0) / FLOAT_CAST(layer->portamentoTime);
}
portamento->cur = 0.0f;
2019-12-01 21:52:53 -05:00
layer->freqScale = freqScale;
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_5) {
2020-06-02 12:44:34 -04:00
layer->portamentoTargetNote = cmd;
2019-08-25 00:46:40 -04:00
}
2019-12-01 21:52:53 -05:00
} else if (instrument != NULL) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU)
2020-06-02 12:44:34 -04:00
sound = instrument_get_audio_bank_sound(instrument, cmd);
2020-02-03 00:51:26 -05:00
#else
2020-06-02 12:44:34 -04:00
sound = cmd < instrument->normalRangeLo ?
&instrument->lowNotesSound : cmd <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
sameSound = (sound == layer->sound);
layer->sound = sound;
2020-06-02 12:44:34 -04:00
layer->freqScale = gNoteFrequencies[cmd] * sound->tuning;
2019-08-25 00:46:40 -04:00
} else {
layer->sound = NULL;
2020-06-02 12:44:34 -04:00
layer->freqScale = gNoteFrequencies[cmd];
2019-08-25 00:46:40 -04:00
}
}
}
layer->delayUnused = layer->delay;
}
}
2019-12-01 21:52:53 -05:00
if (layer->stopSomething == TRUE) {
if (layer->note != NULL || layer->continuousNotes) {
2019-08-25 00:46:40 -04:00
seq_channel_layer_note_decay(layer);
}
2020-12-03 14:26:38 -05:00
return;
}
cmd = FALSE;
if (!layer->continuousNotes) {
cmd = TRUE;
} else if (layer->note == NULL || layer->status == SOUND_LOAD_STATUS_NOT_LOADED) {
cmd = TRUE;
} else if (sameSound == FALSE) {
seq_channel_layer_note_decay(layer);
cmd = TRUE;
}
#if defined(VERSION_EU) || defined(VERSION_SH)
else if (layer != layer->note->parentLayer) {
cmd = TRUE;
}
#endif
else if (layer->sound == NULL) {
init_synthetic_wave(layer->note, layer);
}
if (cmd != FALSE) {
layer->note = alloc_note(layer);
}
if (layer->note != NULL && layer->note->parentLayer == layer) {
note_vibrato_init(layer->note);
}
#if defined(VERSION_EU) || defined(VERSION_SH)
if (seqChannel) {
}
#endif
}
#ifdef VERSION_EU
u8 audioString106[] = "Audio: Note:Velocity Error %d\n";
u8 audioString107[] = "Error: Your assignchannel is stolen.\n";
#endif
#else
// US/JP version with macros to simulate inlining by copt. Edit if you dare.
#include "copt/seq_channel_layer_process_script_copt.inc.c"
#endif
#ifdef VERSION_SH
void seq_channel_layer_process_script_part1(struct SequenceChannelLayer *layer) {
if (!layer->continuousNotes) {
seq_channel_layer_note_decay(layer);
} else if (layer->note != NULL && layer->note->wantedParentLayer == layer) {
seq_channel_layer_note_decay(layer);
}
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1 ||
PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2) {
layer->portamento.mode = 0;
}
layer->notePropertiesNeedInit = TRUE;
}
s32 seq_channel_layer_process_script_part5(struct SequenceChannelLayer *layer, s32 cmd) {
if (!layer->stopSomething && layer->sound != NULL && layer->sound->sample->codec == 2 &&
layer->sound->sample->medium != 0) {
layer->stopSomething = TRUE;
return -1;
}
if (layer->continuousNotes == 1 && layer->note != NULL && layer->status && cmd == 1 &&
layer->note->parentLayer == layer) {
if (layer->sound == NULL) {
init_synthetic_wave(layer->note, layer);
}
} else {
if (cmd == 0) {
seq_channel_layer_note_decay(layer);
}
layer->note = alloc_note(layer);
}
if (layer->note != NULL && layer->note->parentLayer == layer) {
note_vibrato_init(layer->note);
}
return 0;
}
s32 seq_channel_layer_process_script_part2(struct SequenceChannelLayer *layer) {
struct SequenceChannel *seqChannel = layer->seqChannel;
struct SequencePlayer *seqPlayer = seqChannel->seqPlayer;
struct M64ScriptState *state;
s32 temp_a0_5;
u16 sp3A;
u8 cmd;
for (;;) {
state = &layer->scriptState;
cmd = m64_read_u8(state);
if (cmd <= 0xc0) {
return cmd;
}
switch (cmd) {
case 0xff: // layer_end; function return or end of script
if (state->depth == 0) {
// N.B. this function call is *not* inlined even though it's
// within the same file, unlike in the rest of this function.
seq_channel_layer_disable(layer);
return -1;
}
state->pc = state->stack[--state->depth];
break;
case 0xfc: // layer_call
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
sp3A = m64_read_s16(state);
state->stack[state->depth++] = state->pc;
state->pc = seqPlayer->seqData + sp3A;
break;
case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0)
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
state->remLoopIters[state->depth] = m64_read_u8(state);
state->stack[state->depth++] = state->pc;
break;
case 0xf7: // layer_loopend
if (--state->remLoopIters[state->depth - 1] != 0) {
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
case 0xfb: // layer_jump
sp3A = m64_read_s16(state);
state->pc = seqPlayer->seqData + sp3A;
break;
case 0xf4:
state->pc += (s8)m64_read_u8(state);
break;
case 0xc1: // layer_setshortnotevelocity
case 0xca: // layer_setpan
temp_a0_5 = *(state->pc++);
if (cmd == 0xc1) {
layer->velocitySquare = (f32) (temp_a0_5 * temp_a0_5) / (f32) (127 * 127);
} else {
layer->pan = temp_a0_5;
}
break;
case 0xc2: // layer_transpose; set transposition in semitones
case 0xc9: // layer_setshortnoteduration
temp_a0_5 = *(state->pc++);
if (cmd == 0xc9) {
layer->noteDuration = temp_a0_5;
} else {
layer->transposition = temp_a0_5;
}
break;
case 0xc4: // layer_somethingon
case 0xc5: // layer_somethingoff
if (cmd == 0xc4) {
layer->continuousNotes = TRUE;
} else {
layer->continuousNotes = FALSE;
}
seq_channel_layer_note_decay(layer);
break;
case 0xc3: // layer_setshortnotedefaultplaypercentage
sp3A = m64_read_compressed_u16(state);
layer->shortNoteDefaultPlayPercentage = sp3A;
break;
case 0xc6: // layer_setinstr
cmd = m64_read_u8(state);
if (cmd >= 0x7f) {
if (cmd == 0x7f) {
layer->instOrWave = 0;
} else {
layer->instOrWave = cmd;
layer->instrument = NULL;
}
if (1) {
}
if (cmd == 0xff) {
layer->adsr.releaseRate = 0;
}
break;
}
if ((layer->instOrWave = get_instrument(seqChannel, cmd, &layer->instrument, &layer->adsr)) == 0) {
eu_stubbed_printf_1("WARNING: NPRG: cannot change %d\n", cmd);
layer->instOrWave = 0xff;
}
break;
case 0xc7: // layer_portamento
layer->portamento.mode = m64_read_u8(state);
// cmd is reused for the portamento's semitone
cmd = m64_read_u8(state) + seqChannel->transposition +
layer->transposition + seqPlayer->transposition;
if (cmd >= 0x80) {
cmd = 0;
}
layer->portamentoTargetNote = cmd;
// If special, the next param is u8 instead of var
if (PORTAMENTO_IS_SPECIAL(layer->portamento)) {
layer->portamentoTime = *((state)->pc++);
break;
}
sp3A = m64_read_compressed_u16(state);
layer->portamentoTime = sp3A;
break;
case 0xc8: // layer_disableportamento
layer->portamento.mode = 0;
break;
case 0xcb:
sp3A = m64_read_s16(state);
layer->adsr.envelope = (struct AdsrEnvelope *) (seqPlayer->seqData + sp3A);
layer->adsr.releaseRate = m64_read_u8(state);
break;
case 0xcc:
layer->ignoreDrumPan = TRUE;
break;
case 0xcd:
layer->reverbBits.asByte = m64_read_u8(state);
break;
case 0xce:
cmd = m64_read_u8(state) + 0x80;
layer->unkSH28 = unk_sh_data_1[cmd];
// missing break :)
default:
switch (cmd & 0xf0) {
case 0xd0: // layer_setshortnotevelocityfromtable
sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xf];
layer->velocitySquare = (f32) (sp3A * sp3A) / (f32) (127 * 127);
break;
case 0xe0: // layer_setshortnotedurationfromtable
layer->noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf];
break;
default:
eu_stubbed_printf_1("Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n", cmd);
break;
}
}
}
return cmd;
}
s32 seq_channel_layer_process_script_part4(struct SequenceChannelLayer *layer, s32 cmd1) {
s32 sameSound = TRUE;
struct SequenceChannel *seqChannel = layer->seqChannel;
struct Portamento *portamento;
struct AudioBankSound *sound;
struct Instrument *instrument;
struct Drum *drum;
f32 tuning;
s32 vel;
f32 freqScale;
f32 sp24;
f32 temp_f12;
UNUSED s32 pad[2];
struct SequencePlayer *seqPlayer = seqChannel->seqPlayer;
u8 cmd = cmd1;
f32 temp_f2;
s32 temp = layer->instOrWave;
if (temp == 0xff) {
if (!seqChannel->hasInstrument) {
return -1;
}
temp = seqChannel->instOrWave;
}
if (temp == 0) { // drum
// cmd is reused for the drum semitone
cmd += seqChannel->transposition + layer->transposition;
drum = get_drum(seqChannel->bankId, cmd);
if (drum == NULL) {
layer->stopSomething = TRUE;
layer->delayUnused = layer->delay;
return -1;
} else {
layer->adsr.envelope = drum->envelope;
layer->adsr.releaseRate = drum->releaseRate;
if (!layer->ignoreDrumPan) {
layer->pan = drum->pan;
}
layer->sound = &drum->sound;
layer->freqScale = layer->sound->tuning;
}
} else { // instrument
// cmd is reused for the instrument semitone
cmd += seqPlayer->transposition + seqChannel->transposition + layer->transposition;
if (cmd >= 0x80) {
layer->stopSomething = TRUE;
return -1;
} else {
if (layer->instOrWave == 0xff) {
instrument = seqChannel->instrument;
} else {
instrument = layer->instrument;
}
if (layer->portamento.mode != 0) {
if (layer->portamentoTargetNote < cmd) {
vel = cmd;
} else {
vel = layer->portamentoTargetNote;
}
if (instrument != NULL) {
sound = instrument_get_audio_bank_sound(instrument, vel);
sameSound = (sound == layer->sound);
layer->sound = sound;
tuning = sound->tuning;
} else {
layer->sound = NULL;
tuning = 1.0f;
}
temp_f2 = gNoteFrequencies[cmd] * tuning;
temp_f12 = gNoteFrequencies[layer->portamentoTargetNote] * tuning;
portamento = &layer->portamento;
switch (PORTAMENTO_MODE(layer->portamento)) {
case PORTAMENTO_MODE_1:
case PORTAMENTO_MODE_3:
case PORTAMENTO_MODE_5:
sp24 = temp_f2;
freqScale = temp_f12;
break;
case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4:
freqScale = temp_f2;
sp24 = temp_f12;
break;
default:
freqScale = temp_f2;
sp24 = temp_f2;
break;
}
portamento->extent = sp24 / freqScale - 1.0f;
if (PORTAMENTO_IS_SPECIAL(layer->portamento)) {
portamento->speed = US_FLOAT(32512.0) * FLOAT_CAST(seqPlayer->tempo)
/ ((f32) layer->delay * (f32) gTempoInternalToExternal
* FLOAT_CAST(layer->portamentoTime));
} else {
portamento->speed = US_FLOAT(127.0) / FLOAT_CAST(layer->portamentoTime);
}
portamento->cur = 0.0f;
layer->freqScale = freqScale;
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_5) {
layer->portamentoTargetNote = cmd;
}
} else if (instrument != NULL) {
sound = instrument_get_audio_bank_sound(instrument, cmd);
sameSound = (sound == layer->sound);
layer->sound = sound;
layer->freqScale = gNoteFrequencies[cmd] * sound->tuning;
} else {
layer->sound = NULL;
layer->freqScale = gNoteFrequencies[cmd];
}
}
2019-08-25 00:46:40 -04:00
}
2020-12-03 14:26:38 -05:00
layer->delayUnused = layer->delay;
layer->freqScale *= layer->unkSH28;
return sameSound;
}
2019-08-25 00:46:40 -04:00
2020-12-03 14:26:38 -05:00
s32 seq_channel_layer_process_script_part3(struct SequenceChannelLayer *layer, s32 cmd) {
struct M64ScriptState *state = &layer->scriptState;
u16 sp3A;
s32 vel;
struct SequenceChannel *seqChannel = layer->seqChannel;
struct SequencePlayer *seqPlayer = seqChannel->seqPlayer;
2019-08-25 00:46:40 -04:00
2020-12-03 14:26:38 -05:00
if (cmd == 0xc0) { // layer_delay
layer->delay = m64_read_compressed_u16(state);
layer->stopSomething = TRUE;
return -1;
2019-08-25 00:46:40 -04:00
}
2020-12-03 14:26:38 -05:00
layer->stopSomething = FALSE;
if (seqChannel->largeNotes == TRUE) {
switch (cmd & 0xc0) {
case 0x00: // layer_note0 (play percentage, velocity, duration)
sp3A = m64_read_compressed_u16(state);
vel = *(state->pc++);
layer->noteDuration = *(state->pc++);
layer->playPercentage = sp3A;
break;
case 0x40: // layer_note1 (play percentage, velocity)
sp3A = m64_read_compressed_u16(state);
vel = *(state->pc++);
layer->noteDuration = 0;
layer->playPercentage = sp3A;
break;
case 0x80: // layer_note2 (velocity, duration; uses last play percentage)
sp3A = layer->playPercentage;
vel = *(state->pc++);
layer->noteDuration = *(state->pc++);
break;
}
if (vel >= 0x80 || vel < 0) {
vel = 0x7f;
}
layer->velocitySquare = ((f32) vel * (f32) vel) / (f32) (0x7f * 0x7f);
// the remaining bits are used for the semitone
cmd -= (cmd & 0xc0);
} else {
switch (cmd & 0xc0) {
case 0x00: // play note, type 0 (play percentage)
sp3A = m64_read_compressed_u16(state);
layer->playPercentage = sp3A;
break;
case 0x40: // play note, type 1 (uses default play percentage)
sp3A = layer->shortNoteDefaultPlayPercentage;
break;
case 0x80: // play note, type 2 (uses last play percentage)
sp3A = layer->playPercentage;
break;
}
// the remaining bits are used for the semitone
cmd -= cmd & 0xc0;
2020-06-02 12:44:34 -04:00
}
2020-09-20 11:15:47 -04:00
2020-12-03 14:26:38 -05:00
layer->delay = sp3A;
layer->duration = layer->noteDuration * sp3A >> 8;
if ((seqPlayer->muted && (seqChannel->muteBehavior & 0x50) != 0)
|| seqChannel->stopSomething2)
{
layer->stopSomething = TRUE;
return -1;
}
2020-09-20 11:15:47 -04:00
2020-12-03 14:26:38 -05:00
return cmd;
}
2019-08-25 00:46:40 -04:00
#endif
2020-06-02 12:44:34 -04:00
u8 get_instrument(struct SequenceChannel *seqChannel, u8 instId, struct Instrument **instOut, struct AdsrSettings *adsr) {
2019-08-25 00:46:40 -04:00
struct Instrument *inst;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
inst = get_instrument_inner(seqChannel->bankId, instId);
2020-02-03 00:51:26 -05:00
if (inst == NULL)
{
*instOut = NULL;
return 0;
}
adsr->envelope = inst->envelope;
adsr->releaseRate = inst->releaseRate;
*instOut = inst;
instId++;
return instId;
#else
2019-08-25 00:46:40 -04:00
UNUSED u32 pad;
if (instId >= gCtlEntries[seqChannel->bankId].numInstruments) {
instId = gCtlEntries[seqChannel->bankId].numInstruments;
if (instId == 0) {
return 0;
}
instId--;
}
inst = gCtlEntries[seqChannel->bankId].instruments[instId];
if (inst == NULL) {
struct SequenceChannel seqChannelCpy = *seqChannel;
while (instId != 0xff) {
inst = gCtlEntries[seqChannelCpy.bankId].instruments[instId];
2019-09-01 15:50:50 -04:00
if (inst != NULL) {
2019-08-25 00:46:40 -04:00
break;
2019-09-01 15:50:50 -04:00
}
2019-08-25 00:46:40 -04:00
instId--;
}
}
2019-10-05 15:08:05 -04:00
if (((uintptr_t) gBankLoadedPool.persistent.pool.start <= (uintptr_t) inst
&& (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.persistent.pool.start
+ gBankLoadedPool.persistent.pool.size))
|| ((uintptr_t) gBankLoadedPool.temporary.pool.start <= (uintptr_t) inst
&& (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.temporary.pool.start
2019-08-25 00:46:40 -04:00
+ gBankLoadedPool.temporary.pool.size))) {
adsr->envelope = inst->envelope;
adsr->releaseRate = inst->releaseRate;
*instOut = inst;
instId++;
return instId;
}
gAudioErrorFlags = instId + 0x20000;
*instOut = NULL;
return 0;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
void set_instrument(struct SequenceChannel *seqChannel, u8 instId) {
if (instId >= 0x80) {
seqChannel->instOrWave = instId;
seqChannel->instrument = NULL;
} else if (instId == 0x7f) {
seqChannel->instOrWave = 0;
seqChannel->instrument = (struct Instrument *) 1;
} else {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
if ((seqChannel->instOrWave =
get_instrument(seqChannel, instId, &seqChannel->instrument, &seqChannel->adsr)) == 0)
#else
2019-08-25 00:46:40 -04:00
seqChannel->instOrWave =
get_instrument(seqChannel, instId, &seqChannel->instrument, &seqChannel->adsr);
2020-02-03 00:51:26 -05:00
if (seqChannel->instOrWave == 0)
#endif
{
2019-08-25 00:46:40 -04:00
seqChannel->hasInstrument = FALSE;
return;
}
}
seqChannel->hasInstrument = TRUE;
}
void sequence_channel_set_volume(struct SequenceChannel *seqChannel, u8 volume) {
seqChannel->volume = FLOAT_CAST(volume) / US_FLOAT(127.0);
}
void sequence_channel_process_script(struct SequenceChannel *seqChannel) {
2020-06-02 12:44:34 -04:00
struct M64ScriptState *state;
struct SequencePlayer *seqPlayer;
2020-12-03 14:26:38 -05:00
u8 cmd;
s8 temp;
u8 loBits;
2019-08-25 00:46:40 -04:00
u16 sp5A;
2020-12-03 14:26:38 -05:00
s32 sp38;
s8 value;
2019-08-25 00:46:40 -04:00
s32 i;
2020-12-03 14:26:38 -05:00
u8 *seqData;
2019-08-25 00:46:40 -04:00
if (!seqChannel->enabled) {
return;
}
if (seqChannel->stopScript) {
2019-12-01 21:52:53 -05:00
for (i = 0; i < LAYERS_MAX; i++) {
2019-08-25 00:46:40 -04:00
if (seqChannel->layers[i] != NULL) {
seq_channel_layer_process_script(seqChannel->layers[i]);
}
}
return;
}
seqPlayer = seqChannel->seqPlayer;
2019-12-01 21:52:53 -05:00
if (seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_STOP_SCRIPT) != 0) {
2019-08-25 00:46:40 -04:00
return;
}
if (seqChannel->delay != 0) {
seqChannel->delay--;
}
state = &seqChannel->scriptState;
if (seqChannel->delay == 0) {
for (;;) {
cmd = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#if !defined(VERSION_EU) && !defined(VERSION_SH)
2019-12-01 21:52:53 -05:00
if (cmd == 0xff) // chan_end
2019-08-25 00:46:40 -04:00
{
2020-12-03 14:26:38 -05:00
if (state->depth == 0) {
2019-08-25 00:46:40 -04:00
sequence_channel_disable(seqChannel);
break;
}
state->depth--, state->pc = state->stack[state->depth];
}
2019-12-01 21:52:53 -05:00
if (cmd == 0xfe) // chan_delay1
2019-08-25 00:46:40 -04:00
{
break;
}
2019-12-01 21:52:53 -05:00
if (cmd == 0xfd) // chan_delay
2019-08-25 00:46:40 -04:00
{
seqChannel->delay = m64_read_compressed_u16(state);
break;
}
2019-12-01 21:52:53 -05:00
if (cmd == 0xf3) // chan_hang
2019-08-25 00:46:40 -04:00
{
seqChannel->stopScript = TRUE;
break;
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
if (cmd >= 0xb0)
#else
if (cmd > 0xc0)
#endif
{
2019-08-25 00:46:40 -04:00
switch (cmd) {
2020-02-03 00:51:26 -05:00
case 0xff: // chan_end
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
if (state->depth == 0) {
sequence_channel_disable(seqChannel);
goto out;
} else {
2020-06-02 12:44:34 -04:00
state->pc = state->stack[--state->depth];
2020-02-03 00:51:26 -05:00
}
2020-06-02 12:44:34 -04:00
#endif
2020-02-03 00:51:26 -05:00
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xfe: // chan_delay1
goto out;
case 0xfd: // chan_delay
seqChannel->delay = m64_read_compressed_u16(state);
goto out;
case 0xea:
seqChannel->stopScript = TRUE;
goto out;
#endif
2019-12-01 21:52:53 -05:00
case 0xfc: // chan_call
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Audio:Track :Call Macro Level Over Error!\n");
}
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
state->stack[state->depth++] = state->pc;
#else
2019-08-25 00:46:40 -04:00
state->depth++, state->stack[state->depth - 1] = state->pc;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + sp5A;
break;
2019-12-01 21:52:53 -05:00
case 0xf8: // chan_loop; loop start, N iterations (or 256 if N = 0)
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Audio:Track :Loops Macro Level Over Error!\n");
}
2019-08-25 00:46:40 -04:00
state->remLoopIters[state->depth] = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
state->stack[state->depth++] = state->pc;
#else
2019-08-25 00:46:40 -04:00
state->depth++, state->stack[state->depth - 1] = state->pc;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xf7: // chan_loopend
2019-08-25 00:46:40 -04:00
state->remLoopIters[state->depth - 1]--;
if (state->remLoopIters[state->depth - 1] != 0) {
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
2019-12-01 21:52:53 -05:00
case 0xf6: // chan_break; break loop, if combined with jump
2019-08-25 00:46:40 -04:00
state->depth--;
break;
2019-12-01 21:52:53 -05:00
case 0xfb: // chan_jump
case 0xfa: // chan_beqz
case 0xf9: // chan_bltz
case 0xf5: // chan_bgez
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
if (cmd == 0xfa && value != 0)
break;
if (cmd == 0xf9 && value >= 0)
break;
if (cmd == 0xf5 && value < 0)
break;
state->pc = seqPlayer->seqData + sp5A;
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-09-20 11:15:47 -04:00
case 0xf4: // chan_jump_rel
case 0xf3: // chan_beqz_rel
case 0xf2: // chan_bltz_rel
2020-12-03 14:26:38 -05:00
temp = m64_read_u8(state);
2020-02-03 00:51:26 -05:00
if (cmd == 0xf3 && value != 0)
break;
if (cmd == 0xf2 && value >= 0)
break;
2020-12-03 14:26:38 -05:00
state->pc += temp;
2020-02-03 00:51:26 -05:00
break;
#endif
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf1: // chan_reservenotes
#else
2019-12-01 21:52:53 -05:00
case 0xf2: // chan_reservenotes
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
note_pool_clear(&seqChannel->notePool);
2020-12-03 14:26:38 -05:00
note_pool_fill(&seqChannel->notePool, m64_read_u8(state));
2019-08-25 00:46:40 -04:00
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf0: // chan_unreservenotes
#else
2019-12-01 21:52:53 -05:00
case 0xf1: // chan_unreservenotes
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
note_pool_clear(&seqChannel->notePool);
break;
2019-12-01 21:52:53 -05:00
case 0xc2: // chan_setdyntable
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
seqChannel->dynTable = (void *) (seqPlayer->seqData + sp5A);
break;
2019-12-01 21:52:53 -05:00
case 0xc5: // chan_dynsetdyntable
2019-08-25 00:46:40 -04:00
if (value != -1) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
seqData = (*seqChannel->dynTable)[value];
sp38 = (u16)((seqData[0] << 8) + seqData[1]);
seqChannel->dynTable = (void *) (seqPlayer->seqData + sp38);
#else
sp5A = (u16)((((*seqChannel->dynTable)[value])[0] << 8) + (((*seqChannel->dynTable)[value])[1]));
2019-08-25 00:46:40 -04:00
seqChannel->dynTable = (void *) (seqPlayer->seqData + sp5A);
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-09-20 11:15:47 -04:00
case 0xeb: // chan_setbankandinstr
2020-12-03 14:26:38 -05:00
cmd = m64_read_u8(state);
// Switch to the cmd's (0-indexed) bank in this sequence's
2020-02-03 00:51:26 -05:00
// bank set. Note that in the binary format (not in the JSON!)
// the banks are listed backwards, so we counts from the back.
// (gAlBankSets[offset] is number of banks)
2020-12-03 14:26:38 -05:00
sp38 = ((u16 *) gAlBankSets)[seqPlayer->seqId];
loBits = *(sp38 + gAlBankSets);
cmd = gAlBankSets[(s32)sp38 + loBits - cmd];
#ifdef VERSION_SH
if (get_bank_or_seq(1, 2, cmd) != NULL)
#else
if (get_bank_or_seq(&gBankLoadedPool, 2, cmd) != NULL)
#endif
{
seqChannel->bankId = cmd;
2020-09-20 11:15:47 -04:00
} else {
2020-12-03 14:26:38 -05:00
eu_stubbed_printf_1("SUB:ERR:BANK %d NOT CACHED.\n", cmd);
2020-02-03 00:51:26 -05:00
}
// fallthrough
#endif
2019-12-01 21:52:53 -05:00
case 0xc1: // chan_setinstr ("set program"?)
2019-08-25 00:46:40 -04:00
set_instrument(seqChannel, m64_read_u8(state));
break;
2019-12-01 21:52:53 -05:00
case 0xc3: // chan_largenotesoff
2019-08-25 00:46:40 -04:00
seqChannel->largeNotes = FALSE;
break;
2019-12-01 21:52:53 -05:00
case 0xc4: // chan_largenoteson
2019-08-25 00:46:40 -04:00
seqChannel->largeNotes = TRUE;
break;
2019-12-01 21:52:53 -05:00
case 0xdf: // chan_setvol
2019-08-25 00:46:40 -04:00
sequence_channel_set_volume(seqChannel, m64_read_u8(state));
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.volume = TRUE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xe0: // chan_setvolscale
2019-08-25 00:46:40 -04:00
seqChannel->volumeScale = FLOAT_CAST(m64_read_u8(state)) / US_FLOAT(128.0);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.volume = TRUE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xde: // chan_freqscale; pitch bend using raw frequency multiplier N/2^15 (N is u16)
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
2020-12-03 14:26:38 -05:00
seqChannel->freqScale = FLOAT_CAST(sp5A) / US_FLOAT(32768.0);
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.freqScale = TRUE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xd3: // chan_pitchbend; pitch bend by <= 1 octave in either direction (-127..127)
2019-08-25 00:46:40 -04:00
// (m64_read_u8(state) is really s8 here)
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
cmd = m64_read_u8(state) + 128;
#else
cmd = m64_read_u8(state) + 127;
#endif
seqChannel->freqScale = gPitchBendFrequencyScale[cmd];
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.freqScale = TRUE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0xee:
cmd = m64_read_u8(state) + 0x80;
seqChannel->freqScale = unk_sh_data_1[cmd];
seqChannel->changes.as_bitfields.freqScale = TRUE;
break;
#endif
2019-12-01 21:52:53 -05:00
case 0xdd: // chan_setpan
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->newPan = m64_read_u8(state);
seqChannel->changes.as_bitfields.pan = TRUE;
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
seqChannel->pan = FLOAT_CAST(m64_read_u8(state)) / US_FLOAT(128.0);
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xdc: // chan_setpanmix; set proportion of pan to come from channel (0..128)
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqChannel->panChannelWeight = m64_read_u8(state);
seqChannel->changes.as_bitfields.pan = TRUE;
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
seqChannel->panChannelWeight = FLOAT_CAST(m64_read_u8(state)) / US_FLOAT(128.0);
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xdb: // chan_transpose; set transposition in semitones
2020-12-03 14:26:38 -05:00
temp = *state->pc++;
seqChannel->transposition = temp;
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xda: // chan_setenvelope
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
seqChannel->adsr.envelope = (struct AdsrEnvelope *) (seqPlayer->seqData + sp5A);
break;
2019-12-01 21:52:53 -05:00
case 0xd9: // chan_setdecayrelease
2019-08-25 00:46:40 -04:00
seqChannel->adsr.releaseRate = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xd8: // chan_setvibratoextent
2019-08-25 00:46:40 -04:00
seqChannel->vibratoExtentTarget = m64_read_u8(state) * 8;
seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoExtentChangeDelay = 0;
break;
2019-12-01 21:52:53 -05:00
case 0xd7: // chan_setvibratorate
2019-08-25 00:46:40 -04:00
seqChannel->vibratoRateStart = seqChannel->vibratoRateTarget =
m64_read_u8(state) * 32;
seqChannel->vibratoRateChangeDelay = 0;
break;
2019-12-01 21:52:53 -05:00
case 0xe2: // chan_setvibratoextentlinear
2019-08-25 00:46:40 -04:00
seqChannel->vibratoExtentStart = m64_read_u8(state) * 8;
seqChannel->vibratoExtentTarget = m64_read_u8(state) * 8;
seqChannel->vibratoExtentChangeDelay = m64_read_u8(state) * 16;
break;
2019-12-01 21:52:53 -05:00
case 0xe1: // chan_setvibratoratelinear
2019-08-25 00:46:40 -04:00
seqChannel->vibratoRateStart = m64_read_u8(state) * 32;
seqChannel->vibratoRateTarget = m64_read_u8(state) * 32;
seqChannel->vibratoRateChangeDelay = m64_read_u8(state) * 16;
break;
2019-12-01 21:52:53 -05:00
case 0xe3: // chan_setvibratodelay
2019-08-25 00:46:40 -04:00
seqChannel->vibratoDelay = m64_read_u8(state) * 16;
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-12-01 21:52:53 -05:00
case 0xd6: // chan_setupdatesperframe_unimplemented
2020-12-03 14:26:38 -05:00
cmd = m64_read_u8(state);
if (cmd == 0) {
cmd = gAudioUpdatesPerFrame;
2019-08-25 00:46:40 -04:00
}
2020-12-03 14:26:38 -05:00
seqChannel->updatesPerFrameUnused = cmd;
2019-08-25 00:46:40 -04:00
break;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
case 0xd4: // chan_setreverb
2019-08-25 00:46:40 -04:00
seqChannel->reverb = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xc6: // chan_setbank; switch bank within set
2020-12-03 14:26:38 -05:00
cmd = m64_read_u8(state);
2019-09-01 15:50:50 -04:00
// Switch to the temp's (0-indexed) bank in this sequence's
// bank set. Note that in the binary format (not in the JSON!)
// the banks are listed backwards, so we counts from the back.
2019-08-25 00:46:40 -04:00
// (gAlBankSets[offset] is number of banks)
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
sp38 = ((u16 *) gAlBankSets)[seqPlayer->seqId];
loBits = *(sp38 + gAlBankSets);
cmd = gAlBankSets[(s32)sp38 + loBits - cmd];
#else
sp5A = ((u16 *) gAlBankSets)[seqPlayer->seqId];
loBits = *(sp5A + gAlBankSets);
cmd = gAlBankSets[sp5A + loBits - cmd];
#endif
#ifdef VERSION_SH
if (get_bank_or_seq(1, 2, cmd) != NULL)
#else
if (get_bank_or_seq(&gBankLoadedPool, 2, cmd) != NULL)
#endif
{
seqChannel->bankId = cmd;
2020-09-20 11:15:47 -04:00
} else {
2020-12-03 14:26:38 -05:00
eu_stubbed_printf_1("SUB:ERR:BANK %d NOT CACHED.\n", cmd);
2020-06-02 12:44:34 -04:00
}
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xc7: // chan_writeseq; write to sequence data (!)
2020-06-02 12:44:34 -04:00
{
2020-12-03 14:26:38 -05:00
#if !defined(VERSION_EU) && !defined(VERSION_SH)
u8 *seqData;
#endif
cmd = m64_read_u8(state);
sp5A = m64_read_s16(state);
seqData = seqPlayer->seqData + sp5A;
*seqData = (u8)value + cmd;
2020-06-02 12:44:34 -04:00
}
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xc8: // chan_subtract
case 0xc9: // chan_bitand
case 0xcc: // chan_setval
2019-08-25 00:46:40 -04:00
temp = m64_read_u8(state);
if (cmd == 0xc8) {
value -= temp;
} else if (cmd == 0xcc) {
value = temp;
} else {
value &= temp;
}
break;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0xcd:
sequence_channel_disable(seqPlayer->channels[m64_read_u8(state)]);
break;
#endif
2019-12-01 21:52:53 -05:00
case 0xca: // chan_setmutebhv
2019-08-25 00:46:40 -04:00
seqChannel->muteBehavior = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqChannel->changes.as_bitfields.volume = TRUE;
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xcb: // chan_readseq
2020-12-03 14:26:38 -05:00
sp38 = (u16)m64_read_s16(state) + value;
value = seqPlayer->seqData[sp38];
break;
#ifdef VERSION_SH
case 0xce:
seqChannel->unkC8 = m64_read_s16(state);
break;
case 0xcf:
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
2020-12-03 14:26:38 -05:00
seqData = seqPlayer->seqData + sp5A;
seqData[0] = (seqChannel->unkC8 >> 8) & 0xffff;
seqData[1] = (seqChannel->unkC8) & 0xffff;
2019-08-25 00:46:40 -04:00
break;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
case 0xd0: // chan_stereoheadseteffects
2019-08-25 00:46:40 -04:00
seqChannel->stereoHeadsetEffects = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xd1: // chan_setnoteallocationpolicy
2019-08-25 00:46:40 -04:00
seqChannel->noteAllocPolicy = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xd2: // chan_setsustain
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
seqChannel->adsr.sustain = m64_read_u8(state);
#else
2019-08-25 00:46:40 -04:00
seqChannel->adsr.sustain = m64_read_u8(state) << 8;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xe5:
seqChannel->reverbIndex = m64_read_u8(state);
break;
#endif
2019-12-01 21:52:53 -05:00
case 0xe4: // chan_dyncall
2019-08-25 00:46:40 -04:00
if (value != -1) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
if (state->depth >= 4) {
2020-09-20 11:15:47 -04:00
eu_stubbed_printf_0("Audio:Track: CTBLCALL Macro Level Over Error!\n");
}
2020-12-03 14:26:38 -05:00
#endif
seqData = (*seqChannel->dynTable)[value];
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
state->stack[state->depth++] = state->pc;
2020-12-03 14:26:38 -05:00
sp38 = (u16)((seqData[0] << 8) + seqData[1]);
state->pc = seqPlayer->seqData + sp38;
if (0 && sp38 >= gSeqFileHeader->seqArray[seqPlayer->seqId].len) {
eu_stubbed_printf_3("Err :Sub %x ,address %x:Undefined SubTrack Function %x", seqChannel, state->pc, sp38);
}
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
state->depth++, state->stack[state->depth - 1] = state->pc;
2020-12-03 14:26:38 -05:00
sp5A = ((seqData[0] << 8) + seqData[1]);
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + sp5A;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
break;
2020-02-03 00:51:26 -05:00
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xe6:
2020-03-01 22:42:52 -05:00
seqChannel->bookOffset = m64_read_u8(state);
2020-02-03 00:51:26 -05:00
break;
case 0xe7:
sp5A = m64_read_s16(state);
2020-12-03 14:26:38 -05:00
seqData = seqPlayer->seqData + sp5A;
seqChannel->muteBehavior = *seqData++;
seqChannel->noteAllocPolicy = *seqData++;
seqChannel->notePriority = *seqData++;
seqChannel->transposition = (s8) *seqData++;
seqChannel->newPan = *seqData++;
seqChannel->panChannelWeight = *seqData++;
seqChannel->reverb = *seqData++;
seqChannel->reverbIndex = *seqData++; // reverb index?
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.pan = TRUE;
2020-02-03 00:51:26 -05:00
break;
case 0xe8:
seqChannel->muteBehavior = m64_read_u8(state);
seqChannel->noteAllocPolicy = m64_read_u8(state);
seqChannel->notePriority = m64_read_u8(state);
seqChannel->transposition = (s8) m64_read_u8(state);
2020-03-01 22:42:52 -05:00
seqChannel->newPan = m64_read_u8(state);
seqChannel->panChannelWeight = m64_read_u8(state);
2020-02-03 00:51:26 -05:00
seqChannel->reverb = m64_read_u8(state);
seqChannel->reverbIndex = m64_read_u8(state);
2020-03-01 22:42:52 -05:00
seqChannel->changes.as_bitfields.pan = TRUE;
2020-02-03 00:51:26 -05:00
break;
case 0xec:
seqChannel->vibratoExtentTarget = 0;
seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoExtentChangeDelay = 0;
seqChannel->vibratoRateTarget = 0;
seqChannel->vibratoRateStart = 0;
seqChannel->vibratoRateChangeDelay = 0;
seqChannel->freqScale = 1.0f;
break;
2020-09-20 11:15:47 -04:00
case 0xe9: // chan_setnotepriority
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
cmd = m64_read_u8(state);
if ((cmd & 0xf) != 0) {
seqChannel->notePriority = cmd & 0xf;
}
cmd = cmd >> 4;
if (cmd != 0) {
seqChannel->unkSH06 = cmd;
}
#else
2020-02-03 00:51:26 -05:00
seqChannel->notePriority = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#endif
break;
#endif
#ifdef VERSION_SH
case 0xed:
seqChannel->unkSH0C = m64_read_u8(state);
break;
case 0xef:
m64_read_s16(state);
m64_read_u8(state);
break;
case 0xb0:
sp5A = m64_read_s16(state);
seqData = seqPlayer->seqData + sp5A;
seqChannel->filter = (s16 *) (seqData);
break;
case 0xb1:
seqChannel->filter = NULL;
break;
case 0xb3:
if (seqChannel->filter != NULL) {
cmd = m64_read_u8(state);
if (cmd == 0) {
seqChannel->filter = NULL;
} else {
loBits = (cmd >> 4) & 0xf;
cmd &= 0xf;
fill_filter(seqChannel->filter, loBits, cmd);
}
}
break;
case 0xb2:
i = (value * 2);
sp5A = m64_read_s16(state);
sp38 = sp5A + i;
seqChannel->unkC8 = *(u16 *) (seqPlayer->seqData + sp38);
break;
case 0xb4:
seqChannel->dynTable = (void *) (seqPlayer->seqData + seqChannel->unkC8);
break;
case 0xb5:
seqChannel->unkC8 = *(u16 *) (*seqChannel->dynTable)[value];
break;
case 0xb6:
value = (*seqChannel->dynTable)[0][value];
2020-02-03 00:51:26 -05:00
break;
#endif
2019-08-25 00:46:40 -04:00
}
} else {
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
if (cmd >= 0x80) {
loBits = cmd & 7;
switch (cmd & 0xf8) {
case 0x80:
if (seqChannel->layers[loBits] != NULL) {
value = seqChannel->layers[loBits]->finished;
} else {
value = -1;
}
break;
case 0x88:
sp5A = m64_read_s16(state);
if (seq_channel_set_layer(seqChannel, loBits) == 0) {
if (1) {}
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
}
break;
case 0x90:
seq_channel_layer_free(seqChannel, loBits);
break;
case 0x98:
if (value != -1 && seq_channel_set_layer(seqChannel, loBits) != -1) {
seqData = (*seqChannel->dynTable)[value];
sp5A = ((seqData[0] << 8) + seqData[1]);
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
}
break;
}
} else {
#endif
2019-08-25 00:46:40 -04:00
loBits = cmd & 0xf;
2020-12-03 14:26:38 -05:00
2019-08-25 00:46:40 -04:00
switch (cmd & 0xf0) {
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0x00:
seqChannel->delay = loBits;
goto out;
case 0x10:
seqChannel->soundScriptIO[loBits] = -1;
if (func_802f47c8(seqChannel->bankId, (u8)value, &seqChannel->soundScriptIO[loBits]) == -1) {
}
break;
#else
2019-12-01 21:52:53 -05:00
case 0x00: // chan_testlayerfinished
2019-08-25 00:46:40 -04:00
if (seqChannel->layers[loBits] != NULL) {
value = seqChannel->layers[loBits]->finished;
}
2020-02-03 00:51:26 -05:00
#ifdef VERSION_EU
else {
value = -1;
}
#endif
2019-08-25 00:46:40 -04:00
break;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
2020-12-03 14:26:38 -05:00
// sh: 0x70
2019-12-01 21:52:53 -05:00
case 0x70: // chan_iowriteval; write data back to audio lib
2019-08-25 00:46:40 -04:00
seqChannel->soundScriptIO[loBits] = value;
break;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0x60:
#else
2019-12-01 21:52:53 -05:00
case 0x80: // chan_ioreadval; read data from audio lib
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
value = seqChannel->soundScriptIO[loBits];
if (loBits < 4) {
seqChannel->soundScriptIO[loBits] = -1;
}
break;
2020-12-03 14:26:38 -05:00
// sh: 0x50
2019-12-01 21:52:53 -05:00
case 0x50: // chan_ioreadvalsub; subtract with read data from audio lib
2019-08-25 00:46:40 -04:00
value -= seqChannel->soundScriptIO[loBits];
break;
2020-12-03 14:26:38 -05:00
#ifndef VERSION_SH
2020-02-03 00:51:26 -05:00
#ifdef VERSION_EU
2020-12-03 14:26:38 -05:00
// sh: 0x00
2020-09-20 11:15:47 -04:00
case 0x60: // chan_delayshort
2020-02-03 00:51:26 -05:00
seqChannel->delay = loBits;
goto out;
#endif
2019-12-01 21:52:53 -05:00
case 0x90: // chan_setlayer
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
if (seq_channel_set_layer(seqChannel, loBits) == 0) {
2020-12-03 14:26:38 -05:00
#ifdef VERSION_EU
if (1) {}
#endif
2019-08-25 00:46:40 -04:00
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
}
break;
2019-12-01 21:52:53 -05:00
case 0xa0: // chan_freelayer
2019-08-25 00:46:40 -04:00
seq_channel_layer_free(seqChannel, loBits);
break;
2019-12-01 21:52:53 -05:00
case 0xb0: // chan_dynsetlayer
2019-08-25 00:46:40 -04:00
if (value != -1 && seq_channel_set_layer(seqChannel, loBits) != -1) {
2020-12-03 14:26:38 -05:00
seqData = (*seqChannel->dynTable)[value];
sp5A = ((seqData[0] << 8) + seqData[1]);
2020-02-03 00:51:26 -05:00
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
2019-08-25 00:46:40 -04:00
}
break;
2020-02-03 00:51:26 -05:00
#ifndef VERSION_EU
2019-12-01 21:52:53 -05:00
case 0x60: // chan_setnotepriority (arg must be >= 2)
2019-08-25 00:46:40 -04:00
seqChannel->notePriority = loBits;
break;
2020-02-03 00:51:26 -05:00
#endif
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0x20:
#else
2019-12-01 21:52:53 -05:00
case 0x10: // chan_startchannel
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
sp5A = m64_read_s16(state);
sequence_channel_enable(seqPlayer, loBits, seqPlayer->seqData + sp5A);
break;
2020-12-03 14:26:38 -05:00
#ifndef VERSION_SH
2019-12-01 21:52:53 -05:00
case 0x20: // chan_disablechannel
2019-08-25 00:46:40 -04:00
sequence_channel_disable(seqPlayer->channels[loBits]);
break;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
case 0x30: // chan_iowriteval2; write data back to audio lib for another channel
2020-12-03 14:26:38 -05:00
cmd = m64_read_u8(state);
seqPlayer->channels[loBits]->soundScriptIO[cmd] = value;
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0x40: // chan_ioreadval2; read data from audio lib from another channel
2020-12-03 14:26:38 -05:00
cmd = m64_read_u8(state);
value = seqPlayer->channels[loBits]->soundScriptIO[cmd];
2019-08-25 00:46:40 -04:00
break;
}
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
}
#endif
2019-08-25 00:46:40 -04:00
}
}
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
out:
#endif
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
for (i = 0; i < LAYERS_MAX; i++) {
2019-08-25 00:46:40 -04:00
if (seqChannel->layers[i] != 0) {
seq_channel_layer_process_script(seqChannel->layers[i]);
}
}
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_SH) && !defined(NON_MATCHING) // regalloc
void sequence_player_process_sequence(struct SequencePlayer *seqPlayer);
GLOBAL_ASM("asm/non_matchings/sh/audio/seqplayer/sequence_player_process_sequence.s")
2019-08-25 00:46:40 -04:00
#else
void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) {
u8 cmd;
u8 loBits;
u8 temp;
s32 value;
s32 i;
u16 u16v;
u8 *tempPtr;
struct M64ScriptState *state;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
s32 temp32;
#endif
2019-08-25 00:46:40 -04:00
if (seqPlayer->enabled == FALSE) {
return;
}
2020-12-03 14:26:38 -05:00
#ifndef VERSION_SH
2019-08-25 00:46:40 -04:00
if (seqPlayer->bankDmaInProgress == TRUE) {
2020-02-03 00:51:26 -05:00
#ifdef VERSION_EU
if (osRecvMesg(&seqPlayer->bankDmaMesgQueue, NULL, 0) == -1) {
return;
}
if (seqPlayer->bankDmaRemaining == 0) {
seqPlayer->bankDmaInProgress = FALSE;
2020-12-03 14:26:38 -05:00
patch_audio_bank(
(struct AudioBank *) (gCtlEntries[seqPlayer->loadingBankId].instruments - 1),
gAlTbl->seqArray[seqPlayer->loadingBankId].offset,
gCtlEntries[seqPlayer->loadingBankId].numInstruments,
gCtlEntries[seqPlayer->loadingBankId].numDrums);
2020-02-03 00:51:26 -05:00
gCtlEntries[seqPlayer->loadingBankId].drums =
2020-12-03 14:26:38 -05:00
((struct AudioBank *) (gCtlEntries[seqPlayer->loadingBankId].instruments - 1))->drums;
2020-02-03 00:51:26 -05:00
gBankLoadStatus[seqPlayer->loadingBankId] = SOUND_LOAD_STATUS_COMPLETE;
} else {
audio_dma_partial_copy_async(&seqPlayer->bankDmaCurrDevAddr, &seqPlayer->bankDmaCurrMemAddr,
&seqPlayer->bankDmaRemaining, &seqPlayer->bankDmaMesgQueue,
&seqPlayer->bankDmaIoMesg);
}
#else
2019-08-25 00:46:40 -04:00
if (seqPlayer->bankDmaMesg == NULL) {
return;
}
if (seqPlayer->bankDmaRemaining == 0) {
seqPlayer->bankDmaInProgress = FALSE;
2019-12-01 21:52:53 -05:00
patch_audio_bank(seqPlayer->loadingBank, gAlTbl->seqArray[seqPlayer->loadingBankId].offset,
2020-12-03 14:26:38 -05:00
seqPlayer->loadingBankNumInstruments, seqPlayer->loadingBankNumDrums);
2019-08-25 00:46:40 -04:00
gCtlEntries[seqPlayer->loadingBankId].numInstruments = seqPlayer->loadingBankNumInstruments;
gCtlEntries[seqPlayer->loadingBankId].numDrums = seqPlayer->loadingBankNumDrums;
gCtlEntries[seqPlayer->loadingBankId].instruments = seqPlayer->loadingBank->instruments;
gCtlEntries[seqPlayer->loadingBankId].drums = seqPlayer->loadingBank->drums;
gBankLoadStatus[seqPlayer->loadingBankId] = SOUND_LOAD_STATUS_COMPLETE;
} else {
osCreateMesgQueue(&seqPlayer->bankDmaMesgQueue, &seqPlayer->bankDmaMesg, 1);
seqPlayer->bankDmaMesg = NULL;
audio_dma_partial_copy_async(&seqPlayer->bankDmaCurrDevAddr, &seqPlayer->bankDmaCurrMemAddr,
&seqPlayer->bankDmaRemaining, &seqPlayer->bankDmaMesgQueue,
&seqPlayer->bankDmaIoMesg);
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
return;
}
if (seqPlayer->seqDmaInProgress == TRUE) {
2020-02-03 00:51:26 -05:00
#ifdef VERSION_EU
if (osRecvMesg(&seqPlayer->seqDmaMesgQueue, NULL, 0) == -1) {
return;
}
2020-03-01 22:42:52 -05:00
#ifndef AVOID_UB
if (temp) {
}
#endif
2020-02-03 00:51:26 -05:00
#else
2019-08-25 00:46:40 -04:00
if (seqPlayer->seqDmaMesg == NULL) {
return;
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->seqDmaInProgress = FALSE;
gSeqLoadStatus[seqPlayer->seqId] = SOUND_LOAD_STATUS_COMPLETE;
}
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
// If discarded, bail out.
if (IS_SEQ_LOAD_COMPLETE(seqPlayer->seqId) == FALSE
2020-12-03 14:26:38 -05:00
|| (
#ifdef VERSION_SH
seqPlayer->defaultBank[0] != 0xff &&
#endif
IS_BANK_LOAD_COMPLETE(seqPlayer->defaultBank[0]) == FALSE)) {
2020-09-20 11:15:47 -04:00
eu_stubbed_printf_1("Disappear Sequence or Bank %d\n", seqPlayer->seqId);
2019-08-25 00:46:40 -04:00
sequence_player_disable(seqPlayer);
return;
}
// Remove possible SOUND_LOAD_STATUS_DISCARDABLE marks.
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
if (gSeqLoadStatus[seqPlayer->seqId] != 5)
#endif
gSeqLoadStatus[seqPlayer->seqId] = SOUND_LOAD_STATUS_COMPLETE;
#ifdef VERSION_SH
if (gBankLoadStatus[seqPlayer->defaultBank[0]] != 5)
#endif
gBankLoadStatus[seqPlayer->defaultBank[0]] = SOUND_LOAD_STATUS_COMPLETE;
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
if (seqPlayer->muted && (seqPlayer->muteBehavior & MUTE_BEHAVIOR_STOP_SCRIPT) != 0) {
2019-08-25 00:46:40 -04:00
return;
}
// Check if we surpass the number of ticks needed for a tatum, else stop.
seqPlayer->tempoAcc += seqPlayer->tempo;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqPlayer->tempoAcc += seqPlayer->tempoAdd;
#endif
2019-08-25 00:46:40 -04:00
if (seqPlayer->tempoAcc < gTempoInternalToExternal) {
return;
}
seqPlayer->tempoAcc -= (u16) gTempoInternalToExternal;
state = &seqPlayer->scriptState;
if (seqPlayer->delay > 1) {
2020-03-01 22:42:52 -05:00
#ifndef AVOID_UB
if (temp) {
}
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->delay--;
} else {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqPlayer->recalculateVolume = 1;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
for (;;) {
cmd = m64_read_u8(state);
2019-12-01 21:52:53 -05:00
if (cmd == 0xff) // seq_end
2019-08-25 00:46:40 -04:00
{
if (state->depth == 0) {
sequence_player_disable(seqPlayer);
break;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
state->pc = state->stack[--state->depth];
#else
2019-08-25 00:46:40 -04:00
state->depth--, state->pc = state->stack[state->depth];
2020-03-01 22:42:52 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
2019-12-01 21:52:53 -05:00
if (cmd == 0xfd) // seq_delay
2019-08-25 00:46:40 -04:00
{
seqPlayer->delay = m64_read_compressed_u16(state);
break;
}
2019-12-01 21:52:53 -05:00
if (cmd == 0xfe) // seq_delay1
2019-08-25 00:46:40 -04:00
{
seqPlayer->delay = 1;
break;
}
if (cmd >= 0xc0) {
switch (cmd) {
2019-12-01 21:52:53 -05:00
case 0xff: // seq_end
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xfc: // seq_call
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
state->stack[state->depth++] = state->pc;
#else
2019-08-25 00:46:40 -04:00
state->depth++, state->stack[state->depth - 1] = state->pc;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + u16v;
break;
2019-12-01 21:52:53 -05:00
case 0xf8: // seq_loop; loop start, N iterations (or 256 if N = 0)
2020-09-20 11:15:47 -04:00
if (0 && state->depth >= 4) {
eu_stubbed_printf_0("Macro Level Over Error!\n");
}
2019-08-25 00:46:40 -04:00
state->remLoopIters[state->depth] = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
state->stack[state->depth++] = state->pc;
#else
2019-08-25 00:46:40 -04:00
state->depth++, state->stack[state->depth - 1] = state->pc;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xf7: // seq_loopend
2019-08-25 00:46:40 -04:00
state->remLoopIters[state->depth - 1]--;
if (state->remLoopIters[state->depth - 1] != 0) {
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
2019-12-01 21:52:53 -05:00
case 0xfb: // seq_jump
case 0xfa: // seq_beqz; jump if == 0
case 0xf9: // seq_bltz; jump if < 0
case 0xf5: // seq_bgez; jump if >= 0
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
2019-09-01 15:50:50 -04:00
if (cmd == 0xfa && value != 0) {
2019-08-25 00:46:40 -04:00
break;
2019-09-01 15:50:50 -04:00
}
if (cmd == 0xf9 && value >= 0) {
2019-08-25 00:46:40 -04:00
break;
2019-09-01 15:50:50 -04:00
}
if (cmd == 0xf5 && value < 0) {
2019-08-25 00:46:40 -04:00
break;
2019-09-01 15:50:50 -04:00
}
2019-08-25 00:46:40 -04:00
state->pc = seqPlayer->seqData + u16v;
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf4:
case 0xf3:
case 0xf2:
2020-03-01 22:42:52 -05:00
temp = m64_read_u8(state);
2020-02-03 00:51:26 -05:00
if (cmd == 0xf3 && value != 0) {
break;
}
if (cmd == 0xf2 && value >= 0) {
break;
}
2020-12-03 14:26:38 -05:00
state->pc += (s8) temp;
2020-02-03 00:51:26 -05:00
break;
#endif
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf1: // seq_reservenotes
#else
2019-12-01 21:52:53 -05:00
case 0xf2: // seq_reservenotes
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
note_pool_clear(&seqPlayer->notePool);
note_pool_fill(&seqPlayer->notePool, m64_read_u8(state));
break;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xf0: // seq_unreservenotes
#else
2019-12-01 21:52:53 -05:00
case 0xf1: // seq_unreservenotes
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
note_pool_clear(&seqPlayer->notePool);
break;
2019-12-01 21:52:53 -05:00
case 0xdf: // seq_transpose; set transposition in semitones
2019-08-25 00:46:40 -04:00
seqPlayer->transposition = 0;
// fallthrough
2019-12-01 21:52:53 -05:00
case 0xde: // seq_transposerel; add transposition
2019-08-25 00:46:40 -04:00
seqPlayer->transposition += (s8) m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xdd: // seq_settempo (bpm)
2020-12-03 14:26:38 -05:00
#ifndef VERSION_SH
2019-12-01 21:52:53 -05:00
case 0xdc: // seq_addtempo (bpm)
2020-12-03 14:26:38 -05:00
#endif
#ifdef VERSION_SH
seqPlayer->tempo = m64_read_u8(state) * TEMPO_SCALE;
#else
2019-08-25 00:46:40 -04:00
temp = m64_read_u8(state);
if (cmd == 0xdd) {
seqPlayer->tempo = temp * TEMPO_SCALE;
} else {
seqPlayer->tempo += (s8) temp * TEMPO_SCALE;
}
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
if (seqPlayer->tempo > gTempoInternalToExternal) {
seqPlayer->tempo = gTempoInternalToExternal;
}
2020-12-03 14:26:38 -05:00
//if (cmd){}
2019-08-25 00:46:40 -04:00
if ((s16) seqPlayer->tempo <= 0) {
seqPlayer->tempo = 1;
}
break;
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0xdc: // seq_addtempo (bpm)
seqPlayer->tempoAdd = (s8) m64_read_u8(state) * TEMPO_SCALE;
break;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xda:
temp = m64_read_u8(state);
u16v = m64_read_s16(state);
switch (temp) {
case SEQUENCE_PLAYER_STATE_0:
case SEQUENCE_PLAYER_STATE_FADE_OUT:
if (seqPlayer->state != SEQUENCE_PLAYER_STATE_2) {
seqPlayer->fadeTimerUnkEu = u16v;
seqPlayer->state = temp;
}
break;
case SEQUENCE_PLAYER_STATE_2:
2020-12-03 14:26:38 -05:00
seqPlayer->fadeRemainingFrames = u16v;
2020-02-03 00:51:26 -05:00
seqPlayer->state = temp;
2020-12-03 14:26:38 -05:00
seqPlayer->fadeVelocity =
(0.0f - seqPlayer->fadeVolume) / (s32)(u16v & 0xFFFFu);
2020-02-03 00:51:26 -05:00
break;
}
break;
case 0xdb:
temp32 = m64_read_u8(state);
switch (seqPlayer->state) {
case SEQUENCE_PLAYER_STATE_2:
break;
case SEQUENCE_PLAYER_STATE_FADE_OUT:
seqPlayer->state = SEQUENCE_PLAYER_STATE_0;
seqPlayer->fadeVolume = 0.0f;
// fallthrough
case SEQUENCE_PLAYER_STATE_0:
2020-12-03 14:26:38 -05:00
seqPlayer->fadeRemainingFrames = seqPlayer->fadeTimerUnkEu;
2020-02-03 00:51:26 -05:00
if (seqPlayer->fadeTimerUnkEu != 0) {
2020-12-03 14:26:38 -05:00
seqPlayer->fadeVelocity = (temp32 / 127.0f - seqPlayer->fadeVolume) / FLOAT_CAST(seqPlayer->fadeRemainingFrames);
2020-02-03 00:51:26 -05:00
} else {
seqPlayer->fadeVolume = temp32 / 127.0f;
}
}
break;
#else
2019-12-01 21:52:53 -05:00
case 0xdb: // seq_setvol
2019-08-25 00:46:40 -04:00
temp = m64_read_u8(state);
switch (seqPlayer->state) {
case SEQUENCE_PLAYER_STATE_2:
2020-12-03 14:26:38 -05:00
if (seqPlayer->fadeRemainingFrames != 0) {
2019-08-25 00:46:40 -04:00
f32 targetVolume = FLOAT_CAST(temp) / US_FLOAT(127.0);
seqPlayer->fadeVelocity = (targetVolume - seqPlayer->fadeVolume)
2020-12-03 14:26:38 -05:00
/ FLOAT_CAST(seqPlayer->fadeRemainingFrames);
2019-08-25 00:46:40 -04:00
break;
}
// fallthrough
case SEQUENCE_PLAYER_STATE_0:
seqPlayer->fadeVolume = FLOAT_CAST(temp) / US_FLOAT(127.0);
break;
case SEQUENCE_PLAYER_STATE_FADE_OUT:
case SEQUENCE_PLAYER_STATE_4:
seqPlayer->volume = FLOAT_CAST(temp) / US_FLOAT(127.0);
break;
}
break;
2019-12-01 21:52:53 -05:00
case 0xda: // seq_changevol
2020-03-01 22:42:52 -05:00
temp = m64_read_u8(state);
2019-08-25 00:46:40 -04:00
seqPlayer->fadeVolume =
2020-12-03 14:26:38 -05:00
seqPlayer->fadeVolume + (f32)(s8) temp / US_FLOAT(127.0);
2019-08-25 00:46:40 -04:00
break;
2020-02-03 00:51:26 -05:00
#endif
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
case 0xd9:
2020-03-01 22:42:52 -05:00
temp = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
seqPlayer->fadeVolumeScale = (s8) temp / 127.0f;
2020-02-03 00:51:26 -05:00
break;
#endif
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
case 0xd7: // seq_initchannels
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
sequence_player_init_channels(seqPlayer, u16v);
break;
2019-12-01 21:52:53 -05:00
case 0xd6: // seq_disablechannels
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
sequence_player_disable_channels(seqPlayer, u16v);
break;
2019-12-01 21:52:53 -05:00
case 0xd5: // seq_setmutescale
2020-03-01 22:42:52 -05:00
temp = m64_read_u8(state);
2020-12-03 14:26:38 -05:00
seqPlayer->muteVolumeScale = (f32)(s8) temp / US_FLOAT(127.0);
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xd4: // seq_mute
2019-08-25 00:46:40 -04:00
seqPlayer->muted = TRUE;
break;
2019-12-01 21:52:53 -05:00
case 0xd3: // seq_setmutebhv
2019-08-25 00:46:40 -04:00
seqPlayer->muteBehavior = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xd2: // seq_setshortnotevelocitytable
case 0xd1: // seq_setshortnotedurationtable
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
tempPtr = seqPlayer->seqData + u16v;
if (cmd == 0xd2) {
seqPlayer->shortNoteVelocityTable = tempPtr;
} else {
seqPlayer->shortNoteDurationTable = tempPtr;
}
break;
2019-12-01 21:52:53 -05:00
case 0xd0: // seq_setnoteallocationpolicy
2019-08-25 00:46:40 -04:00
seqPlayer->noteAllocPolicy = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xcc: // seq_setval
2019-08-25 00:46:40 -04:00
value = m64_read_u8(state);
break;
2019-12-01 21:52:53 -05:00
case 0xc9: // seq_bitand
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
value &= m64_read_u8(state);
#else
2019-08-25 00:46:40 -04:00
value = m64_read_u8(state) & value;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0xc8: // seq_subtract
2019-08-25 00:46:40 -04:00
value = value - m64_read_u8(state);
break;
2020-09-20 11:15:47 -04:00
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
case 0xc7:
temp = m64_read_u8(state);
u16v = m64_read_s16(state);
seqPlayer->seqData[u16v] = (u8) value + temp;
break;
case 0xc6:
seqPlayer->unkSh = TRUE;
break;
#endif
2020-09-20 11:15:47 -04:00
default:
eu_stubbed_printf_1("Group:Undefine upper C0h command (%x)\n", cmd);
break;
2019-08-25 00:46:40 -04:00
}
} else {
loBits = cmd & 0xf;
switch (cmd & 0xf0) {
2019-12-01 21:52:53 -05:00
case 0x00: // seq_testchdisabled
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
value = seqPlayer->channels[loBits]->finished;
#else
2019-08-25 00:46:40 -04:00
if (IS_SEQUENCE_CHANNEL_VALID(seqPlayer->channels[loBits]) == TRUE) {
value = seqPlayer->channels[loBits]->finished;
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
case 0x10:
break;
case 0x20:
break;
case 0x40:
break;
2019-12-01 21:52:53 -05:00
case 0x50: // seq_subvariation
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
value -= seqPlayer->seqVariationEu[0];
#else
2019-08-25 00:46:40 -04:00
value -= seqPlayer->seqVariation;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
case 0x60:
break;
2019-12-01 21:52:53 -05:00
case 0x70: // seq_setvariation
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
seqPlayer->seqVariationEu[0] = value;
#else
2019-08-25 00:46:40 -04:00
seqPlayer->seqVariation = value;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0x80: // seq_getvariation
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
value = seqPlayer->seqVariationEu[0];
#else
2019-08-25 00:46:40 -04:00
value = seqPlayer->seqVariation;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
break;
2019-12-01 21:52:53 -05:00
case 0x90: // seq_startchannel
2019-08-25 00:46:40 -04:00
u16v = m64_read_s16(state);
sequence_channel_enable(seqPlayer, loBits, seqPlayer->seqData + u16v);
break;
case 0xa0:
break;
2020-12-03 14:26:38 -05:00
#if !defined(VERSION_EU) && !defined(VERSION_SH)
2019-08-25 00:46:40 -04:00
case 0xd8: // (this makes no sense)
break;
case 0xd9:
break;
2020-02-03 00:51:26 -05:00
#endif
2020-09-20 11:15:47 -04:00
default:
eu_stubbed_printf_0("Group:Undefined Command\n");
break;
2019-08-25 00:46:40 -04:00
}
}
}
}
for (i = 0; i < CHANNELS_MAX; i++) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
if (IS_SEQUENCE_CHANNEL_VALID(seqPlayer->channels[i]) == TRUE) {
sequence_channel_process_script(seqPlayer->channels[i]);
}
#else
2019-08-25 00:46:40 -04:00
if (seqPlayer->channels[i] != &gSequenceChannelNone) {
sequence_channel_process_script(seqPlayer->channels[i]);
}
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
}
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
// This runs 240 times per second.
void process_sequences(UNUSED s32 iterationsRemaining) {
s32 i;
2019-12-01 21:52:53 -05:00
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
2019-08-25 00:46:40 -04:00
if (gSequencePlayers[i].enabled == TRUE) {
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
sequence_player_process_sequence(&gSequencePlayers[i]);
sequence_player_process_sound(&gSequencePlayers[i]);
#else
2019-08-25 00:46:40 -04:00
sequence_player_process_sequence(gSequencePlayers + i);
sequence_player_process_sound(gSequencePlayers + i);
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
}
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-12-01 21:52:53 -05:00
reclaim_notes();
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
process_notes();
2019-08-25 00:46:40 -04:00
}
void init_sequence_player(u32 player) {
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
sequence_player_disable(seqPlayer);
#endif
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqPlayer->unkSh = FALSE;
#else
2019-08-25 00:46:40 -04:00
seqPlayer->muted = FALSE;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->delay = 0;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
seqPlayer->state = 1;
#else
2019-08-25 00:46:40 -04:00
seqPlayer->state = SEQUENCE_PLAYER_STATE_0;
2020-02-03 00:51:26 -05:00
#endif
2020-12-03 14:26:38 -05:00
seqPlayer->fadeRemainingFrames = 0;
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
seqPlayer->fadeTimerUnkEu = 0;
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->tempoAcc = 0;
seqPlayer->tempo = 120 * TEMPO_SCALE; // 120 BPM
2020-12-03 14:26:38 -05:00
#ifdef VERSION_SH
seqPlayer->tempoAdd = 0;
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->transposition = 0;
2020-12-03 14:26:38 -05:00
#ifndef VERSION_SH
2019-12-01 21:52:53 -05:00
seqPlayer->muteBehavior = MUTE_BEHAVIOR_STOP_SCRIPT | MUTE_BEHAVIOR_STOP_NOTES | MUTE_BEHAVIOR_SOFTEN;
2020-12-03 14:26:38 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->noteAllocPolicy = 0;
seqPlayer->shortNoteVelocityTable = gDefaultShortNoteVelocityTable;
seqPlayer->shortNoteDurationTable = gDefaultShortNoteDurationTable;
seqPlayer->fadeVolume = 1.0f;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-03-01 22:42:52 -05:00
seqPlayer->fadeVolumeScale = 1.0f;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
seqPlayer->fadeVelocity = 0.0f;
seqPlayer->volume = 0.0f;
seqPlayer->muteVolumeScale = 0.5f;
}
2019-12-01 21:52:53 -05:00
void init_sequence_players(void) {
2019-08-25 00:46:40 -04:00
// Initialization function, called from audio_init
s32 i, j;
2019-12-01 21:52:53 -05:00
for (i = 0; i < ARRAY_COUNT(gSequenceChannels); i++) {
2019-08-25 00:46:40 -04:00
gSequenceChannels[i].seqPlayer = NULL;
gSequenceChannels[i].enabled = FALSE;
2020-12-03 14:26:38 -05:00
#if defined(VERSION_JP) || defined(VERSION_US)
2019-08-25 00:46:40 -04:00
}
2019-12-01 21:52:53 -05:00
for (i = 0; i < ARRAY_COUNT(gSequenceChannels); i++) {
2020-02-03 00:51:26 -05:00
#endif
2019-12-01 21:52:53 -05:00
// @bug Size of wrong array. Zeroes out second half of gSequenceChannels[0],
// all of gSequenceChannels[1..31], and part of gSequenceLayers[0].
// However, this is only called at startup, so it's harmless.
#ifdef AVOID_UB
#define LAYERS_SIZE LAYERS_MAX
#else
#define LAYERS_SIZE ARRAY_COUNT(gSequenceLayers)
#endif
for (j = 0; j < LAYERS_SIZE; j++) {
2019-08-25 00:46:40 -04:00
gSequenceChannels[i].layers[j] = NULL;
}
}
2019-12-01 21:52:53 -05:00
init_layer_freelist();
2019-08-25 00:46:40 -04:00
2019-12-01 21:52:53 -05:00
for (i = 0; i < ARRAY_COUNT(gSequenceLayers); i++) {
gSequenceLayers[i].seqChannel = NULL;
gSequenceLayers[i].enabled = FALSE;
2019-08-25 00:46:40 -04:00
}
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
for (j = 0; j < CHANNELS_MAX; j++) {
gSequencePlayers[i].channels[j] = &gSequenceChannelNone;
}
2020-12-03 14:26:38 -05:00
#if defined(VERSION_EU) || defined(VERSION_SH)
2020-02-03 00:51:26 -05:00
gSequencePlayers[i].seqVariationEu[0] = -1;
#else
2019-08-25 00:46:40 -04:00
gSequencePlayers[i].seqVariation = -1;
2020-12-03 14:26:38 -05:00
#endif
#ifdef VERSION_SH
gSequencePlayers[i].muteBehavior = MUTE_BEHAVIOR_STOP_SCRIPT | MUTE_BEHAVIOR_STOP_NOTES | MUTE_BEHAVIOR_SOFTEN;
gSequencePlayers[i].enabled = FALSE;
gSequencePlayers[i].muted = FALSE;
2020-02-03 00:51:26 -05:00
#endif
2019-08-25 00:46:40 -04:00
gSequencePlayers[i].bankDmaInProgress = FALSE;
gSequencePlayers[i].seqDmaInProgress = FALSE;
init_note_lists(&gSequencePlayers[i].notePool);
init_sequence_player(i);
}
}
2020-12-03 14:26:38 -05:00