diff --git a/include/musyx/hardware.h b/include/musyx/hardware.h index 67bd47de..4ce786d5 100644 --- a/include/musyx/hardware.h +++ b/include/musyx/hardware.h @@ -1,13 +1,13 @@ #ifndef _MUSYX_HARDWARE #define _MUSYX_HARDWARE - #include "musyx/musyx_priv.h" + #ifdef __cplusplus extern "C" { #endif -u32 hwIsStudioActive(u8 studio); +bool hwIsStudioActive(u8 studio); #ifdef __cplusplus } diff --git a/include/musyx/musyx.h b/include/musyx/musyx.h index ebddc786..42c41a25 100644 --- a/include/musyx/musyx.h +++ b/include/musyx/musyx.h @@ -434,16 +434,16 @@ bool sndAuxCallbackPrepareChorus(SND_AUX_CHORUS* ch); bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch); bool sndAuxCallbackUpdateSettingsChorus(SND_AUX_CHORUS* ch); -#define SND_CROSSFADE_STOP 0 // Stop old song after fadedown -#define SND_CROSSFADE_PAUSE 1 // Pause old song after fadedown -#define SND_CROSSFADE_CONTINUE 2 // Continue previously paused song as new one -#define SND_CROSSFADE_START 0 // Start new song (no continue) -#define SND_CROSSFADE_SYNC 4 // Crossfade should start syncronized by sync-controller (104) -#define SND_CROSSFADE_PAUSENEW 8 // Pause new song before even starting it -#define SND_CROSSFADE_TRACKMUTE 16 // Use trackmute informtion -#define SND_CROSSFADE_SPEED 32 // Use speed informtion -#define SND_CROSSFADE_MUTE 64 // Old song continues playing & gets muted after fade down -#define SND_CROSSFADE_MUTENEW 128 // Mute new song after starting it +#define SND_CROSSFADE_STOP 0x0 // Stop old song after fadedown +#define SND_CROSSFADE_PAUSE 0x1 // Pause old song after fadedown +#define SND_CROSSFADE_CONTINUE 0x2 // Continue previously paused song as new one +#define SND_CROSSFADE_START 0x0 // Start new song (no continue) +#define SND_CROSSFADE_SYNC 0x4 // Crossfade should start syncronized by sync-controller (104) +#define SND_CROSSFADE_PAUSENEW 0x8 // Pause new song before even starting it +#define SND_CROSSFADE_TRACKMUTE 0x10 // Use trackmute informtion +#define SND_CROSSFADE_SPEED 0x20 // Use speed informtion +#define SND_CROSSFADE_MUTE 0x40 // Old song continues playing & gets muted after fade down +#define SND_CROSSFADE_MUTENEW 0x80 // Mute new song after starting it #define SND_CROSSFADE_DEFAULT 0 @@ -517,6 +517,33 @@ typedef struct SND_PROFILE_INFO { typedef void (*SND_PROF_USERCALLBACK)(struct SND_PROFILE_INFO*); extern SND_PROF_USERCALLBACK sndProfUserCallback; + +#define SND_MIDICTRL_MODULATION 0x01 +#define SND_MIDICTRL_VOLUME 0x07 +#define SND_MIDICTRL_PANNING 0x0A +#define SND_MIDICTRL_PEDAL 0x40 +#define SND_MIDICTRL_PORTAMENTO 0x41 +#define SND_MIDICTRL_REVERB 0x5B +#define SND_MIDICTRL_CHORUS 0x5D + +#define SND_MIDICTRL_PITCHBEND 0x80 +#define SND_MIDICTRL_SPANNING 0x83 +#define SND_MIDICTRL_DOPPLER 0x84 + +#define SND_SEQVOL_CONTINUE 0 +#define SND_SEQVOL_STOP 1 +#define SND_SEQVOL_PAUSE 2 +#define SND_SEQVOL_MUTE 3 +#define SND_SEQVOL_MODEMASK 0xF + +#define SND_ID_ERROR 0xFFFFFFFF // ID is invalid + +#define SND_MAX_SEQINSTANCES 8 +#define SND_SEQ_ERROR_ID 0xFFFFFFFF +#define SND_SEQ_CROSSFADE_ID 0x80000000 + +#define SND_PAUSEVOL_NORMAL 127 + #ifdef __cplusplus } #endif diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index 5810099d..95dce038 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -2,6 +2,7 @@ #define _MUSYX_MUSYX_PRIV #include "musyx/musyx.h" + #include "musyx/assert.h" #include "musyx/hardware.h" @@ -149,7 +150,7 @@ typedef struct _PBADPCM { u16 pred_scale; // offset 0x22, size 0x2 u16 yn1; // offset 0x24, size 0x2 u16 yn2; // offset 0x26, size 0x2 -} _PDADPCM; +} _PBADPCM; typedef struct _PBSRC { // total size: 0xE @@ -168,26 +169,26 @@ typedef struct _PBADPCMLOOP { typedef struct _PB { // total size: 0xBC - u16 nextHi; // offset 0x0, size 0x2 - u16 nextLo; // offset 0x2, size 0x2 - u16 currHi; // offset 0x4, size 0x2 - u16 currLo; // offset 0x6, size 0x2 - u16 srcSelect; // offset 0x8, size 0x2 - u16 coefSelect; // offset 0xA, size 0x2 - u16 mixerCtrl; // offset 0xC, size 0x2 - u16 state; // offset 0xE, size 0x2 - u16 loopType; // offset 0x10, size 0x2 - struct _PBMIX mix; // offset 0x12, size 0x24 - struct _PBITD itd; // offset 0x36, size 0xE - struct _PBUPDATE update; // offset 0x44, size 0xE - struct _PBDPOP dpop; // offset 0x52, size 0x12 - struct _PBVE ve; // offset 0x64, size 0x4 - struct _PBFIR fir; // offset 0x68, size 0x6 - struct _PBADDR addr; // offset 0x6E, size 0x10 - struct _PBADPCM adpcm; // offset 0x7E, size 0x28 - struct _PBSRC src; // offset 0xA6, size 0xE - struct _PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6 - u16 streamLoopCnt; // offset 0xBA, size 0x2 + u16 nextHi; // offset 0x0, size 0x2 + u16 nextLo; // offset 0x2, size 0x2 + u16 currHi; // offset 0x4, size 0x2 + u16 currLo; // offset 0x6, size 0x2 + u16 srcSelect; // offset 0x8, size 0x2 + u16 coefSelect; // offset 0xA, size 0x2 + u16 mixerCtrl; // offset 0xC, size 0x2 + u16 state; // offset 0xE, size 0x2 + u16 loopType; // offset 0x10, size 0x2 + _PBMIX mix; // offset 0x12, size 0x24 + _PBITD itd; // offset 0x36, size 0xE + _PBUPDATE update; // offset 0x44, size 0xE + _PBDPOP dpop; // offset 0x52, size 0x12 + _PBVE ve; // offset 0x64, size 0x4 + _PBFIR fir; // offset 0x68, size 0x6 + _PBADDR addr; // offset 0x6E, size 0x10 + _PBADPCM adpcm; // offset 0x7E, size 0x28 + _PBSRC src; // offset 0xA6, size 0xE + _PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6 + u16 streamLoopCnt; // offset 0xBA, size 0x2 } _PB; typedef struct SAMPLE_INFO { @@ -236,20 +237,20 @@ typedef struct SAMPLE_HEADER { typedef struct SDIR_DATA { // total size: 0x20 - u16 id; // offset 0x0, size 0x2 - u16 ref_cnt; // offset 0x2, size 0x2 - u32 offset; // offset 0x4, size 0x4 - void* addr; // offset 0x8, size 0x4 - struct SAMPLE_HEADER header; // offset 0xC, size 0x10 - u32 extraData; // offset 0x1C, size 0x4 + u16 id; // offset 0x0, size 0x2 + u16 ref_cnt; // offset 0x2, size 0x2 + u32 offset; // offset 0x4, size 0x4 + void* addr; // offset 0x8, size 0x4 + SAMPLE_HEADER header; // offset 0xC, size 0x10 + u32 extraData; // offset 0x1C, size 0x4 } SDIR_DATA; typedef struct SDIR_TAB { // total size: 0xC - struct SDIR_DATA* data; // offset 0x0, size 0x4 - void* base; // offset 0x4, size 0x4 - u16 numSmp; // offset 0x8, size 0x2 - u16 res; // offset 0xA, size 0x2 + SDIR_DATA* data; // offset 0x0, size 0x4 + void* base; // offset 0x4, size 0x4 + u16 numSmp; // offset 0x8, size 0x2 + u16 res; // offset 0xA, size 0x2 } SDIR_TAB; typedef struct DATA_TAB { @@ -283,9 +284,9 @@ typedef struct MAC_SUBTAB { typedef struct GSTACK { // total size: 0xC - struct GROUP_DATA* gAddr; // offset 0x0, size 0x4 - struct SDIR_DATA* sdirAddr; // offset 0x4, size 0x4 - void* prjAddr; // offset 0x8, size 0x4 + GROUP_DATA* gAddr; // offset 0x0, size 0x4 + SDIR_DATA* sdirAddr; // offset 0x4, size 0x4 + void* prjAddr; // offset 0x8, size 0x4 } GSTACK; typedef struct VSampleInfo { @@ -296,7 +297,7 @@ typedef struct VSampleInfo { } VSampleInfo; typedef struct DSPvoice { - struct _PB* pb; + _PB* pb; void* patchData; void* itdBuffer; struct DSPvoice* next; @@ -374,8 +375,8 @@ typedef struct MSTEP { } MSTEP; typedef struct CALLSTACK { - struct MSTEP* addr; - struct MSTEP* curAddr; + MSTEP* addr; + MSTEP* curAddr; } CALLSTACK; typedef struct SYNTH_QUEUE { @@ -407,25 +408,25 @@ typedef struct SYNTH_LFO { typedef struct SYNTHMasterFader { // total size: 0x30 - float volume; // offset 0x0, size 0x4 - float target; // offset 0x4, size 0x4 - float start; // offset 0x8, size 0x4 - float time; // offset 0xC, size 0x4 - float deltaTime; // offset 0x10, size 0x4 - float pauseVol; // offset 0x14, size 0x4 - float pauseTarget; // offset 0x18, size 0x4 - float pauseStart; // offset 0x1C, size 0x4 - float pauseTime; // offset 0x20, size 0x4 - float pauseDeltaTime; // offset 0x24, size 0x4 - u32 seqId; // offset 0x28, size 0x4 - u8 seqMode; // offset 0x2C, size 0x1 - u8 type; // offset 0x2D, size 0x1 + f32 volume; // offset 0x0, size 0x4 + f32 target; // offset 0x4, size 0x4 + f32 start; // offset 0x8, size 0x4 + f32 time; // offset 0xC, size 0x4 + f32 deltaTime; // offset 0x10, size 0x4 + f32 pauseVol; // offset 0x14, size 0x4 + f32 pauseTarget; // offset 0x18, size 0x4 + f32 pauseStart; // offset 0x1C, size 0x4 + f32 pauseTime; // offset 0x20, size 0x4 + f32 pauseDeltaTime; // offset 0x24, size 0x4 + u32 seqId; // offset 0x28, size 0x4 + u8 seqMode; // offset 0x2C, size 0x1 + u8 type; // offset 0x2D, size 0x1 } SYNTHMasterFader; typedef struct CTRL_SOURCE { u8 midiCtrl; u8 combine; - long scale; + s32 scale; } CTRL_SOURCE; typedef struct CTRL_DEST { @@ -469,7 +470,7 @@ typedef struct _VS { u8 voices[64]; // offset 0x908, size 0x40 u16 nextInstID; // offset 0x948, size 0x2 u32 (*callback)(u8, - struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 + SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 } VS; extern VS vs; @@ -500,7 +501,7 @@ typedef struct SYNTH_VOICE { u64 waitTime; u8 timeUsedByInput; u16 loop; - long local_vars[16]; + s32 local_vars[16]; u32 child; u32 parent; u32 id; @@ -532,44 +533,44 @@ typedef struct SYNTH_VOICE { u16 portLastCtrlState; u32 portDuration; u32 portCurPitch; - u32 portTime; // offset 0x13C, size 0x4 - u8 vibKeyRange; // offset 0x140, size 0x1 - u8 vibCentRange; // offset 0x141, size 0x1 - u32 vibPeriod; // offset 0x144, size 0x4 - u32 vibCurTime; // offset 0x148, size 0x4 - long vibCurOffset; // offset 0x14C, size 0x4 - s16 vibModAddScale; // offset 0x150, size 0x2 - u32 volume; // offset 0x154, size 0x4 - u32 orgVolume; // offset 0x158, size 0x4 - float lastVolFaderScale; // offset 0x15C, size 0x4 - u32 lastPan; // offset 0x160, size 0x4 - u32 lastSPan; // offset 0x164, size 0x4 - float treCurScale; // offset 0x168, size 0x4 - u16 treScale; // offset 0x16C, size 0x2 - u16 treModAddScale; // offset 0x16E, size 0x2 - u32 panning[2]; // offset 0x170, size 0x8 - long panDelta[2]; // offset 0x178, size 0x8 - u32 panTarget[2]; // offset 0x180, size 0x8 - u32 panTime[2]; // offset 0x188, size 0x8 - u8 revVolScale; // offset 0x190, size 0x1 - u8 revVolOffset; // offset 0x191, size 0x1 - u8 volTable; // offset 0x192, size 0x1 - u8 itdMode; // offset 0x193, size 0x1 - long envDelta; // offset 0x194, size 0x4 - u32 envTarget; // offset 0x198, size 0x4 - u32 envCurrent; // offset 0x19C, size 0x4 - u32 sweepOff[2]; // offset 0x1A0, size 0x8 - long sweepAdd[2]; // offset 0x1A8, size 0x8 - long sweepCnt[2]; // offset 0x1B0, size 0x8 - u8 sweepNum[2]; // offset 0x1B8, size 0x2 - struct SYNTH_LFO lfo[2]; // offset 0x1BC, size 0x18 - u8 lfoUsedByInput[2]; // offset 0x1D4, size 0x2 - u8 pbLowerKeyRange; // offset 0x1D6, size 0x1 - u8 pbUpperKeyRange; // offset 0x1D7, size 0x1 - u16 pbLast; // offset 0x1D8, size 0x2 - struct ADSR_VARS pitchADSR; // offset 0x1DC, size 0x28 - s16 pitchADSRRange; // offset 0x204, size 0x2 - u16 curPitch; // offset 0x206, size 0x2 + u32 portTime; // offset 0x13C, size 0x4 + u8 vibKeyRange; // offset 0x140, size 0x1 + u8 vibCentRange; // offset 0x141, size 0x1 + u32 vibPeriod; // offset 0x144, size 0x4 + u32 vibCurTime; // offset 0x148, size 0x4 + s32 vibCurOffset; // offset 0x14C, size 0x4 + s16 vibModAddScale; // offset 0x150, size 0x2 + u32 volume; // offset 0x154, size 0x4 + u32 orgVolume; // offset 0x158, size 0x4 + f32 lastVolFaderScale; // offset 0x15C, size 0x4 + u32 lastPan; // offset 0x160, size 0x4 + u32 lastSPan; // offset 0x164, size 0x4 + f32 treCurScale; // offset 0x168, size 0x4 + u16 treScale; // offset 0x16C, size 0x2 + u16 treModAddScale; // offset 0x16E, size 0x2 + u32 panning[2]; // offset 0x170, size 0x8 + s32 panDelta[2]; // offset 0x178, size 0x8 + u32 panTarget[2]; // offset 0x180, size 0x8 + u32 panTime[2]; // offset 0x188, size 0x8 + u8 revVolScale; // offset 0x190, size 0x1 + u8 revVolOffset; // offset 0x191, size 0x1 + u8 volTable; // offset 0x192, size 0x1 + u8 itdMode; // offset 0x193, size 0x1 + s32 envDelta; // offset 0x194, size 0x4 + u32 envTarget; // offset 0x198, size 0x4 + u32 envCurrent; // offset 0x19C, size 0x4 + u32 sweepOff[2]; // offset 0x1A0, size 0x8 + s32 sweepAdd[2]; // offset 0x1A8, size 0x8 + s32 sweepCnt[2]; // offset 0x1B0, size 0x8 + u8 sweepNum[2]; // offset 0x1B8, size 0x2 + SYNTH_LFO lfo[2]; // offset 0x1BC, size 0x18 + u8 lfoUsedByInput[2]; // offset 0x1D4, size 0x2 + u8 pbLowerKeyRange; // offset 0x1D6, size 0x1 + u8 pbUpperKeyRange; // offset 0x1D7, size 0x1 + u16 pbLast; // offset 0x1D8, size 0x2 + ADSR_VARS pitchADSR; // offset 0x1DC, size 0x28 + s16 pitchADSRRange; // offset 0x204, size 0x2 + u16 curPitch; // offset 0x206, size 0x2 struct setup { u8 vol; // offset 0x0, size 0x1 u8 pan; // offset 0x1, size 0x1 @@ -598,7 +599,7 @@ typedef struct SYNTH_VOICE { u8 mesgNum; // offset 0x3EC, size 0x1 u8 mesgRead; // offset 0x3ED, size 0x1 u8 mesgWrite; // offset 0x3EE, size 0x1 - long mesgQueue[4]; // offset 0x3F0, size 0x10 + s32 mesgQueue[4]; // offset 0x3F0, size 0x10 u16 curOutputVolume; // offset 0x400, size 0x2 } SYNTH_VOICE; @@ -658,31 +659,31 @@ typedef struct POOL_DATA { typedef struct SAL_VOLINFO { // total size: 0x24 - float volL; // offset 0x0, size 0x4 - float volR; // offset 0x4, size 0x4 - float volS; // offset 0x8, size 0x4 - float volAuxAL; // offset 0xC, size 0x4 - float volAuxAR; // offset 0x10, size 0x4 - float volAuxAS; // offset 0x14, size 0x4 - float volAuxBL; // offset 0x18, size 0x4 - float volAuxBR; // offset 0x1C, size 0x4 - float volAuxBS; // offset 0x20, size 0x4 + f32 volL; // offset 0x0, size 0x4 + f32 volR; // offset 0x4, size 0x4 + f32 volS; // offset 0x8, size 0x4 + f32 volAuxAL; // offset 0xC, size 0x4 + f32 volAuxAR; // offset 0x10, size 0x4 + f32 volAuxAS; // offset 0x14, size 0x4 + f32 volAuxBL; // offset 0x18, size 0x4 + f32 volAuxBR; // offset 0x1C, size 0x4 + f32 volAuxBS; // offset 0x20, size 0x4 } SAL_VOLINFO; typedef struct SAL_PANINFO { // total size: 0x30 - u32 pan_i; // offset 0x0, size 0x4 - u32 pan_im; // offset 0x4, size 0x4 - u32 span_i; // offset 0x8, size 0x4 - u32 span_im; // offset 0xC, size 0x4 - u32 rpan_i; // offset 0x10, size 0x4 - u32 rpan_im; // offset 0x14, size 0x4 - float pan_f; // offset 0x18, size 0x4 - float pan_fm; // offset 0x1C, size 0x4 - float span_f; // offset 0x20, size 0x4 - float span_fm; // offset 0x24, size 0x4 - float rpan_f; // offset 0x28, size 0x4 - float rpan_fm; // offset 0x2C, size 0x4 + u32 pan_i; // offset 0x0, size 0x4 + u32 pan_im; // offset 0x4, size 0x4 + u32 span_i; // offset 0x8, size 0x4 + u32 span_im; // offset 0xC, size 0x4 + u32 rpan_i; // offset 0x10, size 0x4 + u32 rpan_im; // offset 0x14, size 0x4 + f32 pan_f; // offset 0x18, size 0x4 + f32 pan_fm; // offset 0x1C, size 0x4 + f32 span_f; // offset 0x20, size 0x4 + f32 span_fm; // offset 0x24, size 0x4 + f32 rpan_f; // offset 0x28, size 0x4 + f32 rpan_fm; // offset 0x2C, size 0x4 } SAL_PANINFO; typedef struct _SPB { @@ -718,44 +719,44 @@ typedef struct _SPB { typedef struct DSPhostDPop { // total size: 0x24 - long l; // offset 0x0, size 0x4 - long r; // offset 0x4, size 0x4 - long s; // offset 0x8, size 0x4 - long lA; // offset 0xC, size 0x4 - long rA; // offset 0x10, size 0x4 - long sA; // offset 0x14, size 0x4 - long lB; // offset 0x18, size 0x4 - long rB; // offset 0x1C, size 0x4 - long sB; // offset 0x20, size 0x4 + s32 l; // offset 0x0, size 0x4 + s32 r; // offset 0x4, size 0x4 + s32 s; // offset 0x8, size 0x4 + s32 lA; // offset 0xC, size 0x4 + s32 rA; // offset 0x10, size 0x4 + s32 sA; // offset 0x14, size 0x4 + s32 lB; // offset 0x18, size 0x4 + s32 rB; // offset 0x1C, size 0x4 + s32 sB; // offset 0x20, size 0x4 } DSPhostDPop; typedef struct DSPinput { // total size: 0xC - u8 studio; // offset 0x0, size 0x1 - u16 vol; // offset 0x2, size 0x2 - u16 volA; // offset 0x4, size 0x2 - u16 volB; // offset 0x6, size 0x2 - struct SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4 + u8 studio; // offset 0x0, size 0x1 + u16 vol; // offset 0x2, size 0x2 + u16 volA; // offset 0x4, size 0x2 + u16 volB; // offset 0x6, size 0x2 + SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4 } DSPinput; typedef struct DSPstudioinfo { // total size: 0xBC - struct _SPB* spb; // offset 0x0, size 0x4 - struct DSPhostDPop hostDPopSum; // offset 0x4, size 0x24 - long* main[2]; // offset 0x28, size 0x8 - long* auxA[3]; // offset 0x30, size 0xC - long* auxB[3]; // offset 0x3C, size 0xC - struct DSPvoice* voiceRoot; // offset 0x48, size 0x4 - struct DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4 - u8 state; // offset 0x50, size 0x1 - u8 isMaster; // offset 0x51, size 0x1 - u8 numInputs; // offset 0x52, size 0x1 - SND_STUDIO_TYPE type; // offset 0x54, size 0x4 - struct DSPinput in[7]; // offset 0x58, size 0x54 - SND_AUX_CALLBACK auxAHandler; // offset 0xAC, size 0x4 - SND_AUX_CALLBACK auxBHandler; // offset 0xB0, size 0x4 - void* auxAUser; // offset 0xB4, size 0x4 - void* auxBUser; // offset 0xB8, size 0x4 + _SPB* spb; // offset 0x0, size 0x4 + DSPhostDPop hostDPopSum; // offset 0x4, size 0x24 + s32* main[2]; // offset 0x28, size 0x8 + s32* auxA[3]; // offset 0x30, size 0xC + s32* auxB[3]; // offset 0x3C, size 0xC + DSPvoice* voiceRoot; // offset 0x48, size 0x4 + DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4 + u8 state; // offset 0x50, size 0x1 + u8 isMaster; // offset 0x51, size 0x1 + u8 numInputs; // offset 0x52, size 0x1 + SND_STUDIO_TYPE type; // offset 0x54, size 0x4 + DSPinput in[7]; // offset 0x58, size 0x54 + SND_AUX_CALLBACK auxAHandler; // offset 0xAC, size 0x4 + SND_AUX_CALLBACK auxBHandler; // offset 0xB0, size 0x4 + void* auxAUser; // offset 0xB4, size 0x4 + void* auxBUser; // offset 0xB8, size 0x4 } DSPstudioinfo; extern DSPstudioinfo dspStudio[8]; @@ -769,6 +770,7 @@ typedef struct CHANNEL_DEFAULTS { // total size: 0x1 u8 pbRange; // offset 0x0, size 0x1 } CHANNEL_DEFAULTS; + typedef struct FX_TAB { // total size: 0xA u16 id; // offset 0x0, size 0x2 @@ -783,16 +785,16 @@ typedef struct FX_TAB { typedef struct FX_DATA { // total size: 0xE - u16 num; // offset 0x0, size 0x2 - u16 reserverd; // offset 0x2, size 0x2 - struct FX_TAB fx[1]; // offset 0x4, size 0xA + u16 num; // offset 0x0, size 0x2 + u16 reserverd; // offset 0x2, size 0x2 + FX_TAB fx[1]; // offset 0x4, size 0xA } FX_DATA; typedef struct FX_GROUP { // total size: 0x8 - u16 gid; // offset 0x0, size 0x2 - u16 fxNum; // offset 0x2, size 0x2 - struct FX_TAB* fxTab; // offset 0x4, size 0x4 + u16 gid; // offset 0x0, size 0x2 + u16 fxNum; // offset 0x2, size 0x2 + FX_TAB* fxTab; // offset 0x4, size 0x4 } FX_GROUP; typedef struct PAGE { @@ -825,12 +827,12 @@ typedef struct ADSR_INFO { union ai_data { struct { // total size: 0x14 - long atime; // offset 0x0, size 0x4 - long dtime; // offset 0x4, size 0x4 - u16 slevel; // offset 0x8, size 0x2 - u16 rtime; // offset 0xA, size 0x2 - long ascale; // offset 0xC, size 0x4 - long dscale; // offset 0x10, size 0x4 + s32 atime; // offset 0x0, size 0x4 + s32 dtime; // offset 0x4, size 0x4 + u16 slevel; // offset 0x8, size 0x2 + u16 rtime; // offset 0xA, size 0x2 + s32 ascale; // offset 0xC, size 0x4 + s32 dscale; // offset 0x10, size 0x4 } dls; struct { // total size: 0x8 @@ -850,7 +852,7 @@ u32 dataInsertMacro(u16 mid, void* macroaddr); u32 dataRemoveMacro(u16 mid); u32 dataInsertCurve(u16 cid, void* curvedata); u32 dataRemoveCurve(u16 sid); -long dataGetSample(u16 sid, SAMPLE_INFO* newsmp); +s32 dataGetSample(u16 sid, SAMPLE_INFO* newsmp); void* dataGetCurve(u16 cid); u32 dataAddSampleReference(u16 sid); u32 dataRemoveSampleReference(u16 sid); @@ -863,7 +865,7 @@ FX_TAB* dataGetFX(u16 fid); s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */ void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio, u32 callbackUserValue, u32 setSRC, u8 itdMode); -void hwSetVolume(u32 v, u8 table, float vol, u32 pan, u32 span, float auxa, float auxb); +void hwSetVolume(u32 v, u8 table, f32 vol, u32 pan, u32 span, f32 auxa, f32 auxb); void hwSetPitch(u32 v, u16 speed); void hwEnableIrq(); void hwDisableIrq(); @@ -885,14 +887,14 @@ void synthSetBpm(u32 pbm, u8 set, u8 section); void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src); void synthSetMusicVolumeType(u8 vGroup, u8 type); -extern long synthGlobalVariable[16]; +extern s32 synthGlobalVariable[16]; extern u16 voicePrioSortRootListRoot; extern u8 voiceMusicRunning; extern u8 voiceFxRunning; extern u8 voiceListInsert; extern u8 voiceListRoot; -void voiceSetPriority(struct SYNTH_VOICE* svoice, u8 prio); -u32 voiceIsLastStarted(struct SYNTH_VOICE* svoice); +void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio); +u32 voiceIsLastStarted(SYNTH_VOICE* svoice); s32 voiceKillSound(u32 voiceid); extern u64 synthRealTime; @@ -933,7 +935,7 @@ extern SND_MESSAGE_CALLBACK salMessageCallback; extern SYNTH_MESSAGE_CALLBACK synthMessageCallback; /* Math */ void salApplyMatrix(const SND_FMATRIX* a, const SND_FVECTOR* b, SND_FVECTOR* out); -float salNormalizeVector(SND_FVECTOR* vec); +f32 salNormalizeVector(SND_FVECTOR* vec); void salCrossProduct(SND_FVECTOR* out, const SND_FVECTOR* a, const SND_FVECTOR* b); void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in); @@ -948,8 +950,8 @@ void salDeactivateVoice(DSPvoice* dsp_vptr); void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type); void salDeactivateStudio(u8 studio); void salActivateVoice(DSPvoice* dsp_vptr, u8 studio); -void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, float vol, u32 pan, u32 span, float auxa, - float auxb, u32 itd, u32 dpl2); +void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, f32 vol, u32 pan, u32 span, f32 auxa, f32 auxb, + u32 itd, u32 dpl2); void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio); void* salMalloc(u32 len); void salFree(void* addr); @@ -1015,8 +1017,9 @@ typedef struct STREAM_INFO { void streamOutputModeChanged(); u8 inpTranslateExCtrl(u8 ctrl); void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag); -void inpAddCtrl(struct CTRL_DEST* dest, u8 ctrl, long scale, u8 comb, u32 isVar); -void inpSetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set, unsigned char value); +void inpAddCtrl(CTRL_DEST* dest, u8 ctrl, s32 scale, u8 comb, u32 isVar); +void inpSetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set, + unsigned char value); void inpSetMidiCtrl14(unsigned char ctrl, unsigned char channel, unsigned char set, u16 value); void inpSetExCtrl(SYNTH_VOICE* svoice, u8 ctrl, s16 v); CHANNEL_DEFAULTS* inpGetChannelDefaults(u8 midi, u8 midiSet); @@ -1028,6 +1031,8 @@ u16 inpGetExCtrl(SYNTH_VOICE* svoice, u8 ctrl); u16 inpGetMidiCtrl(u8 ctrl, u8 channel, u8 set); void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key); u16 inpGetModulation(SYNTH_VOICE* svoice); +void inpResetMidiCtrl(u8 ch, u8 set, u32 coldReset); +void inpResetChannelDefaults(u8 midi, u8 midiSet); /* TODO: Figure out what `unk` is */ void hwSetSRCType(u32 v, u8 salSRCType); void hwSetITDMode(u32 v, u8 mode); diff --git a/include/musyx/seq.h b/include/musyx/seq.h index 41c16e53..8b0cc336 100644 --- a/include/musyx/seq.h +++ b/include/musyx/seq.h @@ -9,15 +9,18 @@ extern "C" { typedef struct ARR { // total size: 0x58 - unsigned long tTab; // offset 0x0, size 0x4 - unsigned long pTab; // offset 0x4, size 0x4 - unsigned long tmTab; // offset 0x8, size 0x4 - unsigned long mTrack; // offset 0xC, size 0x4 - unsigned long info; // offset 0x10, size 0x4 - unsigned long loopPoint[16]; // offset 0x14, size 0x40 - unsigned long tsTab; // offset 0x54, size 0x4 + u32 tTab; // offset 0x0, size 0x4 + u32 pTab; // offset 0x4, size 0x4 + u32 tmTab; // offset 0x8, size 0x4 + u32 mTrack; // offset 0xC, size 0x4 + u32 info; // offset 0x10, size 0x4 + u32 loopPoint[16]; // offset 0x14, size 0x40 + u32 tsTab; // offset 0x54, size 0x4 } ARR; +#define ARR_GET(arr, offset) ((void*)(offset + (u32)arr)) +#define ARR_GET_TYPE(arr, offset, ty) ((ty)ARR_GET(arr, offset)) + typedef struct TENTRY { // total size: 0xC u32 time; // offset 0x0, size 0x4 @@ -117,7 +120,7 @@ typedef struct TICKS { typedef struct SEQ_SECTION { // total size: 0x38 - struct MTRACK mTrack; // offset 0x0, size 0x8 + MTRACK mTrack; // offset 0x0, size 0x8 u32 bpm; // offset 0x8, size 0x4 TICKS tickDelta[2]; // offset 0xC, size 0x10 SEQ_EVENT* globalEventRoot; // offset 0x1C, size 0x4 @@ -159,21 +162,30 @@ typedef struct SEQ_INSTANCE { SEQ_SECTION section[16]; // offset 0x14E8, size 0x380 } SEQ_INSTANCE; +typedef struct SEQ_PATTERN { + // total size: 0x10 + u32 headerLen; // offset 0x0, size 0x4 + u32 pitchBend; // offset 0x4, size 0x4 + u32 modulation; // offset 0x8, size 0x4 + u32 noteData; // offset 0xC, size 0x4 +} SEQ_PATTERN; + extern u8 synthTrackVolume[64]; extern SEQ_INSTANCE seqInstance[8]; extern u16 seqMIDIPriority[8][16]; -void seqSpeed(unsigned long seqId, unsigned short speed); -void seqVolume(unsigned char volume, unsigned short time, unsigned long seqId, unsigned char mode); +void seqSpeed(u32 seqId, u16 speed); +void seqVolume(u8 volume, u16 time, u32 seqId, u8 mode); void sndSeqStop(s32 unk); void sndSeqSpeed(u32 seqId, u16 speed); void sndSeqContinue(s32 unk); void sndSeqMute(s32 unk1, s32 unk2, s32 unk3); -void sndSeqVolume(unsigned char volume, unsigned short time, unsigned long seqId, - unsigned char mode); -void seqStop(unsigned long seqId); +void sndSeqVolume(u8 volume, u16 time, u32 seqId, u8 mode); +u32 sndSeqPlayEx(u16 sgid, u16 sid, void* arrfile, SND_PLAYPARA* para, u8 studio); +void seqStop(u32 seqId); u16 seqGetMIDIPriority(u8 set, u8 channel); -void seqCrossFade(SND_CROSSFADE* ci, unsigned long* new_seqId, unsigned char irq_call); +void seqCrossFade(SND_CROSSFADE* ci, u32* new_seqId, bool8 irq_call); +u32 seqPlaySong(u16 sgid, u16 sid, void* arrfile, SND_PLAYPARA* para, u8 irq_call, u8 studio); #ifdef __cplusplus } diff --git a/include/musyx/txwin.h b/include/musyx/txwin.h index 746d9fc3..34b529ac 100644 --- a/include/musyx/txwin.h +++ b/include/musyx/txwin.h @@ -41,7 +41,7 @@ void winSetFontSize(u16 size); sWIN* winOpenLogWindow(s32 x1, s32 y1, s32 x2, s32 y2, char* caption, u16 num_lines, u32 flags); sWIN* winOpenWindow(s32 x1, s32 y1, s32 x2, s32 y2, char* caption, void* func, u32 flags); -WXOpenWindow(); +// WXOpenWindow(); #ifdef __cpluplus } diff --git a/src/musyx/runtime/hw_dolphin.c b/src/musyx/runtime/hw_dolphin.c index 487771ef..2f19071b 100644 --- a/src/musyx/runtime/hw_dolphin.c +++ b/src/musyx/runtime/hw_dolphin.c @@ -134,7 +134,7 @@ u32 salExitDsp() { void salStartDsp(u16* cmdList) { salDspIsDone = FALSE; PPCSync(); - MUSY_ASSERT(((u32)cmdList & 0x1F)==0); + MUSY_ASSERT(((u32)cmdList & 0x1F) == 0); DSPSendMailToDSP(dspCmdFirstSize | 0xbabe0000); while (DSPCheckMailToDSP()) diff --git a/src/musyx/runtime/seq.c b/src/musyx/runtime/seq.c index 3a553bad..49579d0e 100644 --- a/src/musyx/runtime/seq.c +++ b/src/musyx/runtime/seq.c @@ -222,7 +222,7 @@ static void HandleKeyOffNotes() { n = cseq->noteKeyOff; while (n != NULL) { nn = n->next; - if (n->id != -1 && sndFXCheck(n->id) == -1) { + if (n->id != SND_ID_ERROR && sndFXCheck(n->id) == SND_ID_ERROR) { seqFreeKeyOffNote(n); } @@ -238,22 +238,43 @@ static void InitPublicIds() { seq_next_id = 0; } static u32 GetPublicId(u32 seqId) { u32 pub_id; // r30 SEQ_INSTANCE* si; // r31 - si = &seqInstance[seqId]; + + do { + pub_id = seq_next_id; + seq_next_id = pub_id + 1; + seq_next_id &= ~SND_SEQ_CROSSFADE_ID; + + for (si = seqActiveRoot; si != NULL; si = si->next) { + if (si->publicId == pub_id) { + pub_id = SND_SEQ_ERROR_ID; + break; + } + } + for (si = seqPausedRoot; si != NULL; si = si->next) { + if (si->publicId == pub_id) { + pub_id = SND_SEQ_ERROR_ID; + break; + } + } + } while (pub_id == SND_SEQ_ERROR_ID); + + seqInstance[seqId].publicId = pub_id; + return pub_id; } u32 seqGetPrivateId(u32 seqId) { SEQ_INSTANCE* si; // r31 for (si = seqActiveRoot; si != NULL; si = si->next) { - if (si->publicId == (seqId & 0x7fffffff)) { - return seqId & 0x80000000 | si->index; + if (si->publicId == (seqId & ~SND_SEQ_CROSSFADE_ID)) { + return si->index | seqId & SND_SEQ_CROSSFADE_ID; } } for (si = seqPausedRoot; si != NULL; si = si->next) { - if (si->publicId == (seqId & 0x7fffffff)) { - return seqId & 0x80000000 | si->index; + if (si->publicId == (seqId & ~SND_SEQ_CROSSFADE_ID)) { + return si->index | seqId & SND_SEQ_CROSSFADE_ID; } } - return 0xffffffff; + return SND_ID_ERROR; } static void DoPrgChange(SEQ_INSTANCE* seq, u8 prg, u8 midi) { @@ -292,6 +313,9 @@ static void BuildTransTab(u8* tab, PAGE* page) { } } +static void StartPause(SEQ_INSTANCE* si); +static void InitTrackEvents(); + u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para, u8 studio, u16 sgid) { ARR* arr; // r27 @@ -303,15 +327,15 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL u32 bpm; // r25 if ((nseq = seqFreeRoot) == NULL) { - return -1; - }; - if ((seqFreeRoot = seqFreeRoot->next) != NULL) { + return SND_ID_ERROR; + } + if ((seqFreeRoot = nseq->next) != NULL) { seqFreeRoot->prev = NULL; } - if ((nseq->next = seqActiveRoot) != NULL) { seqActiveRoot->prev = nseq; } + nseq->prev = NULL; seqActiveRoot = nseq; nseq->state = 1; @@ -340,7 +364,7 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL nseq->section[i].speed = 256; } - synthVolume(127, 0, nseq->defVGroup, 0, -1); + synthVolume(SND_PAUSEVOL_NORMAL, 0, nseq->defVGroup, 0, SND_ID_ERROR); } else { if (para->flags & SND_PLAYPARA_TRACKMUTE) { nseq->trackMute[0] = para->trackMute[0]; @@ -368,17 +392,19 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL } if (para->flags & SND_PLAYPARA_VOLUME) { - synthVolume(para->volume.target, para->volume.time, nseq->defVGroup, 0, -1); + synthVolume(para->volume.target, para->volume.time, nseq->defVGroup, SND_SEQVOL_CONTINUE, + SND_SEQ_ERROR_ID); for (i = 0; i < para->numFaded; ++i) { - synthVolume(para->volume.target, para->volume.time, para->faded[i], 0, -1); + synthVolume(para->volume.target, para->volume.time, para->faded[i], SND_SEQVOL_CONTINUE, + SND_SEQ_ERROR_ID); } } } arr = (ARR*)song; if (arr->info & 0x80000000) { - nseq->trackSectionTab = (u8*)(arr->tsTab + (u32)arr); + nseq->trackSectionTab = ARR_GET(arr, arr->tsTab); } else { nseq->trackSectionTab = NULL; } @@ -394,7 +420,7 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL synthSetBpm(bpm >> 10, seqId & 0xFF, i & 0xFF); if (arr->mTrack != NULL) { - nseq->section[i].mTrack.base = (MTRACK_DATA*)(arr->mTrack + (u32)arr); + nseq->section[i].mTrack.base = ARR_GET(arr, arr->mTrack); nseq->section[i].mTrack.addr = nseq->section[i].mTrack.base; } else { nseq->section[i].mTrack.base = NULL; @@ -404,14 +430,61 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL nseq->section[i].loopCnt = 0; } - tracktab = &arr->tTab; - + tracktab = ARR_GET(arr, arr->tTab); for (i = 0; i < 64; ++i) { - synthTrackVolume[i] = 127; + synthTrackVolume[i] = SND_PAUSEVOL_NORMAL; nseq->pattern[i].addr = NULL; - // TODO: Finish + if (tracktab[i] != 0) { + nseq->track[i].addr = nseq->track[i].base = ARR_GET(arr, tracktab[i]); + } else { + nseq->track[i].addr = nseq->track[i].base = NULL; + } } - return -1; + + nseq->noteUsed[0] = NULL; + nseq->noteUsed[1] = NULL; + nseq->noteKeyOff = NULL; + + for (i = 0; i < 16; ++i) { + inpResetMidiCtrl(i, seqId, 1); + } + for (i = 0; i < 16; ++i) { + nseq->prgState[i].macId = 0xffff; + } + for (i = 0; i < 16; ++i) { + inpResetChannelDefaults(i, seqId); + } + if (midiSetup != NULL) { + for (i = 0; i < 16; ++i) { + DoPrgChange(nseq, midiSetup->channel[i].program, i); + inpSetMidiCtrl(SND_MIDICTRL_VOLUME, i, seqId, midiSetup->channel[i].volume); + inpSetMidiCtrl(SND_MIDICTRL_PANNING, i, seqId, midiSetup->channel[i].panning); + inpSetMidiCtrl(SND_MIDICTRL_REVERB, i, seqId, midiSetup->channel[i].reverb); + inpSetMidiCtrl(SND_MIDICTRL_CHORUS, i, seqId, midiSetup->channel[i].chorus); + } + } + for (i = 0; i < 16; ++i) { + seqMIDIPriority[seqId][i] = 0xffff; + } + for (i = 0; i < 16; ++i) { + nseq->section[i].time[0].high = 0; + nseq->section[i].time[0].low = 0; + nseq->section[i].time[1].high = 0; + nseq->section[i].time[1].low = 0; + nseq->section[i].timeIndex = 0; + } + nseq->keyOffCheck = 0; + + if (para != NULL && (para->flags & SND_PLAYPARA_PAUSE) != 0) { + StartPause(nseq); + } + + oldCSeq = cseq; + cseq = nseq; + InitTrackEvents(); + cseq = oldCSeq; + seqId = GetPublicId(seqId); + return seqId; } static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) { @@ -446,7 +519,7 @@ static void HandleMasterTrack(u8 secIndex) { } } -static void RewindMTrack(unsigned char secIndex, unsigned long deltaTime) { +static void RewindMTrack(u8 secIndex, u32 deltaTime) { if (cseq->section[secIndex].mTrack.base == NULL) { return; } @@ -479,11 +552,11 @@ void seqPause(u32 seqId) { SEQ_INSTANCE* si; // r31 seqId = seqGetPrivateId(seqId); - if (seqId == -1) { + if (seqId == SND_SEQ_ERROR_ID) { return; } - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { si = &seqInstance[seqId]; if (si->state == 1) { StartPause(si); @@ -491,22 +564,21 @@ void seqPause(u32 seqId) { ResetNotes(si); } } else { - si = &seqInstance[seqId & 0x7fffffff]; + si = &seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID]; if (si->state != 0) { si->syncCrossInfo.flags |= 8; } } } -void seqStop(unsigned long seqId) { +void seqStop(u32 seqId) { SEQ_INSTANCE* si; // r31 - ; - if ((seqId = seqGetPrivateId(seqId)) == -1) { + if ((seqId = seqGetPrivateId(seqId)) == SND_SEQ_ERROR_ID) { return; } - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { si = &seqInstance[seqId]; switch (si->state) { case 1: @@ -539,7 +611,7 @@ void seqStop(unsigned long seqId) { si->prev = NULL; seqFreeRoot = si; } else { - si = &seqInstance[seqId & 0x7fffffff]; + si = &seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID]; if (si->state != 0) { si->syncSeqIdPtr = NULL; } @@ -557,7 +629,7 @@ void seqKillAllInstances() { } } -void seqKillInstancesByGroupID(unsigned short sgid) { +void seqKillInstancesByGroupID(u16 sgid) { SEQ_INSTANCE* si; // r31 for (si = seqActiveRoot; si != NULL; si = si->next) { @@ -572,19 +644,20 @@ void seqKillInstancesByGroupID(unsigned short sgid) { } } -void seqSpeed(unsigned long seqId, unsigned short speed) { +void seqSpeed(u32 seqId, u16 speed) { u32 i; // r30 seqId = seqGetPrivateId(seqId); - MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid."); +#line 1018 + MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid."); - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { for (i = 0; i < 16; ++i) { seqInstance[seqId].section[i].speed = speed; } } else { - seqId &= 0x7FFFFFFF; - seqInstance[seqId].syncCrossInfo.flags |= 0x20; + seqId &= ~SND_SEQ_CROSSFADE_ID; + seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_SPEED; seqInstance[seqId].syncCrossInfo.speed2 = speed; } } @@ -593,9 +666,10 @@ void seqContinue(u32 seqId) { struct SEQ_INSTANCE* si; // r31 seqId = seqGetPrivateId(seqId); - MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid."); +#line 1043 + MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid."); - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { si = &seqInstance[seqId]; if (si->state == 2) { @@ -618,130 +692,370 @@ void seqContinue(u32 seqId) { si->state = 1; } } else { - seqInstance[seqId & 0x7FFFFFFF].syncCrossInfo.flags &= ~0x8; + seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID].syncCrossInfo.flags &= ~SND_CROSSFADE_PAUSENEW; } } -void seqMute(unsigned long seqId, unsigned long mask1, unsigned long mask2) { +void seqMute(u32 seqId, u32 mask1, u32 mask2) { seqId = seqGetPrivateId(seqId); - if (seqId == 0xffffffff) { + if (seqId == SND_SEQ_ERROR_ID) { return; } - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { seqInstance[seqId].trackMute[0] = mask1; seqInstance[seqId].trackMute[1] = mask2; } else { - seqId &= 0x7fffffff; - seqInstance[seqId].syncCrossInfo.flags |= 0x10; + seqId &= ~SND_SEQ_CROSSFADE_ID; + seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_TRACKMUTE; seqInstance[seqId].syncCrossInfo.trackMute2[0] = mask1; seqInstance[seqId].syncCrossInfo.trackMute2[1] = mask2; } } -void seqVolume(unsigned char volume, unsigned short time, unsigned long seqId, unsigned char mode) { - unsigned long i; // r29 - unsigned long pub_id; // r27 - // TODO - // pub_id = seqId; - seqId = seqGetPrivateId(seqId); +void seqVolume(u8 volume, u16 time, u32 seqId, u8 mode) { + u32 i; // r29 + u32 pub_id; // r27 - if (seqId == -1) { + pub_id = seqId; + seqId = seqGetPrivateId(seqId); + if (seqId == SND_SEQ_ERROR_ID) { return; } - if (!(seqId & 0x80000000)) { + if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) { synthVolume(volume, time, seqInstance[seqId].defVGroup, mode, pub_id); for (i = 0; i < 64; ++i) { if (seqInstance[seqId].trackVolGroup[i] != seqInstance[seqId].defVGroup) { - synthVolume(volume, time, seqInstance[seqId].trackVolGroup[i], 0, -1); + synthVolume(volume, time, seqInstance[seqId].trackVolGroup[i], SND_SEQVOL_CONTINUE, + SND_SEQ_ERROR_ID); } } } else { - seqId &= 0x7fffffff; - switch (mode & 0xf) { - case 0: + seqId &= ~SND_SEQ_CROSSFADE_ID; + switch (mode & SND_SEQVOL_MODEMASK) { + case SND_SEQVOL_CONTINUE: seqInstance[seqId].syncCrossInfo.vol2 = volume; break; - case 1: + case SND_SEQVOL_STOP: seqInstance[seqId].syncSeqIdPtr = NULL; break; - case 2: - seqInstance[seqId].syncCrossInfo.flags |= 8; + case SND_SEQVOL_PAUSE: + seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_PAUSENEW; seqInstance[seqId].syncCrossInfo.vol2 = volume; break; - case 3: - seqInstance[seqId].syncCrossInfo.flags |= 0x80; + case SND_SEQVOL_MUTE: + seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_MUTENEW; seqInstance[seqId].syncCrossInfo.vol2 = volume; break; default: +#line 1153 MUSY_FATAL("Illegal sequencere fade mode detected."); break; } } } -// TODO: very incomplete -void seqCrossFade(SND_CROSSFADE* ci, unsigned long* new_seqId, unsigned char irq_call) { - SND_PLAYPARA pp; // r1+0x14 - unsigned long seqId; // r29 - unsigned short time; // r27 - seqId = seqGetPrivateId(ci->seqId1); +void seqCrossFade(SND_CROSSFADE* ci, u32* new_seqId, bool8 irq_call) { + SND_PLAYPARA pp; // r1+0x14 + u32 seqId; // r29 + u16 time; // r27 - if ((ci->flags & 0x4) != 0) { + seqId = seqGetPrivateId(ci->seqId1); +#line 1170 + MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid."); + + if ((ci->flags & SND_CROSSFADE_SYNC) != 0) { seqInstance[seqId].syncCrossInfo = *ci; seqInstance[seqId].syncActive = TRUE; seqInstance[seqId].syncSeqIdPtr = new_seqId; - seqInstance[seqId].syncCrossInfo.flags &= ~0x4; - *new_seqId = ci->seqId1 | 0x80000000; + seqInstance[seqId].syncCrossInfo.flags &= ~SND_CROSSFADE_SYNC; + *new_seqId = ci->seqId1 | SND_SEQ_CROSSFADE_ID; return; } - if ((irq_call & 0xff) != 0) { - time = 5; - if (ci->time1 > 4) { - time = ci->time1; - } - - if ((ci->flags & 0x1) != 0) { - seqVolume(0, time, seqId, 2); - } else if ((ci->flags & 0x40) != 0) { - seqVolume(0, time, seqId, 3); + if (irq_call) { + time = ci->time1 < 5 ? 5 : ci->time1; + if ((ci->flags & SND_CROSSFADE_PAUSE) != 0) { + seqVolume(0, time, ci->seqId1, SND_SEQVOL_PAUSE); + } else if ((ci->flags & SND_CROSSFADE_MUTE) != 0) { + seqVolume(0, time, ci->seqId1, SND_SEQVOL_MUTE); } else { - seqVolume(0, time, seqId, 1); + seqVolume(0, time, ci->seqId1, SND_SEQVOL_STOP); } + } else { + if ((ci->flags & SND_CROSSFADE_PAUSE) != 0) { + sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_PAUSE); + } else if ((ci->flags & SND_CROSSFADE_MUTE) != 0) { + sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_MUTE); + } else { + sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_STOP); + } + } - if (new_seqId != NULL) { - if ((ci->flags & 0x2) != 0) { - seqId = seqGetPrivateId(ci->seqId2); - if (seqId != 0xffffffff) { - if ((irq_call & 0xff) != 0) { - seqStop(ci->seqId2); - } else { - sndSeqContinue(ci->seqId2); - sndSeqVolume(ci->vol2, ci->time2, ci->seqId2, 0); - if ((ci->flags & 0x10) != 0) { - sndSeqMute(ci->seqId2, ci->trackMute2[0], ci->trackMute2[1]); - } - if ((ci->flags & 0x20) != 0) { - sndSeqSpeed(ci->seqId2, ci->speed2); - } - } - *new_seqId = ci->seqId2; - } else { - *new_seqId = 0xffffffff; + if (new_seqId == NULL) { + return; + } + + if ((ci->flags & SND_CROSSFADE_CONTINUE) != 0) { + if (seqGetPrivateId(ci->seqId2) != SND_SEQ_ERROR_ID) { + if (irq_call) { + seqContinue(ci->seqId2); + seqVolume(ci->vol2, ci->time2, ci->seqId2, SND_SEQVOL_CONTINUE); + if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) { + seqMute(ci->seqId2, ci->trackMute2[0], ci->trackMute2[1]); + } + if ((ci->flags & SND_CROSSFADE_SPEED) != 0) { + seqSpeed(ci->seqId2, ci->speed2); + } + } else { + sndSeqContinue(ci->seqId2); + sndSeqVolume(ci->vol2, ci->time2, ci->seqId2, SND_SEQVOL_CONTINUE); + if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) { + sndSeqMute(ci->seqId2, ci->trackMute2[0], ci->trackMute2[1]); + } + if ((ci->flags & SND_CROSSFADE_SPEED) != 0) { + sndSeqSpeed(ci->seqId2, ci->speed2); } } + *new_seqId = ci->seqId2; + } else { + *new_seqId = SND_SEQ_ERROR_ID; } - - return; - } - - if ((ci->flags & 0x1) != 0) { - sndSeqVolume(0, ci->time1, seqId, 2); - } else if ((ci->flags & 0x40) != 0) { - sndSeqVolume(0, ci->time1, seqId, 3); } else { - sndSeqVolume(0, ci->time1, seqId, 1); + pp.flags = SND_PLAYPARA_VOLUME; + if ((ci->flags & SND_CROSSFADE_PAUSENEW) != 0) { + pp.flags |= SND_PLAYPARA_PAUSE; + } + if ((ci->flags & SND_CROSSFADE_SPEED) != 0) { + pp.flags |= SND_PLAYPARA_SPEED; + pp.speed = ci->speed2; + } + if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) { + pp.flags |= SND_PLAYPARA_TRACKMUTE; + pp.trackMute[0] = ci->trackMute2[0]; + pp.trackMute[1] = ci->trackMute2[1]; + } + pp.volume.time = ci->time2; + pp.volume.target = ci->vol2; + pp.numFaded = 0; + if (irq_call != 0) { + if ((*new_seqId = seqPlaySong(ci->gid2, ci->sid2, ci->arr2, &pp, TRUE, ci->studio2)) != + SND_SEQ_ERROR_ID && + (ci->flags & SND_CROSSFADE_MUTENEW) != 0) { + seqMute(*new_seqId, 0, 0); + } + } else { + if ((*new_seqId = sndSeqPlayEx(ci->gid2, ci->sid2, ci->arr2, &pp, ci->studio2)) != + SND_SEQ_ERROR_ID && + (ci->flags & SND_CROSSFADE_MUTENEW) != 0) { + sndSeqMute(*new_seqId, 0, 0); + } + } } } + +static u8* GetStreamValue(u8* stream, u16* deltaTime, s16* deltaData) { + u8 b1; // r31 + u8 b2; // r29 + s16 v; // r30 + + b1 = stream[0]; + b2 = stream[1]; + if (b1 == 0x80 && b2 == 0) { + return NULL; + } + + if ((b1 & 0x80) != 0) { + *deltaTime = ((b1 & 0x7f) << 8) | b2; + stream += 2; + } else { + *deltaTime = b1; + stream += 1; + } + + b1 = stream[0]; + b2 = stream[1]; + if ((b1 & 0x80) != 0) { + v = ((b1 & 0x7f) << 8) | b2; + v <<= 1; + v >>= 1; + *deltaData = v; + stream += 2; + } else { + v = b1; + v <<= 9; + v >>= 9; + *deltaData = v; + stream += 1; + } + + return stream; +} + +static void InitStream(SEQ_STREAM* stream, u32 streamDataOffset) { + u16 delta; // r1+0x10 + if (streamDataOffset != 0) { + if ((stream->nextAddr = GetStreamValue(ARR_GET(cseq->arrbase, streamDataOffset), &delta, + &stream->nextDelta)) != NULL) { + stream->nextTime = delta; + } else { + stream->nextTime = 0x7fffffff; + } + } else { + stream->nextTime = 0x7fffffff; + } +} + +static u16 HandleStream(SEQ_STREAM* stream) { + u16 delta; // r1+0xC + stream->value += stream->nextDelta; + if (stream->nextAddr != NULL) { + if ((stream->nextAddr = GetStreamValue(stream->nextAddr, &delta, &stream->nextDelta)) != NULL) { + stream->nextTime += delta; + } else { + stream->nextTime = 0x7fffffff; + } + } else { + stream->nextTime = 0x7fffffff; + } + return stream->value; +} + +static SEQ_EVENT* GenerateNextTrackEvent(u8 trackId) { + TRACK* track; // r29 + CPAT* pattern; // r31 + SEQ_EVENT* ev; // r30 + u32 patternTime; // r28 + u32 pitchTime; // r27 + u32 modTime; // r26 + + track = &cseq->track[trackId]; + pattern = &cseq->pattern[trackId]; + + if (track->addr != NULL) { + ev = &cseq->event[trackId]; + ev->trackId = trackId; + ev->info.pattern.base = pattern; + + if (pattern->addr == NULL) { + null_pattern_addr: + if (track->addr->pattern == 0xffff) { + track->addr = NULL; + return NULL; + } else if (track->addr->pattern == 0xfffe) { + if (cseq->trackSectionTab == NULL) { + if (cseq->section[0].loopDisable) { + track->addr = NULL; + return NULL; + } + } else if (cseq->section[cseq->trackSectionTab[trackId]].loopDisable) { + track->addr = NULL; + return NULL; + } + + ev->type = 3; + ev->time = track->addr->time; + track->addr = &track->base[*((u16*)&track->addr->transpose)]; + return ev; + } + + ev->type = 4; + ev->time = track->addr->time; + ev->info.trackAddr = track->addr; + ++track->addr; + return ev; + } + + pitchTime = pattern->pitchBend.nextTime; + modTime = pattern->modulation.nextTime; + + loop: + patternTime = pattern->addr->time + pattern->lTime; + if (patternTime >= pitchTime) { + goto use_pitch_time; + } + if (patternTime >= modTime) { + goto use_mod_time; + } + if (pattern->addr->key == 0xff && pattern->addr->velocity == 0xff) { + pattern->addr = NULL; + goto null_pattern_addr; + } + + ev->info.trackAddr = (TENTRY*)pattern->addr; + pattern->lTime = patternTime; + + if ((pattern->addr->key & 0x80) != 0) { + pattern->addr = (NOTE_DATA*)((u8*)pattern->addr + 4); + goto use_pattern_time; + } + if ((pattern->addr->key | pattern->addr->velocity) == 0) { + pattern->addr = (NOTE_DATA*)((u8*)pattern->addr + 4); + goto loop; + } + ++pattern->addr; + + use_pattern_time: + ev->type = 0; + ev->time = patternTime + pattern->baseTime; + goto end; + + use_pitch_time: + if (pitchTime < modTime) { + ev->time = pitchTime + pattern->baseTime; + ev->type = 2; + } else { + use_mod_time: + ev->time = modTime + pattern->baseTime; + ev->type = 1; + } + + end: + return ev; + } + + return NULL; +} + +static void InsertGlobalEvent(SEQ_SECTION* section, SEQ_EVENT* event) { + SEQ_EVENT* el; // r31 + SEQ_EVENT* last_el; // r30 + + last_el = NULL; + el = section->globalEventRoot; + for (; el != NULL; last_el = el, el = el->next) { + if (el->time > event->time) { + event->next = el; + event->prev = last_el; + if (last_el != NULL) { + last_el->next = event; + } else { + section->globalEventRoot = event; + } + el->prev = event; + return; + } + } + + event->prev = last_el; + if (last_el != NULL) { + last_el->next = event; + } else { + section->globalEventRoot = event; + } + event->next = NULL; +} + +static u32 GetNextEventTime(SEQ_SECTION* section) { + return section->globalEventRoot == NULL ? 0 : section->globalEventRoot->time; +} + +static SEQ_EVENT* GetGlobalEvent(SEQ_SECTION* section) { + SEQ_EVENT* ev; // r31 + ev = section->globalEventRoot; + if (ev != NULL && ((section->globalEventRoot = ev->next) != NULL)) { + section->globalEventRoot->prev = NULL; + } + return ev; +}