#include <3ds/os.h>
#include <3ds/services/csnd.h>
-//See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
+// See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
-Handle CSND_handle = 0;
-Handle CSND_mutexhandle = 0;
-Handle CSND_sharedmemhandle = 0;
-u32 *CSND_sharedmem = NULL;
-static u32 CSND_bitmask=0;
+static Handle csndHandle = 0;
+static Handle csndMutex = 0;
+static Handle csndSharedMemBlock = 0;
+static u32* csndSharedMem = NULL;
+static u32 csndBitmask = 0;
-static u32 CSND_sharedmem_cmdblocksize = 0x2000;
-static u32 CSND_sharedmem_startcmdoff = 0;
-static u32 CSND_sharedmem_currentcmdoff = 0;
+static u32 csndCmdBlockSize = 0x2000;
+static u32 csndCmdStartOff = 0;
+static u32 csndCmdCurOff = 0;
-Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
+static Result CSND_Initialize(u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[4] = off2;
cmdbuf[5] = off3;
- if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
+ if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
- *mutexhandle = cmdbuf[3];
- *sharedmemhandle = cmdbuf[4];
+ csndMutex = cmdbuf[3];
+ csndSharedMemBlock = cmdbuf[4];
return (Result)cmdbuf[1];
}
-Result CSND_cmd2()
+static Result CSND_Shutdown()
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020000;
- if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
+ if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
-Result CSND_cmd5(u32 *bitmask)
+static Result CSND_GetBitmask(u32* bitmask)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00050000;
- if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
+ if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
*bitmask = cmdbuf[2];
return (Result)cmdbuf[1];
}
-Result CSND_initialize(u32* sharedMem)
+Result csndInit(void)
{
Result ret=0;
+ csndSharedMem = (u32*)CSND_SHAREDMEM_DEFAULT;
- if(sharedMem==NULL)sharedMem = (u32*)CSND_SHAREDMEM_DEFAULT;
- CSND_sharedmem = sharedMem;
+ // TODO: proper error handling!
- ret = srvGetServiceHandle(&CSND_handle, "csnd:SND");
- if(ret!=0)return ret;
+ ret = srvGetServiceHandle(&csndHandle, "csnd:SND");
+ if (ret != 0) return ret;
- 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);
- if(ret!=0)return ret;
+ u32 sharedMemSize = csndCmdBlockSize+0x114;
- ret = svcMapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem, 3, 0x10000000);
- if(ret!=0)return ret;
+ ret = CSND_Initialize(sharedMemSize, csndCmdBlockSize, csndCmdBlockSize+8, csndCmdBlockSize+0xc8, csndCmdBlockSize+0xd8);
+ if (ret != 0) return ret;
- memset(CSND_sharedmem, 0, 0x2114);
+ ret = svcMapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem, 3, 0x10000000);
+ if (ret != 0) return ret;
- ret = CSND_cmd5(&CSND_bitmask);
- if(ret!=0)return ret;
+ memset(csndSharedMem, 0, sharedMemSize);
+
+ ret = CSND_GetBitmask(&csndBitmask);
+ if (ret != 0) return ret;
return 0;
}
-Result CSND_shutdown()
+Result csndExit(void)
{
Result ret;
- svcUnmapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem);
- svcCloseHandle(CSND_sharedmemhandle);
+ svcUnmapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem);
+ svcCloseHandle(csndSharedMemBlock);
- ret = CSND_cmd2();
- if(ret!=0)return ret;
-
- return svcCloseHandle(CSND_handle);
+ ret = CSND_Shutdown();
+ svcCloseHandle(csndHandle);
+ return ret;
}
-Result CSND_cmd3(u32 offset)
+static Result CSND_ExecCommand20(u32 offset)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00030040;
cmdbuf[1] = offset;
- if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
+ if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
-void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams)
+static void csndWriteCmdType0(int cmdid, u8 *cmdparams)
{
- u16 *ptr;
+ u16* ptr;
u32 prevoff;
s32 outindex=0;
- svcWaitSynchronizationN(&outindex, &CSND_mutexhandle, 1, 0, ~0);
+ svcWaitSynchronizationN(&outindex, &csndMutex, 1, 0, ~0);
- if(CSND_sharedmem_startcmdoff != CSND_sharedmem_currentcmdoff)
+ if (csndCmdStartOff != csndCmdCurOff)
{
- if(CSND_sharedmem_currentcmdoff>=0x20)
- {
- prevoff = CSND_sharedmem_currentcmdoff-0x20;
- }
+ if (csndCmdCurOff>=0x20)
+ prevoff = csndCmdCurOff-0x20;
else
- {
- prevoff = CSND_sharedmem_cmdblocksize-0x20;
- }
+ prevoff = csndCmdBlockSize-0x20;
- ptr = (u16*)&CSND_sharedmem[prevoff>>2];
- *ptr = CSND_sharedmem_currentcmdoff;
+ ptr = (u16*)&csndSharedMem[prevoff>>2];
+ *ptr = csndCmdCurOff;
}
- ptr = (u16*)&CSND_sharedmem[CSND_sharedmem_currentcmdoff>>2];
+ ptr = (u16*)&csndSharedMem[csndCmdCurOff>>2];
ptr[0] = 0xffff;
ptr[1] = cmdid;
ptr[3] = 0;
memcpy(&ptr[8>>1], cmdparams, 0x18);
- CSND_sharedmem_currentcmdoff+= 0x20;
- if(CSND_sharedmem_currentcmdoff >= CSND_sharedmem_cmdblocksize)CSND_sharedmem_currentcmdoff = 0;
+ csndCmdCurOff += 0x20;
+ if (csndCmdCurOff >= csndCmdBlockSize)
+ csndCmdCurOff = 0;
- svcReleaseMutex(CSND_mutexhandle);
+ svcReleaseMutex(csndMutex);
}
-Result CSND_processtype0cmds()
+static Result csndExecCmdType0()
{
Result ret=0;
- if(CSND_sharedmem_startcmdoff == CSND_sharedmem_currentcmdoff)return 0;
+ // Check we actually wrote commands
+ if (csndCmdStartOff == csndCmdCurOff)
+ return 0;
- ret = CSND_cmd3(CSND_sharedmem_startcmdoff);
- CSND_sharedmem_startcmdoff = CSND_sharedmem_currentcmdoff;
+ ret = CSND_ExecCommand20(csndCmdStartOff);
+ csndCmdStartOff = csndCmdCurOff;
return ret;
}
-u32 CSND_convertsamplerate(u32 samplerate)
-{
- return (u32)(6.7027964E+07f / ((float)samplerate));
-}
-
-void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
+void csndSharedMemtype0_cmd0(u32 channel, u32 value)
{
u32 cmdparams[0x18>>2];
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value;
- CSND_writesharedmem_cmdtype0(0x0, (u8*)&cmdparams);
+ csndWriteCmdType0(0x0, (u8*)&cmdparams);
}
void CSND_setchannel_playbackstate(u32 channel, u32 value)
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value;
- CSND_writesharedmem_cmdtype0(0x1, (u8*)&cmdparams);
+ csndWriteCmdType0(0x1, (u8*)&cmdparams);
}
-void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
+void csndSharedMemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
{
u32 cmdparams[0x18>>2];
cmdparams[1] = physaddr;
cmdparams[2] = size;
- CSND_writesharedmem_cmdtype0(0x3, (u8*)&cmdparams);
+ csndWriteCmdType0(0x3, (u8*)&cmdparams);
}
-void CSND_sharedmemtype0_cmd9(u32 channel, u16 value)
+void csndSharedMemtype0_cmd9(u32 channel, u16 value)
{
u32 cmdparams[0x18>>2];
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value | (value<<16);
- CSND_writesharedmem_cmdtype0(0x9, (u8*)&cmdparams);
+ csndWriteCmdType0(0x9, (u8*)&cmdparams);
}
-void CSND_sharedmemtype0_cmd8(u32 channel, u32 samplerate)
+void csndSharedMemtype0_cmd8(u32 channel, u32 samplerate)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
- cmdparams[1] = CSND_convertsamplerate(samplerate);
+ cmdparams[1] = CSND_TIMER(samplerate);
- CSND_writesharedmem_cmdtype0(0x8, (u8*)&cmdparams);
+ csndWriteCmdType0(0x8, (u8*)&cmdparams);
}
-void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
+void csndSharedMemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
{
u32 val;
u32 cmdparams[0x18>>2];
cmdparams[0] |= (encoding & 3) << 12;
cmdparams[0] |= (unk1 & 3) << 14;
- val = CSND_convertsamplerate(samplerate);
+ val = CSND_TIMER(samplerate);
if(val<0x42)val = 0x42;
if(val>0xffff)val = 0xffff;
cmdparams[0] |= val<<16;
cmdparams[4] = physaddr1;
cmdparams[5] = totalbytesize;
- CSND_writesharedmem_cmdtype0(0xe, (u8*)&cmdparams);
+ csndWriteCmdType0(0xe, (u8*)&cmdparams);
}
-Result CSND_sharedmemtype0_cmdupdatestate(int waitdone)
+Result csndSharedMemtype0_cmdupdatestate(int waitdone)
{
u8 *ptr;
int ret=0;
memset(cmdparams, 0, 0x18);
- ptr = (u8*)&CSND_sharedmem[CSND_sharedmem_startcmdoff>>2];
+ ptr = (u8*)&csndSharedMem[csndCmdStartOff>>2];
- CSND_writesharedmem_cmdtype0(0x300, (u8*)&cmdparams);
+ csndWriteCmdType0(0x300, (u8*)&cmdparams);
- ret = CSND_processtype0cmds();
+ ret = csndExecCmdType0();
if(ret!=0)return ret;
if(waitdone)
physaddr0 = osConvertVirtToPhys((u32)vaddr0);
physaddr1 = osConvertVirtToPhys((u32)vaddr1);
- CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize);
- CSND_sharedmemtype0_cmd8(channel, samplerate);
+ csndSharedMemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize);
+ csndSharedMemtype0_cmd8(channel, samplerate);
if(looping)
{
if(physaddr1>physaddr0)totalbytesize-= (u32)physaddr1 - (u32)physaddr0;
- CSND_sharedmemtype0_cmd3(channel, physaddr1, totalbytesize);
+ csndSharedMemtype0_cmd3(channel, physaddr1, totalbytesize);
}
- CSND_sharedmemtype0_cmd8(channel, samplerate);
- CSND_sharedmemtype0_cmd9(channel, 0xffff);
+ csndSharedMemtype0_cmd8(channel, samplerate);
+ csndSharedMemtype0_cmd9(channel, 0xffff);
CSND_setchannel_playbackstate(channel, 1);
- return CSND_sharedmemtype0_cmdupdatestate(0);
+ return csndSharedMemtype0_cmdupdatestate(0);
}
Result CSND_getchannelstate(u32 entryindex, struct CSND_CHANNEL_STATUS *out)
{
Result ret=0;
- if((ret = CSND_sharedmemtype0_cmdupdatestate(1))!=0)return ret;
+ if((ret = csndSharedMemtype0_cmdupdatestate(1))!=0)return ret;
- memcpy(out, &CSND_sharedmem[(CSND_sharedmem_cmdblocksize+8 + entryindex*0xc) >> 2], 0xc);
- out->position -= 0x0c000000;
+ memcpy(out, &csndSharedMem[(csndCmdBlockSize+8 + entryindex*0xc) >> 2], 0xc);
+ out[2] -= 0x0c000000;
return 0;
}