diff --git a/README.md b/README.md
index a3363778..3d1bf736 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# banjo (89.2214%)
+# banjo (89.9076%)
diff --git a/include/enums.h b/include/enums.h
index 658afe85..b38aedd4 100644
--- a/include/enums.h
+++ b/include/enums.h
@@ -1,14 +1,14 @@
#ifndef ENUMS_H
#define ENUMS_H
-#define SPRITE_TYPE_CI4 (1 << 0)
-#define SPRITE_TYPE_CI8 (1 << 2)
-#define SPRITE_TYPE_I4 (1 << 5)
-#define SPRITE_TYPE_I8 (1 << 6)
-#define SPRITE_TYPE_IA4 (1 << 7)
-#define SPRITE_TYPE_IA8 (1 << 8)
-#define SPRITE_TYPE_UNKNOWN_200 (1 << 9)
-#define SPRITE_TYPE_RGBA16 (1 << 10)
+#define SPRITE_TYPE_CI4 (1 << 0) //0x001
+#define SPRITE_TYPE_CI8 (1 << 2) //0x004
+#define SPRITE_TYPE_I4 (1 << 5) //0x020
+#define SPRITE_TYPE_I8 (1 << 6) //0x040
+#define SPRITE_TYPE_IA4 (1 << 7) //0x080
+#define SPRITE_TYPE_IA8 (1 << 8) //0x100
+#define SPRITE_TYPE_UNKNOWN_200 (1 << 9) //0x200
+#define SPRITE_TYPE_RGBA16 (1 << 10) ////0x400
#define SPRITE_TYPE_RGBA32 (1 << 11)
enum bkprog_e{
@@ -3055,7 +3055,7 @@ enum asset_e
ASSET_543_MODEL_JINJO_STATUE_BASE = 0x543,
ASSET_544_MODEL_JINJONATOR_STATUE_BASE,
ASSET_545_MODEL_STONE_JINJO,
- ASSET_546_MODEL_GRUNTY_SPELL_BARRIER = 0x546,
+ ASSET_546_MODEL_GRUNTY_SPELL_BARRIER,
// 547 GL Blue Egg Refill Pillow
// 548 GL Red Feather Refill Pillow
// 549 GL Gold Feather Refill Pillow
diff --git a/include/file_and_line.h b/include/file_and_line.h
new file mode 100644
index 00000000..6a1551d4
--- /dev/null
+++ b/include/file_and_line.h
@@ -0,0 +1,29 @@
+#ifndef _FILE_AND_LINE_H_
+#define _FILE_AND_LINE_H_
+
+extern void func_8033F000(const char *, const char *, int);
+
+
+#ifdef NONMATCHING
+ #define LINE(line_num) __LINE__
+ #define FILE(file_name) __FILE__
+ #define matching_assert(EX, F, L) assert(EX)
+#else
+ #define LINE(line_num) line_num
+ #define FILE(file_name) "file_name"
+ #ifdef __ANSI_CPP__
+ #define FILE(file_name) # file_name
+ #else
+ #define FILE(file_name) "file_name"
+ #endif
+ #define matching_assert(EX, F, L) assert(EX)
+ #ifdef __ANSI_CPP__
+ #define matching_assert(EX, F, L) ((EX)?((void)0):func_8033F000( # EX , # F, L))
+ #else
+ #define matching_assert(EX, F , L) ((EX)?((void)0):func_8033F000("EX", "F", L))
+ #endif
+#endif
+
+
+
+#endif
\ No newline at end of file
diff --git a/progress/progress_core1.svg b/progress/progress_core1.svg
index 6f0b5513..4b1ca596 100644
--- a/progress/progress_core1.svg
+++ b/progress/progress_core1.svg
@@ -9,7 +9,7 @@
-
+
@@ -17,7 +17,7 @@
core1
- 73.1536%
- 73.1536%
+ 76.3559%
+ 76.3559%
\ No newline at end of file
diff --git a/progress/progress_core2.svg b/progress/progress_core2.svg
index be4e35dc..9bca07fb 100644
--- a/progress/progress_core2.svg
+++ b/progress/progress_core2.svg
@@ -9,7 +9,7 @@
-
+
@@ -17,7 +17,7 @@
core2
- 88.2188%
- 88.2188%
+ 88.6047%
+ 88.6047%
\ No newline at end of file
diff --git a/progress/progress_total.svg b/progress/progress_total.svg
index fc4dd50c..f0b50deb 100644
--- a/progress/progress_total.svg
+++ b/progress/progress_total.svg
@@ -9,7 +9,7 @@
-
+
@@ -17,7 +17,7 @@
Banjo-Kazooie (us.v10)
- 89.2214%
- 89.2214%
+ 89.9076%
+ 89.9076%
\ No newline at end of file
diff --git a/src/core1/code_13990.c b/src/core1/code_13990.c
index 08e8dd7e..2216920e 100644
--- a/src/core1/code_13990.c
+++ b/src/core1/code_13990.c
@@ -33,7 +33,32 @@ void mlMtxApply(Mtx *mPtr){
func_80245A7C(D_80282FD0, mPtr);
}
+#ifndef NONMATCHING
#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_802514BC.s")
+#else
+void func_802514BC(Mtx *arg0) {
+ s32 i, j, k;
+ f32 tmp;
+ f32 sp38[4][4];
+ f32 (*sp34)[4];
+ f32 (*var_s0)[4];
+
+
+ sp34 = reinterpret_cast(f32 *, *D_80282FD0);
+ var_s0 = reinterpret_cast(f32 *, arg0);
+
+ for(i = 0; i < 4; i++){
+ for(j = 0; j < 4; j++){
+ tmp = 0.0f;
+ for(k = 0; k < 4; k++){
+ tmp += var_s0[i][k] * sp34[k][j];
+ }
+ sp38[i][j] = tmp;
+ }
+ }
+ func_80253010(sp34, &sp38, sizeof(Mtx));
+}
+#endif
#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_802515D4.s")
@@ -57,31 +82,13 @@ void func_80251738(void){
v0[0] = 1.0f;
}
-#ifndef NONMATCHING
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_80251788.s")
-#else
f32 *func_80251788(f32 arg0, f32 arg1, f32 arg2){
- f32 (* v0)[4][4] = (f32 *) ++D_80282FD0;
-
- (*v0)[0][3] = 0.0f;
- (*v0)[0][2] = 0.0f;
- (*v0)[0][1] = 0.0f;
- (*v0)[1][3] = 0.0f;
- (*v0)[1][2] = 0.0f;
- (*v0)[1][0] = 0.0f;
- (*v0)[2][3] = 0.0f;
- (*v0)[2][1] = 0.0f;
- (*v0)[2][0] = 0.0f;
- (*v0)[0][0] = 1.0f;
- (*v0)[1][1] = 1.0f;
- (*v0)[2][2] = 1.0f;
- (*v0)[3][3] = 1.0f;
- (*v0)[3][2] = arg2;
- (*v0)[3][1] = arg1;
- (*v0)[3][0] = arg0;
- return &(*v0)[3][3];
+ f32 * var_v0 = ++D_80282FD0;
+ *(var_v0++) = 1.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = 0.0f; *(var_v0++) = 1.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = 0.0f; *(var_v0++) = 0.0f; *(var_v0++) = 1.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = arg0; *(var_v0++) = arg1; *(var_v0++) = arg2; *(var_v0++) = 1.0f;
}
-#endif
#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_802517F8.s")
@@ -92,7 +99,7 @@ f32 *func_80251788(f32 arg0, f32 arg1, f32 arg2){
//mlMtx
void mlMtxIdent(void){
s32 i;
- f32 *v0 = D_80282FD0 = D_80282810;
+ f32 *v0 = D_80282FD0 = &D_80282810;
for(i = 0; i<3; i++){
v0[0] = 1.0f;
v0[1] = 0.0f;
@@ -104,7 +111,13 @@ void mlMtxIdent(void){
v0[0] = 1.0f;
}
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_80251B5C.s")
+void func_80251B5C(f32 arg0, f32 arg1, f32 arg2){
+ f32 * var_v0 = D_80282FD0 = &D_80282810;
+ *(var_v0++) = 1.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = 0.0f; *(var_v0++) = 1.0f; *(var_v0++) = 0.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = 0.0f; *(var_v0++) = 0.0f; *(var_v0++) = 1.0f; *(var_v0++) = 0.0f;
+ *(var_v0++) = arg0; *(var_v0++) = arg1; *(var_v0++) = arg2; *(var_v0++) = 1.0f;
+}
#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_80251BCC.s")
@@ -347,62 +360,3 @@ void func_80252FC8(f32 arg0[3]){
mlMtxRotRoll(-arg0[2]);
}
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_80253010.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_13990/func_80253034.s")
-
-typedef struct{
- u32 unk0;
- u32 unk4;
-}struct49s;
-
-extern struct49s D_803FFE10[];
-
-extern u8 D_8000E800;
-extern u8 D_8002D500;
-extern u32 D_8027BF2C;
-extern u32 D_8027BF30;
-
-void func_80253050(
- s32 overlay_id, u32 ram_start, u32 ram_end, u32 rom_start, u32 rom_end,
- u32 code_start, u32 code_end, u32 data_start, u32 data_end, u32 bss_start, u32 bss_end
-){
- u32 sp34;
- u32 sp30;
- u32 sp2C;
- u32 *tmp;
-
- osWriteBackDCacheAll();
- osInvalDCache(ram_start, ram_end - ram_start);
- osInvalICache(ram_start, ram_end - ram_start);
-
- if(bss_start){
- osInvalDCache(bss_start, bss_end - bss_start);
- }
-
- rom_start = D_803FFE10[overlay_id].unk0;
- rom_end = D_803FFE10[overlay_id].unk4;
-
- if(overlay_id){
- func_80254008();
- sp34 = &D_8000E800;
- }
- else{
- sp34 = &D_8002D500;
- }
- func_802405F0(sp34, rom_start, rom_end - rom_start);
- rarezip_uncompress(&sp34, &ram_start);
- sp2C = D_8027BF2C;
- sp30 = D_8027BF30;
- rarezip_uncompress(&sp34, &ram_start);
-
- if(bss_start){
- bzero(bss_start, bss_end - bss_start);
- osWriteBackDCacheAll();
- tmp = (u32*) bss_start;
- tmp[0] = sp2C;
- tmp[1] = sp30;
- tmp[2] = D_8027BF2C;
- tmp[3] = D_8027BF30;
- }
-}
diff --git a/src/core1/code_15630.c b/src/core1/code_15630.c
new file mode 100644
index 00000000..f75b923d
--- /dev/null
+++ b/src/core1/code_15630.c
@@ -0,0 +1,60 @@
+#include
+#include "functions.h"
+#include "variables.h"
+
+
+typedef struct{
+ u32 unk0;
+ u32 unk4;
+}struct49s;
+
+extern struct49s D_803FFE10[];
+
+extern u8 D_8000E800;
+extern u8 D_8002D500;
+extern u32 D_8027BF2C;
+extern u32 D_8027BF30;
+
+void func_80253050(
+ s32 overlay_id, u32 ram_start, u32 ram_end, u32 rom_start, u32 rom_end,
+ u32 code_start, u32 code_end, u32 data_start, u32 data_end, u32 bss_start, u32 bss_end
+){
+ u32 sp34;
+ u32 sp30;
+ u32 sp2C;
+ u32 *tmp;
+
+ osWriteBackDCacheAll();
+ osInvalDCache(ram_start, ram_end - ram_start);
+ osInvalICache(ram_start, ram_end - ram_start);
+
+ if(bss_start){
+ osInvalDCache(bss_start, bss_end - bss_start);
+ }
+
+ rom_start = D_803FFE10[overlay_id].unk0;
+ rom_end = D_803FFE10[overlay_id].unk4;
+
+ if(overlay_id){
+ func_80254008();
+ sp34 = &D_8000E800;
+ }
+ else{
+ sp34 = &D_8002D500;
+ }
+ func_802405F0(sp34, rom_start, rom_end - rom_start);
+ rarezip_uncompress(&sp34, &ram_start);
+ sp2C = D_8027BF2C;
+ sp30 = D_8027BF30;
+ rarezip_uncompress(&sp34, &ram_start);
+
+ if(bss_start){
+ bzero(bss_start, bss_end - bss_start);
+ osWriteBackDCacheAll();
+ tmp = (u32*) bss_start;
+ tmp[0] = sp2C;
+ tmp[1] = sp30;
+ tmp[2] = D_8027BF2C;
+ tmp[3] = D_8027BF30;
+ }
+}
diff --git a/src/core1/code_22E40.c b/src/core1/code_22E40.c
deleted file mode 100644
index 88a722aa..00000000
--- a/src/core1/code_22E40.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#include
-#include "n_libaudio.h"
-#include "n_synth.h"
-// #include "functions.h"
-// #include "variables.h"
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80260860.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_802609E0.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80260BD4.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/n_alEnvmixerPull.s")
-
-#ifdef NONMATCHING
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__postNextSeqEvent.s")
-#else
-void __postNextSeqEvent(ALSeqPlayer *seqp)
-{
- ALEvent evt;
- s32 deltaTicks;
- ALSeq *seq = seqp->target;
-
- /* sct 1/5/96 - Do nothing if we're not playing or don't have a target sequence. */
- if ((seqp->state != AL_PLAYING) || (seq == NULL))
- return;
-
- /* Get the next event time in ticks. */
- /* If false is returned, then there is no next delta (ie. end of sequence reached). */
- if (!__alSeqNextDelta(seq, &deltaTicks))
- return;
-
- /* Handle loops. */
- if (seqp->loopCount)
- {
- /* Assume that the loop end falls on a MIDI event. Delta time
- will be correct even if we loop */
- if (alSeqGetTicks(seq) + deltaTicks >= seqp->loopEnd->curTicks)
- {
- alSeqSetLoc(seq, seqp->loopStart);
-
- if (seqp->loopCount != -1)
- seqp->loopCount--;
- }
- }
-
- evt.type = AL_SEQ_REF_EVT;
- //alEvtqPostEvent(&seqp->evtq, &evt, deltaTicks * seqp->uspt);
- alEvtqPostEvent(&seqp->evtq, &evt, deltaTicks * seqp->uspt);
-}
-#endif
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__setInstChanState.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80261348.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__initFromBank.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80261490.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__vsDelta.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__vsVol.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__seqpReleaseVoice.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__voiceNeedsNoteKill.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__unmapVoice.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_802617A0.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__vsPan.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__lookupVoice.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__mapVoice.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__lookupSoundQuick.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80261A94.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_802623F4.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_802623FC.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__seqpStopOsc.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/__initChanState.s")
-
-#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_22E40/func_80262BFC.s")
diff --git a/src/core1/done/audio/n_seqplayer.c b/src/core1/done/audio/n_seqplayer.c
new file mode 100644
index 00000000..5e35705d
--- /dev/null
+++ b/src/core1/done/audio/n_seqplayer.c
@@ -0,0 +1,1221 @@
+#include
+#include "n_libaudio.h"
+#include "n_synth.h"
+#include "file_and_line.h"
+#include "assert.h"
+// #include "functions.h"
+// #include "variables.h"
+
+#define KILL_TIME 50000
+
+void __postNextSeqEvent(ALSeqPlayer *seqp);
+ALVoiceState *__mapVoice(ALSeqPlayer *seqp, u8 key, u8 vel, u8 channel);
+void __unmapVoice(ALSeqPlayer *seqp, ALVoice *voice) ;
+ALVoiceState *__lookupVoice(ALSeqPlayer *seqp, u8 key, u8 channel);
+ALSound *__lookupSound(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan);
+ALSound *__lookupSoundQuick(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan);
+s16 __vsVol(N_ALVoiceState *vs, ALSeqPlayer *seqp);
+ALMicroTime __vsDelta(ALVoiceState *vs, ALMicroTime t);
+ALPan __vsPan(ALVoiceState *vs, ALSeqPlayer *seqp);
+void __seqpReleaseVoice(ALSeqPlayer *seqp, ALVoice *voice, ALMicroTime deltaTime);
+char __voiceNeedsNoteKill (ALSeqPlayer *seqp, ALVoice *voice, ALMicroTime killTime);
+void __initFromBank(ALSeqPlayer *seqp, ALBank *b);
+void __setInstChanState(ALSeqPlayer *seqp, ALInstrument *inst, s32 chan);
+void func_80261348(ALSeqPlayer *seqp, s32 chan); //__resetPerfChanState
+void __initChanState(ALSeqPlayer *seqp);
+void __seqpStopOsc(ALSeqPlayer *seqp, ALVoiceState *vs);
+void func_80263850(ALSeq *, ALEvent *);
+
+
+static ALMicroTime __seqpVoiceHandler(void *node);
+static void func_80261A94(ALSeqPlayer *seqp, ALEvent *event); //__handleMIDIMsg
+static void func_802617A0(ALSeqPlayer *seqp, ALEvent *event); //__handleMetaMsg
+static void __handleNextSeqEvent(ALSeqPlayer *seqp);
+static void __setUsptFromTempo(ALSeqPlayer *seqp, f32 tempo); /* sct 1/8/96 */
+
+/*
+ * Sequence Player public functions
+ */
+void n_alSeqpNew(N_ALSeqPlayer *seqp, ALSeqpConfig *c)
+{
+ s32 i;
+ ALEventListItem *items;
+ ALVoiceState *vs;
+ ALVoiceState *voices;
+ ALHeap *hp = c->heap;
+
+ /*
+ * initialize member variables
+ */
+ seqp->bank = 0;
+ seqp->target = NULL;
+ seqp->drvr = &n_syn->head;
+ seqp->chanMask = 0xff;
+ seqp->uspt = 488;
+ seqp->nextDelta = 0;
+ seqp->state = AL_STOPPED;
+ seqp->vol = 0x7FFF; /* full volume */
+ seqp->debugFlags = c->debugFlags;
+ seqp->frameTime = AL_USEC_PER_FRAME; /* should get this from driver */
+ seqp->curTime = 0;
+ seqp->initOsc = c->initOsc;
+ seqp->updateOsc = c->updateOsc;
+ seqp->stopOsc = c->stopOsc;
+ seqp->loopStart = 0;
+ seqp->loopEnd = 0;
+ seqp->loopCount = 0; /* -1 = loop forever, 0 = no loop */
+
+ seqp->nextEvent.type = AL_SEQP_API_EVT; /* start the voice handler "spinning" */
+
+ /*
+ * init the channel state
+ */
+ seqp->maxChannels = c->maxChannels;
+ seqp->chanState = alHeapAlloc(hp, c->maxChannels, sizeof(ALChanState) );
+ __initChanState(seqp); /* sct 11/6/95 */
+
+ /*
+ * init the voice state array
+ */
+ voices = alHeapAlloc(hp, c->maxVoices, sizeof(ALVoiceState));
+ seqp->vFreeList = 0;
+ for (i = 0; i < c->maxVoices; i++) {
+ vs = &voices[i];
+ vs->next = seqp->vFreeList;
+ seqp->vFreeList = vs;
+ }
+
+ seqp->vAllocHead = 0;
+ seqp->vAllocTail = 0;
+
+ /*
+ * init the event queue
+ */
+ items = alHeapAlloc(hp, c->maxEvents, sizeof(ALEventListItem));
+ alEvtqNew(&seqp->evtq, items, c->maxEvents);
+
+ /*
+ * add ourselves to the driver
+ */
+ seqp->node.next = NULL;
+ seqp->node.handler = __seqpVoiceHandler;
+ seqp->node.clientData = seqp;
+ n_alSynAddSeqPlayer(&seqp->node);
+}
+
+/*************************************************************
+ * private routines or driver callback routines
+ *************************************************************/
+ALMicroTime __seqpVoiceHandler(void *node)
+{
+ ALSeqPlayer *seqp = (ALSeqPlayer *) node;
+ ALEvent evt;
+ ALVoice *voice;
+ ALMicroTime delta;
+ ALVoiceState *vs;
+ void *oscState;
+ f32 oscValue;
+ u8 chan;
+
+ do {
+
+ switch (seqp->nextEvent.type) {
+
+ case (AL_SEQ_REF_EVT):
+ __handleNextSeqEvent(seqp);
+ break;
+
+ case (AL_SEQP_API_EVT):
+ evt.type = AL_SEQP_API_EVT;
+ alEvtqPostEvent(&seqp->evtq, (ALEvent *)&evt, seqp->frameTime);
+ break;
+
+ case (AL_NOTE_END_EVT):
+ voice = seqp->nextEvent.msg.note.voice;
+ n_alSynStopVoice(voice);
+ n_alSynFreeVoice(voice);
+ vs = (ALVoiceState *)voice->clientPrivate;
+ if(vs->flags)
+ __seqpStopOsc((ALSeqPlayer*)seqp,vs);
+ __unmapVoice(seqp, voice);
+ break;
+
+ case (AL_SEQP_ENV_EVT):
+ voice = seqp->nextEvent.msg.vol.voice;
+ vs = (ALVoiceState *)voice->clientPrivate;
+
+ if (vs->envPhase == AL_PHASE_ATTACK)
+ vs->envPhase = AL_PHASE_DECAY;
+
+ delta = seqp->nextEvent.msg.vol.delta;
+ vs->envGain = seqp->nextEvent.msg.vol.vol;
+ vs->envEndTime = seqp->curTime + delta;
+ n_alSynSetVol(voice, __vsVol(vs, seqp), delta);
+ break;
+
+ case (AL_TREM_OSC_EVT):
+ vs = seqp->nextEvent.msg.osc.vs;
+ oscState = seqp->nextEvent.msg.osc.oscState;
+ delta = (*seqp->updateOsc)(oscState,&oscValue);
+ vs->tremelo = (u8)oscValue;
+ n_alSynSetVol(&vs->voice, __vsVol(vs,seqp),
+ __vsDelta(vs,seqp->curTime));
+ evt.type = AL_TREM_OSC_EVT;
+ evt.msg.osc.vs = vs;
+ evt.msg.osc.oscState = oscState;
+ alEvtqPostEvent(&seqp->evtq, &evt, delta);
+ break;
+
+ case (AL_VIB_OSC_EVT):
+ vs = seqp->nextEvent.msg.osc.vs;
+ oscState = seqp->nextEvent.msg.osc.oscState;
+ chan = seqp->nextEvent.msg.osc.chan;
+ delta = (*seqp->updateOsc)(oscState,&oscValue);
+ vs->vibrato = oscValue;
+ n_alSynSetPitch(&vs->voice, vs->pitch * vs->vibrato
+ * seqp->chanState[chan].pitchBend);
+ evt.type = AL_VIB_OSC_EVT;
+ evt.msg.osc.vs = vs;
+ evt.msg.osc.oscState = oscState;
+ evt.msg.osc.chan = chan;
+ alEvtqPostEvent(&seqp->evtq, &evt, delta);
+ break;
+
+ case (AL_SEQP_MIDI_EVT):
+ func_80261A94(seqp, &seqp->nextEvent);
+ break;
+
+ case (AL_SEQP_META_EVT):
+ func_802617A0(seqp, &seqp->nextEvent);
+ break;
+
+ case (AL_SEQP_PLAY_EVT):
+ if (seqp->state != AL_PLAYING)
+ {
+ seqp->state = AL_PLAYING;
+ __postNextSeqEvent(seqp); /* seqp must be AL_PLAYING before we call this routine. */
+ }
+ break;
+
+ case (AL_SEQP_STOP_EVT):
+ if ( seqp->state == AL_STOPPING )
+ {
+ for (vs = seqp->vAllocHead; vs != 0; vs = seqp->vAllocHead)
+ {
+ n_alSynStopVoice(&vs->voice);
+ n_alSynFreeVoice(&vs->voice);
+ if(vs->flags)
+ __seqpStopOsc((ALSeqPlayer*)seqp,vs);
+ __unmapVoice((ALSeqPlayer*)seqp, &vs->voice);
+ }
+
+ seqp->curTime = 0;
+ seqp->state = AL_STOPPED;
+
+ /* alEvtqFlush(&seqp->evtq); - Don't flush event
+ queue anymore. */
+ /* sct 1/3/96 - Don't overwrite nextEvent with
+ AL_SEQP_API_EVT or set nextDelta to
+ AL_USEC_PER_FRAME since we're not stopping event
+ processing. */
+ /* sct 1/3/96 - Don't return here since we keep
+ processing events as usual. */
+ }
+ break;
+
+ case (AL_SEQP_STOPPING_EVT):
+ if (seqp->state == AL_PLAYING)
+ {
+ /*
+ * sct 12/29/95 - Remove events associated with the
+ * stopping sequence. Note that flushing
+ * AL_SEQP_MIDI_EVTs may flush events that were
+ * posted after the call to alSeqpStop, so the
+ * application must queue these events either when
+ * the player is fully stopped, or when it is
+ * playing.
+ */
+ alEvtqFlushType(&seqp->evtq, AL_SEQ_REF_EVT);
+ alEvtqFlushType(&seqp->evtq, AL_SEQP_MIDI_EVT);
+
+ /*
+ * sct 1/3/96 - Check to see which voices need to be
+ * killed and release them. Unkilled voices should
+ * have note end events occurring prior to
+ * KILL_TIME.
+ */
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
+ {
+ if (__voiceNeedsNoteKill (seqp, &vs->voice, KILL_TIME))
+ __seqpReleaseVoice(seqp, &vs->voice, KILL_TIME);
+ }
+
+ seqp->state = AL_STOPPING;
+ evt.type = AL_SEQP_STOP_EVT;
+ alEvtqPostEvent(&seqp->evtq, &evt, AL_EVTQ_END);
+ }
+ break;
+
+ case (AL_SEQP_VOL_EVT):
+ seqp->vol = seqp->nextEvent.msg.spvol.vol;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ n_alSynSetVol(&vs->voice, __vsVol(vs, seqp), __vsDelta(vs, seqp->curTime));
+ }
+ break;
+
+ case (AL_SEQP_LOOP_EVT):
+ seqp->loopStart = seqp->nextEvent.msg.loop.start;
+ seqp->loopEnd = seqp->nextEvent.msg.loop.end;
+ seqp->loopCount = seqp->nextEvent.msg.loop.count;
+ break;
+
+ case (AL_SEQP_PRIORITY_EVT):
+ chan = seqp->nextEvent.msg.sppriority.chan;
+ seqp->chanState[chan].priority = seqp->nextEvent.msg.sppriority.priority;
+ break;
+
+ case (AL_SEQP_SEQ_EVT):
+ matching_assert(seqp->state != AL_PLAYING, n_seqplayer.c, 0x11A); /* Must be done playing to change sequences. */
+
+ seqp->target = seqp->nextEvent.msg.spseq.seq;
+ __setUsptFromTempo (seqp, 500000.0);
+ if (seqp->bank)
+ __initFromBank(seqp, seqp->bank);
+ break;
+
+ case (AL_SEQP_BANK_EVT):
+ matching_assert(seqp->state == AL_STOPPED, n_seqplayer.c, 0x123); /* Must be fully stopped to change banks. */
+
+ seqp->bank = seqp->nextEvent.msg.spbank.bank;
+ __initFromBank(seqp, seqp->bank);
+ break;
+
+ /* sct 11/6/95 - these events should now be handled by __handleNextSeqEvent */
+ case (AL_SEQ_END_EVT):
+ case (AL_TEMPO_EVT):
+ case (AL_SEQ_MIDI_EVT):
+ matching_assert(FALSE, n_seqplayer.c, 0x12d);
+ break;
+ }
+
+ seqp->nextDelta = alEvtqNextEvent (&seqp->evtq, &seqp->nextEvent);
+
+ } while (seqp->nextDelta == 0);
+
+ /*
+ * assume that next callback won't be more than half an hour away
+ */
+ seqp->curTime += seqp->nextDelta; /* Update the player's current time. */
+ return seqp->nextDelta;
+}
+
+/*
+ Call this routine to handle the next event in the sequence.
+ Assumes that the next sequence event is scheduled to be processed
+ immediately since it does not check the event's tick time.
+ sct 11/7/95
+*/
+static void
+__handleNextSeqEvent(ALSeqPlayer *seqp)
+{
+ ALEvent evt;
+
+ /* sct 1/5/96 - Do nothing if we don't have a target sequence. */
+ if (seqp->target == NULL)
+ return;
+
+ func_80263850(seqp->target, &evt);
+
+ switch (evt.type)
+ {
+ case AL_SEQ_MIDI_EVT:
+ func_80261A94(seqp, &evt);
+ __postNextSeqEvent(seqp);
+ break;
+
+ case AL_TEMPO_EVT:
+ func_802617A0(seqp, &evt);
+ __postNextSeqEvent(seqp);
+ break;
+
+ case AL_SEQ_END_EVT:
+ seqp->state = AL_STOPPING;
+ evt.type = AL_SEQP_STOP_EVT;
+ alEvtqPostEvent(&seqp->evtq, &evt, AL_EVTQ_END);
+ break;
+
+ default:
+ matching_assert(FALSE, n_seqplayer.c, 0x162); /* Sequence event type not supported. */
+ }
+}
+
+
+void func_80261A94(ALSeqPlayer *seqp, ALEvent *event)
+{
+ ALVoice *voice;
+ ALVoiceState *vs;
+ s32 status;
+ u8 chan;
+ u8 key;
+ u8 vel;
+ u8 byte1;
+ u8 byte2;
+ ALMIDIEvent *midi = &event->msg.midi;
+ s16 vol;
+ ALEvent evt;
+ ALMicroTime deltaTime;
+ ALVoiceState *vstate;
+ ALPan pan;
+ ALFxRef fxref;
+
+ /* sct 12/15/95 - Fixed assert to also allow seqp midi event types. */
+ matching_assert(event->type == AL_SEQ_MIDI_EVT || event->type == AL_SEQP_MIDI_EVT, n_seqplayer.c, 0x17b);
+
+ status = midi->status & AL_MIDI_StatusMask;
+ chan = midi->status & AL_MIDI_ChannelMask;
+ byte1 = key = midi->byte1;
+ byte2 = vel = midi->byte2;
+
+ switch (status) {
+
+ case (AL_MIDI_NoteOn):
+
+ if (vel != 0) { /* a real note on */
+ ALVoiceConfig config;
+ ALSound *sound;
+ s16 cents;
+ f32 pitch,oscValue;
+ u8 fxmix;
+ void *oscState;
+ ALInstrument *inst;
+
+ /* If we're not playing, don't process note ons. */
+ if (seqp->state != AL_PLAYING)
+ break;
+
+ sound = __lookupSoundQuick(seqp, key, vel, chan);
+ ALFlagFailIf(!sound, seqp->debugFlags & NO_SOUND_ERR_MASK,
+ ERR_ALSEQP_NO_SOUND);
+
+ config.priority = seqp->chanState[chan].priority;
+ config.fxBus = 0;
+ config.unityPitch = 0;
+
+ vstate = __mapVoice(seqp, key, vel, chan);
+ ALFlagFailIf(!vstate, seqp->debugFlags & NO_VOICE_ERR_MASK,
+ ERR_ALSEQP_NO_VOICE );
+
+ voice = &vstate->voice;
+
+ n_alSynAllocVoice(voice, &config);
+
+ /*
+ * set up the voice state structure
+ */
+ vstate->sound = sound;
+ vstate->envPhase = AL_PHASE_ATTACK;
+ if (seqp->chanState[chan].sustain > AL_SUSTAIN)
+ vstate->phase = AL_PHASE_SUSTAIN;
+ else
+ vstate->phase = AL_PHASE_NOTEON;
+
+ cents = (key - sound->keyMap->keyBase) * 100
+ + sound->keyMap->detune;
+
+ vstate->pitch = alCents2Ratio(cents);
+ vstate->envGain = sound->envelope->attackVolume;
+ vstate->envEndTime = seqp->curTime +
+ sound->envelope->attackTime;
+
+ /*
+ * setup tremelo and vibrato if active
+ */
+ vstate->flags = 0;
+ inst = seqp->chanState[chan].instrument;
+
+ oscValue = (f32)AL_VOL_FULL; /* set this as a default */
+
+ if(inst->tremType)
+ {
+ if(seqp->initOsc)
+ {
+ deltaTime = (*seqp->initOsc)(&oscState,&oscValue,
+ inst->tremType,
+ inst->tremRate,
+ inst->tremDepth,
+ inst->tremDelay);
+
+ if(deltaTime) /* if deltaTime = zero, don't run osc */
+ {
+ evt.type = AL_TREM_OSC_EVT;
+ evt.msg.osc.vs = vstate;
+ evt.msg.osc.oscState = oscState;
+ alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
+ vstate->flags |= 0x01; /* set tremelo flag bit */
+ }
+ }
+ }
+ /* will default if not changed by initOsc */
+ vstate->tremelo = (u8)oscValue;
+
+ oscValue = 1.0f; /* set this as a default */
+ if(inst->vibType)
+ {
+ if(seqp->initOsc)
+ {
+ deltaTime = (*seqp->initOsc)(&oscState,&oscValue,
+ inst->vibType,
+ inst->vibRate,
+ inst->vibDepth,
+ inst->vibDelay);
+
+ if(deltaTime) /* if deltaTime = zero,don't run osc. */
+ {
+ evt.type = AL_VIB_OSC_EVT;
+ evt.msg.osc.vs = vstate;
+ evt.msg.osc.oscState = oscState;
+ evt.msg.osc.chan = chan;
+ alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
+ vstate->flags |= 0x02; /* set the vibrato flag bit */
+ }
+ }
+ }
+ /* will default if not changed by initOsc */
+ vstate->vibrato = oscValue;
+
+ /*
+ * calculate the note on parameters
+ */
+ pitch = vstate->pitch * seqp->chanState[chan].pitchBend *
+ vstate->vibrato;
+ fxmix = seqp->chanState[chan].fxmix;
+ pan = __vsPan(vstate, seqp);
+ vol = __vsVol(vstate, seqp);
+ deltaTime = sound->envelope->attackTime;
+
+ n_alSynStartVoiceParams(voice, sound->wavetable,
+ pitch, vol, pan, fxmix, deltaTime);
+ /*
+ * set up callbacks for envelope
+ */
+ evt.type = AL_SEQP_ENV_EVT;
+ evt.msg.vol.voice = voice;
+ evt.msg.vol.vol = sound->envelope->decayVolume;
+ evt.msg.vol.delta = sound->envelope->decayTime;
+ deltaTime = sound->envelope->attackTime;
+
+ alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
+
+ break;
+ }
+
+ /*
+ * NOTE: intentional fall-through for note on with zero
+ * velocity
+ */
+
+ case (AL_MIDI_NoteOff):
+ vstate = __lookupVoice(seqp, key, chan);
+ ALFlagFailIf(!vstate, (seqp->debugFlags & NOTE_OFF_ERR_MASK),
+ ERR_ALSEQP_OFF_VOICE );
+
+ if (vstate->phase == AL_PHASE_SUSTAIN)
+ {
+ rmonPrintf("TRACE: '%s' {Line %d}\n", FILE(n_seqplayer.c), LINE(0x211));
+ vstate->phase = AL_PHASE_SUSTREL;
+ } else {
+ vstate->phase = AL_PHASE_RELEASE;
+ rmonPrintf("TRACE: '%s' {Line %d}\n", FILE(n_seqplayer.c), LINE(0x214));
+ __seqpReleaseVoice(seqp, &vstate->voice,
+ vstate->sound->envelope->releaseTime);
+ }
+
+ break;
+
+ case (AL_MIDI_PolyKeyPressure):
+ /*
+ * Aftertouch per key (hardwired to volume). Note that
+ * aftertouch affects only notes that are already
+ * sounding.
+ */
+ vstate = __lookupVoice(seqp, key, chan);
+ ALFailIf(!vstate, ERR_ALSEQP_POLY_VOICE );
+
+ vstate->velocity = byte2;
+ n_alSynSetVol(&vstate->voice, __vsVol(vstate, seqp),
+ __vsDelta(vstate, seqp->curTime));
+ break;
+
+ case (AL_MIDI_ChannelPressure):
+ /*
+ * Aftertouch per channel (hardwired to volume). Note that
+ * aftertouch affects only notes that are already
+ * sounding.
+ */
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if (vs->channel == chan) {
+ vs->velocity = byte1;
+ n_alSynSetVol(&vs->voice, __vsVol(vs, seqp),
+ __vsDelta(vs, seqp->curTime));
+ }
+ }
+ break;
+
+ case (AL_MIDI_ControlChange):
+
+ switch (byte1) {
+
+ case (AL_MIDI_PAN_CTRL):
+ seqp->chanState[chan].pan = byte2;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if (vs->channel == chan) {
+ pan = __vsPan(vs, seqp);
+ n_alSynSetPan(&vs->voice, pan);
+ }
+ }
+ break;
+
+
+ case (AL_MIDI_VOLUME_CTRL):
+ seqp->chanState[chan].vol = byte2;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if ((vs->channel == chan) &&
+ (vs->envPhase != AL_PHASE_RELEASE))
+ {
+ vol = __vsVol(vs, seqp);
+ n_alSynSetVol(&vs->voice, vol,
+ __vsDelta(vs, seqp->curTime));
+ }
+ }
+ break;
+
+ case (0x7D):
+ seqp->chanState[chan].unkA = byte2;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if ((vs->channel == chan) &&
+ (vs->envPhase != AL_PHASE_RELEASE))
+ {
+ vol = __vsVol(vs, seqp);
+ n_alSynSetVol(&vs->voice, vol,
+ __vsDelta(vs, seqp->curTime));
+ }
+ }
+ break;
+
+ case (AL_MIDI_PRIORITY_CTRL):
+ /* leave current voices where they are */
+ seqp->chanState[chan].priority = byte2;
+ break;
+ case (AL_MIDI_SUSTAIN_CTRL):
+ seqp->chanState[chan].sustain = byte2;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if ((vs->channel == chan) &&
+ (vs->phase != AL_PHASE_RELEASE)) {
+ if ( byte2 > AL_SUSTAIN ) {
+ /*
+ * sustain pedal down
+ */
+ if (vs->phase == AL_PHASE_NOTEON)
+ vs->phase = AL_PHASE_SUSTAIN;
+ } else {
+ /*
+ * sustain pedal up
+ */
+ if (vs->phase == AL_PHASE_SUSTAIN)
+ vs->phase = AL_PHASE_NOTEON;
+ else if(vs->phase == AL_PHASE_SUSTREL) {
+ vs->phase = AL_PHASE_RELEASE;
+ __seqpReleaseVoice(seqp, &vs->voice,
+ vs->sound->envelope->releaseTime);
+ }
+ }
+ }
+ }
+ break;
+
+ case (AL_MIDI_FX1_CTRL):
+ seqp->chanState[chan].fxmix = byte2;
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if (vs->channel == chan) {
+ n_alSynSetFXMix(&vs->voice, byte2);
+ }
+ }
+ break;
+
+ case (AL_MIDI_FX_CTRL_0):
+ case (AL_MIDI_FX_CTRL_1):
+ case (AL_MIDI_FX_CTRL_2):
+ case (AL_MIDI_FX_CTRL_3):
+ case (AL_MIDI_FX_CTRL_4):
+ case (AL_MIDI_FX_CTRL_5):
+ case (AL_MIDI_FX_CTRL_6):
+ case (AL_MIDI_FX_CTRL_7):
+#if 0 /* fx control not implemented */
+ fxref = alSynGetFXRef(seqp->drvr, 0, 0);
+ if (fxref)
+ alSynSetFXParam(seqp->drvr, fxref, (s16)byte1, (void *)byte2);
+ break;
+#endif
+ case (AL_MIDI_FX3_CTRL):
+ default:
+ break;
+
+ }
+ break;
+
+ case (AL_MIDI_ProgramChange):
+ /* sct 1/16/96 - We must have a valid bank in order to process the program change. */
+ matching_assert(seqp->bank != NULL, n_seqplayer.c, 0x29c);
+
+
+ if (key < seqp->bank->instCount) {
+ ALInstrument *inst = seqp->bank->instArray[key];
+ __setInstChanState(seqp, inst, chan); /* sct 11/6/95 */
+ }
+#ifdef _DEBUG
+ else
+ __osError(ERR_ALSEQPINVALIDPROG, 2, key, seqp->bank->instCount);
+#endif
+ break;
+
+ case (AL_MIDI_PitchBendChange):
+ {
+ s32 bendVal;
+ f32 bendRatio;
+ s32 cents;
+
+ /*
+ * get 14-bit unsigned midi value
+ */
+ bendVal = ( (byte2 << 7) + byte1) - 8192;
+
+ /*
+ * calculate pitch bend in cents
+ */
+ cents = (seqp->chanState[chan].bendRange * bendVal)/8192;
+
+ /*
+ * calculate the corresponding ratio
+ */
+ bendRatio = alCents2Ratio(cents);
+ seqp->chanState[chan].pitchBend = bendRatio;
+
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if (vs->channel == chan) {
+ n_alSynSetPitch(&vs->voice,
+ vs->pitch * bendRatio * vs->vibrato);
+ }
+ }
+ }
+ break;
+
+ default:
+#ifdef _DEBUG
+ __osError(ERR_ALSEQPUNKNOWNMIDI, 1, status);
+#endif
+ break;
+ }
+}
+
+void func_802617A0(ALSeqPlayer *seqp, ALEvent *event)
+{
+ ALTempoEvent *tevt = &event->msg.tempo;
+ ALEvent evt;
+ s32 tempo;
+
+ if (event->msg.tempo.status == AL_MIDI_Meta)
+ {
+ if (event->msg.tempo.type == AL_MIDI_META_TEMPO)
+ {
+ tempo =
+ (tevt->byte1 << 16) |
+ (tevt->byte2 << 8) |
+ (tevt->byte3 << 0);
+ __setUsptFromTempo (seqp, (f32)tempo); /* sct 1/8/96 */
+ }
+ }
+}
+
+ALVoiceState *__mapVoice(ALSeqPlayer *seqp, u8 key, u8 vel, u8 channel)
+{
+ ALVoiceState *vs = seqp->vFreeList;
+
+ if (vs) {
+
+ seqp->vFreeList = vs->next;
+
+ vs->next = 0;
+
+ if (!seqp->vAllocHead)
+ seqp->vAllocHead = vs;
+ else
+ seqp->vAllocTail->next = vs;
+
+ seqp->vAllocTail = vs;
+
+ vs->channel = channel;
+ vs->key = key;
+ vs->velocity = vel;
+ vs->voice.clientPrivate = vs;
+ }
+
+ return vs;
+}
+
+void __unmapVoice(ALSeqPlayer *seqp, ALVoice *voice)
+{
+ ALVoiceState *prev = 0;
+ ALVoiceState *vs;
+
+ /*
+ * we could use doubly linked lists here and save some code and
+ * execution time, but time spent here in negligible, so it won't
+ * make much difference.
+ */
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if (&vs->voice == voice) {
+
+ if (prev)
+ prev->next = vs->next;
+ else
+ seqp->vAllocHead = vs->next;
+
+ if (vs == seqp->vAllocTail) {
+ seqp->vAllocTail = prev;
+ }
+
+ vs->next = seqp->vFreeList;
+ seqp->vFreeList = vs;
+ return;
+
+ }
+ prev = vs;
+ }
+#ifdef _DEBUG
+ __osError(ERR_ALSEQPUNMAP, 1, voice);
+#endif
+}
+
+ALVoiceState *__lookupVoice(ALSeqPlayer *seqp, u8 key, u8 channel)
+{
+ ALVoiceState *vs;
+
+ for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
+ if ((vs->key == key) && (vs->channel == channel) &&
+ (vs->phase != AL_PHASE_RELEASE) && (vs->phase != AL_PHASE_SUSTREL))
+ return vs;
+ }
+
+ return 0;
+}
+
+#if 0
+ALSound *__lookupSound(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan)
+{
+ s32 i;
+ ALInstrument *inst = seqp->chanState[chan].instrument;
+ ALSound *snd = 0;
+
+ for (i = 0; i < inst->soundCount; i++) {
+ ALSound *sound = inst->soundArray[i];
+ ALKeyMap *keymap = sound->keyMap;
+
+ if ((key >= keymap->keyMin) && (key <= keymap->keyMax) &&
+ (vel >= keymap->velocityMin) && (vel <= keymap->velocityMax)) {
+ snd = sound;
+ break;
+ }
+ }
+ return snd;
+}
+#endif
+
+ALSound *__lookupSoundQuick(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan)
+{
+ ALInstrument *inst = seqp->chanState[chan].instrument;
+ s32 l = 1;
+ s32 r = inst->soundCount;
+ s32 i;
+ ALKeyMap *keymap;
+
+ matching_assert(inst != NULL, n_seqplayer.c, 0x3DE); /* sct 10/31/95 - If inst is NULL, then the seqp probably wasn't setup correctly. */
+
+ while (r >= l) {
+ i = (l+r)/2;
+
+ keymap = inst->soundArray[i-1]->keyMap;
+
+ if ((key >= keymap->keyMin) && (key <= keymap->keyMax) &&
+ (vel >= keymap->velocityMin) && (vel <= keymap->velocityMax)) {
+ return inst->soundArray[i-1];
+ } else if ((key < keymap->keyMin) ||
+ ((vel < keymap->velocityMin) && (key <= keymap->keyMax))) {
+ r = i - 1;
+ } else {
+ l = i + 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * __vsVol calculates the target volume for the voice based on the
+ * note on velocity, envelope, sampleVolume and controller.
+ */
+// s16 __vsVol(ALVoiceState *vs, ALSeqPlayer *seqp)
+// {
+
+// u32 t1,t2;
+
+// t1 = (vs->tremelo*vs->velocity*vs->envGain) >> 6;
+// t2 = (vs->sound->sampleVolume*seqp->vol*
+// seqp->chanState[vs->channel].vol) >> 14;
+
+// t1 *= t2;
+// t1 >>= 15;
+
+// return( (s16)t1 );
+
+// }
+// s16 __vsVol(ALVoiceState *vs, ALSeqPlayer *seqp) {
+// ALChanState *temp_a2;
+
+// temp_a2 = &seqp->chanState[vs->channel];
+// return (s16) ((u32) (((s32) (temp_a2->unk9 * vs->tremelo * vs->velocity * vs->envGain) >> 0xD) * ((s32) (temp_a2->vol * vs->sound->sampleVolume * seqp->vol) >> 0xE)) >> 0xF);
+// }
+
+s16 __vsVol(N_ALVoiceState *vs, ALSeqPlayer *seqp)
+{
+ u32 t1, t2;
+ ALChanState *temp_a2;
+ t1 = (vs->tremelo*vs->velocity*vs->envGain*seqp->chanState[vs->channel].unkA) >> 13;
+ t2 = (vs->sound->sampleVolume*seqp->vol*seqp->chanState[vs->channel].vol) >> 14;
+
+ t1 *= t2;
+ t1 >>= 15;
+ return ((s16)t1);
+}
+
+ALMicroTime __vsDelta(ALVoiceState *vs, ALMicroTime t)
+{
+ /*
+ * If we are interrupting a previously set envelope segment, we
+ * need to recalculate the segment end time given the current
+ * time. Note: this routine assumes that the voice is currently
+ * playing.
+ */
+
+ s32 delta = vs->envEndTime - t;
+
+ if (delta >= 0) {
+ return delta;
+ } else {
+ return AL_GAIN_CHANGE_TIME;
+ }
+}
+
+ALPan __vsPan(ALVoiceState *vs, ALSeqPlayer *seqp)
+{
+ s32 tmp;
+
+ tmp = seqp->chanState[vs->channel].pan - AL_PAN_CENTER +
+ vs->sound->samplePan;
+ tmp = MAX(tmp, AL_PAN_LEFT);
+ tmp = MIN(tmp, AL_PAN_RIGHT);
+
+ return (ALPan) tmp;
+}
+
+#ifdef IMPLEMENTED
+
+s32 seqpGetVoices(SEQP *seqp);
+s32 seqpSetVoices(SEQP *seqp, s32 numvoices);
+
+u16 seqpGetChannelMask(SEQP *seqp);
+s32 seqpSetChannelMask(SEQP *seqp, u16 bitmask);
+
+#endif
+
+void __seqpReleaseVoice(ALSeqPlayer *seqp, ALVoice *voice,
+ ALMicroTime deltaTime)
+{
+ ALEvent evt;
+ ALVoiceState *vs = (ALVoiceState *)voice->clientPrivate;
+
+ /*
+ * if in attack phase, remove all pending volume
+ * events for this voice from the queue
+ */
+
+ if (vs->envPhase == AL_PHASE_ATTACK) {
+ ALLink *thisNode;
+ ALLink *nextNode;
+ ALEventListItem *thisItem, *nextItem;
+
+ thisNode = seqp->evtq.allocList.next;
+ while( thisNode != 0 ) {
+ nextNode = thisNode->next;
+ thisItem = (ALEventListItem *)thisNode;
+ nextItem = (ALEventListItem *)nextNode;
+ if (thisItem->evt.type == AL_SEQP_ENV_EVT) {
+ if(thisItem->evt.msg.vol.voice == voice) {
+ if( nextItem )
+ nextItem->delta += thisItem->delta;
+ alUnlink(thisNode);
+ alLink(thisNode, &seqp->evtq.freeList);
+ }
+ }
+ thisNode = nextNode;
+ }
+ }
+
+ vs->velocity = 0;
+ vs->envPhase = AL_PHASE_RELEASE;
+ vs->envGain = 0;
+ vs->envEndTime = seqp->curTime + deltaTime;
+
+ n_alSynSetPriority(voice, 0); /* make candidate for stealing */
+ n_alSynSetVol(voice, 0, deltaTime);
+ evt.type = AL_NOTE_END_EVT;
+ evt.msg.note.voice = voice;
+ deltaTime += 0x7D00;
+ alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
+}
+
+
+
+/*
+ This special purpose routine is called only when processing
+ a stopping event in order to properly kill all active voices.
+
+ The routine searches through the seqp's event queue for an
+ AL_NOTE_END_EVT for the given voice. If the event's execution
+ time is greater than kill time, it removes the event from the
+ event queue and returns true that it needs to kill the voice.
+ Otherwise, if the event's time is less than the kill time, it
+ returns false that the voice needs to be killed.
+ sct 1/3/96
+*/
+
+#define VOICENEEDSNOTEKILL_DEBUG _DEBUG_INTERNAL&&0 /* For debugging voiceNeedsNoteKill routine. */
+
+char __voiceNeedsNoteKill (ALSeqPlayer *seqp, ALVoice *voice, ALMicroTime killTime)
+{
+ ALLink *thisNode;
+ ALLink *nextNode;
+ ALEventListItem *thisItem;
+ ALMicroTime itemTime = 0;
+ char needsNoteKill = TRUE;
+
+#if VOICENEEDSNOTEKILL_DEBUG
+ alEvtqPrintAllocEvts (&seqp->evtq);
+#endif
+
+ thisNode = seqp->evtq.allocList.next;
+ while (thisNode != 0)
+ {
+ nextNode = thisNode->next;
+ thisItem = (ALEventListItem *)thisNode;
+ itemTime += thisItem->delta;
+
+ if (thisItem->evt.type == AL_NOTE_END_EVT)
+ {
+ if (thisItem->evt.msg.note.voice == voice)
+ {
+ if (itemTime > killTime)
+ {
+ if ((ALEventListItem *)nextNode)
+ ((ALEventListItem *)nextNode)->delta += thisItem->delta;
+ alUnlink(thisNode);
+ alLink(thisNode, &seqp->evtq.freeList);
+ }
+ else
+ needsNoteKill = FALSE;
+ break;
+ }
+ }
+ thisNode = nextNode;
+ }
+
+#if VOICENEEDSNOTEKILL_DEBUG
+ if (thisNode)
+ osSyncPrintf("vox 0x%0x: end time %d kill time %d\n\n", voice, itemTime, killTime);
+ else
+ osSyncPrintf("vox 0x%0x: not found\n\n", voice);
+
+ alEvtqPrintAllocEvts (&seqp->evtq);
+#endif
+
+ return needsNoteKill;
+}
+
+
+
+
+void __initFromBank(ALSeqPlayer *seqp, ALBank *b)
+{
+ /*
+ * init the chanState with the default instrument
+ */
+ s32 i;
+ ALInstrument *inst = 0;
+
+ /* set to the first available instrument. */
+ for(i = 0; !inst ; i++)
+ inst = b->instArray[i];
+
+ /* sct 11/6/95 - Setup the channel state for the given instrument. */
+ /* There is some wasted effort here since both calls the same state vars */
+ /* but it's safer. */
+ for (i = 0; i < seqp->maxChannels; i++) {
+ func_80261348(seqp, i);
+ __setInstChanState(seqp, inst, i);
+ }
+
+ if (b->percussion) {
+ func_80261348(seqp, i);
+ __setInstChanState(seqp, b->percussion, 9);
+ }
+}
+
+
+/*
+ sct 11/6/95 - Call this whenever a new instrument gets assigned to a channel
+ such as when changing banks or in response to a MIDI program change event.
+ Currently also gets called when changing sequences.
+*/
+
+void __setInstChanState(ALSeqPlayer *seqp, ALInstrument *inst, s32 chan)
+{
+ seqp->chanState[chan].instrument = inst;
+ seqp->chanState[chan].pan = inst->pan;
+ seqp->chanState[chan].vol = inst->volume;
+ seqp->chanState[chan].priority = inst->priority;
+ seqp->chanState[chan].bendRange = inst->bendRange;
+}
+
+
+/*
+ sct 11/6/95 -- Call this whenever a new sequence is to be played or when
+ initializing a sequence player.
+*/
+
+void func_80261348(ALSeqPlayer *seqp, s32 chan)
+{
+ seqp->chanState[chan].fxId = AL_FX_NONE;
+ seqp->chanState[chan].fxmix = AL_DEFAULT_FXMIX;
+ seqp->chanState[chan].pan = AL_PAN_CENTER;
+ seqp->chanState[chan].vol = AL_VOL_FULL;
+ seqp->chanState[chan].unkA = AL_VOL_FULL;
+ seqp->chanState[chan].priority = AL_DEFAULT_PRIORITY;
+ seqp->chanState[chan].sustain = 0;
+ seqp->chanState[chan].bendRange = 200;
+ seqp->chanState[chan].pitchBend = 1.0f;
+}
+
+
+/*
+ sct 11/6/95 - Called only when creating a new sequence player.
+*/
+void __initChanState(ALSeqPlayer *seqp)
+{
+ int i;
+
+ for (i = 0; i < seqp->maxChannels; i++)
+ {
+ seqp->chanState[i].instrument = 0;
+ func_80261348 (seqp, i);
+ }
+}
+
+
+void __seqpStopOsc(ALSeqPlayer *seqp, ALVoiceState *vs)
+{
+ ALEventListItem *thisNode,*nextNode;
+ s16 evtType;
+
+ thisNode = (ALEventListItem*)seqp->evtq.allocList.next;
+ while(thisNode)
+ {
+ nextNode = (ALEventListItem*)thisNode->node.next;
+ evtType = thisNode->evt.type;
+ if(evtType == AL_TREM_OSC_EVT || evtType == AL_VIB_OSC_EVT)
+ {
+ if(thisNode->evt.msg.osc.vs == vs)
+ {
+ (*seqp->stopOsc)(thisNode->evt.msg.osc.oscState);
+ alUnlink((ALLink*)thisNode);
+ if(nextNode)
+ nextNode->delta += thisNode->delta;
+ alLink((ALLink*)thisNode, &seqp->evtq.freeList);
+ if(evtType == AL_TREM_OSC_EVT)
+ vs->flags = vs->flags & 0xFE;
+ else /* must be a AL_VIB_OSC_EVT */
+ vs->flags = vs->flags & 0xFD;
+ if(!vs->flags)
+ return; /* there should be no more events */
+ }
+ }
+
+ thisNode = nextNode;
+ }
+}
+
+
+
+/*
+ This routine safely calculates the sequence player's
+ uspt value based on the given tempo. It does this safely
+ by making sure that the player has a target sequence and
+ therefore a qnpt value which is needed for the calculation.
+*/
+static void __setUsptFromTempo (ALSeqPlayer *seqp, f32 tempo)
+{
+ if (seqp->target)
+ seqp->uspt = (s32)((f32)tempo * seqp->target->qnpt);
+ else
+ seqp->uspt = 488; /* This is the initial value set by alSeqpNew. */
+}
+
+/*
+ Calculates the delta time in ticks until the next sequence
+ event taking into account loop points, and posts a
+ sequence reference event with the time in usecs.
+ Does nothing if the sequence player is not playing or there
+ is no target sequence.
+ sct 11/7/95
+*/
+void __postNextSeqEvent(ALSeqPlayer *seqp)
+{
+ ALEvent evt;
+ s32 deltaTicks;
+ ALSeq *seq = seqp->target;
+
+ /* sct 1/5/96 - Do nothing if we're not playing or don't have a target sequence. */
+ if ((seqp->state != AL_PLAYING) || (seq == NULL))
+ return;
+
+ /* Get the next event time in ticks. */
+ /* If false is returned, then there is no next delta (ie. end of sequence reached). */
+ if (!__alSeqNextDelta(seq, &deltaTicks))
+ return;
+
+ /* Handle loops. */
+ if (seqp->loopCount)
+ {
+ /* Assume that the loop end falls on a MIDI event. Delta time
+ will be correct even if we loop */
+ if (alSeqGetTicks(seq) + deltaTicks >= seqp->loopEnd->curTicks)
+ {
+ alSeqSetLoc(seq, seqp->loopStart);
+
+ if (seqp->loopCount != -1)
+ seqp->loopCount--;
+ }
+ }
+
+ evt.type = AL_SEQ_REF_EVT;
+ alEvtqPostEvent(&seqp->evtq, &evt, deltaTicks * seqp->uspt);
+}
\ No newline at end of file
diff --git a/src/core1/n_env.c b/src/core1/n_env.c
new file mode 100644
index 00000000..f872b84a
--- /dev/null
+++ b/src/core1/n_env.c
@@ -0,0 +1,12 @@
+#include
+#include "functions.h"
+#include "variables.h"
+
+
+#pragma GLOBAL_ASM("asm/nonmatchings/core1/n_env/func_80260860.s")
+
+#pragma GLOBAL_ASM("asm/nonmatchings/core1/n_env/func_802609E0.s")
+
+#pragma GLOBAL_ASM("asm/nonmatchings/core1/n_env/func_80260BD4.s")
+
+#pragma GLOBAL_ASM("asm/nonmatchings/core1/n_env/n_alEnvmixerPull.s")
diff --git a/src/core2/code_AEDA0.c b/src/core2/code_AEDA0.c
index 8bd8815a..0577e7d3 100644
--- a/src/core2/code_AEDA0.c
+++ b/src/core2/code_AEDA0.c
@@ -2,6 +2,21 @@
#include "functions.h"
#include "variables.h"
+Mtx *func_8024DD9C(void);
+void func_80251BCC(Mtx *);
+void func_80252330(f32, f32, f32);
+void mlMtxApply(Mtx *);
+void func_803382D8(s32 arg0);
+void func_803382E4(s32 arg0);
+void func_803382F0(s32 arg0);
+void func_803382FC(s32 arg0);
+void func_80338308(s32 arg0, s32 arg1);
+
+/* .data */
+extern Gfx D_80370260[];
+extern Gfx D_80370290[];
+extern Gfx D_803702C0[];
+extern Gfx D_80370308[];
extern u8 D_80370338[4];
extern u8 D_8037033C;
@@ -21,15 +36,136 @@ s32 D_8038363C;
s32 D_80383640;
s32 D_80383644;
+void func_803380F8(Gfx **gfx, Mtx **mtx, f32 arg2[3]);
+void func_803381B4(Gfx **gfx, Mtx **mtx, f32 arg2[3]);
+
/* .code */
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_80335D30.s")
+void func_80335D30(Gfx **gfx){
+ gDPPipeSync((*gfx)++);
+ if (D_80370338[0] == 0) {
+ gDPSetColorDither((*gfx)++, G_CD_DISABLE);
+ }//L80335D7C
+ switch(D_80383634 + 1){
+ case 0:
+ return;
+
+ case 15:
+ gSPDisplayList((*gfx)++, D_803702C0);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, 0xFF);
+ return;
+
+ case 12:
+ gSPDisplayList((*gfx)++, D_80370290);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, 0xFF);
+ return;
+
+ case 10:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineLERP((*gfx)++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038363C);
+ gDPSetEnvColor((*gfx)++, D_80383620, D_80383624, D_80383628, 0xFF);
+ return;
+
+ case 16:
+ gSPDisplayList((*gfx)++, D_80370290);
+ gDPSetCombineLERP((*gfx)++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038363C);
+ gDPSetEnvColor((*gfx)++, D_80383620, D_80383624, D_80383628, 0xFF);
+ return;
+
+ case 8:
+ if (D_8038361C != 0) {
+ gSPDisplayList((*gfx)++, D_80370308);
+ gDPSetCombineLERP((*gfx)++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, COMBINED, ENVIRONMENT, COMBINED, 0, 0, 0, COMBINED);
+ gDPSetEnvColor((*gfx)++, D_8038361C, D_8038361C, D_8038361C, 0xFF);
+ } else {
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ }
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038363C);
+ return;
+
+ case 7:
+ if (D_8038361C != 0) {
+ gSPDisplayList((*gfx)++, D_80370308);
+ gDPSetCombineLERP((*gfx)++, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0, PRIMITIVE, COMBINED, PRIMITIVE_ALPHA, COMBINED, 0, 0, 0, COMBINED);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038361C);
+ } else {
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, 0xFF);
+ }
+ return;
+
+ case 6:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038363C);
+ return;
+
+ case 13:
+ gSPDisplayList((*gfx)++, D_80370290);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, D_8038363C);
+ return;
+
+ case 5:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383610, D_80383614, D_80383618, 0xFF);
+ return;
+
+ case 9:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383630, D_80383630, D_80383630, D_8038363C);
+ return;
+
+ case 14:
+ gSPDisplayList((*gfx)++, D_80370290);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383630, D_80383630, D_80383630, D_8038363C);
+ return;
+
+ case 1:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383630, D_80383630, D_80383630, 0xFF);
+ return;
+
+ case 2:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineLERP((*gfx)++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor((*gfx)++, 0, 0, 0, 0, 0, D_8038363C);
+ return;
+
+ case 11:
+ gSPDisplayList((*gfx)++, D_80370290);
+ gDPSetCombineLERP((*gfx)++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor((*gfx)++, 0, 0, 0, 0, 0, D_8038363C);
+ return;
+
+ case 4:
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor((*gfx)++, 0, 0, D_80383620, D_80383624, D_80383628, D_8038362C);
+ return;
+
+ default://L80336814
+ gSPDisplayList((*gfx)++, D_80370260);
+ gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0, 0, 0, 0, PRIMITIVE);
+ gDPSetPrimColor((*gfx)++, 0, 0, 0, 0, 0, 0xFF);
+ return;
+ }
+}
void func_8033687C( Gfx **gfx )
{
/* Turn off texturing */
gDPPipeSync((*gfx)++);
if (D_80370338[0] == 0) {
- gDPSetColorDither((*gfx)++, 0);
+ gDPSetColorDither((*gfx)++, G_CD_MAGICSQ);
D_80370338[0] = 1;
}
@@ -363,19 +499,45 @@ void func_80337B68(Gfx **gfx, Vtx **vtx, Struct84s *texture_list, s32 texture_in
}
#endif
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_80338048.s")
+void func_80338048(Gfx **gfx, Mtx **mtx, Vtx **vtx, f32 arg3[3], Struct84s *arg4, s32 arg5) {
+ func_803380F8(gfx, mtx, arg3);
+ func_80337B68(gfx, vtx, arg4, arg5);
+ gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
+}
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_803380A0.s")
+void func_803380A0(Gfx **gfx, Mtx **mtx, Vtx **vtx, f32 arg3[3], Struct84s *arg4, s32 arg5) {
+ func_803381B4(gfx, mtx, arg3);
+ func_80337B68(gfx, vtx, arg4, arg5);
+ gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
+}
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_803380F8.s")
+void func_803380F8(Gfx **gfx, Mtx **mtx, f32 arg2[3]) {
+ f32 sp2C[3];
+ f32 sp20[3];
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_803381B4.s")
+ func_8024C5CC(sp2C);
+ sp20[0] = arg2[0] - sp2C[0];
+ sp20[1] = arg2[1] - sp2C[1];
+ sp20[2] = arg2[2] - sp2C[2];
+ func_80251BCC(func_8024DD90());
+ func_80252330(sp20[0], sp20[1], sp20[2]);
+ mlMtxApply(*mtx);
+ gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+}
-void func_803382D8(s32 arg0);
-void func_803382E4(s32 arg0);
-void func_803382F0(s32 arg0);
-void func_803382FC(s32 arg0);
-void func_80338308(s32 arg0, s32 arg1);
+void func_803381B4(Gfx **gfx, Mtx **mtx, f32 arg2[3]) {
+ f32 sp2C[3];
+ f32 sp20[3];
+
+ func_8024C5CC(sp2C);
+ sp20[0] = arg2[0] - sp2C[0];
+ sp20[1] = arg2[1] - sp2C[1];
+ sp20[2] = arg2[2] - sp2C[2];
+ func_80251BCC(func_8024DD9C());
+ func_80252330(sp20[0], sp20[1], sp20[2]);
+ mlMtxApply(*mtx);
+ gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+}
void func_80338270(){
func_803382D8(0xFF);
@@ -425,9 +587,13 @@ void func_80338338(s32 r, s32 g, s32 b){
D_80383618 = b;
}
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_80338354.s")
+void func_80338354(s32 arg0){
+ D_8038361C = arg0 / 8 ;
+}
-#pragma GLOBAL_ASM("asm/nonmatchings/core2/code_AEDA0/func_80338370.s")
+void func_80338370(void){
+ D_80370338[0] = 0;
+}
void func_8033837C(s32 arg0){
D_8037033C = arg0;
diff --git a/subyaml/core1.us.v10.yaml b/subyaml/core1.us.v10.yaml
index 0161feef..b1fe6ff6 100644
--- a/subyaml/core1.us.v10.yaml
+++ b/subyaml/core1.us.v10.yaml
@@ -52,6 +52,8 @@ segments:
- [0x13680, c, code_13680]
- [0x136D0, c, code_136D0]
- [0x13990, c, code_13990]
+ - [0x155F0, hasm, code_155F0] #DONE
+ - [0x15630, c, code_15630] #DONE
- [0x15770, c, code_15770]
- [0x15B30, c, code_15B30] #DONE
- [0x16A50, c, memory]
@@ -97,7 +99,8 @@ segments:
- [0x227F0, c, done/audio/n_drvrNew] #DONE
- [0x22D50, c, done/audio/n_save] #DONE
- [0x22DA0, c, done/audio/n_envresample] #DONE
- - [0x22E40, c, code_22E40] #n_seqplayer.c
+ - [0x22E40, c, n_env]
+ - [0x237F0, c, done/audio/n_seqplayer]
- [0x25360, c, done/audio/n_synstartvoiceparam] #DONE
- [0x25440, c, done/audio/n_mainbus] #DONE
- [0x254C0, c, done/audio/n_load] #DONE
@@ -267,7 +270,7 @@ segments:
- [0x39B60, .data, done/io/vimodempallan1]
- [0x39B60, .data, done/io/vimodentsclan1]
- [0x39C00, bin, data_39C00] # .rodata, code_1D00]
- - [0x39C20, bin, data_39C20] # .rodata, code_31C0]
+ - [0x39C20, .rodata, code_31C0]
- [0x39C30, bin, data_39C30] # .rodata, code_3A70]
- [0x39CA0, bin, data_39CA0] # .rodata, code_72B0]
- [0x39CD0, bin, data_39CD0] # .rodata, code_7F60]
@@ -285,7 +288,7 @@ segments:
- [0x3AD30, bin, data_3AD30]
- [0x3AD60, .rodata, done/audio/n_drvrNew]
- [0x3AD80, bin, data_3AD80]
- - [0x3ADD0, bin, data_3ADD0] # .rodata, code_22E40]
+ - [0x3ADD0, .rodata, done/audio/n_seqplayer]
- [0x3B180, .rodata, done/audio/n_resample]
- [0x3B190, .rodata, done/gu/sinf]
- [0x3B1E0, .rodata, done/audio/cents2ratio]
diff --git a/symbol_addrs.core1.us.v10.txt b/symbol_addrs.core1.us.v10.txt
index 6b2509e9..811071f4 100644
--- a/symbol_addrs.core1.us.v10.txt
+++ b/symbol_addrs.core1.us.v10.txt
@@ -35,7 +35,7 @@ mlMtxRotYaw = 0x80251D84;
mlMtxRotRoll = 0x80251E80;
mlMtxRotate = 0x80252188;
mlMtxScale_xyz = 0x802521C0;
-mlMtxScale = 0x80252280;
+mlMtxScale = 0x80252280;
mlMtx_apply_vec3s = 0x802525A4;
mlMtxTranslate = 0x80252980;