1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#include "SND_bank.h"
#include "OS_mutex.h"
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) {
#pragma unused (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;
}
|