From a989dbd4996fec8caaa227e9743b92abaaf0bd27 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 18 Feb 2023 20:27:24 -0800 Subject: [PATCH] More MusyX structs from DWARF information --- .gitignore | 1 + include/musyx/musyx.h | 1 + include/musyx/musyx_priv.h | 550 +++++++++++++++++++++++++++++++------ include/musyx/synth.h | 25 -- src/musyx/hardware.c | 99 ++++--- src/musyx/hw_dolphin.c | 2 +- src/musyx/snd_init.c | 24 +- src/musyx/snd_midictrl.c | 67 ++++- src/musyx/snd_synthapi.c | 110 +------- src/musyx/synth_ac.c | 2 +- 10 files changed, 601 insertions(+), 280 deletions(-) diff --git a/.gitignore b/.gitignore index 4fa9ca45..a29199ec 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ versions/ build.ninja .ninja_deps .ninja_log +dwarfD/ diff --git a/include/musyx/musyx.h b/include/musyx/musyx.h index bb0d1526..9e1d4b3a 100644 --- a/include/musyx/musyx.h +++ b/include/musyx/musyx.h @@ -11,6 +11,7 @@ typedef signed short s16; typedef unsigned short u16; typedef signed long s32; typedef unsigned long u32; +typedef unsigned long long u64; typedef float f32; typedef double f64; diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index 7b5dbab4..57cda5c3 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -7,83 +7,476 @@ extern "C" { #endif -typedef struct _SynthInfo { - u32 freq; - u32 _4; - u8 unk[0x208]; - u8 voices; - u8 music; - u8 sfx; - u8 studios; +typedef struct SND_STUDIO_INPUT { + // total size: 0x4 + unsigned char vol; // offset 0x0, size 0x1 + unsigned char volA; // offset 0x1, size 0x1 + unsigned char volB; // offset 0x2, size 0x1 + unsigned char srcStudio; // offset 0x3, size 0x1 +} SND_STUDIO_INPUT; + +typedef struct synthInfo { + u32 mixFrq; + u32 numSamples; + SND_PLAYBACKINFO pbInfo; + u8 voiceNum; + u8 maxMusic; + u8 maxSFX; + u8 studioNum; } SynthInfo; -typedef struct DSPVoice { - char data1[0x18]; - u32 _18; - u32 priority; - u32 _20; - u32 flags[5]; - char data2[0x70 - 0x38]; - u16 sampleId; - u16 _72; - u32 _74; - u32 _78; - u32 _7c; - u32 _80; - u32 _84; - u32 _88; - u32 _8c; - u32 sampleType; - u32 _94; - u32 _98; - u32 _9c; - u32 _a0; - u8 _a4; - u8 _a5; - u8 _a6; - u8 _a7; - u32 _a8; - u32 _ac; - u32 _b0; - u32 _b4; - u32 _b8; - u32 _bc; - u16 _c0; - u16 _c2; - u32 _c4; - u32 _c8; - u32 _cc; - u32 _d0; - u32 _d4; - u32 _d8; - u32 _dc; - u32 _e0; - u8 _e4; - u8 _e5; - u8 _e6; - u8 _e7; - u32 _e8; - u8 status; - u8 _ed; - u8 breakSet; - u8 _ef; - u32 itdFlags; -} DSPVoice; +typedef struct ADSR_VARS { + u8 mode; + u8 state; + u32 cnt; + s32 currentVolume; + s32 currentIndex; + s32 currentDelta; -typedef struct SND_VS { - u8 _0; - u8 _1; - u8 _2; - u8 _3; - u8 unk1[0x908 - 0x4]; - u8 _908[64]; - u16 _948; - u32 _94c; -} SND_VS; + union data { + struct _dls { + u32 aTime; + u32 dTime; + u16 sLevel; + u32 rTime; + u16 cutOff; + u8 aMode; + } dls; -extern SND_VS vs; + struct _linear { + u32 aTime; + u32 dTime; + u16 sLevel; + u32 rTime; + } linear; + } data; +} ADSR_VARS; -extern DSPVoice* dspVoice; +typedef struct _PBMIX { + // total size: 0x24 + unsigned short vL; // offset 0x0, size 0x2 + unsigned short vDeltaL; // offset 0x2, size 0x2 + unsigned short vR; // offset 0x4, size 0x2 + unsigned short vDeltaR; // offset 0x6, size 0x2 + unsigned short vAuxAL; // offset 0x8, size 0x2 + unsigned short vDeltaAuxAL; // offset 0xA, size 0x2 + unsigned short vAuxAR; // offset 0xC, size 0x2 + unsigned short vDeltaAuxAR; // offset 0xE, size 0x2 + unsigned short vAuxBL; // offset 0x10, size 0x2 + unsigned short vDeltaAuxBL; // offset 0x12, size 0x2 + unsigned short vAuxBR; // offset 0x14, size 0x2 + unsigned short vDeltaAuxBR; // offset 0x16, size 0x2 + unsigned short vAuxBS; // offset 0x18, size 0x2 + unsigned short vDeltaAuxBS; // offset 0x1A, size 0x2 + unsigned short vS; // offset 0x1C, size 0x2 + unsigned short vDeltaS; // offset 0x1E, size 0x2 + unsigned short vAuxAS; // offset 0x20, size 0x2 + unsigned short vDeltaAuxAS; // offset 0x22, size 0x2 +} _PBMIX; + +typedef struct _PBITD { + // total size: 0xE + unsigned short flag; // offset 0x0, size 0x2 + unsigned short bufferHi; // offset 0x2, size 0x2 + unsigned short bufferLo; // offset 0x4, size 0x2 + unsigned short shiftL; // offset 0x6, size 0x2 + unsigned short shiftR; // offset 0x8, size 0x2 + unsigned short targetShiftL; // offset 0xA, size 0x2 + unsigned short targetShiftR; // offset 0xC, size 0x2 +} _PBITD; + +typedef struct _PBUPDATE { + // total size: 0xE + unsigned short updNum[5]; // offset 0x0, size 0xA + unsigned short dataHi; // offset 0xA, size 0x2 + unsigned short dataLo; // offset 0xC, size 0x2 +} _PBUPDATE; + +typedef struct _PBDPOP { + // total size: 0x12 + unsigned short aL; // offset 0x0, size 0x2 + unsigned short aAuxAL; // offset 0x2, size 0x2 + unsigned short aAuxBL; // offset 0x4, size 0x2 + unsigned short aR; // offset 0x6, size 0x2 + unsigned short aAuxAR; // offset 0x8, size 0x2 + unsigned short aAuxBR; // offset 0xA, size 0x2 + unsigned short aS; // offset 0xC, size 0x2 + unsigned short aAuxAS; // offset 0xE, size 0x2 + unsigned short aAuxBS; // offset 0x10, size 0x2 +} _PBDPOP; + +struct _PBVE { + // total size: 0x4 + unsigned short currentVolume; // offset 0x0, size 0x2 + unsigned short currentDelta; // offset 0x2, size 0x2 +} _PBVE; + +typedef struct _PBFIR { + // total size: 0x6 + unsigned short numCoefs; // offset 0x0, size 0x2 + unsigned short coefsHi; // offset 0x2, size 0x2 + unsigned short coefsLo; // offset 0x4, size 0x2 +} _PBFIR; + +typedef struct _PBADDR { + // total size: 0x10 + unsigned short loopFlag; // offset 0x0, size 0x2 + unsigned short format; // offset 0x2, size 0x2 + unsigned short loopAddressHi; // offset 0x4, size 0x2 + unsigned short loopAddressLo; // offset 0x6, size 0x2 + unsigned short endAddressHi; // offset 0x8, size 0x2 + unsigned short endAddressLo; // offset 0xA, size 0x2 + unsigned short currentAddressHi; // offset 0xC, size 0x2 + unsigned short currentAddressLo; // offset 0xE, size 0x2 +} _PBADDR; + +typedef struct _PBADPCM { + // total size: 0x28 + unsigned short a[8][2]; // offset 0x0, size 0x20 + unsigned short gain; // offset 0x20, size 0x2 + unsigned short pred_scale; // offset 0x22, size 0x2 + unsigned short yn1; // offset 0x24, size 0x2 + unsigned short yn2; // offset 0x26, size 0x2 +} _PDADPCM; + +struct _PBSRC { + // total size: 0xE + unsigned short ratioHi; // offset 0x0, size 0x2 + unsigned short ratioLo; // offset 0x2, size 0x2 + unsigned short currentAddressFrac; // offset 0x4, size 0x2 + unsigned short last_samples[4]; // offset 0x6, size 0x8 +} _PBSRC; + +typedef struct _PBADPCMLOOP { + // total size: 0x6 + unsigned short loop_pred_scale; // offset 0x0, size 0x2 + unsigned short loop_yn1; // offset 0x2, size 0x2 + unsigned short loop_yn2; // offset 0x4, size 0x2 +} _PBADPCMLOOP; + +typedef struct _PB { + // total size: 0xBC + unsigned short nextHi; // offset 0x0, size 0x2 + unsigned short nextLo; // offset 0x2, size 0x2 + unsigned short currHi; // offset 0x4, size 0x2 + unsigned short currLo; // offset 0x6, size 0x2 + unsigned short srcSelect; // offset 0x8, size 0x2 + unsigned short coefSelect; // offset 0xA, size 0x2 + unsigned short mixerCtrl; // offset 0xC, size 0x2 + unsigned short state; // offset 0xE, size 0x2 + unsigned short 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 + unsigned short streamLoopCnt; // offset 0xBA, size 0x2 +} _PB; + +typedef struct SAMPLE_INFO { + // total size: 0x20 + u32 info; // offset 0x0, size 0x4 + void* addr; // offset 0x4, size 0x4 + void* extraData; // offset 0x8, size 0x4 + u32 offset; // offset 0xC, size 0x4 + u32 length; // offset 0x10, size 0x4 + u32 loop; // offset 0x14, size 0x4 + u32 loopLength; // offset 0x18, size 0x4 + u8 compType; // offset 0x1C, size 0x1 +} SAMPLE_INFO; + +typedef struct VSampleInfo { + // total size: 0xC + void* loopBufferAddr; // offset 0x0, size 0x4 + u32 loopBufferLength; // offset 0x4, size 0x4 + u8 inLoopBuffer; // offset 0x8, size 0x1 +} VSampleInfo; + +typedef struct DSPvoice { + struct _PB* pb; + void* patchData; + void* itdBuffer; + struct DSPvoice* next; + struct DSPvoice* prev; + struct DSPvoice* nextAlien; + u32 mesgCallBackUserValue; + u32 prio; + u32 currentAddr; + u32 changed[5]; + u32 pitch[5]; + u16 volL; + u16 volR; + u16 volS; + u16 volLa; + u16 volRa; + u16 volSa; + u16 volLb; + u16 volRb; + u16 volSb; + u16 lastVolL; + u16 lastVolR; + u16 lastVolS; + u16 lastVolLa; + u16 lastVolRa; + u16 lastVolSa; + u16 lastVolLb; + u16 lastVolRb; + u16 lastVolSb; + u16 smp_id; + SAMPLE_INFO smp_info; + VSampleInfo vSampleInfo; + u8 streamLoopPS; + ADSR_VARS adsr; + u16 srcTypeSelect; + u16 srcCoefSelect; + u16 itdShiftL; + u16 itdShiftR; + u8 singleOffset; + struct { + u32 posHi; + u32 posLo; + u32 pitch; + } playInfo; + + struct { + u8 pitch; + u8 vol; + u8 volA; + u8 volB; + } lastUpdate; + + u32 virtualSampleID; + u8 state; + u8 postBreak; + u8 startupBreak; + u8 studio; + u32 flags; +} DSPvoice; + +typedef struct VID_LIST { + struct VID_LIST* next; + struct VID_LIST* prev; + u32 vid; + u32 root; +} VID_LIST; + +typedef enum { + MAC_STATE_RUNNABLE = 0, + MAC_STATE_YIELDED, + MAC_STATE_STOPPED, +} MAC_STATE; + +typedef struct MSTEP { + u32 para[2]; +} MSTEP; + +typedef struct CALLSTACK { + struct MSTEP* addr; + struct MSTEP* curAddr; +} CALLSTACK; + +typedef struct SYNTH_QUEUE { + struct SYNTH_QUEUE* next; + struct SYNTH_QUEUE* prev; + u8 voice; + u8 jobTabIndex; +} SYNTH_QUEUE; + +typedef struct SYNTH_LFO { + u32 time; + u32 period; + s16 value; + s16 lastValue; +} SYNTH_LFO; + +typedef struct CTRL_SOURCE { + u8 midiCtrl; + u8 combine; + long scale; +} CTRL_SOURCE; + +typedef struct CTRL_DEST { + CTRL_SOURCE source[4]; + u16 oldValue; + u8 numSource; +} CTRL_DEST; + +struct SND_VIRTUALSAMPLE_INFO { + // total size: 0x14 + unsigned short smpID; // offset 0x0, size 0x2 + unsigned short instID; // offset 0x2, size 0x2 + union vsData { + struct vsUpdate { + // total size: 0x10 + unsigned long off1; // offset 0x0, size 0x4 + unsigned long len1; // offset 0x4, size 0x4 + unsigned long off2; // offset 0x8, size 0x4 + unsigned long len2; // offset 0xC, size 0x4 + } update; + } data; +} SND_VIRTUALSAMPLE_INFO; + +typedef struct VS_BUFFER { + // total size: 0x24 + unsigned char state; // offset 0x0, size 0x1 + unsigned char hwId; // offset 0x1, size 0x1 + unsigned char smpType; // offset 0x2, size 0x1 + unsigned char voice; // offset 0x3, size 0x1 + unsigned long last; // offset 0x4, size 0x4 + unsigned long finalGoodSamples; // offset 0x8, size 0x4 + unsigned long finalLast; // offset 0xC, size 0x4 + struct SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14 +} VS_BUFFER; + +typedef struct _VS { + // total size: 0x950 + unsigned char numBuffers; // offset 0x0, size 0x1 + unsigned long bufferLength; // offset 0x4, size 0x4 + struct VS_BUFFER streamBuffer[64]; // offset 0x8, size 0x900 + unsigned char voices[64]; // offset 0x908, size 0x40 + unsigned short nextInstID; // offset 0x948, size 0x2 + unsigned long (*callback)(unsigned char, + struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 +} VS; + +extern VS vs; + +#pragma push +#pragma pack(4) +typedef struct SYNTH_VOICE { + SYNTH_QUEUE lowPrecisionJob; + SYNTH_QUEUE zeroOffsetJob; // offset 0xC, size 0xC + SYNTH_QUEUE eventJob; // offset 0x18, size 0xC + u64 lastLowCallTime; + u64 lastZeroCallTime; + MSTEP* addr; + MSTEP* curAddr; + struct SYNTH_VOICE* nextMacActive; + struct SYNTH_VOICE* prevMacActive; + struct SYNTH_VOICE* nextTimeQueueMacro; + struct SYNTH_VOICE* prevTimeQueueMacro; + MAC_STATE state; + MSTEP* trapEventAddr[3]; + MSTEP* trapEventCurAddr[3]; + u8 trapEventAny; + CALLSTACK callStack[4]; + u8 callStackEntryNum; + u8 callStackIndex; + u64 macStartTime; + u64 wait; + u64 waitTime; + u8 timeUsedByInput; + u16 loop; + long local_vars[16]; + u32 child; + u32 parent; + u32 id; + VID_LIST* vidList; + VID_LIST* vidListMaster; + u16 allocId; + u16 macroId; + u8 keyGroup; + u32 lastVID; + u8 prio; + u16 ageSpeed; + u32 age; + u64 cFlags; + u8 block; + u8 fxFlag; + u8 vGroup; + u8 studio; + u8 track; + u8 midi; + u8 midiSet; + u8 section; + u32 sInfo; + u32 playFrq; + u16 curNote; + s8 curDetune; + u8 orgNote; + u8 lastNote; + u8 portType; + 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 + struct setup { + u8 vol; // offset 0x0, size 0x1 + u8 pan; // offset 0x1, size 0x1 + u8 midi; // offset 0x2, size 0x1 + u8 midiSet; // offset 0x3, size 0x1 + u8 section; // offset 0x4, size 0x1 + u8 track; // offset 0x5, size 0x1 + u8 vGroup; // offset 0x6, size 0x1 + u8 studio; // offset 0x7, size 0x1 + u8 itdMode; // offset 0x8, size 0x1 + } setup; // offset 0x208, size 0x9 + u32 midiDirtyFlags; // offset 0x214, size 0x4 + CTRL_DEST inpVolume; // offset 0x218, size 0x24 + CTRL_DEST inpPanning; // offset 0x23C, size 0x24 + CTRL_DEST inpSurroundPanning; // offset 0x260, size 0x24 + CTRL_DEST inpPitchBend; // offset 0x284, size 0x24 + CTRL_DEST inpDoppler; // offset 0x2A8, size 0x24 + CTRL_DEST inpModulation; // offset 0x2CC, size 0x24 + CTRL_DEST inpPedal; // offset 0x2F0, size 0x24 + CTRL_DEST inpPortamento; // offset 0x314, size 0x24 + CTRL_DEST inpPreAuxA; // offset 0x338, size 0x24 + CTRL_DEST inpReverb; // offset 0x35C, size 0x24 + CTRL_DEST inpPreAuxB; // offset 0x380, size 0x24 + CTRL_DEST inpPostAuxB; // offset 0x3A4, size 0x24 + CTRL_DEST inpTremolo; // offset 0x3C8, size 0x24 + 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 + u16 curOutputVolume; // offset 0x400, size 0x2 +} SYNTH_VOICE; +#pragma pop +extern SYNTH_VOICE* synthVoice; + +extern DSPvoice* dspVoice; typedef s32 (*SND_COMPARE)(u16*, u8*); void dataInit(u32, s32); /* extern */ @@ -91,11 +484,11 @@ void dataInitStack(); /* extern */ s32 hwInit(u32* rate, u8 numVoices, u8 numStudios, u32 flags); /* extern */ void hwEnableIrq(); void hwDisableIrq(); -void s3dInit(s32); /* extern */ -void seqInit(); /* extern */ -void streamInit(); /* extern */ -void synthInit(u32, u8); /* extern */ -void vsInit(); /* extern */ +void s3dInit(s32); /* extern */ +void seqInit(); /* extern */ +void streamInit(); /* extern */ +void synthInit(u32, u8); /* extern */ +void vsInit(); /* extern */ void hwExit(); void dataExit(); void s3dExit(); @@ -135,7 +528,8 @@ void* salMalloc(u32 len); void salFree(void* addr); /* Stream */ -typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void * buffer1, u32 len1, void * buffer2, u32 len2, void* user); +typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void* buffer1, u32 len1, void* buffer2, u32 len2, + void* user); typedef struct SND_STREAM_INFO { u32 x0_; u32 x4_; diff --git a/include/musyx/synth.h b/include/musyx/synth.h index 2d9b1c77..b01ab638 100644 --- a/include/musyx/synth.h +++ b/include/musyx/synth.h @@ -6,31 +6,6 @@ extern "C" { #endif -typedef struct VoiceID VoiceID; - -struct VoiceID { - VoiceID* next; - VoiceID* prev; - s32 pubId; - s32 privId; -}; - - -typedef struct SynthVoice { - char data1[0xf4]; - u32 _f4; - VoiceID* voiceId; - char data2[0x18]; - u32 _114[2]; - u8 _11c; - u8 _11d; - u8 _11e; - u8 studio; - char data3[0x404 - 0x120]; -} SynthVoice; - -extern SynthVoice* synthVoice; - typedef void (*SND_AUX_CALLBACK)(u8 reason, SND_AUX_INFO* info, void* user); extern SND_AUX_CALLBACK synthAuxACallback[8]; diff --git a/src/musyx/hardware.c b/src/musyx/hardware.c index bb365eb3..47161067 100644 --- a/src/musyx/hardware.c +++ b/src/musyx/hardware.c @@ -28,7 +28,7 @@ void snd_handle_irq() { for (i = 0; i < salNumVoices; ++i) { for (j = 0; j < 5; ++j) { - dspVoice[i].flags[j] = 0; + dspVoice[i].flags = 0; } } @@ -94,74 +94,67 @@ void hwSetTimeOffset(u8 offset) { salTimeOffset = offset; } u8 hwGetTimeOffset() { return salTimeOffset; } -u32 hwIsActive(s32 idx) { return dspVoice[idx].status != 0; } +u32 hwIsActive(s32 idx) { return dspVoice[idx].state != 0; } void hwSetMesgCallback(SND_MESSAGE_CALLBACK callback) { salMessageCallback = callback; } -void hwSetPriority(s32 idx, s32 priority) { dspVoice[idx].priority = priority; } +void hwSetPriority(s32 idx, s32 priority) { dspVoice[idx].prio = priority; } -void hwInitSamplePlayback(s32 vid, u16 sampleId, u32* param_3, u32 param_4, u32 priority, - u32 param_6, u32 param_7, u32 itdMode) { - u8 i; - u32 j; - u32 k; - s32 flags; - s32 tmpFlags; - u32* tmp; - u32 tmp2; - u32 tmp3; - flags = 0; +void hwInitSamplePlayback(s32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 priority, + u32 callbackUserValue, u32 setSRC, u32 itdMode) { + unsigned char i; // r30 + unsigned long bf; // r29 + DSPvoice* voice; + bf = 0; for (i = 0; i <= salTimeOffset; ++i) { - tmpFlags = dspVoice[vid].flags[i]; - dspVoice[vid].flags[i] = 0; - flags |= tmpFlags & 0x20; + bf |= dspVoice[v].changed[i] & 0x20; + dspVoice[v].changed[i] = 0; } - dspVoice[vid].flags[0] = flags; - dspVoice[vid].priority = priority; - dspVoice[vid]._18 = param_6; - dspVoice[vid].itdFlags = 0; - dspVoice[vid].sampleId = sampleId; - tmp = &dspVoice[vid]._74; - for (j = 4; j > 0; --j) { - tmp[0] = param_3[0]; - tmp[1] = param_3[1]; - tmp += 2; - param_3 += 2; + dspVoice[v].changed[0] = bf; + dspVoice[v].prio = priority; + dspVoice[v].mesgCallBackUserValue = callbackUserValue; + dspVoice[v].flags = 0; + dspVoice[v].smp_id = smpID; + voice = &dspVoice[v]; + ((u32*)&voice->smp_info)[0] = ((u32*)newsmp)[0]; + ((u32*)&voice->smp_info)[1] = ((u32*)newsmp)[1]; + ((u32*)&voice->smp_info)[2] = ((u32*)newsmp)[2]; + ((u32*)&voice->smp_info)[3] = ((u32*)newsmp)[3]; + ((u32*)&voice->smp_info)[4] = ((u32*)newsmp)[4]; + ((u32*)&voice->smp_info)[5] = ((u32*)newsmp)[5]; + ((u32*)&voice->smp_info)[6] = ((u32*)newsmp)[6]; + ((u32*)&voice->smp_info)[7] = ((u32*)newsmp)[7]; + + if (set_defadsr != 0) { + dspVoice[v].adsr.mode = 0; + dspVoice[v].adsr.data.dls.aTime = 0; + dspVoice[v].adsr.data.dls.dTime = 0; + dspVoice[v].adsr.data.dls.sLevel = 0x7FFF; + dspVoice[v].adsr.data.dls.rTime = 0; } - if (param_4 != 0) { - dspVoice[vid]._a4 = 0; - dspVoice[vid]._b8 = 0; - dspVoice[vid]._bc = 0; - dspVoice[vid]._c0 = 0x7FFF; - dspVoice[vid]._c4 = 0; + dspVoice[v].lastUpdate.pitch = 0xff; + dspVoice[v].lastUpdate.vol = 0xff; + dspVoice[v].lastUpdate.volA = 0xff; + dspVoice[v].lastUpdate.volB = 0xff; + + if (setSRC != 0) { + hwSetSRCType(v, 0); + hwSetPolyPhaseFilter(v, 1); } - dspVoice[vid]._e4 = 0xff; - dspVoice[vid]._e5 = 0xff; - dspVoice[vid]._e6 = 0xff; - dspVoice[vid]._e7 = 0xff; - - if (param_7 != 0) { - hwSetSRCType(vid, 0); - hwSetPolyPhaseFilter(vid, 1); - } - - hwSetITDMode(vid, itdMode); + hwSetITDMode(v, itdMode); } void hwBreak(s32 vid) { - if (dspVoice[vid].status == 1 && salTimeOffset == 0) { - dspVoice[vid].breakSet = 1; + if (dspVoice[vid].state == 1 && salTimeOffset == 0) { + dspVoice[vid].startupBreak = 1; } - dspVoice[vid].flags[salTimeOffset] |= 0x20; + // dspVoice[vid].flags[salTimeOffset] |= 0x20; } -void hwSetADSR(s32 vid, u32 *param_2, u8 param_3) { -} +void hwSetADSR(s32 vid, u32* param_2, u8 param_3) {} -void hwOff(s32 vid) { - salDeactivateVoice(&dspVoice[vid]); -} +void hwOff(s32 vid) { salDeactivateVoice(&dspVoice[vid]); } diff --git a/src/musyx/hw_dolphin.c b/src/musyx/hw_dolphin.c index 923e1a68..4dbc3ee0 100644 --- a/src/musyx/hw_dolphin.c +++ b/src/musyx/hw_dolphin.c @@ -77,7 +77,7 @@ u32 salInitAi(SND_SOME_CALLBACK callback, u32 unk, u32* outFreq) { userCallback = callback; AIRegisterDMACallback(salCallback); AIInitDMA(OSCachedToPhysical((u32)salAIBufferBase) + (salAIBufferIndex * 0x280), 0x280); - synthInfo._4 = 0x20; + synthInfo.numSamples = 0x20; *outFreq = 32000; return TRUE; } diff --git a/src/musyx/snd_init.c b/src/musyx/snd_init.c index 9f83801c..c6b799b1 100644 --- a/src/musyx/snd_init.c +++ b/src/musyx/snd_init.c @@ -22,21 +22,21 @@ s32 sndInit(u8 voices, u8 music, u8 sfx, u8 studios, u32 flags, u32 aramSize) { sndActive = 0; if (voices <= 64) { - synthInfo.voices = voices; + synthInfo.voiceNum = voices; } else { - synthInfo.voices = 64; + synthInfo.voiceNum = 64; } if (studios <= 8) { - synthInfo.studios = studios; + synthInfo.studioNum = studios; } else { - synthInfo.studios = 8; + synthInfo.studioNum = 8; } rate = 32000; - synthInfo.music = music; - synthInfo.sfx = sfx; - ret = hwInit(&rate, synthInfo.voices, synthInfo.studios, flags); + synthInfo.maxMusic = music; + synthInfo.maxSFX = sfx; + ret = hwInit(&rate, synthInfo.voiceNum, synthInfo.studioNum, flags); if (ret == 0) { - ret = DoInit(32000, aramSize, synthInfo.voices, flags); + ret = DoInit(32000, aramSize, synthInfo.voiceNum, flags); } return ret; } @@ -50,8 +50,8 @@ void sndQuit() { } void sndSetMaxVoices(u8 music, u8 sfx) { - ASSERT_MSG(music > synthInfo.voices, "Music voices are above maximum voice number."); - ASSERT_MSG(sfx > synthInfo.voices, "Sfx voices are above maximum voice number."); - synthInfo.music = music; - synthInfo.sfx = sfx; + ASSERT_MSG(music > synthInfo.voiceNum, "Music voices are above maximum voice number."); + ASSERT_MSG(sfx > synthInfo.voiceNum, "Sfx voices are above maximum voice number."); + synthInfo.maxMusic = music; + synthInfo.maxSFX = sfx; } diff --git a/src/musyx/snd_midictrl.c b/src/musyx/snd_midictrl.c index fdc904a3..e89ca95a 100644 --- a/src/musyx/snd_midictrl.c +++ b/src/musyx/snd_midictrl.c @@ -1,9 +1,19 @@ #include "musyx/assert.h" #include "musyx/musyx_priv.h" + #define SYNTH_FX_MIDISET 0xFF -u32 inpGlobalMIDIDirtyFlags[8][16]; -s32 midi_ctrl; +typedef struct CHANNEL_DEFAULTS { + unsigned char pbRange; +} CHANNEL_DEFAULTS; + +static u8 fx_lastNote[64]; +static u8 midi_lastNote[8][16]; +static CHANNEL_DEFAULTS inpFXChannelDefaults[64]; +static u8 fx_ctrl[64][134]; +static CHANNEL_DEFAULTS inpChannelDefaults[8][16]; +static u8 midi_ctrl[8][16][134]; +static u32 inpGlobalMIDIDirtyFlags[8][16]; inline bool GetGlobalFlagSet(u8 chan, u8 midiSet, s32 flag) { return (flag & inpGlobalMIDIDirtyFlags[midiSet][chan]) != 0; @@ -32,19 +42,50 @@ void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag) { inpGlobalMIDIDirtyFlags[midiSet][chan] |= flag; } -void inpSetRPNHi(u8 a, u8 b, u8 c) { - -} - -void inpSetRPNLo(u8 a, u8 b, u8 c) { - -} - -void inpSetRPNDec(u8 a, u8 b) { +void inpSetRPNHi(u8 set, u8 channel, u8 value) { + u16 rpn; // r28 + u32 i; // r31 + u8 range; // r29 + if ((midi_ctrl[set][channel][100] | midi_ctrl[set][channel][101]) != 0) { + return; + } + + inpChannelDefaults[set][channel].pbRange = value; + + for (i = 0; i < synthInfo.voiceNum; ++i) { + if (set != synthVoice[i].midiSet || channel != synthVoice[i].midi){ + continue; + } + synthVoice[i].pbUpperKeyRange = value; + synthVoice[i].pbLowerKeyRange = value; + } } +void inpSetRPNLo(u8 a, u8 b, u8 c) {} -void inpSetRPNInc(u8 a, u8 b) { - +void inpSetRPNDec(u8 a, u8 b) {} + +void inpSetRPNInc(u8 a, u8 b) {} + +void inpSetMidiCtrl(u8 ctrl, u8 channel, u8 set, u8 value) { + u32 i; + if (channel == 0xFF) { + return; + } + + if (set != 0xFF) { + switch(ctrl) { + case 38: + inpSetRPNInc(0xFF, channel); + break; + case 97: + inpSetRPNInc(0xFF, channel); + break; + case 6: + inpSetRPNHi(0xff, channel, value); + break; + } + } else { + } } diff --git a/src/musyx/snd_synthapi.c b/src/musyx/snd_synthapi.c index cb009a65..291d775d 100644 --- a/src/musyx/snd_synthapi.c +++ b/src/musyx/snd_synthapi.c @@ -65,17 +65,9 @@ void sndMasterVolume(u8 volume, u16 time, u8 music, u8 fx) { hwEnableIrq(); } -static sndSwapVoices(u32* vals) { - u32 tmp = vals[0]; - vals[0] = vals[1]; - vals[1] = tmp | 0x2000; -} - -#if NONMATCHING -/* This function is nearly matching, relevant scratch: https://decomp.me/scratch/WY9Z1 */ void sndOutputMode(SND_OUTPUTMODE output) { u32 i; - u32 oldSynthFlags = synthFlags; + u32 oldFlags = synthFlags; switch (output) { case SND_OUTPUTMODE_MONO: @@ -95,94 +87,15 @@ void sndOutputMode(SND_OUTPUTMODE output) { break; } - if (oldSynthFlags == synthFlags) { + if (oldFlags == synthFlags) { return; } - /* ???? */ - for (i = 0; i < synthInfo.voices; ++i) { - sndSwapVoices((u32*)&synthVoice[i]._114); + for (i = 0; i < synthInfo.voiceNum; ++i) { + synthVoice[i].cFlags |= 0x0000200000000000; } streamOutputModeChanged(); } -#else -/* clang-format off */ -#pragma push -#pragma optimization_level 0 -#pragma optimizewithasm off -asm void sndOutputMode(SND_OUTPUTMODE output) { - nofralloc -/* 8039C448 003993A8 94 21 FF F0 */ stwu r1, -0x10(r1) -/* 8039C44C 003993AC 7C 08 02 A6 */ mflr r0 -/* 8039C450 003993B0 2C 03 00 01 */ cmpwi r3, 1 -/* 8039C454 003993B4 90 01 00 14 */ stw r0, 0x14(r1) -/* 8039C458 003993B8 93 E1 00 0C */ stw r31, 0xc(r1) -/* 8039C45C 003993BC 83 ED AE 74 */ lwz r31, synthFlags -/* 8039C460 003993C0 41 82 00 38 */ beq lbl_8039C498 -/* 8039C464 003993C4 40 80 00 10 */ bge lbl_8039C474 -/* 8039C468 003993C8 2C 03 00 00 */ cmpwi r3, 0 -/* 8039C46C 003993CC 40 80 00 14 */ bge lbl_8039C480 -/* 8039C470 003993D0 48 00 00 54 */ b lbl_8039C4C4 -lbl_8039C474: -/* 8039C474 003993D4 2C 03 00 03 */ cmpwi r3, 3 -/* 8039C478 003993D8 40 80 00 4C */ bge lbl_8039C4C4 -/* 8039C47C 003993DC 48 00 00 34 */ b lbl_8039C4B0 -lbl_8039C480: -/* 8039C480 003993E0 63 E0 00 01 */ ori r0, r31, 1 -/* 8039C484 003993E4 90 0D AE 74 */ stw r0, synthFlags -/* 8039C488 003993E8 54 00 07 FA */ rlwinm r0, r0, 0, 0x1f, 0x1d -/* 8039C48C 003993EC 90 0D AE 74 */ stw r0, synthFlags -/* 8039C490 003993F0 48 01 7A 8D */ bl hwDisableHRTF -/* 8039C494 003993F4 48 00 00 30 */ b lbl_8039C4C4 -lbl_8039C498: -/* 8039C498 003993F8 57 E3 00 3C */ rlwinm r3, r31, 0, 0, 0x1e -/* 8039C49C 003993FC 57 E0 00 3A */ rlwinm r0, r31, 0, 0, 0x1d -/* 8039C4A0 00399400 90 6D AE 74 */ stw r3, synthFlags -/* 8039C4A4 00399404 90 0D AE 74 */ stw r0, synthFlags -/* 8039C4A8 00399408 48 01 7A 75 */ bl hwDisableHRTF -/* 8039C4AC 0039940C 48 00 00 18 */ b lbl_8039C4C4 -lbl_8039C4B0: -/* 8039C4B0 00399410 57 E0 00 3C */ rlwinm r0, r31, 0, 0, 0x1e -/* 8039C4B4 00399414 90 0D AE 74 */ stw r0, synthFlags -/* 8039C4B8 00399418 60 00 00 02 */ ori r0, r0, 2 -/* 8039C4BC 0039941C 90 0D AE 74 */ stw r0, synthFlags -/* 8039C4C0 00399420 48 01 7A 5D */ bl hwDisableHRTF -lbl_8039C4C4: -/* 8039C4C4 00399424 80 0D AE 74 */ lwz r0, synthFlags -/* 8039C4C8 00399428 7C 1F 00 40 */ cmplw r31, r0 -/* 8039C4CC 0039942C 41 82 00 54 */ beq lbl_8039C520 -/* 8039C4D0 00399430 3C 60 80 55 */ lis r3, synthInfo@ha -/* 8039C4D4 00399434 38 E0 00 00 */ li r7, 0 -/* 8039C4D8 00399438 38 A3 00 50 */ addi r5, r3, synthInfo@l -/* 8039C4DC 0039943C 38 C0 00 00 */ li r6, 0 -/* 8039C4E0 00399440 48 00 00 30 */ b lbl_8039C510 -lbl_8039C4E4: -/* 8039C4E4 00399444 80 6D AE 78 */ lwz r3, synthVoice -/* 8039C4E8 00399448 38 06 01 14 */ addi r0, r6, 0x114 -/* 8039C4EC 0039944C 38 C6 04 04 */ addi r6, r6, 0x404 -/* 8039C4F0 00399450 38 E7 00 01 */ addi r7, r7, 1 -/* 8039C4F4 00399454 7C 83 02 14 */ add r4, r3, r0 -/* 8039C4F8 00399458 7C 63 02 14 */ add r3, r3, r0 -/* 8039C4FC 0039945C 80 04 00 00 */ lwz r0, 0(r4) -/* 8039C500 00399460 80 84 00 04 */ lwz r4, 4(r4) -/* 8039C504 00399464 60 00 20 00 */ ori r0, r0, 0x2000 -/* 8039C508 00399468 90 83 00 04 */ stw r4, 4(r3) -/* 8039C50C 0039946C 90 03 00 00 */ stw r0, 0(r3) -lbl_8039C510: -/* 8039C510 00399470 88 05 02 10 */ lbz r0, 0x210(r5) -/* 8039C514 00399474 7C 07 00 40 */ cmplw r7, r0 -/* 8039C518 00399478 41 80 FF CC */ blt lbl_8039C4E4 -/* 8039C51C 0039947C 48 00 12 81 */ bl streamOutputModeChanged -lbl_8039C520: -/* 8039C520 00399480 80 01 00 14 */ lwz r0, 0x14(r1) -/* 8039C524 00399484 83 E1 00 0C */ lwz r31, 0xc(r1) -/* 8039C528 00399488 7C 08 03 A6 */ mtlr r0 -/* 8039C52C 0039948C 38 21 00 10 */ addi r1, r1, 0x10 -/* 8039C530 00399490 4E 80 00 20 */ blr -} -#pragma pop -/* clang-format on */ -#endif // clang-format off void sndSetAuxProcessingCallbacks(u8 studio, @@ -233,10 +146,10 @@ void synthActivateStudio(u8 studio, u32 arg1, u32 arg2) { void synthDeactivateStudio(u8 studio) { u32 i; - for (i = 0; i < synthInfo.voices; ++i) { + for (i = 0; i < synthInfo.voiceNum; ++i) { if (studio == synthVoice[i].studio) { - if (synthVoice[i]._f4 != 0xFFFFFFFF) { - voiceKillSound(synthVoice[i].voiceId->pubId); + if (synthVoice[i].id != 0xFFFFFFFF) { + voiceKillSound(synthVoice[i].vidList->vid); } else if (hwIsActive(i)) { hwOff(i); } @@ -251,7 +164,10 @@ void synthDeactivateStudio(u8 studio) { hwDeactivateStudio(studio); } -/* TODO: Figure out what `unk` is */ -bool synthAddStudioInput(u8 studio, void* unk) { return hwAddInput(studio, unk); } +bool synthAddStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { + return hwAddInput(studio, in_desc); +} -bool synthRemoveStudioInput(u8 studio, void* unk) { return hwRemoveInput(studio, unk); } +bool synthRemoveStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { + return hwRemoveInput(studio, in_desc); +} diff --git a/src/musyx/synth_ac.c b/src/musyx/synth_ac.c index f8685d9e..3d3e4d81 100644 --- a/src/musyx/synth_ac.c +++ b/src/musyx/synth_ac.c @@ -66,5 +66,5 @@ u32 sndGetPitch(u8 arg0, u32 arg1) { ? (f32)((arg1 & 0xFFFFFF) * (temp_r6 < arg0 ? toneup_tab[(arg0 - temp_r6)] : tonedown_tab[temp_r6 - arg0])) : (f32)(arg1 & 0xFFFFFF)); - return pitch / synthInfo.freq; + return pitch / synthInfo.mixFrq; }