diff options
author | Michael Panzlaff <michael.panzlaff@fau.de> | 2020-05-20 00:59:30 +0200 |
---|---|---|
committer | Michael Panzlaff <michael.panzlaff@fau.de> | 2020-05-29 19:24:16 +0200 |
commit | 34d432730cdae249d7b21cba2278b2cb1cb2f342 (patch) | |
tree | 3ca2a3440eac118db299131611212081a654a114 /arm9/lib/src | |
parent | 501072dd9fb699087cecb5404e0c363b63cfa9c6 (diff) |
decompile SND_* files
Diffstat (limited to 'arm9/lib/src')
-rw-r--r-- | arm9/lib/src/SND_alarm.c | 39 | ||||
-rw-r--r-- | arm9/lib/src/SND_bank.c | 175 | ||||
-rw-r--r-- | arm9/lib/src/SND_command.c | 333 | ||||
-rw-r--r-- | arm9/lib/src/SND_interface.c | 172 | ||||
-rw-r--r-- | arm9/lib/src/SND_main.c | 28 | ||||
-rw-r--r-- | arm9/lib/src/SND_util.c | 238 | ||||
-rw-r--r-- | arm9/lib/src/SND_work.c | 115 |
7 files changed, 1100 insertions, 0 deletions
diff --git a/arm9/lib/src/SND_alarm.c b/arm9/lib/src/SND_alarm.c new file mode 100644 index 00000000..b6178c8d --- /dev/null +++ b/arm9/lib/src/SND_alarm.c @@ -0,0 +1,39 @@ +#include "SND_alarm.h" + +struct AlarmCallback { + SNDAlarmCallback cb; + void *data; + u8 id; +}; + +static struct AlarmCallback sCallbackTable[SND_ALARM_COUNT]; + +ARM_FUNC void SND_AlarmInit(void) { + for (s32 i = 0; i < SND_ALARM_COUNT; i++) { + sCallbackTable[i].cb = NULL; + sCallbackTable[i].data = NULL; + sCallbackTable[i].id = 0; + } +} + +ARM_FUNC void SNDi_IncAlarmId(u32 idx) { + struct AlarmCallback *ac = &sCallbackTable[idx]; + ac->id++; +} + +ARM_FUNC u8 SNDi_SetAlarmHandler(u32 idx, SNDAlarmCallback cb, void *data) { + struct AlarmCallback *ac = &sCallbackTable[idx]; + ac->cb = cb; + ac->data = data; + ac->id++; + return ac->id; +} + +ARM_FUNC void SNDi_CallAlarmHandler(s32 idx) { + struct AlarmCallback *ac = &sCallbackTable[idx & 0xFF]; + if (((idx >> 8) & 0xFF) != ac->id) + return; + if (ac->cb == NULL) + return; + ac->cb(ac->data); +} diff --git a/arm9/lib/src/SND_bank.c b/arm9/lib/src/SND_bank.c new file mode 100644 index 00000000..bc339234 --- /dev/null +++ b/arm9/lib/src/SND_bank.c @@ -0,0 +1,175 @@ +#include "SND_bank.h" +#include "OS_mutex.h" + +void OS_LockMutex(struct OSMutex *); +void OS_UnlockMutex(struct OSMutex *); +void DC_StoreRange(const void *, u32); + +/* + * WaveArc linking seems to work like the following: + * + * Each SNDBankData can have up to 4 WaveArcs assigned. + * To avoid loading the same WaveArc by multiple banks, + * a linked list using WaveArcLinks is chained through all banks + * which use a WaveArc. + * + * That WaveArc has a head pointer, which points to the first + * WaveArcLink in that chain of banks. + */ + +/* + * Set bank's wavearc link at index to specified wavearc + */ +ARM_FUNC void SND_AssignWaveArc(struct SNDBankData *bankData, s32 index, struct SNDWaveArc *waveArc) { + SNDi_LockMutex(); + struct SNDWaveArc *selectedWaveArc = bankData->waveArcLinks[index].waveArc; + if (selectedWaveArc != NULL) { + if (waveArc == selectedWaveArc) { + SNDi_UnlockMutex(); + return; + } + + if (&bankData->waveArcLinks[index] == selectedWaveArc->waveArcLLHead) { + selectedWaveArc->waveArcLLHead = bankData->waveArcLinks[index].waveArcLLnext; + DC_StoreRange(bankData->waveArcLinks[index].waveArc, sizeof(struct SNDWaveArc)); + } else { + struct SNDWaveArcLink *cur; + for (cur = selectedWaveArc->waveArcLLHead; cur != NULL; cur = cur->waveArcLLnext) { + if (&bankData->waveArcLinks[index] == cur->waveArcLLnext) + break; + } + cur->waveArcLLnext = bankData->waveArcLinks[index].waveArcLLnext; + DC_StoreRange(cur, sizeof(*cur)); + } + } + struct SNDWaveArcLink *oldHead = waveArc->waveArcLLHead; + waveArc->waveArcLLHead = &bankData->waveArcLinks[index]; + bankData->waveArcLinks[index].waveArcLLnext = oldHead; + bankData->waveArcLinks[index].waveArc = waveArc; + // BUG: Shouldn't the mutex unlock be after writing to cache? + SNDi_UnlockMutex(); + DC_StoreRange(bankData, sizeof(*bankData)); + DC_StoreRange(waveArc, sizeof(*waveArc)); +} + +ARM_FUNC void SND_DestroyBank(struct SNDBankData *bankData) { + SNDi_LockMutex(); + + for (s32 i = 0; i < SND_BANK_MAX_WAVEARC; i++) { + struct SNDWaveArcLink *curWaveArcLink = &bankData->waveArcLinks[i]; + struct SNDWaveArc *curWaveArc = bankData->waveArcLinks[i].waveArc; + + if (curWaveArc == NULL) + continue; + + if (curWaveArcLink == curWaveArc->waveArcLLHead) { + curWaveArc->waveArcLLHead = bankData->waveArcLinks[i].waveArcLLnext; + DC_StoreRange(curWaveArc, sizeof(*curWaveArc)); + } else { + struct SNDWaveArcLink *cur; + for (cur = curWaveArc->waveArcLLHead; cur != NULL; cur = cur->waveArcLLnext) { + if (&bankData->waveArcLinks[i] == cur->waveArcLLnext) + break; + } + cur->waveArcLLnext = bankData->waveArcLinks[i].waveArcLLnext; + DC_StoreRange(cur, sizeof(*cur)); + } + } + + SNDi_UnlockMutex(); +} + +ARM_FUNC void SND_DestroyWaveArc(struct SNDWaveArc *waveArc) { + SNDi_LockMutex(); + struct SNDWaveArcLink *cur = waveArc->waveArcLLHead; + + while (cur != NULL) { + struct SNDWaveArcLink *newCur = cur->waveArcLLnext; + cur->waveArc = NULL; + cur->waveArcLLnext = NULL; + DC_StoreRange(cur, sizeof(*cur)); + cur = newCur; + } + + SNDi_UnlockMutex(); +} + +ARM_FUNC struct SNDInstPos SND_GetFirstInstDataPos(const struct SNDBankData *bankData) { + struct SNDInstPos retval; + retval.program = 0; + retval.index = 0; + return retval; +} + +ARM_FUNC static inline struct SNDDrumSet *test(const struct SNDBankData *bank, u32 off) { + return (struct SNDDrumSet *)((u8 *)bank + (off >> 8)); +} + +ARM_FUNC BOOL SND_GetNextInstData(const struct SNDBankData *bankData, struct SNDInstData *instData, struct SNDInstPos *instPos) { + while (instPos->program < bankData->instCount) { + struct SNDDrumSet *drums; + struct SNDKeySplit *keySplit; + + u32 instOffset = bankData->instOffsets[instPos->program]; + instData->type = SND_INST_OFFSET_TYPE(instOffset); + + switch (instData->type) { + case SND_INST_PCM: + case SND_INST_PSG: + case SND_INST_NOISE: + case SND_INST_DIRECTPCM: + case SND_INST_DUMMY: + instData->param = *SND_INST_OFFSET_NORMAL(bankData, instOffset); + instPos->program++; + return TRUE; + case SND_INST_DRUM_TABLE: + drums = SND_INST_OFFSET_DRUMS(bankData, instOffset); + // silly programming 101: put a loop in a place that never loops + for (; instPos->index < drums->maxKey - drums->minKey + 1;) { + *instData = drums->instruments[instPos->index]; + instPos->index++; + return TRUE; + } + break; + case SND_INST_KEY_SPLIT: + keySplit = SND_INST_OFFSET_KEYSPL(bankData, instOffset); + for (; instPos->index < SND_INST_MAX_KEYSPLIT;) { + if (keySplit->key[instPos->index] == 0) + break; + *instData = keySplit->instruments[instPos->index]; + instPos->index++; + return TRUE; + } + break; + } + + instPos->program++; + instPos->index = 0; + } + return FALSE; +} + +ARM_FUNC u32 SND_GetWaveDataCount(const struct SNDWaveArc *waveArc) { + return waveArc->waveCount; +} + +ARM_FUNC void SND_SetWaveDataAddress(struct SNDWaveArc *waveArc, s32 index, const struct SNDWaveData *waveData) { + SNDi_LockMutex(); + waveArc->waveOffsets[index] = (u32)waveData; + DC_StoreRange(&waveArc->waveOffsets[index], sizeof(u32)); + SNDi_UnlockMutex(); +} + +ARM_FUNC const struct SNDWaveData *SND_GetWaveDataAddress(const struct SNDWaveArc *waveArc, s32 index) { + SNDi_LockMutex(); + u32 retval = waveArc->waveOffsets[index]; + if (retval != 0) { + // < 0x2000000 aka, not a pointer to main RAM + if (retval < 0x2000000) + retval = (u32)&((u8 *)waveArc)[retval]; + } else { + retval = 0; + } + SNDi_UnlockMutex(); + return (struct SNDWaveData *)retval; +} diff --git a/arm9/lib/src/SND_command.c b/arm9/lib/src/SND_command.c new file mode 100644 index 00000000..4a867ce3 --- /dev/null +++ b/arm9/lib/src/SND_command.c @@ -0,0 +1,333 @@ +#include "SND_command.h" +#include "SND_work.h" +#include "OS_system.h" + +#define SND_CMD_WAIT_QUEUE_COUNT 8 + +static struct SNDCommand sCommandArray[SND_CMD_COUNT]; +static struct SNDSharedWork sSharedWork; +static struct SNDCommand *sWaitingCommandListQueue[SND_CMD_WAIT_QUEUE_COUNT + 1]; // not sure why this is one element to large +static struct SNDCommand *sReserveList; +static struct SNDCommand *sReserveListEnd; +static struct SNDCommand *sFreeListEnd; +static s32 sWaitingCommandListQueueRead; +static s32 sWaitingCommandListQueueWrite; +static s32 sWaitingCommandListCount; +static u32 sCurrentTag; +static u32 sFinishedTag; +static struct SNDCommand *sFreeList; + +// TODO remove these function declarations once they are in the headers +extern s32 PXI_SendWordByFifo(u32, u32, u32); +extern void PXI_SetFifoRecvCallback(u32, void (*)(s32, s32)); +extern BOOL PXI_IsCallbackReady(u32, u32); + +static void InitPXI(void); +static void RequestCommandProc(void); +static struct SNDCommand *AllocCommand(void); +static BOOL IsCommandAvailable(void); + +ARM_FUNC void SND_CommandInit(void) { + InitPXI(); + sFreeList = sCommandArray; + for (int i = 0; i < SND_CMD_COUNT - 1; i++) { + sCommandArray[i].llNext = &sCommandArray[i+1]; + } + sCommandArray[SND_CMD_COUNT - 1].llNext = NULL; + sFreeListEnd = &sCommandArray[SND_CMD_COUNT - 1]; + sReserveList = NULL; + sReserveListEnd = NULL; + sWaitingCommandListCount = 0; + sWaitingCommandListQueueRead = 0; + sWaitingCommandListQueueWrite = 0; + sCurrentTag = 1; + sFinishedTag = 0; + SNDi_SharedWork = &sSharedWork; + SNDi_InitSharedWork(SNDi_SharedWork); + + struct SNDCommand *cmd = SND_AllocCommand(SND_CMD_FLAG_BLOCK); + if (cmd == NULL) + return; + + cmd->id = SND_CMD_SET_SHARED_WORK; + cmd->arg[0] = (u32)SNDi_SharedWork; + SND_PushCommand(cmd); + SND_FlushCommand(SND_CMD_FLAG_BLOCK); +} + +ARM_FUNC const struct SNDCommand *SND_RecvCommandReply(u32 flags) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + if (flags & SND_CMD_FLAG_BLOCK) { + u32 tag = SNDi_GetFinishedCommandTag(); + while (sFinishedTag == tag) { + OS_RestoreInterrupts(oldirq); + OS_SpinWait(100); + oldirq = OS_DisableInterrupts(); + tag = SNDi_GetFinishedCommandTag(); + } + } else { + u32 tag = SNDi_GetFinishedCommandTag(); + if (sFinishedTag == tag) { + OS_RestoreInterrupts(oldirq); + return NULL; + } + } + + struct SNDCommand *queueRead = sWaitingCommandListQueue[sWaitingCommandListQueueRead]; + + if (++sWaitingCommandListQueueRead > SND_CMD_WAIT_QUEUE_COUNT) + sWaitingCommandListQueueRead = 0; + + struct SNDCommand *cur = queueRead; + while (cur->llNext != NULL) + cur = cur->llNext; + + if (sFreeListEnd != NULL) { + sFreeListEnd->llNext = queueRead; + } else { + sFreeList = queueRead; + } + + sFreeListEnd = cur; + sWaitingCommandListCount--; + sFinishedTag++; + + OS_RestoreInterrupts(oldirq); + return queueRead; +} + +ARM_FUNC struct SNDCommand *SND_AllocCommand(u32 flags) { + struct SNDCommand *cmd; + if (!IsCommandAvailable()) + return NULL; + + cmd = AllocCommand(); + if (cmd != NULL) + return cmd; + + if ((flags & SND_CMD_FLAG_BLOCK) == 0) + return NULL; + + if (SND_CountWaitingCommand() > 0) { + while (SND_RecvCommandReply(SND_CMD_FLAG_NOBLOCK) != NULL) { } + + cmd = AllocCommand(); + if (cmd != NULL) + return cmd; + } else { + SND_FlushCommand(SND_CMD_FLAG_BLOCK); + } + + RequestCommandProc(); + + do { + SND_RecvCommandReply(SND_CMD_FLAG_BLOCK); + cmd = AllocCommand(); + } while (cmd == NULL); + return cmd; +} + +ARM_FUNC void SND_PushCommand(struct SNDCommand *cmd) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + struct SNDCommand *newend = cmd; + if (sReserveListEnd == NULL) { + sReserveList = cmd; + sReserveListEnd = cmd; + } else { + sReserveListEnd->llNext = cmd; + sReserveListEnd = cmd; + } + + cmd->llNext = NULL; + + OS_RestoreInterrupts(oldirq); +} + +ARM_FUNC BOOL SND_FlushCommand(u32 flags) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + if (sReserveList == NULL) { + OS_RestoreInterrupts(oldirq); + return TRUE; + } + + if (sWaitingCommandListCount >= SND_CMD_WAIT_QUEUE_COUNT) { + if ((flags & SND_CMD_FLAG_BLOCK) == 0) { + OS_RestoreInterrupts(oldirq); + return FALSE; + } + + do { + SND_RecvCommandReply(SND_CMD_FLAG_BLOCK); + } while (sWaitingCommandListCount >= SND_CMD_WAIT_QUEUE_COUNT); + } + + DC_FlushRange(sCommandArray, sizeof(sCommandArray)); + + s32 result = PXI_SendWordByFifo(7, (u32)sReserveList, 0); + if (result < 0) { + if ((flags & SND_CMD_FLAG_BLOCK) == 0) { + OS_RestoreInterrupts(oldirq); + return FALSE; + } + + result = PXI_SendWordByFifo(7, (u32)sReserveList, 0); + while (result < 0) { + OS_RestoreInterrupts(oldirq); + OS_SpinWait(100); + oldirq = OS_DisableInterrupts(); + result = PXI_SendWordByFifo(7, (u32)sReserveList, 0); + } + } + + if ((flags & SND_CMD_FLAG_IMMEDIATE) != 0) { + RequestCommandProc(); + } + + sWaitingCommandListQueue[sWaitingCommandListQueueWrite] = sReserveList; + + if (++sWaitingCommandListQueueWrite > SND_CMD_WAIT_QUEUE_COUNT) { + sWaitingCommandListQueueWrite = 0; + } + + sReserveList = NULL; + sReserveListEnd = NULL; + sWaitingCommandListCount++; + sCurrentTag++; + + OS_RestoreInterrupts(oldirq); + return TRUE; +} + +ARM_FUNC void SND_WaitForCommandProc(u32 tag) { + if (SND_IsFinishedCommandTag(tag)) + return; + + while (SND_RecvCommandReply(SND_CMD_FLAG_NOBLOCK) != NULL) { } + + if (SND_IsFinishedCommandTag(tag)) + return; + + RequestCommandProc(); + + if (SND_IsFinishedCommandTag(tag)) + return; + + do { + SND_RecvCommandReply(SND_CMD_FLAG_BLOCK); + } while (SND_IsFinishedCommandTag(tag) == 0); +} + +ARM_FUNC u32 SND_GetCurrentCommandTag(void) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + u32 retval; + if (sReserveList == NULL) + retval = sFinishedTag; + else + retval = sCurrentTag; + + OS_RestoreInterrupts(oldirq); + return retval; +} + +ARM_FUNC BOOL SND_IsFinishedCommandTag(u32 tag) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + BOOL result; + if (tag > sFinishedTag) { + if (tag - sFinishedTag < 0x80000000) + result = FALSE; + else + result = TRUE; + } else { + if (sFinishedTag - tag < 0x80000000) + result = TRUE; + else + result = FALSE; + } + + OS_RestoreInterrupts(oldirq); + return result; +} + +ARM_FUNC s32 SND_CountFreeCommand(void) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + s32 count = 0; + for (struct SNDCommand *cmd = sFreeList; cmd != NULL; cmd = cmd->llNext) + count++; + + OS_RestoreInterrupts(oldirq); + return count; +} + +ARM_FUNC s32 SND_CountReservedCommand(void) { + OSIntrMode oldirq = OS_DisableInterrupts(); + + s32 count = 0; + for (struct SNDCommand *cmd = sReserveList; cmd != NULL; cmd = cmd->llNext) + count++; + + OS_RestoreInterrupts(oldirq); + return count; +} + +ARM_FUNC s32 SND_CountWaitingCommand(void) { + return SND_CMD_COUNT - SND_CountFreeCommand() - SND_CountReservedCommand(); +} + +ARM_FUNC static void PxiFifoCallback(s32 a, s32 b) { + OSIntrMode oldirq = OS_DisableInterrupts(); + SNDi_CallAlarmHandler(b); + OS_RestoreInterrupts(oldirq); +} + +ARM_FUNC static void InitPXI(void) { + PXI_SetFifoRecvCallback(7, PxiFifoCallback); + + if (!IsCommandAvailable()) + return; + + if (PXI_IsCallbackReady(7, 1)) + return; + + do { + OS_SpinWait(100); + } while (!PXI_IsCallbackReady(7, 1)); +} + +ARM_FUNC static void RequestCommandProc(void) { + while (PXI_SendWordByFifo(7, 0, 0) < 0) { } +} + +ARM_FUNC static struct SNDCommand *AllocCommand(void) { + OSIntrMode oldirq = OS_DisableInterrupts(); + if (sFreeList == NULL) { + OS_RestoreInterrupts(oldirq); + return NULL; + } + + struct SNDCommand *retval = sFreeList; + + sFreeList = sFreeList->llNext; + if (sFreeList == NULL) + sFreeListEnd = NULL; + OS_RestoreInterrupts(oldirq); + return retval; +} + +ARM_FUNC static BOOL IsCommandAvailable(void) { + if (!OS_IsRunOnEmulator()) + return TRUE; + + OSIntrMode oldirq = OS_DisableInterrupts(); + // TODO use proper register names here + // is this some kind of debug or ensata register? + *(vu32 *)0x4FFF200 = 0x10; + u32 resp = *(vu32 *)0x4FFF200; + OS_RestoreInterrupts(oldirq); + return resp != 0; +} diff --git a/arm9/lib/src/SND_interface.c b/arm9/lib/src/SND_interface.c new file mode 100644 index 00000000..e8369477 --- /dev/null +++ b/arm9/lib/src/SND_interface.c @@ -0,0 +1,172 @@ +#include "SND_interface.h" +#include "SND_command.h" + +static void PushCommand_impl(s32 id, u32 par1, u32 par2, u32 par3, u32 par4); +#define PushCmd1(id, a) PushCommand_impl(id, (u32)(a), 0, 0, 0) +#define PushCmd2(id, a, b) PushCommand_impl(id, (u32)(a), (u32)(b), 0, 0) +#define PushCmd3(id, a, b, c) PushCommand_impl(id, (u32)(a), (u32)(b), (u32)(c), 0) +#define PushCmd4(id, a, b, c, d) PushCommand_impl(id, (u32)(a), (u32)(b), (u32)(c), (u32)(d)) + +// TODO fill in "random" constants with macros + +// ARM_FUNC void SND_StartSeq(s32 player, const void *seqBasePtr, u32 seqOffset, struct SNDBankData *bankData) { } + +ARM_FUNC void SND_StopSeq(s32 player) { + PushCmd1(SND_CMD_STOP_SEQ, player); +} + +ARM_FUNC void SND_PrepareSeq(s32 player, const void *seqBasePtr, u32 seqOffset, struct SNDBankData *bankData) { + PushCmd4(SND_CMD_PREPARE_SEQ, player, seqBasePtr, seqOffset, bankData); +} + +ARM_FUNC void SND_StartPreparedSeq(s32 player) { + PushCmd1(SND_CMD_START_PREPARED_SEQ, player); +} + +ARM_FUNC void SND_PauseSeq(s32 player, BOOL flag) { + PushCmd2(SND_CMD_PAUSE_SEQ, player, flag); +} + +// ARM_FUNC void SND_SetPlayerTempoRatio(s32 player, s32 ratio) { } + +ARM_FUNC void SND_SetPlayerVolume(s32 player, s32 volume) { + SNDi_SetPlayerParam(player, 6, volume, 2); +} + +ARM_FUNC void SND_SetPlayerChannelPriority(s32 player, s32 prio) { + SNDi_SetPlayerParam(player, 4, prio, 1); +} + +// ARM_FUNC void SND_SetPlayerLocalVariable(s32 player, s32 varNo, s16 var) { } + +// ARM_FUNC void SND_SetPlayerGlobalVariable(s32 varNo, s16 var) { } + +// ARM_FUNC void SND_SetTrackVolume(s32 player, u32 trackBitMask, s32 volume) { } + +ARM_FUNC void SND_SetTrackPitch(s32 player, u32 trackBitMask, s32 pitch) { + SNDi_SetTrackParam(player, trackBitMask, 12, pitch, 2); +} + +ARM_FUNC void SND_SetTrackPan(s32 player, u32 trackBitMask, s32 pan) { + SNDi_SetTrackParam(player, trackBitMask, 9, pan, 1); +} + +ARM_FUNC void SND_SetTrackAllocatableChannel(s32 player, u32 trackBitMask, u32 chnBitMask) { + PushCmd3(SND_CMD_ALLOCATABLE_CHANNEL, player, trackBitMask, chnBitMask); +} + +ARM_FUNC void SND_StartTimer(u32 chnBitMask, u32 capBitMask, u32 alarmBitMask, u32 flags) { + PushCmd4(SND_CMD_START_TIMER, chnBitMask, capBitMask, alarmBitMask, flags); +} + +ARM_FUNC void SND_StopTimer(u32 chnBitMask, u32 capBitMask, u32 alarmBitMask, u32 flags) { + s32 i = 0; + u32 tmpMask = alarmBitMask; + + while (i < SND_ALARM_COUNT && tmpMask != 0) { + if (tmpMask & 1) + SNDi_IncAlarmId(i); + i++; + tmpMask >>= 1; + } + + PushCmd4(SND_CMD_STOP_TIMER, chnBitMask, capBitMask, alarmBitMask, flags); +} + +ARM_FUNC void SND_SetupCapture(s32 capture, s32 format, void *bufferPtr, u32 length, BOOL loopFlag, s32 in, s32 out) { + PushCmd3(SND_CMD_SETUP_CAPTURE, bufferPtr, length, + (capture << 31) | (format << 30) | (loopFlag << 29) | (in << 28) | (out << 27)); +} + +ARM_FUNC void SND_SetupAlarm(s32 alarm, u32 tick, u32 period, SNDAlarmCallback cb, void *userData) { + PushCmd4(SND_CMD_SETUP_ALARM, alarm, tick, period, SNDi_SetAlarmHandler(alarm, cb, userData)); +} + +// ARM_FUNC void SND_SetTrackMute(s32 player, u32 trackBitMask, BOOL flag) { } + +// ARM_FUNC void SND_StopUnlockedChannel(u32 chnBitMask, u32 flags) { } + +ARM_FUNC void SND_LockChannel(u32 chnBitMask, u32 flags) { + PushCmd2(SND_CMD_LOCK_CHANNEL, chnBitMask, flags); +} + +ARM_FUNC void SND_UnlockChannel(u32 chnBitMask, u32 flags) { + PushCmd2(SND_CMD_UNLOCK_CHANNEL, chnBitMask, flags); +} + +ARM_FUNC void SND_SetChannelTimer(u32 chnBitMask, s32 timer) { + PushCmd2(SND_CMD_CHANNEL_TIMER, chnBitMask, timer); +} + +ARM_FUNC void SND_SetChannelVolume(u32 chnBitMask, s32 volume, s32 chnDataShift) { + PushCmd3(SND_CMD_CHANNEL_VOLUME, chnBitMask, volume, chnDataShift); +} + +ARM_FUNC void SND_SetChannelPan(u32 chnBitMask, s32 pan) { + PushCmd2(SND_CMD_CHANNEL_PAN, chnBitMask, pan); +} + +ARM_FUNC void SND_SetupChannelPcm(s32 chn, s32 waveFormat, const void *dataAddr, s32 loopMode, s32 loopStart, s32 dataLen, s32 volume, s32 chnDataShift, s32 timer, s32 pan) { + PushCmd4(SND_CMD_SETUP_CHANNEL_PCM, + chn | (timer << 16), + dataAddr, + (volume << 24) | (chnDataShift << 22) | dataLen, + (loopMode << 26) | (waveFormat << 24) | (pan << 16) | loopStart); +} + +// ARM_FUNC void SND_SetupChannelPsg(s32 chn, s32 sndDuty, s32 volume, s32 chnDataShift, s32 timer, s32 pan) { } + +// ARM_FUNC void SND_SetupChannelNoise(s32 chn, s32 volume, s32 chnDataShift, s32 timer, s32 pan) { } + +ARM_FUNC void SND_InvalidateSeqData(const void *start, const void *end) { + PushCmd2(SND_CMD_INVALIDATE_SEQ, start, end); +} + +ARM_FUNC void SND_InvalidateBankData(const void *start, const void *end) { + PushCmd2(SND_CMD_INVALIDATE_BANK, start, end); +} + +ARM_FUNC void SND_InvalidateWaveData(const void *start, const void *end) { + PushCmd2(SND_CMD_INVALIDATE_WAVE, start, end); +} + +// ARM_FUNC void SND_SetMasterVolume(s32 volume) { } + +ARM_FUNC void SND_SetOutputSelector(s32 left, s32 right, s32 channel1, s32 channel3) { + PushCmd4(SND_CMD_OUTPUT_SELECTOR, left, right, channel1, channel3); +} + +ARM_FUNC void SND_SetMasterPan(s32 pan) { + PushCmd1(SND_CMD_MASTER_PAN, pan); +} + +ARM_FUNC void SND_ResetMasterPan(void) { + PushCmd1(SND_CMD_MASTER_PAN, -1); +} + +// ARM_FUNC void SND_ReadDriverInfo(struct SNDDriverInfo *info) { } + +ARM_FUNC void SNDi_SetPlayerParam(s32 player, u32 offset, u32 data, s32 size) { + PushCmd4(SND_CMD_PLAYER_PARAM, player, offset, data, size); +} + +ARM_FUNC void SNDi_SetTrackParam(s32 player, u32 trackBitMask, u32 offset, u32 data, s32 size) { + PushCmd4(SND_CMD_TRACK_PARAM, player | (size << 24), trackBitMask, offset, data); +} + +// ARM_FUNC void SNDi_SetSurroundDecay(s32 decay) { } + +// ARM_FUNC void SNDi_SkipSeq(s32 player, u32 tick) { } + +ARM_FUNC static void PushCommand_impl(s32 id, u32 par1, u32 par2, u32 par3, u32 par4) { + struct SNDCommand *cmd = SND_AllocCommand(SND_CMD_FLAG_BLOCK); + if (cmd == NULL) + return; + + cmd->id = id; + cmd->arg[0] = par1; + cmd->arg[1] = par2; + cmd->arg[2] = par3; + cmd->arg[3] = par4; + SND_PushCommand(cmd); +} diff --git a/arm9/lib/src/SND_main.c b/arm9/lib/src/SND_main.c new file mode 100644 index 00000000..f533b87c --- /dev/null +++ b/arm9/lib/src/SND_main.c @@ -0,0 +1,28 @@ +#include "SND_main.h" + +#include "global.h" +#include "OS_mutex.h" + +static struct OSMutex sSndMutex; +static s32 sSndInitialized; + +// TODO remove these declarations once we have the functions in the headers +void OS_UnlockMutex(struct OSMutex *); +void OS_LockMutex(struct OSMutex *); + +ARM_FUNC void SND_Init(void) { + if (sSndInitialized) + return; + sSndInitialized = 1; + OS_InitMutex(&sSndMutex); + SND_CommandInit(); + SND_AlarmInit(); +} + +ARM_FUNC void SNDi_LockMutex(void) { + OS_LockMutex(&sSndMutex); +} + +ARM_FUNC void SNDi_UnlockMutex(void) { + OS_UnlockMutex(&sSndMutex); +} diff --git a/arm9/lib/src/SND_util.c b/arm9/lib/src/SND_util.c new file mode 100644 index 00000000..6ff8cb14 --- /dev/null +++ b/arm9/lib/src/SND_util.c @@ -0,0 +1,238 @@ +#include "SND_util.h" + +// not used in pokediamond +//static const u16 sPitchTable[0x600] = { +// 0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019f, +// 0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D, +// 0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F, +// 0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743, +// 0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C, +// 0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18, +// 0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07, +// 0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA, +// 0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1, +// 0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB, +// 0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9, +// 0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB, +// 0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0, +// 0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA, +// 0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07, +// 0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17, +// 0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C, +// 0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344, +// 0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561, +// 0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781, +// 0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5, +// 0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD, +// 0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9, +// 0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A, +// 0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E, +// 0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496, +// 0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3, +// 0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913, +// 0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58, +// 0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1, +// 0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE, +// 0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240, +// 0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495, +// 0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0, +// 0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E, +// 0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1, +// 0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18, +// 0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084, +// 0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4, +// 0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569, +// 0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2, +// 0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60, +// 0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3, +// 0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A, +// 0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6, +// 0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487, +// 0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C, +// 0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6, +// 0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55, +// 0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9, +// 0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2, +// 0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450, +// 0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702, +// 0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA, +// 0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77, +// 0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38, +// 0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF, +// 0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB, +// 0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D, +// 0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73, +// 0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F, +// 0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030, +// 0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316, +// 0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602, +// 0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3, +// 0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA, +// 0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6, +// 0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8, +// 0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF, +// 0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC, +// 0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E, +// 0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27, +// 0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145, +// 0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468, +// 0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792, +// 0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1, +// 0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7, +// 0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132, +// 0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473, +// 0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB, +// 0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08, +// 0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B, +// 0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5, +// 0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515, +// 0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B, +// 0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8, +// 0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B, +// 0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4, +// 0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654, +// 0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA, +// 0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66, +// 0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA, +// 0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494, +// 0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834, +// 0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC, +// 0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A, +//}; + +static const u8 sVolumeTable[724] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xB, + 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xC, 0xC, 0xC, 0xC, + 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xE, + 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xF, 0xF, 0xF, 0xF, 0xF, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, + 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, + 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, + 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, + 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, + 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, + 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, + 0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, + 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, + 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, + 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, + 0x7B, 0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, + 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, + 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, + 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, + 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, + 0x34, 0x34, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x39, + 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, + 0x40, 0x40, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, + 0x6B, 0x6C, 0x6D, 0x6F, 0x70, 0x71, 0x73, 0x74, 0x75, + 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, + 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, + 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, + 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, 0x78, 0x79, + 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, + 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, + 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7C, 0x7D, + 0x7E, 0x7F, +}; + +const s16 SNDi_DecibelTable[0x80] = { + -32768,-421,-361, -325, -300, -281, -265, -252, + -240, -230, -221, -212, -205, -198, -192, -186, + -180, -175, -170, -165, -161, -156, -152, -148, + -145, -141, -138, -134, -131, -128, -125, -122, + -120, -117, -114, -112, -110, -107, -105, -103, + -100, -98, -96, -94, -92, -90, -88, -86, + -85, -83, -81, -79, -78, -76, -74, -73, + -71, -70, -68, -67, -65, -64, -62, -61, + -60, -58, -57, -56, -54, -53, -52, -51, + -49, -48, -47, -46, -45, -43, -42, -41, + -40, -39, -38, -37, -36, -35, -34, -33, + -32, -31, -30, -29, -28, -27, -26, -25, + -24, -23, -23, -22, -21, -20, -19, -18, + -17, -17, -16, -15, -14, -13, -12, -12, + -11, -10, -9, -9, -8, -7, -6, -6, + -5, -4, -3, -3, -2, -1, -1, 0, +}; + +// not used in pokediamond +//const s16 SNDi_DecibelSquareTable[0x80] = { +// -32768,-722,-721, -651, -601, -562, -530, -503, +// -480, -460, -442, -425, -410, -396, -383, -371, +// -360, -349, -339, -330, -321, -313, -305, -297, +// -289, -282, -276, -269, -263, -257, -251, -245, +// -239, -234, -229, -224, -219, -214, -210, -205, +// -201, -196, -192, -188, -184, -180, -176, -173, +// -169, -165, -162, -158, -155, -152, -149, -145, +// -142, -139, -136, -133, -130, -127, -125, -122, +// -119, -116, -114, -111, -109, -106, -103, -101, +// -99, -96, -94, -91, -89, -87, -85, -82, +// -80, -78, -76, -74, -72, -70, -68, -66, +// -64, -62, -60, -58, -56, -54, -52, -50, +// -49, -47, -45, -43, -42, -40, -38, -36, +// -35, -33, -31, -30, -28, -27, -25, -23, +// -22, -20, -19, -17, -16, -14, -13, -11, +// -10, -8, -7, -6, -4, -3, -1, 0, +//}; + +ARM_FUNC u16 SND_CalcChannelVolume(s32 x) { + // directly using s32 doesn't match + int decibels = (int)x; + if (decibels < -723) + decibels = -723; + else if (decibels > 0) + decibels = 0; + + u32 resultLo = sVolumeTable[decibels + 723]; + u32 resultHi; + + if (decibels < -240) { + resultHi = 3; + } else { + if (decibels < -120) { + resultHi = 2; + } else { + if (decibels < -60) { + resultHi = 1; + } else { + resultHi = 0; + } + } + } + + return (u16)((resultHi << 8u) | resultLo); +} diff --git a/arm9/lib/src/SND_work.c b/arm9/lib/src/SND_work.c new file mode 100644 index 00000000..a0fb547d --- /dev/null +++ b/arm9/lib/src/SND_work.c @@ -0,0 +1,115 @@ +#include "SND_work.h" +#include "SND_alarm.h" +#include "SND_main.h" + +struct SNDSharedWork *SNDi_SharedWork; + +void DC_InvalidateRange(void *mem, u32 size); +void DC_FlushRange(void *mem, u32 size); + +u32 SND_GetPlayerStatus(void) { + DC_InvalidateRange(&SNDi_SharedWork->playerStatus, 4); + return SNDi_SharedWork->playerStatus; +} + +u16 SND_GetChannelStatus(void) { + DC_InvalidateRange(&SNDi_SharedWork->channelStatus, 2); + return SNDi_SharedWork->channelStatus; +} + +//u16 SND_GetCaptureStatus(void) { +// DC_InvalidateRange(&SNDi_SharedWork->captureStatus, 2); +// return SNDi_SharedWork->captureStatus; +//} + +u32 SND_GetPlayerTickCounter(u32 playerId) { + DC_InvalidateRange(&SNDi_SharedWork->players[playerId].tickCounter, 4); + return SNDi_SharedWork->players[playerId].tickCounter; +} + +//s16 SND_GetPlayerLocalVariable(u32 playerId, u32 var) { +// DC_InvalidateRange(&SNDi_SharedWork->players[playerId].localVars[var], 2); +// return SNDi_SharedWork->players[playerId].localVars[var]; +//} +// +//s16 SND_GetPlayerLocalVariable(u32 var) { +// DC_InvalidateRange(&SNDi_SharedWork->globalVars[var], 2); +// return SNDi_SharedWork->globalVars[var]; +//} +// +//BOOL SND_ReadChannelInfo(const SNDDriverInfo *driverInfo, s32 chnId, SNDChannelInfo *chnInfo) { +// // T O D O, implement if it's actually used +//} +// +//BOOL SND_ReadPlayerInfo(const SNDDriverInfo *driverInfo, s32 playerId, SNDPlayerInfo *playerInfo) { +// if (playerId < 0 || playerId >= SND_PLAYER_COUNT) +// return FALSE; +// SNDPlayer *player = &driverInfo->work.players[playerId]; +// playerInfo->trackBitMask = 0; +// for (s32 i = 0; i < SND_TRACK_COUNT; i++) { +// if (player->tracks[i] != SND_INVALID_TRACK_INDEX) { +// playerInfo->trackBitMask |= (1 << i); +// } +// } +// playerInfo->flags.active = player->flags.active; +// playerInfo->flags.paused = player->flags.paused; +// playerInfo->tempo = player->tempo; +// playerInfo->volume = player->volume; +// return TRUE; +//} +// +// +//BOOL SND_ReadTrackInfo(const SNDDriverInfo *driverInfo s32 playerId, s32 trackId, SNDTrackInfo *trackInfo) { +// if (playerId < 0 || playerId >= SND_PLAYER_COUNT) +// return FALSE; +// if (trackId < 0 || trackId >= SND_TRACK_COUNT) +// return FALSE; +// SNDPlayer *player = &driverInfo->work.players[playerId]; +// if (player->tracks[trackId] == SND_INVALID_TRACK_INDEX) +// return FALSE; +// SNDTrack *track = &driverInfo->work.tracks[trackId]; +// trackInfo->program = track->program; +// trackInfo->volume = track->volume; +// trackInfo->expression = track->expression; +// trackInfo->pitchBend = track->pitchBend; +// trackInfo->bendRange = track->bendRange; +// trackInfo->pan = track->pan + 0x40; // 0x40 == MIDI center pan +// trackInfo->transpose = track->transpose; +// trackInfo->chnCount = 0; +// +// //#define LL_READ_PTR(ptr, basePtr, base) (ptr ? ((typeof(ptr))(s32)(ptr) - (s32)(basePtr) + (s32)&(base)) : NULL) +// //for (SNDExChannel *exChn = LL_READ_PTR(track->channelLLHead, driverInfo->workPtr, driverInfo->work); +// // exChn != NULL; exChn = LL_READ_PTR(exChn->channelLLNext, driverInfo->workPtr, driverInfo->work)) +// //{ +// // trackInfo->channel[trackInfo->chnCount] = exChn->id; +// // trackInfo->chnCount++; +// //} +// //#undef LL_READ_PTR +// +// return TRUE; +//} + +ARM_FUNC u32 SNDi_GetFinishedCommandTag(void) { + DC_InvalidateRange(&SNDi_SharedWork->finishedCommandTag, 4); + return SNDi_SharedWork->finishedCommandTag; +} + +ARM_FUNC void SNDi_InitSharedWork(struct SNDSharedWork *sw) { + sw->playerStatus = 0; + sw->channelStatus = 0; + sw->captureStatus = 0; + sw->finishedCommandTag = 0; + + for (s32 i = 0; i < SND_PLAYER_COUNT; i++) { + sw->players[i].tickCounter = 0; + for (s32 j = 0; j < 16; j++) { + sw->players[i].localVars[j] = -1; + } + } + + for (s32 i = 0; i < 16; i++) { + sw->globalVars[i] = -1; + } + + DC_FlushRange(sw, sizeof(*sw)); +} |