From f75b37e7736bc56d8172d763a621ea54dec4333f Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Wed, 29 Mar 2023 19:27:34 -0700 Subject: [PATCH] Various fixes and matches --- .vscode/c_cpp_properties.json | 6 +- .vscode/settings.json | 3 +- configure.py | 5 +- include/dolphin/GBAPriv.h | 6 +- include/dolphin/os.h | 9 + include/musyx/assert.h | 64 ++- include/musyx/musyx.h | 42 ++ include/musyx/musyx_priv.h | 596 ++++++++++++----------- include/musyx/seq.h | 155 ++++++ include/musyx/synth.h | 3 +- libc/math.h | 1 + src/Dolphin/GBA/GBA.c | 175 +++++-- src/Dolphin/GBA/GBAGetProcessStatus.c | 84 +++- src/Dolphin/GBA/GBAJoyBoot.c | 109 +++-- src/Dolphin/GBA/GBAKey.c | 116 +++++ src/Dolphin/GBA/GBARead.c | 20 +- src/Dolphin/GBA/GBAWrite.c | 27 +- src/Dolphin/GBA/GBAXfer.c | 33 +- src/musyx/runtime/hardware.c | 2 +- src/musyx/runtime/seq.c | 670 ++++++++++++++++++++++++++ src/musyx/runtime/stream.c | 454 ++++++++++++++++- src/musyx/runtime/synthmacros.c | 6 +- src/musyx/runtime/synthvoice.c | 12 +- 23 files changed, 2120 insertions(+), 478 deletions(-) create mode 100644 src/Dolphin/GBA/GBAKey.c create mode 100644 src/musyx/runtime/seq.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index f1ecc99f..a83d22fd 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,8 +3,8 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/include", - "${workspaceFolder}/libc" + "${workspaceFolder}/include/**", + "${workspaceFolder}/libc/**" ], "cStandard": "c99", "cppStandard": "c++98", @@ -21,4 +21,4 @@ } ], "version": 4 -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index e94951fc..b42177ab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -59,7 +59,8 @@ "osfont.h": "c", "arq.h": "c", "string.h": "c", - "hw_regs.h": "c" + "hw_regs.h": "c", + "synth.h": "c" }, "files.autoSave": "onFocusChange", "files.insertFinalNewline": true, diff --git a/configure.py b/configure.py index d9b9c12b..b6d7cef3 100755 --- a/configure.py +++ b/configure.py @@ -925,7 +925,7 @@ LIBS = [ "cflags": "$cflags_musyx -DMUSY_VERSION_MAJOR=1 -DMUSY_VERSION_MINOR=5 -DMUSY_VERSION_PATCH=4", "host": False, "objects": [ - "musyx/runtime/seq", + ["musyx/runtime/seq", False], ["musyx/runtime/synth", False], ["musyx/runtime/seq_api", True], ["musyx/runtime/snd_synthapi", True, {"add_to_all": False}], @@ -1034,6 +1034,7 @@ LIBS = [ { "lib": "gba", "mw_version": "1.2.5e", + #"cflags" : "-proc gecko -Cpp_exceptions off -fp hard -nodefaults -nosyspath -i include -i libc -g -sym on -D_DEBUG=1 -enum int -use_lmw_stmw on", "cflags": "$cflags_base", "host": False, "objects": [ @@ -1043,7 +1044,7 @@ LIBS = [ ["Dolphin/GBA/GBARead", True], ["Dolphin/GBA/GBAWrite", True], ["Dolphin/GBA/GBAXfer", True], - "Dolphin/GBA/GBAKey", + ["Dolphin/GBA/GBAKey", True], ], }, ] diff --git a/include/dolphin/GBAPriv.h b/include/dolphin/GBAPriv.h index 1a95c99b..32fe4fcd 100644 --- a/include/dolphin/GBAPriv.h +++ b/include/dolphin/GBAPriv.h @@ -13,7 +13,7 @@ extern "C" { typedef void (*GBATransferCallback)(s32 chan); -typedef struct GBASecParams { +typedef struct GBASecParam { u8 readbuf[4]; s32 paletteColor; s32 paletteSpeed; @@ -23,7 +23,7 @@ typedef struct GBASecParams { u32 keyA; s32 keyB; u8 _padding1[24]; -} GBASecParams; +} GBASecParam; typedef struct GBABootInfo { s32 paletteColor; @@ -61,7 +61,7 @@ typedef struct GBAControl { GBATransferCallback proc; GBABootInfo bootInfo; DSPTaskInfo task; - GBASecParams* param; + GBASecParam* param; } GBAControl; extern GBAControl __GBA[4]; diff --git a/include/dolphin/os.h b/include/dolphin/os.h index e87a4daf..f7d61d97 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -29,12 +29,21 @@ u32 __OSCoreClock AT_ADDRESS(OS_BASE_CACHED | 0x00FC); // sync with OSLoMem.h #define OS_CORE_CLOCK __OSCoreClock #define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4) +#ifndef _DEBUG #define OSPhysicalToCached(paddr) ((void*)((u32)(paddr) + OS_BASE_CACHED)) #define OSPhysicalToUncached(paddr) ((void*)((u32)(paddr) + OS_BASE_UNCACHED)) #define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr)-OS_BASE_CACHED)) #define OSUncachedToPhysical(ucaddr) ((u32)((u8*)(ucaddr)-OS_BASE_UNCACHED)) #define OSCachedToUncached(caddr) ((void*)((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) #define OSUncachedToCached(ucaddr) ((void*)((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) +#else +u32 OSPhysicalToCached(void* paddr); +u32 OSPhysicalToUncached(void* paddr); +u32 OSCachedToPhysical(void* caddr); +u32 OSUncachedToPhysical(void* ucaddr); +u32 OSCachedToUncached(void* caddr); +u32 OSUncachedToCached(void* ucaddr); +#endif #define OSTicksToCycles(ticks) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2) #define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK) diff --git a/include/musyx/assert.h b/include/musyx/assert.h index 451e6a21..7ce9a86d 100644 --- a/include/musyx/assert.h +++ b/include/musyx/assert.h @@ -1,30 +1,25 @@ #ifndef _MUSYX_ASSERT #define _MUSYX_ASSERT +#include "musyx/version.h" extern void OSPanic(const char* file, int line, const char* msg, ...); extern void OSReport(const char* msg, ...); -static inline unsigned __SOME_ASSERT_DERP1() { - return 0; -} +static inline unsigned __SOME_ASSERT_DERP1() { return 0; } -static inline unsigned __SOME_ASSERT_DERP2() { - return __SOME_ASSERT_DERP1(); -} +static inline unsigned __SOME_ASSERT_DERP2() { return __SOME_ASSERT_DERP1(); } -static inline void __SOME_ASSERT_DERP() { - __SOME_ASSERT_DERP2() != 0; -} +static inline void __SOME_ASSERT_DERP() { __SOME_ASSERT_DERP2() != 0; } #ifndef ASSERT #ifdef _DEBUG -#define MUSY_ASSERT(cond) \ - do { \ - if (!(cond)) { \ - OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \ - } \ - __SOME_ASSERT_DERP(); \ - } while(0) +#define MUSY_ASSERT(cond) \ + do { \ + if (!(cond)) { \ + OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \ + } \ + __SOME_ASSERT_DERP(); \ + } while (0) #else #define MUSY_ASSERT(cond) #endif @@ -32,12 +27,27 @@ static inline void __SOME_ASSERT_DERP() { #ifndef MUSY_ASSERT_MSG #ifdef _DEBUG -#define MUSY_ASSERT_MSG(cond, msg) \ - do { \ - if (!(cond)) { \ - OSPanic(__FILE__, __LINE__, msg); \ - } \ - } while(0) +#if MUSY_VERSION >= MUSY_VERSION_CHECK(2, 0, 0) +#define MUSY_ASSERT_MSG(cond, msg) \ + do { \ + s32 tmp = 1; \ + s32 tmp2; \ + if (!(cond)) { \ + OSPanic(__FILE__, __LINE__, msg); \ + tmp2 = 0; \ + if (tmp2 == 0) { \ + tmp = 0; \ + } \ + } \ + } while (0) +#else +#define MUSY_ASSERT_MSG(cond, msg) \ + do { \ + if (!(cond)) { \ + OSPanic(__FILE__, __LINE__, msg); \ + } \ + } while (0) +#endif #else #define MUSY_ASSERT_MSG(cond, msg) #endif @@ -46,9 +56,17 @@ static inline void __SOME_ASSERT_DERP() { #ifndef MUSY_DEBUG #ifdef _DEBUG #define MUSY_DEBUG OSReport -#else +#else #define MUSY_DEBUG #endif #endif +#ifndef MUSY_FATAL +#ifdef _DEBUG +#define MUSY_FATAL(msg) OSPanic(__FILE__, __LINE__, msg) +#else +#define MUSY_FATAL +#endif +#endif + #endif // _MUSYX_ASSERT diff --git a/include/musyx/musyx.h b/include/musyx/musyx.h index 6f1cfd90..f2490101 100644 --- a/include/musyx/musyx.h +++ b/include/musyx/musyx.h @@ -39,6 +39,10 @@ typedef signed long bool; #define SYNTH_MAX_VOICES 64 +typedef struct SND_ADPCMSTREAM_INFO { + s16 coefTab[8][2]; // Table of coef. pairs +} SND_ADPCMSTREAM_INFO; + typedef u32 SND_SEQID; typedef u32 SND_VOICEID; typedef u32 SND_STREAMID; @@ -65,6 +69,13 @@ typedef struct SND_SEQVOLDEF { u8 volGroup; } SND_SEQVOLDEF; +#define SND_PLAYPARA_DEFAULT 0x00000000 +#define SND_PLAYPARA_TRACKMUTE 0x00000001 +#define SND_PLAYPARA_SPEED 0x00000002 +#define SND_PLAYPARA_VOLUME 0x00000004 +#define SND_PLAYPARA_SEQVOLDEF 0x00000008 +#define SND_PLAYPARA_PAUSE 0x00000010 + typedef struct SND_PLAYPARA { u32 flags; u32 trackMute[2]; @@ -310,6 +321,37 @@ 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_DEFAULT 0 + +typedef struct SND_CROSSFADE { + SND_SEQID seqId1; + u16 time1; + + SND_SEQID seqId2; + u16 time2; + void* arr2; + SND_GROUPID gid2; + SND_SONGID sid2; + u8 vol2; + u8 studio2; + + u32 trackMute2[2]; + u16 speed2; + + u8 flags; +} SND_CROSSFADE; + typedef struct SND_PROFILE_DATA { unsigned long loadStores; unsigned long missCycles; diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index 5f9b7cd0..45b1c6af 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -10,10 +10,10 @@ extern "C" { 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 + u8 vol; // offset 0x0, size 0x1 + u8 volA; // offset 0x1, size 0x1 + u8 volB; // offset 0x2, size 0x1 + u8 srcStudio; // offset 0x3, size 0x1 } SND_STUDIO_INPUT; typedef struct SYNTH_VOICELIST { @@ -28,8 +28,8 @@ extern SYNTH_VOICELIST voicePrioSortVoices[64]; typedef struct SYNTH_ROOTLIST { // total size: 0x4 - unsigned short next; // offset 0x0, size 0x2 - unsigned short prev; // offset 0x2, size 0x2 + u16 next; // offset 0x0, size 0x2 + u16 prev; // offset 0x2, size 0x2 } SYNTH_ROOTLIST; extern SYNTH_ROOTLIST voicePrioSortRootList[256]; @@ -73,117 +73,117 @@ typedef struct ADSR_VARS { 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 + u16 vL; // offset 0x0, size 0x2 + u16 vDeltaL; // offset 0x2, size 0x2 + u16 vR; // offset 0x4, size 0x2 + u16 vDeltaR; // offset 0x6, size 0x2 + u16 vAuxAL; // offset 0x8, size 0x2 + u16 vDeltaAuxAL; // offset 0xA, size 0x2 + u16 vAuxAR; // offset 0xC, size 0x2 + u16 vDeltaAuxAR; // offset 0xE, size 0x2 + u16 vAuxBL; // offset 0x10, size 0x2 + u16 vDeltaAuxBL; // offset 0x12, size 0x2 + u16 vAuxBR; // offset 0x14, size 0x2 + u16 vDeltaAuxBR; // offset 0x16, size 0x2 + u16 vAuxBS; // offset 0x18, size 0x2 + u16 vDeltaAuxBS; // offset 0x1A, size 0x2 + u16 vS; // offset 0x1C, size 0x2 + u16 vDeltaS; // offset 0x1E, size 0x2 + u16 vAuxAS; // offset 0x20, size 0x2 + u16 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 + u16 flag; // offset 0x0, size 0x2 + u16 bufferHi; // offset 0x2, size 0x2 + u16 bufferLo; // offset 0x4, size 0x2 + u16 shiftL; // offset 0x6, size 0x2 + u16 shiftR; // offset 0x8, size 0x2 + u16 targetShiftL; // offset 0xA, size 0x2 + u16 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 + u16 updNum[5]; // offset 0x0, size 0xA + u16 dataHi; // offset 0xA, size 0x2 + u16 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 + u16 aL; // offset 0x0, size 0x2 + u16 aAuxAL; // offset 0x2, size 0x2 + u16 aAuxBL; // offset 0x4, size 0x2 + u16 aR; // offset 0x6, size 0x2 + u16 aAuxAR; // offset 0x8, size 0x2 + u16 aAuxBR; // offset 0xA, size 0x2 + u16 aS; // offset 0xC, size 0x2 + u16 aAuxAS; // offset 0xE, size 0x2 + u16 aAuxBS; // offset 0x10, size 0x2 } _PBDPOP; typedef struct _PBVE { // total size: 0x4 - unsigned short currentVolume; // offset 0x0, size 0x2 - unsigned short currentDelta; // offset 0x2, size 0x2 + u16 currentVolume; // offset 0x0, size 0x2 + u16 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 + u16 numCoefs; // offset 0x0, size 0x2 + u16 coefsHi; // offset 0x2, size 0x2 + u16 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 + u16 loopFlag; // offset 0x0, size 0x2 + u16 format; // offset 0x2, size 0x2 + u16 loopAddressHi; // offset 0x4, size 0x2 + u16 loopAddressLo; // offset 0x6, size 0x2 + u16 endAddressHi; // offset 0x8, size 0x2 + u16 endAddressLo; // offset 0xA, size 0x2 + u16 currentAddressHi; // offset 0xC, size 0x2 + u16 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 + u16 a[8][2]; // offset 0x0, size 0x20 + u16 gain; // offset 0x20, size 0x2 + u16 pred_scale; // offset 0x22, size 0x2 + u16 yn1; // offset 0x24, size 0x2 + u16 yn2; // offset 0x26, size 0x2 } _PDADPCM; typedef 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 + u16 ratioHi; // offset 0x0, size 0x2 + u16 ratioLo; // offset 0x2, size 0x2 + u16 currentAddressFrac; // offset 0x4, size 0x2 + u16 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 + u16 loop_pred_scale; // offset 0x0, size 0x2 + u16 loop_yn1; // offset 0x2, size 0x2 + u16 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 + 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 @@ -194,7 +194,7 @@ typedef struct _PB { 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 + u16 streamLoopCnt; // offset 0xBA, size 0x2 } _PB; typedef struct SAMPLE_INFO { @@ -211,81 +211,81 @@ typedef struct SAMPLE_INFO { typedef struct GROUP_DATA { // total size: 0x28 - unsigned long nextOff; // offset 0x0, size 0x4 - unsigned short id; // offset 0x4, size 0x2 - unsigned short type; // offset 0x6, size 0x2 - unsigned long macroOff; // offset 0x8, size 0x4 - unsigned long sampleOff; // offset 0xC, size 0x4 - unsigned long curveOff; // offset 0x10, size 0x4 - unsigned long keymapOff; // offset 0x14, size 0x4 - unsigned long layerOff; // offset 0x18, size 0x4 + u32 nextOff; // offset 0x0, size 0x4 + u16 id; // offset 0x4, size 0x2 + u16 type; // offset 0x6, size 0x2 + u32 macroOff; // offset 0x8, size 0x4 + u32 sampleOff; // offset 0xC, size 0x4 + u32 curveOff; // offset 0x10, size 0x4 + u32 keymapOff; // offset 0x14, size 0x4 + u32 layerOff; // offset 0x18, size 0x4 union { struct fx { // total size: 0x4 - unsigned long tableOff; // offset 0x0, size 0x4 + u32 tableOff; // offset 0x0, size 0x4 } fx; struct song { // total size: 0xC - unsigned long normpageOff; // offset 0x0, size 0x4 - unsigned long drumpageOff; // offset 0x4, size 0x4 - unsigned long midiSetupOff; // offset 0x8, size 0x4 + u32 normpageOff; // offset 0x0, size 0x4 + u32 drumpageOff; // offset 0x4, size 0x4 + u32 midiSetupOff; // offset 0x8, size 0x4 } song; } data; // offset 0x1C, size 0xC } GROUP_DATA; typedef struct SAMPLE_HEADER { // total size: 0x10 - unsigned long info; // offset 0x0, size 0x4 - unsigned long length; // offset 0x4, size 0x4 - unsigned long loopOffset; // offset 0x8, size 0x4 - unsigned long loopLength; // offset 0xC, size 0x4 + u32 info; // offset 0x0, size 0x4 + u32 length; // offset 0x4, size 0x4 + u32 loopOffset; // offset 0x8, size 0x4 + u32 loopLength; // offset 0xC, size 0x4 } SAMPLE_HEADER; typedef struct SDIR_DATA { // total size: 0x20 - unsigned short id; // offset 0x0, size 0x2 - unsigned short ref_cnt; // offset 0x2, size 0x2 - unsigned long offset; // offset 0x4, 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 struct SAMPLE_HEADER header; // offset 0xC, size 0x10 - unsigned long extraData; // offset 0x1C, size 0x4 + 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 - unsigned short numSmp; // offset 0x8, size 0x2 - unsigned short res; // offset 0xA, size 0x2 + u16 numSmp; // offset 0x8, size 0x2 + u16 res; // offset 0xA, size 0x2 } SDIR_TAB; typedef struct DATA_TAB { // total size: 0x8 - void* data; // offset 0x0, size 0x4 - unsigned short id; // offset 0x4, size 0x2 - unsigned short refCount; // offset 0x6, size 0x2 + void* data; // offset 0x0, size 0x4 + u16 id; // offset 0x4, size 0x2 + u16 refCount; // offset 0x6, size 0x2 } DATA_TAB; typedef struct LAYER_TAB { // total size: 0xC - void* data; // offset 0x0, size 0x4 - unsigned short id; // offset 0x4, size 0x2 - unsigned short num; // offset 0x6, size 0x2 - unsigned short refCount; // offset 0x8, size 0x2 - unsigned short reserved; // offset 0xA, size 0x2 + void* data; // offset 0x0, size 0x4 + u16 id; // offset 0x4, size 0x2 + u16 num; // offset 0x6, size 0x2 + u16 refCount; // offset 0x8, size 0x2 + u16 reserved; // offset 0xA, size 0x2 } LAYER_TAB; typedef struct MAC_MAINTAB { // total size: 0x4 - unsigned short num; // offset 0x0, size 0x2 - unsigned short subTabIndex; // offset 0x2, size 0x2 + u16 num; // offset 0x0, size 0x2 + u16 subTabIndex; // offset 0x2, size 0x2 } MAC_MAINTAB; typedef struct MAC_SUBTAB { // total size: 0x8 - void* data; // offset 0x0, size 0x4 - unsigned short id; // offset 0x4, size 0x2 - unsigned short refCount; // offset 0x6, size 0x2 + void* data; // offset 0x0, size 0x4 + u16 id; // offset 0x4, size 0x2 + u16 refCount; // offset 0x6, size 0x2 } MAC_SUBTAB; typedef struct GSTACK { @@ -414,19 +414,19 @@ 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 - unsigned long seqId; // offset 0x28, size 0x4 - unsigned char seqMode; // offset 0x2C, size 0x1 - unsigned char type; // offset 0x2D, size 0x1 + 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 } SYNTHMasterFader; typedef struct CTRL_SOURCE { @@ -443,40 +443,40 @@ typedef struct CTRL_DEST { typedef struct SND_VIRTUALSAMPLE_INFO { // total size: 0x14 - unsigned short smpID; // offset 0x0, size 0x2 - unsigned short instID; // offset 0x2, size 0x2 + u16 smpID; // offset 0x0, size 0x2 + u16 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 + u32 off1; // offset 0x0, size 0x4 + u32 len1; // offset 0x4, size 0x4 + u32 off2; // offset 0x8, size 0x4 + u32 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 - SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14 + u8 state; // offset 0x0, size 0x1 + u8 hwId; // offset 0x1, size 0x1 + u8 smpType; // offset 0x2, size 0x1 + u8 voice; // offset 0x3, size 0x1 + u32 last; // offset 0x4, size 0x4 + u32 finalGoodSamples; // offset 0x8, size 0x4 + u32 finalLast; // offset 0xC, size 0x4 + 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 + u8 numBuffers; // offset 0x0, size 0x1 + u32 bufferLength; // offset 0x4, size 0x4 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 + u8 voices[64]; // offset 0x908, size 0x40 + u16 nextInstID; // offset 0x948, size 0x2 + u32 (*callback)(u8, + struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 } VS; extern VS vs; @@ -611,46 +611,46 @@ typedef struct SYNTH_VOICE { typedef struct synthITDInfo { // total size: 0x2 - unsigned char music; // offset 0x0, size 0x1 - unsigned char sfx; // offset 0x1, size 0x1 + u8 music; // offset 0x0, size 0x1 + u8 sfx; // offset 0x1, size 0x1 } synthITDInfo; #pragma pop typedef struct LAYER { // total size: 0xC - unsigned short id; // offset 0x0, size 0x2 - unsigned char keyLow; // offset 0x2, size 0x1 - unsigned char keyHigh; // offset 0x3, size 0x1 - signed char transpose; // offset 0x4, size 0x1 - unsigned char volume; // offset 0x5, size 0x1 - signed short prioOffset; // offset 0x6, size 0x2 - unsigned char panning; // offset 0x8, size 0x1 - unsigned char reserved[3]; // offset 0x9, size 0x3 + u16 id; // offset 0x0, size 0x2 + u8 keyLow; // offset 0x2, size 0x1 + u8 keyHigh; // offset 0x3, size 0x1 + s8 transpose; // offset 0x4, size 0x1 + u8 volume; // offset 0x5, size 0x1 + s16 prioOffset; // offset 0x6, size 0x2 + u8 panning; // offset 0x8, size 0x1 + u8 reserved[3]; // offset 0x9, size 0x3 } LAYER; typedef struct KEYMAP { // total size: 0x8 - unsigned short id; // offset 0x0, size 0x2 - signed char transpose; // offset 0x2, size 0x1 - unsigned char panning; // offset 0x3, size 0x1 - signed short prioOffset; // offset 0x4, size 0x2 - unsigned char reserved[2]; // offset 0x6, size 0x2 + u16 id; // offset 0x0, size 0x2 + s8 transpose; // offset 0x2, size 0x1 + u8 panning; // offset 0x3, size 0x1 + s16 prioOffset; // offset 0x4, size 0x2 + u8 reserved[2]; // offset 0x6, size 0x2 } KEYMAP; typedef struct MEM_DATA { // total size: 0x408 - unsigned long nextOff; // offset 0x0, size 0x4 - unsigned short id; // offset 0x4, size 0x2 - unsigned short reserved; // offset 0x6, size 0x2 + u32 nextOff; // offset 0x0, size 0x4 + u16 id; // offset 0x4, size 0x2 + u16 reserved; // offset 0x6, size 0x2 union { struct { // total size: 0x10 - unsigned long num; // offset 0x0, size 0x4 - LAYER entry[1]; // offset 0x4, size 0xC + u32 num; // offset 0x0, size 0x4 + LAYER entry[1]; // offset 0x4, size 0xC } layer; KEYMAP map[128]; - unsigned char tab[1]; + u8 tab[1]; MSTEP cmd[1][2]; } data; // offset 0x8, size 0x400 } MEM_DATA; @@ -694,33 +694,33 @@ typedef struct SAL_PANINFO { typedef struct _SPB { // total size: 0x36 - unsigned short dpopLHi; // offset 0x0, size 0x2 - unsigned short dpopLLo; // offset 0x2, size 0x2 - unsigned short dpopLDelta; // offset 0x4, size 0x2 - unsigned short dpopRHi; // offset 0x6, size 0x2 - unsigned short dpopRLo; // offset 0x8, size 0x2 - unsigned short dpopRDelta; // offset 0xA, size 0x2 - unsigned short dpopSHi; // offset 0xC, size 0x2 - unsigned short dpopSLo; // offset 0xE, size 0x2 - unsigned short dpopSDelta; // offset 0x10, size 0x2 - unsigned short dpopALHi; // offset 0x12, size 0x2 - unsigned short dpopALLo; // offset 0x14, size 0x2 - unsigned short dpopALDelta; // offset 0x16, size 0x2 - unsigned short dpopARHi; // offset 0x18, size 0x2 - unsigned short dpopARLo; // offset 0x1A, size 0x2 - unsigned short dpopARDelta; // offset 0x1C, size 0x2 - unsigned short dpopASHi; // offset 0x1E, size 0x2 - unsigned short dpopASLo; // offset 0x20, size 0x2 - unsigned short dpopASDelta; // offset 0x22, size 0x2 - unsigned short dpopBLHi; // offset 0x24, size 0x2 - unsigned short dpopBLLo; // offset 0x26, size 0x2 - unsigned short dpopBLDelta; // offset 0x28, size 0x2 - unsigned short dpopBRHi; // offset 0x2A, size 0x2 - unsigned short dpopBRLo; // offset 0x2C, size 0x2 - unsigned short dpopBRDelta; // offset 0x2E, size 0x2 - unsigned short dpopBSHi; // offset 0x30, size 0x2 - unsigned short dpopBSLo; // offset 0x32, size 0x2 - unsigned short dpopBSDelta; // offset 0x34, size 0x2 + u16 dpopLHi; // offset 0x0, size 0x2 + u16 dpopLLo; // offset 0x2, size 0x2 + u16 dpopLDelta; // offset 0x4, size 0x2 + u16 dpopRHi; // offset 0x6, size 0x2 + u16 dpopRLo; // offset 0x8, size 0x2 + u16 dpopRDelta; // offset 0xA, size 0x2 + u16 dpopSHi; // offset 0xC, size 0x2 + u16 dpopSLo; // offset 0xE, size 0x2 + u16 dpopSDelta; // offset 0x10, size 0x2 + u16 dpopALHi; // offset 0x12, size 0x2 + u16 dpopALLo; // offset 0x14, size 0x2 + u16 dpopALDelta; // offset 0x16, size 0x2 + u16 dpopARHi; // offset 0x18, size 0x2 + u16 dpopARLo; // offset 0x1A, size 0x2 + u16 dpopARDelta; // offset 0x1C, size 0x2 + u16 dpopASHi; // offset 0x1E, size 0x2 + u16 dpopASLo; // offset 0x20, size 0x2 + u16 dpopASDelta; // offset 0x22, size 0x2 + u16 dpopBLHi; // offset 0x24, size 0x2 + u16 dpopBLLo; // offset 0x26, size 0x2 + u16 dpopBLDelta; // offset 0x28, size 0x2 + u16 dpopBRHi; // offset 0x2A, size 0x2 + u16 dpopBRLo; // offset 0x2C, size 0x2 + u16 dpopBRDelta; // offset 0x2E, size 0x2 + u16 dpopBSHi; // offset 0x30, size 0x2 + u16 dpopBSLo; // offset 0x32, size 0x2 + u16 dpopBSDelta; // offset 0x34, size 0x2 } _SPB; typedef struct DSPhostDPop { @@ -738,10 +738,10 @@ typedef struct DSPhostDPop { typedef struct DSPinput { // total size: 0xC - unsigned char studio; // offset 0x0, size 0x1 - unsigned short vol; // offset 0x2, size 0x2 - unsigned short volA; // offset 0x4, size 0x2 - unsigned short volB; // offset 0x6, size 0x2 + 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 } DSPinput; @@ -754,9 +754,9 @@ typedef struct DSPstudioinfo { long* auxB[3]; // offset 0x3C, size 0xC struct DSPvoice* voiceRoot; // offset 0x48, size 0x4 struct DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4 - unsigned char state; // offset 0x50, size 0x1 - unsigned char isMaster; // offset 0x51, size 0x1 - unsigned char numInputs; // offset 0x52, size 0x1 + 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 @@ -774,50 +774,50 @@ typedef s32 (*SND_COMPARE)(void*, void*); typedef struct CHANNEL_DEFAULTS { // total size: 0x1 - unsigned char pbRange; // offset 0x0, size 0x1 + u8 pbRange; // offset 0x0, size 0x1 } CHANNEL_DEFAULTS; typedef struct FX_TAB { // total size: 0xA - unsigned short id; // offset 0x0, size 0x2 - unsigned short macro; // offset 0x2, size 0x2 - unsigned char maxVoices; // offset 0x4, size 0x1 - unsigned char priority; // offset 0x5, size 0x1 - unsigned char volume; // offset 0x6, size 0x1 - unsigned char panning; // offset 0x7, size 0x1 - unsigned char key; // offset 0x8, size 0x1 - unsigned char vGroup; // offset 0x9, size 0x1 + u16 id; // offset 0x0, size 0x2 + u16 macro; // offset 0x2, size 0x2 + u8 maxVoices; // offset 0x4, size 0x1 + u8 priority; // offset 0x5, size 0x1 + u8 volume; // offset 0x6, size 0x1 + u8 panning; // offset 0x7, size 0x1 + u8 key; // offset 0x8, size 0x1 + u8 vGroup; // offset 0x9, size 0x1 } FX_TAB; typedef struct FX_DATA { // total size: 0xE - unsigned short num; // offset 0x0, size 0x2 - unsigned short 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 + struct FX_TAB fx[1]; // offset 0x4, size 0xA } FX_DATA; typedef struct FX_GROUP { // total size: 0x8 - unsigned short gid; // offset 0x0, size 0x2 - unsigned short fxNum; // offset 0x2, size 0x2 + u16 gid; // offset 0x0, size 0x2 + u16 fxNum; // offset 0x2, size 0x2 struct FX_TAB* fxTab; // offset 0x4, size 0x4 } FX_GROUP; typedef struct PAGE { // total size: 0x6 - unsigned short macro; // offset 0x0, size 0x2 - unsigned char prio; // offset 0x2, size 0x1 - unsigned char maxVoices; // offset 0x3, size 0x1 - unsigned char index; // offset 0x4, size 0x1 - unsigned char reserved; // offset 0x5, size 0x1 + u16 macro; // offset 0x0, size 0x2 + u8 prio; // offset 0x2, size 0x1 + u8 maxVoices; // offset 0x3, size 0x1 + u8 index; // offset 0x4, size 0x1 + u8 reserved; // offset 0x5, size 0x1 } PAGE; typedef struct MIDI_CHANNEL_SETUP { // total size: 0x5 - unsigned char program; // offset 0x0, size 0x1 - unsigned char volume; // offset 0x1, size 0x1 - unsigned char panning; // offset 0x2, size 0x1 - unsigned char reverb; // offset 0x3, size 0x1 - unsigned char chorus; // offset 0x4, size 0x1 + u8 program; // offset 0x0, size 0x1 + u8 volume; // offset 0x1, size 0x1 + u8 panning; // offset 0x2, size 0x1 + u8 reverb; // offset 0x3, size 0x1 + u8 chorus; // offset 0x4, size 0x1 } MIDI_CHANNEL_SETUP; typedef struct MIDISETUP { @@ -832,19 +832,19 @@ typedef struct ADSR_INFO { union ai_data { struct { // total size: 0x14 - long atime; // offset 0x0, size 0x4 - long dtime; // offset 0x4, size 0x4 - unsigned short slevel; // offset 0x8, size 0x2 - unsigned short rtime; // offset 0xA, size 0x2 - long ascale; // offset 0xC, size 0x4 - long dscale; // offset 0x10, size 0x4 + 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 } dls; struct { // total size: 0x8 - unsigned short atime; // offset 0x0, size 0x2 - unsigned short dtime; // offset 0x2, size 0x2 - unsigned short slevel; // offset 0x4, size 0x2 - unsigned short rtime; // offset 0x6, size 0x2 + u16 atime; // offset 0x0, size 0x2 + u16 dtime; // offset 0x2, size 0x2 + u16 slevel; // offset 0x4, size 0x2 + u16 rtime; // offset 0x6, size 0x2 } linear; } data; // offset 0x0, size 0x14 } ADSR_INFO; @@ -870,22 +870,25 @@ 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 hwSetPitch(u32 v, u16 speed); void hwEnableIrq(); void hwDisableIrq(); void* hwTransAddr(void* samples); void seqInit(); /* extern */ -unsigned long seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, - SND_PLAYPARA* para, u8 studio, u16 sgid); -unsigned long seqGetPrivateId(unsigned long seqId); +u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para, + u8 studio, u16 sgid); +u32 seqGetPrivateId(u32 seqId); void streamInit(); /* extern */ void vsInit(); /* extern */ void hwExit(); void dataExit(); void s3dInit(s32); /* extern */ -void s3dKillEmitterByFXID(FX_TAB* fxTab, unsigned long num); +void s3dKillEmitterByFXID(FX_TAB* fxTab, u32 num); void s3dExit(); void synthInit(u32, u8); /* extern */ +void synthSetBpm(u32 pbm, u8 set, u8 section); void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src); void synthSetMusicVolumeType(u8 vGroup, u8 type); @@ -895,7 +898,7 @@ extern u8 voiceMusicRunning; extern u8 voiceFxRunning; extern u8 voiceListInsert; extern u8 voiceListRoot; -void voiceSetPriority(struct SYNTH_VOICE* svoice, unsigned char prio); +void voiceSetPriority(struct SYNTH_VOICE* svoice, u8 prio); u32 voiceIsLastStarted(struct SYNTH_VOICE* svoice); s32 voiceKillSound(u32 voiceid); @@ -909,13 +912,19 @@ void* sndBSearch(void* key, void* base, s32 num, s32 len, SND_COMPARE cmp); void sndConvertMs(u32* time); void sndConvertTicks(u32* out, SYNTH_VOICE* svoice); u32 sndConvert2Ms(u32 time); -void hwActivateStudio(unsigned char studio, unsigned long isMaster, SND_STUDIO_TYPE type); +u32 sndStreamAllocLength(u32 num, u32 flags); +void sndStreamFree(u32 stid); +u32 sndStreamActivate(u32 stid); +void sndStreamDeactivate(u32 stid); + +void hwActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type); void hwDeactivateStudio(u8); -void hwSetPriority(unsigned long v, unsigned long prio); +void hwSetPriority(u32 v, u32 prio); u32 hwIsActive(u32); u32 hwGlobalActivity(); -void hwSetAUXProcessingCallbacks(unsigned char studio, SND_AUX_CALLBACK auxA, void* userA, +void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA, SND_AUX_CALLBACK auxB, void* userB); +u8 hwInitStream(u32 len); s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index); u32 sndGetPitch(u8 key, u32 sInfo); @@ -944,7 +953,7 @@ void salInitHRTFBuffer(); void salActivateVoice(DSPvoice* dsp_vptr, u8 studio); void salDeactivateVoice(DSPvoice* dsp_vptr); void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type); -void salDeactivateStudio(unsigned char studio); +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); @@ -959,38 +968,75 @@ extern u8 salNumVoices; /* Stream */ 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_; - u32 x8_; - u8 xc_; - char data2[0x10 - 0xd]; - SND_STREAM_UPDATE_CALLBACK updateCb; - char data3[0x4C - 0x14]; - SND_VOICEID voiceId; - void* user; - char data4[0x64 - 0x54]; -} SND_STREAM_INFO; +typedef struct SNDADPCMinfo { + // total size: 0x28 + u16 numCoef; // offset 0x0, size 0x2 + u8 initialPS; // offset 0x2, size 0x1 + u8 loopPS; // offset 0x3, size 0x1 + s16 loopY0; // offset 0x4, size 0x2 + s16 loopY1; // offset 0x6, size 0x2 + s16 coefTab[8][2]; // offset 0x8, size 0x20 +} SNDADPCMinfo; + +typedef struct STREAM_INFO { +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) + u32 nextStreamHandle; +#endif + u32 stid; + u32 flags; + u8 state; + u8 type; +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) + u8 hwStreamHandle; + u8 lastPSFromBuffer; +#endif + SND_STREAM_UPDATE_CALLBACK updateFunction; + s16* buffer; + u32 size; + u32 bytes; + u32 last; + SNDADPCMinfo adpcmInfo; + volatile SND_VOICEID voice; + u32 user; + u32 frq; + u8 prio; + u8 vol; + u8 pan; + u8 span; + u8 auxa; + u8 auxb; + +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) + u8 orgPan; + u8 orgSPan; +#endif + + u8 studio; + /* These were moved to near the start of the structure in later versions */ +#if MUSY_VERSION <= MUSY_VERSION_CHECK(1, 5, 3) + u8 hwStreamHandle; + u32 nextStreamHandle; +#endif +} STREAM_INFO; void streamOutputModeChanged(); -u8 inpTranslateExCtrl(unsigned char ctrl); +u8 inpTranslateExCtrl(u8 ctrl); void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag); -void inpAddCtrl(struct CTRL_DEST* dest, unsigned char ctrl, long scale, unsigned char comb, - unsigned long isVar); -void inpSetExCtrl(SYNTH_VOICE* svoice, unsigned char ctrl, signed short v); -CHANNEL_DEFAULTS* inpGetChannelDefaults(unsigned char midi, unsigned char midiSet); +void inpAddCtrl(struct CTRL_DEST* dest, u8 ctrl, long scale, u8 comb, u32 isVar); +void inpSetExCtrl(SYNTH_VOICE* svoice, u8 ctrl, s16 v); +CHANNEL_DEFAULTS* inpGetChannelDefaults(u8 midi, u8 midiSet); extern CTRL_DEST inpAuxA[8][4]; extern CTRL_DEST inpAuxB[8][4]; void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key); u8 inpGetMidiLastNote(u8 midi, u8 midiSet); -unsigned short inpGetExCtrl(SYNTH_VOICE* svoice, unsigned char ctrl); -unsigned short inpGetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set); -void inpSetMidiLastNote(unsigned char midi, unsigned char midiSet, unsigned char key); +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); /* TODO: Figure out what `unk` is */ void hwSetSRCType(u32 v, u8 salSRCType); void hwSetITDMode(u32 v, u8 mode); -void hwSetPolyPhaseFilter(unsigned long v, unsigned char salCoefSel); +void hwSetPolyPhaseFilter(u32 v, u8 salCoefSel); bool hwAddInput(u8 studio, SND_STUDIO_INPUT* in_desc); bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc); void hwChangeStudio(u32 v, u8 studio); @@ -1005,19 +1051,15 @@ extern u8 dspScale2IndexTab[1024]; typedef void* (*ARAMUploadCallback)(u32, u32); -u32 aramGetStreamBufferAddress(unsigned char id, unsigned long* len); -void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned long highPrio, - void (*callback)(unsigned long), unsigned long user); +u32 aramGetStreamBufferAddress(u8 id, u32* len); +void aramUploadData(void* mram, u32 aram, u32 len, u32 highPrio, void (*callback)(u32), u32 user); void aramFreeStreamBuffer(u8 id); -void* aramStoreData(void* src, unsigned long len); -void aramRemoveData(void* aram, unsigned long len); - -unsigned long macStart(unsigned short macid, unsigned char priority, unsigned char maxVoices, - unsigned short allocId, unsigned char key, unsigned char vol, - unsigned char panning, unsigned char midi, unsigned char midiSet, - unsigned char section, unsigned short step, unsigned short trackid, - unsigned char new_vid, unsigned char vGroup, unsigned char studio, - unsigned long itd); +void* aramStoreData(void* src, u32 len); +void aramRemoveData(void* aram, u32 len); +u8 aramAllocateStreamBuffer(u32 len); +u32 macStart(u16 macid, u8 priority, u8 maxVoices, u16 allocId, u8 key, u8 vol, u8 panning, u8 midi, + u8 midiSet, u8 section, u16 step, u16 trackid, u8 new_vid, u8 vGroup, u8 studio, + u32 itd); void macMakeInactive(SYNTH_VOICE* svoice, MAC_STATE); void sndProfUpdateMisc(SND_PROFILE_INFO* info); diff --git a/include/musyx/seq.h b/include/musyx/seq.h index c1c8baf0..016f717d 100644 --- a/include/musyx/seq.h +++ b/include/musyx/seq.h @@ -7,6 +7,160 @@ extern "C" { #endif +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 +} ARR; + +typedef struct TENTRY { + // total size: 0xC + u32 time; // offset 0x0, size 0x4 + u8 prgChange; // offset 0x4, size 0x1 + u8 velocity; // offset 0x5, size 0x1 + u8 res[2]; // offset 0x6, size 0x2 + u16 pattern; // offset 0x8, size 0x2 + s8 transpose; // offset 0xA, size 0x1 + s8 velocityAdd; // offset 0xB, size 0x1 +} TENTRY; + +typedef struct TRACK { + // total size: 0x8 + struct TENTRY* base; // offset 0x0, size 0x4 + struct TENTRY* addr; // offset 0x4, size 0x4 +} TRACK; + +typedef struct NOTE { + // total size: 0x14 + struct NOTE* next; // offset 0x0, size 0x4 + struct NOTE* prev; // offset 0x4, size 0x4 + u32 id; // offset 0x8, size 0x4 + s32 endTime; // offset 0xC, size 0x4 + u8 section; // offset 0x10, size 0x1 + u8 timeIndex; // offset 0x11, size 0x1 + u8 reserved[2]; // offset 0x12, size 0x2 +} NOTE; + +typedef struct NOTE_DATA { + // total size: 0x6 + u16 time; // offset 0x0, size 0x2 + u8 key; // offset 0x2, size 0x1 + u8 velocity; // offset 0x3, size 0x1 + u16 length; // offset 0x4, size 0x2 +} NOTE_DATA; + +typedef struct PRG_STATE { + // total size: 0x4 + u16 macId; // offset 0x0, size 0x2 + u8 priority; // offset 0x2, size 0x1 + u8 maxVoices; // offset 0x3, size 0x1 +} PRG_STATE; + +typedef struct SEQ_STREAM { + // total size: 0xC + u8* nextAddr; // offset 0x0, size 0x4 + u16 value; // offset 0x4, size 0x2 + s16 nextDelta; // offset 0x6, size 0x2 + u32 nextTime; // offset 0x8, size 0x4 +} SEQ_STREAM; + +typedef struct CPAT { + // total size: 0x2C + u32 lTime; // offset 0x0, size 0x4 + u32 baseTime; // offset 0x4, size 0x4 + NOTE_DATA* addr; // offset 0x8, size 0x4 + TENTRY* patternInfo; // offset 0xC, size 0x4 + SEQ_STREAM pitchBend; // offset 0x10, size 0xC + SEQ_STREAM modulation; // offset 0x1C, size 0xC + u8 midi; // offset 0x28, size 0x1 +} CPAT; + +typedef struct SEQ_EVENT { + // total size: 0x18 + struct SEQ_EVENT* next; // offset 0x0, size 0x4 + struct SEQ_EVENT* prev; // offset 0x4, size 0x4 + u32 time; // offset 0x8, size 0x4 + union evInfo { + TENTRY* trackAddr; + struct { + // total size: 0x8 + NOTE_DATA* addr; // offset 0x0, size 0x4 + CPAT* base; // offset 0x4, size 0x4 + } pattern; + } info; // offset 0xC, size 0x8 + u8 type; // offset 0x14, size 0x1 + u8 trackId; // offset 0x15, size 0x1 +} SEQ_EVENT; + +typedef struct MTRACK_DATA { + // total size: 0x8 + u32 time; // offset 0x0, size 0x4 + u32 bpm; // offset 0x4, size 0x4 +} MTRACK_DATA; + +typedef struct MTRACK { + // total size: 0x8 + MTRACK_DATA* base; // offset 0x0, size 0x4 + MTRACK_DATA* addr; // offset 0x4, size 0x4 +} MTRACK; + +typedef struct TICKS { + // total size: 0x8 + u32 low; // offset 0x0, size 0x4 + long high; // offset 0x4, size 0x4 +} TICKS; + +typedef struct SEQ_SECTION { + // total size: 0x38 + struct 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 + TICKS time[2]; // offset 0x20, size 0x10 + u8 timeIndex; // offset 0x30, size 0x1 + u16 speed; // offset 0x32, size 0x2 + u16 loopCnt; // offset 0x34, size 0x2 + u8 loopDisable; // offset 0x36, size 0x1 +} SEQ_SECTION; + +typedef struct SEQ_INSTANCE { + // total size: 0x1868 + struct SEQ_INSTANCE* next; // offset 0x0, size 0x4 + struct SEQ_INSTANCE* prev; // offset 0x4, size 0x4 + u8 state; // offset 0x8, size 0x1 + u8 index; // offset 0x9, size 0x1 + u16 groupID; // offset 0xA, size 0x2 + u32 publicId; // offset 0xC, size 0x4 + PAGE* normtab; // offset 0x10, size 0x4 + u8 normTrans[128]; // offset 0x14, size 0x80 + PAGE* drumtab; // offset 0x94, size 0x4 + u8 drumTrans[128]; // offset 0x98, size 0x80 + ARR* arrbase; // offset 0x118, size 0x4 + u32 trackMute[2]; // offset 0x11C, size 0x8 + TRACK track[64]; // offset 0x124, size 0x200 + u8 trackVolGroup[64]; // offset 0x324, size 0x40 + CPAT pattern[64]; // offset 0x364, size 0xB00 + NOTE* noteUsed[2]; // offset 0xE64, size 0x8 + NOTE* noteKeyOff; // offset 0xE6C, size 0x4 + PRG_STATE prgState[16]; // offset 0xE70, size 0x40 + u8 defVGroup; // offset 0xEB0, size 0x1 + SND_CROSSFADE syncCrossInfo; // offset 0xEB4, size 0x28 + u32* syncSeqIdPtr; // offset 0xEDC, size 0x4 + u8 syncActive; // offset 0xEE0, size 0x1 + u8 defStudio; // offset 0xEE1, size 0x1 + u8 keyOffCheck; // offset 0xEE2, size 0x1 + SEQ_EVENT event[64]; // offset 0xEE4, size 0x600 + u8* trackSectionTab; // offset 0x14E4, size 0x4 + SEQ_SECTION section[16]; // offset 0x14E8, size 0x380 +} SEQ_INSTANCE; + +extern u8 synthTrackVolume[64]; +extern SEQ_INSTANCE seqInstance[8]; extern u16 seqMIDIPriority[8][16]; void sndSeqStop(s32 unk); @@ -14,6 +168,7 @@ void sndSeqSpeed(s32 unk1, s32 unk2); void sndSeqContinue(s32 unk); void sndSeqMute(s32 unk1, s32 unk2, s32 unk3); void sndSeqVolume(s32 unk1, s32 unk2, s32 unk3, s32 unk4); +void seqStop(unsigned long seqId); u16 seqGetMIDIPriority(s32 unk1, s32 unk2); #ifdef __cplusplus diff --git a/include/musyx/synth.h b/include/musyx/synth.h index 0d10a830..f08fb666 100644 --- a/include/musyx/synth.h +++ b/include/musyx/synth.h @@ -23,7 +23,8 @@ bool synthFXSetCtrl(SND_VOICEID vid, u8 ctrl, u8 value); bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value); bool synthSendKeyOff(SND_VOICEID vid); SND_VOICEID synthFXStart(SND_FXID fid, u8 vol, u8 pan, u8 studio, u8); -void synthVolume(u8 volume, u16 time, u8 volgroup2, s32, s32); +void synthVolume(unsigned char volume, unsigned short time, unsigned char vGroup, + unsigned char seqMode, unsigned long seqId); /* TODO: Move this where it belongs */ void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA, diff --git a/libc/math.h b/libc/math.h index fe3442cc..5dec523f 100644 --- a/libc/math.h +++ b/libc/math.h @@ -88,6 +88,7 @@ double ldexp(double x, int exp); double copysign(double x, double y); double floor(double x); +float floorf(float x) { return floor(x); } double fabs(double x); double pow(double x, double y); diff --git a/src/Dolphin/GBA/GBA.c b/src/Dolphin/GBA/GBA.c index d0016b95..c55e03fd 100644 --- a/src/Dolphin/GBA/GBA.c +++ b/src/Dolphin/GBA/GBA.c @@ -1,17 +1,54 @@ +/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +*/ #include "dolphin/GBAPriv.h" -static GBASecParams SecParams[4]; +static GBASecParam SecParams[4]; GBAControl __GBA[4]; BOOL __GBAReset = FALSE; static BOOL OnReset(BOOL); -static OSResetFunctionInfo ResetFunctionInfo = { - OnReset, - 127 -}; +static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127}; -void ShortCommandProc(s32 chan) { +static void ShortCommandProc(s32 chan) { GBAControl* gba; gba = &__GBA[chan]; @@ -27,6 +64,19 @@ void ShortCommandProc(s32 chan) { gba->status[0] = gba->input[2] & GBA_JSTAT_MASK; } +/* + + + + + + + + + + +*/ + void GBAInit() { GBAControl* gba; s32 chan; @@ -37,16 +87,37 @@ void GBAInit() { OSInitThreadQueue(&gba->threadQueue); gba->param = &SecParams[chan]; - // ASSERTMSG((u32) gba->param % 32 == 0) - } - + ASSERT((u32) gba->param % 32 == 0); + } OSInitAlarm(); - DSPInit(); - __GBAReset = FALSE; + DSPInit(); + + __GBAReset = FALSE; OSRegisterResetFunction(&ResetFunctionInfo); } +/* + + + + + + + + + + + + + + + + + + + +*/ s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) { GBAControl* gba; gba = &__GBA[chan]; @@ -59,43 +130,89 @@ s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) { gba->callback = callback; return __GBATransfer(chan, 1, 3, ShortCommandProc); } +/* - +*/ s32 GBAGetStatus(s32 chan, u8* status) { GBAControl* gba = &__GBA[chan]; + + // s32 ret = GBAGetStatusAsync(chan, status, __GBASyncCallback); - return ret != GBA_READY ? ret : __GBASync(chan); -} + if (ret != GBA_READY) { - -s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback) { - GBAControl* gba; - s32 ret; - gba = &__GBA[chan]; - if (gba->callback != NULL) { - ret = GBA_BUSY; - } else { - gba->output[0] = 0xFF; - gba->status = status; - gba->callback = callback; - ret = __GBATransfer(chan, 1, 3, ShortCommandProc); + return ret; } - - return ret; + return __GBASync(chan); } +/* + + + + + + + + + + + + + + + + + + + + + + + + + + +*/ +s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback) { + GBAControl* gba = &__GBA[chan]; + s32 ret; + if (gba->callback != NULL) { + + return GBA_BUSY; + } + gba->output[0] = 0xFF; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 1, 3, ShortCommandProc); +} +/* +*/ s32 GBAReset(s32 chan, u8* status) { + GBAControl* gba = &__GBA[chan]; s32 ret; ret = GBAResetAsync(chan, status, __GBASyncCallback); if (ret != GBA_READY) { + return ret; } - return __GBASync(chan); } +/* + + + + + + + + + + + +*/ BOOL OnReset(BOOL) { __GBAReset = TRUE; return TRUE; diff --git a/src/Dolphin/GBA/GBAGetProcessStatus.c b/src/Dolphin/GBA/GBAGetProcessStatus.c index df8ea7cf..6b8f98b4 100644 --- a/src/Dolphin/GBA/GBAGetProcessStatus.c +++ b/src/Dolphin/GBA/GBAGetProcessStatus.c @@ -1,14 +1,71 @@ +/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +*/ #include "dolphin/GBAPriv.h" -s32 GBAGetProcessStatus(s32 chan, u8* percentp) { - BOOL enabled; - s32 ret; // r29 - GBAControl * gba; // r25 - GBABootInfo * bootInfo; // r31 - u8 percent; // r30 - OSTime t; // r27 +/* + + + + + + + + + +*/ +s32 GBAGetProcessStatus(s32 chan, u8* percentp) { + BOOL enabled; + s32 ret; // r29 + GBAControl* gba = &__GBA[chan]; // r25 + GBABootInfo* bootInfo; // r31 + u8 percent; // r30 + OSTime t; // r27 - gba = &__GBA[chan]; bootInfo = &gba->bootInfo; enabled = OSDisableInterrupts(); @@ -17,9 +74,12 @@ s32 GBAGetProcessStatus(s32 chan, u8* percentp) { percent = (bootInfo->curOffset * 100) / bootInfo->realLength; if (bootInfo->begin != 0) { t = OSGetTime(); + if (OSTicksToMilliseconds(t - bootInfo->begin) < (5500)) { + percent = ((t - bootInfo->begin) * percent) / OSMillisecondsToTicks((OSTime)5500); + } - if (t - bootInfo->begin < OSMillisecondsToTicks(5500)) { - percentp = 0; + if (percent >= 100) { + percent = 100; } } @@ -27,9 +87,9 @@ s32 GBAGetProcessStatus(s32 chan, u8* percentp) { *percentp = percent; } } else if (gba->callback != NULL) { - ret = 2; + ret = 2; } else { - ret = 0; + ret = 0; } OSRestoreInterrupts(enabled); diff --git a/src/Dolphin/GBA/GBAJoyBoot.c b/src/Dolphin/GBA/GBAJoyBoot.c index 3cf26f50..5c8724dd 100644 --- a/src/Dolphin/GBA/GBAJoyBoot.c +++ b/src/Dolphin/GBA/GBAJoyBoot.c @@ -17,22 +17,24 @@ static void F37(s32 chan, s32 ret); static void F39(s32 chan, s32 ret); static u32 F72(u32 crc, u32 src, vu8* keyp) { - int i; - int poly; - + int i; // r31 + int poly = + (keyp[0x13] << 8) + ((keyp[0x15] + (keyp[0x18] - (keyp[0x18] << 4))) - keyp[0x10]); // r30 for (i = keyp[1]; i > keyp[11]; --i) { - if ((src ^ crc) & 1 != 0) { - crc = (crc >> 1) ^ ((keyp[19] * 256 + keyp[21] + keyp[24] + keyp[24] * -16) - keyp[16]); + if ((src ^ crc) & 1) { + crc >>= 1; + crc ^= poly; } else { crc >>= 1; } + src >>= 1; } } u32 F95(u32 src, vu8* keyp) { - return src * ((keyp[3] << keyp[0x16]) | keyp[1] | (keyp[4] << keyp[0x11]) | - (keyp[4] << keyp[0x18])) - + return src * ((keyp[4] << keyp[0x11]) | keyp[1] | (keyp[4] << keyp[0x18]) | + (keyp[3] << keyp[0x16])) - (keyp[7] - keyp[6]); } @@ -52,36 +54,35 @@ static void F104(s32 chan, s32 ret) { s32 GBAJoyBootAsync(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status, GBACallback callback) { int ret; - GBABootInfo* bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; u8 percent; - bootInfo = &__GBA[chan].bootInfo; if (chan & ~3) { - ret = GBA_JOYBOOT_ERR_INVALID; + return GBA_JOYBOOT_ERR_INVALID; } else if (length == 0 || GBA_JOYBOOT_PROGRAM_SIZE_MAX < length) { - ret = GBA_JOYBOOT_ERR_INVALID; + return GBA_JOYBOOT_ERR_INVALID; } else if (paletteSpeed < -4 || paletteSpeed > 4) { - ret = GBA_JOYBOOT_ERR_INVALID; + return GBA_JOYBOOT_ERR_INVALID; } else if (paletteColor < 0 || paletteColor > 6) { - ret = GBA_JOYBOOT_ERR_INVALID; + return GBA_JOYBOOT_ERR_INVALID; } else if (programp[0xac] * programp[0xad] * programp[0xae] * programp[0xaf] == 0) { - ret = GBA_JOYBOOT_ERR_INVALID; - } else { - ret = GBAGetProcessStatus(chan, &percent); - if (ret != 0) { - return ret; - } + return GBA_JOYBOOT_ERR_INVALID; + } - bootInfo->paletteColor = paletteColor; - bootInfo->paletteSpeed = paletteSpeed; - bootInfo->programp = programp; - bootInfo->length = length; - bootInfo->status = status; - bootInfo->callback = callback; - bootInfo->curOffset = D54[8]; - ret = GBAGetStatusAsync(chan, bootInfo->status, F23); - if (ret != GBA_READY) { - bootInfo->callback = NULL; - } + ret = GBAGetProcessStatus(chan, &percent); + if (ret != 0) { + return ret; + } + + bootInfo->paletteColor = paletteColor; + bootInfo->paletteSpeed = paletteSpeed; + bootInfo->programp = programp; + bootInfo->length = length; + bootInfo->status = status; + bootInfo->callback = callback; + bootInfo->curOffset = D54[8]; + ret = GBAGetStatusAsync(chan, bootInfo->status, F23); + if (ret != GBA_READY) { + bootInfo->callback = NULL; } return ret; @@ -91,7 +92,7 @@ static void F23(s32 chan, s32 ret) { GBABootInfo* bootInfo; gba = &__GBA[chan]; - bootInfo = &gba->bootInfo; + bootInfo = &__GBA[chan].bootInfo; if (ret != GBA_READY || (ret = GBAResetAsync(chan, bootInfo->status, F25)) != GBA_READY) { F104(chan, ret); @@ -102,7 +103,7 @@ static void F23(s32 chan, s32 ret) { static void F25(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY && *bootInfo->status != D54[37]) { ret = GBA_JOYBOOT_UNKNOWN_STATE; @@ -117,7 +118,7 @@ static void F25(s32 chan, s32 ret) { static void F27(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY && *bootInfo->status != D54[0]) { ret = GBA_JOYBOOT_UNKNOWN_STATE; @@ -132,7 +133,7 @@ static void F27(s32 chan, s32 ret) { static void F29(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY) { __GBAX02(chan, bootInfo->readbuf); @@ -144,7 +145,7 @@ static void F29(s32 chan, s32 ret) { } void __GBAX01(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; int val200; if (ret == GBA_READY) { @@ -184,11 +185,9 @@ void __GBAX01(s32 chan, s32 ret) { } static void F31(s32 chan, s32 ret) { - GBAControl* gba; - GBABootInfo* bootInfo; + GBAControl* gba = &__GBA[chan]; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; u32 writeWord; - gba = &__GBA[chan]; - bootInfo = &gba->bootInfo; if (ret == GBA_READY) { if (bootInfo->firstXfer != FALSE) { @@ -232,10 +231,11 @@ static void F31(s32 chan, s32 ret) { writeWord = bootInfo->crc | (bootInfo->curOffset << 16); } - if (D54[43] < bootInfo->curOffset) { + if (bootInfo->curOffset > D54[43]) { bootInfo->keyA = F95(bootInfo->keyA, &D54[20]); - writeWord ^= bootInfo->keyA ^ -(bootInfo->curOffset + D54[11] * 0x100000) ^ - ((D54[18] << 8) | (D54[19] << 16) | (D54[11] << 24) | D54[11]); + writeWord ^= bootInfo->keyA; + writeWord ^= -(bootInfo->curOffset + D54[11] * 0x100000); + writeWord ^= (D54[11] | (D54[11] << 24)) | (D54[19] << 16) | (D54[18] << 8); } bootInfo->writebuf[3] = (writeWord >> D54[0]); @@ -248,7 +248,13 @@ static void F31(s32 chan, s32 ret) { } if (bootInfo->i < D54[33]) { - bootInfo->dummyWord[bootInfo->i] = writeWord; + bootInfo->dummyWord[3 - (1 - bootInfo->i)] = writeWord; + bootInfo->dummyWord[5 - bootInfo->i] = + bootInfo->dummyWord[(2 - (1 - bootInfo->i))] * bootInfo->dummyWord[4 - bootInfo->i]; + bootInfo->dummyWord[5 - (1 - bootInfo->i)] = + bootInfo->dummyWord[((1 - bootInfo->i))] * bootInfo->dummyWord[1 - (1 - bootInfo->i)]; + bootInfo->dummyWord[7 - bootInfo->i] = + bootInfo->dummyWord[(-(1 - bootInfo->i))] * bootInfo->dummyWord[4 - bootInfo->i]; } ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31); @@ -266,7 +272,7 @@ exit: } static void F33(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY) { for (bootInfo->i = 33; bootInfo->i < 36; ++bootInfo->i) { @@ -297,7 +303,7 @@ static void F33(s32 chan, s32 ret) { } static void F35(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == 0) { if (OSSecondsToTicks(10) <= OSGetTick() - bootInfo->start) { @@ -322,7 +328,7 @@ static void F35(s32 chan, s32 ret) { static void F37(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY) { if ((((bootInfo->readbuf[3] ^ (bootInfo->initialCode >> 24)) | @@ -344,7 +350,7 @@ static void F37(s32 chan, s32 ret) { static void F39(s32 chan, s32 ret) { GBAControl* gba = &__GBA[chan]; - GBABootInfo* bootInfo = &gba->bootInfo; + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; if (ret == GBA_READY) { *bootInfo->status = 0; @@ -354,13 +360,12 @@ static void F39(s32 chan, s32 ret) { gba->ret = ret; } -s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, unsigned char* programp, s32 length, - unsigned char* status) { +s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status) { s32 ret = GBAJoyBootAsync(chan, paletteColor, paletteSpeed, programp, length, status, __GBASyncCallback); - if (ret == GBA_READY) { - ret = __GBASync(chan); + if (ret != GBA_READY) { + return ret; } - return ret; + return __GBASync(chan); } diff --git a/src/Dolphin/GBA/GBAKey.c b/src/Dolphin/GBA/GBAKey.c new file mode 100644 index 00000000..35fd4bf2 --- /dev/null +++ b/src/Dolphin/GBA/GBAKey.c @@ -0,0 +1,116 @@ +#include "dolphin/GBAPriv.h" + +static volatile u8 D35[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 2, 255, 0, 33, 19, 6, 18, 3, 18, 4, + 19, 5, 0, 146, 0, 255, 0, 136, 255, 255, 0, 137, 255, 255, 0, 138, 255, 255, 0, + 139, 255, 255, 143, 0, 139, 0, 140, 0, 2, 191, 128, 126, 22, 252, 220, 209, 22, 253, + 0, 0, 22, 251, 0, 1, 2, 191, 128, 120, 36, 255, 2, 128, 171, 186, 2, 148, 0, + 41, 142, 0, 2, 191, 128, 120, 32, 255, 2, 64, 15, 255, 31, 94, 0, 155, 0, 0, + 0, 153, 0, 32, 0, 135, 0, 0, 0, 128, 0, 65, 2, 159, 128, 188, 2, 191, 0, + 140, 2, 191, 128, 126, 22, 252, 220, 209, 22, 253, 0, 3, 22, 251, 0, 1, 143, 0, + 2, 191, 128, 120, 2, 128, 205, 209, 2, 148, 0, 76, 38, 255, 2, 128, 0, 1, 2, + 149, 0, 94, 2, 128, 0, 2, 2, 149, 128, 0, 2, 159, 0, 76, 0, 33, 142, 0, + 2, 191, 128, 120, 36, 255, 2, 191, 128, 120, 36, 255, 2, 191, 128, 120, 36, 255, 2, + 191, 128, 120, 0, 197, 255, 255, 2, 64, 15, 255, 28, 158, 2, 191, 128, 120, 0, 199, + 255, 255, 2, 191, 128, 120, 0, 198, 255, 255, 2, 191, 128, 120, 0, 192, 255, 255, 2, + 191, 128, 120, 32, 255, 2, 64, 15, 255, 31, 94, 2, 191, 128, 120, 33, 255, 2, 191, + 128, 120, 35, 255, 18, 5, 18, 6, 2, 159, 128, 181, 0, 33, 129, 0, 0, 129, 0, + 16, 16, 32, 27, 62, 0, 223, 20, 86, 3, 64, 255, 208, 132, 23, 0, 128, 0, 0, + 0, 134, 0, 0, 0, 130, 0, 31, 0, 222, 21, 246, 20, 8, 0, 223, 23, 102, 3, + 64, 0, 255, 31, 95, 2, 191, 136, 229, 31, 28, 129, 30, 25, 30, 20, 120, 31, 252, + 31, 94, 2, 191, 136, 9, 2, 191, 135, 35, 0, 6, 129, 6, 0, 222, 22, 108, 20, + 4, 2, 64, 255, 0, 0, 223, 18, 49, 21, 120, 3, 64, 0, 255, 31, 95, 2, 191, + 136, 229, 31, 28, 129, 30, 25, 30, 20, 120, 31, 252, 31, 94, 2, 191, 136, 9, 2, + 191, 135, 35, 129, 0, 137, 0, 0, 209, 0, 5, 153, 0, 130, 0, 2, 149, 0, 229, + 2, 145, 0, 243, 0, 130, 0, 16, 0, 134, 0, 1, 0, 208, 23, 27, 145, 0, 125, + 0, 77, 0, 21, 1, 31, 95, 0, 223, 0, 3, 21, 4, 2, 191, 136, 9, 2, 159, + 1, 2, 0, 130, 0, 17, 0, 223, 0, 3, 21, 1, 31, 95, 0, 222, 16, 67, 2, + 64, 255, 240, 2, 191, 136, 229, 2, 159, 1, 2, 0, 130, 0, 16, 0, 134, 0, 1, + 0, 208, 18, 133, 145, 0, 77, 0, 21, 1, 0, 222, 0, 3, 20, 4, 31, 94, 2, + 191, 136, 9, 0, 131, 0, 19, 27, 126, 137, 35, 0, 131, 0, 19, 0, 223, 0, 7, + 0, 222, 17, 184, 2, 64, 255, 240, 31, 94, 2, 191, 129, 244, 241, 0, 2, 191, 132, + 88, 143, 0, 0, 130, 0, 21, 0, 222, 0, 6, 0, 218, 22, 91, 2, 191, 136, 229, + 20, 253, 20, 3, 27, 94, 27, 92, 0, 130, 0, 22, 0, 222, 23, 35, 20, 244, 0, + 218, 22, 107, 2, 191, 136, 229, 177, 0, 2, 144, 1, 46, 129, 0, 20, 253, 142, 0, + 0, 223, 20, 145, 3, 64, 208, 240, 28, 191, 0, 223, 20, 104, 0, 209, 17, 252, 21, + 124, 28, 223, 0, 209, 17, 184, 153, 0, 20, 24, 20, 120, 31, 94, 31, 254, 31, 101, + 54, 0, 20, 2, 31, 102, 55, 0, 21, 1, 76, 0, 21, 24, 153, 0, 53, 0, 76, + 0, 0, 223, 0, 18, 63, 0, 0, 255, 0, 18, 20, 112, 0, 223, 0, 17, 63, 0, + 0, 255, 0, 17, 31, 165, 21, 1, 31, 230, 241, 0, 21, 248, 245, 0, 31, 95, 31, + 125, 129, 0, 0, 222, 0, 17, 52, 0, 137, 0, 0, 223, 0, 18, 53, 0, 76, 0, + 0, 223, 0, 18, 21, 120, 76, 0, 137, 0, 31, 254, 21, 8, 59, 0, 0, 222, 0, + 17, 62, 0, 0, 223, 0, 18, 59, 0, 28, 191, 0, 218, 21, 241, 53, 0, 2, 149, + 1, 146, 0, 223, 16, 226, 21, 8, 31, 95, 0, 223, 16, 59, 121, 0, 57, 0, 48, + 128, 0, 254, 0, 34, 0, 220, 18, 41, 0, 221, 17, 248, 92, 0, 240, 0, 31, 229, + 48, 128, 2, 159, 1, 165, 0, 223, 16, 202, 21, 8, 31, 95, 0, 223, 16, 67, 117, + 0, 57, 0, 48, 128, 0, 254, 0, 34, 0, 220, 18, 89, 0, 221, 22, 254, 76, 0, + 240, 0, 31, 229, 48, 128, 0, 254, 0, 35, 0, 218, 0, 8, 0, 216, 0, 9, 0, + 155, 0, 32, 0, 153, 0, 8, 0, 135, 0, 0, 2, 191, 128, 139, 2, 223, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static s32 F152(DSPTaskInfo* task) { + s32 chan; // r31 + GBAControl* gba; // r29 + + for (chan = 0; chan < 4; ++chan) { + gba = &__GBA[chan]; + if (&gba->task == task) { + return chan; + } + } + + ASSERT(0 <= chan && chan < 4); + OSPanic(__FILE__, 169, "GBA - unexpected dsp call"); + return -1; +} + +static void F23(void* task) { + s32 chan; // r31 + GBAControl* gba; // r30 + chan = F152(task); + gba = &__GBA[chan]; + DSPSendMailToDSP(0xabba0000); + while (DSPCheckMailToDSP()) + ; + DSPSendMailToDSP((u32)gba->param); + while (DSPCheckMailToDSP()) + ; +} + +void F25(void* task) { + s32 chan; // r31 + chan = F152(task); + __GBAX01(chan, 0); +} + +void __GBAX02(s32 chan, u8* readbuf) { + GBAControl* gba; // r28 + GBABootInfo* bootInfo; // r29 + GBASecParam* param; // r30 + DSPTaskInfo* task; // r31 + + gba = &__GBA[chan]; + bootInfo = &__GBA[chan].bootInfo; + param = gba->param; + memcpy(param, readbuf, 4); + param->paletteColor = bootInfo->paletteColor; + param->paletteSpeed = bootInfo->paletteSpeed; + param->length = bootInfo->length; + param->out = ¶m->keyA; + DCInvalidateRange(¶m->keyA, 32); + DCFlushRange(param, 32); + task = &gba->task; + task->priority = 255; + task->iram_mmem_addr = (u16*)OSCachedToPhysical(D35); + task->iram_length = sizeof(D35); + task->iram_addr = 0; + task->dsp_init_vector = 16; + task->init_cb = F23; + task->res_cb = NULL; + task->done_cb = F25; + task->req_cb = NULL; + DSPAddTask(task); +} diff --git a/src/Dolphin/GBA/GBARead.c b/src/Dolphin/GBA/GBARead.c index cb0431a7..f43a2b99 100644 --- a/src/Dolphin/GBA/GBARead.c +++ b/src/Dolphin/GBA/GBARead.c @@ -1,6 +1,6 @@ #include "dolphin/GBAPriv.h" -void ReadProc(s32 chan) { +static void ReadProc(s32 chan) { GBAControl* gba; gba = &__GBA[chan]; @@ -12,26 +12,24 @@ void ReadProc(s32 chan) { s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) { GBAControl* gba; - s32 ret; gba = &__GBA[chan]; if (gba->callback != NULL) { - ret = 2; - } else { - gba->output[0] = 0x14; - gba->ptr = dst; - gba->status = status; - gba->callback = callback; - ret = __GBATransfer(chan, 1, 5, ReadProc); + return 2; } - return ret; -} + gba->output[0] = 0x14; + gba->ptr = dst; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 1, 5, ReadProc); +} s32 GBARead(s32 chan, u8* dst, u8* status) { s32 tmp; + GBAControl* gba = &__GBA[chan]; s32 ret; ret = GBAReadAsync(chan, dst, status, __GBASyncCallback); if (ret != GBA_READY) { diff --git a/src/Dolphin/GBA/GBAWrite.c b/src/Dolphin/GBA/GBAWrite.c index a4bc9c75..de8aab2b 100644 --- a/src/Dolphin/GBA/GBAWrite.c +++ b/src/Dolphin/GBA/GBAWrite.c @@ -1,6 +1,6 @@ #include "dolphin/GBAPriv.h" -void WriteProc(s32 chan) { +static void WriteProc(s32 chan) { GBAControl* gba; gba = &__GBA[chan]; @@ -12,28 +12,23 @@ void WriteProc(s32 chan) { } s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) { - GBAControl* gba; - s32 ret; - gba = &__GBA[chan]; + GBAControl* gba = &__GBA[chan]; if (gba->callback != NULL) { - ret = GBA_BUSY; - } else { - gba->output[0] = 0x15; - memcpy(&gba->output[1], src, 4); - gba->ptr = src; - gba->status = status; - gba->callback = callback; - ret = __GBATransfer(chan, 5, 1, WriteProc); + return GBA_BUSY; } - - return ret; + gba->output[0] = 0x15; + memcpy(&gba->output[1], src, 4); + gba->ptr = src; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 5, 1, WriteProc); } - s32 GBAWrite(s32 chan, u8* src, u8* status) { - s32 ret; s32 tmp; + GBAControl* gba = &__GBA[chan]; + s32 ret; ret = GBAWriteAsync(chan, src, status, __GBASyncCallback); if (ret != GBA_READY) { return ret; diff --git a/src/Dolphin/GBA/GBAXfer.c b/src/Dolphin/GBA/GBAXfer.c index d6e0b212..0cef6c93 100644 --- a/src/Dolphin/GBA/GBAXfer.c +++ b/src/Dolphin/GBA/GBAXfer.c @@ -1,12 +1,12 @@ #include "dolphin/GBAPriv.h" #include "dolphin/sipriv.h" -void __GBAHandler(s32 chan, u32 error, OSContext* context) { +static void __GBAHandler(s32 chan, u32 error, OSContext* context) { GBAControl* gba; GBATransferCallback proc; GBACallback callback; OSContext exceptionContext; - + gba = &__GBA[chan]; if (__GBAReset != 0) { return; @@ -37,12 +37,15 @@ void __GBAHandler(s32 chan, u32 error, OSContext* context) { OSSetCurrentContext(context); } -void __GBASyncCallback(s32 chan, s32 ret) { OSWakeupThread(&__GBA[chan].threadQueue); } +void __GBASyncCallback(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; + OSWakeupThread(&gba->threadQueue); +} s32 __GBASync(s32 chan) { GBAControl* gba; - s32 enabled; s32 ret; + s32 enabled; gba = &__GBA[chan]; enabled = OSDisableInterrupts(); @@ -57,40 +60,42 @@ s32 __GBASync(s32 chan) { } void TypeAndStatusCallback(s32 chan, u32 type) { - s32 tmp; GBAControl* gba; - OSContext* context; + GBATransferCallback proc; GBACallback callback; - GBATransferCallback xferCallback; - OSContext tmpContext; + OSContext exceptionContext; + OSContext* context; + gba = &__GBA[chan]; if (__GBAReset != 0) { return; } + ASSERT(!(type & SI_ERROR_BUSY)); if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) { gba->ret = GBA_NOT_READY; } else { - if (SITransfer(chan, gba->output, gba->outputBytes, gba->input, gba->inputBytes, __GBAHandler, gba->delay)) { + if (SITransfer(chan, gba->output, gba->outputBytes, gba->input, gba->inputBytes, __GBAHandler, + gba->delay)) { return; } gba->ret = GBA_BUSY; } if (gba->proc != NULL) { - xferCallback = gba->proc; + proc = gba->proc; gba->proc = NULL; - xferCallback(chan); + proc(chan); } if (gba->callback != NULL) { context = OSGetCurrentContext(); - OSClearContext(&tmpContext); - OSSetCurrentContext(&tmpContext); + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); callback = gba->callback; gba->callback = NULL; callback(chan, gba->ret); - OSClearContext(&tmpContext); + OSClearContext(&exceptionContext); OSSetCurrentContext(context); __OSReschedule(); } diff --git a/src/musyx/runtime/hardware.c b/src/musyx/runtime/hardware.c index 05ffd9ba..069a509d 100644 --- a/src/musyx/runtime/hardware.c +++ b/src/musyx/runtime/hardware.c @@ -423,7 +423,7 @@ void hwFlushStream(void* base, unsigned long offset, unsigned long bytes, unsign } void hwPrepareStreamBuffer() {} -u32 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); } +u8 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); } void hwExitStream(u8 id) { aramFreeStreamBuffer(id); } diff --git a/src/musyx/runtime/seq.c b/src/musyx/runtime/seq.c new file mode 100644 index 00000000..e452695d --- /dev/null +++ b/src/musyx/runtime/seq.c @@ -0,0 +1,670 @@ +#include "musyx/seq.h" +#include "musyx/synth.h" + +static NOTE seqNote[256]; +SEQ_INSTANCE seqInstance[8]; +u16 seqMIDIPriority[8][16]; + +static SEQ_INSTANCE* cseq = NULL; +static NOTE* noteFree = NULL; +static u32 curSeqId = 0; +static u8 curFadeOutState = 0; +static u32 seq_next_id = 0; +struct SEQ_INSTANCE* seqFreeRoot = NULL; +struct SEQ_INSTANCE* seqActiveRoot = NULL; +struct SEQ_INSTANCE* seqPausedRoot = NULL; + +static void ClearNotes() { + NOTE* ln = NULL; // r30 + s32 i; // r29 + + noteFree = &seqNote[0]; + for (i = 0; i < 256; ++i) { + seqNote[i].prev = ln; + if (ln != NULL) { + ln->next = &seqNote[i]; + } + ln = &seqNote[i]; + } + + ln->next = NULL; +} + +static void ResetNotes(SEQ_INSTANCE* seq) { + NOTE* n; // r31 + u32 i; // r30 + for (i = 0; i < 2; ++i) { + n = seq->noteUsed[i]; + if (n != NULL) { + for (; n->next != NULL; n = n->next) { + } + + if (noteFree != NULL) { + n->next = noteFree; + noteFree->prev = n; + } + + noteFree = seq->noteUsed[i]; + seq->noteUsed[i] = NULL; + } + } + + n = seq->noteKeyOff; + + if (n != NULL) { + for (; n->next != NULL; n = n->next) { + } + + if (noteFree != NULL) { + n->next = noteFree; + noteFree->prev = n; + } + + noteFree = seq->noteKeyOff; + seq->noteKeyOff = NULL; + } +} + +static void KillNotes(SEQ_INSTANCE* seq) { + NOTE* n; // r31 + u32 i; // r30 + + for (i = 0; i < 2; ++i) { + for (n = seq->noteUsed[i]; n != NULL; n = n->next) { + voiceKillSound(n->id); + } + } + + for (n = seq->noteKeyOff; n != NULL; n = n->next) { + voiceKillSound(n->id); + } +} + +static NOTE* AllocateNote(u32 endTime, u8 section) { + NOTE* n; // r31 + NOTE* nl; // r30 + NOTE* last_nl; // r29 + if ((n = noteFree) != NULL) { + if ((noteFree = n->next) != NULL) { + noteFree->prev = NULL; + } + + n->endTime = endTime; + n->section = section; + n->timeIndex = cseq->section[section].timeIndex; + last_nl = NULL; + for (nl = cseq->noteUsed[n->timeIndex]; nl != NULL; nl = nl->next) { + if (nl->endTime > n->endTime) { + n->next = nl; + n->prev = last_nl; + if (last_nl != NULL) { + last_nl->next = n; + } else { + cseq->noteUsed[n->timeIndex] = n; + } + + nl->prev = n; + return n; + } + + last_nl = nl; + } + n->prev = last_nl; + + if (last_nl != NULL) { + last_nl->next = n; + } else { + cseq->noteUsed[n->timeIndex] = n; + } + + n->next = NULL; + } + + return n; +} + +static void FreeNote(struct NOTE* n) { + if (n->next != NULL) { + n->next->prev = n->prev; + } + + if (n->prev != NULL) { + n->prev->next = n->next; + } else { + cseq->noteUsed[n->timeIndex] = n->next; + } + + if ((n->next = noteFree) != NULL) { + noteFree->prev = n; + } + + n->prev = NULL; + noteFree = n; +} + +static u32 HandleNotes() { + NOTE* note; // r31 + u32 i; // r30 + + for (i = 0; i < 2; ++i) { + note = cseq->noteUsed[i]; + if (note != NULL) { + while (note->endTime <= cseq->section[note->section].time[i].high) { + synthSendKeyOff(note->id); + + if ((cseq->noteUsed[i] = note->next) != NULL) { + cseq->noteUsed[i]->prev = NULL; + } + + if ((note->next = cseq->noteKeyOff) != NULL) { + cseq->noteKeyOff->prev = note; + } + cseq->noteKeyOff = note; + note = cseq->noteUsed[i]; + + if (note == NULL) { + break; + } + } + } + } + + return cseq->noteUsed[0] != NULL || cseq->noteUsed[1] != NULL; +} + +static void KeyOffNotes() { + NOTE* note; // r31 + NOTE* nextNote; // r29 + u32 i; // r30 + + for (i = 0; i < 2; ++i) { + note = cseq->noteUsed[i]; + + while (note != NULL) { + nextNote = note->next; + synthSendKeyOff(note->id); + if ((cseq->noteUsed[i] = note->next) != NULL) { + cseq->noteUsed[i]->prev = NULL; + } + + if ((note->next = cseq->noteKeyOff) != NULL) { + cseq->noteKeyOff->prev = note; + } + cseq->noteKeyOff = note; + note = nextNote; + } + } +} + +static void seqFreeKeyOffNote(NOTE* n) { + if (n->next != NULL) { + n->next->prev = n->prev; + } + + if (n->prev != NULL) { + n->prev->next = n->next; + } else { + cseq->noteKeyOff = n->next; + } + + if ((n->next = noteFree) != NULL) { + noteFree->prev = n; + } + + n->prev = NULL; + noteFree = n; +} + +static void HandleKeyOffNotes() { + NOTE* n; // r31 + NOTE* nn; // r30 + if (!cseq->keyOffCheck) { + n = cseq->noteKeyOff; + while (n != NULL) { + nn = n->next; + if (n->id != -1 && sndFXCheck(n->id) == -1) { + seqFreeKeyOffNote(n); + } + + n = nn; + } + } + + cseq->keyOffCheck = (cseq->keyOffCheck + 1) % 5; +} + +static void InitPublicIds() { seq_next_id = 0; } + +static u32 GetPublicId(u32 seqId) { + u32 pub_id; // r30 + SEQ_INSTANCE* si; // r31 + si = &seqInstance[seqId]; +} + +u32 seqGetPrivateId(u32 seqId) { + SEQ_INSTANCE* si; // r31 +} + +static void DoPrgChange(SEQ_INSTANCE* seq, u8 prg, u8 midi) { + seqMIDIPriority[curSeqId][midi] = 0xFFFF; + if (midi != 9) { + prg = seq->normTrans[prg]; + if (prg == 0xFF) { + return; + } + + seq->prgState[midi].macId = seq->normtab[prg].macro; + seq->prgState[midi].priority = seq->normtab[prg].prio; + seq->prgState[midi].maxVoices = seq->normtab[prg].maxVoices; + return; + } + + prg = seq->drumTrans[prg]; + if (prg == 0xFF) { + return; + } + + seq->prgState[midi].macId = seq->drumtab[prg].macro; + seq->prgState[midi].priority = seq->drumtab[prg].prio; + seq->prgState[midi].maxVoices = seq->drumtab[prg].maxVoices; +} + +static void BuildTransTab(u8* tab, PAGE* page) { + u8 i; // r31 + + for (i = 0; i < 128; ++i) { + tab[i] = 0xff; + } + + for (i = 0; page->index != 0xFF; ++i, ++page) { + tab[page->index] = i; + } +} + +u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para, + u8 studio, u16 sgid) { + ARR* arr; // r27 + u32* tracktab; // r24 + s32 i; // r31 + SEQ_INSTANCE* nseq; // r30 + SEQ_INSTANCE* oldCSeq; // r23 + u32 seqId; // r28 + u32 bpm; // r25 + + if ((nseq = seqFreeRoot) == NULL) { + return -1; + }; + if ((seqFreeRoot = seqFreeRoot->next) != NULL) { + seqFreeRoot->prev = NULL; + } + + if ((nseq->next = seqActiveRoot) != NULL) { + seqActiveRoot->prev = nseq; + } + nseq->prev = NULL; + seqActiveRoot = nseq; + nseq->state = 1; + for (i = 0; i < 16; ++i) { + nseq->section[i].globalEventRoot = NULL; + } + + seqId = nseq->index; + nseq->syncActive = FALSE; + nseq->normtab = norm; + nseq->drumtab = drum; + nseq->arrbase = (ARR*)song; + nseq->groupID = sgid; + BuildTransTab(nseq->normTrans, nseq->normtab); + BuildTransTab(nseq->drumTrans, nseq->drumtab); + nseq->defVGroup = seqId + 23; + for (i = 0; i < 64; ++i) { + nseq->trackVolGroup[i] = nseq->defVGroup; + } + + nseq->defStudio = studio; + if (para == NULL) { + nseq->trackMute[0] = -1; + nseq->trackMute[1] = -1; + for (i = 0; i < 16; ++i) { + nseq->section[i].speed = 256; + } + + synthVolume(127, 0, nseq->defVGroup, 0, -1); + } else { + if (para->flags & SND_PLAYPARA_TRACKMUTE) { + nseq->trackMute[0] = para->trackMute[0]; + nseq->trackMute[1] = para->trackMute[1]; + } else { + nseq->trackMute[0] = -1; + nseq->trackMute[1] = -1; + } + + if (para->flags & SND_PLAYPARA_SPEED) { + for (i = 0; i < 16; ++i) { + nseq->section[i].speed = para->speed; + } + } else { + for (i = 0; i < 16; ++i) { + nseq->section[i].speed = 256; + } + } + + if (para->flags & SND_PLAYPARA_SEQVOLDEF) { + for (i = 0; i < para->numSeqVolDef; ++i) { + nseq->trackVolGroup[para->seqVolDef[i].track] = para->seqVolDef[i].volGroup; + synthSetMusicVolumeType(para->seqVolDef[i].volGroup, 0); + } + } + + if (para->flags & SND_PLAYPARA_VOLUME) { + synthVolume(para->volume.target, para->volume.time, nseq->defVGroup, 0, -1); + + for (i = 0; i < para->numFaded; ++i) { + synthVolume(para->volume.target, para->volume.time, para->faded[i], 0, -1); + } + } + } + + arr = (ARR*)song; + if (arr->info & 0x80000000) { + nseq->trackSectionTab = (u8*)(arr->tsTab + (u32)arr); + } else { + nseq->trackSectionTab = NULL; + } + + bpm = arr->info & 0x0fffffff; + + if (!(arr->info & 0x40000000)) { + bpm <<= 10; + } + + for (i = 0; i < 16; ++i) { + nseq->section[i].bpm = bpm; + 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.addr = nseq->section[i].mTrack.base; + } else { + nseq->section[i].mTrack.base = NULL; + } + + nseq->section[i].loopDisable = FALSE; + nseq->section[i].loopCnt = 0; + } + + tracktab = &arr->tTab; + + for (i = 0; i < 64; ++i) { + synthTrackVolume[i] = 127; + nseq->pattern[i].addr = NULL; + // TODO: Finish + } + return -1; +} + +static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) { + float tickDelta = (float)section->bpm * (float)deltaTime * 0.0000000244140619f; + tickDelta *= section->speed * 0.00390625f; + + section->tickDelta[section->timeIndex].low = fmodf(tickDelta * 65536.f, 65536.f); + section->tickDelta[section->timeIndex].high = floorf(tickDelta); +} + +static void HandleMasterTrack(u8 secIndex) { + SEQ_SECTION* section; // r31 + section = &cseq->section[secIndex]; + + if (section->mTrack.base == NULL) { + return; + } + + while (section->mTrack.addr->time != -1) { + if (section->mTrack.addr->time > section->time[section->timeIndex].high) { + break; + } + + if (cseq->arrbase->info & 0x40000000) { + synthSetBpm((section->bpm = section->mTrack.addr->bpm) >> 10, curSeqId, secIndex); + } else { + synthSetBpm(section->mTrack.addr->bpm, curSeqId, secIndex); + section->bpm = section->mTrack.addr->bpm << 10; + } + + ++section->mTrack.addr; + } +} + +static void RewindMTrack(unsigned char secIndex, unsigned long deltaTime) { + if (cseq->section[secIndex].mTrack.base == NULL) { + return; + } + cseq->section[secIndex].mTrack.addr = cseq->section[secIndex].mTrack.base; + HandleMasterTrack(secIndex); + SetTickDelta(cseq->section + secIndex, deltaTime); +} + +static void StartPause(SEQ_INSTANCE* si) { + if (si->prev != NULL) { + si->prev->next = si->next; + } else { + seqActiveRoot = si->next; + } + + if (si->next != NULL) { + si->next->prev = si->prev; + } + + if ((si->next = seqPausedRoot) != NULL) { + seqPausedRoot->prev = si; + } + + si->prev = NULL; + seqPausedRoot = si; + si->state = 2; +} + +void seqPause(u32 seqId) { + SEQ_INSTANCE* si; // r31 + seqId = seqGetPrivateId(seqId); + + if (seqId == -1) { + return; + } + + if (!(seqId & 0x80000000)) { + si = &seqInstance[seqId]; + if (si->state == 1) { + StartPause(si); + KillNotes(si); + ResetNotes(si); + } + } else { + si = &seqInstance[seqId & 0x7fffffff]; + if (si->state != 0) { + si->syncCrossInfo.flags |= 8; + } + } +} + +void seqStop(unsigned long seqId) { + SEQ_INSTANCE* si; // r31 + ; + + if ((seqId = seqGetPrivateId(seqId)) == -1) { + return; + } + + if (!(seqId & 0x80000000)) { + si = &seqInstance[seqId]; + switch (si->state) { + case 1: + if (si->prev != NULL) { + si->prev->next = si->next; + } else { + seqActiveRoot = si->next; + } + + KillNotes(&seqInstance[seqId]); + ResetNotes(&seqInstance[seqId]); + break; + case 2: + if (si->prev != NULL) { + si->prev->next = si->next; + } else { + seqPausedRoot = si->next; + } + break; + } + + if (si->next != NULL) { + si->next->prev = si->prev; + } + si->state = 0; + if (seqFreeRoot != NULL) { + seqFreeRoot->prev = si; + } + si->next = seqFreeRoot; + si->prev = NULL; + seqFreeRoot = si; + } else { + si = &seqInstance[seqId & 0x7fffffff]; + if (si->state != 0) { + si->syncSeqIdPtr = NULL; + } + } +} + +void seqKillAllInstances() { + SEQ_INSTANCE* si; // r31 + for (si = seqActiveRoot; si != NULL; si = si->next) { + seqStop(si->publicId); + } + + for (si = seqPausedRoot; si != NULL; si = si->next) { + seqStop(si->publicId); + } +} + +void seqKillInstancesByGroupID(unsigned short sgid) { + SEQ_INSTANCE* si; // r31 + + for (si = seqActiveRoot; si != NULL; si = si->next) { + if (si->groupID == sgid) { + seqStop(si->publicId); + } + } + for (si = seqPausedRoot; si != NULL; si = si->next) { + if (si->groupID == sgid) { + seqStop(si->publicId); + } + } +} + +void seqSpeed(unsigned long seqId, unsigned short speed) { + u32 i; // r30 + + seqId = seqGetPrivateId(seqId); + MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid."); + + if (!(seqId & 0x80000000)) { + for (i = 0; i < 16; ++i) { + seqInstance[seqId].section[i].speed = speed; + } + } else { + seqId &= 0x7FFFFFFF; + seqInstance[seqId].syncCrossInfo.flags |= 0x20; + seqInstance[seqId].syncCrossInfo.speed2 = speed; + } +} + +void seqContinue(u32 seqId) { + struct SEQ_INSTANCE* si; // r31 + + seqId = seqGetPrivateId(seqId); + MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid."); + + if (!(seqId & 0x80000000)) { + si = &seqInstance[seqId]; + + if (si->state == 2) { + if (si->prev != NULL) { + si->prev->next = si->next; + } else { + seqPausedRoot = si->next; + } + + if (si->next != NULL) { + si->next->prev = si->prev; + } + + if ((si->next = seqActiveRoot) != NULL) { + seqActiveRoot->prev = si; + } + + si->prev = NULL; + seqActiveRoot = si; + si->state = 1; + } + } else { + seqInstance[seqId & 0x7FFFFFFF].syncCrossInfo.flags &= ~0x8; + } +} + +void seqMute(unsigned long seqId, unsigned long mask1, unsigned long mask2) { + seqId = seqGetPrivateId(seqId); + if (seqId == 0xffffffff) { + return; + } + + if (!(seqId & 0x80000000)) { + seqInstance[seqId].trackMute[0] = mask1; + seqInstance[seqId].trackMute[1] = mask2; + } else { + seqId &= 0x7fffffff; + seqInstance[seqId].syncCrossInfo.flags |= 0x10; + 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 + pub_id = seqId; + seqId = seqGetPrivateId(seqId); + + if (seqId == -1) { + return; + } + + if (!(seqId & 0x80000000)) { + 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); + } + } + } else { + seqId &= 0x7fffffff; + switch (mode & 0xf) { + case 0: + seqInstance[seqId].syncCrossInfo.vol2 = volume; + break; + case 1: + seqInstance[seqId].syncSeqIdPtr = NULL; + break; + case 2: + seqInstance[seqId].syncCrossInfo.flags |= 8; + seqInstance[seqId].syncCrossInfo.vol2 = volume; + break; + case 3: + seqInstance[seqId].syncCrossInfo.flags |= 0x80; + seqInstance[seqId].syncCrossInfo.vol2 = volume; + break; + default: + MUSY_FATAL("Illegal sequencere fade mode detected."); + break; + } + } +} diff --git a/src/musyx/runtime/stream.c b/src/musyx/runtime/stream.c index b2edcd44..c3db672e 100644 --- a/src/musyx/runtime/stream.c +++ b/src/musyx/runtime/stream.c @@ -1,58 +1,462 @@ #include "musyx/musyx_priv.h" +#include "musyx/synth.h" +#ifndef _DEBUG +#include "dolphin/os.h" +#endif -SND_STREAM_INFO streamInfo[64]; - -u32 nextPublicID = 0; -u8 streamCallDelay = 0; +static STREAM_INFO streamInfo[64]; u8 streamCallCnt = 0; +u8 streamCallDelay = 0; +u32 nextPublicID = 0; void streamInit() { s32 i; streamCallCnt = 0; streamCallDelay = 3; - - for (i = 0; i < synthInfo.voices; ++i) { - streamInfo[i].xc_ = 0; + for (i = 0; i < synthInfo.voiceNum; ++i) { + streamInfo[i].state = 0; } - nextPublicID = 0; } -void SetHWMix(SND_STREAM_INFO* info) { - // hwSetVolume() +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) +void SetHWMix(const STREAM_INFO* si) { + hwSetVolume(si->voice, 0, si->vol * (1 / 127.f), (si->pan << 16), (si->span << 16), + si->auxa * (1 / 127.f), si->auxb * (1 / 127.f)); } +#endif -void streamHandle() {} +void streamHandle() { + u32 i; // r25 + u32 cpos; // r30 + u32 len; // r29 + struct SAMPLE_INFO newsmp; // r1+0x8 + struct STREAM_INFO* si; // r31 + float f; // r63 + // TODO: Match this +} void streamCorrectLoops() {} -void streamKill(SND_STREAMID streamId) { - SND_STREAM_INFO* stream = &streamInfo[streamId]; - - switch (stream->xc_) { +void streamKill(u32 voice) { + STREAM_INFO* si = &streamInfo[voice]; + switch (si->state) { case 1: case 2: - if (stream->xc_ == 2) { - voiceUnblock(stream->voiceId); + if (si->state == 2) { + voiceUnblock(si->voice); } - stream->xc_ = 3; - stream->updateCb(NULL, 0, NULL, 0, stream->user); + si->state = 3; + si->updateFunction(NULL, 0, NULL, 0, (void*)si->user); + break; + default: break; } } -s32 GetPrivateIndex(s32 something) { - s32 i; +static u32 GetPrivateIndex(u32 publicID) { + u32 i; // r31 for (i = 0; i < 64; ++i) { - if (streamInfo[i].xc_ != 0 && something == streamInfo[i].x4_) { + if (streamInfo[i].state != 0 && publicID == streamInfo[i].stid) { return i; } } - return -1; } -void sndStreamARAMUpdate() { - +static u32 GeneratePublicID() { + u32 id; // r30 + u32 i; // r31 + + do { + if ((id = nextPublicID++) == -1) { + id = nextPublicID; + nextPublicID = id + 1; + } + for (i = 0; i < 64; ++i) { + if (streamInfo[i].state != 0 && id == streamInfo[i].stid) { + break; + } + } + } while (i != 64); + + return id; +} + +u32 sndStreamCallbackFrq(u32 msTime) { + s32 time; // r31 + time = ((msTime * 2 + 5) / 10) - 1; + streamCallDelay = time < 0 ? 0 : time; + return (streamCallDelay + 1) * 5; +} + +void sndStreamARAMUpdate(u32 stid, u32 off1, u32 len1, u32 off2, u32 len2) { + u32 i; // r30 + + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + switch (streamInfo[i].type) { + case 0: + off1 *= 2; + len1 *= 2; + off2 *= 2; + len2 *= 2; + break; + case 1: + off1 = (off1 / 14) * 8; + len1 = ((len1 + 13) / 14) * 8; + off2 = (off2 / 14) * 8; + len2 = ((len2 + 13) / 14) * 8; + break; + } + + if (len1 != 0) { + hwFlushStream(streamInfo[i].buffer, off1, len1, streamInfo[i].hwStreamHandle, 0, 0); + } + + if (len2 != 0) { + hwFlushStream(streamInfo[i].buffer, off2, len2, streamInfo[i].hwStreamHandle, 0, 0); + } + +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) + if (streamInfo[i].type == 1) { + streamInfo[i].lastPSFromBuffer = (*(u32*)OSCachedToUncached(streamInfo[i].buffer)) >> 24; + if (streamInfo[i].voice != -1) { + hwSetStreamLoopPS(streamInfo[i].voice, streamInfo[i].lastPSFromBuffer); + } + } +#else + if (streamInfo[i].type == 1) { + hwSetStreamLoopPS(streamInfo[i].voice, *(u32*)OSCachedToUncached(streamInfo[i].buffer) >> 24); + } +#endif + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + hwEnableIrq(); +} + +static void CheckOutputMode(u8* pan, u8* span) { + if (synthFlags & 1) { + *pan = 64; + *span = 0; + } else if (!(synthFlags & 2)) { + *span = 0; + } +} + +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) +static void SetupVolumeAndPan(STREAM_INFO* si, u8 vol, u8 pan, u8 span, u8 auxa, u8 auxb) { + si->orgPan = pan; + si->orgSPan = span; + CheckOutputMode(&pan, &span); + si->vol = vol; + si->pan = pan; + si->span = span; + si->auxa = auxa; + si->auxb = auxb; +} +#endif + +u32 sndStreamAllocEx(u8 prio, void* buffer, u32 samples, u32 frq, u8 vol, u8 pan, u8 span, u8 auxa, + u8 auxb, u8 studio, u32 flags, SND_STREAM_UPDATE_CALLBACK updateFunction, + u32 user, SND_ADPCMSTREAM_INFO* adpcmInfo) { + u32 stid; // r29 + u32 i; // r31 + u32 bytes; // r25 + u32 j; // r28 + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + + for (i = 0; i < 64; ++i) { + if (streamInfo[i].state == 0) { + break; + } + } + + if (i != 64) { + stid = GeneratePublicID(); + streamInfo[i].stid = stid; + streamInfo[i].flags = flags; + bytes = sndStreamAllocLength(samples, flags); + streamInfo[i].buffer = (s16*)buffer; + streamInfo[i].size = samples; + streamInfo[i].bytes = bytes; + streamInfo[i].updateFunction = updateFunction; + streamInfo[i].voice = -1; + if (flags & 1) { + if (adpcmInfo != NULL) { + for (j = 0; j < 8; j++) { + streamInfo[i].adpcmInfo.coefTab[j][0] = adpcmInfo->coefTab[j][0]; + streamInfo[i].adpcmInfo.coefTab[j][1] = adpcmInfo->coefTab[j][1]; + } + streamInfo[i].adpcmInfo.numCoef = 8; + } + streamInfo[i].type = 1; + } else { + streamInfo[i].type = 0; + } + + streamInfo[i].frq = frq; + streamInfo[i].studio = studio; + streamInfo[i].prio = prio; +#if MUSY_VERSION <= MUSY_VERSION_CHECK(1, 5, 3) + CheckOutputMode(&pan, &span); + streamInfo[i].vol = vol; + streamInfo[i].pan = pan; + streamInfo[i].span = span; + streamInfo[i].auxa = auxa; + streamInfo[i].auxb = auxb; +#else + SetupVolumeAndPan(&streamInfo[i], vol, pan, span, auxa, auxb); +#endif + streamInfo[i].user = user; + streamInfo[i].nextStreamHandle = -1; + streamInfo[i].state = 3; + if ((streamInfo[i].hwStreamHandle = hwInitStream(bytes)) != 0xFF) { + if (!(flags & 0x10000) && !sndStreamActivate(stid)) { + MUSY_DEBUG("No voice could be allocated for streaming.\n"); + stid = -1; + } + } else { + MUSY_DEBUG("No ARAM memory could be allocated for streaming.\n"); + stid = -1; + } + if (stid == -1) { + streamInfo[i].state = 0; + } + } else { + stid = -1; + } + + hwEnableIrq(); + + return stid; +} + +u32 sndStreamAllocStereo(u8 prio, void* lBuffer, void* rBuffer, u32 samples, u32 frq, u8 vol, + u8 pan, u8 span, u8 auxa, u8 auxb, u8 studio, u32 flags, + SND_STREAM_UPDATE_CALLBACK updateFunction, u32 lUser, u32 rUser, + SND_ADPCMSTREAM_INFO* adpcmInfoL, SND_ADPCMSTREAM_INFO* adpcmInfoR) { + u32 stid[2]; // r1+0x38 + s16 rPan; // r31 + s16 lPan; // r30 + + lPan = pan - 64; + lPan = lPan < 0 ? 0 : lPan > 127 ? 127 : lPan; + rPan = pan + 64; + rPan = rPan < 0 ? 0 : rPan > 127 ? 127 : rPan; + + hwDisableIrq(); + + ; + if ((stid[0] = sndStreamAllocEx(prio, lBuffer, samples, frq, vol, lPan, span, auxa, auxb, studio, + flags, updateFunction, lUser, adpcmInfoL)) != 0xFFFFFFFF) { + if ((stid[1] = sndStreamAllocEx(prio, rBuffer, samples, frq, vol, rPan, span, auxa, auxb, + studio, flags, updateFunction, rUser, adpcmInfoR)) == + 0xFFFFFFFF) { + sndStreamFree(stid[0]); + hwEnableIrq(); + return 0xFFFFFFFF; + } + + streamInfo[GetPrivateIndex(stid[0])].nextStreamHandle = stid[1]; + } + + hwEnableIrq(); + return stid[0]; +} +u32 sndStreamAllocLength(u32 num, u32 flags) { + if (flags & 1) { + return (((num + 13) / 14) * 8 + 31) & ~31; + } + + return (num * 2 + 31) & ~31; +} + +void sndStreamADPCMParameter(u32 stid, SND_ADPCMSTREAM_INFO* adpcmInfo) { + u32 j; // r31 + u32 i; // r30 + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + for (j = 0; j < 8; ++j) { + streamInfo[i].adpcmInfo.coefTab[j][0] = adpcmInfo->coefTab[j][0]; + streamInfo[i].adpcmInfo.coefTab[j][1] = adpcmInfo->coefTab[j][1]; + } + streamInfo[i].adpcmInfo.numCoef = 8; + if (streamInfo[i].nextStreamHandle != 0xffffffff) { + sndStreamADPCMParameter(streamInfo[i].nextStreamHandle, adpcmInfo); + } + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + hwEnableIrq(); +} + +void sndStreamMixParameter(u32 stid, u8 vol, u8 pan, u8 span, u8 fxvol) { + u32 i; // r31 + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + + if (i != -1) { +#if MUSY_VERSION < MUSY_VERSION_CHECK(1, 5, 4) + CheckOutputMode(&pan, &span); + streamInfo[i].vol = vol; + streamInfo[i].pan = pan; + streamInfo[i].span = span; + streamInfo[i].auxa = fxvol; + streamInfo[i].auxb = 0; + hwSetVolume(streamInfo[i].voice, 0, vol * (1 / 127.f), (pan << 16), (span << 16), + fxvol * (1 / 127.f), 0.f); +#else + SetupVolumeAndPan(&streamInfo[i], vol, pan, span, fxvol, 0); + SetHWMix(&streamInfo[i]); +#endif + + if (streamInfo[i].nextStreamHandle != -1) { + sndStreamMixParameter(streamInfo[i].nextStreamHandle, vol, pan, span, fxvol); + } + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + hwEnableIrq(); +} + +void sndStreamMixParameterEx(u32 stid, u8 vol, u8 pan, u8 span, u8 auxa, u8 auxb) { + u32 i; // r31 + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { +#if MUSY_VERSION <= MUSY_VERSION_CHECK(1, 5, 3) + streamInfo[i].vol = vol; + streamInfo[i].pan = pan; + streamInfo[i].span = span; + streamInfo[i].auxa = fxvol; + streamInfo[i].auxb = 0; + if (streamInfo[i].state == 2) { + hwSetVolume(streamInfo[i].voice, 0, vol * (1 / 127.f), (pan << 16), (span << 16), + auxa * (1 / 127.f), auxb * (1 / 127.f)); + } +#else + SetupVolumeAndPan(&streamInfo[i], vol, pan, span, auxa, auxb); + if (streamInfo[i].state == 2) { + SetHWMix(&streamInfo[i]); + } +#endif + + if (streamInfo[i].nextStreamHandle != -1) { + sndStreamMixParameterEx(streamInfo[i].nextStreamHandle, vol, pan, span, auxa, auxb); + } + + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + hwEnableIrq(); +} + +void sndStreamFrq(u32 stid, u32 frq) { + u32 i; // r31 + u16 pitch; // r27 + + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + streamInfo[i].frq = frq; + if (streamInfo[i].state == 2) { + pitch = (4096.f * frq) / synthInfo.mixFrq; + hwSetPitch(streamInfo[i].voice, pitch); + } + + if (streamInfo[i].nextStreamHandle != -1) { + sndStreamFrq(streamInfo[i].nextStreamHandle, frq); + } + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + + hwEnableIrq(); +} + +void sndStreamFree(u32 stid) { + u32 i; // r31 + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + sndStreamDeactivate(stid); + hwExitStream(streamInfo[i].hwStreamHandle); + if (streamInfo[i].nextStreamHandle != -1) { + sndStreamFree(streamInfo[i].nextStreamHandle); + } + + streamInfo[i].state = 0; + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + + hwEnableIrq(); +} + +u32 sndStreamActivate(u32 stid) { + u32 i; // r31 + u32 ret; // r28 + + ret = 0; + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + if (streamInfo[i].state == 3) { + if ((streamInfo[i].voice = voiceBlock(streamInfo[i].prio)) == -1) { + MUSY_DEBUG("No voice could be allocated for streaming.\n"); + hwEnableIrq(); + return 0; + } + + streamInfo[i].last = 0; + streamInfo[i].state = 1; + } else { + MUSY_DEBUG("Stream is already active.\n"); + } + + if (streamInfo[i].nextStreamHandle != -1) { + ret = sndStreamActivate(streamInfo[i].nextStreamHandle); + } else { + ret = 1; + } + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + hwEnableIrq(); + return ret; +} + +void sndStreamDeactivate(u32 stid) { + u32 i; // r31 + + MUSY_ASSERT_MSG(sndActive, "Sound system is not initialized."); + hwDisableIrq(); + i = GetPrivateIndex(stid); + if (i != -1) { + if (streamInfo[i].state == 1 || streamInfo[i].state == 2) { + voiceUnblock(streamInfo[i].voice); + streamInfo[i].state = 3; + } + + if (streamInfo[i].nextStreamHandle != -1) { + sndStreamDeactivate(streamInfo[i].nextStreamHandle); + } + } else { + MUSY_DEBUG("ID is invalid.\n"); + } + + hwEnableIrq(); } diff --git a/src/musyx/runtime/synthmacros.c b/src/musyx/runtime/synthmacros.c index d4344461..29418a40 100644 --- a/src/musyx/runtime/synthmacros.c +++ b/src/musyx/runtime/synthmacros.c @@ -618,6 +618,7 @@ static void mcmdSetADSRFromCtrl(SYNTH_VOICE* svoice, MSTEP* cstep) { float sScale; // r63 ADSR_INFO adsr; // r1+0x10 } + static void mcmdSetPitchADSR(SYNTH_VOICE* svoice, MSTEP* cstep) { ADSR_INFO adsr; // r1+0x10 ADSR_INFO* adsr_ptr; // r31 @@ -625,6 +626,7 @@ static void mcmdSetPitchADSR(SYNTH_VOICE* svoice, MSTEP* cstep) { s32 ascale; // r27 s32 dscale; // r26 } + static u32 mcmdPitchSweep(SYNTH_VOICE* svoice, MSTEP* cstep, int num) { s32 delta; // r31 svoice->sweepOff[num] = 0; @@ -692,7 +694,7 @@ static u32 TranslateVolume(u32 volume, u16 curve) { if (vhigh < 0x7f) { d = vlow * (ptr[vhigh + 1] - ptr[vhigh]); - volume = d + (ptr[vhigh] << 16); + volume = d + ((u8)ptr[vhigh] << 16); } else { volume = ptr[vhigh] << 16; } @@ -793,6 +795,7 @@ static void mcmdRandomKey(SYNTH_VOICE* svoice, MSTEP* cstep) { s32 i2; // r27 u8 detune; // r26 } + static void mcmdSetPitchbendAfterKeyOff(SYNTH_VOICE* svoice) { svoice->cFlags |= 0x10000; } static void mcmdScaleReverb(SYNTH_VOICE* svoice, MSTEP* cstep) { svoice->revVolScale = (u8)(cstep->para[0] >> 8); @@ -1073,6 +1076,7 @@ static void mcmdGetMessage(SYNTH_VOICE* svoice, MSTEP* cstep) { } varSet32(svoice, 0, (u8)(cstep->para[0] >> 8), mesg); } + static void mcmdGetVID(SYNTH_VOICE* svoice, MSTEP* cstep) { if ((u8)(cstep->para[0] >> 0x10) == 0) { varSet32(svoice, 0, (u8)(cstep->para[0] >> 8), svoice->vidList->vid); diff --git a/src/musyx/runtime/synthvoice.c b/src/musyx/runtime/synthvoice.c index 5013a182..0685ef8e 100644 --- a/src/musyx/runtime/synthvoice.c +++ b/src/musyx/runtime/synthvoice.c @@ -299,9 +299,7 @@ u32 voiceAllocate(u8 priority, u8 maxVoices, u16 allocId, u8 fxFlag) { void voiceFree(SYNTH_VOICE* svoice) { u32 i; // r29 SYNTH_VOICELIST* sfv; // r30 -#line 628 MUSY_ASSERT(svoice->id != 0xFFFFFFFF); -#line 256 macMakeInactive(svoice, MAC_STATE_STOPPED); voiceRemovePriority(svoice); svoice->addr = NULL; @@ -413,11 +411,11 @@ long voiceKillSound(u32 voiceid) { u32 next_voiceid; // r28 u32 i; // r30 if (sndActive != FALSE) { - for (i = vidGetInternalId(voiceid); i != 0xFFFFFFFF; i = next_voiceid) { - voiceid = (u8)i; - next_voiceid = synthVoice[voiceid].child; - if (i == synthVoice[voiceid].id) { - voiceKill(voiceid); + for (voiceid = vidGetInternalId(voiceid); voiceid != -1; voiceid = next_voiceid) { + i = voiceid & 0xff; + next_voiceid = synthVoice[i].child; + if (voiceid == synthVoice[i].id) { + voiceKill(i); ret = 0; } }