diff --git a/libctru/include/3ds/services/csnd.h b/libctru/include/3ds/services/csnd.h index 84201c9..e66e38c 100644 --- a/libctru/include/3ds/services/csnd.h +++ b/libctru/include/3ds/services/csnd.h @@ -4,30 +4,24 @@ #define CSND_SHAREDMEM_DEFAULT 0x10004000 +#define CSND_TIMER(n) (0x3FEC3FC / ((u32)(n))) + typedef enum{ - CSND_LOOP_DISABLE, - CSND_LOOP_ENABLE + CSND_LOOP_DISABLE, + CSND_LOOP_ENABLE, } CSND_LOOPING; typedef enum{ - CSND_ENCODING_PCM8, - CSND_ENCODING_PCM16, - CSND_ENCODING_IMA_ADPCM, - CSND_ENCODING_PSG//"3 = PSG, similar to DS?" + CSND_ENCODING_PCM8, + CSND_ENCODING_PCM16, + CSND_ENCODING_IMA_ADPCM, + CSND_ENCODING_PSG, // Similar to DS? } CSND_ENCODING; -struct CSND_CHANNEL_STATUS { - u8 state; - u8 pad[3]; - u32 unknown; - u32 position; -} ALIGN(4); +// 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 - -Result CSND_initialize(u32* sharedMem); -Result CSND_shutdown(); +Result csndInit(void); +Result csndExit(void); u32 CSND_convertsamplerate(u32 samplerate); Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1); diff --git a/libctru/source/services/csnd.c b/libctru/source/services/csnd.c index d118329..0751aca 100644 --- a/libctru/source/services/csnd.c +++ b/libctru/source/services/csnd.c @@ -6,19 +6,19 @@ #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(); @@ -30,78 +30,79 @@ Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_siz 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(); @@ -109,35 +110,31 @@ Result CSND_cmd3(u32 offset) 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; @@ -145,30 +142,28 @@ void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams) 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]; @@ -177,7 +172,7 @@ void CSND_sharedmemtype0_cmd0(u32 channel, u32 value) 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) @@ -189,10 +184,10 @@ 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]; @@ -202,10 +197,10 @@ void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size) 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]; @@ -214,22 +209,22 @@ void CSND_sharedmemtype0_cmd9(u32 channel, u16 value) 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]; @@ -243,7 +238,7 @@ void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 sample 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; @@ -252,10 +247,10 @@ void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 sample 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; @@ -264,11 +259,11 @@ Result CSND_sharedmemtype0_cmdupdatestate(int waitdone) 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) @@ -287,28 +282,28 @@ Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u3 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; }