My Project
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
csnd.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <string.h>
3 #include <3ds.h>
4 
5 //See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
6 
11 static u32 CSND_bitmask=0;
12 
13 static u32 CSND_sharedmem_cmdblocksize = 0x2000;
14 static u32 CSND_sharedmem_startcmdoff = 0;
15 static u32 CSND_sharedmem_currentcmdoff = 0;
16 
17 Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
18 {
19  Result ret=0;
20  u32 *cmdbuf = getThreadCommandBuffer();
21 
22  cmdbuf[0] = 0x00010140;
23  cmdbuf[1] = sharedmem_size;
24  cmdbuf[2] = off0;
25  cmdbuf[3] = off1;
26  cmdbuf[4] = off2;
27  cmdbuf[5] = off3;
28 
29  if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
30 
31  *mutexhandle = cmdbuf[3];
32  *sharedmemhandle = cmdbuf[4];
33 
34  return (Result)cmdbuf[1];
35 }
36 
38 {
39  Result ret=0;
40  u32 *cmdbuf = getThreadCommandBuffer();
41 
42  cmdbuf[0] = 0x00020000;
43 
44  if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
45 
46  return (Result)cmdbuf[1];
47 }
48 
49 Result CSND_cmd5(u32 *bitmask)
50 {
51  Result ret=0;
52  u32 *cmdbuf = getThreadCommandBuffer();
53 
54  cmdbuf[0] = 0x00050000;
55 
56  if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
57 
58  *bitmask = cmdbuf[2];
59 
60  return (Result)cmdbuf[1];
61 }
62 
64 {
65  Result ret=0;
66 
67  if(sharedMem==NULL)sharedMem = (u32*)CSND_SHAREDMEM_DEFAULT;
68  CSND_sharedmem = sharedMem;
69 
70  ret = srvGetServiceHandle(&CSND_handle, "csnd:SND");
71  if(ret!=0)return ret;
72 
73  ret = CSND_cmd1(&CSND_mutexhandle, &CSND_sharedmemhandle, CSND_sharedmem_cmdblocksize+0x114, CSND_sharedmem_cmdblocksize, CSND_sharedmem_cmdblocksize+8, CSND_sharedmem_cmdblocksize+0xc8, CSND_sharedmem_cmdblocksize+0xd8);
74  if(ret!=0)return ret;
75 
77  if(ret!=0)return ret;
78 
79  memset(CSND_sharedmem, 0, 0x2114);
80 
81  ret = CSND_cmd5(&CSND_bitmask);
82  if(ret!=0)return ret;
83 
84  return 0;
85 }
86 
88 {
89  Result ret;
90 
93 
94  ret = CSND_cmd2();
95  if(ret!=0)return ret;
96 
98 }
99 
101 {
102  Result ret=0;
103  u32 *cmdbuf = getThreadCommandBuffer();
104 
105  cmdbuf[0] = 0x00030040;
106  cmdbuf[1] = offset;
107 
108  if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
109 
110  return (Result)cmdbuf[1];
111 }
112 
113 void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams)
114 {
115  u16 *ptr;
116  u32 prevoff;
117  s32 outindex=0;
118 
119  svcWaitSynchronizationN(&outindex, &CSND_mutexhandle, 1, 0, ~0);
120 
121  if(CSND_sharedmem_startcmdoff != CSND_sharedmem_currentcmdoff)
122  {
123  if(CSND_sharedmem_currentcmdoff>=0x20)
124  {
125  prevoff = CSND_sharedmem_currentcmdoff-0x20;
126  }
127  else
128  {
129  prevoff = CSND_sharedmem_cmdblocksize-0x20;
130  }
131 
132  ptr = (u16*)&CSND_sharedmem[prevoff>>2];
133  *ptr = CSND_sharedmem_currentcmdoff;
134  }
135 
136  ptr = (u16*)&CSND_sharedmem[CSND_sharedmem_currentcmdoff>>2];
137 
138  ptr[0] = 0xffff;
139  ptr[1] = cmdid;
140  ptr[2] = 0;
141  ptr[3] = 0;
142  memcpy(&ptr[8>>1], cmdparams, 0x18);
143 
144  CSND_sharedmem_currentcmdoff+= 0x20;
145  if(CSND_sharedmem_currentcmdoff >= CSND_sharedmem_cmdblocksize)CSND_sharedmem_currentcmdoff = 0;
146 
148 }
149 
151 {
152  Result ret=0;
153 
154  if(CSND_sharedmem_startcmdoff == CSND_sharedmem_currentcmdoff)return 0;
155 
156  ret = CSND_cmd3(CSND_sharedmem_startcmdoff);
157  CSND_sharedmem_startcmdoff = CSND_sharedmem_currentcmdoff;
158 
159  return ret;
160 }
161 
163 {
164  return (u32)(6.7027964E+07f / ((float)samplerate));
165 }
166 
167 void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
168 {
169  u32 cmdparams[0x18>>2];
170 
171  memset(cmdparams, 0, 0x18);
172 
173  cmdparams[0] = channel & 0x1f;
174  cmdparams[1] = value;
175 
176  CSND_writesharedmem_cmdtype0(0x0, (u8*)&cmdparams);
177 }
178 
180 {
181  u32 cmdparams[0x18>>2];
182 
183  memset(cmdparams, 0, 0x18);
184 
185  cmdparams[0] = channel & 0x1f;
186  cmdparams[1] = value;
187 
188  CSND_writesharedmem_cmdtype0(0x1, (u8*)&cmdparams);
189 }
190 
191 void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
192 {
193  u32 cmdparams[0x18>>2];
194 
195  memset(cmdparams, 0, 0x18);
196 
197  cmdparams[0] = channel & 0x1f;
198  cmdparams[1] = physaddr;
199  cmdparams[2] = size;
200 
201  CSND_writesharedmem_cmdtype0(0x3, (u8*)&cmdparams);
202 }
203 
204 void CSND_sharedmemtype0_cmd9(u32 channel, u16 value)
205 {
206  u32 cmdparams[0x18>>2];
207 
208  memset(cmdparams, 0, 0x18);
209 
210  cmdparams[0] = channel & 0x1f;
211  cmdparams[1] = value | (value<<16);
212 
213  CSND_writesharedmem_cmdtype0(0x9, (u8*)&cmdparams);
214 }
215 
216 void CSND_sharedmemtype0_cmd8(u32 channel, u32 samplerate)
217 {
218  u32 cmdparams[0x18>>2];
219 
220  memset(cmdparams, 0, 0x18);
221 
222  cmdparams[0] = channel & 0x1f;
223  cmdparams[1] = CSND_convertsamplerate(samplerate);
224 
225  CSND_writesharedmem_cmdtype0(0x8, (u8*)&cmdparams);
226 }
227 
228 void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
229 {
230  u32 val;
231  u32 cmdparams[0x18>>2];
232 
233  memset(cmdparams, 0, 0x18);
234 
235  cmdparams[0] = channel & 0x1f;
236  cmdparams[0] |= (unk0 & 0xf) << 6;
237  if(!looping)cmdparams[0] |= 2 << 10;
238  if(looping)cmdparams[0] |= 1 << 10;
239  cmdparams[0] |= (encoding & 3) << 12;
240  cmdparams[0] |= (unk1 & 3) << 14;
241 
242  val = CSND_convertsamplerate(samplerate);
243  if(val<0x42)val = 0x42;
244  if(val>0xffff)val = 0xffff;
245  cmdparams[0] |= val<<16;
246 
247  cmdparams[3] = physaddr0;
248  cmdparams[4] = physaddr1;
249  cmdparams[5] = totalbytesize;
250 
251  CSND_writesharedmem_cmdtype0(0xe, (u8*)&cmdparams);
252 }
253 
255 {
256  u8 *ptr;
257  int ret=0;
258 
259  u32 cmdparams[0x18>>2];
260 
261  memset(cmdparams, 0, 0x18);
262 
263  ptr = (u8*)&CSND_sharedmem[CSND_sharedmem_startcmdoff>>2];
264 
265  CSND_writesharedmem_cmdtype0(0x300, (u8*)&cmdparams);
266 
267  ret = CSND_processtype0cmds();
268  if(ret!=0)return ret;
269 
270  if(waitdone)
271  {
272  while(*ptr == 0);
273  }
274 
275  return 0;
276 }
277 
278 Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1)
279 {
280  u32 physaddr0 = 0;
281  u32 physaddr1 = 0;
282 
283  physaddr0 = osConvertVirtToPhys((u32)vaddr0);
284  physaddr1 = osConvertVirtToPhys((u32)vaddr1);
285 
286  CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize);
287  CSND_sharedmemtype0_cmd8(channel, samplerate);
288  if(looping)
289  {
290  if(physaddr1>physaddr0)totalbytesize-= (u32)physaddr1 - (u32)physaddr0;
291  CSND_sharedmemtype0_cmd3(channel, physaddr1, totalbytesize);
292  }
293  CSND_sharedmemtype0_cmd8(channel, samplerate);
294  CSND_sharedmemtype0_cmd9(channel, 0xffff);
295  CSND_setchannel_playbackstate(channel, 1);
296 
298 }
299 
301 {
302  Result ret=0;
303 
304  if((ret = CSND_sharedmemtype0_cmdupdatestate(1))!=0)return ret;
305 
306  memcpy(out, &CSND_sharedmem[(CSND_sharedmem_cmdblocksize+8 + entryindex*0xc) >> 2], 0xc);
307  out[2] -= 0x0c000000;
308 
309  return 0;
310 }
311 
313 {
314  Result ret;
315  u32 entry[0xc>>2];
316 
317  ret = CSND_getchannelstate(entryindex, entry);
318  if(ret!=0)return ret;
319 
320  *status = entry[0] & 0xff;
321 
322  return 0;
323 }
324 
Handle CSND_sharedmemhandle
Definition: csnd.c:9
Result CSND_initialize(u32 *sharedMem)
Definition: csnd.c:63
Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1)
Definition: csnd.c:278
void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
Definition: csnd.c:167
s32 Result
Definition: types.h:42
#define CSND_SHAREDMEM_DEFAULT
Definition: csnd.h:3
void CSND_sharedmemtype0_cmd8(u32 channel, u32 samplerate)
Definition: csnd.c:216
s32 svcCloseHandle(Handle handle)
uint16_t u16
Definition: types.h:22
Result srvGetServiceHandle(Handle *out, const char *name)
Definition: srv.c:109
Result CSND_cmd3(u32 offset)
Definition: csnd.c:100
u32 * CSND_sharedmem
Definition: csnd.c:10
Result CSND_shutdown()
Definition: csnd.c:87
Result CSND_cmd2()
Definition: csnd.c:37
u32 Handle
Definition: types.h:41
s32 svcUnmapMemoryBlock(Handle memblock, u32 addr)
u32 osConvertVirtToPhys(u32 vaddr)
Definition: os.c:19
Handle CSND_handle
Definition: csnd.c:7
u32 * getThreadCommandBuffer(void)
uint8_t u8
Definition: types.h:21
Result CSND_getchannelstate(u32 entryindex, u32 *out)
Definition: csnd.c:300
void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams)
Definition: csnd.c:113
uint32_t u32
Definition: types.h:23
void CSND_setchannel_playbackstate(u32 channel, u32 value)
Definition: csnd.c:179
int32_t s32
Definition: types.h:28
u32 CSND_convertsamplerate(u32 samplerate)
Definition: csnd.c:162
Handle CSND_mutexhandle
Definition: csnd.c:8
void CSND_sharedmemtype0_cmd9(u32 channel, u16 value)
Definition: csnd.c:204
void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
Definition: csnd.c:228
s32 svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm)
void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
Definition: csnd.c:191
s32 svcSendSyncRequest(Handle session)
Result CSND_processtype0cmds()
Definition: csnd.c:150
Result CSND_sharedmemtype0_cmdupdatestate(int waitdone)
Definition: csnd.c:254
s32 svcReleaseMutex(Handle handle)
Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
Definition: csnd.c:17
Result CSND_cmd5(u32 *bitmask)
Definition: csnd.c:49
Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status)
Definition: csnd.c:312
s32 svcWaitSynchronizationN(s32 *out, Handle *handles, s32 handles_num, bool wait_all, s64 nanoseconds)