summaryrefslogtreecommitdiff
path: root/arm9/lib/src/SND_bank.c
diff options
context:
space:
mode:
authorred031000 <rubenru09@aol.com>2020-05-29 18:45:08 +0100
committerred031000 <rubenru09@aol.com>2020-05-29 18:45:08 +0100
commit0d8876b37adebcda571659089dcff343fccdfc8b (patch)
tree0fc796c2d9a711cd8ba6f1919391a57174aa5b3f /arm9/lib/src/SND_bank.c
parent83d33f36fcf46dec8ea99b86563a19885be4bd8e (diff)
parentd6fd8d1ed926feebffab4154a84eb70a84083bfc (diff)
Merge branch 'master' of https://github.com/martmists/pokediamond
Diffstat (limited to 'arm9/lib/src/SND_bank.c')
-rw-r--r--arm9/lib/src/SND_bank.c175
1 files changed, 175 insertions, 0 deletions
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;
+}