Various fixes and matches

This commit is contained in:
Phillip Stephens 2023-03-29 19:27:34 -07:00
parent a5c3f5a97c
commit f75b37e773
23 changed files with 2120 additions and 478 deletions

View File

@ -3,8 +3,8 @@
{ {
"name": "Linux", "name": "Linux",
"includePath": [ "includePath": [
"${workspaceFolder}/include", "${workspaceFolder}/include/**",
"${workspaceFolder}/libc" "${workspaceFolder}/libc/**"
], ],
"cStandard": "c99", "cStandard": "c99",
"cppStandard": "c++98", "cppStandard": "c++98",
@ -21,4 +21,4 @@
} }
], ],
"version": 4 "version": 4
} }

View File

@ -59,7 +59,8 @@
"osfont.h": "c", "osfont.h": "c",
"arq.h": "c", "arq.h": "c",
"string.h": "c", "string.h": "c",
"hw_regs.h": "c" "hw_regs.h": "c",
"synth.h": "c"
}, },
"files.autoSave": "onFocusChange", "files.autoSave": "onFocusChange",
"files.insertFinalNewline": true, "files.insertFinalNewline": true,

View File

@ -925,7 +925,7 @@ LIBS = [
"cflags": "$cflags_musyx -DMUSY_VERSION_MAJOR=1 -DMUSY_VERSION_MINOR=5 -DMUSY_VERSION_PATCH=4", "cflags": "$cflags_musyx -DMUSY_VERSION_MAJOR=1 -DMUSY_VERSION_MINOR=5 -DMUSY_VERSION_PATCH=4",
"host": False, "host": False,
"objects": [ "objects": [
"musyx/runtime/seq", ["musyx/runtime/seq", False],
["musyx/runtime/synth", False], ["musyx/runtime/synth", False],
["musyx/runtime/seq_api", True], ["musyx/runtime/seq_api", True],
["musyx/runtime/snd_synthapi", True, {"add_to_all": False}], ["musyx/runtime/snd_synthapi", True, {"add_to_all": False}],
@ -1034,6 +1034,7 @@ LIBS = [
{ {
"lib": "gba", "lib": "gba",
"mw_version": "1.2.5e", "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", "cflags": "$cflags_base",
"host": False, "host": False,
"objects": [ "objects": [
@ -1043,7 +1044,7 @@ LIBS = [
["Dolphin/GBA/GBARead", True], ["Dolphin/GBA/GBARead", True],
["Dolphin/GBA/GBAWrite", True], ["Dolphin/GBA/GBAWrite", True],
["Dolphin/GBA/GBAXfer", True], ["Dolphin/GBA/GBAXfer", True],
"Dolphin/GBA/GBAKey", ["Dolphin/GBA/GBAKey", True],
], ],
}, },
] ]

View File

@ -13,7 +13,7 @@ extern "C" {
typedef void (*GBATransferCallback)(s32 chan); typedef void (*GBATransferCallback)(s32 chan);
typedef struct GBASecParams { typedef struct GBASecParam {
u8 readbuf[4]; u8 readbuf[4];
s32 paletteColor; s32 paletteColor;
s32 paletteSpeed; s32 paletteSpeed;
@ -23,7 +23,7 @@ typedef struct GBASecParams {
u32 keyA; u32 keyA;
s32 keyB; s32 keyB;
u8 _padding1[24]; u8 _padding1[24];
} GBASecParams; } GBASecParam;
typedef struct GBABootInfo { typedef struct GBABootInfo {
s32 paletteColor; s32 paletteColor;
@ -61,7 +61,7 @@ typedef struct GBAControl {
GBATransferCallback proc; GBATransferCallback proc;
GBABootInfo bootInfo; GBABootInfo bootInfo;
DSPTaskInfo task; DSPTaskInfo task;
GBASecParams* param; GBASecParam* param;
} GBAControl; } GBAControl;
extern GBAControl __GBA[4]; extern GBAControl __GBA[4];

View File

@ -29,12 +29,21 @@ u32 __OSCoreClock AT_ADDRESS(OS_BASE_CACHED | 0x00FC); // sync with OSLoMem.h
#define OS_CORE_CLOCK __OSCoreClock #define OS_CORE_CLOCK __OSCoreClock
#define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4) #define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4)
#ifndef _DEBUG
#define OSPhysicalToCached(paddr) ((void*)((u32)(paddr) + OS_BASE_CACHED)) #define OSPhysicalToCached(paddr) ((void*)((u32)(paddr) + OS_BASE_CACHED))
#define OSPhysicalToUncached(paddr) ((void*)((u32)(paddr) + OS_BASE_UNCACHED)) #define OSPhysicalToUncached(paddr) ((void*)((u32)(paddr) + OS_BASE_UNCACHED))
#define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr)-OS_BASE_CACHED)) #define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr)-OS_BASE_CACHED))
#define OSUncachedToPhysical(ucaddr) ((u32)((u8*)(ucaddr)-OS_BASE_UNCACHED)) #define OSUncachedToPhysical(ucaddr) ((u32)((u8*)(ucaddr)-OS_BASE_UNCACHED))
#define OSCachedToUncached(caddr) ((void*)((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) #define OSCachedToUncached(caddr) ((void*)((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED)))
#define OSUncachedToCached(ucaddr) ((void*)((u8*)(ucaddr) - (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 OSTicksToCycles(ticks) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2)
#define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK) #define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK)

View File

@ -1,30 +1,25 @@
#ifndef _MUSYX_ASSERT #ifndef _MUSYX_ASSERT
#define _MUSYX_ASSERT #define _MUSYX_ASSERT
#include "musyx/version.h"
extern void OSPanic(const char* file, int line, const char* msg, ...); extern void OSPanic(const char* file, int line, const char* msg, ...);
extern void OSReport(const char* msg, ...); extern void OSReport(const char* msg, ...);
static inline unsigned __SOME_ASSERT_DERP1() { static inline unsigned __SOME_ASSERT_DERP1() { return 0; }
return 0;
}
static inline unsigned __SOME_ASSERT_DERP2() { static inline unsigned __SOME_ASSERT_DERP2() { return __SOME_ASSERT_DERP1(); }
return __SOME_ASSERT_DERP1();
}
static inline void __SOME_ASSERT_DERP() { static inline void __SOME_ASSERT_DERP() { __SOME_ASSERT_DERP2() != 0; }
__SOME_ASSERT_DERP2() != 0;
}
#ifndef ASSERT #ifndef ASSERT
#ifdef _DEBUG #ifdef _DEBUG
#define MUSY_ASSERT(cond) \ #define MUSY_ASSERT(cond) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \ OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \
} \ } \
__SOME_ASSERT_DERP(); \ __SOME_ASSERT_DERP(); \
} while(0) } while (0)
#else #else
#define MUSY_ASSERT(cond) #define MUSY_ASSERT(cond)
#endif #endif
@ -32,12 +27,27 @@ static inline void __SOME_ASSERT_DERP() {
#ifndef MUSY_ASSERT_MSG #ifndef MUSY_ASSERT_MSG
#ifdef _DEBUG #ifdef _DEBUG
#define MUSY_ASSERT_MSG(cond, msg) \ #if MUSY_VERSION >= MUSY_VERSION_CHECK(2, 0, 0)
do { \ #define MUSY_ASSERT_MSG(cond, msg) \
if (!(cond)) { \ do { \
OSPanic(__FILE__, __LINE__, msg); \ s32 tmp = 1; \
} \ s32 tmp2; \
} while(0) 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 #else
#define MUSY_ASSERT_MSG(cond, msg) #define MUSY_ASSERT_MSG(cond, msg)
#endif #endif
@ -46,9 +56,17 @@ static inline void __SOME_ASSERT_DERP() {
#ifndef MUSY_DEBUG #ifndef MUSY_DEBUG
#ifdef _DEBUG #ifdef _DEBUG
#define MUSY_DEBUG OSReport #define MUSY_DEBUG OSReport
#else #else
#define MUSY_DEBUG #define MUSY_DEBUG
#endif #endif
#endif #endif
#ifndef MUSY_FATAL
#ifdef _DEBUG
#define MUSY_FATAL(msg) OSPanic(__FILE__, __LINE__, msg)
#else
#define MUSY_FATAL
#endif
#endif
#endif // _MUSYX_ASSERT #endif // _MUSYX_ASSERT

View File

@ -39,6 +39,10 @@ typedef signed long bool;
#define SYNTH_MAX_VOICES 64 #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_SEQID;
typedef u32 SND_VOICEID; typedef u32 SND_VOICEID;
typedef u32 SND_STREAMID; typedef u32 SND_STREAMID;
@ -65,6 +69,13 @@ typedef struct SND_SEQVOLDEF {
u8 volGroup; u8 volGroup;
} SND_SEQVOLDEF; } 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 { typedef struct SND_PLAYPARA {
u32 flags; u32 flags;
u32 trackMute[2]; u32 trackMute[2];
@ -310,6 +321,37 @@ bool sndAuxCallbackPrepareChorus(SND_AUX_CHORUS* ch);
bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch); bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch);
bool sndAuxCallbackUpdateSettingsChorus(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 { typedef struct SND_PROFILE_DATA {
unsigned long loadStores; unsigned long loadStores;
unsigned long missCycles; unsigned long missCycles;

View File

@ -10,10 +10,10 @@ extern "C" {
typedef struct SND_STUDIO_INPUT { typedef struct SND_STUDIO_INPUT {
// total size: 0x4 // total size: 0x4
unsigned char vol; // offset 0x0, size 0x1 u8 vol; // offset 0x0, size 0x1
unsigned char volA; // offset 0x1, size 0x1 u8 volA; // offset 0x1, size 0x1
unsigned char volB; // offset 0x2, size 0x1 u8 volB; // offset 0x2, size 0x1
unsigned char srcStudio; // offset 0x3, size 0x1 u8 srcStudio; // offset 0x3, size 0x1
} SND_STUDIO_INPUT; } SND_STUDIO_INPUT;
typedef struct SYNTH_VOICELIST { typedef struct SYNTH_VOICELIST {
@ -28,8 +28,8 @@ extern SYNTH_VOICELIST voicePrioSortVoices[64];
typedef struct SYNTH_ROOTLIST { typedef struct SYNTH_ROOTLIST {
// total size: 0x4 // total size: 0x4
unsigned short next; // offset 0x0, size 0x2 u16 next; // offset 0x0, size 0x2
unsigned short prev; // offset 0x2, size 0x2 u16 prev; // offset 0x2, size 0x2
} SYNTH_ROOTLIST; } SYNTH_ROOTLIST;
extern SYNTH_ROOTLIST voicePrioSortRootList[256]; extern SYNTH_ROOTLIST voicePrioSortRootList[256];
@ -73,117 +73,117 @@ typedef struct ADSR_VARS {
typedef struct _PBMIX { typedef struct _PBMIX {
// total size: 0x24 // total size: 0x24
unsigned short vL; // offset 0x0, size 0x2 u16 vL; // offset 0x0, size 0x2
unsigned short vDeltaL; // offset 0x2, size 0x2 u16 vDeltaL; // offset 0x2, size 0x2
unsigned short vR; // offset 0x4, size 0x2 u16 vR; // offset 0x4, size 0x2
unsigned short vDeltaR; // offset 0x6, size 0x2 u16 vDeltaR; // offset 0x6, size 0x2
unsigned short vAuxAL; // offset 0x8, size 0x2 u16 vAuxAL; // offset 0x8, size 0x2
unsigned short vDeltaAuxAL; // offset 0xA, size 0x2 u16 vDeltaAuxAL; // offset 0xA, size 0x2
unsigned short vAuxAR; // offset 0xC, size 0x2 u16 vAuxAR; // offset 0xC, size 0x2
unsigned short vDeltaAuxAR; // offset 0xE, size 0x2 u16 vDeltaAuxAR; // offset 0xE, size 0x2
unsigned short vAuxBL; // offset 0x10, size 0x2 u16 vAuxBL; // offset 0x10, size 0x2
unsigned short vDeltaAuxBL; // offset 0x12, size 0x2 u16 vDeltaAuxBL; // offset 0x12, size 0x2
unsigned short vAuxBR; // offset 0x14, size 0x2 u16 vAuxBR; // offset 0x14, size 0x2
unsigned short vDeltaAuxBR; // offset 0x16, size 0x2 u16 vDeltaAuxBR; // offset 0x16, size 0x2
unsigned short vAuxBS; // offset 0x18, size 0x2 u16 vAuxBS; // offset 0x18, size 0x2
unsigned short vDeltaAuxBS; // offset 0x1A, size 0x2 u16 vDeltaAuxBS; // offset 0x1A, size 0x2
unsigned short vS; // offset 0x1C, size 0x2 u16 vS; // offset 0x1C, size 0x2
unsigned short vDeltaS; // offset 0x1E, size 0x2 u16 vDeltaS; // offset 0x1E, size 0x2
unsigned short vAuxAS; // offset 0x20, size 0x2 u16 vAuxAS; // offset 0x20, size 0x2
unsigned short vDeltaAuxAS; // offset 0x22, size 0x2 u16 vDeltaAuxAS; // offset 0x22, size 0x2
} _PBMIX; } _PBMIX;
typedef struct _PBITD { typedef struct _PBITD {
// total size: 0xE // total size: 0xE
unsigned short flag; // offset 0x0, size 0x2 u16 flag; // offset 0x0, size 0x2
unsigned short bufferHi; // offset 0x2, size 0x2 u16 bufferHi; // offset 0x2, size 0x2
unsigned short bufferLo; // offset 0x4, size 0x2 u16 bufferLo; // offset 0x4, size 0x2
unsigned short shiftL; // offset 0x6, size 0x2 u16 shiftL; // offset 0x6, size 0x2
unsigned short shiftR; // offset 0x8, size 0x2 u16 shiftR; // offset 0x8, size 0x2
unsigned short targetShiftL; // offset 0xA, size 0x2 u16 targetShiftL; // offset 0xA, size 0x2
unsigned short targetShiftR; // offset 0xC, size 0x2 u16 targetShiftR; // offset 0xC, size 0x2
} _PBITD; } _PBITD;
typedef struct _PBUPDATE { typedef struct _PBUPDATE {
// total size: 0xE // total size: 0xE
unsigned short updNum[5]; // offset 0x0, size 0xA u16 updNum[5]; // offset 0x0, size 0xA
unsigned short dataHi; // offset 0xA, size 0x2 u16 dataHi; // offset 0xA, size 0x2
unsigned short dataLo; // offset 0xC, size 0x2 u16 dataLo; // offset 0xC, size 0x2
} _PBUPDATE; } _PBUPDATE;
typedef struct _PBDPOP { typedef struct _PBDPOP {
// total size: 0x12 // total size: 0x12
unsigned short aL; // offset 0x0, size 0x2 u16 aL; // offset 0x0, size 0x2
unsigned short aAuxAL; // offset 0x2, size 0x2 u16 aAuxAL; // offset 0x2, size 0x2
unsigned short aAuxBL; // offset 0x4, size 0x2 u16 aAuxBL; // offset 0x4, size 0x2
unsigned short aR; // offset 0x6, size 0x2 u16 aR; // offset 0x6, size 0x2
unsigned short aAuxAR; // offset 0x8, size 0x2 u16 aAuxAR; // offset 0x8, size 0x2
unsigned short aAuxBR; // offset 0xA, size 0x2 u16 aAuxBR; // offset 0xA, size 0x2
unsigned short aS; // offset 0xC, size 0x2 u16 aS; // offset 0xC, size 0x2
unsigned short aAuxAS; // offset 0xE, size 0x2 u16 aAuxAS; // offset 0xE, size 0x2
unsigned short aAuxBS; // offset 0x10, size 0x2 u16 aAuxBS; // offset 0x10, size 0x2
} _PBDPOP; } _PBDPOP;
typedef struct _PBVE { typedef struct _PBVE {
// total size: 0x4 // total size: 0x4
unsigned short currentVolume; // offset 0x0, size 0x2 u16 currentVolume; // offset 0x0, size 0x2
unsigned short currentDelta; // offset 0x2, size 0x2 u16 currentDelta; // offset 0x2, size 0x2
} _PBVE; } _PBVE;
typedef struct _PBFIR { typedef struct _PBFIR {
// total size: 0x6 // total size: 0x6
unsigned short numCoefs; // offset 0x0, size 0x2 u16 numCoefs; // offset 0x0, size 0x2
unsigned short coefsHi; // offset 0x2, size 0x2 u16 coefsHi; // offset 0x2, size 0x2
unsigned short coefsLo; // offset 0x4, size 0x2 u16 coefsLo; // offset 0x4, size 0x2
} _PBFIR; } _PBFIR;
typedef struct _PBADDR { typedef struct _PBADDR {
// total size: 0x10 // total size: 0x10
unsigned short loopFlag; // offset 0x0, size 0x2 u16 loopFlag; // offset 0x0, size 0x2
unsigned short format; // offset 0x2, size 0x2 u16 format; // offset 0x2, size 0x2
unsigned short loopAddressHi; // offset 0x4, size 0x2 u16 loopAddressHi; // offset 0x4, size 0x2
unsigned short loopAddressLo; // offset 0x6, size 0x2 u16 loopAddressLo; // offset 0x6, size 0x2
unsigned short endAddressHi; // offset 0x8, size 0x2 u16 endAddressHi; // offset 0x8, size 0x2
unsigned short endAddressLo; // offset 0xA, size 0x2 u16 endAddressLo; // offset 0xA, size 0x2
unsigned short currentAddressHi; // offset 0xC, size 0x2 u16 currentAddressHi; // offset 0xC, size 0x2
unsigned short currentAddressLo; // offset 0xE, size 0x2 u16 currentAddressLo; // offset 0xE, size 0x2
} _PBADDR; } _PBADDR;
typedef struct _PBADPCM { typedef struct _PBADPCM {
// total size: 0x28 // total size: 0x28
unsigned short a[8][2]; // offset 0x0, size 0x20 u16 a[8][2]; // offset 0x0, size 0x20
unsigned short gain; // offset 0x20, size 0x2 u16 gain; // offset 0x20, size 0x2
unsigned short pred_scale; // offset 0x22, size 0x2 u16 pred_scale; // offset 0x22, size 0x2
unsigned short yn1; // offset 0x24, size 0x2 u16 yn1; // offset 0x24, size 0x2
unsigned short yn2; // offset 0x26, size 0x2 u16 yn2; // offset 0x26, size 0x2
} _PDADPCM; } _PDADPCM;
typedef struct _PBSRC { typedef struct _PBSRC {
// total size: 0xE // total size: 0xE
unsigned short ratioHi; // offset 0x0, size 0x2 u16 ratioHi; // offset 0x0, size 0x2
unsigned short ratioLo; // offset 0x2, size 0x2 u16 ratioLo; // offset 0x2, size 0x2
unsigned short currentAddressFrac; // offset 0x4, size 0x2 u16 currentAddressFrac; // offset 0x4, size 0x2
unsigned short last_samples[4]; // offset 0x6, size 0x8 u16 last_samples[4]; // offset 0x6, size 0x8
} _PBSRC; } _PBSRC;
typedef struct _PBADPCMLOOP { typedef struct _PBADPCMLOOP {
// total size: 0x6 // total size: 0x6
unsigned short loop_pred_scale; // offset 0x0, size 0x2 u16 loop_pred_scale; // offset 0x0, size 0x2
unsigned short loop_yn1; // offset 0x2, size 0x2 u16 loop_yn1; // offset 0x2, size 0x2
unsigned short loop_yn2; // offset 0x4, size 0x2 u16 loop_yn2; // offset 0x4, size 0x2
} _PBADPCMLOOP; } _PBADPCMLOOP;
typedef struct _PB { typedef struct _PB {
// total size: 0xBC // total size: 0xBC
unsigned short nextHi; // offset 0x0, size 0x2 u16 nextHi; // offset 0x0, size 0x2
unsigned short nextLo; // offset 0x2, size 0x2 u16 nextLo; // offset 0x2, size 0x2
unsigned short currHi; // offset 0x4, size 0x2 u16 currHi; // offset 0x4, size 0x2
unsigned short currLo; // offset 0x6, size 0x2 u16 currLo; // offset 0x6, size 0x2
unsigned short srcSelect; // offset 0x8, size 0x2 u16 srcSelect; // offset 0x8, size 0x2
unsigned short coefSelect; // offset 0xA, size 0x2 u16 coefSelect; // offset 0xA, size 0x2
unsigned short mixerCtrl; // offset 0xC, size 0x2 u16 mixerCtrl; // offset 0xC, size 0x2
unsigned short state; // offset 0xE, size 0x2 u16 state; // offset 0xE, size 0x2
unsigned short loopType; // offset 0x10, size 0x2 u16 loopType; // offset 0x10, size 0x2
struct _PBMIX mix; // offset 0x12, size 0x24 struct _PBMIX mix; // offset 0x12, size 0x24
struct _PBITD itd; // offset 0x36, size 0xE struct _PBITD itd; // offset 0x36, size 0xE
struct _PBUPDATE update; // offset 0x44, size 0xE struct _PBUPDATE update; // offset 0x44, size 0xE
@ -194,7 +194,7 @@ typedef struct _PB {
struct _PBADPCM adpcm; // offset 0x7E, size 0x28 struct _PBADPCM adpcm; // offset 0x7E, size 0x28
struct _PBSRC src; // offset 0xA6, size 0xE struct _PBSRC src; // offset 0xA6, size 0xE
struct _PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6 struct _PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6
unsigned short streamLoopCnt; // offset 0xBA, size 0x2 u16 streamLoopCnt; // offset 0xBA, size 0x2
} _PB; } _PB;
typedef struct SAMPLE_INFO { typedef struct SAMPLE_INFO {
@ -211,81 +211,81 @@ typedef struct SAMPLE_INFO {
typedef struct GROUP_DATA { typedef struct GROUP_DATA {
// total size: 0x28 // total size: 0x28
unsigned long nextOff; // offset 0x0, size 0x4 u32 nextOff; // offset 0x0, size 0x4
unsigned short id; // offset 0x4, size 0x2 u16 id; // offset 0x4, size 0x2
unsigned short type; // offset 0x6, size 0x2 u16 type; // offset 0x6, size 0x2
unsigned long macroOff; // offset 0x8, size 0x4 u32 macroOff; // offset 0x8, size 0x4
unsigned long sampleOff; // offset 0xC, size 0x4 u32 sampleOff; // offset 0xC, size 0x4
unsigned long curveOff; // offset 0x10, size 0x4 u32 curveOff; // offset 0x10, size 0x4
unsigned long keymapOff; // offset 0x14, size 0x4 u32 keymapOff; // offset 0x14, size 0x4
unsigned long layerOff; // offset 0x18, size 0x4 u32 layerOff; // offset 0x18, size 0x4
union { union {
struct fx { struct fx {
// total size: 0x4 // total size: 0x4
unsigned long tableOff; // offset 0x0, size 0x4 u32 tableOff; // offset 0x0, size 0x4
} fx; } fx;
struct song { struct song {
// total size: 0xC // total size: 0xC
unsigned long normpageOff; // offset 0x0, size 0x4 u32 normpageOff; // offset 0x0, size 0x4
unsigned long drumpageOff; // offset 0x4, size 0x4 u32 drumpageOff; // offset 0x4, size 0x4
unsigned long midiSetupOff; // offset 0x8, size 0x4 u32 midiSetupOff; // offset 0x8, size 0x4
} song; } song;
} data; // offset 0x1C, size 0xC } data; // offset 0x1C, size 0xC
} GROUP_DATA; } GROUP_DATA;
typedef struct SAMPLE_HEADER { typedef struct SAMPLE_HEADER {
// total size: 0x10 // total size: 0x10
unsigned long info; // offset 0x0, size 0x4 u32 info; // offset 0x0, size 0x4
unsigned long length; // offset 0x4, size 0x4 u32 length; // offset 0x4, size 0x4
unsigned long loopOffset; // offset 0x8, size 0x4 u32 loopOffset; // offset 0x8, size 0x4
unsigned long loopLength; // offset 0xC, size 0x4 u32 loopLength; // offset 0xC, size 0x4
} SAMPLE_HEADER; } SAMPLE_HEADER;
typedef struct SDIR_DATA { typedef struct SDIR_DATA {
// total size: 0x20 // total size: 0x20
unsigned short id; // offset 0x0, size 0x2 u16 id; // offset 0x0, size 0x2
unsigned short ref_cnt; // offset 0x2, size 0x2 u16 ref_cnt; // offset 0x2, size 0x2
unsigned long offset; // offset 0x4, size 0x4 u32 offset; // offset 0x4, size 0x4
void* addr; // offset 0x8, size 0x4 void* addr; // offset 0x8, size 0x4
struct SAMPLE_HEADER header; // offset 0xC, size 0x10 struct SAMPLE_HEADER header; // offset 0xC, size 0x10
unsigned long extraData; // offset 0x1C, size 0x4 u32 extraData; // offset 0x1C, size 0x4
} SDIR_DATA; } SDIR_DATA;
typedef struct SDIR_TAB { typedef struct SDIR_TAB {
// total size: 0xC // total size: 0xC
struct SDIR_DATA* data; // offset 0x0, size 0x4 struct SDIR_DATA* data; // offset 0x0, size 0x4
void* base; // offset 0x4, size 0x4 void* base; // offset 0x4, size 0x4
unsigned short numSmp; // offset 0x8, size 0x2 u16 numSmp; // offset 0x8, size 0x2
unsigned short res; // offset 0xA, size 0x2 u16 res; // offset 0xA, size 0x2
} SDIR_TAB; } SDIR_TAB;
typedef struct DATA_TAB { typedef struct DATA_TAB {
// total size: 0x8 // total size: 0x8
void* data; // offset 0x0, size 0x4 void* data; // offset 0x0, size 0x4
unsigned short id; // offset 0x4, size 0x2 u16 id; // offset 0x4, size 0x2
unsigned short refCount; // offset 0x6, size 0x2 u16 refCount; // offset 0x6, size 0x2
} DATA_TAB; } DATA_TAB;
typedef struct LAYER_TAB { typedef struct LAYER_TAB {
// total size: 0xC // total size: 0xC
void* data; // offset 0x0, size 0x4 void* data; // offset 0x0, size 0x4
unsigned short id; // offset 0x4, size 0x2 u16 id; // offset 0x4, size 0x2
unsigned short num; // offset 0x6, size 0x2 u16 num; // offset 0x6, size 0x2
unsigned short refCount; // offset 0x8, size 0x2 u16 refCount; // offset 0x8, size 0x2
unsigned short reserved; // offset 0xA, size 0x2 u16 reserved; // offset 0xA, size 0x2
} LAYER_TAB; } LAYER_TAB;
typedef struct MAC_MAINTAB { typedef struct MAC_MAINTAB {
// total size: 0x4 // total size: 0x4
unsigned short num; // offset 0x0, size 0x2 u16 num; // offset 0x0, size 0x2
unsigned short subTabIndex; // offset 0x2, size 0x2 u16 subTabIndex; // offset 0x2, size 0x2
} MAC_MAINTAB; } MAC_MAINTAB;
typedef struct MAC_SUBTAB { typedef struct MAC_SUBTAB {
// total size: 0x8 // total size: 0x8
void* data; // offset 0x0, size 0x4 void* data; // offset 0x0, size 0x4
unsigned short id; // offset 0x4, size 0x2 u16 id; // offset 0x4, size 0x2
unsigned short refCount; // offset 0x6, size 0x2 u16 refCount; // offset 0x6, size 0x2
} MAC_SUBTAB; } MAC_SUBTAB;
typedef struct GSTACK { typedef struct GSTACK {
@ -414,19 +414,19 @@ typedef struct SYNTH_LFO {
typedef struct SYNTHMasterFader { typedef struct SYNTHMasterFader {
// total size: 0x30 // total size: 0x30
float volume; // offset 0x0, size 0x4 float volume; // offset 0x0, size 0x4
float target; // offset 0x4, size 0x4 float target; // offset 0x4, size 0x4
float start; // offset 0x8, size 0x4 float start; // offset 0x8, size 0x4
float time; // offset 0xC, size 0x4 float time; // offset 0xC, size 0x4
float deltaTime; // offset 0x10, size 0x4 float deltaTime; // offset 0x10, size 0x4
float pauseVol; // offset 0x14, size 0x4 float pauseVol; // offset 0x14, size 0x4
float pauseTarget; // offset 0x18, size 0x4 float pauseTarget; // offset 0x18, size 0x4
float pauseStart; // offset 0x1C, size 0x4 float pauseStart; // offset 0x1C, size 0x4
float pauseTime; // offset 0x20, size 0x4 float pauseTime; // offset 0x20, size 0x4
float pauseDeltaTime; // offset 0x24, size 0x4 float pauseDeltaTime; // offset 0x24, size 0x4
unsigned long seqId; // offset 0x28, size 0x4 u32 seqId; // offset 0x28, size 0x4
unsigned char seqMode; // offset 0x2C, size 0x1 u8 seqMode; // offset 0x2C, size 0x1
unsigned char type; // offset 0x2D, size 0x1 u8 type; // offset 0x2D, size 0x1
} SYNTHMasterFader; } SYNTHMasterFader;
typedef struct CTRL_SOURCE { typedef struct CTRL_SOURCE {
@ -443,40 +443,40 @@ typedef struct CTRL_DEST {
typedef struct SND_VIRTUALSAMPLE_INFO { typedef struct SND_VIRTUALSAMPLE_INFO {
// total size: 0x14 // total size: 0x14
unsigned short smpID; // offset 0x0, size 0x2 u16 smpID; // offset 0x0, size 0x2
unsigned short instID; // offset 0x2, size 0x2 u16 instID; // offset 0x2, size 0x2
union vsData { union vsData {
struct vsUpdate { struct vsUpdate {
// total size: 0x10 // total size: 0x10
unsigned long off1; // offset 0x0, size 0x4 u32 off1; // offset 0x0, size 0x4
unsigned long len1; // offset 0x4, size 0x4 u32 len1; // offset 0x4, size 0x4
unsigned long off2; // offset 0x8, size 0x4 u32 off2; // offset 0x8, size 0x4
unsigned long len2; // offset 0xC, size 0x4 u32 len2; // offset 0xC, size 0x4
} update; } update;
} data; } data;
} SND_VIRTUALSAMPLE_INFO; } SND_VIRTUALSAMPLE_INFO;
typedef struct VS_BUFFER { typedef struct VS_BUFFER {
// total size: 0x24 // total size: 0x24
unsigned char state; // offset 0x0, size 0x1 u8 state; // offset 0x0, size 0x1
unsigned char hwId; // offset 0x1, size 0x1 u8 hwId; // offset 0x1, size 0x1
unsigned char smpType; // offset 0x2, size 0x1 u8 smpType; // offset 0x2, size 0x1
unsigned char voice; // offset 0x3, size 0x1 u8 voice; // offset 0x3, size 0x1
unsigned long last; // offset 0x4, size 0x4 u32 last; // offset 0x4, size 0x4
unsigned long finalGoodSamples; // offset 0x8, size 0x4 u32 finalGoodSamples; // offset 0x8, size 0x4
unsigned long finalLast; // offset 0xC, size 0x4 u32 finalLast; // offset 0xC, size 0x4
SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14 SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14
} VS_BUFFER; } VS_BUFFER;
typedef struct _VS { typedef struct _VS {
// total size: 0x950 // total size: 0x950
unsigned char numBuffers; // offset 0x0, size 0x1 u8 numBuffers; // offset 0x0, size 0x1
unsigned long bufferLength; // offset 0x4, size 0x4 u32 bufferLength; // offset 0x4, size 0x4
VS_BUFFER streamBuffer[64]; // offset 0x8, size 0x900 VS_BUFFER streamBuffer[64]; // offset 0x8, size 0x900
unsigned char voices[64]; // offset 0x908, size 0x40 u8 voices[64]; // offset 0x908, size 0x40
unsigned short nextInstID; // offset 0x948, size 0x2 u16 nextInstID; // offset 0x948, size 0x2
unsigned long (*callback)(unsigned char, u32 (*callback)(u8,
struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4
} VS; } VS;
extern VS vs; extern VS vs;
@ -611,46 +611,46 @@ typedef struct SYNTH_VOICE {
typedef struct synthITDInfo { typedef struct synthITDInfo {
// total size: 0x2 // total size: 0x2
unsigned char music; // offset 0x0, size 0x1 u8 music; // offset 0x0, size 0x1
unsigned char sfx; // offset 0x1, size 0x1 u8 sfx; // offset 0x1, size 0x1
} synthITDInfo; } synthITDInfo;
#pragma pop #pragma pop
typedef struct LAYER { typedef struct LAYER {
// total size: 0xC // total size: 0xC
unsigned short id; // offset 0x0, size 0x2 u16 id; // offset 0x0, size 0x2
unsigned char keyLow; // offset 0x2, size 0x1 u8 keyLow; // offset 0x2, size 0x1
unsigned char keyHigh; // offset 0x3, size 0x1 u8 keyHigh; // offset 0x3, size 0x1
signed char transpose; // offset 0x4, size 0x1 s8 transpose; // offset 0x4, size 0x1
unsigned char volume; // offset 0x5, size 0x1 u8 volume; // offset 0x5, size 0x1
signed short prioOffset; // offset 0x6, size 0x2 s16 prioOffset; // offset 0x6, size 0x2
unsigned char panning; // offset 0x8, size 0x1 u8 panning; // offset 0x8, size 0x1
unsigned char reserved[3]; // offset 0x9, size 0x3 u8 reserved[3]; // offset 0x9, size 0x3
} LAYER; } LAYER;
typedef struct KEYMAP { typedef struct KEYMAP {
// total size: 0x8 // total size: 0x8
unsigned short id; // offset 0x0, size 0x2 u16 id; // offset 0x0, size 0x2
signed char transpose; // offset 0x2, size 0x1 s8 transpose; // offset 0x2, size 0x1
unsigned char panning; // offset 0x3, size 0x1 u8 panning; // offset 0x3, size 0x1
signed short prioOffset; // offset 0x4, size 0x2 s16 prioOffset; // offset 0x4, size 0x2
unsigned char reserved[2]; // offset 0x6, size 0x2 u8 reserved[2]; // offset 0x6, size 0x2
} KEYMAP; } KEYMAP;
typedef struct MEM_DATA { typedef struct MEM_DATA {
// total size: 0x408 // total size: 0x408
unsigned long nextOff; // offset 0x0, size 0x4 u32 nextOff; // offset 0x0, size 0x4
unsigned short id; // offset 0x4, size 0x2 u16 id; // offset 0x4, size 0x2
unsigned short reserved; // offset 0x6, size 0x2 u16 reserved; // offset 0x6, size 0x2
union { union {
struct { struct {
// total size: 0x10 // total size: 0x10
unsigned long num; // offset 0x0, size 0x4 u32 num; // offset 0x0, size 0x4
LAYER entry[1]; // offset 0x4, size 0xC LAYER entry[1]; // offset 0x4, size 0xC
} layer; } layer;
KEYMAP map[128]; KEYMAP map[128];
unsigned char tab[1]; u8 tab[1];
MSTEP cmd[1][2]; MSTEP cmd[1][2];
} data; // offset 0x8, size 0x400 } data; // offset 0x8, size 0x400
} MEM_DATA; } MEM_DATA;
@ -694,33 +694,33 @@ typedef struct SAL_PANINFO {
typedef struct _SPB { typedef struct _SPB {
// total size: 0x36 // total size: 0x36
unsigned short dpopLHi; // offset 0x0, size 0x2 u16 dpopLHi; // offset 0x0, size 0x2
unsigned short dpopLLo; // offset 0x2, size 0x2 u16 dpopLLo; // offset 0x2, size 0x2
unsigned short dpopLDelta; // offset 0x4, size 0x2 u16 dpopLDelta; // offset 0x4, size 0x2
unsigned short dpopRHi; // offset 0x6, size 0x2 u16 dpopRHi; // offset 0x6, size 0x2
unsigned short dpopRLo; // offset 0x8, size 0x2 u16 dpopRLo; // offset 0x8, size 0x2
unsigned short dpopRDelta; // offset 0xA, size 0x2 u16 dpopRDelta; // offset 0xA, size 0x2
unsigned short dpopSHi; // offset 0xC, size 0x2 u16 dpopSHi; // offset 0xC, size 0x2
unsigned short dpopSLo; // offset 0xE, size 0x2 u16 dpopSLo; // offset 0xE, size 0x2
unsigned short dpopSDelta; // offset 0x10, size 0x2 u16 dpopSDelta; // offset 0x10, size 0x2
unsigned short dpopALHi; // offset 0x12, size 0x2 u16 dpopALHi; // offset 0x12, size 0x2
unsigned short dpopALLo; // offset 0x14, size 0x2 u16 dpopALLo; // offset 0x14, size 0x2
unsigned short dpopALDelta; // offset 0x16, size 0x2 u16 dpopALDelta; // offset 0x16, size 0x2
unsigned short dpopARHi; // offset 0x18, size 0x2 u16 dpopARHi; // offset 0x18, size 0x2
unsigned short dpopARLo; // offset 0x1A, size 0x2 u16 dpopARLo; // offset 0x1A, size 0x2
unsigned short dpopARDelta; // offset 0x1C, size 0x2 u16 dpopARDelta; // offset 0x1C, size 0x2
unsigned short dpopASHi; // offset 0x1E, size 0x2 u16 dpopASHi; // offset 0x1E, size 0x2
unsigned short dpopASLo; // offset 0x20, size 0x2 u16 dpopASLo; // offset 0x20, size 0x2
unsigned short dpopASDelta; // offset 0x22, size 0x2 u16 dpopASDelta; // offset 0x22, size 0x2
unsigned short dpopBLHi; // offset 0x24, size 0x2 u16 dpopBLHi; // offset 0x24, size 0x2
unsigned short dpopBLLo; // offset 0x26, size 0x2 u16 dpopBLLo; // offset 0x26, size 0x2
unsigned short dpopBLDelta; // offset 0x28, size 0x2 u16 dpopBLDelta; // offset 0x28, size 0x2
unsigned short dpopBRHi; // offset 0x2A, size 0x2 u16 dpopBRHi; // offset 0x2A, size 0x2
unsigned short dpopBRLo; // offset 0x2C, size 0x2 u16 dpopBRLo; // offset 0x2C, size 0x2
unsigned short dpopBRDelta; // offset 0x2E, size 0x2 u16 dpopBRDelta; // offset 0x2E, size 0x2
unsigned short dpopBSHi; // offset 0x30, size 0x2 u16 dpopBSHi; // offset 0x30, size 0x2
unsigned short dpopBSLo; // offset 0x32, size 0x2 u16 dpopBSLo; // offset 0x32, size 0x2
unsigned short dpopBSDelta; // offset 0x34, size 0x2 u16 dpopBSDelta; // offset 0x34, size 0x2
} _SPB; } _SPB;
typedef struct DSPhostDPop { typedef struct DSPhostDPop {
@ -738,10 +738,10 @@ typedef struct DSPhostDPop {
typedef struct DSPinput { typedef struct DSPinput {
// total size: 0xC // total size: 0xC
unsigned char studio; // offset 0x0, size 0x1 u8 studio; // offset 0x0, size 0x1
unsigned short vol; // offset 0x2, size 0x2 u16 vol; // offset 0x2, size 0x2
unsigned short volA; // offset 0x4, size 0x2 u16 volA; // offset 0x4, size 0x2
unsigned short volB; // offset 0x6, size 0x2 u16 volB; // offset 0x6, size 0x2
struct SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4 struct SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4
} DSPinput; } DSPinput;
@ -754,9 +754,9 @@ typedef struct DSPstudioinfo {
long* auxB[3]; // offset 0x3C, size 0xC long* auxB[3]; // offset 0x3C, size 0xC
struct DSPvoice* voiceRoot; // offset 0x48, size 0x4 struct DSPvoice* voiceRoot; // offset 0x48, size 0x4
struct DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4 struct DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4
unsigned char state; // offset 0x50, size 0x1 u8 state; // offset 0x50, size 0x1
unsigned char isMaster; // offset 0x51, size 0x1 u8 isMaster; // offset 0x51, size 0x1
unsigned char numInputs; // offset 0x52, size 0x1 u8 numInputs; // offset 0x52, size 0x1
SND_STUDIO_TYPE type; // offset 0x54, size 0x4 SND_STUDIO_TYPE type; // offset 0x54, size 0x4
struct DSPinput in[7]; // offset 0x58, size 0x54 struct DSPinput in[7]; // offset 0x58, size 0x54
SND_AUX_CALLBACK auxAHandler; // offset 0xAC, size 0x4 SND_AUX_CALLBACK auxAHandler; // offset 0xAC, size 0x4
@ -774,50 +774,50 @@ typedef s32 (*SND_COMPARE)(void*, void*);
typedef struct CHANNEL_DEFAULTS { typedef struct CHANNEL_DEFAULTS {
// total size: 0x1 // total size: 0x1
unsigned char pbRange; // offset 0x0, size 0x1 u8 pbRange; // offset 0x0, size 0x1
} CHANNEL_DEFAULTS; } CHANNEL_DEFAULTS;
typedef struct FX_TAB { typedef struct FX_TAB {
// total size: 0xA // total size: 0xA
unsigned short id; // offset 0x0, size 0x2 u16 id; // offset 0x0, size 0x2
unsigned short macro; // offset 0x2, size 0x2 u16 macro; // offset 0x2, size 0x2
unsigned char maxVoices; // offset 0x4, size 0x1 u8 maxVoices; // offset 0x4, size 0x1
unsigned char priority; // offset 0x5, size 0x1 u8 priority; // offset 0x5, size 0x1
unsigned char volume; // offset 0x6, size 0x1 u8 volume; // offset 0x6, size 0x1
unsigned char panning; // offset 0x7, size 0x1 u8 panning; // offset 0x7, size 0x1
unsigned char key; // offset 0x8, size 0x1 u8 key; // offset 0x8, size 0x1
unsigned char vGroup; // offset 0x9, size 0x1 u8 vGroup; // offset 0x9, size 0x1
} FX_TAB; } FX_TAB;
typedef struct FX_DATA { typedef struct FX_DATA {
// total size: 0xE // total size: 0xE
unsigned short num; // offset 0x0, size 0x2 u16 num; // offset 0x0, size 0x2
unsigned short reserverd; // offset 0x2, size 0x2 u16 reserverd; // offset 0x2, size 0x2
struct FX_TAB fx[1]; // offset 0x4, size 0xA struct FX_TAB fx[1]; // offset 0x4, size 0xA
} FX_DATA; } FX_DATA;
typedef struct FX_GROUP { typedef struct FX_GROUP {
// total size: 0x8 // total size: 0x8
unsigned short gid; // offset 0x0, size 0x2 u16 gid; // offset 0x0, size 0x2
unsigned short fxNum; // offset 0x2, size 0x2 u16 fxNum; // offset 0x2, size 0x2
struct FX_TAB* fxTab; // offset 0x4, size 0x4 struct FX_TAB* fxTab; // offset 0x4, size 0x4
} FX_GROUP; } FX_GROUP;
typedef struct PAGE { typedef struct PAGE {
// total size: 0x6 // total size: 0x6
unsigned short macro; // offset 0x0, size 0x2 u16 macro; // offset 0x0, size 0x2
unsigned char prio; // offset 0x2, size 0x1 u8 prio; // offset 0x2, size 0x1
unsigned char maxVoices; // offset 0x3, size 0x1 u8 maxVoices; // offset 0x3, size 0x1
unsigned char index; // offset 0x4, size 0x1 u8 index; // offset 0x4, size 0x1
unsigned char reserved; // offset 0x5, size 0x1 u8 reserved; // offset 0x5, size 0x1
} PAGE; } PAGE;
typedef struct MIDI_CHANNEL_SETUP { typedef struct MIDI_CHANNEL_SETUP {
// total size: 0x5 // total size: 0x5
unsigned char program; // offset 0x0, size 0x1 u8 program; // offset 0x0, size 0x1
unsigned char volume; // offset 0x1, size 0x1 u8 volume; // offset 0x1, size 0x1
unsigned char panning; // offset 0x2, size 0x1 u8 panning; // offset 0x2, size 0x1
unsigned char reverb; // offset 0x3, size 0x1 u8 reverb; // offset 0x3, size 0x1
unsigned char chorus; // offset 0x4, size 0x1 u8 chorus; // offset 0x4, size 0x1
} MIDI_CHANNEL_SETUP; } MIDI_CHANNEL_SETUP;
typedef struct MIDISETUP { typedef struct MIDISETUP {
@ -832,19 +832,19 @@ typedef struct ADSR_INFO {
union ai_data { union ai_data {
struct { struct {
// total size: 0x14 // total size: 0x14
long atime; // offset 0x0, size 0x4 long atime; // offset 0x0, size 0x4
long dtime; // offset 0x4, size 0x4 long dtime; // offset 0x4, size 0x4
unsigned short slevel; // offset 0x8, size 0x2 u16 slevel; // offset 0x8, size 0x2
unsigned short rtime; // offset 0xA, size 0x2 u16 rtime; // offset 0xA, size 0x2
long ascale; // offset 0xC, size 0x4 long ascale; // offset 0xC, size 0x4
long dscale; // offset 0x10, size 0x4 long dscale; // offset 0x10, size 0x4
} dls; } dls;
struct { struct {
// total size: 0x8 // total size: 0x8
unsigned short atime; // offset 0x0, size 0x2 u16 atime; // offset 0x0, size 0x2
unsigned short dtime; // offset 0x2, size 0x2 u16 dtime; // offset 0x2, size 0x2
unsigned short slevel; // offset 0x4, size 0x2 u16 slevel; // offset 0x4, size 0x2
unsigned short rtime; // offset 0x6, size 0x2 u16 rtime; // offset 0x6, size 0x2
} linear; } linear;
} data; // offset 0x0, size 0x14 } data; // offset 0x0, size 0x14
} ADSR_INFO; } ADSR_INFO;
@ -870,22 +870,25 @@ FX_TAB* dataGetFX(u16 fid);
s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */ s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */
void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio, void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio,
u32 callbackUserValue, u32 setSRC, u8 itdMode); 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 hwEnableIrq();
void hwDisableIrq(); void hwDisableIrq();
void* hwTransAddr(void* samples); void* hwTransAddr(void* samples);
void seqInit(); /* extern */ void seqInit(); /* extern */
unsigned long seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para,
SND_PLAYPARA* para, u8 studio, u16 sgid); u8 studio, u16 sgid);
unsigned long seqGetPrivateId(unsigned long seqId); u32 seqGetPrivateId(u32 seqId);
void streamInit(); /* extern */ void streamInit(); /* extern */
void vsInit(); /* extern */ void vsInit(); /* extern */
void hwExit(); void hwExit();
void dataExit(); void dataExit();
void s3dInit(s32); /* extern */ void s3dInit(s32); /* extern */
void s3dKillEmitterByFXID(FX_TAB* fxTab, unsigned long num); void s3dKillEmitterByFXID(FX_TAB* fxTab, u32 num);
void s3dExit(); void s3dExit();
void synthInit(u32, u8); /* extern */ void synthInit(u32, u8); /* extern */
void synthSetBpm(u32 pbm, u8 set, u8 section);
void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src); void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src);
void synthSetMusicVolumeType(u8 vGroup, u8 type); void synthSetMusicVolumeType(u8 vGroup, u8 type);
@ -895,7 +898,7 @@ extern u8 voiceMusicRunning;
extern u8 voiceFxRunning; extern u8 voiceFxRunning;
extern u8 voiceListInsert; extern u8 voiceListInsert;
extern u8 voiceListRoot; 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); u32 voiceIsLastStarted(struct SYNTH_VOICE* svoice);
s32 voiceKillSound(u32 voiceid); 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 sndConvertMs(u32* time);
void sndConvertTicks(u32* out, SYNTH_VOICE* svoice); void sndConvertTicks(u32* out, SYNTH_VOICE* svoice);
u32 sndConvert2Ms(u32 time); 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 hwDeactivateStudio(u8);
void hwSetPriority(unsigned long v, unsigned long prio); void hwSetPriority(u32 v, u32 prio);
u32 hwIsActive(u32); u32 hwIsActive(u32);
u32 hwGlobalActivity(); 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); SND_AUX_CALLBACK auxB, void* userB);
u8 hwInitStream(u32 len);
s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index); s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index);
u32 sndGetPitch(u8 key, u32 sInfo); u32 sndGetPitch(u8 key, u32 sInfo);
@ -944,7 +953,7 @@ void salInitHRTFBuffer();
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio); void salActivateVoice(DSPvoice* dsp_vptr, u8 studio);
void salDeactivateVoice(DSPvoice* dsp_vptr); void salDeactivateVoice(DSPvoice* dsp_vptr);
void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type); 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 salActivateVoice(DSPvoice* dsp_vptr, u8 studio);
void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, float vol, u32 pan, u32 span, float auxa, void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, float vol, u32 pan, u32 span, float auxa,
float auxb, u32 itd, u32 dpl2); float auxb, u32 itd, u32 dpl2);
@ -959,38 +968,75 @@ extern u8 salNumVoices;
/* Stream */ /* Stream */
typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void* buffer1, u32 len1, void* buffer2, u32 len2, typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void* buffer1, u32 len1, void* buffer2, u32 len2,
void* user); void* user);
typedef struct SND_STREAM_INFO { typedef struct SNDADPCMinfo {
u32 x0_; // total size: 0x28
u32 x4_; u16 numCoef; // offset 0x0, size 0x2
u32 x8_; u8 initialPS; // offset 0x2, size 0x1
u8 xc_; u8 loopPS; // offset 0x3, size 0x1
char data2[0x10 - 0xd]; s16 loopY0; // offset 0x4, size 0x2
SND_STREAM_UPDATE_CALLBACK updateCb; s16 loopY1; // offset 0x6, size 0x2
char data3[0x4C - 0x14]; s16 coefTab[8][2]; // offset 0x8, size 0x20
SND_VOICEID voiceId; } SNDADPCMinfo;
void* user;
char data4[0x64 - 0x54]; typedef struct STREAM_INFO {
} SND_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(); void streamOutputModeChanged();
u8 inpTranslateExCtrl(unsigned char ctrl); u8 inpTranslateExCtrl(u8 ctrl);
void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag); void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag);
void inpAddCtrl(struct CTRL_DEST* dest, unsigned char ctrl, long scale, unsigned char comb, void inpAddCtrl(struct CTRL_DEST* dest, u8 ctrl, long scale, u8 comb, u32 isVar);
unsigned long isVar); void inpSetExCtrl(SYNTH_VOICE* svoice, u8 ctrl, s16 v);
void inpSetExCtrl(SYNTH_VOICE* svoice, unsigned char ctrl, signed short v); CHANNEL_DEFAULTS* inpGetChannelDefaults(u8 midi, u8 midiSet);
CHANNEL_DEFAULTS* inpGetChannelDefaults(unsigned char midi, unsigned char midiSet);
extern CTRL_DEST inpAuxA[8][4]; extern CTRL_DEST inpAuxA[8][4];
extern CTRL_DEST inpAuxB[8][4]; extern CTRL_DEST inpAuxB[8][4];
void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key); void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key);
u8 inpGetMidiLastNote(u8 midi, u8 midiSet); u8 inpGetMidiLastNote(u8 midi, u8 midiSet);
unsigned short inpGetExCtrl(SYNTH_VOICE* svoice, unsigned char ctrl); u16 inpGetExCtrl(SYNTH_VOICE* svoice, u8 ctrl);
unsigned short inpGetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set); u16 inpGetMidiCtrl(u8 ctrl, u8 channel, u8 set);
void inpSetMidiLastNote(unsigned char midi, unsigned char midiSet, unsigned char key); void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key);
u16 inpGetModulation(SYNTH_VOICE* svoice); u16 inpGetModulation(SYNTH_VOICE* svoice);
/* TODO: Figure out what `unk` is */ /* TODO: Figure out what `unk` is */
void hwSetSRCType(u32 v, u8 salSRCType); void hwSetSRCType(u32 v, u8 salSRCType);
void hwSetITDMode(u32 v, u8 mode); 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 hwAddInput(u8 studio, SND_STUDIO_INPUT* in_desc);
bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc); bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc);
void hwChangeStudio(u32 v, u8 studio); void hwChangeStudio(u32 v, u8 studio);
@ -1005,19 +1051,15 @@ extern u8 dspScale2IndexTab[1024];
typedef void* (*ARAMUploadCallback)(u32, u32); typedef void* (*ARAMUploadCallback)(u32, u32);
u32 aramGetStreamBufferAddress(unsigned char id, unsigned long* len); u32 aramGetStreamBufferAddress(u8 id, u32* len);
void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned long highPrio, void aramUploadData(void* mram, u32 aram, u32 len, u32 highPrio, void (*callback)(u32), u32 user);
void (*callback)(unsigned long), unsigned long user);
void aramFreeStreamBuffer(u8 id); void aramFreeStreamBuffer(u8 id);
void* aramStoreData(void* src, unsigned long len); void* aramStoreData(void* src, u32 len);
void aramRemoveData(void* aram, unsigned long len); void aramRemoveData(void* aram, u32 len);
u8 aramAllocateStreamBuffer(u32 len);
unsigned long macStart(unsigned short macid, unsigned char priority, unsigned char maxVoices, u32 macStart(u16 macid, u8 priority, u8 maxVoices, u16 allocId, u8 key, u8 vol, u8 panning, u8 midi,
unsigned short allocId, unsigned char key, unsigned char vol, u8 midiSet, u8 section, u16 step, u16 trackid, u8 new_vid, u8 vGroup, u8 studio,
unsigned char panning, unsigned char midi, unsigned char midiSet, u32 itd);
unsigned char section, unsigned short step, unsigned short trackid,
unsigned char new_vid, unsigned char vGroup, unsigned char studio,
unsigned long itd);
void macMakeInactive(SYNTH_VOICE* svoice, MAC_STATE); void macMakeInactive(SYNTH_VOICE* svoice, MAC_STATE);
void sndProfUpdateMisc(SND_PROFILE_INFO* info); void sndProfUpdateMisc(SND_PROFILE_INFO* info);

View File

@ -7,6 +7,160 @@
extern "C" { extern "C" {
#endif #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]; extern u16 seqMIDIPriority[8][16];
void sndSeqStop(s32 unk); void sndSeqStop(s32 unk);
@ -14,6 +168,7 @@ void sndSeqSpeed(s32 unk1, s32 unk2);
void sndSeqContinue(s32 unk); void sndSeqContinue(s32 unk);
void sndSeqMute(s32 unk1, s32 unk2, s32 unk3); void sndSeqMute(s32 unk1, s32 unk2, s32 unk3);
void sndSeqVolume(s32 unk1, s32 unk2, s32 unk3, s32 unk4); void sndSeqVolume(s32 unk1, s32 unk2, s32 unk3, s32 unk4);
void seqStop(unsigned long seqId);
u16 seqGetMIDIPriority(s32 unk1, s32 unk2); u16 seqGetMIDIPriority(s32 unk1, s32 unk2);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -23,7 +23,8 @@ bool synthFXSetCtrl(SND_VOICEID vid, u8 ctrl, u8 value);
bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value); bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value);
bool synthSendKeyOff(SND_VOICEID vid); bool synthSendKeyOff(SND_VOICEID vid);
SND_VOICEID synthFXStart(SND_FXID fid, u8 vol, u8 pan, u8 studio, u8); 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 */ /* TODO: Move this where it belongs */
void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA, void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA,

View File

@ -88,6 +88,7 @@ double ldexp(double x, int exp);
double copysign(double x, double y); double copysign(double x, double y);
double floor(double x); double floor(double x);
float floorf(float x) { return floor(x); }
double fabs(double x); double fabs(double x);
double pow(double x, double y); double pow(double x, double y);

View File

@ -1,17 +1,54 @@
/*
*/
#include "dolphin/GBAPriv.h" #include "dolphin/GBAPriv.h"
static GBASecParams SecParams[4]; static GBASecParam SecParams[4];
GBAControl __GBA[4]; GBAControl __GBA[4];
BOOL __GBAReset = FALSE; BOOL __GBAReset = FALSE;
static BOOL OnReset(BOOL); static BOOL OnReset(BOOL);
static OSResetFunctionInfo ResetFunctionInfo = { static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127};
OnReset,
127
};
void ShortCommandProc(s32 chan) { static void ShortCommandProc(s32 chan) {
GBAControl* gba; GBAControl* gba;
gba = &__GBA[chan]; gba = &__GBA[chan];
@ -27,6 +64,19 @@ void ShortCommandProc(s32 chan) {
gba->status[0] = gba->input[2] & GBA_JSTAT_MASK; gba->status[0] = gba->input[2] & GBA_JSTAT_MASK;
} }
/*
*/
void GBAInit() { void GBAInit() {
GBAControl* gba; GBAControl* gba;
s32 chan; s32 chan;
@ -37,16 +87,37 @@ void GBAInit() {
OSInitThreadQueue(&gba->threadQueue); OSInitThreadQueue(&gba->threadQueue);
gba->param = &SecParams[chan]; gba->param = &SecParams[chan];
// ASSERTMSG((u32) gba->param % 32 == 0) ASSERT((u32) gba->param % 32 == 0);
} }
OSInitAlarm(); OSInitAlarm();
DSPInit();
__GBAReset = FALSE;
DSPInit();
__GBAReset = FALSE;
OSRegisterResetFunction(&ResetFunctionInfo); OSRegisterResetFunction(&ResetFunctionInfo);
} }
/*
*/
s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) { s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) {
GBAControl* gba; GBAControl* gba;
gba = &__GBA[chan]; gba = &__GBA[chan];
@ -59,43 +130,89 @@ s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) {
gba->callback = callback; gba->callback = callback;
return __GBATransfer(chan, 1, 3, ShortCommandProc); return __GBATransfer(chan, 1, 3, ShortCommandProc);
} }
/*
*/
s32 GBAGetStatus(s32 chan, u8* status) { s32 GBAGetStatus(s32 chan, u8* status) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
//
s32 ret = GBAGetStatusAsync(chan, status, __GBASyncCallback); s32 ret = GBAGetStatusAsync(chan, status, __GBASyncCallback);
return ret != GBA_READY ? ret : __GBASync(chan); if (ret != GBA_READY) {
}
return ret;
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 __GBASync(chan);
return ret;
} }
/*
*/
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) { s32 GBAReset(s32 chan, u8* status) {
GBAControl* gba = &__GBA[chan];
s32 ret; s32 ret;
ret = GBAResetAsync(chan, status, __GBASyncCallback); ret = GBAResetAsync(chan, status, __GBASyncCallback);
if (ret != GBA_READY) { if (ret != GBA_READY) {
return ret; return ret;
} }
return __GBASync(chan); return __GBASync(chan);
} }
/*
*/
BOOL OnReset(BOOL) { BOOL OnReset(BOOL) {
__GBAReset = TRUE; __GBAReset = TRUE;
return TRUE; return TRUE;

View File

@ -1,14 +1,71 @@
/*
*/
#include "dolphin/GBAPriv.h" #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; bootInfo = &gba->bootInfo;
enabled = OSDisableInterrupts(); enabled = OSDisableInterrupts();
@ -17,9 +74,12 @@ s32 GBAGetProcessStatus(s32 chan, u8* percentp) {
percent = (bootInfo->curOffset * 100) / bootInfo->realLength; percent = (bootInfo->curOffset * 100) / bootInfo->realLength;
if (bootInfo->begin != 0) { if (bootInfo->begin != 0) {
t = OSGetTime(); t = OSGetTime();
if (OSTicksToMilliseconds(t - bootInfo->begin) < (5500)) {
percent = ((t - bootInfo->begin) * percent) / OSMillisecondsToTicks((OSTime)5500);
}
if (t - bootInfo->begin < OSMillisecondsToTicks(5500)) { if (percent >= 100) {
percentp = 0; percent = 100;
} }
} }
@ -27,9 +87,9 @@ s32 GBAGetProcessStatus(s32 chan, u8* percentp) {
*percentp = percent; *percentp = percent;
} }
} else if (gba->callback != NULL) { } else if (gba->callback != NULL) {
ret = 2; ret = 2;
} else { } else {
ret = 0; ret = 0;
} }
OSRestoreInterrupts(enabled); OSRestoreInterrupts(enabled);

View File

@ -17,22 +17,24 @@ static void F37(s32 chan, s32 ret);
static void F39(s32 chan, s32 ret); static void F39(s32 chan, s32 ret);
static u32 F72(u32 crc, u32 src, vu8* keyp) { static u32 F72(u32 crc, u32 src, vu8* keyp) {
int i; int i; // r31
int poly; int poly =
(keyp[0x13] << 8) + ((keyp[0x15] + (keyp[0x18] - (keyp[0x18] << 4))) - keyp[0x10]); // r30
for (i = keyp[1]; i > keyp[11]; --i) { for (i = keyp[1]; i > keyp[11]; --i) {
if ((src ^ crc) & 1 != 0) { if ((src ^ crc) & 1) {
crc = (crc >> 1) ^ ((keyp[19] * 256 + keyp[21] + keyp[24] + keyp[24] * -16) - keyp[16]); crc >>= 1;
crc ^= poly;
} else { } else {
crc >>= 1; crc >>= 1;
} }
src >>= 1; src >>= 1;
} }
} }
u32 F95(u32 src, vu8* keyp) { u32 F95(u32 src, vu8* keyp) {
return src * ((keyp[3] << keyp[0x16]) | keyp[1] | (keyp[4] << keyp[0x11]) | return src * ((keyp[4] << keyp[0x11]) | keyp[1] | (keyp[4] << keyp[0x18]) |
(keyp[4] << keyp[0x18])) - (keyp[3] << keyp[0x16])) -
(keyp[7] - keyp[6]); (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, s32 GBAJoyBootAsync(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length,
u8* status, GBACallback callback) { u8* status, GBACallback callback) {
int ret; int ret;
GBABootInfo* bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
u8 percent; u8 percent;
bootInfo = &__GBA[chan].bootInfo;
if (chan & ~3) { if (chan & ~3) {
ret = GBA_JOYBOOT_ERR_INVALID; return GBA_JOYBOOT_ERR_INVALID;
} else if (length == 0 || GBA_JOYBOOT_PROGRAM_SIZE_MAX < length) { } 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) { } else if (paletteSpeed < -4 || paletteSpeed > 4) {
ret = GBA_JOYBOOT_ERR_INVALID; return GBA_JOYBOOT_ERR_INVALID;
} else if (paletteColor < 0 || paletteColor > 6) { } 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) { } else if (programp[0xac] * programp[0xad] * programp[0xae] * programp[0xaf] == 0) {
ret = GBA_JOYBOOT_ERR_INVALID; return GBA_JOYBOOT_ERR_INVALID;
} else { }
ret = GBAGetProcessStatus(chan, &percent);
if (ret != 0) {
return ret;
}
bootInfo->paletteColor = paletteColor; ret = GBAGetProcessStatus(chan, &percent);
bootInfo->paletteSpeed = paletteSpeed; if (ret != 0) {
bootInfo->programp = programp; return ret;
bootInfo->length = length; }
bootInfo->status = status;
bootInfo->callback = callback; bootInfo->paletteColor = paletteColor;
bootInfo->curOffset = D54[8]; bootInfo->paletteSpeed = paletteSpeed;
ret = GBAGetStatusAsync(chan, bootInfo->status, F23); bootInfo->programp = programp;
if (ret != GBA_READY) { bootInfo->length = length;
bootInfo->callback = NULL; 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; return ret;
@ -91,7 +92,7 @@ static void F23(s32 chan, s32 ret) {
GBABootInfo* bootInfo; GBABootInfo* bootInfo;
gba = &__GBA[chan]; gba = &__GBA[chan];
bootInfo = &gba->bootInfo; bootInfo = &__GBA[chan].bootInfo;
if (ret != GBA_READY || (ret = GBAResetAsync(chan, bootInfo->status, F25)) != GBA_READY) { if (ret != GBA_READY || (ret = GBAResetAsync(chan, bootInfo->status, F25)) != GBA_READY) {
F104(chan, ret); F104(chan, ret);
@ -102,7 +103,7 @@ static void F23(s32 chan, s32 ret) {
static void F25(s32 chan, s32 ret) { static void F25(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY && *bootInfo->status != D54[37]) { if (ret == GBA_READY && *bootInfo->status != D54[37]) {
ret = GBA_JOYBOOT_UNKNOWN_STATE; ret = GBA_JOYBOOT_UNKNOWN_STATE;
@ -117,7 +118,7 @@ static void F25(s32 chan, s32 ret) {
static void F27(s32 chan, s32 ret) { static void F27(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY && *bootInfo->status != D54[0]) { if (ret == GBA_READY && *bootInfo->status != D54[0]) {
ret = GBA_JOYBOOT_UNKNOWN_STATE; ret = GBA_JOYBOOT_UNKNOWN_STATE;
@ -132,7 +133,7 @@ static void F27(s32 chan, s32 ret) {
static void F29(s32 chan, s32 ret) { static void F29(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) { if (ret == GBA_READY) {
__GBAX02(chan, bootInfo->readbuf); __GBAX02(chan, bootInfo->readbuf);
@ -144,7 +145,7 @@ static void F29(s32 chan, s32 ret) {
} }
void __GBAX01(s32 chan, s32 ret) { void __GBAX01(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
int val200; int val200;
if (ret == GBA_READY) { if (ret == GBA_READY) {
@ -184,11 +185,9 @@ void __GBAX01(s32 chan, s32 ret) {
} }
static void F31(s32 chan, s32 ret) { static void F31(s32 chan, s32 ret) {
GBAControl* gba; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
u32 writeWord; u32 writeWord;
gba = &__GBA[chan];
bootInfo = &gba->bootInfo;
if (ret == GBA_READY) { if (ret == GBA_READY) {
if (bootInfo->firstXfer != FALSE) { if (bootInfo->firstXfer != FALSE) {
@ -232,10 +231,11 @@ static void F31(s32 chan, s32 ret) {
writeWord = bootInfo->crc | (bootInfo->curOffset << 16); writeWord = bootInfo->crc | (bootInfo->curOffset << 16);
} }
if (D54[43] < bootInfo->curOffset) { if (bootInfo->curOffset > D54[43]) {
bootInfo->keyA = F95(bootInfo->keyA, &D54[20]); bootInfo->keyA = F95(bootInfo->keyA, &D54[20]);
writeWord ^= bootInfo->keyA ^ -(bootInfo->curOffset + D54[11] * 0x100000) ^ writeWord ^= bootInfo->keyA;
((D54[18] << 8) | (D54[19] << 16) | (D54[11] << 24) | D54[11]); writeWord ^= -(bootInfo->curOffset + D54[11] * 0x100000);
writeWord ^= (D54[11] | (D54[11] << 24)) | (D54[19] << 16) | (D54[18] << 8);
} }
bootInfo->writebuf[3] = (writeWord >> D54[0]); bootInfo->writebuf[3] = (writeWord >> D54[0]);
@ -248,7 +248,13 @@ static void F31(s32 chan, s32 ret) {
} }
if (bootInfo->i < D54[33]) { 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); ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31);
@ -266,7 +272,7 @@ exit:
} }
static void F33(s32 chan, s32 ret) { static void F33(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) { if (ret == GBA_READY) {
for (bootInfo->i = 33; bootInfo->i < 36; ++bootInfo->i) { 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) { static void F35(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == 0) { if (ret == 0) {
if (OSSecondsToTicks(10) <= OSGetTick() - bootInfo->start) { if (OSSecondsToTicks(10) <= OSGetTick() - bootInfo->start) {
@ -322,7 +328,7 @@ static void F35(s32 chan, s32 ret) {
static void F37(s32 chan, s32 ret) { static void F37(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) { if (ret == GBA_READY) {
if ((((bootInfo->readbuf[3] ^ (bootInfo->initialCode >> 24)) | 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) { static void F39(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan]; GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &gba->bootInfo; GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) { if (ret == GBA_READY) {
*bootInfo->status = 0; *bootInfo->status = 0;
@ -354,13 +360,12 @@ static void F39(s32 chan, s32 ret) {
gba->ret = ret; gba->ret = ret;
} }
s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, unsigned char* programp, s32 length, s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status) {
unsigned char* status) {
s32 ret = GBAJoyBootAsync(chan, paletteColor, paletteSpeed, programp, length, status, s32 ret = GBAJoyBootAsync(chan, paletteColor, paletteSpeed, programp, length, status,
__GBASyncCallback); __GBASyncCallback);
if (ret == GBA_READY) { if (ret != GBA_READY) {
ret = __GBASync(chan); return ret;
} }
return ret; return __GBASync(chan);
} }

116
src/Dolphin/GBA/GBAKey.c Normal file
View File

@ -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 = &param->keyA;
DCInvalidateRange(&param->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);
}

View File

@ -1,6 +1,6 @@
#include "dolphin/GBAPriv.h" #include "dolphin/GBAPriv.h"
void ReadProc(s32 chan) { static void ReadProc(s32 chan) {
GBAControl* gba; GBAControl* gba;
gba = &__GBA[chan]; gba = &__GBA[chan];
@ -12,26 +12,24 @@ void ReadProc(s32 chan) {
s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) { s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) {
GBAControl* gba; GBAControl* gba;
s32 ret;
gba = &__GBA[chan]; gba = &__GBA[chan];
if (gba->callback != NULL) { if (gba->callback != NULL) {
ret = 2; return 2;
} else {
gba->output[0] = 0x14;
gba->ptr = dst;
gba->status = status;
gba->callback = callback;
ret = __GBATransfer(chan, 1, 5, ReadProc);
} }
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 GBARead(s32 chan, u8* dst, u8* status) {
s32 tmp; s32 tmp;
GBAControl* gba = &__GBA[chan];
s32 ret; s32 ret;
ret = GBAReadAsync(chan, dst, status, __GBASyncCallback); ret = GBAReadAsync(chan, dst, status, __GBASyncCallback);
if (ret != GBA_READY) { if (ret != GBA_READY) {

View File

@ -1,6 +1,6 @@
#include "dolphin/GBAPriv.h" #include "dolphin/GBAPriv.h"
void WriteProc(s32 chan) { static void WriteProc(s32 chan) {
GBAControl* gba; GBAControl* gba;
gba = &__GBA[chan]; gba = &__GBA[chan];
@ -12,28 +12,23 @@ void WriteProc(s32 chan) {
} }
s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) { s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) {
GBAControl* gba; GBAControl* gba = &__GBA[chan];
s32 ret;
gba = &__GBA[chan];
if (gba->callback != NULL) { if (gba->callback != NULL) {
ret = GBA_BUSY; return 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);
} }
gba->output[0] = 0x15;
return ret; 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 GBAWrite(s32 chan, u8* src, u8* status) {
s32 ret;
s32 tmp; s32 tmp;
GBAControl* gba = &__GBA[chan];
s32 ret;
ret = GBAWriteAsync(chan, src, status, __GBASyncCallback); ret = GBAWriteAsync(chan, src, status, __GBASyncCallback);
if (ret != GBA_READY) { if (ret != GBA_READY) {
return ret; return ret;

View File

@ -1,12 +1,12 @@
#include "dolphin/GBAPriv.h" #include "dolphin/GBAPriv.h"
#include "dolphin/sipriv.h" #include "dolphin/sipriv.h"
void __GBAHandler(s32 chan, u32 error, OSContext* context) { static void __GBAHandler(s32 chan, u32 error, OSContext* context) {
GBAControl* gba; GBAControl* gba;
GBATransferCallback proc; GBATransferCallback proc;
GBACallback callback; GBACallback callback;
OSContext exceptionContext; OSContext exceptionContext;
gba = &__GBA[chan]; gba = &__GBA[chan];
if (__GBAReset != 0) { if (__GBAReset != 0) {
return; return;
@ -37,12 +37,15 @@ void __GBAHandler(s32 chan, u32 error, OSContext* context) {
OSSetCurrentContext(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) { s32 __GBASync(s32 chan) {
GBAControl* gba; GBAControl* gba;
s32 enabled;
s32 ret; s32 ret;
s32 enabled;
gba = &__GBA[chan]; gba = &__GBA[chan];
enabled = OSDisableInterrupts(); enabled = OSDisableInterrupts();
@ -57,40 +60,42 @@ s32 __GBASync(s32 chan) {
} }
void TypeAndStatusCallback(s32 chan, u32 type) { void TypeAndStatusCallback(s32 chan, u32 type) {
s32 tmp;
GBAControl* gba; GBAControl* gba;
OSContext* context; GBATransferCallback proc;
GBACallback callback; GBACallback callback;
GBATransferCallback xferCallback; OSContext exceptionContext;
OSContext tmpContext; OSContext* context;
gba = &__GBA[chan]; gba = &__GBA[chan];
if (__GBAReset != 0) { if (__GBAReset != 0) {
return; return;
} }
ASSERT(!(type & SI_ERROR_BUSY));
if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) { if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) {
gba->ret = GBA_NOT_READY; gba->ret = GBA_NOT_READY;
} else { } 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; return;
} }
gba->ret = GBA_BUSY; gba->ret = GBA_BUSY;
} }
if (gba->proc != NULL) { if (gba->proc != NULL) {
xferCallback = gba->proc; proc = gba->proc;
gba->proc = NULL; gba->proc = NULL;
xferCallback(chan); proc(chan);
} }
if (gba->callback != NULL) { if (gba->callback != NULL) {
context = OSGetCurrentContext(); context = OSGetCurrentContext();
OSClearContext(&tmpContext); OSClearContext(&exceptionContext);
OSSetCurrentContext(&tmpContext); OSSetCurrentContext(&exceptionContext);
callback = gba->callback; callback = gba->callback;
gba->callback = NULL; gba->callback = NULL;
callback(chan, gba->ret); callback(chan, gba->ret);
OSClearContext(&tmpContext); OSClearContext(&exceptionContext);
OSSetCurrentContext(context); OSSetCurrentContext(context);
__OSReschedule(); __OSReschedule();
} }

View File

@ -423,7 +423,7 @@ void hwFlushStream(void* base, unsigned long offset, unsigned long bytes, unsign
} }
void hwPrepareStreamBuffer() {} void hwPrepareStreamBuffer() {}
u32 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); } u8 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); }
void hwExitStream(u8 id) { aramFreeStreamBuffer(id); } void hwExitStream(u8 id) { aramFreeStreamBuffer(id); }

670
src/musyx/runtime/seq.c Normal file
View File

@ -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;
}
}
}

View File

@ -1,58 +1,462 @@
#include "musyx/musyx_priv.h" #include "musyx/musyx_priv.h"
#include "musyx/synth.h"
#ifndef _DEBUG
#include "dolphin/os.h"
#endif
SND_STREAM_INFO streamInfo[64]; static STREAM_INFO streamInfo[64];
u32 nextPublicID = 0;
u8 streamCallDelay = 0;
u8 streamCallCnt = 0; u8 streamCallCnt = 0;
u8 streamCallDelay = 0;
u32 nextPublicID = 0;
void streamInit() { void streamInit() {
s32 i; s32 i;
streamCallCnt = 0; streamCallCnt = 0;
streamCallDelay = 3; streamCallDelay = 3;
for (i = 0; i < synthInfo.voiceNum; ++i) {
for (i = 0; i < synthInfo.voices; ++i) { streamInfo[i].state = 0;
streamInfo[i].xc_ = 0;
} }
nextPublicID = 0; nextPublicID = 0;
} }
void SetHWMix(SND_STREAM_INFO* info) { #if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4)
// hwSetVolume() 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 streamCorrectLoops() {}
void streamKill(SND_STREAMID streamId) { void streamKill(u32 voice) {
SND_STREAM_INFO* stream = &streamInfo[streamId]; STREAM_INFO* si = &streamInfo[voice];
switch (si->state) {
switch (stream->xc_) {
case 1: case 1:
case 2: case 2:
if (stream->xc_ == 2) { if (si->state == 2) {
voiceUnblock(stream->voiceId); voiceUnblock(si->voice);
} }
stream->xc_ = 3; si->state = 3;
stream->updateCb(NULL, 0, NULL, 0, stream->user); si->updateFunction(NULL, 0, NULL, 0, (void*)si->user);
break;
default:
break; break;
} }
} }
s32 GetPrivateIndex(s32 something) { static u32 GetPrivateIndex(u32 publicID) {
s32 i; u32 i; // r31
for (i = 0; i < 64; ++i) { 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 i;
} }
} }
return -1; 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();
} }

View File

@ -618,6 +618,7 @@ static void mcmdSetADSRFromCtrl(SYNTH_VOICE* svoice, MSTEP* cstep) {
float sScale; // r63 float sScale; // r63
ADSR_INFO adsr; // r1+0x10 ADSR_INFO adsr; // r1+0x10
} }
static void mcmdSetPitchADSR(SYNTH_VOICE* svoice, MSTEP* cstep) { static void mcmdSetPitchADSR(SYNTH_VOICE* svoice, MSTEP* cstep) {
ADSR_INFO adsr; // r1+0x10 ADSR_INFO adsr; // r1+0x10
ADSR_INFO* adsr_ptr; // r31 ADSR_INFO* adsr_ptr; // r31
@ -625,6 +626,7 @@ static void mcmdSetPitchADSR(SYNTH_VOICE* svoice, MSTEP* cstep) {
s32 ascale; // r27 s32 ascale; // r27
s32 dscale; // r26 s32 dscale; // r26
} }
static u32 mcmdPitchSweep(SYNTH_VOICE* svoice, MSTEP* cstep, int num) { static u32 mcmdPitchSweep(SYNTH_VOICE* svoice, MSTEP* cstep, int num) {
s32 delta; // r31 s32 delta; // r31
svoice->sweepOff[num] = 0; svoice->sweepOff[num] = 0;
@ -692,7 +694,7 @@ static u32 TranslateVolume(u32 volume, u16 curve) {
if (vhigh < 0x7f) { if (vhigh < 0x7f) {
d = vlow * (ptr[vhigh + 1] - ptr[vhigh]); d = vlow * (ptr[vhigh + 1] - ptr[vhigh]);
volume = d + (ptr[vhigh] << 16); volume = d + ((u8)ptr[vhigh] << 16);
} else { } else {
volume = ptr[vhigh] << 16; volume = ptr[vhigh] << 16;
} }
@ -793,6 +795,7 @@ static void mcmdRandomKey(SYNTH_VOICE* svoice, MSTEP* cstep) {
s32 i2; // r27 s32 i2; // r27
u8 detune; // r26 u8 detune; // r26
} }
static void mcmdSetPitchbendAfterKeyOff(SYNTH_VOICE* svoice) { svoice->cFlags |= 0x10000; } static void mcmdSetPitchbendAfterKeyOff(SYNTH_VOICE* svoice) { svoice->cFlags |= 0x10000; }
static void mcmdScaleReverb(SYNTH_VOICE* svoice, MSTEP* cstep) { static void mcmdScaleReverb(SYNTH_VOICE* svoice, MSTEP* cstep) {
svoice->revVolScale = (u8)(cstep->para[0] >> 8); 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); varSet32(svoice, 0, (u8)(cstep->para[0] >> 8), mesg);
} }
static void mcmdGetVID(SYNTH_VOICE* svoice, MSTEP* cstep) { static void mcmdGetVID(SYNTH_VOICE* svoice, MSTEP* cstep) {
if ((u8)(cstep->para[0] >> 0x10) == 0) { if ((u8)(cstep->para[0] >> 0x10) == 0) {
varSet32(svoice, 0, (u8)(cstep->para[0] >> 8), svoice->vidList->vid); varSet32(svoice, 0, (u8)(cstep->para[0] >> 8), svoice->vidList->vid);

View File

@ -299,9 +299,7 @@ u32 voiceAllocate(u8 priority, u8 maxVoices, u16 allocId, u8 fxFlag) {
void voiceFree(SYNTH_VOICE* svoice) { void voiceFree(SYNTH_VOICE* svoice) {
u32 i; // r29 u32 i; // r29
SYNTH_VOICELIST* sfv; // r30 SYNTH_VOICELIST* sfv; // r30
#line 628
MUSY_ASSERT(svoice->id != 0xFFFFFFFF); MUSY_ASSERT(svoice->id != 0xFFFFFFFF);
#line 256
macMakeInactive(svoice, MAC_STATE_STOPPED); macMakeInactive(svoice, MAC_STATE_STOPPED);
voiceRemovePriority(svoice); voiceRemovePriority(svoice);
svoice->addr = NULL; svoice->addr = NULL;
@ -413,11 +411,11 @@ long voiceKillSound(u32 voiceid) {
u32 next_voiceid; // r28 u32 next_voiceid; // r28
u32 i; // r30 u32 i; // r30
if (sndActive != FALSE) { if (sndActive != FALSE) {
for (i = vidGetInternalId(voiceid); i != 0xFFFFFFFF; i = next_voiceid) { for (voiceid = vidGetInternalId(voiceid); voiceid != -1; voiceid = next_voiceid) {
voiceid = (u8)i; i = voiceid & 0xff;
next_voiceid = synthVoice[voiceid].child; next_voiceid = synthVoice[i].child;
if (i == synthVoice[voiceid].id) { if (voiceid == synthVoice[i].id) {
voiceKill(voiceid); voiceKill(i);
ret = 0; ret = 0;
} }
} }