Merge pull request #25 from MeltyPlayer/audio

Exposed audio playback functionality by adding decomp logic into libsm64.
This commit is contained in:
Jeremy Burns
2022-12-21 10:10:11 -07:00
committed by GitHub
65 changed files with 24098 additions and 22 deletions
+3 -3
View File
@@ -7,9 +7,9 @@ else
CC := cc CC := cc
LDFLAGS := -lm -shared LDFLAGS := -lm -shared
endif endif
CFLAGS := -g -Wall -fPIC -DSM64_LIB_EXPORT -DGBI_FLOATS CFLAGS := -g -Wall -fPIC -DSM64_LIB_EXPORT -DGBI_FLOATS -DVERSION_US -DNO_SEGMENTED_MEMORY
SRC_DIRS := src src/decomp src/decomp/engine src/decomp/game src/decomp/mario src/decomp/tools SRC_DIRS := src src/decomp src/decomp/engine src/decomp/include/PR src/decomp/game src/decomp/pc src/decomp/pc/audio src/decomp/mario src/decomp/tools src/decomp/audio
BUILD_DIR := build BUILD_DIR := build
DIST_DIR := dist DIST_DIR := dist
ALL_DIRS := $(addprefix $(BUILD_DIR)/,$(SRC_DIRS)) ALL_DIRS := $(addprefix $(BUILD_DIR)/,$(SRC_DIRS))
@@ -42,7 +42,7 @@ src/decomp/mario/geo.inc.c: ./import-mario-geo.py
$(BUILD_DIR)/%.o: %.c $(IMPORTED) $(BUILD_DIR)/%.o: %.c $(IMPORTED)
@$(CC) $(CFLAGS) -MM -MP -MT $@ -MF $(BUILD_DIR)/$*.d $< @$(CC) $(CFLAGS) -MM -MP -MT $@ -MF $(BUILD_DIR)/$*.d $<
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -I src/decomp/include -o $@ $<
$(LIB_FILE): $(O_FILES) $(LIB_FILE): $(O_FILES)
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
@@ -0,0 +1,500 @@
//! Copt inlining for US/JP. Here be dragons
// This version is basically identical to EU
#include <ultra64.h>
#include <macros.h>
#include "../heap.h"
#include "../data.h"
#include "../load.h"
#include "../seqplayer.h"
#include "../external.h"
#include "../effects.h"
#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
#define COPT 0
#if COPT
#define M64_READ_U8(state, dst) \
dst = m64_read_u8(state);
#else
#define M64_READ_U8(state, dst) \
{ \
u8 * _ptr_pc; \
u8 _pc; \
_ptr_pc = (*state).pc; \
((*state).pc)++; \
_pc = *_ptr_pc; \
dst = _pc; \
}
#endif
#if COPT
#define M64_READ_S16(state, dst) \
dst = m64_read_s16(state);
#else
#define M64_READ_S16(state, dst) \
{ \
s16 _ret; \
_ret = *(*state).pc << 8; \
((*state).pc)++; \
_ret = *(*state).pc | _ret; \
((*state).pc)++; \
dst = _ret; \
}
#endif
#if COPT
#define M64_READ_COMPRESSED_U16(state, dst) \
dst = m64_read_compressed_u16(state);
#else
#define M64_READ_COMPRESSED_U16(state, dst) \
{ \
u16 ret = *(state->pc++); \
if (ret & 0x80) { \
ret = (ret << 8) & 0x7f00; \
ret = *(state->pc++) | ret; \
} \
dst = ret; \
}
#endif
#if COPT
#define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
dst = get_instrument(seqChannel, instId, _instOut, _adsr);
#else
#define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
{ \
struct AdsrSettings *adsr = _adsr; \
struct Instrument **instOut = _instOut;\
u8 _instId = instId; \
struct Instrument *inst; \
UNUSED u32 pad; \
/* copt inlines instId here */ \
if (instId >= gCtlEntries[(*seqChannel).bankId].numInstruments) { \
_instId = gCtlEntries[(*seqChannel).bankId].numInstruments; \
if (_instId == 0) { \
dst = 0; \
goto ret ## l; \
} \
_instId--; \
} \
inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
if (inst == NULL) { \
while (_instId != 0xff) { \
inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
if (inst != NULL) { \
goto gi ## l; \
} \
_instId--; \
} \
gi ## l:; \
} \
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 \
+ gBankLoadedPool.temporary.pool.size))) { \
(*adsr).envelope = (*inst).envelope; \
(*adsr).releaseRate = (*inst).releaseRate; \
*instOut = inst; \
_instId++; \
goto ret ## l; \
} \
gAudioErrorFlags = _instId + 0x20000; \
*instOut = NULL; \
ret ## l: ; \
}
#endif
void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) {
struct SequencePlayer *seqPlayer; // sp5C, t4
struct SequenceChannel *seqChannel; // sp58, t5
struct M64ScriptState *state;
struct Portamento *portamento;
struct AudioBankSound *sound;
struct Instrument *instrument;
struct Drum *drum;
s32 temp_a0_5;
u8 sameSound;
u8 cmd; // a0 sp3E, EU s2
u8 cmdSemitone; // sp3D, t0
u16 sp3A; // t2, a0, a1
f32 tuning; // f0
s32 vel; // sp30, t3
s32 usedSemitone; // a1
f32 freqScale; // sp28, f0
f32 sp24;
f32 temp_f12;
f32 temp_f2;
//! Copt: manually inline these functions in the scope of this routine
#ifdef __sgi
#pragma inline routine(m64_read_u8)
#pragma inline routine(m64_read_compressed_u16)
#pragma inline routine(m64_read_s16)
#pragma inline routine(get_instrument)
#endif
sameSound = TRUE;
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;
}
if (!layer->continuousNotes) {
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;
}
seqChannel = (*layer).seqChannel;
seqPlayer = (*seqChannel).seqPlayer;
for (;;) {
state = &layer->scriptState;
//M64_READ_U8(state, cmd);
{
u8 *_ptr_pc;
_ptr_pc = (*state).pc++;
cmd = *_ptr_pc;
}
if (cmd <= 0xc0) {
break;
}
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;
}
state->depth--, state->pc = state->stack[state->depth];
break;
case 0xfc: // layer_call
M64_READ_S16(state, sp3A);
state->depth++, state->stack[state->depth - 1] = state->pc;
state->pc = seqPlayer->seqData + sp3A;
break;
case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0)
M64_READ_U8(state, state->remLoopIters[state->depth]);
state->depth++, state->stack[state->depth - 1] = 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
M64_READ_S16(state, sp3A);
state->pc = seqPlayer->seqData + sp3A;
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);
} else {
layer->pan = (f32) temp_a0_5 / US_FLOAT(128.0);
}
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
//! copt needs a ternary:
//layer->continuousNotes = (cmd == 0xc4) ? TRUE : FALSE;
{
u8 setting;
if (cmd == 0xc4) {
setting = TRUE;
} else {
setting = FALSE;
}
layer->continuousNotes = setting;
seq_channel_layer_note_decay(layer);
}
break;
case 0xc3: // layer_setshortnotedefaultplaypercentage
M64_READ_COMPRESSED_U16(state, sp3A);
layer->shortNoteDefaultPlayPercentage = sp3A;
break;
case 0xc6: // layer_setinstr
M64_READ_U8(state, cmdSemitone);
if (cmdSemitone < 127) {
GET_INSTRUMENT(seqChannel, cmdSemitone, &(*layer).instrument, &(*layer).adsr, cmdSemitone, 1);
}
break;
case 0xc7: // layer_portamento
M64_READ_U8(state, (*layer).portamento.mode);
M64_READ_U8(state, cmdSemitone);
cmdSemitone = cmdSemitone + (*seqChannel).transposition;
cmdSemitone += (*layer).transposition;
cmdSemitone += (*seqPlayer).transposition;
if (cmdSemitone >= 0x80) {
cmdSemitone = 0;
}
layer->portamentoTargetNote = cmdSemitone;
// If special, the next param is u8 instead of var
if (PORTAMENTO_IS_SPECIAL((*layer).portamento)) {
layer->portamentoTime = *((state)->pc++);
break;
}
M64_READ_COMPRESSED_U16(state, sp3A);
layer->portamentoTime = sp3A;
break;
case 0xc8: // layer_disableportamento
layer->portamento.mode = 0;
break;
default:
switch (cmd & 0xf0) {
case 0xd0: // layer_setshortnotevelocityfromtable
sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xf];
(*layer).velocitySquare = (f32)(sp3A * sp3A);
break;
case 0xe0: // layer_setshortnotedurationfromtable
(*layer).noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf];
break;
}
}
}
if (cmd == 0xc0) { // layer_delay
M64_READ_COMPRESSED_U16(state, layer->delay);
layer->stopSomething = TRUE;
} else {
layer->stopSomething = FALSE;
if (seqChannel->largeNotes == TRUE) {
switch (cmd & 0xc0) {
case 0x00: // layer_note0 (play percentage, velocity, duration)
M64_READ_COMPRESSED_U16(state, sp3A);
vel = *((*state).pc++);
layer->noteDuration = *((*state).pc++);
layer->playPercentage = sp3A;
goto l1090;
case 0x40: // layer_note1 (play percentage, velocity)
M64_READ_COMPRESSED_U16(state, sp3A);
vel = *((*state).pc++);
layer->noteDuration = 0;
layer->playPercentage = sp3A;
goto l1090;
case 0x80: // layer_note2 (velocity, duration; uses last play percentage)
sp3A = layer->playPercentage;
vel = *((*state).pc++);
layer->noteDuration = *((*state).pc++);
goto l1090;
}
l1090:
cmdSemitone = cmd - (cmd & 0xc0);
layer->velocitySquare = vel * vel;
} else {
switch (cmd & 0xc0) {
case 0x00: // play note, type 0 (play percentage)
M64_READ_COMPRESSED_U16(state, sp3A);
layer->playPercentage = sp3A;
goto l1138;
case 0x40: // play note, type 1 (uses default play percentage)
sp3A = layer->shortNoteDefaultPlayPercentage;
goto l1138;
case 0x80: // play note, type 2 (uses last play percentage)
sp3A = layer->playPercentage;
goto l1138;
}
l1138:
cmdSemitone = cmd - (cmd & 0xc0);
}
layer->delay = sp3A;
layer->duration = layer->noteDuration * sp3A / 256;
if ((seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES) != 0)
|| seqChannel->stopSomething2
|| !seqChannel->hasInstrument
) {
layer->stopSomething = TRUE;
} else {
if (seqChannel->instOrWave == 0) { // drum
cmdSemitone += (*seqChannel).transposition + (*layer).transposition;
if (cmdSemitone >= gCtlEntries[seqChannel->bankId].numDrums) {
cmdSemitone = gCtlEntries[seqChannel->bankId].numDrums;
if (cmdSemitone == 0) {
// this goto looks a bit like a function return...
layer->stopSomething = TRUE;
goto skip;
}
cmdSemitone--;
}
drum = gCtlEntries[seqChannel->bankId].drums[cmdSemitone];
if (drum == NULL) {
layer->stopSomething = TRUE;
} else {
layer->adsr.envelope = drum->envelope;
layer->adsr.releaseRate = drum->releaseRate;
layer->pan = FLOAT_CAST(drum->pan) / US_FLOAT(128.0);
layer->sound = &drum->sound;
layer->freqScale = layer->sound->tuning;
}
skip:;
} else { // instrument
cmdSemitone += (*seqPlayer).transposition + (*seqChannel).transposition + (*layer).transposition;
if (cmdSemitone >= 0x80) {
layer->stopSomething = TRUE;
} else {
instrument = layer->instrument;
if (instrument == NULL) {
instrument = seqChannel->instrument;
}
if (layer->portamento.mode != 0) {
//! copt needs a ternary:
//usedSemitone = (layer->portamentoTargetNote < cmdSemitone) ? cmdSemitone : layer->portamentoTargetNote;
if (layer->portamentoTargetNote < cmdSemitone) {
usedSemitone = cmdSemitone;
} else {
usedSemitone = layer->portamentoTargetNote;
}
if (instrument != NULL) {
sound = (u8) usedSemitone < instrument->normalRangeLo ? &instrument->lowNotesSound
: (u8) usedSemitone <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
sameSound = (sound == (*layer).sound);
layer->sound = sound;
tuning = (*sound).tuning;
} else {
layer->sound = NULL;
tuning = 1.0f;
}
temp_f2 = gNoteFrequencies[cmdSemitone] * 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;
goto l13cc;
case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4:
freqScale = temp_f2;
sp24 = temp_f12;
goto l13cc;
}
l13cc:
portamento->extent = sp24 / freqScale - US_FLOAT(1.0);
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 = cmdSemitone;
}
} else if (instrument != NULL) {
sound = cmdSemitone < instrument->normalRangeLo ?
&instrument->lowNotesSound : cmdSemitone <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
sameSound = (sound == (*layer).sound);
layer->sound = sound;
layer->freqScale = gNoteFrequencies[cmdSemitone] * (*sound).tuning;
} else {
layer->sound = NULL;
layer->freqScale = gNoteFrequencies[cmdSemitone];
}
}
}
layer->delayUnused = layer->delay;
}
}
if (layer->stopSomething == TRUE) {
if (layer->note != NULL || layer->continuousNotes) {
seq_channel_layer_note_decay(layer);
}
return;
}
cmdSemitone = FALSE;
if (!layer->continuousNotes) {
cmdSemitone = TRUE;
} else if (layer->note == NULL || layer->status == SOUND_LOAD_STATUS_NOT_LOADED) {
cmdSemitone = TRUE;
} else if (sameSound == FALSE) {
seq_channel_layer_note_decay(layer);
cmdSemitone = TRUE;
} else if (layer->sound == NULL) {
init_synthetic_wave(layer->note, layer);
}
if (cmdSemitone != FALSE) {
(*layer).note = alloc_note(layer);
}
if (layer->note != NULL && layer->note->parentLayer == layer) {
note_vibrato_init(layer->note);
}
}
+961
View File
@@ -0,0 +1,961 @@
#include <ultra64.h>
#include "data.h"
#include "effects.h"
extern struct OSMesgQueue OSMesgQueue0;
extern struct OSMesgQueue OSMesgQueue1;
extern struct OSMesgQueue OSMesgQueue2;
extern struct OSMesgQueue OSMesgQueue3;
#ifdef VERSION_EU
struct ReverbSettingsEU sReverbSettings[] = {
{ 0x04, 0x0c, 0x2fff },
{ 0x04, 0x0a, 0x47ff },
{ 0x04, 0x10, 0x2fff },
{ 0x04, 0x0e, 0x3fff },
{ 0x04, 0x0c, 0x4fff },
{ 0x04, 0x0a, 0x37ff }
};
struct AudioSessionSettingsEU gAudioSessionPresets[] = {
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[2], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[3], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[4], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00004000, 0x00006e00,
0x00003f00, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00004100, 0x00006e00,
0x00004400, 0x00002a80 },
{ 0x00007d00, 0x01, 0x14, 0x01, 0x00, &sReverbSettings[5], 0x7fff, 0x0000, 0x00003500, 0x00006280,
0x00004000, 0x00001b00 }
};
#endif
// Format:
// - frequency
// - max number of simultaneous notes
// - reverb downsample rate (makes the ring buffer be downsampled to save memory)
// - reverb window size (ring buffer size, length affects reverb delay)
// - reverb gain (0 = min reverb, 32767 = max reverb, 32769 to 65535 = louder and louder...)
// - volume
// - memory used for persistent sequences
// - memory used for persistent banks
// - memory used for temporary sequences
// - memory used for temporary banks
#if defined(VERSION_JP) || defined(VERSION_US)
struct AudioSessionSettings gAudioSessionPresets[18] = {
#ifdef VERSION_JP
{ 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3E00, 0x6200, 0x3F00, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3F00, 0x6200, 0x4400, 0x2A80 },
{ 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x3300, 0x5500, 0x4000, 0x1B00 },
#else
{ 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x4000, 0x6E00, 0x3F00, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x4100, 0x6E00, 0x4400, 0x2A80 },
{ 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x34C0, 0x6280, 0x4000, 0x1B00 },
#endif
{ 27000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x0800, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x1000, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 14, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 12, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 10, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 8, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
#endif
// gAudioCosineTable[k] = round((2**15 - 1) * cos(pi/2 * k / 127)). Unused.
#if defined(VERSION_JP) || defined(VERSION_US)
u16 gAudioCosineTable[128] = {
0x7FFF, 32764, 32757, 32744, 32727, 32704, 32677, 32644, 32607, 32564, 32517, 32464, 32407,
32344, 32277, 32205, 32127, 32045, 31958, 31866, 31770, 31668, 31561, 31450, 31334, 31213,
31087, 30957, 30822, 30682, 30537, 30388, 30234, 30075, 29912, 29744, 29572, 29395, 29214,
29028, 28838, 28643, 28444, 28241, 28033, 27821, 27605, 27385, 27160, 26931, 26698, 26461,
26220, 25975, 25726, 25473, 25216, 24956, 24691, 24423, 24151, 23875, 23596, 23313, 23026,
22736, 22442, 22145, 21845, 21541, 21234, 20924, 20610, 20294, 19974, 19651, 19325, 18997,
18665, 18331, 17993, 17653, 17310, 16965, 16617, 16266, 15913, 15558, 15200, 14840, 14477,
14113, 13746, 13377, 13006, 12633, 12258, 11881, 11503, 11122, 10740, 10357, 9971, 9584,
9196, 8806, 8415, 8023, 7630, 7235, 6839, 6442, 6044, 5646, 5246, 4845, 4444,
4042, 3640, 3237, 2833, 2429, 2025, 1620, 1216, 810, 405, 0,
};
#endif
// Transforms a pitch scale factor in -127..127 into a frequency scale factor
// between -1 and +1 octave.
// gPitchBendFrequencyScale[k] = 0.5 * 2^(k/127)
#ifndef VERSION_SH
#if defined(VERSION_EU)
f32 gPitchBendFrequencyScale[256] = {
0.5f,
#else
f32 gPitchBendFrequencyScale[255] = {
#endif
0.5f, 0.502736f, 0.505488f, 0.508254f, 0.511036f, 0.513833f, 0.516645f, 0.519472f, 0.522315f,
0.525174f, 0.528048f, 0.530938f, 0.533843f, 0.536765f, 0.539702f, 0.542656f, 0.545626f, 0.548612f,
0.551614f, 0.554633f, 0.557669f, 0.560721f, 0.563789f, 0.566875f, 0.569977f, 0.573097f, 0.576233f,
0.579387f, 0.582558f, 0.585746f, 0.588951f, 0.592175f, 0.595415f, 0.598674f, 0.601950f, 0.605245f,
0.608557f, 0.611888f, 0.615236f, 0.618603f, 0.621989f, 0.625393f, 0.628815f, 0.632257f, 0.635717f,
0.639196f, 0.642694f, 0.646212f, 0.649748f, 0.653304f, 0.656880f, 0.660475f, 0.664089f, 0.667724f,
0.671378f, 0.675052f, 0.678747f, 0.682461f, 0.686196f, 0.689952f, 0.693727f, 0.697524f, 0.701341f,
0.705180f, 0.709039f, 0.712919f, 0.716821f, 0.720744f, 0.724689f, 0.728655f, 0.732642f, 0.736652f,
0.740684f, 0.744737f, 0.748813f, 0.752911f, 0.757031f, 0.761175f, 0.765340f, 0.769529f, 0.773740f,
0.777975f, 0.782232f, 0.786513f, 0.790818f, 0.795146f, 0.799497f, 0.803873f, 0.808272f, 0.812696f,
0.817144f, 0.821616f, 0.826112f, 0.830633f, 0.835179f, 0.839750f, 0.844346f, 0.848966f, 0.853613f,
0.858284f, 0.862982f, 0.867704f, 0.872453f, 0.877228f, 0.882029f, 0.886856f, 0.891709f, 0.896590f,
0.901496f, 0.906430f, 0.911391f, 0.916379f, 0.921394f, 0.926436f, 0.931507f, 0.936604f, 0.941730f,
0.946884f, 0.952066f, 0.957277f, 0.962516f, 0.967783f, 0.973080f, 0.978405f, 0.983760f, 0.989144f,
0.994557f, 1.0f, 1.005473f, 1.010975f, 1.016508f, 1.022071f, 1.027665f, 1.033289f, 1.038944f,
1.044630f, 1.050347f, 1.056095f, 1.061875f, 1.067687f, 1.073530f, 1.079405f, 1.085312f, 1.091252f,
1.097224f, 1.103229f, 1.109267f, 1.115337f, 1.121441f, 1.127579f, 1.133750f, 1.139955f, 1.146193f,
1.152466f, 1.158773f, 1.165115f, 1.171491f, 1.177903f, 1.184349f, 1.190831f, 1.197348f, 1.203901f,
1.210489f, 1.217114f, 1.223775f, 1.230473f, 1.237207f, 1.243978f, 1.250786f, 1.257631f, 1.264514f,
1.271434f, 1.278392f, 1.285389f, 1.292423f, 1.299497f, 1.306608f, 1.313759f, 1.320949f, 1.328178f,
1.335447f, 1.342756f, 1.350104f, 1.357493f, 1.364922f, 1.372392f, 1.379903f, 1.387455f, 1.395048f,
1.402683f, 1.410360f, 1.418078f, 1.425839f, 1.433642f, 1.441488f, 1.449377f, 1.457309f, 1.465285f,
1.473304f, 1.481367f, 1.489474f, 1.497626f, 1.505822f, 1.514063f, 1.522349f, 1.530681f, 1.539058f,
1.547481f, 1.555950f, 1.564465f, 1.573027f, 1.581636f, 1.590292f, 1.598995f, 1.607746f, 1.616545f,
1.625392f, 1.634287f, 1.643231f, 1.652224f, 1.661266f, 1.670358f, 1.679500f, 1.688691f, 1.697933f,
1.707225f, 1.716569f, 1.725963f, 1.735409f, 1.744906f, 1.754456f, 1.764058f, 1.773712f, 1.783419f,
1.793179f, 1.802993f, 1.812860f, 1.822782f, 1.832757f, 1.842788f, 1.852873f, 1.863013f, 1.873209f,
1.883461f, 1.893768f, 1.904132f, 1.914553f, 1.925031f, 1.935567f, 1.946159f, 1.956810f, 1.967520f,
1.978287f, 1.989114f, 2.0f
};
// Frequencies for notes using the standard twelve-tone equal temperament scale.
// For indices 0..116, gNoteFrequencies[k] = 2^((k-39)/12).
// For indices 117..128, gNoteFrequencies[k] = 0.5 * 2^((k-39)/12).
// The 39 in the formula refers to piano key 40 (middle C, at 256 Hz) being
// the reference frequency, which is assigned value 1.
// clang-format off
f32 gNoteFrequencies[128] = {
0.105112f, 0.111362f, 0.117984f, 0.125f, 0.132433f, 0.140308f, 0.148651f, 0.15749f, 0.166855f, 0.176777f, 0.187288f, 0.198425f,
0.210224f, 0.222725f, 0.235969f, 0.25f, 0.264866f, 0.280616f, 0.297302f, 0.31498f, 0.33371f, 0.353553f, 0.374577f, 0.39685f,
0.420448f, 0.445449f, 0.471937f, 0.5f, 0.529732f, 0.561231f, 0.594604f, 0.629961f, 0.66742f, 0.707107f, 0.749154f, 0.793701f,
0.840897f, 0.890899f, 0.943875f, 1.0f, 1.059463f, 1.122462f, 1.189207f, 1.259921f, 1.33484f, 1.414214f, 1.498307f, 1.587401f,
1.681793f, 1.781798f, 1.887749f, 2.0f, 2.118926f, 2.244924f, 2.378414f, 2.519842f, 2.66968f, 2.828428f, 2.996615f, 3.174803f,
3.363586f, 3.563596f, 3.775498f, 4.0f, 4.237853f, 4.489849f, 4.756829f, 5.039685f, 5.33936f, 5.656855f, 5.993229f, 6.349606f,
6.727173f, 7.127192f, 7.550996f, 8.0f, 8.475705f, 8.979697f, 9.513658f, 10.07937f, 10.67872f, 11.31371f, 11.986459f, 12.699211f,
13.454346f, 14.254383f, 15.101993f, 16.0f, 16.95141f, 17.959394f, 19.027315f, 20.15874f, 21.35744f, 22.62742f, 23.972918f, 25.398422f,
26.908691f, 28.508766f, 30.203985f, 32.0f, 33.90282f, 35.91879f, 38.05463f, 40.31748f, 42.71488f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f, 85.42976f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f
};
// clang-format on
// goes up by ~12 at each step for the first 4 values (starting from 0), then by ~6
u8 gDefaultShortNoteVelocityTable[16] = {
12, 25, 38, 51, 57, 64, 71, 76, 83, 89, 96, 102, 109, 115, 121, 127,
};
// goes down by 26 at each step for the first 4 values (starting from 255), then by ~12
u8 gDefaultShortNoteDurationTable[16] = {
229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0,
};
#if defined(VERSION_JP) || defined(VERSION_US)
// gVibratoCurve[k] = k*8
s8 gVibratoCurve[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 };
#endif
struct AdsrEnvelope gDefaultEnvelope[] = {
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
};
#endif
#ifdef VERSION_EU
struct NoteSubEu gZeroNoteSub = { 0 };
struct NoteSubEu gDefaultNoteSub = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { NULL } };
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 sSawtoothWaves[256] = {
0, 1023, 2047, 3071, 4095, 5119, 6143, 7167, 8191, 9215, 10239,
11263, 0x2FFF, 13311, 0x37FF, 15359, 0x3FFF, 17407, 0x47FF, 19455, 0x4FFF, 21503,
22527, 23551, 24575, 25599, 26623, 27647, 28671, 29695, 30719, 31743, -0x7FFF,
-31743, -30719, -29695, -28671, -27647, -26623, -25599, -24575, -23551, -22527, -21503,
-0x4FFF, -19455, -0x47FF, -17407, -0x3FFF, -15359, -0x37FF, -13311, -0x2FFF, -11263, -10239,
-9215, -8191, -7167, -6143, -5119, -4095, -3071, -2047, -1023,
0, 0x7FF, 0xFFF, 0x17FF, 0x1FFF, 0x27FF, 0x2FFF, 0x37FF, 0x3FFF, 0x47FF, 0x4FFF,
0x57FF, 0x5FFF, 0x67FF, 0x6FFF, 0x77FF, 0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801,
0xb001, 0xb801, 0xc001, 0xc801, 0xd001, 0xd801, 0xe001, 0xe801, 0xf001, 0xf801, 0x0000,
0x07ff, 0x0fff, 0x17ff, 0x1fff, 0x27ff, 0x2fff, 0x37ff, 0x3fff, 0x47ff, 0x4fff, 0x57ff,
0x5fff, 0x67ff, 0x6fff, 0x77ff, 0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801, 0xb001,
0xb801, 0xc001, 0xc801, 0xd001, 0xd801, 0xe001, 0xe801, 0xf001, 0xf801,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001
};
s16 sTriangleWaves[256] = {
0x0000, 0x07ff, 0x0fff, 0x17ff, 0x1fff, 0x27ff, 0x2fff, 0x37ff, 0x3fff, 0x47ff, 0x4fff, 0x57ff,
0x5fff, 0x67ff, 0x6fff, 0x77ff, 0x7fff, 0x77ff, 0x6fff, 0x67ff, 0x5fff, 0x57ff, 0x4fff, 0x47ff,
0x3fff, 0x37ff, 0x2fff, 0x27ff, 0x1fff, 0x17ff, 0x0fff, 0x07ff, 0x0000, 0xf801, 0xf001, 0xe801,
0xe001, 0xd801, 0xd001, 0xc801, 0xc001, 0xb801, 0xb001, 0xa801, 0xa001, 0x9801, 0x9001, 0x8801,
0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801, 0xb001, 0xb801, 0xc001, 0xc801, 0xd001, 0xd801,
0xe001, 0xe801, 0xf001, 0xf801, 0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x7fff, 0x6fff, 0x5fff, 0x4fff, 0x3fff, 0x2fff, 0x1fff, 0x0fff, 0x0000, 0xf001, 0xe001, 0xd001,
0xc001, 0xb001, 0xa001, 0x9001, 0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff, 0x7fff, 0x6fff, 0x5fff, 0x4fff,
0x3fff, 0x2fff, 0x1fff, 0x0fff, 0x0000, 0xf001, 0xe001, 0xd001, 0xc001, 0xb001, 0xa001, 0x9001,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001, 0x0000, 0x1fff, 0x3fff, 0x5fff,
0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001,
0x8001, 0xa001, 0xc001, 0xe001, 0x0000, 0x1fff, 0x3fff, 0x5fff, 0x7fff, 0x5fff, 0x3fff, 0x1fff,
0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001, 0x0000, 0x1fff, 0x3fff, 0x5fff,
0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001,
};
s16 sSineWaves[256] = {
0x0000, 0x0c8b, 0x18f8, 0x2527, 0x30fb, 0x3c56, 0x471c, 0x5133, 0x5a81, 0x62f1, 0x6a6c, 0x70e1,
0x7640, 0x7a7c, 0x7d89, 0x7f61, 0x7fff, 0x7f61, 0x7d89, 0x7a7c, 0x7640, 0x70e1, 0x6a6c, 0x62f1,
0x5a81, 0x5133, 0x471c, 0x3c56, 0x30fb, 0x2527, 0x18f8, 0x0c8b, 0x0000, 0xf375, 0xe708, 0xdad9,
0xcf05, 0xc3aa, 0xb8e4, 0xaecd, 0xa57f, 0x9d0f, 0x9594, 0x8f1f, 0x89c0, 0x8584, 0x8277, 0x809f,
0x8001, 0x809f, 0x8277, 0x8584, 0x89c0, 0x8f1f, 0x9594, 0x9d0f, 0xa57f, 0xaecd, 0xb8e4, 0xc3aa,
0xcf05, 0xdad9, 0xe708, 0xf375, 0x0000, 0x18f8, 0x30fb, 0x471c, 0x5a81, 0x6a6c, 0x7640, 0x7d89,
0x7fff, 0x7d89, 0x7640, 0x6a6c, 0x5a81, 0x471c, 0x30fb, 0x18f8, 0x0000, 0xe708, 0xcf05, 0xb8e4,
0xa57f, 0x9594, 0x89c0, 0x8277, 0x8001, 0x8277, 0x89c0, 0x9594, 0xa57f, 0xb8e4, 0xcf05, 0xe708,
0x0000, 0x18f8, 0x30fb, 0x471c, 0x5a81, 0x6a6c, 0x7640, 0x7d89, 0x7fff, 0x7d89, 0x7640, 0x6a6c,
0x5a81, 0x471c, 0x30fb, 0x18f8, 0x0000, 0xe708, 0xcf05, 0xb8e4, 0xa57f, 0x9594, 0x89c0, 0x8277,
0x8001, 0x8277, 0x89c0, 0x9594, 0xa57f, 0xb8e4, 0xcf05, 0xe708, 0x0000, 0x30fb, 0x5a81, 0x7640,
0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05,
0x0000, 0x30fb, 0x5a81, 0x7640, 0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0,
0x8001, 0x89c0, 0xa57f, 0xcf05, 0x0000, 0x30fb, 0x5a81, 0x7640, 0x7fff, 0x7640, 0x5a81, 0x30fb,
0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05, 0x0000, 0x30fb, 0x5a81, 0x7640,
0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f,
};
s16 sSquareWaves[256] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001,
0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001,
};
s16 sEuUnknownWave6[256] = {
0x0000, 0x9ba7, 0x9b41, 0x6c9b, 0x9450, 0xadda, 0x569e, 0x189a, 0x69bf, 0xb79d, 0x6fe9, 0x08ec,
0x0d34, 0x1aea, 0xce76, 0xad86, 0x2710, 0xa038, 0x7e28, 0x2fd8, 0x3af8, 0x3bfa, 0xd10b, 0x84c7,
0xcd7f, 0x18f4, 0xd4c8, 0x76f8, 0x8994, 0xaa11, 0x73fb, 0x6c01, 0x0000, 0x93ff, 0x8c05, 0x55ef,
0x766c, 0x8907, 0x2b38, 0xe70d, 0x3281, 0x7b38, 0x2ef5, 0xc407, 0xc508, 0xd027, 0x81d8, 0x5fc9,
0xd8f0, 0x5279, 0x318a, 0xe517, 0xf2cc, 0xf713, 0x9017, 0x4864, 0x9641, 0xe765, 0xa962, 0x5227,
0x6bb0, 0x9364, 0x64bf, 0x645a, 0x0000, 0x9b41, 0x9450, 0x569e, 0x69bf, 0x6fe9, 0x0d34, 0xce76,
0x2710, 0x7e28, 0x3af8, 0xd10b, 0xcd7f, 0xd4c8, 0x8994, 0x73fb, 0x0000, 0x8c05, 0x766c, 0x2b38,
0x3281, 0x2ef5, 0xc508, 0x81d8, 0xd8f0, 0x318a, 0xf2cc, 0x9017, 0x9641, 0xa962, 0x6bb0, 0x64bf,
0x0000, 0x9b41, 0x9450, 0x569e, 0x69bf, 0x6fe9, 0x0d34, 0xce76, 0x2710, 0x7e28, 0x3af8, 0xd10b,
0xcd7f, 0xd4c8, 0x8994, 0x73fb, 0x0000, 0x8c05, 0x766c, 0x2b38, 0x3281, 0x2ef5, 0xc508, 0x81d8,
0xd8f0, 0x318a, 0xf2cc, 0x9017, 0x9641, 0xa962, 0x6bb0, 0x64bf, 0x0000, 0x9450, 0x69bf, 0x0d34,
0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0,
0x0000, 0x9450, 0x69bf, 0x0d34, 0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508,
0xd8f0, 0xf2cc, 0x9641, 0x6bb0, 0x0000, 0x9450, 0x69bf, 0x0d34, 0x2710, 0x3af8, 0xcd7f, 0x8994,
0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0, 0x0000, 0x9450, 0x69bf, 0x0d34,
0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641,
};
s16 gEuUnknownWave7[256] = {
0x0000, 0x3fbc, 0x4eb4, 0x4f21, 0x6a49, 0x806f, 0x7250, 0x6a7b, 0x8d2e, 0xac0a, 0x98d6, 0x7832,
0x7551, 0x71ca, 0x4eee, 0x3731, 0x4e20, 0x644d, 0x4a50, 0x23ba, 0x1b09, 0x119a, 0xe914, 0xccbe,
0xe14e, 0xf8a3, 0xe47e, 0xc937, 0xd181, 0xde39, 0xcfc6, 0xcf94, 0x0000, 0x306c, 0x303a, 0x21c7,
0x2e7f, 0x36c8, 0x1b82, 0x075e, 0x1eb2, 0x3341, 0x16ec, 0xee67, 0xe4f7, 0xdc45, 0xb5b0, 0x9bb4,
0xb1e0, 0xc8ce, 0xb112, 0x8e37, 0x8aaf, 0x87cd, 0x672a, 0x53f7, 0x72d2, 0x9584, 0x8db0, 0x7f92,
0x95b7, 0xb0de, 0xb14c, 0xc045, 0x0000, 0x4eb4, 0x6a49, 0x7250, 0x8d2e, 0x98d6, 0x7551, 0x4eee,
0x4e20, 0x4a50, 0x1b09, 0xe914, 0xe14e, 0xe47e, 0xd181, 0xcfc6, 0x0000, 0x303a, 0x2e7f, 0x1b82,
0x1eb2, 0x16ec, 0xe4f7, 0xb5b0, 0xb1e0, 0xb112, 0x8aaf, 0x672a, 0x72d2, 0x8db0, 0x95b7, 0xb14c,
0x0000, 0x4eb4, 0x6a49, 0x7250, 0x8d2e, 0x98d6, 0x7551, 0x4eee, 0x4e20, 0x4a50, 0x1b09, 0xe914,
0xe14e, 0xe47e, 0xd181, 0xcfc6, 0x0000, 0x303a, 0x2e7f, 0x1b82, 0x1eb2, 0x16ec, 0xe4f7, 0xb5b0,
0xb1e0, 0xb112, 0x8aaf, 0x672a, 0x72d2, 0x8db0, 0x95b7, 0xb14c, 0x0000, 0x6a49, 0x8d2e, 0x7551,
0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7,
0x0000, 0x6a49, 0x8d2e, 0x7551, 0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7,
0xb1e0, 0x8aaf, 0x72d2, 0x95b7, 0x0000, 0x6a49, 0x8d2e, 0x7551, 0x4e20, 0x1b09, 0xe14e, 0xd181,
0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7, 0x0000, 0x6a49, 0x8d2e, 0x7551,
0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2,
};
s16 *gWaveSamples[6] = { sSawtoothWaves, sTriangleWaves, sSineWaves, sSquareWaves, sEuUnknownWave6, gEuUnknownWave7 };
#else
// !VERSION_EU
s16 sSineWave[0x40] = {
0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244,
28897, 30272, 31356, 32137, 32609, 0x7FFF, 32609, 32137, 31356, 30272, 28897,
27244, 25329, 23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211, 0,
-3211, -6392, -9511, -12539, -15446, -18204, -20787, -23169, -25329, -27244, -28897,
-30272, -31356, -32137, -32609, -0x7FFF, -32609, -32137, -31356, -30272, -28897, -27244,
-25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
};
s16 sSquareWave[0x40] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF,
-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF,
};
s16 sTriangleWave[0x40] = {
0, 0x7FF, 0xFFF, 0x17FF, 0x1FFF, 0x27FF, 0x2FFF, 0x37FF, 0x3FFF, 0x47FF, 0x4FFF,
0x57FF, 0x5FFF, 0x67FF, 0x6FFF, 0x77FF, 0x7FFF, 0x77FF, 0x6FFF, 0x67FF, 0x5FFF, 0x57FF,
0x4FFF, 0x47FF, 0x3FFF, 0x37FF, 0x2FFF, 0x27FF, 0x1FFF, 0x17FF, 0xFFF, 0x7FF, 0,
-0x7FF, -0xFFF, -0x17FF, -0x1FFF, -10239, -0x2FFF, -0x37FF, -0x3FFF, -0x47FF, -0x4FFF, -22527,
-24575, -26623, -28671, -30719, -0x7FFF, -30719, -28671, -26623, -24575, -22527, -0x4FFF,
-0x47FF, -0x3FFF, -0x37FF, -0x2FFF, -0x27FF, -0x1FFF, -0x17FF, -0xFFF, -0x7FF,
};
s16 sSawtoothWave[0x40] = {
0, 1023, 2047, 3071, 4095, 5119, 6143, 7167, 8191, 9215, 10239,
11263, 0x2FFF, 13311, 0x37FF, 15359, 0x3FFF, 17407, 0x47FF, 19455, 0x4FFF, 21503,
22527, 23551, 24575, 25599, 26623, 27647, 28671, 29695, 30719, 31743, -0x7FFF,
-31743, -30719, -29695, -28671, -27647, -26623, -25599, -24575, -23551, -22527, -21503,
-0x4FFF, -19455, -0x47FF, -17407, -0x3FFF, -15359, -0x37FF, -13311, -0x2FFF, -11263, -10239,
-9215, -8191, -7167, -6143, -5119, -4095, -3071, -2047, -1023,
};
s16 *gWaveSamples[4] = { sSawtoothWave, sTriangleWave, sSineWave, sSquareWave };
#endif
#ifdef VERSION_SH
s32 unk_sh_data_0[2] = {0, 0};
f32 gPitchBendFrequencyScale[256] = {
0.5f, 0.5f, 0.502736f, 0.505488f, 0.508254f, 0.511036f, 0.513833f, 0.516645f, 0.519472f,
0.522315f, 0.525174f, 0.528048f, 0.530938f, 0.533843f, 0.536765f, 0.539702f, 0.542656f, 0.545626f,
0.548612f, 0.551614f, 0.554633f, 0.557669f, 0.560721f, 0.563789f, 0.566875f, 0.569977f, 0.573097f,
0.576233f, 0.579387f, 0.582558f, 0.585746f, 0.588951f, 0.592175f, 0.595415f, 0.598674f, 0.601950f,
0.605245f, 0.608557f, 0.611888f, 0.615236f, 0.618603f, 0.621989f, 0.625393f, 0.628815f, 0.632257f,
0.635717f, 0.639196f, 0.642694f, 0.646212f, 0.649748f, 0.653304f, 0.656880f, 0.660475f, 0.664089f,
0.667724f, 0.671378f, 0.675052f, 0.678747f, 0.682461f, 0.686196f, 0.689952f, 0.693727f, 0.697524f,
0.701341f, 0.705180f, 0.709039f, 0.712919f, 0.716821f, 0.720744f, 0.724689f, 0.728655f, 0.732642f,
0.736652f, 0.740684f, 0.744737f, 0.748813f, 0.752911f, 0.757031f, 0.761175f, 0.765340f, 0.769529f,
0.773740f, 0.777975f, 0.782232f, 0.786513f, 0.790818f, 0.795146f, 0.799497f, 0.803873f, 0.808272f,
0.812696f, 0.817144f, 0.821616f, 0.826112f, 0.830633f, 0.835179f, 0.839750f, 0.844346f, 0.848966f,
0.853613f, 0.858284f, 0.862982f, 0.867704f, 0.872453f, 0.877228f, 0.882029f, 0.886856f, 0.891709f,
0.896590f, 0.901496f, 0.906430f, 0.911391f, 0.916379f, 0.921394f, 0.926436f, 0.931507f, 0.936604f,
0.941730f, 0.946884f, 0.952066f, 0.957277f, 0.962516f, 0.967783f, 0.973080f, 0.978405f, 0.983760f,
0.989144f, 0.994557f, 1.0f, 1.005473f, 1.010975f, 1.016508f, 1.022071f, 1.027665f, 1.033289f,
1.038944f, 1.044630f, 1.050347f, 1.056095f, 1.061875f, 1.067687f, 1.073530f, 1.079405f, 1.085312f,
1.091252f, 1.097224f, 1.103229f, 1.109267f, 1.115337f, 1.121441f, 1.127579f, 1.133750f, 1.139955f,
1.146193f, 1.152466f, 1.158773f, 1.165115f, 1.171491f, 1.177903f, 1.184349f, 1.190831f, 1.197348f,
1.203901f, 1.210489f, 1.217114f, 1.223775f, 1.230473f, 1.237207f, 1.243978f, 1.250786f, 1.257631f,
1.264514f, 1.271434f, 1.278392f, 1.285389f, 1.292423f, 1.299497f, 1.306608f, 1.313759f, 1.320949f,
1.328178f, 1.335447f, 1.342756f, 1.350104f, 1.357493f, 1.364922f, 1.372392f, 1.379903f, 1.387455f,
1.395048f, 1.402683f, 1.410360f, 1.418078f, 1.425839f, 1.433642f, 1.441488f, 1.449377f, 1.457309f,
1.465285f, 1.473304f, 1.481367f, 1.489474f, 1.497626f, 1.505822f, 1.514063f, 1.522349f, 1.530681f,
1.539058f, 1.547481f, 1.555950f, 1.564465f, 1.573027f, 1.581636f, 1.590292f, 1.598995f, 1.607746f,
1.616545f, 1.625392f, 1.634287f, 1.643231f, 1.652224f, 1.661266f, 1.670358f, 1.679500f, 1.688691f,
1.697933f, 1.707225f, 1.716569f, 1.725963f, 1.735409f, 1.744906f, 1.754456f, 1.764058f, 1.773712f,
1.783419f, 1.793179f, 1.802993f, 1.812860f, 1.822782f, 1.832757f, 1.842788f, 1.852873f, 1.863013f,
1.873209f, 1.883461f, 1.893768f, 1.904132f, 1.914553f, 1.925031f, 1.935567f, 1.946159f, 1.956810f,
1.967520f, 1.978287f, 1.989114f, 2.0f
};
#endif
#ifdef VERSION_SH
f32 unk_sh_data_1[] = {
0.890899f, 0.890899f, 0.89171f, 0.892521f, 0.893333f, 0.894146f, 0.89496f, 0.895774f,
0.89659f, 0.897406f, 0.898222f, 0.89904f, 0.899858f, 0.900677f, 0.901496f, 0.902317f,
0.903138f, 0.90396f, 0.904783f, 0.905606f, 0.90643f, 0.907255f, 0.908081f, 0.908907f,
0.909734f, 0.910562f, 0.911391f, 0.91222f, 0.91305f, 0.913881f, 0.914713f, 0.915545f,
0.916379f, 0.917213f, 0.918047f, 0.918883f, 0.919719f, 0.920556f, 0.921394f, 0.922232f,
0.923072f, 0.923912f, 0.924752f, 0.925594f, 0.926436f, 0.927279f, 0.928123f, 0.928968f,
0.929813f, 0.93066f, 0.931507f, 0.932354f, 0.933203f, 0.934052f, 0.934902f, 0.935753f,
0.936604f, 0.937457f, 0.93831f, 0.939164f, 0.940019f, 0.940874f, 0.94173f, 0.942587f,
0.943445f, 0.944304f, 0.945163f, 0.946023f, 0.946884f, 0.947746f, 0.948608f, 0.949472f,
0.950336f, 0.951201f, 0.952066f, 0.952933f, 0.9538f, 0.954668f, 0.955537f, 0.956406f,
0.957277f, 0.958148f, 0.95902f, 0.959893f, 0.960766f, 0.961641f, 0.962516f, 0.963392f,
0.964268f, 0.965146f, 0.966024f, 0.966903f, 0.967783f, 0.968664f, 0.969546f, 0.970428f,
0.971311f, 0.972195f, 0.97308f, 0.973965f, 0.974852f, 0.975739f, 0.976627f, 0.977516f,
0.978405f, 0.979296f, 0.980187f, 0.981079f, 0.981972f, 0.982865f, 0.98376f, 0.984655f,
0.985551f, 0.986448f, 0.987346f, 0.988244f, 0.989144f, 0.990044f, 0.990945f, 0.991847f,
0.992749f, 0.993653f, 0.994557f, 0.995462f, 0.996368f, 0.997275f, 0.998182f, 0.999091f,
1.0f, 1.00091f, 1.001821f, 1.002733f, 1.003645f, 1.004559f, 1.005473f, 1.006388f,
1.007304f, 1.00822f, 1.009138f, 1.010056f, 1.010975f, 1.011896f, 1.012816f, 1.013738f,
1.014661f, 1.015584f, 1.016508f, 1.017433f, 1.018359f, 1.019286f, 1.020214f, 1.021142f,
1.022071f, 1.023002f, 1.023933f, 1.024864f, 1.025797f, 1.026731f, 1.027665f, 1.0286f,
1.029536f, 1.030473f, 1.031411f, 1.03235f, 1.033289f, 1.03423f, 1.035171f, 1.036113f,
1.037056f, 1.038f, 1.038944f, 1.03989f, 1.040836f, 1.041783f, 1.042731f, 1.04368f,
1.04463f, 1.045581f, 1.046532f, 1.047485f, 1.048438f, 1.049392f, 1.050347f, 1.051303f,
1.05226f, 1.053217f, 1.054176f, 1.055135f, 1.056095f, 1.057056f, 1.058018f, 1.058981f,
1.059945f, 1.06091f, 1.061875f, 1.062842f, 1.063809f, 1.064777f, 1.065746f, 1.066716f,
1.067687f, 1.068658f, 1.069631f, 1.070604f, 1.071578f, 1.072554f, 1.07353f, 1.074507f,
1.075485f, 1.076463f, 1.077443f, 1.078424f, 1.079405f, 1.080387f, 1.08137f, 1.082355f,
1.08334f, 1.084325f, 1.085312f, 1.0863f, 1.087289f, 1.088278f, 1.089268f, 1.09026f,
1.091252f, 1.092245f, 1.093239f, 1.094234f, 1.09523f, 1.096226f, 1.097224f, 1.098223f,
1.099222f, 1.100222f, 1.101224f, 1.102226f, 1.103229f, 1.104233f, 1.105238f, 1.106244f,
1.10725f, 1.108258f, 1.109267f, 1.110276f, 1.111287f, 1.112298f, 1.11331f, 1.114323f,
1.115337f, 1.116352f, 1.117368f, 1.118385f, 1.119403f, 1.120422f, 1.121441f, 1.122462f,
};
// Shindou moved these variables down here. :/
// clang-format off
f32 gNoteFrequencies[128] = {
0.105112f, 0.111362f, 0.117984f, 0.125f, 0.132433f, 0.140308f, 0.148651f, 0.15749f, 0.166855f, 0.176777f, 0.187288f, 0.198425f,
0.210224f, 0.222725f, 0.235969f, 0.25f, 0.264866f, 0.280616f, 0.297302f, 0.31498f, 0.33371f, 0.353553f, 0.374577f, 0.39685f,
0.420448f, 0.445449f, 0.471937f, 0.5f, 0.529732f, 0.561231f, 0.594604f, 0.629961f, 0.66742f, 0.707107f, 0.749154f, 0.793701f,
0.840897f, 0.890899f, 0.943875f, 1.0f, 1.059463f, 1.122462f, 1.189207f, 1.259921f, 1.33484f, 1.414214f, 1.498307f, 1.587401f,
1.681793f, 1.781798f, 1.887749f, 2.0f, 2.118926f, 2.244924f, 2.378414f, 2.519842f, 2.66968f, 2.828428f, 2.996615f, 3.174803f,
3.363586f, 3.563596f, 3.775498f, 4.0f, 4.237853f, 4.489849f, 4.756829f, 5.039685f, 5.33936f, 5.656855f, 5.993229f, 6.349606f,
6.727173f, 7.127192f, 7.550996f, 8.0f, 8.475705f, 8.979697f, 9.513658f, 10.07937f, 10.67872f, 11.31371f, 11.986459f, 12.699211f,
13.454346f, 14.254383f, 15.101993f, 16.0f, 16.95141f, 17.959394f, 19.027315f, 20.15874f, 21.35744f, 22.62742f, 23.972918f, 25.398422f,
26.908691f, 28.508766f, 30.203985f, 32.0f, 33.90282f, 35.91879f, 38.05463f, 40.31748f, 42.71488f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f, 85.42976f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f
};
// clang-format on
u8 gDefaultShortNoteVelocityTable[16] = {
12, 25, 38, 51, 57, 64, 71, 76, 83, 89, 96, 102, 109, 115, 121, 127,
};
u8 gDefaultShortNoteDurationTable[16] = {
229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0,
};
struct AdsrEnvelope gDefaultEnvelope[] = {
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
};
u8 unk_sh_data2[4] = { 0, 0, 0, 0 };
struct NoteSubEu gZeroNoteSub = { 0 };
struct NoteSubEu gDefaultNoteSub = {
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { NULL },
#ifdef VERSION_SH
0
#endif
};
u16 gHeadsetPanQuantization[0x40] = {
0x3C, 0x3A, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2E,
0x2C, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E,
0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E,
0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#endif
#ifdef VERSION_EU
u8 euUnknownData_8030194c[4] = { 0x40, 0x20, 0x10, 0x08 };
u16 gHeadsetPanQuantization[0x10] = {
0x40, 0x40, 0x30, 0x30, 0x20, 0x20, 0x10, 0, 0, 0,
};
#elif !defined(VERSION_SH)
u16 gHeadsetPanQuantization[10] = { 0x40, 0x30, 0x20, 0x10, 0, 0, 0, 0, 0, 0 };
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 euUnknownData_80301950[64] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 500, 0, 0, 0, 0, 0, 0, 0, 500, 0, 0, 0, 0, 0, 0, 0, 500, 0, 0, 0, 0, 0, 0, 0, 500, 0, 0, 0, 0,
};
#endif
// Linearly interpolated between
// f(0/2 * 127) = 1
// f(1/2 * 127) = 1/sqrt(2)
// f(2/2 * 127) = 0
f32 gHeadsetPanVolume[128] = {
1.0f, 0.995386f, 0.990772f, 0.986157f, 0.981543f, 0.976929f, 0.972315f, 0.967701f, 0.963087f,
0.958472f, 0.953858f, 0.949244f, 0.94463f, 0.940016f, 0.935402f, 0.930787f, 0.926173f, 0.921559f,
0.916945f, 0.912331f, 0.907717f, 0.903102f, 0.898488f, 0.893874f, 0.88926f, 0.884646f, 0.880031f,
0.875417f, 0.870803f, 0.866189f, 0.861575f, 0.856961f, 0.852346f, 0.847732f, 0.843118f, 0.838504f,
0.83389f, 0.829276f, 0.824661f, 0.820047f, 0.815433f, 0.810819f, 0.806205f, 0.801591f, 0.796976f,
0.792362f, 0.787748f, 0.783134f, 0.77852f, 0.773906f, 0.769291f, 0.764677f, 0.760063f, 0.755449f,
0.750835f, 0.74622f, 0.741606f, 0.736992f, 0.732378f, 0.727764f, 0.72315f, 0.718535f, 0.713921f,
0.709307f, 0.70537f, 0.70211f, 0.69885f, 0.695591f, 0.692331f, 0.689071f, 0.685811f, 0.682551f,
0.679291f, 0.676031f, 0.672772f, 0.669512f, 0.666252f, 0.662992f, 0.659732f, 0.656472f, 0.653213f,
0.649953f, 0.646693f, 0.643433f, 0.640173f, 0.636913f, 0.633654f, 0.630394f, 0.627134f, 0.623874f,
0.620614f, 0.617354f, 0.614094f, 0.610835f, 0.607575f, 0.604315f, 0.601055f, 0.597795f, 0.594535f,
0.591276f, 0.588016f, 0.584756f, 0.581496f, 0.578236f, 0.574976f, 0.571717f, 0.568457f, 0.565197f,
0.561937f, 0.558677f, 0.555417f, 0.552157f, 0.548898f, 0.545638f, 0.542378f, 0.539118f, 0.535858f,
0.532598f, 0.529339f, 0.526079f, 0.522819f, 0.519559f, 0.516299f, 0.513039f, 0.50978f, 0.50652f,
0.50326f, 0.5f
};
// Linearly interpolated between
// f(0/4 * 127) = 1/sqrt(2)
// f(1/4 * 127) = 1
// f(2/4 * 127) = 1/sqrt(2)
// f(3/4 * 127) = 0
// f(4/4 * 127) = 1/sqrt(8)
f32 gStereoPanVolume[128] = {
0.707f, 0.716228f, 0.725457f, 0.734685f, 0.743913f, 0.753142f, 0.76237f, 0.771598f, 0.780827f,
0.790055f, 0.799283f, 0.808512f, 0.81774f, 0.826968f, 0.836197f, 0.845425f, 0.854654f, 0.863882f,
0.87311f, 0.882339f, 0.891567f, 0.900795f, 0.910024f, 0.919252f, 0.92848f, 0.937709f, 0.946937f,
0.956165f, 0.965394f, 0.974622f, 0.98385f, 0.993079f, 0.997693f, 0.988465f, 0.979236f, 0.970008f,
0.960779f, 0.951551f, 0.942323f, 0.933095f, 0.923866f, 0.914638f, 0.905409f, 0.896181f, 0.886953f,
0.877724f, 0.868496f, 0.859268f, 0.850039f, 0.840811f, 0.831583f, 0.822354f, 0.813126f, 0.803898f,
0.794669f, 0.785441f, 0.776213f, 0.766984f, 0.757756f, 0.748528f, 0.739299f, 0.730071f, 0.720843f,
0.711614f, 0.695866f, 0.673598f, 0.651331f, 0.629063f, 0.606795f, 0.584528f, 0.56226f, 0.539992f,
0.517724f, 0.495457f, 0.473189f, 0.450921f, 0.428654f, 0.406386f, 0.384118f, 0.36185f, 0.339583f,
0.317315f, 0.295047f, 0.27278f, 0.250512f, 0.228244f, 0.205976f, 0.183709f, 0.161441f, 0.139173f,
0.116905f, 0.094638f, 0.07237f, 0.050102f, 0.027835f, 0.005567f, 0.00835f, 0.019484f, 0.030618f,
0.041752f, 0.052886f, 0.06402f, 0.075154f, 0.086287f, 0.097421f, 0.108555f, 0.119689f, 0.130823f,
0.141957f, 0.153091f, 0.164224f, 0.175358f, 0.186492f, 0.197626f, 0.20876f, 0.219894f, 0.231028f,
0.242161f, 0.253295f, 0.264429f, 0.275563f, 0.286697f, 0.297831f, 0.308965f, 0.320098f, 0.331232f,
0.342366f, 0.3535f
};
// gDefaultVolume[k] = cos(pi/2 * k / 127)
f32 gDefaultPanVolume[128] = {
1.0f, 0.999924f, 0.999694f, 0.999312f, 0.998776f, 0.998088f, 0.997248f, 0.996254f, 0.995109f,
0.993811f, 0.992361f, 0.990759f, 0.989006f, 0.987101f, 0.985045f, 0.982839f, 0.980482f, 0.977976f,
0.97532f, 0.972514f, 0.96956f, 0.966457f, 0.963207f, 0.959809f, 0.956265f, 0.952574f, 0.948737f,
0.944755f, 0.940629f, 0.936359f, 0.931946f, 0.92739f, 0.922692f, 0.917853f, 0.912873f, 0.907754f,
0.902497f, 0.897101f, 0.891567f, 0.885898f, 0.880093f, 0.874153f, 0.868079f, 0.861873f, 0.855535f,
0.849066f, 0.842467f, 0.835739f, 0.828884f, 0.821901f, 0.814793f, 0.807561f, 0.800204f, 0.792725f,
0.785125f, 0.777405f, 0.769566f, 0.76161f, 0.753536f, 0.745348f, 0.737045f, 0.72863f, 0.720103f,
0.711466f, 0.70272f, 0.693867f, 0.684908f, 0.675843f, 0.666676f, 0.657406f, 0.648036f, 0.638567f,
0.629f, 0.619337f, 0.609579f, 0.599728f, 0.589785f, 0.579752f, 0.56963f, 0.559421f, 0.549126f,
0.538748f, 0.528287f, 0.517745f, 0.507124f, 0.496425f, 0.485651f, 0.474802f, 0.46388f, 0.452888f,
0.441826f, 0.430697f, 0.419502f, 0.408243f, 0.396921f, 0.385538f, 0.374097f, 0.362598f, 0.351044f,
0.339436f, 0.327776f, 0.316066f, 0.304308f, 0.292503f, 0.280653f, 0.268761f, 0.256827f, 0.244854f,
0.232844f, 0.220798f, 0.208718f, 0.196606f, 0.184465f, 0.172295f, 0.160098f, 0.147877f, 0.135634f,
0.12337f, 0.111087f, 0.098786f, 0.086471f, 0.074143f, 0.061803f, 0.049454f, 0.037097f, 0.024734f,
0.012368f, 0.0f
};
#if defined(VERSION_JP) || defined(VERSION_US)
// gVolRampingLhs136[k] = 2^16 * max(1, (256*k)^(1/17)
f32 gVolRampingLhs136[128] = {
65536.0f, 90811.555f, 94590.766f, 96873.96f, 98527.26f, 99829.06f, 100905.47f,
101824.61f, 102627.57f, 103341.086f, 103983.55f, 104568.164f, 105104.75f, 105600.8f,
106062.14f, 106493.46f, 106898.52f, 107280.414f, 107641.73f, 107984.62f, 108310.93f,
108622.23f, 108919.875f, 109205.055f, 109478.8f, 109742.0f, 109995.48f, 110239.94f,
110476.02f, 110704.305f, 110925.3f, 111139.45f, 111347.21f, 111548.945f, 111745.0f,
111935.7f, 112121.35f, 112302.2f, 112478.51f, 112650.51f, 112818.4f, 112982.38f,
113142.66f, 113299.37f, 113452.69f, 113602.766f, 113749.734f, 113893.73f, 114034.87f,
114173.26f, 114309.02f, 114442.26f, 114573.055f, 114701.5f, 114827.69f, 114951.695f,
115073.6f, 115193.47f, 115311.375f, 115427.39f, 115541.56f, 115653.96f, 115764.63f,
115873.64f, 115981.04f, 116086.86f, 116191.164f, 116293.99f, 116395.38f, 116495.38f,
116594.02f, 116691.34f, 116787.39f, 116882.19f, 116975.77f, 117068.17f, 117159.414f,
117249.54f, 117338.57f, 117426.53f, 117513.45f, 117599.35f, 117684.266f, 117768.2f,
117851.195f, 117933.266f, 118014.44f, 118094.72f, 118174.14f, 118252.71f, 118330.46f,
118407.4f, 118483.55f, 118558.914f, 118633.53f, 118707.4f, 118780.54f, 118852.97f,
118924.695f, 118995.74f, 119066.11f, 119135.82f, 119204.88f, 119273.31f, 119341.125f,
119408.32f, 119474.92f, 119540.93f, 119606.36f, 119671.22f, 119735.52f, 119799.28f,
119862.5f, 119925.195f, 119987.36f, 120049.02f, 120110.18f, 120170.84f, 120231.016f,
120290.71f, 120349.945f, 120408.7f, 120467.016f, 120524.875f, 120582.3f, 120639.28f,
120695.84f, 120751.984f
};
// gVolRampingRhs136[k] = 1 / max(1, (256*k)^(1/17))
f32 gVolRampingRhs136[128] = {
1.0f, 0.72167f, 0.692837f, 0.676508f, 0.665156f, 0.656482f, 0.649479f, 0.643616f, 0.638581f,
0.634172f, 0.630254f, 0.62673f, 0.62353f, 0.620601f, 0.617902f, 0.615399f, 0.613067f, 0.610885f,
0.608835f, 0.606901f, 0.605073f, 0.603339f, 0.60169f, 0.600119f, 0.598618f, 0.597183f, 0.595806f,
0.594485f, 0.593215f, 0.591991f, 0.590812f, 0.589674f, 0.588573f, 0.587509f, 0.586478f, 0.585479f,
0.58451f, 0.583568f, 0.582654f, 0.581764f, 0.580898f, 0.580055f, 0.579233f, 0.578432f, 0.57765f,
0.576887f, 0.576142f, 0.575414f, 0.574701f, 0.574005f, 0.573323f, 0.572656f, 0.572002f, 0.571361f,
0.570733f, 0.570118f, 0.569514f, 0.568921f, 0.568339f, 0.567768f, 0.567207f, 0.566656f, 0.566114f,
0.565582f, 0.565058f, 0.564543f, 0.564036f, 0.563537f, 0.563046f, 0.562563f, 0.562087f, 0.561618f,
0.561156f, 0.560701f, 0.560253f, 0.559811f, 0.559375f, 0.558945f, 0.558521f, 0.558102f, 0.557689f,
0.557282f, 0.55688f, 0.556483f, 0.556091f, 0.555704f, 0.555322f, 0.554944f, 0.554571f, 0.554203f,
0.553839f, 0.553479f, 0.553123f, 0.552772f, 0.552424f, 0.55208f, 0.55174f, 0.551404f, 0.551071f,
0.550742f, 0.550417f, 0.550095f, 0.549776f, 0.549461f, 0.549148f, 0.548839f, 0.548534f, 0.548231f,
0.547931f, 0.547634f, 0.54734f, 0.547048f, 0.54676f, 0.546474f, 0.546191f, 0.54591f, 0.545632f,
0.545357f, 0.545084f, 0.544813f, 0.544545f, 0.54428f, 0.544016f, 0.543755f, 0.543496f, 0.543239f,
0.542985f, 0.542732f
};
// gVolRampingLhs144[k] = 2^16 * max(1, (256*k)^(1/18))
f32 gVolRampingLhs144[128] = {
65536.0f, 89180.734f, 92681.9f, 94793.33f, 96320.52f, 97522.02f, 98514.84f,
99362.14f, 100101.99f, 100759.16f, 101350.664f, 101888.74f, 102382.46f, 102838.75f,
103263.016f, 103659.58f, 104031.914f, 104382.89f, 104714.88f, 105029.89f, 105329.61f,
105615.5f, 105888.81f, 106150.63f, 106401.914f, 106643.49f, 106876.12f, 107100.44f,
107317.05f, 107526.47f, 107729.17f, 107925.6f, 108116.125f, 108301.12f, 108480.88f,
108655.72f, 108825.91f, 108991.68f, 109153.28f, 109310.914f, 109464.77f, 109615.04f,
109761.88f, 109905.46f, 110045.92f, 110183.41f, 110318.02f, 110449.91f, 110579.17f,
110705.914f, 110830.234f, 110952.234f, 111071.99f, 111189.59f, 111305.12f, 111418.64f,
111530.23f, 111639.95f, 111747.875f, 111854.05f, 111958.54f, 112061.4f, 112162.67f,
112262.42f, 112360.68f, 112457.51f, 112552.93f, 112647.0f, 112739.76f, 112831.23f,
112921.46f, 113010.484f, 113098.33f, 113185.02f, 113270.61f, 113355.11f, 113438.555f,
113520.97f, 113602.375f, 113682.805f, 113762.27f, 113840.81f, 113918.44f, 113995.18f,
114071.055f, 114146.08f, 114220.266f, 114293.65f, 114366.24f, 114438.06f, 114509.12f,
114579.44f, 114649.02f, 114717.91f, 114786.086f, 114853.586f, 114920.42f, 114986.6f,
115052.14f, 115117.055f, 115181.34f, 115245.04f, 115308.13f, 115370.65f, 115432.59f,
115493.98f, 115554.81f, 115615.11f, 115674.875f, 115734.12f, 115792.85f, 115851.08f,
115908.82f, 115966.07f, 116022.85f, 116079.16f, 116135.01f, 116190.4f, 116245.35f,
116299.87f, 116353.945f, 116407.6f, 116460.84f, 116513.67f, 116566.09f, 116618.125f,
116669.76f, 116721.01f
};
// gVolRampingRhs144[k] = 1 / max(1, (256*k)^(1/18))
f32 gVolRampingRhs144[128] = {
1.0f, 0.734867f, 0.707107f, 0.691357f, 0.680395f, 0.672012f, 0.66524f, 0.659567f, 0.654692f,
0.650422f, 0.646626f, 0.643211f, 0.64011f, 0.637269f, 0.634651f, 0.632223f, 0.629961f, 0.627842f,
0.625852f, 0.623975f, 0.622199f, 0.620515f, 0.618913f, 0.617387f, 0.615929f, 0.614533f, 0.613196f,
0.611912f, 0.610677f, 0.609487f, 0.60834f, 0.607233f, 0.606163f, 0.605128f, 0.604125f, 0.603153f,
0.60221f, 0.601294f, 0.600403f, 0.599538f, 0.598695f, 0.597874f, 0.597074f, 0.596294f, 0.595533f,
0.59479f, 0.594064f, 0.593355f, 0.592661f, 0.591983f, 0.591319f, 0.590669f, 0.590032f, 0.589408f,
0.588796f, 0.588196f, 0.587608f, 0.58703f, 0.586463f, 0.585906f, 0.58536f, 0.584822f, 0.584294f,
0.583775f, 0.583265f, 0.582762f, 0.582268f, 0.581782f, 0.581303f, 0.580832f, 0.580368f, 0.579911f,
0.57946f, 0.579017f, 0.578579f, 0.578148f, 0.577722f, 0.577303f, 0.576889f, 0.576481f, 0.576078f,
0.575681f, 0.575289f, 0.574902f, 0.574519f, 0.574142f, 0.573769f, 0.5734f, 0.573036f, 0.572677f,
0.572321f, 0.57197f, 0.571623f, 0.57128f, 0.57094f, 0.570605f, 0.570273f, 0.569945f, 0.56962f,
0.569299f, 0.568981f, 0.568667f, 0.568355f, 0.568047f, 0.567743f, 0.567441f, 0.567142f, 0.566846f,
0.566553f, 0.566263f, 0.565976f, 0.565692f, 0.56541f, 0.565131f, 0.564854f, 0.56458f, 0.564309f,
0.56404f, 0.563773f, 0.563509f, 0.563247f, 0.562987f, 0.56273f, 0.562475f, 0.562222f, 0.561971f,
0.561722f, 0.561476f
};
// gVolRampingLhs128[k] = 2^16 * max(1, (256*k)^(1/16))
f32 gVolRampingLhs128[128] = {
65536.0f, 92681.9f, 96785.28f, 99269.31f, 101070.33f, 102489.78f, 103664.336f,
104667.914f, 105545.09f, 106324.92f, 107027.39f, 107666.84f, 108253.95f, 108796.87f,
109301.95f, 109774.29f, 110217.98f, 110636.39f, 111032.33f, 111408.164f, 111765.9f,
112107.234f, 112433.66f, 112746.46f, 113046.766f, 113335.555f, 113613.72f, 113882.02f,
114141.164f, 114391.77f, 114634.414f, 114869.58f, 115097.74f, 115319.31f, 115534.68f,
115744.19f, 115948.16f, 116146.875f, 116340.625f, 116529.66f, 116714.195f, 116894.46f,
117070.64f, 117242.945f, 117411.52f, 117576.55f, 117738.17f, 117896.54f, 118051.77f,
118204.0f, 118353.35f, 118499.92f, 118643.83f, 118785.16f, 118924.01f, 119060.47f,
119194.625f, 119326.555f, 119456.336f, 119584.03f, 119709.71f, 119833.445f, 119955.29f,
120075.31f, 120193.555f, 120310.08f, 120424.94f, 120538.17f, 120649.836f, 120759.97f,
120868.62f, 120975.82f, 121081.62f, 121186.05f, 121289.14f, 121390.94f, 121491.47f,
121590.766f, 121688.87f, 121785.79f, 121881.57f, 121976.24f, 122069.82f, 122162.33f,
122253.805f, 122344.266f, 122433.73f, 122522.23f, 122609.77f, 122696.4f, 122782.11f,
122866.93f, 122950.89f, 123033.99f, 123116.26f, 123197.72f, 123278.37f, 123358.24f,
123437.34f, 123515.69f, 123593.3f, 123670.19f, 123746.36f, 123821.84f, 123896.63f,
123970.76f, 124044.23f, 124117.04f, 124189.23f, 124260.78f, 124331.73f, 124402.07f,
124471.83f, 124540.99f, 124609.59f, 124677.63f, 124745.12f, 124812.055f, 124878.47f,
124944.34f, 125009.71f, 125074.57f, 125138.92f, 125202.79f, 125266.164f, 125329.06f,
125391.5f, 125453.47f
};
// gVolRampingRhs128[k] = 1 / max(1, (256*k)^(1/16))
f32 gVolRampingRhs128[128] = {
1.0f, 0.707107f, 0.677128f, 0.660184f, 0.64842f, 0.639439f, 0.632194f, 0.626133f, 0.620929f,
0.616375f, 0.612329f, 0.608693f, 0.605391f, 0.60237f, 0.599587f, 0.597007f, 0.594604f, 0.592355f,
0.590243f, 0.588251f, 0.586369f, 0.584583f, 0.582886f, 0.581269f, 0.579725f, 0.578247f, 0.576832f,
0.575473f, 0.574166f, 0.572908f, 0.571696f, 0.570525f, 0.569394f, 0.5683f, 0.567241f, 0.566214f,
0.565218f, 0.564251f, 0.563311f, 0.562398f, 0.561508f, 0.560642f, 0.559799f, 0.558976f, 0.558173f,
0.55739f, 0.556625f, 0.555877f, 0.555146f, 0.554431f, 0.553732f, 0.553047f, 0.552376f, 0.551719f,
0.551075f, 0.550443f, 0.549823f, 0.549216f, 0.548619f, 0.548033f, 0.547458f, 0.546892f, 0.546337f,
0.545791f, 0.545254f, 0.544726f, 0.544206f, 0.543695f, 0.543192f, 0.542696f, 0.542209f, 0.541728f,
0.541255f, 0.540788f, 0.540329f, 0.539876f, 0.539429f, 0.538988f, 0.538554f, 0.538125f, 0.537702f,
0.537285f, 0.536873f, 0.536467f, 0.536065f, 0.535669f, 0.535277f, 0.534891f, 0.534509f, 0.534131f,
0.533759f, 0.53339f, 0.533026f, 0.532666f, 0.53231f, 0.531958f, 0.53161f, 0.531266f, 0.530925f,
0.530588f, 0.530255f, 0.529926f, 0.529599f, 0.529277f, 0.528957f, 0.528641f, 0.528328f, 0.528018f,
0.527711f, 0.527407f, 0.527106f, 0.526808f, 0.526513f, 0.52622f, 0.525931f, 0.525644f, 0.525359f,
0.525077f, 0.524798f, 0.524522f, 0.524247f, 0.523975f, 0.523706f, 0.523439f, 0.523174f, 0.522911f,
0.522651f, 0.522393f
};
#endif
#ifdef VERSION_SH
u16 unk_sh_data_3[] = {
// 30 entries
// pattern:
// A B
// C D
// C B
// A E
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x0E6F, 0x1091,
0x11EF, 0x1267,
0x11EF, 0x1091,
0x0E6F, 0x0BB8,
0x0C1D, 0x111D,
0x1494, 0x15D2,
0x1494, 0x111D,
0x0C1D, 0x068E,
0x0838, 0x116E,
0x18A6, 0x1B61,
0x18A6, 0x116E,
0x0838, 0x0001,
0x0227, 0x0F42,
0x1B75, 0x206B,
0x1B75, 0x0F42,
0x0227, 0xFA2B,
0xFC28, 0x0AAE,
0x1BE7, 0x2394,
0x1BE7, 0x0AAE,
0xFC28, 0xF874,
0xF809, 0x0582,
0x1C36, 0x2788,
0x1C36, 0x0582,
0xF809, 0xFAEB,
0xF5F0, 0x0001,
0x1E34, 0x2F71,
0x1E34, 0x0001,
0xF5F0, 0x0000,
0xF8AD, 0xFAF3,
0x19ED, 0x2EB6,
0x19ED, 0xFAF3,
0xF8AD, 0x04AC,
0xFCC0, 0xF6FF,
0x178B, 0x3207,
0x178B, 0xF6FF,
0xFCC0, 0x065F,
0x01A5, 0xF44E,
0x1510, 0x36B4,
0x1510, 0xF44E,
0x01A5, 0x047B,
0x05C1, 0xF3CC,
0x1145, 0x3988,
0x1145, 0xF3CC,
0x05C1, 0x0001,
0x07B9, 0xF517,
0x0D20, 0x3C4C,
0x0D20, 0xF517,
0x07B9, 0xFBD4,
0x07C0, 0xF71C,
0x09A1, 0x4528,
0x09A1, 0xF71C,
0x07C0, 0xF9B7,
0x058F, 0xFA43,
0x05DC, 0x585F,
0x05DC, 0xFA43,
0x058F, 0xFAB3,
};
u16 unk_sh_data_4[] = {
0xFA73, 0xFA42,
0xFA27, 0x5866,
0xFA27, 0xFA42,
0xFA73, 0xFAB2,
0xF842, 0xF71B,
0xF661, 0x452B,
0xF661, 0xF71B,
0xF842, 0xF9B5,
0xF848, 0xF516,
0xF2E1, 0x3C4D,
0xF2E1, 0xF516,
0xF848, 0xFBD2,
0xFA3F, 0xF3CA,
0xEEBD, 0x3989,
0xEEBD, 0xF3CA,
0xFA3F, 0xFFFF,
0xFE5B, 0xF44C,
0xEAF2, 0x36B5,
0xEAF2, 0xF44C,
0xFE5B, 0x0479,
0x0340, 0xF6FD,
0xE877, 0x3207,
0xE877, 0xF6FD,
0x0340, 0x065E,
0x0753, 0xFAF1,
0xE615, 0x2EB5,
0xE615, 0xFAF1,
0x0753, 0x04AB,
0x0A12, 0xFFFF,
0xE1CD, 0x2F71,
0xE1CD, 0xFFFF,
0x0A12, 0x0000,
0x07FA, 0x057F,
0xE3CA, 0x2789,
0xE3CA, 0x057F,
0x07FA, 0xFAEA,
0x03DB, 0x0AAC,
0xE41A, 0x2394,
0xE41A, 0x0AAC,
0x03DB, 0xF873,
0xFDDC, 0x0F41,
0xE489, 0x206E,
0xE489, 0x0F41,
0xFDDC, 0xFA28,
0xF7CA, 0x116E,
0xE758, 0x1B63,
0xE758, 0x116E,
0xF7CA, 0xFFFF,
0xF3E4, 0x111D,
0xEB6A, 0x15D4,
0xEB6A, 0x111D,
0xF3E4, 0x068B,
0xF192, 0x1092,
0xEE11, 0x1268,
0xEE11, 0x1092,
0xF192, 0x0BB6,
0xF05F, 0x1026,
0xEF89, 0x1093,
0xEF89, 0x1026,
0xF05F, 0x0EEB,
0x0000, 0x0000,
0x0000, 0x0000,
0x7FFF, 0xD001,
0x3FFF, 0xF001,
0x5FFF, 0x9001,
0x7FFF, 0x8001
};
#endif
#ifndef VERSION_SH
s16 gTatumsPerBeat = TATUMS_PER_BEAT;
s8 gUnusedCount80333EE8 = UNUSED_COUNT_80333EE8;
s32 gAudioHeapSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_HEAP_SIZE);
s32 gAudioInitPoolSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_INIT_POOL_SIZE);
volatile s32 gAudioLoadLock = AUDIO_LOCK_UNINITIALIZED;
#endif
#if defined(VERSION_EU)
u8 bufferDelete2[12] = { 0 };
u8 D_EU_80302010 = 0;
u8 D_EU_80302014 = 0;
struct OSMesgQueue *OSMesgQueues[4] = { &OSMesgQueue0, &OSMesgQueue1, &OSMesgQueue2, &OSMesgQueue3 };
#elif defined(VERSION_JP) || defined(VERSION_US)
s8 sUnused8033EF8 = 24;
#endif
// .bss
volatile s32 gAudioFrameCount;
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 gCurrAudioFrameDmaCount;
#else
volatile s32 gCurrAudioFrameDmaCount;
#endif
s32 gAudioTaskIndex;
s32 gCurrAiBufferIndex;
u64 *gAudioCmdBuffers[2];
u64 *gAudioCmd;
struct SPTask *gAudioTask;
struct SPTask gAudioTasks[2];
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 D_EU_802298D0;
s32 gRefreshRate;
#endif
s16 *gAiBuffers[NUMAIBUFFERS];
s16 gAiBufferLengths[NUMAIBUFFERS];
#if defined(VERSION_JP) || defined(VERSION_US)
u32 gUnused80226E58[0x10];
u16 gUnused80226E98[0x10];
#endif
u32 gAudioRandom;
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 gAudioErrorFlags;
#endif
#ifdef VERSION_SH
volatile u32 gAudioLoadLockSH;
struct EuAudioCmd sAudioCmd[0x100];
u8 D_SH_80350F18;
u8 D_SH_80350F19;
OSMesg D_SH_80350F1C[1];
OSMesgQueue D_SH_80350F20; // address written to D_SH_80350F38
OSMesgQueue *D_SH_80350F38;
OSMesg D_SH_80350F40[4];
OSMesgQueue D_SH_80350F50; // address written to D_SH_80350F68
OSMesgQueue *D_SH_80350F68;
OSMesg D_SH_80350F6C[1];
OSMesgQueue D_SH_80350F70; // address written to D_SH_80350F88
OSMesgQueue *D_SH_80350F88;
OSMesg D_SH_80350F8C[1];
OSMesgQueue D_SH_80350F90; // address written to D_SH_80350F90
OSMesgQueue *D_SH_80350FA8;
#endif
u64 gAudioGlobalsEndMarker;
+154
View File
@@ -0,0 +1,154 @@
#ifndef AUDIO_DATA_H
#define AUDIO_DATA_H
#include <PR/ultratypes.h>
#include "internal.h"
#include <types.h>
#define AUDIO_LOCK_UNINITIALIZED 0
#define AUDIO_LOCK_NOT_LOADING 0x76557364
#define AUDIO_LOCK_LOADING 0x19710515
#define NUMAIBUFFERS 3
// constant .data
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct AudioSessionSettingsEU gAudioSessionPresets[];
#else
extern struct AudioSessionSettings gAudioSessionPresets[18];
#endif
extern u16 D_80332388[128]; // unused
#if defined(VERSION_EU) || defined(VERSION_SH)
extern f32 gPitchBendFrequencyScale[256];
#else
extern f32 gPitchBendFrequencyScale[255];
#endif
extern f32 gNoteFrequencies[128];
extern u8 gDefaultShortNoteVelocityTable[16];
extern u8 gDefaultShortNoteDurationTable[16];
extern s8 gVibratoCurve[16];
extern struct AdsrEnvelope gDefaultEnvelope[3];
#if defined(VERSION_EU) || defined(VERSION_SH)
extern s16 gEuUnknownWave7[256];
extern s16 *gWaveSamples[6];
#else
extern s16 *gWaveSamples[4];
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
extern u8 euUnknownData_8030194c[4];
#ifdef VERSION_EU
extern u16 gHeadsetPanQuantization[0x10];
#else
extern u16 gHeadsetPanQuantization[0x40];
#endif
extern s16 euUnknownData_80301950[64];
extern struct NoteSubEu gZeroNoteSub;
extern struct NoteSubEu gDefaultNoteSub;
#else
extern u16 gHeadsetPanQuantization[10];
#endif
extern f32 gHeadsetPanVolume[128];
extern f32 gStereoPanVolume[128];
extern f32 gDefaultPanVolume[128];
extern f32 gVolRampingLhs136[128];
extern f32 gVolRampingRhs136[128];
extern f32 gVolRampingLhs144[128];
extern f32 gVolRampingRhs144[128];
extern f32 gVolRampingLhs128[128];
extern f32 gVolRampingRhs128[128];
// non-constant .data
extern s16 gTatumsPerBeat;
extern s8 gUnusedCount80333EE8;
extern s32 gAudioHeapSize; // AUDIO_HEAP_SIZE
extern s32 gAudioInitPoolSize; // AUDIO_INIT_POOL_SIZE
extern volatile s32 gAudioLoadLock;
// .bss
extern volatile s32 gAudioFrameCount;
// number of DMAs performed during this frame
#if defined(VERSION_EU) || defined(VERSION_SH)
extern s32 gCurrAudioFrameDmaCount;
#else
extern volatile s32 gCurrAudioFrameDmaCount;
#endif
extern s32 gAudioTaskIndex;
extern s32 gCurrAiBufferIndex;
extern u64 *gAudioCmdBuffers[2];
extern u64 *gAudioCmd;
extern struct SPTask *gAudioTask;
extern struct SPTask gAudioTasks[2];
#if defined(VERSION_EU) || defined(VERSION_SH)
extern f32 D_EU_802298D0;
extern s32 gRefreshRate;
#endif
extern s16 *gAiBuffers[NUMAIBUFFERS];
extern s16 gAiBufferLengths[NUMAIBUFFERS];
#if defined(VERSION_SH)
#define AIBUFFER_LEN 0xb00
#elif defined(VERSION_EU)
#define AIBUFFER_LEN (0xa0 * 17)
#else
#define AIBUFFER_LEN (0xa0 * 16)
#endif
extern u32 gUnused80226E58[0x10];
extern u16 gUnused80226E98[0x10];
extern u32 gAudioRandom;
#ifdef VERSION_SH
extern f32 unk_sh_data_1[];
extern volatile u32 gAudioLoadLockSH;
extern u8 D_SH_80350F18;
extern u8 D_SH_80350F19;
extern OSMesg D_SH_80350F1C[1];
extern OSMesgQueue D_SH_80350F20; // address written to D_SH_80350F38
extern OSMesgQueue *D_SH_80350F38;
extern OSMesg D_SH_80350F40[4];
extern OSMesgQueue D_SH_80350F50; // address written to D_SH_80350F68
extern OSMesgQueue *D_SH_80350F68;
extern OSMesg D_SH_80350F6C[1];
extern OSMesgQueue D_SH_80350F70; // address written to D_SH_80350F88
extern OSMesgQueue *D_SH_80350F88;
extern OSMesg D_SH_80350F8C[1];
extern OSMesgQueue D_SH_80350F90; // address written to D_SH_80350F90
extern OSMesgQueue *D_SH_80350FA8;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
#define UNUSED_COUNT_80333EE8 24
#define AUDIO_HEAP_SIZE 0x2c500
#define AUDIO_INIT_POOL_SIZE 0x2c00
#else
#define UNUSED_COUNT_80333EE8 16
#define AUDIO_HEAP_SIZE 0x31150
#define AUDIO_INIT_POOL_SIZE 0x2500
#endif
#ifdef VERSION_SH
extern u32 D_SH_80315EF0;
extern u16 D_SH_80315EF4;
extern u16 D_SH_80315EF8;
extern u16 D_SH_80315EFC;
#endif
#endif // AUDIO_DATA_H
+545
View File
@@ -0,0 +1,545 @@
#include <ultra64.h>
#include "effects.h"
#include "load.h"
#include "data.h"
#include "seqplayer.h"
#ifdef VERSION_JP
#define US_FLOAT2(x) x##.0
#else
#define US_FLOAT2(x) x
#endif
f32 gTrackVolume = 1.0f;
#if defined(VERSION_EU) || defined(VERSION_SH)
void sequence_channel_process_sound(struct SequenceChannel *seqChannel, s32 recalculateVolume) {
f32 channelVolume;
s32 i;
if (seqChannel->changes.as_bitfields.volume || recalculateVolume) {
channelVolume = seqChannel->volume * seqChannel->volumeScale * seqChannel->seqPlayer->appliedFadeVolume;
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_SOFTEN) != 0) {
channelVolume = seqChannel->seqPlayer->muteVolumeScale * channelVolume;
}
#ifdef VERSION_SH
seqChannel->appliedVolume = channelVolume * channelVolume;
#else
seqChannel->appliedVolume = channelVolume;
#endif
}
if (seqChannel->changes.as_bitfields.pan) {
seqChannel->pan = seqChannel->newPan * seqChannel->panChannelWeight;
}
for (i = 0; i < 4; ++i) {
struct SequenceChannelLayer *layer = seqChannel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) {
if (layer->notePropertiesNeedInit) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
layer->noteVelocity = layer->velocitySquare * seqChannel->appliedVolume;
layer->notePan = (seqChannel->pan + layer->pan * (0x80 - seqChannel->panChannelWeight)) >> 7;
layer->notePropertiesNeedInit = FALSE;
} else {
if (seqChannel->changes.as_bitfields.freqScale) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
}
if (seqChannel->changes.as_bitfields.volume || recalculateVolume) {
layer->noteVelocity = layer->velocitySquare * seqChannel->appliedVolume;
}
if (seqChannel->changes.as_bitfields.pan) {
layer->notePan = (seqChannel->pan + layer->pan * (0x80 - seqChannel->panChannelWeight)) >> 7;
}
}
}
}
seqChannel->changes.as_u8 = 0;
}
#else
static void sequence_channel_process_sound(struct SequenceChannel *seqChannel) {
f32 channelVolume;
f32 panLayerWeight;
f32 panFromChannel;
s32 i;
channelVolume = seqChannel->volume * seqChannel->volumeScale * seqChannel->seqPlayer->fadeVolume;
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_SOFTEN) != 0) {
channelVolume *= seqChannel->seqPlayer->muteVolumeScale;
}
panFromChannel = seqChannel->pan * seqChannel->panChannelWeight;
panLayerWeight = US_FLOAT(1.0) - seqChannel->panChannelWeight;
for (i = 0; i < 4; i++) {
struct SequenceChannelLayer *layer = seqChannel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
layer->noteVelocity = layer->velocitySquare * (channelVolume * gTrackVolume);
layer->notePan = (layer->pan * panLayerWeight) + panFromChannel;
}
}
}
#endif
void sequence_player_process_sound(struct SequencePlayer *seqPlayer) {
s32 i;
if (seqPlayer->fadeRemainingFrames != 0) {
seqPlayer->fadeVolume += seqPlayer->fadeVelocity;
#if defined(VERSION_EU) || defined(VERSION_SH)
seqPlayer->recalculateVolume = TRUE;
#endif
if (seqPlayer->fadeVolume > US_FLOAT2(1)) {
seqPlayer->fadeVolume = US_FLOAT2(1);
}
if (seqPlayer->fadeVolume < 0) {
seqPlayer->fadeVolume = 0;
}
if (--seqPlayer->fadeRemainingFrames == 0) {
#if defined(VERSION_EU) || defined(VERSION_SH)
if (seqPlayer->state == 2) {
sequence_player_disable(seqPlayer);
return;
}
#else
switch (seqPlayer->state) {
case SEQUENCE_PLAYER_STATE_FADE_OUT:
sequence_player_disable(seqPlayer);
return;
case SEQUENCE_PLAYER_STATE_2:
case SEQUENCE_PLAYER_STATE_3:
seqPlayer->state = SEQUENCE_PLAYER_STATE_0;
break;
case SEQUENCE_PLAYER_STATE_4:
break;
}
#endif
}
}
#if defined(VERSION_EU) || defined(VERSION_SH)
if (seqPlayer->recalculateVolume) {
seqPlayer->appliedFadeVolume = seqPlayer->fadeVolume * seqPlayer->fadeVolumeScale;
}
#endif
// Process channels
for (i = 0; i < CHANNELS_MAX; i++) {
if (IS_SEQUENCE_CHANNEL_VALID(seqPlayer->channels[i]) == TRUE
&& seqPlayer->channels[i]->enabled == TRUE) {
#if defined(VERSION_EU) || defined(VERSION_SH)
sequence_channel_process_sound(seqPlayer->channels[i], seqPlayer->recalculateVolume);
#else
sequence_channel_process_sound(seqPlayer->channels[i]);
#endif
}
}
#if defined(VERSION_EU) || defined(VERSION_SH)
seqPlayer->recalculateVolume = FALSE;
#endif
}
f32 get_portamento_freq_scale(struct Portamento *p) {
u32 v0;
f32 result;
#if defined(VERSION_JP) || defined(VERSION_US)
if (p->mode == 0) {
return 1.0f;
}
#endif
p->cur += p->speed;
v0 = (u32) p->cur;
#if defined(VERSION_EU) || defined(VERSION_SH)
if (v0 > 127)
#else
if (v0 >= 127)
#endif
{
v0 = 127;
}
#if defined(VERSION_EU) || defined(VERSION_SH)
result = US_FLOAT(1.0) + p->extent * (gPitchBendFrequencyScale[v0 + 128] - US_FLOAT(1.0));
#else
result = US_FLOAT(1.0) + p->extent * (gPitchBendFrequencyScale[v0 + 127] - US_FLOAT(1.0));
#endif
return result;
}
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 get_vibrato_pitch_change(struct VibratoState *vib) {
s32 index;
vib->time += (s32) vib->rate;
index = (vib->time >> 10) & 0x3F;
return vib->curve[index] >> 8;
}
#else
s8 get_vibrato_pitch_change(struct VibratoState *vib) {
s32 index;
vib->time += vib->rate;
index = (vib->time >> 10) & 0x3F;
switch (index & 0x30) {
case 0x10:
index = 31 - index;
case 0x00:
return vib->curve[index];
case 0x20:
index -= 0x20;
break;
case 0x30:
index = 63 - index;
break;
}
return -vib->curve[index];
}
#endif
f32 get_vibrato_freq_scale(struct VibratoState *vib) {
s32 pitchChange;
f32 extent;
f32 result;
if (vib->delay != 0) {
vib->delay--;
return 1;
}
if (vib->extentChangeTimer) {
if (vib->extentChangeTimer == 1) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget;
} else {
vib->extent +=
((s32) vib->seqChannel->vibratoExtentTarget - vib->extent) / (s32) vib->extentChangeTimer;
}
vib->extentChangeTimer--;
} else if (vib->seqChannel->vibratoExtentTarget != (s32) vib->extent) {
if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget;
}
}
if (vib->rateChangeTimer) {
if (vib->rateChangeTimer == 1) {
vib->rate = (s32) vib->seqChannel->vibratoRateTarget;
} else {
vib->rate += ((s32) vib->seqChannel->vibratoRateTarget - vib->rate) / (s32) vib->rateChangeTimer;
}
vib->rateChangeTimer--;
} else if (vib->seqChannel->vibratoRateTarget != (s32) vib->rate) {
if ((vib->rateChangeTimer = vib->seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = (s32) vib->seqChannel->vibratoRateTarget;
}
}
if (vib->extent == 0) {
return 1.0f;
}
pitchChange = get_vibrato_pitch_change(vib);
extent = (f32) vib->extent / US_FLOAT(4096.0);
#if defined(VERSION_EU) || defined(VERSION_SH)
result = US_FLOAT(1.0) + extent * (gPitchBendFrequencyScale[pitchChange + 128] - US_FLOAT(1.0));
#else
result = US_FLOAT(1.0) + extent * (gPitchBendFrequencyScale[pitchChange + 127] - US_FLOAT(1.0));
#endif
return result;
}
void note_vibrato_update(struct Note *note) {
#if defined(VERSION_EU) || defined(VERSION_SH)
if (note->portamento.mode != 0) {
note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento);
}
if (note->vibratoState.active && note->parentLayer != NO_LAYER) {
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
}
#else
if (note->vibratoState.active) {
note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento);
if (note->parentLayer != NO_LAYER) {
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
}
}
#endif
}
void note_vibrato_init(struct Note *note) {
struct VibratoState *vib;
UNUSED struct SequenceChannel *seqChannel;
#if defined(VERSION_EU) || defined(VERSION_SH)
struct NotePlaybackState *seqPlayerState = (struct NotePlaybackState *) &note->priority;
#endif
note->vibratoFreqScale = 1.0f;
note->portamentoFreqScale = 1.0f;
vib = &note->vibratoState;
#if defined(VERSION_JP) || defined(VERSION_US)
if (note->parentLayer->seqChannel->vibratoExtentStart == 0
&& note->parentLayer->seqChannel->vibratoExtentTarget == 0
&& note->parentLayer->portamento.mode == 0) {
vib->active = FALSE;
return;
}
#endif
vib->active = TRUE;
vib->time = 0;
#if defined(VERSION_EU) || defined(VERSION_SH)
vib->curve = gWaveSamples[2];
vib->seqChannel = note->parentLayer->seqChannel;
if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = FLOAT_CAST(vib->seqChannel->vibratoExtentTarget);
} else {
vib->extent = FLOAT_CAST(vib->seqChannel->vibratoExtentStart);
}
if ((vib->rateChangeTimer = vib->seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = FLOAT_CAST(vib->seqChannel->vibratoRateTarget);
} else {
vib->rate = FLOAT_CAST(vib->seqChannel->vibratoRateStart);
}
vib->delay = vib->seqChannel->vibratoDelay;
seqPlayerState->portamento = seqPlayerState->parentLayer->portamento;
#else
vib->curve = gVibratoCurve;
vib->seqChannel = note->parentLayer->seqChannel;
seqChannel = vib->seqChannel;
if ((vib->extentChangeTimer = seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = seqChannel->vibratoExtentTarget;
} else {
vib->extent = seqChannel->vibratoExtentStart;
}
if ((vib->rateChangeTimer = seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = seqChannel->vibratoRateTarget;
} else {
vib->rate = seqChannel->vibratoRateStart;
}
vib->delay = seqChannel->vibratoDelay;
note->portamento = note->parentLayer->portamento;
#endif
}
void adsr_init(struct AdsrState *adsr, struct AdsrEnvelope *envelope, UNUSED s16 *volOut) {
adsr->action = 0;
adsr->state = ADSR_STATE_DISABLED;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->delay = 0;
adsr->envelope = envelope;
#ifdef VERSION_SH
adsr->sustain = 0.0f;
#endif
adsr->current = 0.0f;
#else
adsr->initial = 0;
adsr->delay = 0;
adsr->velocity = 0;
adsr->envelope = envelope;
adsr->volOut = volOut;
#endif
}
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 adsr_update(struct AdsrState *adsr) {
#else
s32 adsr_update(struct AdsrState *adsr) {
#endif
u8 action = adsr->action;
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 state = adsr->state;
switch (state) {
#else
switch (adsr->state) {
#endif
case ADSR_STATE_DISABLED:
return 0;
case ADSR_STATE_INITIAL: {
#if defined(VERSION_JP) || defined(VERSION_US)
adsr->current = adsr->initial;
adsr->target = adsr->initial;
#endif
if (action & ADSR_ACTION_HANG) {
adsr->state = ADSR_STATE_HANG;
break;
}
// fallthrough
}
case ADSR_STATE_START_LOOP:
adsr->envIndex = 0;
#if defined(VERSION_JP) || defined(VERSION_US)
adsr->currentHiRes = adsr->current << 0x10;
#endif
adsr->state = ADSR_STATE_LOOP;
// fallthrough
#ifdef VERSION_SH
restart:
#endif
case ADSR_STATE_LOOP:
adsr->delay = BSWAP16(adsr->envelope[adsr->envIndex].delay);
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->state = ADSR_STATE_DISABLED;
break;
case ADSR_HANG:
adsr->state = ADSR_STATE_HANG;
break;
case ADSR_GOTO:
adsr->envIndex = BSWAP16(adsr->envelope[adsr->envIndex].arg);
#ifdef VERSION_SH
goto restart;
#else
break;
#endif
case ADSR_RESTART:
adsr->state = ADSR_STATE_INITIAL;
break;
default:
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->delay >= 4) {
adsr->delay = adsr->delay * gAudioBufferParameters.updatesPerFrame
#ifdef VERSION_SH
/ gAudioBufferParameters.presetUnk4
#endif
/ 4;
}
#if defined(VERSION_SH)
if (adsr->delay == 0) {
adsr->delay = 1;
}
adsr->target = (f32) BSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0f;
#elif defined(VERSION_EU)
adsr->target = (f32) BSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0;
#endif
adsr->target = adsr->target * adsr->target;
adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
#else
adsr->target = BSWAP16(adsr->envelope[adsr->envIndex].arg);
adsr->velocity = ((adsr->target - adsr->current) << 0x10) / adsr->delay;
#endif
adsr->state = ADSR_STATE_FADE;
adsr->envIndex++;
break;
}
if (adsr->state != ADSR_STATE_FADE) {
break;
}
// fallthrough
case ADSR_STATE_FADE:
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->current += adsr->velocity;
#else
adsr->currentHiRes += adsr->velocity;
adsr->current = adsr->currentHiRes >> 0x10;
#endif
if (--adsr->delay <= 0) {
adsr->state = ADSR_STATE_LOOP;
}
// fallthrough
case ADSR_STATE_HANG:
break;
case ADSR_STATE_DECAY:
case ADSR_STATE_RELEASE: {
adsr->current -= adsr->fadeOutVel;
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->sustain != 0.0f && state == ADSR_STATE_DECAY) {
#else
if (adsr->sustain != 0 && adsr->state == ADSR_STATE_DECAY) {
#endif
if (adsr->current < adsr->sustain) {
adsr->current = adsr->sustain;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->delay = 128;
#else
adsr->delay = adsr->sustain / 16;
#endif
adsr->state = ADSR_STATE_SUSTAIN;
}
break;
}
#if defined(VERSION_SH)
if (adsr->current < 0.00001f) {
adsr->current = 0.0f;
adsr->state = ADSR_STATE_DISABLED;
}
#elif defined(VERSION_EU)
if (adsr->current < 0) {
adsr->current = 0.0f;
adsr->state = ADSR_STATE_DISABLED;
}
#else
if (adsr->current < 100) {
adsr->current = 0;
adsr->state = ADSR_STATE_DISABLED;
}
#endif
break;
}
case ADSR_STATE_SUSTAIN:
adsr->delay -= 1;
if (adsr->delay == 0) {
adsr->state = ADSR_STATE_RELEASE;
}
break;
}
if ((action & ADSR_ACTION_DECAY)) {
adsr->state = ADSR_STATE_DECAY;
adsr->action = action & ~ADSR_ACTION_DECAY;
}
if ((action & ADSR_ACTION_RELEASE)) {
adsr->state = ADSR_STATE_RELEASE;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->action = action & ~ADSR_ACTION_RELEASE;
#else
adsr->action = action & ~(ADSR_ACTION_RELEASE | ADSR_ACTION_DECAY);
#endif
}
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->current < 0.0f) {
return 0.0f;
}
if (adsr->current > 1.0f) {
eu_stubbed_printf_1("Audio:Envp: overflow %f\n", adsr->current);
return 1.0f;
}
return adsr->current;
#else
*adsr->volOut = adsr->current;
return 0;
#endif
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef AUDIO_EFFECTS_H
#define AUDIO_EFFECTS_H
#include <PR/ultratypes.h>
#include "internal.h"
#include <platform_info.h>
#define ADSR_STATE_DISABLED 0
#define ADSR_STATE_INITIAL 1
#define ADSR_STATE_START_LOOP 2
#define ADSR_STATE_LOOP 3
#define ADSR_STATE_FADE 4
#define ADSR_STATE_HANG 5
#define ADSR_STATE_DECAY 6
#define ADSR_STATE_RELEASE 7
#define ADSR_STATE_SUSTAIN 8
#define ADSR_ACTION_RELEASE 0x10
#define ADSR_ACTION_DECAY 0x20
#define ADSR_ACTION_HANG 0x40
#define ADSR_DISABLE 0
#define ADSR_HANG -1
#define ADSR_GOTO -2
#define ADSR_RESTART -3
// Envelopes are always stored as big endian, to match sequence files which are
// byte blobs and can embed envelopes. Hence this byteswapping macro.
#if IS_BIG_ENDIAN
#define BSWAP16(x) (x)
#else
#define BSWAP16(x) (((x) & 0xff) << 8 | (((x) >> 8) & 0xff))
#endif
extern f32 gTrackVolume;
void sequence_player_process_sound(struct SequencePlayer *seqPlayer);
void note_vibrato_update(struct Note *note);
void note_vibrato_init(struct Note *note);
void adsr_init(struct AdsrState *adsr, struct AdsrEnvelope *envelope, s16 *volOut);
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 adsr_update(struct AdsrState *adsr);
#else
s32 adsr_update(struct AdsrState *adsr);
#endif
#endif // AUDIO_EFFECTS_H
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
#ifndef AUDIO_EXTERNAL_H
#define AUDIO_EXTERNAL_H
#include <PR/ultratypes.h>
#include <types.h>
// Sequence arguments, passed to seq_player_play_sequence. seqId may be bit-OR'ed with
// SEQ_VARIATION; this will load the same sequence, but set a variation
// bit which may be read by the sequence script.
#define SEQUENCE_ARGS(priority, seqId) ((priority << 8) | seqId)
#define SOUND_MODE_STEREO 0
#define SOUND_MODE_MONO 3
#define SOUND_MODE_HEADSET 1
#define SEQ_PLAYER_LEVEL 0 // Level background music
#define SEQ_PLAYER_ENV 1 // Misc music like the puzzle jingle
#define SEQ_PLAYER_SFX 2 // Sound effects
extern s32 gAudioErrorFlags;
extern f32 gGlobalSoundSource[3];
extern u32 gAudioRandom;
extern f32 gAudioVolume;
extern u8 gAudioReverb;
struct Sound {
s32 soundBits;
f32 *position;
}; // size = 0x8
extern struct Sound sSoundRequests[0x100];
extern u8 sSoundRequestCount;
extern u8 gAudioSPTaskYieldBuffer[]; // ucode yield data ptr; only used in JP
struct SPTask *create_next_audio_frame_task(void);
void create_next_audio_buffer(s16 *samples, u32 num_samples);
void audio_signal_game_loop_tick(void);
void update_game_sound(void);
void seq_player_fade_out(u8 player, u16 fadeDuration);
void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration);
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage);
void seq_player_unlower_volume(u8 player, u16 fadeDuration);
void set_audio_muted(u8 muted);
void sound_init(void);
void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId);
void stop_sound(u32 soundBits, f32 *pos);
void stop_sounds_from_source(f32 *pos);
void stop_sounds_in_continuous_banks(void);
void sound_banks_disable(u8 player, u16 bankMask);
void sound_banks_enable(u8 player, u16 bankMask);
void set_sound_moving_speed(u8 bank, u8 speed);
void play_dialog_sound(u8 dialogID);
void play_music(u8 player, u16 seqArgs, u16 fadeTimer);
void stop_background_music(u16 seqId);
void fadeout_background_music(u16 arg0, u16 fadeOut);
void drop_queued_background_music(void);
u16 get_current_background_music(void);
void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer);
void func_80321080(u16 fadeTimer);
void func_803210D4(u16 fadeOutTime);
void play_course_clear(void);
void play_peachs_jingle(void);
void play_puzzle_jingle(void);
void play_star_fanfare(void);
void play_power_star_jingle(u8 arg0);
void play_race_fanfare(void);
void play_toads_jingle(void);
void sound_reset(u8 presetId);
void audio_set_sound_mode(u8 arg0);
void audio_init(void); // in load.c
void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2);
#if defined(VERSION_EU) || defined(VERSION_SH)
struct SPTask *unused_80321460();
struct SPTask *unused_80321460(void);
#endif
#endif // AUDIO_EXTERNAL_H
+3
View File
@@ -0,0 +1,3 @@
#include <ultra64.h>
u64 gAudioGlobalsStartMarker;
File diff suppressed because it is too large Load Diff
+144
View File
@@ -0,0 +1,144 @@
#ifndef AUDIO_HEAP_H
#define AUDIO_HEAP_H
#include <PR/ultratypes.h>
#include "internal.h"
#define SOUND_LOAD_STATUS_NOT_LOADED 0
#define SOUND_LOAD_STATUS_IN_PROGRESS 1
#define SOUND_LOAD_STATUS_COMPLETE 2
#define SOUND_LOAD_STATUS_DISCARDABLE 3
#define SOUND_LOAD_STATUS_4 4
#define SOUND_LOAD_STATUS_5 5
#define IS_BANK_LOAD_COMPLETE(bankId) (gBankLoadStatus[bankId] >= SOUND_LOAD_STATUS_COMPLETE)
#define IS_SEQ_LOAD_COMPLETE(seqId) (gSeqLoadStatus[seqId] >= SOUND_LOAD_STATUS_COMPLETE)
struct SoundAllocPool
{
u8 *start;
u8 *cur;
u32 size;
s32 numAllocatedEntries;
}; // size = 0x10
struct SeqOrBankEntry {
u8 *ptr;
u32 size;
#ifdef VERSION_SH
s16 poolIndex;
s16 id;
#else
s32 id; // seqId or bankId
#endif
}; // size = 0xC
struct PersistentPool
{
/*0x00*/ u32 numEntries;
/*0x04*/ struct SoundAllocPool pool;
/*0x14*/ struct SeqOrBankEntry entries[32];
}; // size = 0x194
struct TemporaryPool
{
/*EU, SH*/
/*0x00, 0x00*/ u32 nextSide;
/*0x04, */ struct SoundAllocPool pool;
/*0x04, pool.start */
/*0x08, pool.cur */
/*0x0C, 0x0C pool.size */
/*0x10, 0x10 pool.numAllocatedEntries */
/*0x14, */ struct SeqOrBankEntry entries[2];
/*0x14, 0x14 entries[0].ptr */
/*0x18, entries[0].size*/
/*0x1C, 0x1E entries[0].id */
/*0x20, 0x20 entries[1].ptr */
/*0x24, entries[1].size*/
/*0x28, 0x2A entries[1].id */
}; // size = 0x2C
struct SoundMultiPool
{
/*0x000*/ struct PersistentPool persistent;
/*0x194*/ struct TemporaryPool temporary;
/* */ u32 pad2[4];
}; // size = 0x1D0
struct Unk1Pool
{
struct SoundAllocPool pool;
struct SeqOrBankEntry entries[32];
};
struct UnkEntry
{
s8 used;
s8 medium;
s8 bankId;
u32 pad;
u8 *srcAddr;
u8 *dstAddr;
u32 size;
};
struct UnkPool
{
/*0x00*/ struct SoundAllocPool pool;
/*0x10*/ struct UnkEntry entries[64];
/*0x510*/ s32 numEntries;
/*0x514*/ u32 unk514;
};
extern u8 gAudioHeap[];
extern s16 gVolume;
extern s8 gReverbDownsampleRate;
extern struct SoundAllocPool gAudioInitPool;
extern struct SoundAllocPool gNotesAndBuffersPool;
extern struct SoundAllocPool gPersistentCommonPool;
extern struct SoundAllocPool gTemporaryCommonPool;
extern struct SoundMultiPool gSeqLoadedPool;
extern struct SoundMultiPool gBankLoadedPool;
#ifdef VERSION_SH
extern struct Unk1Pool gUnkPool1;
extern struct UnkPool gUnkPool2;
extern struct UnkPool gUnkPool3;
#endif
extern u8 gBankLoadStatus[64];
extern u8 gSeqLoadStatus[256];
extern volatile u8 gAudioResetStatus;
extern u8 gAudioResetPresetIdToLoad;
#if defined(VERSION_EU) || defined(VERSION_SH)
extern volatile u8 gAudioResetStatus;
#endif
void *soundAlloc(struct SoundAllocPool *pool, u32 size);
void *sound_alloc_uninitialized(struct SoundAllocPool *pool, u32 size);
void sound_init_main_pools(s32 sizeForAudioInitPool);
void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size);
#ifdef VERSION_SH
void *alloc_bank_or_seq(s32 poolIdx, s32 size, s32 arg3, s32 id);
void *get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id);
#else
void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id);
void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id);
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 audio_shut_down_and_reset_step(void);
void audio_reset_session(void);
#else
void audio_reset_session(struct AudioSessionSettings *preset);
#endif
void discard_bank(s32 bankId);
#ifdef VERSION_SH
void fill_filter(s16 filter[8], s32 arg1, s32 arg2);
u8 *func_sh_802f1d40(u32 size, s32 bank, u8 *arg2, s8 medium);
u8 *func_sh_802f1d90(u32 size, s32 bank, u8 *arg2, s8 medium);
void *unk_pool1_lookup(s32 poolIdx, s32 id);
void *unk_pool1_alloc(s32 poolIndex, s32 arg1, u32 size);
#endif
#endif // AUDIO_HEAP_H
+886
View File
@@ -0,0 +1,886 @@
#ifndef AUDIO_INTERNAL_H
#define AUDIO_INTERNAL_H
#include <ultra64.h>
#include <types.h>
#if defined(VERSION_EU) || defined(VERSION_SH)
#define SEQUENCE_PLAYERS 4
#define SEQUENCE_CHANNELS 48
#define SEQUENCE_LAYERS 64
#else
#define SEQUENCE_PLAYERS 3
#define SEQUENCE_CHANNELS 32
#ifdef VERSION_JP
#define SEQUENCE_LAYERS 48
#else
#define SEQUENCE_LAYERS 52
#endif
#endif
#define LAYERS_MAX 4
#define CHANNELS_MAX 16
#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
#define MUTE_BEHAVIOR_STOP_SCRIPT 0x80 // stop processing sequence/channel scripts
#define MUTE_BEHAVIOR_STOP_NOTES 0x40 // prevent further notes from playing
#define MUTE_BEHAVIOR_SOFTEN 0x20 // lower volume, by default to half
#define SEQUENCE_PLAYER_STATE_0 0
#define SEQUENCE_PLAYER_STATE_FADE_OUT 1
#define SEQUENCE_PLAYER_STATE_2 2
#define SEQUENCE_PLAYER_STATE_3 3
#define SEQUENCE_PLAYER_STATE_4 4
#define NOTE_PRIORITY_DISABLED 0
#define NOTE_PRIORITY_STOPPING 1
#define NOTE_PRIORITY_MIN 2
#define NOTE_PRIORITY_DEFAULT 3
#define TATUMS_PER_BEAT 48
// abi.h contains more details about the ADPCM and S8 codecs, "skip" skips codec processing
#define CODEC_ADPCM 0
#define CODEC_S8 1
#define CODEC_SKIP 2
#ifdef VERSION_JP
#define TEMPO_SCALE 1
#else
#define TEMPO_SCALE TATUMS_PER_BEAT
#endif
// TODO: US_FLOAT should probably be renamed to JP_DOUBLE since eu seems to use floats too
#ifdef VERSION_JP
#define US_FLOAT(x) x
#else
#define US_FLOAT(x) x ## f
#endif
// Convert u8 or u16 to f32. On JP, this uses a u32->f32 conversion,
// resulting in more bloated codegen, while on US it goes through s32.
// Since u8 and u16 fit losslessly in both, behavior is the same.
#ifdef VERSION_JP
#define FLOAT_CAST(x) (f32) (x)
#else
#define FLOAT_CAST(x) (f32) (s32) (x)
#endif
// No-op printf macro which leaves string literals in rodata in IDO. IDO
// doesn't support variadic macros, so instead we let the parameter list
// expand to a no-op comma expression. Another possibility is that it might
// have expanded to something with "if (0)". See also goddard/gd_main.h.
// On US/JP, -sopt optimizes away these except for external.c.
#ifdef __sgi
#define stubbed_printf
#else
#define stubbed_printf(...)
#endif
#ifdef VERSION_EU
#define eu_stubbed_printf_0(msg) stubbed_printf(msg)
#define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a)
#define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b)
#define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c)
#else
#define eu_stubbed_printf_0(msg)
#define eu_stubbed_printf_1(msg, a)
#define eu_stubbed_printf_2(msg, a, b)
#define eu_stubbed_printf_3(msg, a, b, c)
#endif
struct NotePool;
struct AudioListItem
{
// A node in a circularly linked list. Each node is either a head or an item:
// - Items can be either detached (prev = NULL), or attached to a list.
// 'value' points to something of interest.
// - List heads are always attached; if a list is empty, its head points
// to itself. 'count' contains the size of the list.
// If the list holds notes, 'pool' points back to the pool where it lives.
// Otherwise, that member is NULL.
struct AudioListItem *prev;
struct AudioListItem *next;
union {
void *value; // either Note* or SequenceChannelLayer*
s32 count;
} u;
struct NotePool *pool;
}; // size = 0x10
struct NotePool
{
struct AudioListItem disabled;
struct AudioListItem decaying;
struct AudioListItem releasing;
struct AudioListItem active;
};
struct VibratoState {
/*0x00, 0x00*/ struct SequenceChannel *seqChannel;
/*0x04, 0x04*/ u32 time;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x08*/ s16 *curve;
/* , 0x0C*/ f32 extent;
/* , 0x10*/ f32 rate;
/* , 0x14*/ u8 active;
#else
/*0x08, */ s8 *curve;
/*0x0C, */ u8 active;
/*0x0E, */ u16 rate;
/*0x10, */ u16 extent;
#endif
/*0x12, 0x16*/ u16 rateChangeTimer;
/*0x14, 0x18*/ u16 extentChangeTimer;
/*0x16, 0x1A*/ u16 delay;
}; // size = 0x18, 0x1C on EU
// Pitch sliding by up to one octave in the positive direction. Negative
// direction is "supported" by setting extent to be negative. The code
// extrapolates exponentially in the wrong direction in that case, but that
// doesn't prevent seqplayer from doing it, AFAICT.
struct Portamento {
u8 mode; // bit 0x80 denotes something; the rest are an index 0-5
f32 cur;
f32 speed;
f32 extent;
}; // size = 0x10
struct AdsrEnvelope {
s16 delay;
s16 arg;
}; // size = 0x4
struct AdpcmLoop
{
u32 start;
u32 end;
u32 count;
u32 pad;
s16 state[16]; // only exists if count != 0. 8-byte aligned
};
struct AdpcmBook
{
s32 order;
s32 npredictors;
s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
};
struct AudioBankSample
{
#ifdef VERSION_SH
#if !IS_BIG_ENDIAN
u32 size : 24;
#endif
/* 0x00 */ u32 codec : 4;
/* 0x00 */ u32 medium : 2;
/* 0x00 */ u32 bit1 : 1;
/* 0x00 */ u32 isPatched : 1;
#if IS_BIG_ENDIAN
/* 0x01 */ u32 size : 24;
#endif
#else
u8 unused;
u8 loaded;
#endif
u8 *sampleAddr;
struct AdpcmLoop *loop;
struct AdpcmBook *book;
#ifndef VERSION_SH
u32 sampleSize; // never read. either 0 or 1 mod 9, depending on padding
#endif
};
struct AudioBankSound
{
struct AudioBankSample *sample;
f32 tuning; // frequency scale factor
}; // size = 0x8
struct Instrument
{
/*0x00*/ u8 loaded;
/*0x01*/ u8 normalRangeLo;
/*0x02*/ u8 normalRangeHi;
/*0x03*/ u8 releaseRate;
/*0x04*/ struct AdsrEnvelope *envelope;
/*0x08*/ struct AudioBankSound lowNotesSound;
/*0x10*/ struct AudioBankSound normalNotesSound;
/*0x18*/ struct AudioBankSound highNotesSound;
}; // size = 0x20
struct Drum
{
u8 releaseRate;
u8 pan;
u8 loaded;
struct AudioBankSound sound;
struct AdsrEnvelope *envelope;
};
struct AudioBank
{
struct Drum **drums;
struct Instrument *instruments[1];
}; // dynamic size
struct CtlEntry
{
#ifndef VERSION_SH
u8 unused;
#endif
u8 numInstruments;
u8 numDrums;
#ifdef VERSION_SH
u8 bankId1;
u8 bankId2;
#endif
struct Instrument **instruments;
struct Drum **drums;
}; // size = 0xC
struct M64ScriptState {
u8 *pc;
u8 *stack[4];
u8 remLoopIters[4];
u8 depth;
}; // size = 0x1C
// Also known as a Group, according to debug strings.
struct SequencePlayer
{
/*US/JP, EU, SH */
#if defined(VERSION_EU) || defined(VERSION_SH)
/*0x000, 0x000, 0x000*/ u8 enabled : 1;
#else
/*0x000, 0x000*/ volatile u8 enabled : 1;
#endif
/*0x000, 0x000*/ u8 finished : 1; // never read
/*0x000, 0x000*/ u8 muted : 1;
/*0x000, 0x000*/ u8 seqDmaInProgress : 1;
/*0x000, 0x000*/ u8 bankDmaInProgress : 1;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* 0x000*/ u8 recalculateVolume : 1;
#endif
#ifdef VERSION_SH
/* 0x000*/ u8 unkSh: 1;
#endif
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x001 */ s8 seqVariation;
#endif
/*0x002, 0x001, 0x001*/ u8 state;
/*0x003, 0x002*/ u8 noteAllocPolicy;
/*0x004, 0x003*/ u8 muteBehavior;
/*0x005, 0x004*/ u8 seqId;
/*0x006, 0x005*/ u8 defaultBank[1]; // must be an array to get a comparison
// to match; other u8's might also be part of that array
/*0x007, 0x006*/ u8 loadingBankId;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x008, ?????*/ u8 loadingBankNumInstruments;
/*0x009, ?????*/ u8 loadingBankNumDrums;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x007, 0x007*/ s8 seqVariationEu[1];
#endif
/*0x00A, 0x008*/ u16 tempo; // beats per minute in JP, tatums per minute in US/EU
/*0x00C, 0x00A*/ u16 tempoAcc;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x00E, 0x010*/ u16 fadeRemainingFrames;
#endif
#ifdef VERSION_SH
/* 0x00C*/ s16 tempoAdd;
#endif
/*0x010, 0x00C, 0x00E*/ s16 transposition;
/*0x012, 0x00E, 0x010*/ u16 delay;
#if defined(VERSION_EU) || defined(VERSION_SH)
/*0x00E, 0x010, 0x012*/ u16 fadeRemainingFrames;
/* , 0x012, 0x014*/ u16 fadeTimerUnkEu;
#endif
/*0x014, 0x014*/ u8 *seqData; // buffer of some sort
/*0x018, 0x018, 0x1C*/ f32 fadeVolume; // set to 1.0f
/*0x01C, 0x01C*/ f32 fadeVelocity; // set to 0.0f
/*0x020, 0x020, 0x024*/ f32 volume; // set to 0.0f
/*0x024, 0x024*/ f32 muteVolumeScale; // set to 0.5f
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x028, 0x02C*/ f32 fadeVolumeScale;
/* , 0x02C*/ f32 appliedFadeVolume;
#else
/* */ u8 pad2[4];
#endif
/*0x02C, 0x030, 0x034*/ struct SequenceChannel *channels[CHANNELS_MAX];
/*0x06C, 0x070*/ struct M64ScriptState scriptState;
/*0x088, 0x08C*/ u8 *shortNoteVelocityTable;
/*0x08C, 0x090*/ u8 *shortNoteDurationTable;
/*0x090, 0x094*/ struct NotePool notePool;
/*0x0D0, 0x0D4*/ OSMesgQueue seqDmaMesgQueue;
/*0x0E8, 0x0EC*/ OSMesg seqDmaMesg;
/*0x0EC, 0x0F0*/ OSIoMesg seqDmaIoMesg;
/*0x100, 0x108*/ OSMesgQueue bankDmaMesgQueue;
/*0x118, 0x120*/ OSMesg bankDmaMesg;
/*0x11C, 0x124*/ OSIoMesg bankDmaIoMesg;
/*0x130, 0x13C*/ u8 *bankDmaCurrMemAddr;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x134, ?????*/ struct AudioBank *loadingBank;
#endif
/*0x138, 0x140*/ uintptr_t bankDmaCurrDevAddr;
/*0x13C, 0x144*/ ssize_t bankDmaRemaining;
}; // size = 0x140, 0x148 on EU, 0x14C on SH
struct AdsrSettings
{
u8 releaseRate;
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 sustain;
#else
u16 sustain; // sustain level, 2^16 = max
#endif
struct AdsrEnvelope *envelope;
}; // size = 0x8
struct AdsrState {
/*0x00, 0x00*/ u8 action;
/*0x01, 0x01*/ u8 state;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x02, */ s16 initial; // always 0
/*0x04, */ s16 target;
/*0x06, */ s16 current;
#endif
/*0x08, 0x02*/ s16 envIndex;
/*0x0A, 0x04*/ s16 delay;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x08*/ f32 sustain;
/* , 0x0C*/ f32 velocity;
/* , 0x10*/ f32 fadeOutVel;
/* , 0x14*/ f32 current;
/* , 0x18*/ f32 target;
s32 pad1C;
#else
/*0x0C, */ s16 sustain;
/*0x0E, */ s16 fadeOutVel;
/*0x10, */ s32 velocity;
/*0x14, */ s32 currentHiRes;
/*0x18, */ s16 *volOut;
#endif
/*0x1C, 0x20*/ struct AdsrEnvelope *envelope;
}; // size = 0x20, 0x24 in EU
struct ReverbBitsData {
/* 0x00 */ u8 bit0 : 1;
/* 0x00 */ u8 bit1 : 1;
/* 0x00 */ u8 bit2 : 1;
/* 0x00 */ u8 usesHeadsetPanEffects : 1;
/* 0x00 */ u8 stereoHeadsetEffects : 2;
/* 0x00 */ u8 strongRight : 1;
/* 0x00 */ u8 strongLeft : 1;
};
union ReverbBits {
/* 0x00 */ struct ReverbBitsData s;
/* 0x00 */ u8 asByte;
};
struct ReverbInfo {
u8 reverbVol;
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
u8 pan;
union ReverbBits reverbBits;
f32 freqScale;
f32 velocity;
s32 unused;
s16 *filter;
};
struct NoteAttributes
{
u8 reverbVol;
#ifdef VERSION_SH
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 pan;
#endif
#ifdef VERSION_SH
union ReverbBits reverbBits;
#endif
f32 freqScale;
f32 velocity;
#if defined(VERSION_JP) || defined(VERSION_US)
f32 pan;
#endif
#ifdef VERSION_SH
s16 *filter;
#endif
}; // size = 0x10
// Also known as a SubTrack, according to debug strings.
// Confusingly, a SubTrack is a container of Tracks.
struct SequenceChannel
{
/* U/J, EU, SH */
/*0x00, 0x00*/ u8 enabled : 1;
/*0x00, 0x00*/ u8 finished : 1;
/*0x00, 0x00*/ u8 stopScript : 1;
/*0x00, 0x00*/ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
/*0x00, 0x00*/ u8 hasInstrument : 1;
/*0x00, 0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00, ????*/ u8 largeNotes : 1; // notes specify duration and velocity
/*0x00, ????*/ u8 unused : 1; // never read, set to 0
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x01*/ union {
struct {
u8 freqScale : 1;
u8 volume : 1;
u8 pan : 1;
} as_bitfields;
u8 as_u8;
} changes;
#endif
/*0x01, 0x02*/ u8 noteAllocPolicy;
/*0x02, 0x03, 0x03*/ u8 muteBehavior;
/*0x03, 0x04, 0x04*/ u8 reverbVol; // until EU: Q1.7, after EU: UQ0.8
/*0x04, ????*/ u8 notePriority; // 0-3
#ifdef VERSION_SH
u8 unkSH06; // some priority
#endif
/*0x05, 0x06*/ u8 bankId;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x07*/ u8 reverbIndex;
/* , 0x08, 0x09*/ u8 bookOffset;
/* , 0x09*/ u8 newPan;
/* , 0x0A*/ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128)
#else
/*0x06, */ u8 updatesPerFrameUnused;
#endif
#ifdef VERSION_SH
/* 0x0C*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
/*0x08, 0x0C, 0x0E*/ u16 vibratoRateStart; // initially 0x800
/*0x0A, 0x0E, 0x10*/ u16 vibratoExtentStart;
/*0x0C, 0x10, 0x12*/ u16 vibratoRateTarget; // initially 0x800
/*0x0E, 0x12, 0x14*/ u16 vibratoExtentTarget;
/*0x10, 0x14, 0x16*/ u16 vibratoRateChangeDelay;
/*0x12, 0x16, 0x18*/ u16 vibratoExtentChangeDelay;
/*0x14, 0x18, 0x1A*/ u16 vibratoDelay;
/*0x16, 0x1A, 0x1C*/ u16 delay;
/*0x18, 0x1C, 0x1E*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
/*0x1A, 0x1E, 0x20*/ s16 transposition;
/*0x1C, 0x20, 0x24*/ f32 volumeScale;
/*0x20, 0x24, 0x28*/ f32 volume;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x24, */ f32 pan;
/*0x28, */ f32 panChannelWeight; // proportion of pan that comes from the channel (0..1)
#else
/* , 0x28*/ s32 pan;
/* , 0x2C*/ f32 appliedVolume;
#endif
/*0x2C, 0x30*/ f32 freqScale;
/*0x30, 0x34*/ u8 (*dynTable)[][2];
/*0x34, ????*/ struct Note *noteUnused; // never read
/*0x38, ????*/ struct SequenceChannelLayer *layerUnused; // never read
/*0x3C, 0x40*/ struct Instrument *instrument;
/*0x40, 0x44*/ struct SequencePlayer *seqPlayer;
/*0x44, 0x48*/ struct SequenceChannelLayer *layers[LAYERS_MAX];
#ifndef VERSION_SH
/*0x54, 0x58 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
#endif
/*0x5C, 0x60*/ struct M64ScriptState scriptState;
/*0x78, 0x7C*/ struct AdsrSettings adsr;
/*0x80, 0x84*/ struct NotePool notePool;
#ifdef VERSION_SH
/* 0xC0*/ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
/* 0xC8*/ u16 unkC8;
/* 0xCC*/ s16 *filter;
#endif
}; // size = 0xC0, 0xC4 in EU, 0xD0 in SH
// Also known as a Track, according to debug strings.
struct SequenceChannelLayer
{
/* U/J, EU, SH */
/*0x00, 0x00*/ u8 enabled : 1;
/*0x00, 0x00*/ u8 finished : 1;
/*0x00, 0x00*/ u8 stopSomething : 1; // ?
/*0x00, 0x00*/ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x00*/ u8 unusedEu0b8 : 1;
/* , 0x00*/ u8 notePropertiesNeedInit : 1;
/* , 0x00*/ u8 ignoreDrumPan : 1;
#ifdef VERSION_SH
/* , , 0x01 */ union ReverbBits reverbBits;
#endif
/* , 0x01, 0x02*/ u8 instOrWave;
#endif
/*0x01, 0x02, 0x03*/ u8 status; // 0x03 in SH
/*0x02, 0x03*/ u8 noteDuration; // set to 0x80
/*0x03, 0x04*/ u8 portamentoTargetNote;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x05*/ u8 pan; // 0..128
/* , 0x06, 0x07*/ u8 notePan;
#endif
/*0x04, 0x08*/ struct Portamento portamento;
/*0x14, 0x18*/ struct AdsrSettings adsr;
/*0x1C, 0x20*/ u16 portamentoTime;
/*0x1E, 0x22*/ s16 transposition; // #semitones added to play commands
// (m64 instruction encoding only allows referring to the limited range
// 0..0x3f; this makes 0x40..0x7f accessible as well)
/*0x20, 0x24, 0x24*/ f32 freqScale;
#ifdef VERSION_SH
/* 0x28*/ f32 freqScaleMultiplier;
#endif
/*0x24, 0x28, 0x2C*/ f32 velocitySquare;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x28, */ f32 pan; // 0..1
#endif
/*0x2C, 0x2C, 0x30*/ f32 noteVelocity;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x30*/ f32 notePan;
#endif
/*0x34, 0x30, 0x34*/ f32 noteFreqScale;
/*0x38, 0x34*/ s16 shortNoteDefaultPlayPercentage;
/*0x3A, 0x36*/ s16 playPercentage; // it's not really a percentage...
/*0x3C, 0x38*/ s16 delay;
/*0x3E, 0x3A*/ s16 duration;
/*0x40, 0x3C*/ s16 delayUnused; // set to 'delay', never read
/*0x44, 0x40, 0x44*/ struct Note *note;
/*0x48, 0x44*/ struct Instrument *instrument;
/*0x4C, 0x48*/ struct AudioBankSound *sound;
/*0x50, 0x4C, 0x50*/ struct SequenceChannel *seqChannel;
/*0x54, 0x50*/ struct M64ScriptState scriptState;
/*0x70, 0x6C*/ struct AudioListItem listItem;
#if defined(VERSION_EU)
u8 pad2[4];
#endif
}; // size = 0x80
#if defined(VERSION_EU) || defined(VERSION_SH)
struct NoteSynthesisState
{
/*0x00*/ u8 restart;
/*0x01*/ u8 sampleDmaIndex;
/*0x02*/ u8 prevHeadsetPanRight;
/*0x03*/ u8 prevHeadsetPanLeft;
#ifdef VERSION_SH
/* 0x04*/ u8 reverbVol;
/* 0x05*/ u8 unk5;
#endif
/*0x04, 0x06*/ u16 samplePosFrac;
/*0x08*/ s32 samplePosInt;
/*0x0C*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x10*/ s16 curVolLeft; // UQ0.16 (EU Q1.15)
/*0x12*/ s16 curVolRight; // UQ0.16 (EU Q1.15)
};
struct NotePlaybackState
{
/* U/J, EU, SH */
/*0x04, 0x00, 0x00*/ u8 priority;
/* 0x01, 0x01*/ u8 waveId;
/* 0x02, 0x02*/ u8 sampleCountIndex;
#ifdef VERSION_SH
/* 0x03*/ u8 bankId;
/* 0x04*/ u8 unkSH34;
#endif
/*0x08, 0x04, 0x06*/ s16 adsrVolScale;
/*0x18, 0x08, 0x08*/ f32 portamentoFreqScale;
/*0x1C, 0x0C, 0x0C*/ f32 vibratoFreqScale;
/*0x28, 0x10, */ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x14, 0x14*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x18, 0x18*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x1C, 0x1C*/ struct NoteAttributes attributes;
/*0x54, 0x28, 0x2C*/ struct AdsrState adsr;
/*0x74, 0x4C, */ struct Portamento portamento;
/*0x84, 0x5C, */ struct VibratoState vibratoState;
};
struct NoteSubEu
{
/*0x00*/ volatile u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00*/ u8 usesHeadsetPanEffects : 1;
/*0x01*/ u8 reverbIndex : 3;
/*0x01*/ u8 bookOffset : 3;
/*0x01*/ u8 isSyntheticWave : 1;
/*0x01*/ u8 hasTwoAdpcmParts : 1;
#ifdef VERSION_EU
/*0x02*/ u8 bankId;
#else
/*0x02*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
/*0x03*/ u8 headsetPanRight;
/*0x04*/ u8 headsetPanLeft;
/*0x05*/ u8 reverbVol; // UQ0.7 (EU Q1.7)
/*0x06*/ u16 targetVolLeft; // UQ0.12 (EU UQ0.10)
/*0x08*/ u16 targetVolRight; // UQ0.12 (EU UQ0.10)
/*0x0A*/ u16 resamplingRateFixedPoint; // stored as signed but loaded as u16
/*0x0C*/ union {
s16 *samples;
struct AudioBankSound *audioBankSound;
} sound;
#ifdef VERSION_SH
/*0x10*/ s16 *filter;
#endif
};
struct Note
{
/* U/J, EU, SH */
/*0xA4, 0x00, 0x00*/ struct AudioListItem listItem;
/* 0x10, 0x10*/ struct NoteSynthesisState synthesisState;
// The next members are actually part of a struct (NotePlaybackState), but
// that results in messy US/EU ifdefs. Instead we cast to a struct pointer
// when needed... This breaks alignment on non-N64 platforms, which we hack
// around by skipping the padding in that case.
// TODO: use macros or something instead.
#ifdef TARGET_N64
u8 pad0[12];
#endif
/*0x04, 0x30, 0x30*/ u8 priority;
/* 0x31, 0x31*/ u8 waveId;
/* 0x32, 0x32*/ u8 sampleCountIndex;
#ifdef VERSION_SH
/* 0x33*/ u8 bankId;
/* 0x34*/ u8 unkSH34;
#endif
/*0x08, 0x34, 0x36*/ s16 adsrVolScale;
/*0x18, 0x38, */ f32 portamentoFreqScale;
/*0x1C, 0x3C, */ f32 vibratoFreqScale;
/*0x28, 0x40, */ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x4C, 0x4C*/ struct NoteAttributes attributes;
/*0x54, 0x58, 0x5C*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
u8 pad3[8];
/* , 0xB0, 0xB4*/ struct NoteSubEu noteSubEu;
}; // size = 0xC0, known to be 0xC8 on SH
#else
// volatile Note, needed in synthesis_process_notes
struct vNote
{
/* U/J, EU */
/*0x00*/ volatile u8 enabled : 1;
long long int force_structure_alignment;
}; // size = 0xC0
struct Note
{
/* U/J, EU */
/*0x00*/ u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 restart : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x01*/ u8 usesHeadsetPanEffects;
/*0x02*/ u8 unk2;
/*0x03*/ u8 sampleDmaIndex;
/*0x04, 0x30*/ u8 priority;
/*0x05*/ u8 sampleCount; // 0, 8, 16, 32 or 64
/*0x06*/ u8 instOrWave;
/*0x07*/ u8 bankId; // in NoteSubEu on EU
/*0x08*/ s16 adsrVolScale;
/* */ u8 pad1[2];
/*0x0C, 0xB3*/ u16 headsetPanRight;
/*0x0E, 0xB4*/ u16 headsetPanLeft;
/*0x10*/ u16 prevHeadsetPanRight;
/*0x12*/ u16 prevHeadsetPanLeft;
/*0x14*/ s32 samplePosInt;
/*0x18, 0x38*/ f32 portamentoFreqScale;
/*0x1C, 0x3C*/ f32 vibratoFreqScale;
/*0x20*/ u16 samplePosFrac;
/*0x24*/ struct AudioBankSound *sound;
/*0x28, 0x40*/ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/*0x34*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x38*/ f32 frequency;
/*0x3C*/ u16 targetVolLeft; // Q1.15, but will always be non-negative
/*0x3E*/ u16 targetVolRight; // Q1.15, but will always be non-negative
/*0x40*/ u8 reverbVol; // Q1.7
/*0x41*/ u8 unused1; // never read, set to 0x3f
/*0x44*/ struct NoteAttributes attributes;
/*0x54, 0x58*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
/*0x9C*/ s16 curVolLeft; // Q1.15, but will always be non-negative
/*0x9E*/ s16 curVolRight; // Q1.15, but will always be non-negative
/*0xA0*/ s16 reverbVolShifted; // Q1.15
/*0xA2*/ s16 unused2; // never read, set to 0
/*0xA4, 0x00*/ struct AudioListItem listItem;
/* */ u8 pad2[0xc];
}; // size = 0xC0
#endif
struct NoteSynthesisBuffers
{
s16 adpcmdecState[0x10];
s16 finalResampleState[0x10];
#ifdef VERSION_SH
s16 unk[0x10];
s16 filterBuffer[0x20];
s16 panSamplesBuffer[0x20];
#else
s16 mixEnvelopeState[0x28];
s16 panResampleState[0x10];
s16 panSamplesBuffer[0x20];
s16 dummyResampleState[0x10];
#if defined(VERSION_JP) || defined(VERSION_US)
s16 samples[0x40];
#endif
#endif
};
#ifdef VERSION_EU
struct ReverbSettingsEU
{
u8 downsampleRate;
u8 windowSize; // To be multiplied by 64
u16 gain;
};
#else
struct ReverbSettingsEU
{
u8 downsampleRate; // always 1
u8 windowSize; // To be multiplied by 16
u16 gain;
u16 unk4; // always zero
u16 unk6; // always zero
s8 unk8; // always -1
u16 unkA; // always 0x3000
s16 unkC; // always zero
s16 unkE; // always zero
};
#endif
struct AudioSessionSettingsEU
{
/* 0x00 */ u32 frequency;
/* 0x04 */ u8 unk1; // always 1
/* 0x05 */ u8 maxSimultaneousNotes;
/* 0x06 */ u8 numReverbs; // always 1
/* 0x07 */ u8 unk2; // always 0
/* 0x08 */ struct ReverbSettingsEU *reverbSettings;
/* 0x0C */ u16 volume;
/* 0x0E */ u16 unk3; // always 0
/* 0x10 */ u32 persistentSeqMem;
/* 0x14 */ u32 persistentBankMem;
#ifdef VERSION_SH
/* 0x18 */ u32 unk18; // always 0
#endif
/* 0x18, 0x1C */ u32 temporarySeqMem;
/* 0x1C, 0x20 */ u32 temporaryBankMem;
#ifdef VERSION_SH
/* 0x24 */ u32 unk24; // always 0
/* 0x28 */ u32 unkMem28; // always 0
/* 0x2C */ u32 unkMem2C; // always 0
#endif
}; // 0x30 on shindou
struct AudioSessionSettings
{
/*0x00*/ u32 frequency;
/*0x04*/ u8 maxSimultaneousNotes;
/*0x05*/ u8 reverbDownsampleRate; // always 1
/*0x06*/ u16 reverbWindowSize;
/*0x08*/ u16 reverbGain;
/*0x0A*/ u16 volume;
/*0x0C*/ u32 persistentSeqMem;
/*0x10*/ u32 persistentBankMem;
/*0x14*/ u32 temporarySeqMem;
/*0x18*/ u32 temporaryBankMem;
}; // size = 0x1C
struct AudioBufferParametersEU {
/*0x00*/ s16 presetUnk4; // audio frames per vsync?
/*0x02*/ u16 frequency;
/*0x04*/ u16 aiFrequency; // ?16
/*0x06*/ s16 samplesPerFrameTarget;
/*0x08*/ s16 maxAiBufferLength;
/*0x0A*/ s16 minAiBufferLength;
/*0x0C*/ s16 updatesPerFrame;
/*0x0E*/ s16 samplesPerUpdate;
/*0x10*/ s16 samplesPerUpdateMax;
/*0x12*/ s16 samplesPerUpdateMin;
/*0x14*/ f32 resampleRate; // contains 32000.0f / frequency
/*0x18*/ f32 updatesPerFrameInv; // 1.0f / updatesPerFrame
/*0x1C*/ f32 unkUpdatesPerFrameScaled; // 3.0f / (1280.0f * updatesPerFrame)
};
struct EuAudioCmd {
union {
#if IS_BIG_ENDIAN
struct {
u8 op;
u8 arg1;
u8 arg2;
u8 arg3;
} s;
#else
struct {
u8 arg3;
u8 arg2;
u8 arg1;
u8 op;
} s;
#endif
s32 first;
} u;
union {
s32 as_s32;
u32 as_u32;
f32 as_f32;
#if IS_BIG_ENDIAN
u8 as_u8;
s8 as_s8;
#else
struct {
u8 pad0[3];
u8 as_u8;
};
struct {
u8 pad1[3];
s8 as_s8;
};
#endif
} u2;
};
#ifdef VERSION_SH
struct PendingDmaSample {
u8 medium;
u8 bankId;
u8 idx;
uintptr_t devAddr;
void *vAddr;
u8 *resultSampleAddr;
s32 state;
s32 remaining;
s8 *io;
/*0x1C*/ struct AudioBankSample sample;
/*0x2C*/ OSMesgQueue queue;
/*0x44*/ OSMesg mesgs[1];
/*0x48*/ OSIoMesg ioMesg;
};
struct UnkStruct80343D00 {
u32 someIndex; // array into one of the two slots below
struct PendingDmaSample arr[2];
};
// in external.c
extern s32 D_SH_80343CF0;
extern struct UnkStruct80343D00 D_SH_80343D00;
#endif
#endif // AUDIO_INTERNAL_H
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
#ifndef AUDIO_LOAD_H
#define AUDIO_LOAD_H
#include <PR/ultratypes.h>
#include "internal.h"
#define AUDIO_FRAME_DMA_QUEUE_SIZE 0x40
#define PRELOAD_BANKS 2
#define PRELOAD_SEQUENCE 1
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone)
extern struct Note *gNotes;
// Music in SM64 is played using 3 players:
// gSequencePlayers[0] is level background music
// gSequencePlayers[1] is misc music, like the puzzle jingle
// gSequencePlayers[2] is sound
extern struct SequencePlayer gSequencePlayers[SEQUENCE_PLAYERS];
extern struct SequenceChannel gSequenceChannels[SEQUENCE_CHANNELS];
extern struct SequenceChannelLayer gSequenceLayers[SEQUENCE_LAYERS];
extern struct SequenceChannel gSequenceChannelNone;
extern struct AudioListItem gLayerFreeList;
extern struct NotePool gNoteFreeLists;
extern OSMesgQueue gCurrAudioFrameDmaQueue;
extern u32 gSampleDmaNumListItems;
extern ALSeqFile *gAlCtlHeader;
extern ALSeqFile *gAlTbl;
extern ALSeqFile *gSeqFileHeader;
extern u8 *gAlBankSets;
extern struct CtlEntry *gCtlEntries;
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct AudioBufferParametersEU gAudioBufferParameters;
#endif
extern s32 gAiFrequency;
#ifdef VERSION_SH
extern s16 gCurrAiBufferLength;
extern s32 D_SH_8034F68C;
#endif
extern s32 gMaxAudioCmds;
extern s32 gMaxSimultaneousNotes;
extern s32 gSamplesPerFrameTarget;
extern s32 gMinAiBufferLength;
extern s16 gTempoInternalToExternal;
extern s8 gAudioUpdatesPerFrame; // = 4
extern s8 gSoundMode;
#ifdef VERSION_SH
extern OSMesgQueue gUnkQueue1;
struct UnkStructSH8034EC88 {
u8 *endAndMediumIdentification;
struct AudioBankSample *sample;
u8 *ramAddr;
u32 encodedInfo;
s32 isFree;
};
struct PatchStruct {
s32 bankId1;
s32 bankId2;
void *baseAddr1;
void *baseAddr2;
s32 medium1;
s32 medium2;
};
extern struct UnkStructSH8034EC88 D_SH_8034EC88[0x80];
#endif
struct AudioBank *bank_load_immediate(s32 bankId, s32 arg1);
void audio_dma_partial_copy_async(uintptr_t *devAddr, u8 **vAddr, ssize_t *remaining, OSMesgQueue *queue, OSIoMesg *mesg);
void decrease_sample_dma_ttls(void);
#ifdef VERSION_SH
void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *dmaIndexRef, s32 medium);
#else
void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *dmaIndexRef);
#endif
void init_sample_dma_buffers(s32 arg0);
#if defined(VERSION_SH)
void patch_audio_bank(s32 bankId, struct AudioBank *mem, struct PatchStruct *patchInfo);
#else
void patch_audio_bank(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums);
#endif
#ifdef VERSION_SH
void preload_sequence(u32 seqId, s32 preloadMask);
#else
void preload_sequence(u32 seqId, u8 preloadMask);
#endif
void load_sequence(u32 player, u32 seqId, s32 loadAsync);
#ifdef VERSION_SH
void func_sh_802f3158(s32 seqId, s32 arg1, s32 arg2, OSMesgQueue *retQueue);
u8 *func_sh_802f3220(u32 seqId, u32 *a1);
struct AudioBankSample *func_sh_802f4978(s32 bankId, s32 idx);
s32 func_sh_802f47c8(s32 bankId, u8 idx, s8 *io);
void *func_sh_802f3f08(s32 poolIdx, s32 arg1, s32 arg2, s32 arg3, OSMesgQueue *retQueue);
void func_sh_802f41e4(s32 audioResetStatus);
BAD_RETURN(s32) func_sh_802f3368(s32 bankId);
void *func_sh_802f3764(s32 arg0, s32 idx, s32 *arg2);
s32 func_sh_802f3024(s32 bankId, s32 instId, s32 arg2);
void func_sh_802f30f4(s32 arg0, s32 arg1, s32 arg2, OSMesgQueue *arg3);
void func_sh_802f3288(s32 idx);
#endif
#endif // AUDIO_LOAD_H
+11
View File
@@ -0,0 +1,11 @@
#include "load_dat.h"
struct seqFile *gSoundDataADSR;
struct seqFile *gSoundDataRaw;
struct seqFile *gMusicData;
#ifndef VERSION_SH
unsigned char* gBankSetsData;
#endif
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "../tools/convTypes.h"
#include <stdlib.h>
extern struct seqFile *gSoundDataADSR;
extern struct seqFile *gSoundDataRaw;
extern struct seqFile *gMusicData;
#ifndef VERSION_SH
extern unsigned char *gBankSetsData;
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
#ifndef AUDIO_PLAYBACK_H
#define AUDIO_PLAYBACK_H
#include <PR/ultratypes.h>
#include "internal.h"
// Mask bits denoting where to allocate notes from, according to a channel's
// noteAllocPolicy. Despite being checked as bitmask bits, the bits are not
// orthogonal; rather, the smallest bit wins, except for NOTE_ALLOC_LAYER,
// which *is* orthogonal to the other. SEQ implicitly includes CHANNEL.
// If none of the CHANNEL/SEQ/GLOBAL_FREELIST bits are set, all three locations
// are tried.
#define NOTE_ALLOC_LAYER 1
#define NOTE_ALLOC_CHANNEL 2
#define NOTE_ALLOC_SEQ 4
#define NOTE_ALLOC_GLOBAL_FREELIST 8
void process_notes(void);
void seq_channel_layer_note_decay(struct SequenceChannelLayer *seqLayer);
void seq_channel_layer_note_release(struct SequenceChannelLayer *seqLayer);
void init_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer);
void init_note_lists(struct NotePool *pool);
void init_note_free_list(void);
void note_pool_clear(struct NotePool *pool);
void note_pool_fill(struct NotePool *pool, s32 count);
void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *item);
void audio_list_remove(struct AudioListItem *item);
struct Note *alloc_note(struct SequenceChannelLayer *seqLayer);
void reclaim_notes(void);
void note_init_all(void);
#if defined(VERSION_SH)
void note_set_vel_pan_reverb(struct Note *note, struct ReverbInfo *reverbInfo);
#elif defined(VERSION_EU)
void note_set_vel_pan_reverb(struct Note *note, f32 velocity, u8 pan, u8 reverbVol);
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
struct AudioBankSound *instrument_get_audio_bank_sound(struct Instrument *instrument, s32 semitone);
struct Instrument *get_instrument_inner(s32 bankId, s32 instId);
struct Drum *get_drum(s32 bankId, s32 drumId);
void note_init_volume(struct Note *note);
void note_set_frequency(struct Note *note, f32 frequency);
void note_enable(struct Note *note);
void note_disable(struct Note *note);
#endif
#endif // AUDIO_PLAYBACK_H
+351
View File
@@ -0,0 +1,351 @@
#include <ultra64.h>
#include "internal.h"
#include "load.h"
#include "data.h"
#include "seqplayer.h"
#include "synthesis.h"
#ifdef VERSION_EU
#ifdef __sgi
#define stubbed_printf
#else
#define stubbed_printf(...)
#endif
#define SAMPLES_TO_OVERPRODUCE 0x10
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
#ifdef VERSION_JP
typedef u16 FadeT;
#else
typedef s32 FadeT;
#endif
extern volatile u8 gAudioResetStatus;
extern u8 gAudioResetPresetIdToLoad;
extern OSMesgQueue *OSMesgQueues[];
extern struct EuAudioCmd sAudioCmd[0x100];
void func_8031D690(s32 player, FadeT fadeInTime);
void seq_player_fade_to_zero_volume(s32 player, FadeT fadeOutTime);
void decrease_sample_dma_ttls(void);
s32 audio_shut_down_and_reset_step(void);
void func_802ad7ec(u32);
#ifdef TARGET_N64
struct SPTask *create_next_audio_frame_task(void) {
u32 samplesRemainingInAI;
s32 writtenCmds;
s32 index;
OSTask_t *task;
s32 flags;
s16 *currAiBuffer;
s32 oldDmaCount;
OSMesg sp30;
OSMesg sp2C;
gAudioFrameCount++;
if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) {
stubbed_printf("DAC:Lost 1 Frame.\n");
return NULL;
}
osSendMesg(OSMesgQueues[0], (OSMesg) gAudioFrameCount, 0);
gAudioTaskIndex ^= 1;
gCurrAiBufferIndex++;
gCurrAiBufferIndex %= NUMAIBUFFERS;
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
samplesRemainingInAI = osAiGetLength() / 4;
if (gAiBufferLengths[index] != 0) {
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
}
oldDmaCount = gCurrAudioFrameDmaCount;
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
}
gCurrAudioFrameDmaCount = 0;
decrease_sample_dma_ttls();
if (osRecvMesg(OSMesgQueues[2], &sp30, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (s32) sp30;
gAudioResetStatus = 5;
}
if (gAudioResetStatus != 0) {
if (audio_shut_down_and_reset_step() == 0) {
if (gAudioResetStatus == 0) {
osSendMesg(OSMesgQueues[3], (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK);
}
return NULL;
}
}
gAudioTask = &gAudioTasks[gAudioTaskIndex];
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
index = gCurrAiBufferIndex;
currAiBuffer = gAiBuffers[index];
gAiBufferLengths[index] = ((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE;
if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength;
}
if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength;
}
if (osRecvMesg(OSMesgQueues[1], &sp2C, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) sp2C);
}
flags = 0;
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
index = gAudioTaskIndex;
gAudioTask->msgqueue = NULL;
gAudioTask->msg = NULL;
task = &gAudioTask->task.t;
task->type = M_AUDTASK;
task->flags = flags;
task->ucode_boot = rspF3DBootStart;
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
task->ucode = rspAspMainStart;
task->ucode_data = rspAspMainDataStart;
task->ucode_size = 0x800; // (this size is ignored)
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
task->dram_stack = NULL;
task->dram_stack_size = 0;
task->output_buff = NULL;
task->output_buff_size = NULL;
task->data_ptr = gAudioCmdBuffers[index];
task->data_size = writtenCmds * sizeof(u64);
task->yield_data_ptr = NULL;
task->yield_data_size = 0;
return gAudioTask;
}
#else
struct SPTask *create_next_audio_frame_task(void) {
return NULL;
}
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
s32 writtenCmds;
OSMesg msg;
gAudioFrameCount++;
decrease_sample_dma_ttls();
if (osRecvMesg(OSMesgQueues[2], &msg, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (intptr_t) msg;
gAudioResetStatus = 5;
}
if (gAudioResetStatus != 0) {
audio_reset_session();
gAudioResetStatus = 0;
}
if (osRecvMesg(OSMesgQueues[1], &msg, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) msg);
}
synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
}
#endif
void eu_process_audio_cmd(struct EuAudioCmd *cmd) {
s32 i;
switch (cmd->u.s.op) {
case 0x81:
preload_sequence(cmd->u.s.arg2, 3);
break;
case 0x82:
case 0x88:
load_sequence(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
func_8031D690(cmd->u.s.arg1, cmd->u2.as_s32);
break;
case 0x83:
if (gSequencePlayers[cmd->u.s.arg1].enabled != FALSE) {
if (cmd->u2.as_s32 == 0) {
sequence_player_disable(&gSequencePlayers[cmd->u.s.arg1]);
}
else {
seq_player_fade_to_zero_volume(cmd->u.s.arg1, cmd->u2.as_s32);
}
}
break;
case 0xf0:
gSoundMode = cmd->u2.as_s32;
break;
case 0xf1:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = TRUE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf2:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = FALSE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
}
}
const char undefportcmd[] = "Undefined Port Command %d\n";
extern OSMesgQueue *OSMesgQueues[];
extern u8 D_EU_80302010;
extern u8 D_EU_80302014;
extern OSMesg OSMesg0;
extern OSMesg OSMesg1;
extern OSMesg OSMesg2;
extern OSMesg OSMesg3;
void seq_player_fade_to_zero_volume(s32 player, FadeT fadeOutTime) {
if (fadeOutTime == 0) {
fadeOutTime = 1;
}
gSequencePlayers[player].fadeVelocity = -(gSequencePlayers[player].fadeVolume / fadeOutTime);
gSequencePlayers[player].state = 2;
gSequencePlayers[player].fadeRemainingFrames = fadeOutTime;
}
void func_8031D690(s32 player, FadeT fadeInTime) {
if (fadeInTime != 0) {
gSequencePlayers[player].state = 1;
gSequencePlayers[player].fadeTimerUnkEu = fadeInTime;
gSequencePlayers[player].fadeRemainingFrames = fadeInTime;
gSequencePlayers[player].fadeVolume = 0.0f;
gSequencePlayers[player].fadeVelocity = 0.0f;
}
}
void port_eu_init_queues(void) {
D_EU_80302010 = 0;
D_EU_80302014 = 0;
osCreateMesgQueue(OSMesgQueues[0], &OSMesg0, 1);
osCreateMesgQueue(OSMesgQueues[1], &OSMesg1, 4);
osCreateMesgQueue(OSMesgQueues[2], &OSMesg2, 1);
osCreateMesgQueue(OSMesgQueues[3], &OSMesg3, 1);
}
void func_802ad6f0(s32 arg0, s32 *arg1) {
struct EuAudioCmd *cmd = &sAudioCmd[D_EU_80302010 & 0xff];
cmd->u.first = arg0;
cmd->u2.as_u32 = *arg1;
D_EU_80302010++;
}
void func_802ad728(u32 arg0, f32 arg1) {
func_802ad6f0(arg0, (s32*) &arg1);
}
void func_802ad74c(u32 arg0, u32 arg1) {
func_802ad6f0(arg0, (s32*) &arg1);
}
void func_802ad770(u32 arg0, s8 arg1) {
s32 sp1C = arg1 << 24;
func_802ad6f0(arg0, &sp1C);
}
void func_802ad7a0(void) {
osSendMesg(OSMesgQueues[1],
(OSMesg)(u32)((D_EU_80302014 & 0xff) << 8 | (D_EU_80302010 & 0xff)),
OS_MESG_NOBLOCK);
D_EU_80302014 = D_EU_80302010;
}
void func_802ad7ec(u32 arg0) {
struct EuAudioCmd *cmd;
struct SequencePlayer *seqPlayer;
struct SequenceChannel *chan;
u8 end = arg0 & 0xff;
u8 i = (arg0 >> 8) & 0xff;
for (;;) {
if (i == end) break;
cmd = &sAudioCmd[i++ & 0xff];
if (cmd->u.s.arg1 < SEQUENCE_PLAYERS) {
seqPlayer = &gSequencePlayers[cmd->u.s.arg1];
if ((cmd->u.s.op & 0x80) != 0) {
eu_process_audio_cmd(cmd);
}
else if ((cmd->u.s.op & 0x40) != 0) {
switch (cmd->u.s.op) {
case 0x41:
seqPlayer->fadeVolumeScale = cmd->u2.as_f32;
seqPlayer->recalculateVolume = TRUE;
break;
case 0x47:
seqPlayer->tempo = cmd->u2.as_s32 * TATUMS_PER_BEAT;
break;
case 0x48:
seqPlayer->transposition = cmd->u2.as_s8;
break;
case 0x46:
seqPlayer->seqVariationEu[cmd->u.s.arg3] = cmd->u2.as_s8;
break;
}
}
else if (seqPlayer->enabled != FALSE && cmd->u.s.arg2 < 0x10) {
chan = seqPlayer->channels[cmd->u.s.arg2];
if (IS_SEQUENCE_CHANNEL_VALID(chan))
{
switch (cmd->u.s.op) {
case 1:
chan->volumeScale = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
break;
case 2:
chan->volume = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
break;
case 3:
chan->newPan = cmd->u2.as_s8;
chan->changes.as_bitfields.pan = TRUE;
break;
case 4:
chan->freqScale = cmd->u2.as_f32;
chan->changes.as_bitfields.freqScale = TRUE;
break;
case 5:
chan->reverbVol = cmd->u2.as_s8;
break;
case 6:
if (cmd->u.s.arg3 < 8) {
chan->soundScriptIO[cmd->u.s.arg3] = cmd->u2.as_s8;
}
break;
case 8:
chan->stopSomething2 = cmd->u2.as_s8;
}
}
}
}
cmd->u.s.op = 0;
}
}
void port_eu_init(void) {
port_eu_init_queues();
}
#endif
+597
View File
@@ -0,0 +1,597 @@
#ifdef VERSION_SH
// TODO: merge this with port_eu.c?
#include <ultra64.h>
#include "data.h"
#include "heap.h"
#include "load.h"
#include "synthesis.h"
#include "internal.h"
#include "seqplayer.h"
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x80
#define SAMPLES_TO_OVERPRODUCE 0x10
extern s32 D_SH_80314FC8;
extern struct SPTask *D_SH_80314FCC;
extern u8 D_SH_80315098;
extern u8 D_SH_8031509C;
extern OSMesgQueue *D_SH_80350F68;
void func_8031D690(s32 playerIndex, s32 numFrames);
void seq_player_fade_to_zero_volume(s32 arg0, s32 numFrames);
void func_802ad7ec(u32 arg0);
#ifdef TARGET_N64
struct SPTask *create_next_audio_frame_task(void) {
u32 samplesRemainingInAI;
s32 writtenCmds;
s32 index;
OSTask_t *task;
s32 flags;
s16 *currAiBuffer;
s32 oldDmaCount;
s32 sp38;
s32 sp34;
s32 writtenCmdsCopy;
gAudioFrameCount++;
if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) {
if ((gAudioFrameCount % gAudioBufferParameters.presetUnk4) + 1 == gAudioBufferParameters.presetUnk4) {
return D_SH_80314FCC;
}
return NULL;
}
osSendMesg(D_SH_80350F38, (OSMesg) gAudioFrameCount, OS_MESG_NOBLOCK);
gAudioTaskIndex ^= 1;
gCurrAiBufferIndex++;
gCurrAiBufferIndex %= NUMAIBUFFERS;
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
samplesRemainingInAI = osAiGetLength() / 4;
if (gAudioLoadLockSH < 0x10U) {
if (gAiBufferLengths[index] != 0) {
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
}
}
oldDmaCount = gCurrAudioFrameDmaCount;
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
}
gCurrAudioFrameDmaCount = 0;
decrease_sample_dma_ttls();
func_sh_802f41e4(gAudioResetStatus);
if (osRecvMesg(D_SH_80350F88, (OSMesg *) &sp38, OS_MESG_NOBLOCK) != -1) {
if (gAudioResetStatus == 0) {
gAudioResetStatus = 5;
}
gAudioResetPresetIdToLoad = (u8) sp38;
}
if (gAudioResetStatus != 0) {
if (audio_shut_down_and_reset_step() == 0) {
if (gAudioResetStatus == 0) {
osSendMesg(D_SH_80350FA8, (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK);
}
D_SH_80314FCC = 0;
return NULL;
}
}
if (gAudioLoadLockSH >= 0x11U) {
return NULL;
}
if (gAudioLoadLockSH != 0) {
gAudioLoadLockSH++;
}
gAudioTask = &gAudioTasks[gAudioTaskIndex];
gAudioCmd = (u64 *) gAudioCmdBuffers[gAudioTaskIndex];
index = gCurrAiBufferIndex;
currAiBuffer = gAiBuffers[index];
gAiBufferLengths[index] = (s16) ((((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI) +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE);
if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength;
}
if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength;
}
if (osRecvMesg(D_SH_80350F68, (OSMesg *) &sp34, 0) != -1) {
do {
func_802ad7ec(sp34);
} while (osRecvMesg(D_SH_80350F68, (OSMesg *) &sp34, 0) != -1);
}
flags = 0;
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]);
gAudioRandom = (u32) (osGetCount() * (gAudioRandom + gAudioFrameCount));
gAudioRandom = (u32) (gAiBuffers[index][gAudioFrameCount & 0xFF] + gAudioRandom);
index = gAudioTaskIndex;
gAudioTask->msgqueue = NULL;
gAudioTask->msg = NULL;
task = &gAudioTask->task.t;
task->type = M_AUDTASK;
task->flags = flags;
task->ucode_boot = rspF3DBootStart;
task->ucode_boot_size = (u8 *) rspF3DStart - (u8 *) rspF3DBootStart;
task->ucode = rspAspMainStart;
task->ucode_data = rspAspMainDataStart;
task->ucode_size = 0x1000;
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
task->dram_stack = NULL;
task->dram_stack_size = 0;
task->output_buff = NULL;
task->output_buff_size = NULL;
task->data_ptr = gAudioCmdBuffers[index];
task->data_size = writtenCmds * sizeof(u64);
task->yield_data_ptr = NULL;
task->yield_data_size = 0;
writtenCmdsCopy = writtenCmds;
if (D_SH_80314FC8 < writtenCmdsCopy) {
D_SH_80314FC8 = writtenCmdsCopy;
}
if (gAudioBufferParameters.presetUnk4 == 1) {
return gAudioTask;
} else {
D_SH_80314FCC = gAudioTask;
return NULL;
}
}
#else
struct SPTask *create_next_audio_frame_task(void) {
return NULL;
}
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
s32 writtenCmds;
OSMesg msg;
gAudioFrameCount++;
decrease_sample_dma_ttls();
if (osRecvMesg(D_SH_80350F88, &msg, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (intptr_t) msg;
if (gAudioResetStatus == 0) {
gAudioResetStatus = 5;
}
}
if (gAudioResetStatus != 0) {
audio_reset_session();
gAudioResetStatus = 0;
}
while (osRecvMesg(D_SH_80350F68, &msg, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) msg);
}
synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
gCurrAudioFrameDmaCount = 0;
}
#endif
void eu_process_audio_cmd(struct EuAudioCmd *cmd) {
s32 i;
struct Note *note;
struct NoteSubEu *sub;
switch (cmd->u.s.op) {
case 0x81:
preload_sequence(cmd->u.s.arg2, 3);
break;
case 0x82:
case 0x88:
load_sequence(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
func_8031D690(cmd->u.s.arg1, cmd->u2.as_s32);
break;
case 0x83:
if (gSequencePlayers[cmd->u.s.arg1].enabled != FALSE) {
if (cmd->u2.as_s32 == 0) {
sequence_player_disable(&gSequencePlayers[cmd->u.s.arg1]);
}
else {
seq_player_fade_to_zero_volume(cmd->u.s.arg1, cmd->u2.as_s32);
}
}
break;
case 0x84:
break;
case 0xf0:
gSoundMode = cmd->u2.as_s32;
break;
case 0xf1:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = TRUE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf2:
if (cmd->u2.as_s32 == 1) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
note = &gNotes[i];
sub = &note->noteSubEu;
if (note->noteSubEu.enabled && note->unkSH34 == 0) {
if ((note->parentLayer->seqChannel->muteBehavior & 8) != 0) {
sub->finished = TRUE;
}
}
}
}
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = FALSE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf3:
func_sh_802f3024(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
break;
case 0xf4:
func_sh_802f30f4(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3, &gUnkQueue1);
break;
case 0xf5:
func_sh_802f3158(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3, &gUnkQueue1);
break;
case 0xf6:
func_sh_802f3288(cmd->u.s.arg2);
break;
}
}
void seq_player_fade_to_zero_volume(s32 arg0, s32 fadeOutTime) {
struct SequencePlayer *player;
if (fadeOutTime == 0) {
fadeOutTime = 1;
}
player = &gSequencePlayers[arg0];
player->state = 2;
player->fadeRemainingFrames = fadeOutTime;
player->fadeVelocity = -(player->fadeVolume / (f32) fadeOutTime);
}
void func_8031D690(s32 playerIndex, s32 fadeInTime) {
struct SequencePlayer *player;
if (fadeInTime != 0) {
player = &gSequencePlayers[playerIndex];
player->state = 1;
player->fadeTimerUnkEu = fadeInTime;
player->fadeRemainingFrames = fadeInTime;
player->fadeVolume = 0.0f;
player->fadeVelocity = 0.0f;
}
}
void port_eu_init_queues(void) {
D_SH_80350F18 = 0;
D_SH_80350F19 = 0;
D_SH_80350F38 = &D_SH_80350F20;
D_SH_80350F68 = &D_SH_80350F50;
D_SH_80350F88 = &D_SH_80350F70;
D_SH_80350FA8 = &D_SH_80350F90;
osCreateMesgQueue(D_SH_80350F38, D_SH_80350F1C, 1);
osCreateMesgQueue(D_SH_80350F68, D_SH_80350F40, 4);
osCreateMesgQueue(D_SH_80350F88, D_SH_80350F6C, 1);
osCreateMesgQueue(D_SH_80350FA8, D_SH_80350F8C, 1);
}
extern struct EuAudioCmd sAudioCmd[0x100];
void func_802ad6f0(s32 arg0, s32 *arg1) {
struct EuAudioCmd *cmd = &sAudioCmd[D_SH_80350F18 & 0xff];
cmd->u.first = arg0;
cmd->u2.as_u32 = *arg1;
D_SH_80350F18++;
if (D_SH_80350F18 == D_SH_80350F19) {
D_SH_80350F18--;
}
}
void func_802ad728(u32 arg0, f32 arg1) {
func_802ad6f0(arg0, (s32 *) &arg1);
}
void func_802ad74c(u32 arg0, u32 arg1) {
func_802ad6f0(arg0, (s32 *) &arg1);
}
void func_802ad770(u32 arg0, s8 arg1) {
s32 sp1C = arg1 << 24;
func_802ad6f0(arg0, &sp1C);
}
char shindouDebugPrint133[] = "AudioSend: %d -> %d (%d)\n";
void func_sh_802F64C8(void) {
static s32 D_SH_8031503C = 0;
s32 mesg;
if (((D_SH_80350F18 - D_SH_80350F19 + 0x100) & 0xff) > D_SH_8031503C) {
D_SH_8031503C = (D_SH_80350F18 - D_SH_80350F19 + 0x100) & 0xff;
}
mesg = ((D_SH_80350F19 & 0xff) << 8) | (D_SH_80350F18 & 0xff);
osSendMesg(D_SH_80350F68, (OSMesg)mesg, OS_MESG_NOBLOCK);
D_SH_80350F19 = D_SH_80350F18;
}
void func_sh_802f6540(void) {
D_SH_80350F19 = D_SH_80350F18;
}
void func_802ad7ec(u32 arg0) {
struct EuAudioCmd *cmd;
struct SequencePlayer *seqPlayer;
struct SequenceChannel *chan;
u8 end;
UNUSED static char shindouDebugPrint134[] = "Continue Port\n";
UNUSED static char shindouDebugPrint135[] = "%d -> %d\n";
UNUSED static char shindouDebugPrint136[] = "Sync-Frame Break. (Remain %d)\n";
UNUSED static char shindouDebugPrint137[] = "Undefined Port Command %d\n";
static u8 D_SH_80315098 = 0;
static u8 D_SH_8031509C = 0;
if (D_SH_8031509C == 0) {
D_SH_80315098 = (arg0 >> 8) & 0xff;
}
end = arg0 & 0xff;
for (;;) {
if (D_SH_80315098 == end) {
D_SH_8031509C = 0;
break;
}
cmd = &sAudioCmd[D_SH_80315098 & 0xff];
D_SH_80315098++;
if (cmd->u.s.op == 0xf8) {
D_SH_8031509C = 1;
break;
}
else if ((cmd->u.s.op & 0xf0) == 0xf0) {
eu_process_audio_cmd(cmd);
}
else if (cmd->u.s.arg1 < SEQUENCE_PLAYERS) {
seqPlayer = &gSequencePlayers[cmd->u.s.arg1];
if ((cmd->u.s.op & 0x80) != 0) {
eu_process_audio_cmd(cmd);
}
else if ((cmd->u.s.op & 0x40) != 0) {
switch (cmd->u.s.op) {
case 0x41:
if (seqPlayer->fadeVolumeScale != cmd->u2.as_f32) {
seqPlayer->fadeVolumeScale = cmd->u2.as_f32;
seqPlayer->recalculateVolume = TRUE;
}
break;
case 0x47:
seqPlayer->tempo = cmd->u2.as_s32 * TATUMS_PER_BEAT;
break;
case 0x49:
seqPlayer->tempoAdd = cmd->u2.as_s32 * TEMPO_SCALE;
break;
case 0x48:
seqPlayer->transposition = cmd->u2.as_s8;
break;
case 0x46:
seqPlayer->seqVariationEu[cmd->u.s.arg3] = cmd->u2.as_s8;
break;
}
}
else if (seqPlayer->enabled != FALSE && cmd->u.s.arg2 < 0x10) {
chan = seqPlayer->channels[cmd->u.s.arg2];
if (IS_SEQUENCE_CHANNEL_VALID(chan))
{
switch (cmd->u.s.op) {
case 1:
if (chan->volumeScale != cmd->u2.as_f32) {
chan->volumeScale = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
}
break;
case 2:
if (chan->volume != cmd->u2.as_f32) {
chan->volume = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
}
break;
case 3:
if (chan->newPan != cmd->u2.as_s8) {
chan->newPan = cmd->u2.as_s8;
chan->changes.as_bitfields.pan = TRUE;
}
break;
case 4:
if (chan->freqScale != cmd->u2.as_f32) {
chan->freqScale = cmd->u2.as_f32;
chan->changes.as_bitfields.freqScale = TRUE;
}
break;
case 5:
//! @bug u8 s8 comparison (but harmless)
if (chan->reverbVol != cmd->u2.as_s8) {
chan->reverbVol = cmd->u2.as_s8;
}
break;
case 6:
if (cmd->u.s.arg3 < 8) {
chan->soundScriptIO[cmd->u.s.arg3] = cmd->u2.as_s8;
}
break;
case 8:
chan->stopSomething2 = cmd->u2.as_s8;
break;
case 9:
chan->muteBehavior = cmd->u2.as_s8;
}
}
}
}
cmd->u.s.op = 0;
}
}
u32 func_sh_802f6878(s32 *arg0) {
u32 sp1C;
if (osRecvMesg(&gUnkQueue1, (OSMesg *) &sp1C, 0) == -1) {
*arg0 = 0;
return 0U;
}
*arg0 = (s32) (sp1C & 0xFFFFFF);
return sp1C >> 0x18;
}
u8 *func_sh_802f68e0(u32 index, u32 *a1) {
return func_sh_802f3220(index, a1);
}
s32 func_sh_802f6900(void) {
s32 ret;
s32 sp18;
ret = osRecvMesg(D_SH_80350FA8, (OSMesg *) &sp18, 0);
if (ret == -1) {
return 0;
}
if (sp18 != gAudioResetPresetIdToLoad) {
return 0;
} else {
return 1;
}
}
// TODO: (Scrub C)
void func_sh_802f6958(OSMesg mesg) {
s32 a;
OSMesg recvMesg;
do {
a = -1;
} while (osRecvMesg(D_SH_80350FA8, &recvMesg, OS_MESG_NOBLOCK) != a);
func_sh_802f6540();
osSendMesg(D_SH_80350F88, mesg, OS_MESG_NOBLOCK);
}
void func_sh_802f69cc(void) {
gAudioLoadLockSH = 1;
func_sh_802f6958(0);
gAudioResetStatus = 0;
}
s32 func_sh_802f6a08(s32 playerIndex, s32 channelIndex, s32 soundScriptIOIndex) {
struct SequenceChannel *seqChannel;
struct SequencePlayer *player;
player = &gSequencePlayers[playerIndex];
if (player->enabled) {
seqChannel = player->channels[channelIndex];
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel)) {
return seqChannel->soundScriptIO[soundScriptIOIndex];
}
}
return -1;
}
s8 func_sh_802f6a6c(s32 playerIndex, s32 index) {
return gSequencePlayers[playerIndex].seqVariationEu[index];
}
void port_eu_init(void) {
port_eu_init_queues();
}
char shindouDebugPrint138[] = "specchg conjunction error (Msg:%d Cur:%d)\n";
char shindouDebugPrint139[] = "Error : Queue is not empty ( %x ) \n";
char shindouDebugPrint140[] = "Audio: setvol: volume minus %f\n";
char shindouDebugPrint141[] = "Audio: setvol: volume overflow %f\n";
char shindouDebugPrint142[] = "Audio: setpitch: pitch zero or minus %f\n";
char shindouDebugPrint143[] = "----------------------Double-Error CH: %x %f\n";
char shindouDebugPrint144[] = "----------------------Double-Error NT: %x\n";
char shindouDebugPrint145[] = "CAUTION:SUB IS SEPARATED FROM GROUP\n";
char shindouDebugPrint146[] = "CAUTION:PAUSE EMERGENCY\n";
char shindouDebugPrint147[] = "Error:Wait Track disappear\n";
char shindouDebugPrint148[] = "Audio: voiceman: No bank error %d\n";
char shindouDebugPrint149[] = "Audio: voiceman: progNo. overflow %d,%d\n";
char shindouDebugPrint150[] = "ptr2 %x\n";
char shindouDebugPrint151[] = "Audio: voiceman: progNo. undefined %d,%d\n";
char shindouDebugPrint152[] = "Audio: voiceman: No bank error %d\n";
char shindouDebugPrint153[] = "Audio: voiceman: Percussion Overflow %d,%d\n";
char shindouDebugPrint154[] = "Audio: voiceman: Percussion table pointer (bank %d) is irregular %x.\n";
char shindouDebugPrint155[] = "Audio: voiceman: Percpointer NULL %d,%d\n";
char shindouDebugPrint156[] = "--4 %x\n";
char shindouDebugPrint157[] = "NoteOff Comes during wait release %x (note %x)\n";
char shindouDebugPrint158[] = "Slow Release Batting\n";
u8 euUnknownData_8030194c[4] = { 0x40, 0x20, 0x10, 0x08 };
char shindouDebugPrint159[] = "Audio:Wavemem: Bad voiceno (%d)\n";
char shindouDebugPrint160[] = "Audio: C-Alloc : Dealloc voice is NULL\n";
char shindouDebugPrint161[] = "Alloc Error:Dim voice-Alloc %d";
char shindouDebugPrint162[] = "Error:Same List Add\n";
char shindouDebugPrint163[] = "Already Cut\n";
char shindouDebugPrint164[] = "Audio: C-Alloc : lowerPrio is NULL\n";
char shindouDebugPrint165[] = "Intterupt UseStop %d (Kill %d)\n";
char shindouDebugPrint166[] = "Intterupt RelWait %d (Kill %d)\n";
char shindouDebugPrint167[] = "Drop Voice (Prio %x)\n";
s32 D_SH_803154CC = 0; // file boundary
// effects.c
char shindouDebugPrint168[] = "Audio:Envp: overflow %f\n";
s32 D_SH_803154EC = 0; // file boundary
// seqplayer.c
char shindouDebugPrint169[] = "Audio:Track:Warning: No Free Notetrack\n";
char shindouDebugPrint170[] = "SUBTRACK DIM\n";
char shindouDebugPrint171[] = "Audio:Track: Warning :SUBTRACK had been stolen by other Group.\n";
char shindouDebugPrint172[] = "SEQID %d,BANKID %d\n";
char shindouDebugPrint173[] = "ERR:SUBTRACK %d NOT ALLOCATED\n";
char shindouDebugPrint174[] = "Stop Release\n";
char shindouDebugPrint175[] = "Error:Same List Add\n";
char shindouDebugPrint176[] = "Wait Time out!\n";
char shindouDebugPrint177[] = "Macro Level Over Error!\n";
char shindouDebugPrint178[] = "Macro Level Over Error!\n"; // Again
char shindouDebugPrint179[] = "WARNING: NPRG: cannot change %d\n";
char shindouDebugPrint180[] = "Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n";
char shindouDebugPrint181[] = "Error: Subtrack no prg.\n";
char shindouDebugPrint182[] = "ERR %x\n";
char shindouDebugPrint183[] = "Note OverFlow %d\n";
char shindouDebugPrint184[] = "trs %d , %d, %d\n";
char shindouDebugPrint185[] = "Audio: Note:Velocity Error %d\n";
char shindouDebugPrint186[] = "Audio:Track :Call Macro Level Over Error!\n";
char shindouDebugPrint187[] = "Audio:Track :Loops Macro Level Over Error!\n";
char shindouDebugPrint188[] = "SUB:ERR:BANK %d NOT CACHED.\n";
char shindouDebugPrint189[] = "SUB:ERR:BANK %d NOT CACHED.\n";
char shindouDebugPrint190[] = "Audio:Track: CTBLCALL Macro Level Over Error!\n";
char shindouDebugPrint191[] = "Set Noise %d\n";
char shindouDebugPrint192[] = "[%2x] \n";
char shindouDebugPrint193[] = "Err :Sub %x ,address %x:Undefined SubTrack Function %x";
char shindouDebugPrint194[] = "VoiceLoad Error Bank:%d,Prog:%d\n";
char shindouDebugPrint195[] = "Disappear Sequence or Bank %d\n";
char shindouDebugPrint196[] = "[FIN] group.\n";
char shindouDebugPrint197[] = "Macro Level Over Error!\n";
char shindouDebugPrint198[] = "Macro Level Over Error!\n";
char shindouDebugPrint199[] = "Group:Undefine upper C0h command (%x)\n";
char shindouDebugPrint200[] = "Group:Undefined Command\n";
#endif
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
#ifndef AUDIO_SEQPLAYER_H
#define AUDIO_SEQPLAYER_H
#include <PR/ultratypes.h>
#include "internal.h"
#include "playback.h"
void seq_channel_layer_disable(struct SequenceChannelLayer *seqPlayer);
void sequence_channel_disable(struct SequenceChannel *seqPlayer);
void sequence_player_disable(struct SequencePlayer* seqPlayer);
void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item);
void *audio_list_pop_back(struct AudioListItem *list);
void process_sequences(s32 iterationsRemaining);
void init_sequence_player(u32 player);
void init_sequence_players(void);
#endif // AUDIO_SEQPLAYER_H
+148
View File
@@ -0,0 +1,148 @@
#include <ultra64.h>
#ifdef VERSION_SH
// synthesis.c
char shindouDebugPrint1[] = "Terminate-Canceled Channel %d,Phase %d\n";
char shindouDebugPrint2[] = "S->W\n";
char shindouDebugPrint3[] = "W->S\n";
char shindouDebugPrint4[] = "S-Resample Pitch %x (old %d -> delay %d)\n";
s32 shindouDebugPrintPadding1[] = {0,0,0};
// heap.c
char shindouDebugPrint5[] = "Warning:Kill Note %x \n";
char shindouDebugPrint6[] = "Kill Voice %d (ID %d) %d\n";
char shindouDebugPrint7[] = "Warning: Running Sequence's data disappear!\n";
char shindouDebugPrint8[] = "%x %x %x\n";
char shindouDebugPrint9[] = "Audio:Memory:Heap OverFlow : Not Allocate %d!\n";
char shindouDebugPrint10[] = "%x %x %x\n"; // Again
char shindouDebugPrint11[] = "Audio:Memory:Heap OverFlow : Not Allocate %d!\n"; // Again
char shindouDebugPrint12[] = "Audio:Memory:DataHeap Not Allocate \n";
char shindouDebugPrint13[] = "StayHeap Not Allocate %d\n";
char shindouDebugPrint14[] = "AutoHeap Not Allocate %d\n";
char shindouDebugPrint15[] = "Status ID0 : %d ID1 : %d\n";
char shindouDebugPrint16[] = "id 0 is Stopping\n";
char shindouDebugPrint17[] = "id 0 is Stop\n";
char shindouDebugPrint18[] = "id 1 is Stopping\n";
char shindouDebugPrint19[] = "id 1 is Stop\n";
char shindouDebugPrint20[] = "WARNING: NO FREE AUTOSEQ AREA.\n";
char shindouDebugPrint21[] = "WARNING: NO STOP AUTO AREA.\n";
char shindouDebugPrint22[] = " AND TRY FORCE TO STOP SIDE \n";
char shindouDebugPrint23[] = "Check ID0 (seq ID %d) Useing ...\n";
char shindouDebugPrint24[] = "Check ID1 (seq ID %d) Useing ...\n";
char shindouDebugPrint25[] = "No Free Seq area.\n";
char shindouDebugPrint26[] = "CH %d: ID %d\n";
char shindouDebugPrint27[] = "TWO SIDES ARE LOADING... ALLOC CANCELED.\n";
char shindouDebugPrint28[] = "WARNING: Before Area Overlaid After.";
char shindouDebugPrint29[] = "WARNING: After Area Overlaid Before.";
char shindouDebugPrint30[] = "MEMORY:SzHeapAlloc ERROR: sza->side %d\n";
char shindouDebugPrint31[] = "Audio:MEMORY:SzHeap Overflow error. (%d bytes)\n";
char shindouDebugPrint32[] = "Auto Heap Unhit for ID %d\n";
char shindouDebugPrint33[] = "Heap Reconstruct Start %x\n";
char shindouDebugPrint34[] = "---------------------------------------TEMPO %d %f\n";
char shindouDebugPrint35[] = "%f \n";
char shindouDebugPrint36[] = "%f \n"; // Again
char shindouDebugPrint37[] = "AHPBASE %x\n";
char shindouDebugPrint38[] = "AHPCUR %x\n";
char shindouDebugPrint39[] = "HeapTop %x\n";
char shindouDebugPrint40[] = "SynoutRate %d / %d \n";
char shindouDebugPrint41[] = "FXSIZE %d\n";
char shindouDebugPrint42[] = "FXCOMP %d\n";
char shindouDebugPrint43[] = "FXDOWN %d\n";
char shindouDebugPrint44[] = "WaveCacheLen: %d\n";
char shindouDebugPrint45[] = "SpecChange Finished\n";
char shindouDebugPrint46[] = "Warning:Emem Over,not alloc %d\n";
char shindouDebugPrint47[] = "Single AutoSize %d\n";
char shindouDebugPrint48[] = "Single Ptr %x\n";
char shindouDebugPrint49[] = "Request--------Single-Auto, %d\n";
char shindouDebugPrint50[] = "Retry %x, %x, len %x\n";
char shindouDebugPrint51[] = "DMAing list %d is killed.\n";
char shindouDebugPrint52[] = "Try Kill %d \n";
char shindouDebugPrint53[] = "Try Kill %x %x\n";
char shindouDebugPrint54[] = "Try Kill %x %x %x\n";
char shindouDebugPrint55[] = "Rom back %x %x \n";
char shindouDebugPrint56[] = "Error sw NULL \n";
char shindouDebugPrint57[] = "Request--------Single-Stay, %d\n";
char shindouDebugPrint58[] = "Try Kill %d \n";
char shindouDebugPrint59[] = "Try Kill %x %x\n";
char shindouDebugPrint60[] = "Try Kill %x %x %x\n";
s32 shindouDebugPrintPadding[] = {0, 0, 0};
// load.c
char shindouDebugPrint61[] = "CAUTION:WAVE CACHE FULL %d";
char shindouDebugPrint62[] = "SUPERDMA";
char shindouDebugPrint63[] = "Bank Change... top %d lba %d\n";
char shindouDebugPrint64[] = "BankCount %d\n";
char shindouDebugPrint65[] = "BANK LOAD MISS! FOR %d\n";
char shindouDebugPrint66[] = "BankCount %d\n";
char shindouDebugPrint67[] = "Flush Start\n";
char shindouDebugPrint68[] = "%d ->%d\n";
char shindouDebugPrint69[] = "useflag %d\n";
char shindouDebugPrint70[] = "BankCount %d\n";
char shindouDebugPrint71[] = "%2x ";
char shindouDebugPrint72[] = "StartSeq (Group %d,Seq %d) Process finish\n";
char shindouDebugPrint73[] = "LoadCtrl, Ptr %x and Media is %d\n";
char shindouDebugPrint74[] = "Load Bank, Type %d , ID %d\n";
char shindouDebugPrint75[] = "get auto\n";
char shindouDebugPrint76[] = "get s-auto %x\n";
char shindouDebugPrint77[] = "Seq %d Write ID OK %d!\n";
char shindouDebugPrint78[] = "Banknumber %d\n";
char shindouDebugPrint79[] = "Bank Offset %x %d %d\n";
char shindouDebugPrint80[] = "PEP Touch %x \n";
char shindouDebugPrint81[] = "FastCopy";
char shindouDebugPrint82[] = "FastCopy";
char shindouDebugPrint83[] = "Error: Cannot DMA Media [%d]\n";
char shindouDebugPrint84[] = "Warning: size not align 16 %x (%s)\n";
char shindouDebugPrint85[] = "Load Bank BG, Type %d , ID %d\n";
char shindouDebugPrint86[] = "get auto\n";
char shindouDebugPrint87[] = "get s-auto %x\n";
char shindouDebugPrint88[] = "Clear Workarea %x -%x size %x \n";
char shindouDebugPrint89[] = "AudioHeap is %x\n";
char shindouDebugPrint90[] = "Heap reset.Synth Change %x \n";
char shindouDebugPrint91[] = "Heap %x %x %x\n";
char shindouDebugPrint92[] = "Main Heap Initialize.\n";
char shindouDebugPrint93[] = "%d :WaveA %d WaveB %d Inst %d,Perc %d\n";
char shindouDebugPrint94[] = "---------- Init Completed. ------------\n";
char shindouDebugPrint95[] = " Syndrv :[%6d]\n";
char shindouDebugPrint96[] = " Seqdrv :[%6d]\n";
char shindouDebugPrint97[] = " audiodata :[%6d]\n";
char shindouDebugPrint98[] = "---------------------------------------\n";
char shindouDebugPrint99[] = "Entry--- %d %d\n";
char shindouDebugPrint100[] = "---Block LPS here\n";
char shindouDebugPrint101[] = "===Block LPS end\n";
char shindouDebugPrint102[] = "SLOWCOPY";
char shindouDebugPrint103[] = "Req: Src %x Dest %x Len %x,media %d,retcode %d\n";
char shindouDebugPrint104[] = "Remain Size %d\n";
char shindouDebugPrint105[] = "---Block BG here\n";
char shindouDebugPrint106[] = "===Block BG end\n";
char shindouDebugPrint107[] = "Retcode %x\n";
char shindouDebugPrint108[] = "Other Type: Not Write ID.\n";
char shindouDebugPrint109[] = "BGLOAD:Error: dma length 0\n";
char shindouDebugPrint110[] = "BGCOPY";
char shindouDebugPrint111[] = "Error: Already wavetable is touched %x.\n";
char shindouDebugPrint112[] = "Touch Warning: Length zero %x\n";
char shindouDebugPrint113[] = "It's busy now!!!!! %d\n"; // This one's my favorite
char shindouDebugPrint114[] = "BG LOAD BUFFER is OVER.\n";
char shindouDebugPrint115[] = "Warning: Length zero %x\n";
char shindouDebugPrint116[] = "Wave Load %d \n";
char shindouDebugPrint117[] = "Total Bg Wave Load %d \n";
char shindouDebugPrint118[] = "Receive %d\n";
char shindouDebugPrint119[] = "============Error: Magic is Broken after loading.\n";
char shindouDebugPrint120[] = "Remain DMA: %d\n";
char shindouDebugPrint121[] = "N start %d\n";
char shindouDebugPrint122[] = "============Error: Magic is Broken: %x\n";
char shindouDebugPrint123[] = "Error: No Handle.\n";
char shindouDebugPrint124[] = "Success: %x\n";
// port_eu.c
char shindouDebugPrint125[] = "DAC:Lost 1 Frame.\n";
char shindouDebugPrint126[] = "DMA: Request queue over.( %d )\n";
char shindouDebugPrint127[] = "Spec Change Override. %d -> %d\n";
char shindouDebugPrint128[] = "Audio:now-max tasklen is %d / %d\n";
char shindouDebugPrint129[] = "Audio:Warning:ABI Tasklist length over (%d)\n";
s32 D_SH_80314FC8 = 0x80;
struct SPTask *D_SH_80314FCC = NULL;
char shindouDebugPrint130[] = "BGLOAD Start %d\n";
char shindouDebugPrint131[] = "Error: OverFlow Your Request\n";
char shindouDebugPrint132[] = "---AudioSending (%d->%d) \n";
// These continue in unk_shindou_audio_file.c
#endif
File diff suppressed because it is too large Load Diff
+99
View File
@@ -0,0 +1,99 @@
#ifndef AUDIO_SYNTHESIS_H
#define AUDIO_SYNTHESIS_H
#include "internal.h"
#ifdef VERSION_SH
#define DEFAULT_LEN_1CH 0x180
#define DEFAULT_LEN_2CH 0x300
#else
#define DEFAULT_LEN_1CH 0x140
#define DEFAULT_LEN_2CH 0x280
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
#define MAX_UPDATES_PER_FRAME 5
#else
#define MAX_UPDATES_PER_FRAME 4
#endif
struct ReverbRingBufferItem
{
s16 numSamplesAfterDownsampling;
s16 chunkLen; // never read
s16 *toDownsampleLeft;
s16 *toDownsampleRight; // data pointed to by left and right are adjacent in memory
s32 startPos; // start pos in ring buffer
s16 lengthA; // first length in ring buffer (from startPos, at most until end)
s16 lengthB; // second length in ring buffer (from pos 0)
}; // size = 0x14
struct SynthesisReverb
{
/*0x00, 0x00, 0x00*/ u8 resampleFlags;
/*0x01, 0x01, 0x01*/ u8 useReverb;
/*0x02, 0x02, 0x02*/ u8 framesLeftToIgnore;
/*0x03, 0x03, 0x03*/ u8 curFrame;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* 0x04, 0x04*/ u8 downsampleRate;
#ifdef VERSION_SH
/* 0x05*/ s8 unk5;
#endif
/* 0x06, 0x06*/ u16 windowSize; // same as bufSizePerChannel
#endif
#ifdef VERSION_SH
/* 0x08*/ u16 unk08;
#endif
/*0x04, 0x08, 0x0A*/ u16 reverbGain;
/*0x06, 0x0A, 0x0C*/ u16 resampleRate;
#ifdef VERSION_SH
/* 0x0E*/ u16 panRight;
/* 0x10*/ u16 panLeft;
#endif
/*0x08, 0x0C, 0x14*/ s32 nextRingBufferPos;
/*0x0C, 0x10, 0x18*/ s32 unkC; // never read
/*0x10, 0x14, 0x1C*/ s32 bufSizePerChannel;
struct
{
s16 *left;
s16 *right;
} ringBuffer;
/*0x1C, 0x20, 0x28*/ s16 *resampleStateLeft;
/*0x20, 0x24, 0x2C*/ s16 *resampleStateRight;
/*0x24, 0x28, 0x30*/ s16 *unk24; // never read
/*0x28, 0x2C, 0x34*/ s16 *unk28; // never read
/*0x2C, 0x30, 0x38*/ struct ReverbRingBufferItem items[2][MAX_UPDATES_PER_FRAME];
#if defined(VERSION_EU) || defined(VERSION_SH)
// Only used in sh:
/* 0x100*/ s16 *unk100;
/* 0x104*/ s16 *unk104;
/* 0x108*/ s16 *unk108;
/* 0x10C*/ s16 *unk10C;
#endif
}; // 0xCC <= size <= 0x100
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct SynthesisReverb gSynthesisReverbs[4];
extern s8 gNumSynthesisReverbs;
extern struct NoteSubEu *gNoteSubsEu;
extern f32 gLeftVolRampings[3][1024];
extern f32 gRightVolRampings[3][1024];
extern f32 *gCurrentLeftVolRamping; // Points to any of the three left buffers above
extern f32 *gCurrentRightVolRamping; // Points to any of the three right buffers above
#else
extern struct SynthesisReverb gSynthesisReverb;
#endif
#ifdef VERSION_SH
extern s16 D_SH_803479B4;
#endif
u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen);
#if defined(VERSION_JP) || defined(VERSION_US)
void note_init_volume(struct Note *note);
void note_set_vel_pan_reverb(struct Note *note, f32 velocity, f32 pan, u8 reverbVol);
void note_set_frequency(struct Note *note, f32 frequency);
void note_enable(struct Note *note);
void note_disable(struct Note *note);
#endif
#endif // AUDIO_SYNTHESIS_H
+914
View File
@@ -0,0 +1,914 @@
#ifdef VERSION_SH
#include <ultra64.h>
#include "synthesis.h"
#include "heap.h"
#include "data.h"
#include "load.h"
#include "seqplayer.h"
#include "internal.h"
#include "external.h"
#ifndef TARGET_N64
#include "../pc/mixer.h"
#endif
#define DMEM_ADDR_TEMP 0x450
#define DMEM_ADDR_RESAMPLED 0x470
#define DMEM_ADDR_RESAMPLED2 0x5f0
#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x5f0
#define DMEM_ADDR_NOTE_PAN_TEMP 0x650
#define DMEM_ADDR_COMPRESSED_ADPCM_DATA 0x990
#define DMEM_ADDR_LEFT_CH 0x990
#define DMEM_ADDR_RIGHT_CH 0xb10
#define DMEM_ADDR_WET_LEFT_CH 0xc90
#define DMEM_ADDR_WET_RIGHT_CH 0xe10
#define aSetLoadBufferPair(pkt, c, off) \
aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_LEFT_CH, 0, DEFAULT_LEN_1CH - c); \
aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \
aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_RIGHT_CH, 0, DEFAULT_LEN_1CH - c); \
aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off)))
#define aSetSaveBufferPair(pkt, c, d, off) \
aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_LEFT_CH, d); \
aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \
aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_RIGHT_CH, d); \
aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off)));
#define ALIGN(val, amnt) (((val) + (1 << amnt) - 1) & ~((1 << amnt) - 1))
struct VolumeChange {
u16 sourceLeft;
u16 sourceRight;
u16 targetLeft;
u16 targetRight;
};
u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex);
u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex);
u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad);
u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags);
u64 *process_envelope(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, u32 flags);
u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight);
struct SynthesisReverb gSynthesisReverbs[4];
u8 sAudioSynthesisPad[0x10];
s16 gVolume;
s8 gUseReverb;
s8 gNumSynthesisReverbs;
s16 D_SH_803479B4; // contains 4096
struct NoteSubEu *gNoteSubsEu;
// Equivalent functionality as the US/JP version,
// just that the reverb structure is chosen from an array with index
// Identical in EU.
void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex, s32 reverbIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb = &gSynthesisReverbs[reverbIndex];
s32 srcPos;
s32 dstPos;
s32 nSamples;
s32 excessiveSamples;
s32 UNUSED pad[3];
if (reverb->downsampleRate != 1) {
if (reverb->framesLeftToIgnore == 0) {
// Now that the RSP has finished, downsample the samples produced two frames ago by skipping
// samples.
item = &reverb->items[reverb->curFrame][updateIndex];
// Touches both left and right since they are adjacent in memory
osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH);
for (srcPos = 0, dstPos = 0; dstPos < item->lengthA / 2;
srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[item->startPos + dstPos] =
item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[item->startPos + dstPos] =
item->toDownsampleRight[srcPos];
}
for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos];
}
}
}
item = &reverb->items[reverb->curFrame][updateIndex];
nSamples = chunkLen / reverb->downsampleRate;
excessiveSamples = (nSamples + reverb->nextRingBufferPos) - reverb->bufSizePerChannel;
if (excessiveSamples < 0) {
// There is space in the ring buffer before it wraps around
item->lengthA = nSamples * 2;
item->lengthB = 0;
item->startPos = (s32) reverb->nextRingBufferPos;
reverb->nextRingBufferPos += nSamples;
} else {
// Ring buffer wrapped around
item->lengthA = (nSamples - excessiveSamples) * 2;
item->lengthB = excessiveSamples * 2;
item->startPos = reverb->nextRingBufferPos;
reverb->nextRingBufferPos = excessiveSamples;
}
// These fields are never read later
item->numSamplesAfterDownsampling = nSamples;
item->chunkLen = chunkLen;
}
u64 *synthesis_load_reverb_ring_buffer(u64 *cmd, u16 addr, u16 srcOffset, s32 len, s32 reverbIndex) {
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[srcOffset]),
addr, len);
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[srcOffset]),
addr + DEFAULT_LEN_1CH, len);
return cmd;
}
u64 *synthesis_save_reverb_ring_buffer(u64 *cmd, u16 addr, u16 destOffset, s32 len, s32 reverbIndex) {
aSaveBuffer(cmd++, addr,
VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[destOffset]), len);
aSaveBuffer(cmd++, addr + DEFAULT_LEN_1CH,
VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[destOffset]), len);
return cmd;
}
void func_sh_802ed644(s32 updateIndexStart, s32 noteIndex) {
s32 i;
for (i = updateIndexStart + 1; i < gAudioBufferParameters.updatesPerFrame; i++) {
if (!gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].needsInit) {
gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].enabled = FALSE;
} else {
break;
}
}
}
void synthesis_load_note_subs_eu(s32 updateIndex) {
struct NoteSubEu *src;
struct NoteSubEu *dest;
s32 i;
for (i = 0; i < gMaxSimultaneousNotes; i++) {
src = &gNotes[i].noteSubEu;
dest = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (src->enabled) {
*dest = *src;
src->needsInit = FALSE;
} else {
dest->enabled = FALSE;
}
}
}
// TODO: (Scrub C) pointless mask and whitespace
u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) {
s32 i, j;
u32 *aiBufPtr;
u64 *cmd = cmdBuf;
s32 chunkLen;
for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) {
process_sequences(i - 1);
synthesis_load_note_subs_eu(gAudioBufferParameters.updatesPerFrame - i);
}
aiBufPtr = (u32 *) aiBuf;
for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) {
if (i == 1) {
chunkLen = bufLen;
} else {
if (bufLen / i >= gAudioBufferParameters.samplesPerUpdateMax) {
chunkLen = gAudioBufferParameters.samplesPerUpdateMax;
} else if (bufLen / i <= gAudioBufferParameters.samplesPerUpdateMin) {
chunkLen = gAudioBufferParameters.samplesPerUpdateMin;
} else {
chunkLen = gAudioBufferParameters.samplesPerUpdate;
}
}
for (j = 0; j < gNumSynthesisReverbs; j++) {
if (gSynthesisReverbs[j].useReverb != 0) {
prepare_reverb_ring_buffer(chunkLen, gAudioBufferParameters.updatesPerFrame - i, j);
}
}
cmd = synthesis_do_one_audio_update((s16 *) aiBufPtr, chunkLen, cmd, gAudioBufferParameters.updatesPerFrame - i);
bufLen -= chunkLen;
aiBufPtr += chunkLen;
}
for (j = 0; j < gNumSynthesisReverbs; j++) {
if (gSynthesisReverbs[j].framesLeftToIgnore != 0) {
gSynthesisReverbs[j].framesLeftToIgnore--;
}
gSynthesisReverbs[j].curFrame ^= 1;
}
*writtenCmds = cmd - cmdBuf;
return cmd;
}
u64 *synthesis_resample_and_mix_reverb(u64 *cmd, s32 bufLen, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
s16 startPad;
s16 paddedLengthA;
item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex];
if (gSynthesisReverbs[reverbIndex].downsampleRate == 1) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
}
aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
} else {
startPad = (item->startPos % 8u) * 2;
paddedLengthA = ALIGN(startPad + item->lengthA, 4);
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, (item->startPos - startPad / 2), DEFAULT_LEN_1CH, reverbIndex);
if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + paddedLengthA, 0, DEFAULT_LEN_1CH - paddedLengthA, reverbIndex);
}
aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED + startPad, DMEM_ADDR_WET_LEFT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateLeft));
aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED2 + startPad, DMEM_ADDR_WET_RIGHT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateRight));
aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
}
if (gSynthesisReverbs[reverbIndex].panRight != 0 || gSynthesisReverbs[reverbIndex].panLeft != 0) {
// Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan)
aDMEMMove(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_1CH);
aMix(cmd++, gSynthesisReverbs[reverbIndex].panRight, DMEM_ADDR_WET_RIGHT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_1CH);
aMix(cmd++, gSynthesisReverbs[reverbIndex].panLeft, DMEM_ADDR_RESAMPLED, DMEM_ADDR_WET_RIGHT_CH, DEFAULT_LEN_1CH);
}
return cmd;
}
u64 *synthesis_load_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb;
reverb = &gSynthesisReverbs[reverbIndex];
item = &reverb->items[reverb->curFrame][updateIndex];
// Get the oldest samples in the ring buffer into the wet channels
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex);
}
return cmd;
}
u64 *synthesis_save_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex];
switch (gSynthesisReverbs[reverbIndex].downsampleRate) {
case 1:
// Put the oldest samples in the ring buffer into the wet channels
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
}
break;
default:
// Downsampling is done later by CPU when RSP is done, therefore we need to have double
// buffering. Left and right buffers are adjacent in memory.
aSaveBuffer(cmd++, DMEM_ADDR_WET_LEFT_CH,
VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex].toDownsampleLeft), DEFAULT_LEN_2CH);
break;
}
gSynthesisReverbs[reverbIndex].resampleFlags = 0;
return cmd;
}
u64 *func_sh_802EDF24(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb;
reverb = &gSynthesisReverbs[reverbIndex];
item = &reverb->items[reverb->curFrame][updateIndex];
// Put the oldest samples in the ring buffer into the wet channels
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex);
}
return cmd;
}
u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) {
struct NoteSubEu *noteSubEu;
u8 noteIndices[56];
s32 temp;
s32 i;
s16 j;
s16 notePos = 0;
if (gNumSynthesisReverbs == 0) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
if (gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i].enabled) {
noteIndices[notePos++] = i;
}
}
} else {
for (j = 0; j < gNumSynthesisReverbs; j++) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (noteSubEu->enabled && j == noteSubEu->reverbIndex) {
noteIndices[notePos++] = i;
}
}
}
for (i = 0; i < gMaxSimultaneousNotes; i++) {
noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (noteSubEu->enabled && noteSubEu->reverbIndex >= gNumSynthesisReverbs) {
noteIndices[notePos++] = i;
}
}
}
aClearBuffer(cmd++, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
i = 0;
for (j = 0; j < gNumSynthesisReverbs; j++) {
gUseReverb = gSynthesisReverbs[j].useReverb;
if (gUseReverb != 0) {
cmd = synthesis_resample_and_mix_reverb(cmd, bufLen, j, updateIndex);
}
for (; i < notePos; i++) {
temp = updateIndex * gMaxSimultaneousNotes;
if (j == gNoteSubsEu[temp + noteIndices[i]].reverbIndex) {
cmd = synthesis_process_note(noteIndices[i],
&gNoteSubsEu[temp + noteIndices[i]],
&gNotes[noteIndices[i]].synthesisState,
aiBuf, bufLen, cmd, updateIndex);
continue;
} else {
break;
}
}
if (gSynthesisReverbs[j].useReverb != 0) {
if (gSynthesisReverbs[j].unk100 != NULL) {
aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk100);
aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_LEFT_CH, gSynthesisReverbs[j].unk108);
}
if (gSynthesisReverbs[j].unk104 != NULL) {
aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk104);
aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_RIGHT_CH, gSynthesisReverbs[j].unk10C);
}
cmd = synthesis_save_reverb_samples(cmd, j, updateIndex);
if (gSynthesisReverbs[j].unk5 != -1) {
if (gSynthesisReverbs[gSynthesisReverbs[j].unk5].downsampleRate == 1) {
cmd = synthesis_load_reverb_samples(cmd, gSynthesisReverbs[j].unk5, updateIndex);
aMix(cmd++, gSynthesisReverbs[j].unk08, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_2CH);
cmd = func_sh_802EDF24(cmd++, gSynthesisReverbs[j].unk5, updateIndex);
}
}
}
}
for (; i < notePos; i++) {
struct NoteSubEu *noteSubEu2 = &gNoteSubsEu[updateIndex * gMaxSimultaneousNotes + noteIndices[i]];
cmd = synthesis_process_note(noteIndices[i],
noteSubEu2,
&gNotes[noteIndices[i]].synthesisState,
aiBuf, bufLen, cmd, updateIndex);
}
temp = bufLen * 2;
aInterleave(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_LEFT_CH, DMEM_ADDR_RIGHT_CH, temp);
aSaveBuffer(cmd++, DMEM_ADDR_TEMP, VIRTUAL_TO_PHYSICAL2(aiBuf), temp * 2);
return cmd;
}
u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, UNUSED s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) {
UNUSED s32 pad0[3];
struct AudioBankSample *audioBookSample; // sp164, sp138
struct AdpcmLoop *loopInfo; // sp160, sp134
s16 *curLoadedBook; // sp154, sp130
UNUSED u8 padEU[0x04];
UNUSED u8 pad8[0x04];
s32 noteFinished; // 150 t2, sp124
s32 restart; // 14c t3, sp120
s32 flags; // sp148, sp11C, t8
u16 resamplingRateFixedPoint; // sp5c, sp11A
s32 nSamplesToLoad; //s0, Ec
UNUSED u8 pad7[0x0c]; // sp100
s32 sp130; //sp128, sp104
UNUSED s32 tempBufLen;
UNUSED u32 pad9;
s32 t0;
u8 *sampleAddr; // sp120, spF4
s32 s6;
s32 samplesLenAdjusted; // 108, spEC
s32 nAdpcmSamplesProcessed; // signed required for US // spc0
s32 endPos; // sp110, spE4
s32 nSamplesToProcess; // sp10c/a0, spE0
// Might have been used to store (samplesLenFixedPoint >> 0x10), but doing so causes strange
// behavior with the break near the end of the loop, causing US and JP to need a goto instead
UNUSED s32 samplesLenInt;
s32 s2;
s32 leftRight; //s0
s32 s5; //s4
u32 samplesLenFixedPoint; // v1_1
s32 s3; // spA0
s32 nSamplesInThisIteration; // v1_2
u32 a3;
u8 *v0_2;
s32 unk_s6; // sp90
s32 s5Aligned;
s32 sp88;
s32 sp84;
u32 temp;
s32 nParts; // spE8, spBC
s32 curPart; // spE4, spB8
s32 aligned;
UNUSED u32 padSH1;
s32 resampledTempLen; // spD8, spAC, sp6c
u16 noteSamplesDmemAddrBeforeResampling; // spD6, spAA, sp6a -- 6C
UNUSED u32 padSH2;
UNUSED u32 padSH3;
UNUSED u32 padSH4;
struct Note *note; // sp58
u16 sp56; // sp56
u16 addr;
u8 synthesisVolume;
curLoadedBook = NULL;
note = &gNotes[noteIndex];
flags = 0;
if (noteSubEu->needsInit == TRUE) {
flags = A_INIT;
synthesisState->restart = 0;
synthesisState->samplePosInt = 0;
synthesisState->samplePosFrac = 0;
synthesisState->curVolLeft = 0;
synthesisState->curVolRight = 0;
synthesisState->prevHeadsetPanRight = 0;
synthesisState->prevHeadsetPanLeft = 0;
synthesisState->reverbVol = noteSubEu->reverbVol;
synthesisState->unk5 = 0;
note->noteSubEu.finished = 0;
}
resamplingRateFixedPoint = noteSubEu->resamplingRateFixedPoint;
nParts = noteSubEu->hasTwoAdpcmParts + 1;
samplesLenFixedPoint = (resamplingRateFixedPoint * bufLen * 2) + synthesisState->samplePosFrac;
nSamplesToLoad = (samplesLenFixedPoint >> 0x10);
synthesisState->samplePosFrac = samplesLenFixedPoint & 0xFFFF;
if ((synthesisState->unk5 == 1) && (nParts == 2)) {
nSamplesToLoad += 2;
sp56 = 2;
} else if ((synthesisState->unk5 == 2) && (nParts == 1)) {
nSamplesToLoad -= 4;
sp56 = 4;
} else {
sp56 = 0;
}
synthesisState->unk5 = nParts;
if (noteSubEu->isSyntheticWave) {
cmd = load_wave_samples(cmd, noteSubEu, synthesisState, nSamplesToLoad);
noteSamplesDmemAddrBeforeResampling = (synthesisState->samplePosInt * 2) + DMEM_ADDR_UNCOMPRESSED_NOTE;
synthesisState->samplePosInt += nSamplesToLoad;
} else {
// ADPCM note
audioBookSample = noteSubEu->sound.audioBankSound->sample;
loopInfo = audioBookSample->loop;
endPos = loopInfo->end;
sampleAddr = audioBookSample->sampleAddr;
resampledTempLen = 0;
for (curPart = 0; curPart < nParts; curPart++) {
nAdpcmSamplesProcessed = 0; // s8
s5 = 0; // s4
if (nParts == 1) {
samplesLenAdjusted = nSamplesToLoad;
} else if (nSamplesToLoad & 1) {
samplesLenAdjusted = (nSamplesToLoad & ~1) + (curPart * 2);
} else {
samplesLenAdjusted = nSamplesToLoad;
}
if (audioBookSample->codec == CODEC_ADPCM) {
if (curLoadedBook != (*audioBookSample->book).book) {
u32 nEntries;
switch (noteSubEu->bookOffset) {
case 1:
curLoadedBook = euUnknownData_80301950 + 1;
break;
case 2:
curLoadedBook = euUnknownData_80301950 + 2;
break;
case 3:
default:
curLoadedBook = audioBookSample->book->book;
break;
}
nEntries = 16 * audioBookSample->book->order * audioBookSample->book->npredictors;
aLoadADPCM(cmd++, nEntries, VIRTUAL_TO_PHYSICAL2(curLoadedBook));
}
}
while (nAdpcmSamplesProcessed != samplesLenAdjusted) {
s32 samplesRemaining; // v1
s32 s0;
noteFinished = FALSE;
restart = FALSE;
s2 = synthesisState->samplePosInt & 0xf;
samplesRemaining = endPos - synthesisState->samplePosInt;
nSamplesToProcess = samplesLenAdjusted - nAdpcmSamplesProcessed;
if (s2 == 0 && synthesisState->restart == FALSE) {
s2 = 16;
}
s6 = 16 - s2; // a1
if (nSamplesToProcess < samplesRemaining) {
t0 = (nSamplesToProcess - s6 + 0xf) / 16;
s0 = t0 * 16;
s3 = s6 + s0 - nSamplesToProcess;
} else {
s0 = samplesRemaining - s6;
s3 = 0;
if (s0 <= 0) {
s0 = 0;
s6 = samplesRemaining;
}
t0 = (s0 + 0xf) / 16;
if (loopInfo->count != 0) {
// Loop around and restart
restart = 1;
} else {
noteFinished = 1;
}
}
switch (audioBookSample->codec) {
case CODEC_ADPCM:
unk_s6 = 9;
sp88 = 0x10;
sp84 = 0;
break;
case CODEC_S8:
unk_s6 = 0x10;
sp88 = 0x10;
sp84 = 0;
break;
case CODEC_SKIP: goto skip;
}
if (t0 != 0) {
temp = (synthesisState->samplePosInt + sp88 - s2) / 16;
if (audioBookSample->medium == 0) {
v0_2 = sp84 + (temp * unk_s6) + sampleAddr;
} else {
v0_2 = dma_sample_data((uintptr_t)(sp84 + (temp * unk_s6) + sampleAddr),
ALIGN(t0 * unk_s6 + 16, 4), flags, &synthesisState->sampleDmaIndex, audioBookSample->medium);
}
a3 = ((uintptr_t)v0_2 & 0xf);
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(v0_2 - a3), addr, ALIGN(t0 * unk_s6 + 16, 4));
} else {
s0 = 0;
a3 = 0;
}
if (synthesisState->restart != FALSE) {
aSetLoop(cmd++, VIRTUAL_TO_PHYSICAL2(audioBookSample->loop->state));
flags = A_LOOP; // = 2
synthesisState->restart = FALSE;
}
nSamplesInThisIteration = s0 + s6 - s3;
if (nAdpcmSamplesProcessed == 0) {
switch (audioBookSample->codec) {
case CODEC_ADPCM:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2);
aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
case CODEC_S8:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2);
aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
}
sp130 = s2 * 2;
} else {
s5Aligned = ALIGN(s5 + 16, 4);
switch (audioBookSample->codec) {
case CODEC_ADPCM:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2);
aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
case CODEC_S8:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2);
aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
}
aDMEMMove(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned + (s2 * 2), DMEM_ADDR_UNCOMPRESSED_NOTE + s5, (nSamplesInThisIteration) * 2);
}
nAdpcmSamplesProcessed += nSamplesInThisIteration;
switch (flags) {
case A_INIT: // = 1
sp130 = 0x20;
s5 = (s0 + 0x10) * 2;
break;
case A_LOOP: // = 2
s5 = (nSamplesInThisIteration) * 2 + s5;
break;
default:
if (s5 != 0) {
s5 = (nSamplesInThisIteration) * 2 + s5;
} else {
s5 = (s2 + (nSamplesInThisIteration)) * 2;
}
break;
}
flags = 0;
skip:
if (noteFinished) {
aClearBuffer(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5,
(samplesLenAdjusted - nAdpcmSamplesProcessed) * 2);
noteSubEu->finished = 1;
note->noteSubEu.finished = 1;
func_sh_802ed644(updateIndex, noteIndex);
break;
}
if (restart != 0) {
synthesisState->restart = TRUE;
synthesisState->samplePosInt = loopInfo->start;
} else {
synthesisState->samplePosInt += nSamplesToProcess;
}
}
switch (nParts) {
case 1:
noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_UNCOMPRESSED_NOTE + sp130;
break;
case 2:
switch (curPart) {
case 0:
aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, DMEM_ADDR_RESAMPLED);
resampledTempLen = samplesLenAdjusted;
noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_RESAMPLED;
if (noteSubEu->finished != FALSE) {
aClearBuffer(cmd++, noteSamplesDmemAddrBeforeResampling + resampledTempLen, samplesLenAdjusted + 0x10);
}
break;
case 1:
aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, resampledTempLen + DMEM_ADDR_RESAMPLED);
break;
}
}
if (noteSubEu->finished != FALSE) {
break;
}
}
}
flags = 0;
if (noteSubEu->needsInit == TRUE) {
flags = A_INIT;
noteSubEu->needsInit = FALSE;
}
flags = flags | sp56;
cmd = final_resample(cmd, synthesisState, bufLen * 2, resamplingRateFixedPoint,
noteSamplesDmemAddrBeforeResampling, flags);
if ((flags & 1) != 0) {
flags = 1;
}
if (noteSubEu->filter) {
aFilter(cmd++, 0x02, bufLen * 2, noteSubEu->filter);
aFilter(cmd++, flags, DMEM_ADDR_TEMP, synthesisState->synthesisBuffers->filterBuffer);
}
if (noteSubEu->bookOffset == 3) {
aUnknown25(cmd++, 0, bufLen * 2, DMEM_ADDR_TEMP, DMEM_ADDR_TEMP);
}
synthesisVolume = noteSubEu->synthesisVolume;
if (synthesisVolume != 0) {
if (synthesisVolume < 0x10) {
synthesisVolume = 0x10;
}
aHiLoGain(cmd++, synthesisVolume, (bufLen + 0x10) * 2, DMEM_ADDR_TEMP);
}
if (noteSubEu->headsetPanRight != 0 || synthesisState->prevHeadsetPanRight != 0) {
leftRight = 1;
} else if (noteSubEu->headsetPanLeft != 0 || synthesisState->prevHeadsetPanLeft != 0) {
leftRight = 2;
} else {
leftRight = 0;
}
cmd = process_envelope(cmd, noteSubEu, synthesisState, bufLen, DMEM_ADDR_TEMP, leftRight, flags);
if (noteSubEu->usesHeadsetPanEffects) {
if ((flags & 1) == 0) {
flags = 0;
}
cmd = note_apply_headset_pan_effects(cmd, noteSubEu, synthesisState, bufLen * 2, flags, leftRight);
}
return cmd;
}
u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad) {
s32 a3;
s32 repeats;
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(noteSubEu->sound.samples),
DMEM_ADDR_UNCOMPRESSED_NOTE, 128);
synthesisState->samplePosInt &= 0x3f;
a3 = 64 - synthesisState->samplePosInt;
if (a3 < nSamplesToLoad) {
repeats = (nSamplesToLoad - a3 + 63) / 64;
if (repeats != 0) {
aDuplicate(cmd++,
/*dmemin*/ DMEM_ADDR_UNCOMPRESSED_NOTE,
/*dmemout*/ DMEM_ADDR_UNCOMPRESSED_NOTE + 128,
/*copies*/ repeats);
}
}
return cmd;
}
u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags) {
if (pitch == 0) {
aClearBuffer(cmd++, DMEM_ADDR_TEMP, count);
} else {
aSetBuffer(cmd++, /*flags*/ 0, dmemIn, /*dmemout*/ DMEM_ADDR_TEMP, count);
aResample(cmd++, flags, pitch, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->finalResampleState));
}
return cmd;
}
u64 *process_envelope(u64 *cmd, struct NoteSubEu *note, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, UNUSED u32 flags) {
u16 sourceRight;
u16 sourceLeft;
u16 targetLeft;
u16 targetRight;
s16 rampLeft;
s16 rampRight;
s32 sourceReverbVol;
s16 rampReverb;
s32 reverbVolDiff = 0;
sourceLeft = synthesisState->curVolLeft;
sourceRight = synthesisState->curVolRight;
targetLeft = note->targetVolLeft;
targetRight = note->targetVolRight;
targetLeft <<= 4;
targetRight <<= 4;
if (targetLeft != sourceLeft) {
rampLeft = (targetLeft - sourceLeft) / (nSamples >> 3);
} else {
rampLeft = 0;
}
if (targetRight != sourceRight) {
rampRight = (targetRight - sourceRight) / (nSamples >> 3);
} else {
rampRight = 0;
}
sourceReverbVol = synthesisState->reverbVol;
if (note->reverbVol != sourceReverbVol) {
reverbVolDiff = ((note->reverbVol & 0x7f) - (sourceReverbVol & 0x7f)) << 9;
rampReverb = reverbVolDiff / (nSamples >> 3);
synthesisState->reverbVol = note->reverbVol;
} else {
rampReverb = 0;
}
synthesisState->curVolLeft = sourceLeft + rampLeft * (nSamples >> 3);
synthesisState->curVolRight = sourceRight + rampRight * (nSamples >> 3);
if (note->usesHeadsetPanEffects) {
aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DEFAULT_LEN_1CH);
aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight);
aEnvSetup2(cmd++, sourceLeft, sourceRight);
switch (headsetPanSettings) {
case 1:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_NOTE_PAN_TEMP,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
case 2:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_NOTE_PAN_TEMP,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
default:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
}
} else {
aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight);
aEnvSetup2(cmd++, sourceLeft, sourceRight);
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
}
return cmd;
}
u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight) {
u16 dest;
u16 pitch;
u8 prevPanShift;
u8 panShift;
UNUSED u8 unkDebug;
switch (leftRight) {
case 1:
dest = DMEM_ADDR_LEFT_CH;
panShift = noteSubEu->headsetPanRight;
note->prevHeadsetPanLeft = 0;
prevPanShift = note->prevHeadsetPanRight;
note->prevHeadsetPanRight = panShift;
break;
case 2:
dest = DMEM_ADDR_RIGHT_CH;
panShift = noteSubEu->headsetPanLeft;
note->prevHeadsetPanRight = 0;
prevPanShift = note->prevHeadsetPanLeft;
note->prevHeadsetPanLeft = panShift;
break;
default:
return cmd;
}
if (flags != 1) { // A_INIT?
// Slightly adjust the sample rate in order to fit a change in pan shift
if (panShift != prevPanShift) {
pitch = (((bufLen << 0xf) / 2) - 1) / ((bufLen + panShift - prevPanShift - 2) / 2);
aSetBuffer(cmd++, 0, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, (bufLen + panShift) - prevPanShift);
aResampleZoh(cmd++, pitch, 0);
} else {
aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen);
}
if (prevPanShift != 0) {
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer),
DMEM_ADDR_NOTE_PAN_TEMP, ALIGN(prevPanShift, 4));
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + prevPanShift, bufLen + panShift - prevPanShift);
} else {
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP, bufLen + panShift);
}
} else {
// Just shift right
aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen);
aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, panShift);
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + panShift, bufLen);
}
if (panShift) {
// Save excessive samples for next iteration
aSaveBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP + bufLen,
VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer), ALIGN(panShift, 4));
}
aAddMixer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, dest, (bufLen + 0x3f) & 0xffc0);
return cmd;
}
#endif
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
#ifndef _ULTRA64_LIBAUDIO_H_
#define _ULTRA64_LIBAUDIO_H_
#include "abi.h"
#include <stdlib.h>
typedef struct
{
u8 *offset __attribute__((aligned (8)));
s32 len __attribute__((aligned (8)));
} ALSeqData;
typedef struct
{
unsigned short revision;
unsigned short seqCount;
unsigned int pad;
ALSeqData seqArray[1];
} __attribute__((aligned (16))) ALSeqFile;
void alSeqFileNew(ALSeqFile *f, u8 *base);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _LIBULTRA_H
#define _LIBULTRA_H
#define TV_TYPE_NTSC 1
#define TV_TYPE_PAL 0
#define TV_TYPE_MPAL 2
#define RESET_TYPE_COLD_RESET 0
#define RESET_TYPE_NMI 1
#define RESET_TYPE_BOOT_DISK 2
extern u32 osTvType;
extern u32 osRomBase;
extern u32 osResetType;
extern u32 osMemSize;
extern u8 osAppNmiBuffer[64];
#endif /* _LIBULTRA_H */
+800
View File
@@ -0,0 +1,800 @@
/*====================================================================
* os.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/**************************************************************************
*
* $Revision: 1.149 $
* $Date: 1997/12/15 04:30:52 $
* $Source: /disk6/Master/cvsmdev2/PR/include/os.h,v $
*
**************************************************************************/
#ifndef _OS_H_
#define _OS_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#include "PR/os_message.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
/*
* Structure for device manager block
*/
typedef struct {
s32 active; /* Status flag */
OSThread *thread; /* Calling thread */
OSMesgQueue *cmdQueue; /* Command queue */
OSMesgQueue *evtQueue; /* Event queue */
OSMesgQueue *acsQueue; /* Access queue */
/* Raw DMA routine */
s32 (*dma)(s32, u32, void *, u32);
s32 (*edma)(OSPiHandle *, s32, u32, void *, u32);
} OSDevMgr;
/*
* Structure for file system
*/
typedef struct {
int status;
OSMesgQueue *queue;
int channel;
u8 id[32];
u8 label[32];
int version;
int dir_size;
int inode_table; /* block location */
int minode_table; /* mirrioring inode_table */
int dir_table; /* block location */
int inode_start_page; /* page # */
u8 banks;
u8 activebank;
} OSPfs;
typedef struct {
u32 file_size; /* bytes */
u32 game_code;
u16 company_code;
char ext_name[4];
char game_name[16];
} OSPfsState;
/*
* Structure for Profiler
*/
typedef struct {
u16 *histo_base; /* histogram base */
u32 histo_size; /* histogram size */
u32 *text_start; /* start of text segment */
u32 *text_end; /* end of text segment */
} OSProf;
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
/* Thread states */
#define OS_STATE_STOPPED 1
#define OS_STATE_RUNNABLE 2
#define OS_STATE_RUNNING 4
#define OS_STATE_WAITING 8
/* Events */
#ifdef _FINALROM
#define OS_NUM_EVENTS 15
#else
#define OS_NUM_EVENTS 23
#endif
#define OS_EVENT_SW1 0 /* CPU SW1 interrupt */
#define OS_EVENT_SW2 1 /* CPU SW2 interrupt */
#define OS_EVENT_CART 2 /* Cartridge interrupt: used by rmon */
#define OS_EVENT_COUNTER 3 /* Counter int: used by VI/Timer Mgr */
#define OS_EVENT_SP 4 /* SP task done interrupt */
#define OS_EVENT_SI 5 /* SI (controller) interrupt */
#define OS_EVENT_AI 6 /* AI interrupt */
#define OS_EVENT_VI 7 /* VI interrupt: used by VI/Timer Mgr */
#define OS_EVENT_PI 8 /* PI interrupt: used by PI Manager */
#define OS_EVENT_DP 9 /* DP full sync interrupt */
#define OS_EVENT_CPU_BREAK 10 /* CPU breakpoint: used by rmon */
#define OS_EVENT_SP_BREAK 11 /* SP breakpoint: used by rmon */
#define OS_EVENT_FAULT 12 /* CPU fault event: used by rmon */
#define OS_EVENT_THREADSTATUS 13 /* CPU thread status: used by rmon */
#define OS_EVENT_PRENMI 14 /* Pre NMI interrupt */
#ifndef _FINALROM
#define OS_EVENT_RDB_READ_DONE 15 /* RDB read ok event: used by rmon */
#define OS_EVENT_RDB_LOG_DONE 16 /* read of log data complete */
#define OS_EVENT_RDB_DATA_DONE 17 /* read of hostio data complete */
#define OS_EVENT_RDB_REQ_RAMROM 18 /* host needs ramrom access */
#define OS_EVENT_RDB_FREE_RAMROM 19 /* host is done with ramrom access */
#define OS_EVENT_RDB_DBG_DONE 20
#define OS_EVENT_RDB_FLUSH_PROF 21
#define OS_EVENT_RDB_ACK_PROF 22
#endif
/* Flags for debugging purpose */
#define OS_FLAG_CPU_BREAK 1 /* Break exception has occurred */
#define OS_FLAG_FAULT 2 /* CPU fault has occurred */
/* Interrupt masks */
#define OS_IM_NONE 0x00000001
#define OS_IM_SW1 0x00000501
#define OS_IM_SW2 0x00000601
#define OS_IM_CART 0x00000c01
#define OS_IM_PRENMI 0x00001401
#define OS_IM_RDBWRITE 0x00002401
#define OS_IM_RDBREAD 0x00004401
#define OS_IM_COUNTER 0x00008401
#define OS_IM_CPU 0x0000ff01
#define OS_IM_SP 0x00010401
#define OS_IM_SI 0x00020401
#define OS_IM_AI 0x00040401
#define OS_IM_VI 0x00080401
#define OS_IM_PI 0x00100401
#define OS_IM_DP 0x00200401
#define OS_IM_ALL 0x003fff01
#define RCP_IMASK 0x003f0000
#define RCP_IMASKSHIFT 16
/* Recommended thread priorities for the system threads */
#define OS_PRIORITY_MAX 255
#define OS_PRIORITY_VIMGR 254
#define OS_PRIORITY_RMON 250
#define OS_PRIORITY_RMONSPIN 200
#define OS_PRIORITY_PIMGR 150
#define OS_PRIORITY_SIMGR 140
#define OS_PRIORITY_APPMAX 127
#define OS_PRIORITY_IDLE 0 /* Must be 0 */
/* Flags to turn blocking on/off when sending/receiving message */
#define OS_MESG_NOBLOCK 0
#define OS_MESG_BLOCK 1
/* Flags to indicate direction of data transfer */
#define OS_READ 0 /* device -> RDRAM */
#define OS_WRITE 1 /* device <- RDRAM */
#define OS_OTHERS 2 /* for Leo disk only */
/*
* I/O message types
*/
#define OS_MESG_TYPE_BASE (10)
#define OS_MESG_TYPE_LOOPBACK (OS_MESG_TYPE_BASE+0)
#define OS_MESG_TYPE_DMAREAD (OS_MESG_TYPE_BASE+1)
#define OS_MESG_TYPE_DMAWRITE (OS_MESG_TYPE_BASE+2)
#define OS_MESG_TYPE_VRETRACE (OS_MESG_TYPE_BASE+3)
#define OS_MESG_TYPE_COUNTER (OS_MESG_TYPE_BASE+4)
#define OS_MESG_TYPE_EDMAREAD (OS_MESG_TYPE_BASE+5)
#define OS_MESG_TYPE_EDMAWRITE (OS_MESG_TYPE_BASE+6)
/*
* I/O message priority
*/
#define OS_MESG_PRI_NORMAL 0
#define OS_MESG_PRI_HIGH 1
/*
* Page size argument for TLB routines
*/
#define OS_PM_4K 0x0000000
#define OS_PM_16K 0x0006000
#define OS_PM_64K 0x001e000
#define OS_PM_256K 0x007e000
#define OS_PM_1M 0x01fe000
#define OS_PM_4M 0x07fe000
#define OS_PM_16M 0x1ffe000
/*
* Stack size for I/O device managers: PIM (PI Manager), VIM (VI Manager),
* SIM (SI Manager)
*
*/
#define OS_PIM_STACKSIZE 4096
#define OS_VIM_STACKSIZE 4096
#define OS_SIM_STACKSIZE 4096
#define OS_MIN_STACKSIZE 72
/*
* Values for osTvType
*/
#define OS_TV_PAL 0
#define OS_TV_NTSC 1
#define OS_TV_MPAL 2
/*
* Video Interface (VI) mode type
*/
#define OS_VI_NTSC_LPN1 0 /* NTSC */
#define OS_VI_NTSC_LPF1 1
#define OS_VI_NTSC_LAN1 2
#define OS_VI_NTSC_LAF1 3
#define OS_VI_NTSC_LPN2 4
#define OS_VI_NTSC_LPF2 5
#define OS_VI_NTSC_LAN2 6
#define OS_VI_NTSC_LAF2 7
#define OS_VI_NTSC_HPN1 8
#define OS_VI_NTSC_HPF1 9
#define OS_VI_NTSC_HAN1 10
#define OS_VI_NTSC_HAF1 11
#define OS_VI_NTSC_HPN2 12
#define OS_VI_NTSC_HPF2 13
#define OS_VI_PAL_LPN1 14 /* PAL */
#define OS_VI_PAL_LPF1 15
#define OS_VI_PAL_LAN1 16
#define OS_VI_PAL_LAF1 17
#define OS_VI_PAL_LPN2 18
#define OS_VI_PAL_LPF2 19
#define OS_VI_PAL_LAN2 20
#define OS_VI_PAL_LAF2 21
#define OS_VI_PAL_HPN1 22
#define OS_VI_PAL_HPF1 23
#define OS_VI_PAL_HAN1 24
#define OS_VI_PAL_HAF1 25
#define OS_VI_PAL_HPN2 26
#define OS_VI_PAL_HPF2 27
#define OS_VI_MPAL_LPN1 28 /* MPAL - mainly Brazil */
#define OS_VI_MPAL_LPF1 29
#define OS_VI_MPAL_LAN1 30
#define OS_VI_MPAL_LAF1 31
#define OS_VI_MPAL_LPN2 32
#define OS_VI_MPAL_LPF2 33
#define OS_VI_MPAL_LAN2 34
#define OS_VI_MPAL_LAF2 35
#define OS_VI_MPAL_HPN1 36
#define OS_VI_MPAL_HPF1 37
#define OS_VI_MPAL_HAN1 38
#define OS_VI_MPAL_HAF1 39
#define OS_VI_MPAL_HPN2 40
#define OS_VI_MPAL_HPF2 41
/*
* Video Interface (VI) special features
*/
#define OS_VI_GAMMA_ON 0x0001
#define OS_VI_GAMMA_OFF 0x0002
#define OS_VI_GAMMA_DITHER_ON 0x0004
#define OS_VI_GAMMA_DITHER_OFF 0x0008
#define OS_VI_DIVOT_ON 0x0010
#define OS_VI_DIVOT_OFF 0x0020
#define OS_VI_DITHER_FILTER_ON 0x0040
#define OS_VI_DITHER_FILTER_OFF 0x0080
/*
* Video Interface (VI) mode attribute bit
*/
#define OS_VI_BIT_NONINTERLACE 0x0001 /* lo-res */
#define OS_VI_BIT_INTERLACE 0x0002 /* lo-res */
#define OS_VI_BIT_NORMALINTERLACE 0x0004 /* hi-res */
#define OS_VI_BIT_DEFLICKINTERLACE 0x0008 /* hi-res */
#define OS_VI_BIT_ANTIALIAS 0x0010
#define OS_VI_BIT_POINTSAMPLE 0x0020
#define OS_VI_BIT_16PIXEL 0x0040
#define OS_VI_BIT_32PIXEL 0x0080
#define OS_VI_BIT_LORES 0x0100
#define OS_VI_BIT_HIRES 0x0200
#define OS_VI_BIT_NTSC 0x0400
#define OS_VI_BIT_PAL 0x0800
/*
* Leo Disk
*/
/* transfer mode */
#define LEO_BLOCK_MODE 1
#define LEO_TRACK_MODE 2
#define LEO_SECTOR_MODE 3
/*
* Controllers number
*/
#ifndef _HW_VERSION_1
#define MAXCONTROLLERS 4
#else
#define MAXCONTROLLERS 6
#endif
/* controller errors */
#define CONT_NO_RESPONSE_ERROR 0x8
#define CONT_OVERRUN_ERROR 0x4
#ifdef _HW_VERSION_1
#define CONT_FRAME_ERROR 0x2
#define CONT_COLLISION_ERROR 0x1
#endif
/* Controller type */
#define CONT_ABSOLUTE 0x0001
#define CONT_RELATIVE 0x0002
#define CONT_JOYPORT 0x0004
#define CONT_EEPROM 0x8000
#define CONT_EEP16K 0x4000
#define CONT_TYPE_MASK 0x1f07
#define CONT_TYPE_NORMAL 0x0005
#define CONT_TYPE_MOUSE 0x0002
/* Controller status */
#define CONT_CARD_ON 0x01
#define CONT_CARD_PULL 0x02
#define CONT_ADDR_CRC_ER 0x04
#define CONT_EEPROM_BUSY 0x80
/* EEPROM TYPE */
#define EEPROM_TYPE_4K 0x01
#define EEPROM_TYPE_16K 0x02
/* Buttons */
#define CONT_A 0x8000
#define CONT_B 0x4000
#define CONT_G 0x2000
#define CONT_START 0x1000
#define CONT_UP 0x0800
#define CONT_DOWN 0x0400
#define CONT_LEFT 0x0200
#define CONT_RIGHT 0x0100
#define CONT_L 0x0020
#define CONT_R 0x0010
#define CONT_E 0x0008
#define CONT_D 0x0004
#define CONT_C 0x0002
#define CONT_F 0x0001
/* Nintendo's official button names */
#define A_BUTTON CONT_A
#define B_BUTTON CONT_B
#define L_TRIG CONT_L
#define R_TRIG CONT_R
#define Z_TRIG CONT_G
#define START_BUTTON CONT_START
#define U_JPAD CONT_UP
#define L_JPAD CONT_LEFT
#define R_JPAD CONT_RIGHT
#define D_JPAD CONT_DOWN
#define U_CBUTTONS CONT_E
#define L_CBUTTONS CONT_C
#define R_CBUTTONS CONT_F
#define D_CBUTTONS CONT_D
/* File System size */
#define OS_PFS_VERSION 0x0200
#define OS_PFS_VERSION_HI (OS_PFS_VERSION >> 8)
#define OS_PFS_VERSION_LO (OS_PFS_VERSION & 255)
#define PFS_FILE_NAME_LEN 16
#define PFS_FILE_EXT_LEN 4
#define BLOCKSIZE 32 /* bytes */
#define PFS_ONE_PAGE 8 /* blocks */
#define PFS_MAX_BANKS 62
/* File System flag */
#define PFS_READ 0
#define PFS_WRITE 1
#define PFS_CREATE 2
/* File System status */
#define PFS_INITIALIZED 0x1
#define PFS_CORRUPTED 0x2 /* File system was corrupted */
/* File System error number */
#define PFS_ERR_NOPACK 1 /* no memory card is plugged or */
#define PFS_ERR_NEW_PACK 2 /* ram pack has been changed to a */
/* different one */
#define PFS_ERR_INCONSISTENT 3 /* need to run Pfschecker */
#define PFS_ERR_CONTRFAIL CONT_OVERRUN_ERROR
#define PFS_ERR_INVALID 5 /* invalid parameter or file not exist*/
#define PFS_ERR_BAD_DATA 6 /* the data read from pack are bad*/
#define PFS_DATA_FULL 7 /* no free pages on ram pack */
#define PFS_DIR_FULL 8 /* no free directories on ram pack*/
#define PFS_ERR_EXIST 9 /* file exists */
#define PFS_ERR_ID_FATAL 10 /* dead ram pack */
#define PFS_ERR_DEVICE 11 /* wrong device type*/
/* definition for EEPROM */
#define EEPROM_MAXBLOCKS 64
#define EEP16K_MAXBLOCKS 256
#define EEPROM_BLOCK_SIZE 8
/*
* PI/EPI
*/
#define PI_DOMAIN1 0
#define PI_DOMAIN2 1
/*
* Profiler constants
*/
#define PROF_MIN_INTERVAL 50 /* microseconds */
/*
* Boot addresses
*/
#define BOOT_ADDRESS_ULTRA 0x80000400
#define BOOT_ADDRESS_COSIM 0x80002000
#define BOOT_ADDRESS_EMU 0x20010000
#define BOOT_ADDRESS_INDY 0x88100000
/*
* Size of buffer the retains contents after NMI
*/
#define OS_APP_NMI_BUFSIZE 64
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/* PARTNER-N64 */
#ifdef PTN64
#define osReadHost osReadHost_pt
#define osWriteHost osWriteHost_pt
#endif
/* Get count of valid messages in queue */
#define MQ_GET_COUNT(mq) ((mq)->validCount)
/* Figure out if message queue is empty or full */
#define MQ_IS_EMPTY(mq) (MQ_GET_COUNT(mq) == 0)
#define MQ_IS_FULL(mq) (MQ_GET_COUNT(mq) >= (mq)->msgCount)
/*
* CPU counter increments at 3/4 of bus clock rate:
*
* Bus Clock Proc Clock Counter (1/2 Proc Clock)
* --------- ---------- ------------------------
* 62.5 Mhz 93.75 Mhz 46.875 Mhz
*/
extern u64 osClockRate;
#define OS_CLOCK_RATE 62500000LL
#define OS_CPU_COUNTER (OS_CLOCK_RATE*3/4)
#define OS_NSEC_TO_CYCLES(n) (((u64)(n)*(OS_CPU_COUNTER/15625000LL))/(1000000000LL/15625000LL))
#define OS_USEC_TO_CYCLES(n) (((u64)(n)*(OS_CPU_COUNTER/15625LL))/(1000000LL/15625LL))
#define OS_CYCLES_TO_NSEC(c) (((u64)(c)*(1000000000LL/15625000LL))/(OS_CPU_COUNTER/15625000LL))
#define OS_CYCLES_TO_USEC(c) (((u64)(c)*(1000000LL/15625LL))/(OS_CPU_COUNTER/15625LL))
/**************************************************************************
*
* Extern variables
*
*/
extern OSViMode osViModeTable[]; /* Global VI mode table */
extern OSViMode osViModeNtscLpn1; /* Individual VI NTSC modes */
extern OSViMode osViModeNtscLpf1;
extern OSViMode osViModeNtscLan1;
extern OSViMode osViModeNtscLaf1;
extern OSViMode osViModeNtscLpn2;
extern OSViMode osViModeNtscLpf2;
extern OSViMode osViModeNtscLan2;
extern OSViMode osViModeNtscLaf2;
extern OSViMode osViModeNtscHpn1;
extern OSViMode osViModeNtscHpf1;
extern OSViMode osViModeNtscHan1;
extern OSViMode osViModeNtscHaf1;
extern OSViMode osViModeNtscHpn2;
extern OSViMode osViModeNtscHpf2;
extern OSViMode osViModePalLpn1; /* Individual VI PAL modes */
extern OSViMode osViModePalLpf1;
extern OSViMode osViModePalLan1;
extern OSViMode osViModePalLaf1;
extern OSViMode osViModePalLpn2;
extern OSViMode osViModePalLpf2;
extern OSViMode osViModePalLan2;
extern OSViMode osViModePalLaf2;
extern OSViMode osViModePalHpn1;
extern OSViMode osViModePalHpf1;
extern OSViMode osViModePalHan1;
extern OSViMode osViModePalHaf1;
extern OSViMode osViModePalHpn2;
extern OSViMode osViModePalHpf2;
extern OSViMode osViModeMpalLpn1; /* Individual VI MPAL modes */
extern OSViMode osViModeMpalLpf1;
extern OSViMode osViModeMpalLan1;
extern OSViMode osViModeMpalLaf1;
extern OSViMode osViModeMpalLpn2;
extern OSViMode osViModeMpalLpf2;
extern OSViMode osViModeMpalLan2;
extern OSViMode osViModeMpalLaf2;
extern OSViMode osViModeMpalHpn1;
extern OSViMode osViModeMpalHpf1;
extern OSViMode osViModeMpalHan1;
extern OSViMode osViModeMpalHaf1;
extern OSViMode osViModeMpalHpn2;
extern OSViMode osViModeMpalHpf2;
extern s32 osRomType; /* Bulk or cartridge ROM. 0=cartridge 1=bulk */
extern u32 osRomBase; /* Rom base address of the game image */
extern u32 osTvType; /* 0 = PAL, 1 = NTSC, 2 = MPAL */
extern u32 osResetType; /* 0 = cold reset, 1 = NMI */
extern s32 osCicId;
extern s32 osVersion;
extern u32 osMemSize; /* Memory Size */
extern s32 osAppNMIBuffer[];
extern OSIntMask __OSGlobalIntMask; /* global interrupt mask */
extern OSPiHandle *__osPiTable; /* The head of OSPiHandle link list */
extern OSPiHandle *__osDiskHandle; /* For exceptasm to get disk info*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Thread operations */
extern void osCreateThread(OSThread *, OSId, void (*)(void *),
void *, void *, OSPri);
extern void osDestroyThread(OSThread *);
extern void osYieldThread(void);
extern void osStartThread(OSThread *);
extern void osStopThread(OSThread *);
extern OSId osGetThreadId(OSThread *);
extern void osSetThreadPri(OSThread *, OSPri);
extern OSPri osGetThreadPri(OSThread *);
/* Message operations */
extern void osCreateMesgQueue(OSMesgQueue *, OSMesg *, s32);
extern s32 osSendMesg(OSMesgQueue *, OSMesg, s32);
extern s32 osJamMesg(OSMesgQueue *, OSMesg, s32);
extern s32 osRecvMesg(OSMesgQueue *, OSMesg *, s32);
/* Event operations */
extern void osSetEventMesg(OSEvent, OSMesgQueue *, OSMesg);
/* Interrupt operations */
extern OSIntMask osGetIntMask(void);
extern OSIntMask osSetIntMask(OSIntMask);
/* RDB port operations */
extern void osInitRdb(u8 *sendBuf, u32 sendSize);
/* Cache operations and macros */
extern void osInvalDCache(void *, size_t);
extern void osInvalICache(void *, size_t);
extern void osWritebackDCache(void *, size_t);
extern void osWritebackDCacheAll(void);
#define OS_DCACHE_ROUNDUP_ADDR(x) (void *)(((((u32)(x)+0xf)/0x10)*0x10))
#define OS_DCACHE_ROUNDUP_SIZE(x) (u32)(((((u32)(x)+0xf)/0x10)*0x10))
/* TLB management routines */
extern void osMapTLB(s32, OSPageMask, void *, u32, u32, s32);
extern void osMapTLBRdb(void);
extern void osUnmapTLB(s32);
extern void osUnmapTLBAll(void);
extern void osSetTLBASID(s32);
/* Address translation routines and macros */
extern u32 osVirtualToPhysical(void *);
extern void * osPhysicalToVirtual(u32);
#define OS_K0_TO_PHYSICAL(x) (u32)(((char *)(x)-0x80000000))
#define OS_K1_TO_PHYSICAL(x) (u32)(((char *)(x)-0xa0000000))
#define OS_PHYSICAL_TO_K0(x) (void *)(((u32)(x)+0x80000000))
#define OS_PHYSICAL_TO_K1(x) (void *)(((u32)(x)+0xa0000000))
/* I/O operations */
/* Audio interface (Ai) */
extern u32 osAiGetStatus(void);
extern u32 osAiGetLength(void);
extern s32 osAiSetFrequency(u32);
extern s32 osAiSetNextBuffer(void *, u32);
/* Display processor interface (Dp) */
extern u32 osDpGetStatus(void);
extern void osDpSetStatus(u32);
extern void osDpGetCounters(u32 *);
extern s32 osDpSetNextBuffer(void *, u64);
/* Peripheral interface (Pi) */
extern u32 osPiGetStatus(void);
extern s32 osPiGetDeviceType(void);
extern s32 osPiRawWriteIo(u32, u32);
extern s32 osPiRawReadIo(u32, u32 *);
extern s32 osPiRawStartDma(s32, u32, void *, u32);
extern s32 osPiWriteIo(u32, u32);
extern s32 osPiReadIo(u32, u32 *);
extern s32 osPiStartDma(OSIoMesg *, s32, s32, u32, void *, u32,
OSMesgQueue *);
extern void osCreatePiManager(OSPri, OSMesgQueue *, OSMesg *, s32);
/* Video interface (Vi) */
extern u32 osViGetStatus(void);
extern u32 osViGetCurrentMode(void);
extern u32 osViGetCurrentLine(void);
extern u32 osViGetCurrentField(void);
extern void *osViGetCurrentFramebuffer(void);
extern void *osViGetNextFramebuffer(void);
extern void osViSetXScale(f32);
extern void osViSetYScale(f32);
extern void osViSetSpecialFeatures(u32);
extern void osViSetMode(OSViMode *);
extern void osViSetEvent(OSMesgQueue *, OSMesg, u32);
extern void osViSwapBuffer(void *);
extern void osViBlack(u8);
extern void osViFade(u8, u16);
extern void osViRepeatLine(u8);
extern void osCreateViManager(OSPri);
/* Timer interface */
extern OSTime osGetTime(void);
extern void osSetTime(OSTime);
extern u32 osSetTimer(OSTimer *, OSTime, OSTime,
OSMesgQueue *, OSMesg);
extern int osStopTimer(OSTimer *);
/* Controller interface */
extern s32 osContInit(OSMesgQueue *, u8 *, OSContStatus *);
extern s32 osContReset(OSMesgQueue *, OSContStatus *);
extern s32 osContStartQuery(OSMesgQueue *);
extern s32 osContStartReadData(OSMesgQueue *);
#ifndef _HW_VERSION_1
extern s32 osContSetCh(u8);
#endif
extern void osContGetQuery(OSContStatus *);
extern void osContGetReadData(OSContPad *);
/* file system interface */
extern s32 osPfsInitPak(OSMesgQueue *, OSPfs *, int);
extern s32 osPfsRepairId(OSPfs *);
extern s32 osPfsInit(OSMesgQueue *, OSPfs *, int);
extern s32 osPfsReFormat(OSPfs *, OSMesgQueue *, int);
extern s32 osPfsChecker(OSPfs *);
extern s32 osPfsAllocateFile(OSPfs *, u16, u32, u8 *, u8 *, int, s32 *);
extern s32 osPfsFindFile(OSPfs *, u16, u32, u8 *, u8 *, s32 *);
extern s32 osPfsDeleteFile(OSPfs *, u16, u32, u8 *, u8 *);
extern s32 osPfsReadWriteFile(OSPfs *, s32, u8, int, int, u8 *);
extern s32 osPfsFileState(OSPfs *, s32, OSPfsState *);
extern s32 osPfsGetLabel(OSPfs *, u8 *, int *);
extern s32 osPfsSetLabel(OSPfs *, u8 *);
extern s32 osPfsIsPlug(OSMesgQueue *, u8 *);
extern s32 osPfsFreeBlocks(OSPfs *, s32 *);
extern s32 osPfsNumFiles(OSPfs *, s32 *, s32 *);
/* EEPROM interface */
extern s32 osEepromProbe(OSMesgQueue *);
extern s32 osEepromRead(OSMesgQueue *, u8, u8 *);
extern s32 osEepromWrite(OSMesgQueue *, u8, u8 *);
extern s32 osEepromLongRead(OSMesgQueue *, u8, u8 *, int);
extern s32 osEepromLongWrite(OSMesgQueue *, u8, u8 *, int);
/* MOTOR interface */
extern s32 osMotorInit(OSMesgQueue *, OSPfs *, int);
extern s32 osMotorStop(OSPfs *);
extern s32 osMotorStart(OSPfs *);
/* Enhanced PI interface */
extern OSPiHandle *osCartRomInit(void);
extern OSPiHandle *osLeoDiskInit(void);
extern OSPiHandle *osDriveRomInit(void);
extern s32 osEPiDeviceType(OSPiHandle *, OSPiInfo *);
extern s32 osEPiRawWriteIo(OSPiHandle *, u32 , u32);
extern s32 osEPiRawReadIo(OSPiHandle *, u32 , u32 *);
extern s32 osEPiRawStartDma(OSPiHandle *, s32 , u32 , void *, u32 );
extern s32 osEPiWriteIo(OSPiHandle *, u32 , u32 );
extern s32 osEPiReadIo(OSPiHandle *, u32 , u32 *);
extern s32 osEPiStartDma(OSPiHandle *, OSIoMesg *, s32);
extern s32 osEPiLinkHandle(OSPiHandle *);
/* Profiler Interface */
extern void osProfileInit(OSProf *, u32 profcnt);
extern void osProfileStart(u32);
extern void osProfileFlush(void);
extern void osProfileStop(void);
/* Game <> Host data transfer functions */
extern s32 osTestHost(void);
extern void osReadHost(void *, u32);
extern void osWriteHost(void *, u32);
extern void osAckRamromRead(void);
extern void osAckRamromWrite(void);
/* byte string operations */
extern void bcopy(const void *, void *, size_t);
extern int bcmp(const void *, const void *, int);
extern void bzero(void *, size_t);
/* Miscellaneous operations */
extern void osInitialize(void);
extern u32 osGetCount(void);
extern void osExit(void);
extern u32 osGetMemSize(void);
/* Printf */
extern int sprintf(char *s, const char *fmt, ...);
extern void osSyncPrintf(const char *fmt, ...);
extern void osAsyncPrintf(const char *fmt, ...);
extern int osSyncGetChars(char *buf);
extern int osAsyncGetChars(char *buf);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_H */
+92
View File
@@ -0,0 +1,92 @@
/*====================================================================
* os_ai.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_ai.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:04 $
*---------------------------------------------------------------------*/
#ifndef _OS_AI_H_
#define _OS_AI_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Audio interface (Ai) */
extern u32 osAiGetStatus(void);
extern u32 osAiGetLength(void);
extern s32 osAiSetFrequency(u32);
extern s32 osAiSetNextBuffer(void *, u32);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_AI_H_ */
+96
View File
@@ -0,0 +1,96 @@
/*====================================================================
* os_cache.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_cache.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:04 $
*---------------------------------------------------------------------*/
#ifndef _OS_CACHE_H_
#define _OS_CACHE_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
#define OS_DCACHE_ROUNDUP_ADDR(x) (void *)(((((u32)(x)+0xf)/0x10)*0x10))
#define OS_DCACHE_ROUNDUP_SIZE(x) (u32)(((((u32)(x)+0xf)/0x10)*0x10))
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Cache operations and macros */
extern void osInvalDCache(void *, size_t);
extern void osInvalICache(void *, size_t);
extern void osWritebackDCache(void *, size_t);
extern void osWritebackDCacheAll(void);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_CACHE_H_ */
+107
View File
@@ -0,0 +1,107 @@
/*====================================================================
* os_eeprom.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_eeprom.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:06 $
*---------------------------------------------------------------------*/
#ifndef _OS_EEPROM_H_
#define _OS_EEPROM_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#include "os_message.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
/* EEPROM TYPE */
#define EEPROM_TYPE_4K 0x01
#define EEPROM_TYPE_16K 0x02
/* definition for EEPROM */
#define EEPROM_MAXBLOCKS 64
#define EEP16K_MAXBLOCKS 256
#define EEPROM_BLOCK_SIZE 8
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* EEPROM interface */
extern s32 osEepromProbe(OSMesgQueue *);
extern s32 osEepromRead(OSMesgQueue *, u8, u8 *);
extern s32 osEepromWrite(OSMesgQueue *, u8, u8 *);
extern s32 osEepromLongRead(OSMesgQueue *, u8, u8 *, int);
extern s32 osEepromLongWrite(OSMesgQueue *, u8, u8 *, int);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_EEPROM_H_ */
+119
View File
@@ -0,0 +1,119 @@
/*====================================================================
* os_exception.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_exception.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:07 $
*---------------------------------------------------------------------*/
#ifndef _OS_EXCEPTION_H_
#define _OS_EXCEPTION_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
typedef u32 OSIntMask;
typedef u32 OSHWIntr;
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
/* Flags for debugging purpose */
#define OS_FLAG_CPU_BREAK 1 /* Break exception has occurred */
#define OS_FLAG_FAULT 2 /* CPU fault has occurred */
/* Interrupt masks */
#define OS_IM_NONE 0x00000001
#define OS_IM_SW1 0x00000501
#define OS_IM_SW2 0x00000601
#define OS_IM_CART 0x00000c01
#define OS_IM_PRENMI 0x00001401
#define OS_IM_RDBWRITE 0x00002401
#define OS_IM_RDBREAD 0x00004401
#define OS_IM_COUNTER 0x00008401
#define OS_IM_CPU 0x0000ff01
#define OS_IM_SP 0x00010401
#define OS_IM_SI 0x00020401
#define OS_IM_AI 0x00040401
#define OS_IM_VI 0x00080401
#define OS_IM_PI 0x00100401
#define OS_IM_DP 0x00200401
#define OS_IM_ALL 0x003fff01
#define RCP_IMASK 0x003f0000
#define RCP_IMASKSHIFT 16
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Interrupt operations */
extern OSIntMask osGetIntMask(void);
extern OSIntMask osSetIntMask(OSIntMask);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_EXCEPTION_H_ */
+19
View File
@@ -0,0 +1,19 @@
#ifndef _ULTRA64_OS_INTERNAL_H_
#define _ULTRA64_OS_INTERNAL_H_
#include "os_message.h"
/* Internal functions used by the operating system */
/* Do not include this header in application code */
/* Variables */
//extern u64 osClockRate;
/* Functions */
/*u32 __osProbeTLB(void *);
u32 __osDisableInt(void);
void __osRestoreInt(u32);*/
OSThread *__osGetCurrFaultedThread(void);
#endif
+10
View File
@@ -0,0 +1,10 @@
#ifndef _OS_LIBC_H_
#define _OS_LIBC_H_
#include "ultratypes.h"
// Old deprecated functions from strings.h, replaced by memcpy/memset.
extern void bcopy(const void *, void *, size_t);
extern void bzero(void *, size_t);
#endif /* !_OS_LIBC_H_ */
+164
View File
@@ -0,0 +1,164 @@
/*====================================================================
* os_message.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_message.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:15 $
*---------------------------------------------------------------------*/
#ifndef _OS_MESSAGE_H_
#define _OS_MESSAGE_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#include "os_thread.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
typedef u32 OSEvent;
/*
* Structure for message
*/
typedef void * OSMesg;
/*
* Structure for message queue
*/
typedef struct OSMesgQueue_s {
OSThread *mtqueue; /* Queue to store threads blocked
on empty mailboxes (receive) */
OSThread *fullqueue; /* Queue to store threads blocked
on full mailboxes (send) */
s32 validCount; /* Contains number of valid message */
s32 first; /* Points to first valid message */
s32 msgCount; /* Contains total # of messages */
OSMesg *msg; /* Points to message buffer array */
} OSMesgQueue;
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
/* Events */
#ifdef _FINALROM
#define OS_NUM_EVENTS 15
#else
#define OS_NUM_EVENTS 23
#endif
#define OS_EVENT_SW1 0 /* CPU SW1 interrupt */
#define OS_EVENT_SW2 1 /* CPU SW2 interrupt */
#define OS_EVENT_CART 2 /* Cartridge interrupt: used by rmon */
#define OS_EVENT_COUNTER 3 /* Counter int: used by VI/Timer Mgr */
#define OS_EVENT_SP 4 /* SP task done interrupt */
#define OS_EVENT_SI 5 /* SI (controller) interrupt */
#define OS_EVENT_AI 6 /* AI interrupt */
#define OS_EVENT_VI 7 /* VI interrupt: used by VI/Timer Mgr */
#define OS_EVENT_PI 8 /* PI interrupt: used by PI Manager */
#define OS_EVENT_DP 9 /* DP full sync interrupt */
#define OS_EVENT_CPU_BREAK 10 /* CPU breakpoint: used by rmon */
#define OS_EVENT_SP_BREAK 11 /* SP breakpoint: used by rmon */
#define OS_EVENT_FAULT 12 /* CPU fault event: used by rmon */
#define OS_EVENT_THREADSTATUS 13 /* CPU thread status: used by rmon */
#define OS_EVENT_PRENMI 14 /* Pre NMI interrupt */
#ifndef _FINALROM
#define OS_EVENT_RDB_READ_DONE 15 /* RDB read ok event: used by rmon */
#define OS_EVENT_RDB_LOG_DONE 16 /* read of log data complete */
#define OS_EVENT_RDB_DATA_DONE 17 /* read of hostio data complete */
#define OS_EVENT_RDB_REQ_RAMROM 18 /* host needs ramrom access */
#define OS_EVENT_RDB_FREE_RAMROM 19 /* host is done with ramrom access */
#define OS_EVENT_RDB_DBG_DONE 20
#define OS_EVENT_RDB_FLUSH_PROF 21
#define OS_EVENT_RDB_ACK_PROF 22
#endif
/* Flags to turn blocking on/off when sending/receiving message */
#define OS_MESG_NOBLOCK 0
#define OS_MESG_BLOCK 1
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/* Get count of valid messages in queue */
#define MQ_GET_COUNT(mq) ((mq)->validCount)
/* Figure out if message queue is empty or full */
#define MQ_IS_EMPTY(mq) (MQ_GET_COUNT(mq) == 0)
#define MQ_IS_FULL(mq) (MQ_GET_COUNT(mq) >= (mq)->msgCount)
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Message operations */
extern void osCreateMesgQueue(OSMesgQueue *, OSMesg *, s32);
extern s32 osSendMesg(OSMesgQueue *, OSMesg, s32);
extern s32 osJamMesg(OSMesgQueue *, OSMesg, s32);
extern s32 osRecvMesg(OSMesgQueue *, OSMesg *, s32);
/* Event operations */
extern void osSetEventMesg(OSEvent, OSMesgQueue *, OSMesg);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_MESSAGE_H_ */
+11
View File
@@ -0,0 +1,11 @@
#ifndef _ULTRA64_OS_MISC_H_
#define _ULTRA64_OS_MISC_H_
#include "ultratypes.h"
/* Miscellaneous OS functions */
void osInitialize(void);
u32 osGetCount(void);
uintptr_t osVirtualToPhysical(void *);
#endif
+88
View File
@@ -0,0 +1,88 @@
#ifndef _ULTRA64_PI_H_
#define _ULTRA64_PI_H_
#include <ultra64.h>
/* Ultra64 Parallel Interface */
/* Types */
typedef struct {
#if !defined(VERSION_EU)
u32 errStatus;
#endif
void *dramAddr;
void *C2Addr;
u32 sectorSize;
u32 C1ErrNum;
u32 C1ErrSector[4];
} __OSBlockInfo;
typedef struct {
u32 cmdType; // 0
u16 transferMode; // 4
u16 blockNum; // 6
s32 sectorNum; // 8
uintptr_t devAddr; // c
#if defined(VERSION_EU)
u32 errStatus; //error status added moved to blockinfo
#endif
u32 bmCtlShadow; // 10
u32 seqCtlShadow; // 14
__OSBlockInfo block[2]; // 18
} __OSTranxInfo;
typedef struct OSPiHandle_s {
struct OSPiHandle_s *next;
u8 type;
u8 latency;
u8 pageSize;
u8 relDuration;
u8 pulse;
u8 domain;
u32 baseAddress;
u32 speed;
__OSTranxInfo transferInfo;
} OSPiHandle;
typedef struct {
u8 type;
uintptr_t address;
} OSPiInfo;
typedef struct {
u16 type;
u8 pri;
u8 status;
OSMesgQueue *retQueue;
} OSIoMesgHdr;
typedef struct {
/*0x00*/ OSIoMesgHdr hdr;
/*0x08*/ void *dramAddr;
/*0x0C*/ uintptr_t devAddr;
/*0x10*/ size_t size;
#if defined(VERSION_EU) || defined(VERSION_SH)
OSPiHandle *piHandle; // from the official definition
#endif
} OSIoMesg;
/* Definitions */
#define OS_READ 0 // device -> RDRAM
#define OS_WRITE 1 // device <- RDRAM
#define OS_MESG_PRI_NORMAL 0
#define OS_MESG_PRI_HIGH 1
/* Functions */
s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, uintptr_t devAddr, void *vAddr,
size_t nbytes, OSMesgQueue *mq);
void osCreatePiManager(OSPri pri, OSMesgQueue *cmdQ, OSMesg *cmdBuf, s32 cmdMsgCnt);
OSMesgQueue *osPiGetCmdQueue(void);
s32 osPiWriteIo(uintptr_t devAddr, u32 data);
s32 osPiReadIo(uintptr_t devAddr, u32 *data);
s32 osPiRawStartDma(s32 dir, u32 cart_addr, void *dram_addr, size_t size);
s32 osEPiRawStartDma(OSPiHandle *piHandle, s32 dir, u32 cart_addr, void *dram_addr, size_t size);
#endif
+92
View File
@@ -0,0 +1,92 @@
/*====================================================================
* os_rdp.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_rdp.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:16 $
*---------------------------------------------------------------------*/
#ifndef _OS_RDP_H_
#define _OS_RDP_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* Display processor interface (Dp) */
extern u32 osDpGetStatus(void);
extern void osDpSetStatus(u32);
extern void osDpGetCounters(u32 *);
extern s32 osDpSetNextBuffer(void *, u64);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_RDP_H_ */
+75
View File
@@ -0,0 +1,75 @@
#ifndef _ULTRA64_THREAD_H_
#define _ULTRA64_THREAD_H_
#include "ultratypes.h"
/* Recommended priorities for system threads */
#define OS_PRIORITY_MAX 255
#define OS_PRIORITY_VIMGR 254
#define OS_PRIORITY_RMON 250
#define OS_PRIORITY_RMONSPIN 200
#define OS_PRIORITY_PIMGR 150
#define OS_PRIORITY_SIMGR 140
#define OS_PRIORITY_APPMAX 127
#define OS_PRIORITY_IDLE 0
#define OS_STATE_STOPPED 1
#define OS_STATE_RUNNABLE 2
#define OS_STATE_RUNNING 4
#define OS_STATE_WAITING 8
/* Types */
typedef s32 OSPri;
typedef s32 OSId;
typedef union
{
struct {f32 f_odd; f32 f_even;} f;
} __OSfp;
typedef struct
{
/* registers */
/*0x20*/ u64 at, v0, v1, a0, a1, a2, a3;
/*0x58*/ u64 t0, t1, t2, t3, t4, t5, t6, t7;
/*0x98*/ u64 s0, s1, s2, s3, s4, s5, s6, s7;
/*0xD8*/ u64 t8, t9, gp, sp, s8, ra;
/*0x108*/ u64 lo, hi;
/*0x118*/ u32 sr, pc, cause, badvaddr, rcp;
/*0x12C*/ u32 fpcsr;
__OSfp fp0, fp2, fp4, fp6, fp8, fp10, fp12, fp14;
__OSfp fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30;
} __OSThreadContext;
typedef struct
{
u32 flag;
u32 count;
u64 time;
} __OSThreadprofile_s;
typedef struct OSThread_s
{
/*0x00*/ struct OSThread_s *next;
/*0x04*/ OSPri priority;
/*0x08*/ struct OSThread_s **queue;
/*0x0C*/ struct OSThread_s *tlnext;
/*0x10*/ u16 state;
/*0x12*/ u16 flags;
/*0x14*/ OSId id;
/*0x18*/ int fp;
/*0x1C*/ __OSThreadprofile_s *thprof;
/*0x20*/ __OSThreadContext context;
} OSThread;
/* Functions */
void osCreateThread(OSThread *thread, OSId id, void (*entry)(void *),
void *arg, void *sp, OSPri pri);
OSId osGetThreadId(OSThread *thread);
OSPri osGetThreadPri(OSThread *thread);
void osSetThreadPri(OSThread *thread, OSPri pri);
void osStartThread(OSThread *thread);
void osStopThread(OSThread *thread);
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef _ULTRA64_TIME_H_
#define _ULTRA64_TIME_H_
#include "ultratypes.h"
#include "os_message.h"
/* Types */
typedef struct OSTimer_str
{
struct OSTimer_str *next;
struct OSTimer_str *prev;
u64 interval;
u64 remaining;
OSMesgQueue *mq;
OSMesg *msg;
} OSTimer;
typedef u64 OSTime;
/* Functions */
OSTime osGetTime(void);
void osSetTime(OSTime time);
u32 osSetTimer(OSTimer *, OSTime, OSTime, OSMesgQueue *, OSMesg);
#endif
+107
View File
@@ -0,0 +1,107 @@
/*====================================================================
* os_tlb.h
*
* Copyright 1995, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
/*---------------------------------------------------------------------*
Copyright (C) 1998 Nintendo. (Originated by SGI)
$RCSfile: os_tlb.h,v $
$Revision: 1.1 $
$Date: 1998/10/09 08:01:20 $
*---------------------------------------------------------------------*/
#ifndef _OS_TLB_H_
#define _OS_TLB_H_
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
#include "ultratypes.h"
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Type definitions
*
*/
typedef u32 OSPageMask;
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
/**************************************************************************
*
* Global definitions
*
*/
/*
* Page size argument for TLB routines
*/
#define OS_PM_4K 0x0000000
#define OS_PM_16K 0x0006000
#define OS_PM_64K 0x001e000
#define OS_PM_256K 0x007e000
#define OS_PM_1M 0x01fe000
#define OS_PM_4M 0x07fe000
#define OS_PM_16M 0x1ffe000
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
/**************************************************************************
*
* Macro definitions
*
*/
/**************************************************************************
*
* Extern variables
*
*/
/**************************************************************************
*
* Function prototypes
*
*/
/* TLB management routines */
extern void osMapTLB(s32, OSPageMask, void *, u32, u32, s32);
extern void osMapTLBRdb(void);
extern void osUnmapTLB(s32);
extern void osUnmapTLBAll(void);
extern void osSetTLBASID(s32);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
#ifdef _LANGUAGE_C_PLUS_PLUS
}
#endif
#endif /* !_OS_TLB_H_ */
+117
View File
@@ -0,0 +1,117 @@
#ifndef _ULTRA64_VI_H_
#define _ULTRA64_VI_H_
#include "ultratypes.h"
#include "os_message.h"
/* Ultra64 Video Interface */
/* Special Features */
#define OS_VI_GAMMA_ON 0x0001
#define OS_VI_GAMMA_OFF 0x0002
#define OS_VI_GAMMA_DITHER_ON 0x0004
#define OS_VI_GAMMA_DITHER_OFF 0x0008
#define OS_VI_DIVOT_ON 0x0010
#define OS_VI_DIVOT_OFF 0x0020
#define OS_VI_DITHER_FILTER_ON 0x0040
#define OS_VI_DITHER_FILTER_OFF 0x0080
#define OS_VI_GAMMA 0x08
#define OS_VI_GAMMA_DITHER 0x04
#define OS_VI_DIVOT 0x10
#define OS_VI_DITHER_FILTER 0x10000
#define OS_VI_UNK200 0x200
#define OS_VI_UNK100 0x100
/* Types */
typedef struct
{
u32 ctrl;
u32 width;
u32 burst;
u32 vSync;
u32 hSync;
u32 leap;
u32 hStart;
u32 xScale;
u32 vCurrent;
} OSViCommonRegs;
typedef struct
{
u32 origin;
u32 yScale;
u32 vStart;
u32 vBurst;
u32 vIntr;
} OSViFieldRegs;
typedef struct
{
u8 type;
OSViCommonRegs comRegs;
OSViFieldRegs fldRegs[2];
} OSViMode;
typedef struct
{
/* 0x00 */ u16 unk00; //some kind of flags. swap buffer sets to 0x10
/* 0x02 */ u16 retraceCount;
/* 0x04 */ void* buffer;
/* 0x08 */ OSViMode *modep;
/* 0x0c */ u32 features;
/* 0x10 */ OSMesgQueue *mq;
/* 0x14 */ OSMesg *msg;
/* 0x18 */ u32 unk18;
/* 0x1c */ u32 unk1c;
/* 0x20 */ u32 unk20;
/* 0x24 */ f32 unk24;
/* 0x28 */ u16 unk28;
/* 0x2c */ u32 unk2c;
} OSViContext;
void osCreateViManager(OSPri pri);
void osViSetMode(OSViMode *mode);
void osViSetEvent(OSMesgQueue *mq, OSMesg msg, u32 retraceCount);
void osViBlack(u8 active);
void osViSetSpecialFeatures(u32 func);
void osViSwapBuffer(void *vaddr);
#define OS_VI_NTSC_LPN1 0 /* NTSC */
#define OS_VI_NTSC_LPF1 1
#define OS_VI_NTSC_LAN1 2
#define OS_VI_NTSC_LAF1 3
#define OS_VI_NTSC_LPN2 4
#define OS_VI_NTSC_LPF2 5
#define OS_VI_NTSC_LAN2 6
#define OS_VI_NTSC_LAF2 7
#define OS_VI_NTSC_HPN1 8
#define OS_VI_NTSC_HPF1 9
#define OS_VI_NTSC_HAN1 10
#define OS_VI_NTSC_HAF1 11
#define OS_VI_NTSC_HPN2 12
#define OS_VI_NTSC_HPF2 13
#define OS_VI_PAL_LPN1 14 /* PAL */
#define OS_VI_PAL_LPF1 15
#define OS_VI_PAL_LAN1 16
#define OS_VI_PAL_LAF1 17
#define OS_VI_PAL_LPN2 18
#define OS_VI_PAL_LPF2 19
#define OS_VI_PAL_LAN2 20
#define OS_VI_PAL_LAF2 21
#define OS_VI_PAL_HPN1 22
#define OS_VI_PAL_HPF1 23
#define OS_VI_PAL_HAN1 24
#define OS_VI_PAL_HAF1 25
#define OS_VI_PAL_HPN2 26
#define OS_VI_PAL_HPF2 27
extern OSViMode osViModeTable[]; /* Global VI mode table */
#endif
+116
View File
@@ -0,0 +1,116 @@
#ifndef _ULTRA64_SPTASK_H_
#define _ULTRA64_SPTASK_H_
/* Task Types */
#define M_GFXTASK 1
#define M_AUDTASK 2
#define M_VIDTASK 3
#define M_HVQTASK 6
#define M_HVQMTASK 7
#if (defined(F3DEX_GBI) || defined(F3DLP_GBI) || defined(F3DEX_GBI_2))
#define OS_YIELD_DATA_SIZE 0xc00
#else
#define OS_YIELD_DATA_SIZE 0x900
#endif
#define OS_YIELD_AUDIO_SIZE 0x400
/* Flags */
#define M_TASK_FLAG0 1
#define M_TASK_FLAG1 2
#ifdef VERSION_SH
#define M_TASK_FLAG2 4
#endif
/* SpStatus */
#define SPSTATUS_CLEAR_HALT 0x00000001
#define SPSTATUS_SET_HALT 0x00000002
#define SPSTATUS_CLEAR_BROKE 0x00000004
#define SPSTATUS_CLEAR_INTR 0x00000008
#define SPSTATUS_SET_INTR 0x00000010
#define SPSTATUS_CLEAR_SSTEP 0x00000020
#define SPSTATUS_SET_SSTEP 0x00000040
#define SPSTATUS_CLEAR_INTR_ON_BREAK 0x00000080
#define SPSTATUS_SET_INTR_ON_BREAK 0x00000100
#define SPSTATUS_CLEAR_SIGNAL0 0x00000200
#define SPSTATUS_SET_SIGNAL0 0x00000400
#define SPSTATUS_CLEAR_SIGNAL1 0x00000800
#define SPSTATUS_SET_SIGNAL1 0x00001000
#define SPSTATUS_CLEAR_SIGNAL2 0x00002000
#define SPSTATUS_SET_SIGNAL2 0x00004000
#define SPSTATUS_CLEAR_SIGNAL3 0x00008000
#define SPSTATUS_SET_SIGNAL3 0x00010000
#define SPSTATUS_CLEAR_SIGNAL4 0x00020000
#define SPSTATUS_SET_SIGNAL4 0x00040000
#define SPSTATUS_CLEAR_SIGNAL5 0x00080000
#define SPSTATUS_SET_SIGNAL5 0x00100000
#define SPSTATUS_CLEAR_SIGNAL6 0x00200000
#define SPSTATUS_SET_SIGNAL6 0x00800000
#define SPSTATUS_CLEAR_SIGNAL7 0x01000000
#define SPSTATUS_SET_SIGNAL7 0x02000000
#define SPSTATUS_HALT 0x0001
#define SPSTATUS_BROKE 0x0002
#define SPSTATUS_DMA_BUSY 0x0004
#define SPSTATUS_DMA_FULL 0x0008
#define SPSTATUS_IO_FULL 0x0010
#define SPSTATUS_SINGLE_STEP 0x0020
#define SPSTATUS_INTERRUPT_ON_BREAK 0x0040
#define SPSTATUS_SIGNAL0_SET 0x0080
#define SPSTATUS_SIGNAL1_SET 0x0100
#define SPSTATUS_SIGNAL2_SET 0x0200
#define SPSTATUS_SIGNAL3_SET 0x0400
#define SPSTATUS_SIGNAL4_SET 0x0800
#define SPSTATUS_SIGNAL5_SET 0x1000
#define SPSTATUS_SIGNAL6_SET 0x2000
#define SPSTATUS_SIGNAL7_SET 0x4000
/* Types */
/* Types */
typedef struct
{
/*0x00*/ u32 type;
/*0x04*/ u32 flags;
/*0x08*/ u64 *ucode_boot;
/*0x0C*/ u32 ucode_boot_size;
/*0x10*/ u64 *ucode;
/*0x14*/ u32 ucode_size;
/*0x18*/ u64 *ucode_data;
/*0x1C*/ u32 ucode_data_size;
/*0x20*/ u64 *dram_stack;
/*0x24*/ u32 dram_stack_size;
/*0x28*/ u64 *output_buff;
/*0x2C*/ u64 *output_buff_size;
/*0x30*/ u64 *data_ptr;
/*0x34*/ u32 data_size;
/*0x38*/ u64 *yield_data_ptr;
/*0x3C*/ u32 yield_data_size;
} OSTask_t; // size = 0x40
typedef union {
OSTask_t t;
long long int force_structure_alignment;
} OSTask;
typedef u32 OSYieldResult;
/* Functions */
#define osSpTaskStart(p) \
osSpTaskLoad(p); \
osSpTaskStartGo(p);
void osSpTaskLoad(OSTask *task);
void osSpTaskStartGo(OSTask *task);
void osSpTaskYield(void);
OSYieldResult osSpTaskYielded(OSTask *task);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef _ULTRA64_UCODE_H_
#define _ULTRA64_UCODE_H_
#define SP_DRAM_STACK_SIZE8 0x400
#define SP_UCODE_SIZE 0x1000
#define SP_UCODE_DATA_SIZE 0x800
// standard boot ucode
extern u64 rspF3DBootStart[], rspF3DBootEnd[];
// F3D ucode
extern u64 rspF3DStart[], rspF3DEnd[];
// F3D ucode data
extern u64 rspF3DDataStart[], rspF3DDataEnd[];
// aspMain (audio) ucode
extern u64 rspAspMainStart[], rspAspMainEnd[];
// aspMain ucode data
extern u64 rspAspMainDataStart[], rspAspMainDataEnd[];
#endif
+35
View File
@@ -21,21 +21,56 @@
#define SOUNDARGS_SHIFT_SOUNDID 16 #define SOUNDARGS_SHIFT_SOUNDID 16
#define SOUNDARGS_SHIFT_PRIORITY 8 #define SOUNDARGS_SHIFT_PRIORITY 8
/* Sound banks */
#define SOUND_BANK_ACTION 0
#define SOUND_BANK_MOVING 1
#define SOUND_BANK_VOICE 2
#define SOUND_BANK_GENERAL 3
#define SOUND_BANK_ENV 4
#define SOUND_BANK_OBJ 5
#define SOUND_BANK_AIR 6
#define SOUND_BANK_MENU 7
#define SOUND_BANK_GENERAL2 8
#define SOUND_BANK_OBJ2 9
#define SOUND_BANK_COUNT 10
#define SOUND_BANKS_ALL_BITS 0xffff
#define SOUND_BANKS_ALL ((1 << SOUND_BANK_COUNT) - 1)
#define SOUND_BANKS_FOREGROUND (\
(1 << SOUND_BANK_ACTION) |\
(1 << SOUND_BANK_VOICE) |\
(1 << SOUND_BANK_MENU))
#define SOUND_BANKS_BACKGROUND (SOUND_BANKS_ALL & ~SOUND_BANKS_FOREGROUND)
#define SOUND_BANKS_DISABLED_DURING_INTRO_CUTSCENE (\
(1 << SOUND_BANK_ENV) |\
(1 << SOUND_BANK_OBJ) |\
(1 << SOUND_BANK_GENERAL2) |\
(1 << SOUND_BANK_OBJ2))
#define SOUND_BANKS_DISABLED_AFTER_CREDITS (\
(1 << SOUND_BANK_ACTION) |\
(1 << SOUND_BANK_MOVING) |\
(1 << SOUND_BANK_VOICE) |\
(1 << SOUND_BANK_GENERAL))
/* Audio Status */ /* Audio Status */
#define SOUND_STATUS_STOPPED 0 #define SOUND_STATUS_STOPPED 0
#define SOUND_STATUS_STARTING 1 #define SOUND_STATUS_STARTING 1
#define SOUND_STATUS_WAITING SOUND_STATUS_STARTING
#define SOUND_STATUS_PLAYING 2 #define SOUND_STATUS_PLAYING 2
/* Audio lower bitflags. TODO: Figure out what these mean and use them below. */ /* Audio lower bitflags. TODO: Figure out what these mean and use them below. */
#define SOUND_LO_BITFLAG_UNK1 0x10 // fade in? #define SOUND_LO_BITFLAG_UNK1 0x10 // fade in?
#define SOUND_LOWER_BACKGROUND_MUSIC SOUND_LO_BITFLAG_UNK1
#define SOUND_NO_ECHO 0x20 // not in JP #define SOUND_NO_ECHO 0x20 // not in JP
#define SOUND_LO_BITFLAG_UNK8 0x80 // restart playing on each play_sound call? #define SOUND_LO_BITFLAG_UNK8 0x80 // restart playing on each play_sound call?
#define SOUND_DISCRETE SOUND_LO_BITFLAG_UNK8
/* Audio playback bitflags. */ /* Audio playback bitflags. */
#define SOUND_NO_VOLUME_LOSS 0x1000000 // No volume loss with distance #define SOUND_NO_VOLUME_LOSS 0x1000000 // No volume loss with distance
#define SOUND_VIBRATO 0x2000000 // Randomly alter frequency each audio frame #define SOUND_VIBRATO 0x2000000 // Randomly alter frequency each audio frame
#define SOUND_NO_PRIORITY_LOSS 0x4000000 // Do not prioritize closer sounds #define SOUND_NO_PRIORITY_LOSS 0x4000000 // Do not prioritize closer sounds
#define SOUND_NO_FREQUENCY_LOSS 0x8000000 // Frequency scale does not change with distance #define SOUND_NO_FREQUENCY_LOSS 0x8000000 // Frequency scale does not change with distance
#define SOUND_CONSTANT_FREQUENCY SOUND_NO_FREQUENCY_LOSS
// silence // silence
#define NO_SOUND 0 #define NO_SOUND 0
+1 -1
View File
@@ -10,6 +10,6 @@
#define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#endif #endif
#define DOUBLE_SIZE_ON_64_BIT(size) ((size) * (sizeof(void *) / 4)) #define DOUBLE_SIZE_ON_64_BIT(size) ((size) * 2)
#endif // PLATFORM_INFO_H #endif // PLATFORM_INFO_H
+14 -14
View File
@@ -4,7 +4,7 @@
// This file contains various data types used in Super Mario 64 that don't yet // This file contains various data types used in Super Mario 64 that don't yet
// have an appropriate header. // have an appropriate header.
// #include <ultra64.h> #include "ultra64.h"
#include "macros.h" #include "macros.h"
#include "PR/ultratypes.h" #include "PR/ultratypes.h"
@@ -62,19 +62,19 @@ enum SpTaskState {
SPTASK_STATE_FINISHED_DP SPTASK_STATE_FINISHED_DP
}; };
// struct SPTask struct SPTask
// { {
// /*0x00*/ OSTask task; /*0x00*/ OSTask task;
// /*0x40*/ OSMesgQueue *msgqueue; /*0x40*/ OSMesgQueue *msgqueue;
// /*0x44*/ OSMesg msg; /*0x44*/ OSMesg msg;
// /*0x48*/ enum SpTaskState state; /*0x48*/ enum SpTaskState state;
// }; // size = 0x4C, align = 0x8 }; // size = 0x4C, align = 0x8
//
// struct VblankHandler struct VblankHandler
// { {
// OSMesgQueue *queue; OSMesgQueue *queue;
// OSMesg msg; OSMesg msg;
// }; };
#define ANIM_FLAG_NOLOOP (1 << 0) // 0x01 #define ANIM_FLAG_NOLOOP (1 << 0) // 0x01
#define ANIM_FLAG_FORWARD (1 << 1) // 0x02 #define ANIM_FLAG_FORWARD (1 << 1) // 0x02
+31
View File
@@ -0,0 +1,31 @@
#ifndef _ULTRA64_H_
#define _ULTRA64_H_
#include <math.h>
#ifndef _LANGUAGE_C
#define _LANGUAGE_C
#endif
#include "PR/ultratypes.h"
#include "PR/os_exception.h"
#include "PR/os_misc.h"
#include "PR/os_rdp.h"
#include "PR/os_thread.h"
#include "PR/os_time.h"
#include "PR/os_message.h"
#include "PR/os_cont.h"
#include "PR/os_tlb.h"
#include "PR/sptask.h"
#include "PR/ucode.h"
#include "PR/os_cache.h"
#include "PR/os_vi.h"
#include "PR/os_pi.h"
#include "PR/os_internal.h"
#include "PR/os_eeprom.h"
#include "PR/os_libc.h"
#include "PR/os_ai.h"
#include "PR/libaudio.h"
#include "PR/libultra.h"
#endif
+93
View File
@@ -0,0 +1,93 @@
#include "libultra_internal.h"
#include "libaudio_internal.h"
#define PATCH(SRC, BASE, TYPE) //SRC = (TYPE)((uintptr_t) SRC + (uintptr_t) BASE)
void alSeqFileNew(ALSeqFile *f, u8 *base) {
int i;
for (i = 0; i < f->seqCount; i++) {
PATCH(f->seqArray[i].offset, base, u8 *);
}
}
static void _bnkfPatchBank(ALInstrument *inst, ALBankFile *f, u8 *table) {
int i;
ALSound *sound;
ALWaveTable *wavetable;
u8 *table2;
if (inst->flags) {
return;
}
inst->flags = 1;
for (i = 0; i < inst->soundCount; i++) {
PATCH(inst->soundArray[i], f, ALSound *);
sound = inst->soundArray[i];
if (sound->flags) {
continue;
}
table2 = table;
sound->flags = 1;
PATCH(sound->envelope, f, ALEnvelope *);
PATCH(sound->keyMap, f, ALKeyMap *);
PATCH(sound->wavetable, f, ALWaveTable *);
wavetable = sound->wavetable;
if (wavetable->flags) {
continue;
}
wavetable->flags = 1;
PATCH(wavetable->base, table2, u8 *);
if (wavetable->type == 0) {
PATCH(wavetable->waveInfo.adpcmWave.book, f, ALADPCMBook *);
if (wavetable->waveInfo.adpcmWave.loop != NULL) {
PATCH(wavetable->waveInfo.adpcmWave.loop, f, ALADPCMloop *);
}
} else if (wavetable->type == 1) {
if (wavetable->waveInfo.rawWave.loop != NULL) {
PATCH(wavetable->waveInfo.rawWave.loop, f, ALRawLoop *);
}
}
}
}
// Force adding another jr $ra. Has to be called or it doesn't get put in the
// right place.
static void unused(void) {
}
void alBnkfNew(ALBankFile *f, u8 *table) {
ALBank *bank;
int i;
int j;
unused();
if (f->revision != AL_BANK_VERSION) {
return;
}
for (i = 0; i < f->bankCount; i++) {
PATCH(f->bankArray[i], f, ALBank *);
if (f->bankArray[i] == NULL) {
continue;
}
bank = f->bankArray[i];
if (bank->flags == 0) {
bank->flags = 1;
if (bank->percussion != NULL) {
PATCH(bank->percussion, f, ALInstrument *);
_bnkfPatchBank(bank->percussion, f, table);
}
for (j = 0; j < bank->instCount; j++) {
PATCH(bank->instArray[j], f, ALInstrument *);
if (bank->instArray[j] != NULL) {
_bnkfPatchBank(bank->instArray[j], f, table);
}
}
}
}
}
+127
View File
@@ -0,0 +1,127 @@
#ifndef _LIBAUDIO_INTERNAL_H_
#define _LIBAUDIO_INTERNAL_H_
#include <ultra64.h>
#define AL_BANK_VERSION 0x4231 /* 'B1' */
typedef u8 ALPan;
typedef s32 ALMicroTime;
/* Possible wavetable types */
enum
{
AL_ADPCM_WAVE = 0,
AL_RAW16_WAVE
};
typedef struct
{
u32 start;
u32 end;
u32 count;
} ALRawLoop;
typedef struct
{
u32 start;
u32 end;
u32 count;
ADPCM_STATE state;
} ALADPCMloop;
typedef struct
{
s32 order;
s32 npredictors;
s16 book[1]; // variable size, 8-byte aligned
} ALADPCMBook;
typedef struct
{
ALMicroTime attackTime;
ALMicroTime decayTime;
ALMicroTime releaseTime;
u8 attackVolume;
u8 decayVolume;
} ALEnvelope;
typedef struct
{
u8 velocityMin;
u8 velocityMax;
u8 keyMin;
u8 keyMax;
u8 keyBase;
s8 detune;
} ALKeyMap;
typedef struct
{
ALADPCMloop *loop;
ALADPCMBook *book;
} ALADPCMWaveInfo;
typedef struct
{
ALRawLoop *loop;
} ALRAWWaveInfo;
typedef struct ALWaveTable_s
{
u8 *base; /* ptr to start of wave data */
s32 len; /* length of data in bytes */
u8 type; /* compression type */
u8 flags; /* offset/address flags */
union {
ALADPCMWaveInfo adpcmWave;
ALRAWWaveInfo rawWave;
} waveInfo;
} ALWaveTable;
typedef struct ALSound_s
{
ALEnvelope *envelope;
ALKeyMap *keyMap;
ALWaveTable *wavetable; /* offset to wavetable struct */
ALPan samplePan;
u8 sampleVolume;
u8 flags;
} ALSound;
typedef struct
{
u8 volume; /* overall volume for this instrument */
ALPan pan; /* 0 = hard left, 127 = hard right */
u8 priority; /* voice priority for this instrument */
u8 flags;
u8 tremType; /* the type of tremelo osc. to use */
u8 tremRate; /* the rate of the tremelo osc. */
u8 tremDepth; /* the depth of the tremelo osc */
u8 tremDelay; /* the delay for the tremelo osc */
u8 vibType; /* the type of tremelo osc. to use */
u8 vibRate; /* the rate of the tremelo osc. */
u8 vibDepth; /* the depth of the tremelo osc */
u8 vibDelay; /* the delay for the tremelo osc */
s16 bendRange; /* pitch bend range in cents */
s16 soundCount; /* number of sounds in this array */
ALSound *soundArray[1];
} ALInstrument;
typedef struct ALBank_s
{
s16 instCount; /* number of programs in this bank */
u8 flags;
u8 pad;
s32 sampleRate; /* e.g. 44100, 22050, etc... */
ALInstrument *percussion; /* default percussion for GM */
ALInstrument *instArray[1]; /* ARRAY of instruments */
} ALBank;
typedef struct
{ /* Note: sizeof won't be correct */
s16 revision; /* format revision of this file */
s16 bankCount; /* number of banks */
ALBank *bankArray[1]; /* ARRAY of bank offsets */
} ALBankFile;
void alBnkfNew(ALBankFile *f, u8 *table);
#endif
+99
View File
@@ -0,0 +1,99 @@
#ifndef _LIBULTRA_INTERNAL_H_
#define _LIBULTRA_INTERNAL_H_
#include <ultra64.h>
/*
* This define is needed because the original definitions in __osDequeueThread.c are declared
* seperately instead of part of a single struct, however some code alises over this memory
* assuming a unified structure. To fix this, we declare the full type here and then alias the
* symbol names to the correct members in AVOID_UB.
*/
#ifdef AVOID_UB
typedef struct OSThread_ListHead_s
{
/*0x00*/ struct OSThread_s *next;
/*0x04*/ OSPri priority;
/*0x08*/ struct OSThread_s *queue;
/*0x0C*/ struct OSThread_s *tlnext;
/*0x10*/ struct OSThread_s *unk10;
/*0x14*/ u32 unk14;
} OSThread_ListHead;
// Now fix the symbols to the new one.
extern OSThread_ListHead D_80334890_fix;
#define D_80334890 D_80334890_fix.next
#define D_80334894 D_80334890_fix.priority
#define D_80334898 D_80334890_fix.queue
#define D_8033489C D_80334890_fix.tlnext
#define D_803348A0 D_80334890_fix.unk10
// Fix for the EEPROM array.
extern u32 D_80365E00[16];
// alias the last array element correctly
#define D_80365E3C D_80365E00[15]
#else
// Original OSThread_ListHead definitions
extern OSThread *D_80334890;
extern u32 D_80334894;
extern OSThread *D_80334898;
extern OSThread *D_8033489C;
extern OSThread *D_803348A0;
// Original EEPROM definitions
extern u32 D_80365E00[15];
extern u32 D_80365E3C;
#endif
typedef struct {
u32 initialized; // probably something like initialized?
OSThread *mgrThread;
OSMesgQueue *cmdQueue;
OSMesgQueue *eventQueue;
OSMesgQueue *accessQueue;
s32 (*dma_func)(s32, u32, void *, size_t);
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 (*edma_func)(OSPiHandle*, s32, u32, void *, size_t);
#else
u64 force_align;
#endif
} OSMgrArgs;
s32 __osDisableInt(void);
void __osRestoreInt(s32);
void __osEnqueueAndYield(OSThread **);
void __osDequeueThread(OSThread **, OSThread *);
void __osEnqueueThread(OSThread **, OSThread *);
OSThread *__osPopThread(OSThread **);
s32 __osSiRawStartDma(s32, void *);
void __osSiCreateAccessQueue(void);
void __osSiGetAccess(void);
void __osSiRelAccess(void);
u32 __osProbeTLB(void *);
void __osPiCreateAccessQueue(void);
void __osPiGetAccess(void);
void __osSetSR(u32);
u32 __osGetSR(void);
void __osSetFpcCsr(u32);
s32 __osSiRawReadIo(void *, u32 *);
s32 __osSiRawWriteIo(void *, u32);
s32 osPiRawReadIo(u32 a0, u32 *a1);
void __osSpSetStatus(u32);
u32 __osSpGetStatus(void);
s32 __osSpSetPc(void *);
s32 __osSpDeviceBusy(void);
s32 __osSiDeviceBusy(void);
s32 __osSpRawStartDma(u32 dir, void *sp_ptr, void *dram_ptr, size_t size);
void __osViInit(void);
OSViContext *__osViGetCurrentContext(void);
OSViContext *__osViGetCurrentContext2(void);
void __osViSwapContext(void);
void __osSetTimerIntr(u64);
u64 __osInsertTimer(OSTimer *);
void __osSetCompare(u32);
s32 __osAiDeviceBusy(void);
void __osDispatchThread(void);
u32 __osGetCause(void);
s32 __osAtomicDec(u32 *);
#endif
File diff suppressed because it is too large Load Diff
+117
View File
@@ -0,0 +1,117 @@
#ifndef MIXER_H
#define MIXER_H
#include <stdbool.h>
#include <stdint.h>
#include <ultra64.h>
#ifdef VERSION_SH
#define NEW_AUDIO_UCODE
#endif
#undef aSegment
#undef aClearBuffer
#undef aSetBuffer
#undef aLoadBuffer
#undef aSaveBuffer
#undef aDMEMMove
#undef aMix
#undef aEnvMixer
#undef aResample
#undef aInterleave
#undef aSetVolume
#undef aSetVolume32
#undef aSetLoop
#undef aLoadADPCM
#undef aADPCMdec
#undef aS8Dec
#undef aAddMixer
#undef aDuplicate
#undef aDMEMMove2
#undef aResampleZoh
#undef aDownsampleHalf
#undef aEnvSetup1
#undef aEnvSetup2
#undef aFilter
#undef aHiLoGain
#undef aUnknown25
void aClearBufferImpl(uint16_t addr, int nbytes);
void aLoadADPCMImpl(int num_entries_times_16, const int16_t *book_source_addr);
void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes);
void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes);
void aSetLoopImpl(ADPCM_STATE *adpcm_loop_state);
void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state);
void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state);
#ifndef NEW_AUDIO_UCODE
void aSetVolumeImpl(uint8_t flags, int16_t v, int16_t t, int16_t r);
void aLoadBufferImpl(const void *source_addr);
void aSaveBufferImpl(int16_t *dest_addr);
void aInterleaveImpl(uint16_t left, uint16_t right);
void aMixImpl(int16_t gain, uint16_t in_addr, uint16_t out_addr);
void aEnvMixerImpl(uint8_t flags, ENVMIX_STATE state);
#else
void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes);
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes);
void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c);
void aMixImpl(int16_t gain, uint16_t in_addr, uint16_t out_addr, uint16_t count);
void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right);
void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right);
void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb,
bool neg_left, bool neg_right,
uint16_t dry_left_addr, uint16_t dry_right_addr,
uint16_t wet_left_addr, uint16_t wet_right_addr);
void aS8DecImpl(uint8_t flags, ADPCM_STATE state);
void aAddMixerImpl(uint16_t in_addr, uint16_t out_addr, uint16_t count);
void aDuplicateImpl(uint16_t in_addr, uint16_t out_addr, uint16_t count);
void aDMEMMove2Impl(uint8_t t, uint16_t in_addr, uint16_t out_addr, uint16_t count);
void aResampleZohImpl(uint16_t pitch, uint16_t start_fract);
void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr);
void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t state_or_filter[8]);
void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr);
void aUnknown25Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr);
#endif
#define aSegment(pkt, s, b) do { } while(0)
#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c)
#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, d)
#define aSetBuffer(pkt, f, i, o, c) aSetBufferImpl(f, i, o, c)
#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c)
#define aSetLoop(pkt, a) aSetLoopImpl(a)
#define aADPCMdec(pkt, f, s) aADPCMdecImpl(f, s)
#define aResample(pkt, f, p, s) aResampleImpl(f, p, s)
#ifndef NEW_AUDIO_UCODE
#define aSetVolume(pkt, f, v, t, r) aSetVolumeImpl(f, v, t, r)
#define aSetVolume32(pkt, f, v, tr) aSetVolume(pkt, f, v, (int16_t)((tr) >> 16), (int16_t)(tr))
#define aLoadBuffer(pkt, s) aLoadBufferImpl(s)
#define aSaveBuffer(pkt, s) aSaveBufferImpl(s)
#define aInterleave(pkt, l, r) aInterleaveImpl(l, r)
#define aMix(pkt, f, g, i, o) aMixImpl(g, i, o)
#define aEnvMixer(pkt, f, s) aEnvMixerImpl(f, s)
#else
#define aLoadBuffer(pkt, s, d, c) aLoadBufferImpl(s, d, c)
#define aSaveBuffer(pkt, s, d, c) aSaveBufferImpl(s, d, c)
#define aInterleave(pkt, o, l, r, c) aInterleaveImpl(o, l, r, c)
#define aMix(pkt, g, i, o, c) aMixImpl(g, i, o, c)
#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \
aEnvSetup1Impl(initialVolReverb, rampReverb, rampLeft, rampRight)
#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) \
aEnvSetup2Impl(initialVolLeft, initialVolRight)
#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, \
dryLeft, dryRight, wetLeft, wetRight) \
aEnvMixerImpl(inBuf, nSamples, swapReverb, negLeft, negRight, \
dryLeft, dryRight, wetLeft, wetRight)
#define aS8Dec(pkt, f, s) aS8DecImpl(f, s)
#define aAddMixer(pkt, s, d, c) aAddMixerImpl(s, d, c)
#define aDuplicate(pkt, s, d, c) aDuplicateImpl(s, d, c)
#define aDMEMMove2(pkt, t, i, o, c) aDMEMMove2Impl(t, i, o, c)
#define aResampleZoh(pkt, pitch, startFract) aResampleZohImpl(pitch, startFract)
#define aDownsampleHalf(pkt, nSamples, i, o) aDownsampleHalfImpl(nSamples, i, o)
#define aFilter(pkt, f, countOrBuf, addr) aFilterImpl(f, countOrBuf, addr)
#define aHiLoGain(pkt, g, buflen, i) aHiLoGainImpl(g, buflen, i)
#define aUnknown25(pkt, f, c, o, i) aUnknown25Impl(f, c, o, i)
#endif
#endif
+216
View File
@@ -0,0 +1,216 @@
#include <stdio.h>
#include <string.h>
#include "libultra_internal.h"
#include <macros.h>
#ifdef TARGET_WEB
#include <emscripten.h>
#endif
extern OSMgrArgs piMgrArgs;
u64 osClockRate = 62500000;
s32 osPiStartDma(UNUSED OSIoMesg *mb, UNUSED s32 priority, UNUSED s32 direction,
uintptr_t devAddr, void *vAddr, size_t nbytes,
UNUSED OSMesgQueue *mq) {
memcpy(vAddr, (const void *) devAddr, nbytes);
return 0;
}
void osCreateMesgQueue(OSMesgQueue *mq, OSMesg *msgBuf, s32 count) {
mq->validCount = 0;
mq->first = 0;
mq->msgCount = count;
mq->msg = msgBuf;
return;
}
void osSetEventMesg(UNUSED OSEvent e, UNUSED OSMesgQueue *mq, UNUSED OSMesg msg) {
}
s32 osJamMesg(UNUSED OSMesgQueue *mq, UNUSED OSMesg msg, UNUSED s32 flag) {
return 0;
}
s32 osSendMesg(UNUSED OSMesgQueue *mq, UNUSED OSMesg msg, UNUSED s32 flag) {
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 index;
if (mq->validCount >= mq->msgCount) {
return -1;
}
index = (mq->first + mq->validCount) % mq->msgCount;
mq->msg[index] = msg;
mq->validCount++;
#endif
return 0;
}
s32 osRecvMesg(UNUSED OSMesgQueue *mq, UNUSED OSMesg *msg, UNUSED s32 flag) {
#if defined(VERSION_EU) || defined(VERSION_SH)
if (mq->validCount == 0) {
return -1;
}
if (msg != NULL) {
*msg = *(mq->first + mq->msg);
}
mq->first = (mq->first + 1) % mq->msgCount;
mq->validCount--;
#endif
return 0;
}
uintptr_t osVirtualToPhysical(void *addr) {
return (uintptr_t) addr;
}
void osCreateViManager(UNUSED OSPri pri) {
}
void osViSetMode(UNUSED OSViMode *mode) {
}
void osViSetEvent(UNUSED OSMesgQueue *mq, UNUSED OSMesg msg, UNUSED u32 retraceCount) {
}
void osViBlack(UNUSED u8 active) {
}
void osViSetSpecialFeatures(UNUSED u32 func) {
}
void osViSwapBuffer(UNUSED void *vaddr) {
}
OSTime osGetTime(void) {
return 0;
}
void osWritebackDCacheAll(void) {
}
void osWritebackDCache(UNUSED void *a, UNUSED size_t b) {
}
void osInvalDCache(UNUSED void *a, UNUSED size_t b) {
}
u32 osGetCount(void) {
static u32 counter;
return counter++;
}
s32 osAiSetFrequency(u32 freq) {
u32 a1;
s32 a2;
u32 D_8033491C;
#ifdef VERSION_EU
D_8033491C = 0x02E6025C;
#else
D_8033491C = 0x02E6D354;
#endif
a1 = D_8033491C / (float) freq + .5f;
if (a1 < 0x84) {
return -1;
}
a2 = (a1 / 66) & 0xff;
if (a2 > 16) {
a2 = 16;
}
return D_8033491C / (s32) a1;
}
s32 osEepromProbe(UNUSED OSMesgQueue *mq) {
return 1;
}
s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) {
u8 content[512];
s32 ret = -1;
#ifdef TARGET_WEB
if (EM_ASM_INT({
var s = localStorage.sm64_save_file;
if (s && s.length === 684) {
try {
var binary = atob(s);
if (binary.length === 512) {
for (var i = 0; i < 512; i++) {
HEAPU8[$0 + i] = binary.charCodeAt(i);
}
return 1;
}
} catch (e) {
}
}
return 0;
}, content)) {
memcpy(buffer, content + address * 8, nbytes);
ret = 0;
}
#else
FILE *fp = fopen("sm64_save_file.bin", "rb");
if (fp == NULL) {
return -1;
}
if (fread(content, 1, 512, fp) == 512) {
memcpy(buffer, content + address * 8, nbytes);
ret = 0;
}
fclose(fp);
#endif
return ret;
}
s32 osEepromLongWrite(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) {
u8 content[512] = {0};
if (address != 0 || nbytes != 512) {
osEepromLongRead(mq, 0, content, 512);
}
memcpy(content + address * 8, buffer, nbytes);
#ifdef TARGET_WEB
EM_ASM({
var str = "";
for (var i = 0; i < 512; i++) {
str += String.fromCharCode(HEAPU8[$0 + i]);
}
localStorage.sm64_save_file = btoa(str);
}, content);
s32 ret = 0;
#else
FILE* fp = fopen("sm64_save_file.bin", "wb");
if (fp == NULL) {
return -1;
}
s32 ret = fwrite(content, 1, 512, fp) == 512 ? 0 : -1;
fclose(fp);
#endif
return ret;
}
s32 gNumVblanks;
s32 osMotorInit(UNUSED OSMesgQueue *mq, UNUSED void *pfs, UNUSED int channel) {
return 0;
}
s32 osMotorStart(UNUSED void *pfs) {
return 0;
}
s32 osMotorStop(UNUSED void *pfs) {
return 0;
}
OSPiHandle *osCartRomInit(void) {
static OSPiHandle handle;
return &handle;
}
OSPiHandle *osDriveRomInit(void) {
static OSPiHandle handle;
return &handle;
}
s32 osEPiStartDma(UNUSED OSPiHandle *pihandle, OSIoMesg *mb, UNUSED s32 direction) {
memcpy(mb->dramAddr, (const void *) mb->devAddr, mb->size);
osSendMesg(mb->hdr.retQueue, mb, OS_MESG_NOBLOCK);
}
+97
View File
@@ -0,0 +1,97 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#define TYPE_CTL 1
#define TYPE_TBL 2
#define TYPE_SEQ 3
struct CLoop
{
unsigned int start;
unsigned int end;
int count;
unsigned int pad;
short state[1];
};
struct CBook
{
int order; // must be 2
int npredictors; // must be 2
short table[32]; // 8 * order * npredictors
};
struct CSample{
unsigned int zero;
uintptr_t addr;
struct CLoop* loop; // must not be null
struct CBook* book; // must not be null
unsigned int sample_size;
};
struct CSound{
struct CSample* sample_addr;
float tuning;
};
struct delay_arg{
unsigned short delay;
unsigned short arg;
};
struct CEnvelope{
struct delay_arg delay_args[1]; // array of [(delay,arg)]
};
struct CDrum{
unsigned char release_rate;
unsigned char pan;
unsigned char loaded;
unsigned char pad;
struct CSound snd;
struct CEnvelope* env_addr;
};
struct CInstrument{
unsigned char loaded;
unsigned char normal_range_lo;
unsigned char normal_range_hi;
unsigned char release_rate;
struct CEnvelope* env_addr;
struct CSound sound_lo;
struct CSound sound_med;
struct CSound sound_hi;
};
struct TBL{
unsigned char* data;
};
struct SEQ{
unsigned char* data;
};
struct CTL
{
unsigned int numInstruments;
unsigned int numDrums;
unsigned int shared;
unsigned int iso_date;
struct CDrum** drum_pointers;
struct CInstrument* instrument_pointers[1];
};
struct seqObject{
uintptr_t offset __attribute__((aligned (8)));
unsigned int len __attribute__((aligned (8)));
};
struct seqFile{
unsigned short revision;
unsigned short seqCount;
unsigned int pad;
struct seqObject seqArray[1];
} __attribute__((aligned (16)));
+374
View File
@@ -0,0 +1,374 @@
#pragma once
#include "convUtils.h"
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "convUtils.h"
#include "convTypes.h"
/**
* This code is based on the only documentation that exists (that I know of) for the SM64 CTL/TBL format
* as well as dylanpdx's audio extraction implementation.
* https://github.com/n64decomp/sm64/blob/1372ae1bb7cbedc03df366393188f4f05dcfc422/tools/disassemble_sound.py
* https://github.com/n64decomp/sm64/blob/1372ae1bb7cbedc03df366393188f4f05dcfc422/tools/assemble_sound.py
* https://github.com/Retro64Mod/libsm64-retro64
*/
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
unsigned char* gCtlSeqs;
struct seqFile* parse_seqfile(unsigned char* seq){ /* Read SeqFile data */
short revision = read_u16_be(seq);
short bankCount = read_u16_be(seq + 2);
unsigned int size = sizeof(struct seqFile) + (bankCount-1) * sizeof(struct seqObject);
struct seqFile* seqFile = (struct seqFile*)calloc(size, 1);
seqFile->revision = revision;
seqFile->seqCount = bankCount;
for (int i = 0; i < bankCount; i++){ // read bank offsets and sizes
seqFile->seqArray[i].offset = (uintptr_t)read_u32_be(seq + 4 + i * 8);
seqFile->seqArray[i].len = read_u32_be((seq + 4 + i * 8 + 4));
}
if (revision == TYPE_CTL){
// CTL file, contains instrument and drum data, this is really the only one that needs to be parsed, the rest only needs a header change
gCtlSeqs = (unsigned char*)calloc(0x20B40, 1); // We only really need 0x20AD0 bytes but still
uintptr_t pos = (uintptr_t)gCtlSeqs;
for (int i = 0; i < bankCount; i++){
uintptr_t start = pos;
struct CTL* ptr = parse_ctl_data(seq+(seqFile->seqArray[i].offset), &pos);
seqFile->seqArray[i].offset = ptr;
seqFile->seqArray[i].len = (unsigned int)(pos - start);
}
}else if (revision == TYPE_TBL){
// TBL file, contains raw audio data
for (int i = 0; i < bankCount; i++){
seqFile->seqArray[i].offset = seq+(seqFile->seqArray[i].offset);
}
}else if (revision == TYPE_SEQ){
// SEQ file, contains music files (*.m64)
for (int i = 0; i < bankCount; i++){
seqFile->seqArray[i].offset = seq+(seqFile->seqArray[i].offset);
}
}
return seqFile;
}
void ctl_free(){
free(gCtlSeqs);
}
void snd_ptrs_to_offsets(struct CSound* snd, uintptr_t ctlData){
struct CSample* smp = snd->sample_addr;
if((uintptr_t)(smp->loop) > ctlData)
smp->loop = (struct CLoop*)((uintptr_t)(smp->loop) - ctlData);
if((uintptr_t)(smp->book) > ctlData)
smp->book = (struct CBook*)((uintptr_t)(smp->book) - ctlData);
snd->sample_addr = (struct CSample*)((uintptr_t)(snd->sample_addr) - ctlData);
}
void ptrs_to_offsets(struct seqFile* ctl){
if (ctl->revision != TYPE_CTL){
return;
}
for (int i = 0; i < ctl->seqCount; i++){
struct CTL* ptr = (struct CTL*)ctl->seqArray[i].offset;
uintptr_t ctlData = (uintptr_t)ptr + 0x10;
// find all samples in the CTL file
for (int j = 0; j < ptr->numInstruments; j++){
struct CInstrument* inst = ptr->instrument_pointers[j];
if (inst==0x0)
continue; // null instrument.
inst->env_addr = (struct CEnvelope*)((uintptr_t)inst->env_addr - ctlData);
if (inst->sound_hi.sample_addr!=0x0){
snd_ptrs_to_offsets(&(inst->sound_hi), ctlData);
}
if (inst->sound_med.sample_addr!=0x0){
snd_ptrs_to_offsets(&(inst->sound_med), ctlData);
}
if (inst->sound_lo.sample_addr!=0x0){
snd_ptrs_to_offsets(&(inst->sound_lo), ctlData);
}
ptr->instrument_pointers[j] = (struct CInstrument*)((uintptr_t)(inst) - ctlData);
}
if(ptr->numDrums != 0){
for (int j = 0; j < ptr->numDrums; j++){
struct CDrum* drum = ptr->drum_pointers[j];
if (drum==0x0)
continue; // null drum.
drum->env_addr = (struct CEnvelope*)((uintptr_t)drum->env_addr - ctlData);
if (drum->snd.sample_addr!=0x0){
snd_ptrs_to_offsets(&(drum->snd), ctlData);
}
ptr->drum_pointers[j] = (struct CDrum*)((uintptr_t)(drum) - ctlData);
}
ptr->drum_pointers = (struct CDrum**)((uintptr_t)(ptr->drum_pointers) - ctlData);
}
}
}
struct CLoop* parse_loop(unsigned char* loop, uintptr_t* pos){
uint32_t count = read_u32_be(loop + 8); // variable is signed, but the data is being read as unsigned.
unsigned int size = sizeof(struct CLoop) - 4;
if(count != 0){
size = sizeof(struct CLoop) - 4 + sizeof(short) * 16;
}
struct CLoop* loop_ptr = (struct CLoop*)(*pos);
*pos += size;
*pos = ALIGN16(*pos);
loop_ptr->start = read_u32_be(loop);
loop_ptr->end = read_u32_be(loop + 4);
loop_ptr->count = count;
loop_ptr->pad = read_u32_be(loop + 12);
if (loop_ptr->count!=0){
for (int i = 0;i<16;i++){
loop_ptr->state[i]=read_u16_be(loop + 16 + i*2);
}
}
return loop_ptr;
}
struct CBook* parse_book(unsigned char* book, uintptr_t* pos){
struct CBook* book_ptr = (struct CBook*)(*pos);
*pos += sizeof(struct CBook);
*pos = ALIGN16(*pos);
book_ptr->order = read_u32_be(book);
book_ptr->npredictors = read_u32_be(book + 4); // both are signed
unsigned char* table_data = book+8;
for (int i = 0; i < 8 * book_ptr->order * book_ptr->npredictors; i ++){
book_ptr->table[i] = read_u16_be(table_data + i * 2);
}
return book_ptr;
}
struct CSample* parse_sample(unsigned char* sample,unsigned char* ctl, uintptr_t* pos){
struct CSample* samp = (struct CSample*)(*pos);
*pos += sizeof(struct CSample);
*pos = ALIGN16(*pos);
samp->zero=read_u32_be(sample);
samp->addr=read_u32_be(sample+4);
samp->loop=read_u32_be(sample+8);// loop address
samp->book=read_u32_be(sample+12);// book address
samp->sample_size=read_u32_be(sample+16);
samp->book=parse_book(ctl+((uintptr_t)samp->book), pos);
samp->loop=parse_loop(ctl+((uintptr_t)samp->loop), pos);
return samp;
}
struct CSound* parse_sound(unsigned char* sound,unsigned char* ctl, uintptr_t* pos, uintptr_t sndPos, struct SampleList* samples){
struct CSound* snd = (struct CSound*)(sndPos);
snd->sample_addr=read_u32_be(sound);
snd->tuning = (float)read_f32_be(sound+4);
// if sample_addr is 0 then the sound is null
if (snd->sample_addr!=0){
int smpIndex = -1;
for(int i = 0; i < samples->count; i++){
if(samples->orig_addrs[i] == (uintptr_t)(snd->sample_addr)){
smpIndex = i;
break;
}
}
if(smpIndex < 0){
samples->orig_addrs[samples->count] = (uintptr_t)(snd->sample_addr);
snd->sample_addr = parse_sample(ctl+((uintptr_t)snd->sample_addr),ctl, pos);
samples->addrs[samples->count] = snd->sample_addr;
samples->count++;
} else {
snd->sample_addr = samples->addrs[smpIndex];
}
}
return snd;
}
struct CDrum* parse_drum(unsigned char* drum,unsigned char* ctl, uintptr_t* pos, struct SampleList* samples){ /* Read Drum data */
struct CDrum* drumData = malloc(sizeof(struct CDrum));
drumData->release_rate = drum[0];
drumData->pan = drum[1];
drumData->loaded = drum[2];
drumData->pad = drum[3];
drumData->snd=*parse_sound(drum+4,ctl, pos, &drumData->snd, samples);
drumData->env_addr=read_u32_be(drum+12);
return drumData;
}
struct CEnvelope* parse_envelope(unsigned char* env, uintptr_t* pos, int* size){
int count = 0;
while(1){
unsigned short delay = read_u16_le(env + count * 4);
unsigned short arg = read_u16_le(env + count * 4 + 2);
unsigned short delayC = (-delay);
count++;
if ((1 <= delayC && delayC <= 3) || delay == 0)
break;
}
*size = sizeof(struct CEnvelope) + sizeof(struct delay_arg) * (count-1);
struct CEnvelope* envData = malloc(*size);
for (int i = 0; i < count; i++){
envData->delay_args[i].delay = read_u16_le(env + i * 4);
envData->delay_args[i].arg = read_u16_le(env + i * 4 + 2);
}
return envData;
}
struct CInstrument* parse_instrument(unsigned char* instrument,unsigned char* ctl, uintptr_t* pos, struct SampleList* samples){
struct CInstrument* inst = malloc(sizeof(struct CInstrument));
inst->loaded = instrument[0];
inst->normal_range_lo = instrument[1];
inst->normal_range_hi = instrument[2];
inst->release_rate = instrument[3];
inst->env_addr=read_u32_be(instrument+4);
inst->sound_lo=*parse_sound(instrument+8,ctl, pos, &(inst->sound_lo), samples);
inst->sound_med=*parse_sound(instrument+16,ctl, pos, &(inst->sound_med), samples);
inst->sound_hi=*parse_sound(instrument+24,ctl, pos, &(inst->sound_hi), samples);
return inst;
}
struct TBL* parse_tbl_data(unsigned char* tbl){
struct TBL* tblData = malloc(sizeof(struct TBL));
tblData->data = tbl;
return tblData;
}
struct SEQ* parse_seq_data(unsigned char* seq){
struct SEQ* seqData = malloc(sizeof(struct SEQ));
seqData->data = seq;
return seqData;
}
struct CTL* parse_ctl_data(unsigned char* ctlData, uintptr_t* pos){
int instruments=read_u32_be(ctlData);
unsigned int size = sizeof(struct CTL) + sizeof(struct CInstrument*) * (instruments-1);
struct CTL* ctl = (struct CTL*)(*pos);
*pos += size;
*pos = ALIGN16(*pos);
#pragma region Parse CTL header
ctl->numInstruments = read_u32_be(ctlData);
ctl->numDrums = read_u32_be(ctlData + 4);
ctl->shared = read_u32_be(ctlData + 8);
ctl->iso_date = read_u32_be(ctlData + 12);
#pragma endregion
struct SampleList samples = {0};
struct EnvelopeMeta envData[128] = {0};
int envCount = 0;
samples.count = 0;
// header parsed, now read data
if(ctl->numDrums != 0) {
ctl->drum_pointers= (struct CDrum**)(*pos);
size = sizeof(struct CDrum*) * ctl->numDrums;
*pos += size;
*pos = ALIGN16(*pos);
int drumTablePtr = read_u32_be(ctlData + 16);
for (int i = 0; i < ctl->numDrums; i++){
uint32_t data = read_u32_be(ctlData + drumTablePtr+16 + i * 4);
struct CDrum* d = parse_drum(ctlData+data+16,ctlData+16, pos, &samples);
bool used = 0;
for(int j = 0; j < envCount; j++){
if(envData[j].orig == (uintptr_t)d->env_addr){
used = 1;
break;
}
}
if(used == 0){
int size = 0;
unsigned char* addr = ctlData+((uintptr_t)d->env_addr)+16;
envData[envCount].orig = (uintptr_t)(d->env_addr);
envData[envCount].addr = parse_envelope(addr, pos, &size);
envData[envCount].size = size;
envCount++;
}
ctl->drum_pointers[i] = d;
}
*pos = ALIGN16(*pos);
} else {
ctl->drum_pointers= NULL;
}
// parse instrument data
int instTablePtr = 4;
for (int i = 0; i < ctl->numInstruments; i++){
uint32_t data = read_u32_be(ctlData + 16 + instTablePtr + i * 4);
if (data == 0)
continue;
struct CInstrument* inst = parse_instrument(ctlData+16+data,ctlData+16, pos, &samples);
bool used = 0;
for(int j = 0; j < envCount; j++){
if(envData[j].orig == (uintptr_t)inst->env_addr){
used = 1;
break;
}
}
if(used == 0){
int size = 0;
unsigned char* addr = ctlData+((uintptr_t)inst->env_addr)+16;
envData[envCount].orig = (uintptr_t)(inst->env_addr);
envData[envCount].addr = parse_envelope(addr, pos, &size);
envData[envCount].size = size;
envCount++;
}
ctl->instrument_pointers[i] = inst;
}
*pos = ALIGN16(*pos);
// Copy envelopes to ctl
for (int i = 0; i < envCount; i++){
struct CEnvelope* env = envData[i].addr;
memcpy((uint8_t*)(*pos), env, envData[i].size);
for (int j = 0; j < ctl->numInstruments; j++){
struct CInstrument* inst = ctl->instrument_pointers[j];
if (inst == 0x0)
continue;
if((uintptr_t)(inst->env_addr) == envData[i].orig){
inst->env_addr = (struct CEnvelope*)(*pos);
}
}
for (int j = 0; j < ctl->numDrums; j++){
struct CDrum* drum = ctl->drum_pointers[j];
if (drum == 0x0)
continue;
if((uintptr_t)(drum->env_addr) == envData[i].orig){
drum->env_addr = (struct CEnvelope*)(*pos);
}
}
free(env);
*pos += envData[i].size;
}
*pos = ALIGN16(*pos);
// Copy instruments to ctl
for (int i = 0; i < ctl->numInstruments; i++){
struct CInstrument* inst = ctl->instrument_pointers[i];
if (inst == 0x0)
continue;
memcpy((uint8_t*)(*pos), inst, sizeof(struct CInstrument));
free(inst);
ctl->instrument_pointers[i] = (struct CInstrument*)(*pos);
*pos += sizeof(struct CInstrument);
}
*pos = ALIGN16(*pos);
// Copy drums to ctl
for (int i = 0; i < ctl->numDrums; i++){
struct CDrum* drum = ctl->drum_pointers[i];
if (drum == 0x0)
continue;
memcpy((uint8_t*)(*pos), drum, sizeof(struct CDrum));
free(drum);
ctl->drum_pointers[i] = (struct CDrum*)(*pos);
*pos += sizeof(struct CDrum);
}
*pos = ALIGN16(*pos);
//
return ctl;
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "../pc/libaudio_internal.h"
#define read_u16_le(p) ((uint8_t*)p)[1] * 0x100u + ((uint8_t*)p)[0]
struct EnvelopeMeta {
uintptr_t orig;
struct CEnvelope* addr;
int size;
};
struct SampleList {
int count;
uintptr_t orig_addrs[256];
struct CSample* addrs[256];
};
struct seqFile* parse_seqfile(unsigned char* seq);
struct CTL* parse_ctl_data(unsigned char* ctlData, uintptr_t* pos);
struct TBL* parse_tbl_data(unsigned char* tbl);
struct SEQ* parse_seq_data(unsigned char* seq);
void ptrs_to_offsets(struct seqFile* ctl);
void ctl_free();
#define INITIAL_GFX_ALLOC 10
#define INITIAL_GEO_ALLOC 10
+26
View File
@@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "decomp/audio/external.h"
#include "decomp/include/PR/os_cont.h" #include "decomp/include/PR/os_cont.h"
#include "decomp/engine/math_util.h" #include "decomp/engine/math_util.h"
#include "decomp/include/sm64.h" #include "decomp/include/sm64.h"
@@ -29,6 +30,7 @@
#include "load_surfaces.h" #include "load_surfaces.h"
#include "gfx_adapter.h" #include "gfx_adapter.h"
#include "load_anim_data.h" #include "load_anim_data.h"
#include "load_audio_data.h"
#include "load_tex_data.h" #include "load_tex_data.h"
#include "obj_pool.h" #include "obj_pool.h"
@@ -134,6 +136,30 @@ SM64_LIB_FN void sm64_global_terminate( void )
memory_terminate(); memory_terminate();
} }
SM64_LIB_FN void sm64_audio_init( uint8_t *rom ) {
load_audio_banks( rom );
}
#define SAMPLES_HIGH 544
#define SAMPLES_LOW 528
extern SM64_LIB_FN uint32_t sm64_audio_tick( uint32_t numQueuedSamples, uint32_t numDesiredSamples, int16_t *audio_buffer ) {
if ( !is_audio_initialized ) {
DEBUG_PRINT("Attempted to tick audio, but sm64_audio_init() has not been called yet.");
return 0;
}
update_game_sound();
u32 num_audio_samples = numQueuedSamples < numDesiredSamples ? SAMPLES_HIGH : SAMPLES_LOW;
for (int i = 0; i < 2; i++)
{
create_next_audio_buffer( audio_buffer + i * ( 2 * num_audio_samples ), num_audio_samples );
}
return num_audio_samples;
}
SM64_LIB_FN void sm64_static_surfaces_load( const struct SM64Surface *surfaceArray, uint32_t numSurfaces ) SM64_LIB_FN void sm64_static_surfaces_load( const struct SM64Surface *surfaceArray, uint32_t numSurfaces )
{ {
surfaces_load_static( surfaceArray, numSurfaces ); surfaces_load_static( surfaceArray, numSurfaces );
+3
View File
@@ -133,6 +133,9 @@ extern SM64_LIB_FN void sm64_register_play_sound_function( SM64PlaySoundFunction
extern SM64_LIB_FN void sm64_global_init( uint8_t *rom, uint8_t *outTexture ); extern SM64_LIB_FN void sm64_global_init( uint8_t *rom, uint8_t *outTexture );
extern SM64_LIB_FN void sm64_global_terminate( void ); extern SM64_LIB_FN void sm64_global_terminate( void );
extern SM64_LIB_FN void sm64_audio_init( uint8_t *rom );
extern SM64_LIB_FN uint32_t sm64_audio_tick( uint32_t numQueuedSamples, uint32_t numDesiredSamples, int16_t *audio_buffer );
extern SM64_LIB_FN void sm64_static_surfaces_load( const struct SM64Surface *surfaceArray, uint32_t numSurfaces ); extern SM64_LIB_FN void sm64_static_surfaces_load( const struct SM64Surface *surfaceArray, uint32_t numSurfaces );
extern SM64_LIB_FN int32_t sm64_mario_create( float x, float y, float z ); extern SM64_LIB_FN int32_t sm64_mario_create( float x, float y, float z );
+27
View File
@@ -0,0 +1,27 @@
#include "load_audio_data.h"
#include "decomp/tools/convUtils.h"
#include "decomp/audio/load.h"
#include "decomp/audio/load_dat.h"
bool is_audio_initialized = false;
extern void load_audio_banks( uint8_t *rom ) {
uint8_t *rom2 = malloc( 0x800000 );
memcpy( rom2, rom, 0x800000 );
rom = rom2;
gSoundDataADSR = parse_seqfile( rom+0x57B720 ); //ctl
gSoundDataRaw = parse_seqfile( rom+0x593560 ); //tbl
gMusicData = parse_seqfile( rom+0x7B0860 );
gBankSetsData = rom+0x7CC621;
memmove( gBankSetsData+0x45,gBankSetsData+0x45-1,0x5B );
gBankSetsData[0x45]=0x00;
ptrs_to_offsets( gSoundDataADSR );
audio_init();
sound_init();
sound_reset( 0 );
is_audio_initialized = true;
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
extern bool is_audio_initialized;
extern void load_audio_banks( uint8_t *rom );
+11
View File
@@ -1,8 +1,19 @@
#include "play_sound.h" #include "play_sound.h"
#include "decomp/audio/external.h"
#include "debug_print.h"
#include "load_audio_data.h"
SM64PlaySoundFunctionPtr g_play_sound_func = NULL; SM64PlaySoundFunctionPtr g_play_sound_func = NULL;
extern void play_sound( uint32_t soundBits, f32 *pos ) { extern void play_sound( uint32_t soundBits, f32 *pos ) {
if ( is_audio_initialized ) {
DEBUG_PRINT("$ play_sound(%d) request %d; pos %f %f %f\n", soundBits,sSoundRequestCount,pos[0],pos[1],pos[2]);
sSoundRequests[sSoundRequestCount].soundBits = soundBits;
sSoundRequests[sSoundRequestCount].position = pos;
sSoundRequestCount++;
}
if ( g_play_sound_func ) { if ( g_play_sound_func ) {
g_play_sound_func(soundBits, pos); g_play_sound_func(soundBits, pos);
} }