]> Chaos Git - corbenik/ctrulib.git/commitdiff
Partially fix csndChnGetState() and csndChnIsPlaying()
authorfincs <fincs.alt1@gmail.com>
Thu, 1 Jan 2015 19:04:31 +0000 (20:04 +0100)
committerfincs <fincs.alt1@gmail.com>
Tue, 20 Jan 2015 16:54:33 +0000 (17:54 +0100)
libctru/include/3ds/services/csnd.h
libctru/source/services/csnd.c

index ef6656d720123693320b92926550c4363c5a7305..a28fc19da70934296ce18608e1125b4930cf56fb 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
-
 #include <3ds/types.h>
 
+#define CSND_NUM_CHANNELS 32
 #define CSND_SHAREDMEM_DEFAULT 0x10004000
 
 #define CSND_TIMER(n) (0x3FEC3FC / ((u32)(n)))
@@ -18,8 +18,27 @@ typedef enum{
     CSND_ENCODING_PSG, // Similar to DS?
 } CSND_ENCODING;
 
+typedef union
+{
+       u32 value[3];
+       struct
+       {
+               u8 active;
+               u8 _pad1;
+               u16 _pad2;
+               s16 adpcmSample;
+               u8 adpcmIndex;
+               u8 _pad3;
+               u32 samplePAddr;
+       };
+} CSND_ChnInfo;
+
 // See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
 
+extern vu32* csndSharedMem;
+extern u32 csndSharedMemSize;
+extern u32 csndChannels; // Bitmask of channels that are allowed for usage
+
 Result csndInit(void);
 Result csndExit(void);
 
@@ -37,5 +56,7 @@ Result CSND_UpdateChnInfo(bool waitDone);
 
 Result csndChnPlaySound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1);
 
-Result csndChnGetState(u32 entryindex, u32 *out);
-Result csndChnIsPlaying(u32 entryindex, u8 *status);
+CSND_ChnInfo* csndChnGetInfo(u32 channel); // Requires previous CSND_UpdateChnInfo()
+
+Result csndChnGetState(u32 channel, u32 *out);
+Result csndChnIsPlaying(u32 channel, u8 *status);
index 59ce9a1993e82d8f5d0bab92ed147b2a4fd9acd7..0237c3fea2450b3f2ebe95676468fbe3415f184f 100644 (file)
@@ -8,12 +8,15 @@
 
 // See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
 
+vu32* csndSharedMem = NULL;
+u32 csndSharedMemSize;
+u32 csndChannels = 0;
+
 static Handle csndHandle = 0;
 static Handle csndMutex = 0;
 static Handle csndSharedMemBlock = 0;
-static vu32* csndSharedMem = NULL;
-static u32 csndBitmask = 0;
 
+static u8 csndChnIdx[CSND_NUM_CHANNELS];
 static u32 csndCmdBlockSize = 0x2000;
 static u32 csndCmdStartOff = 0;
 static u32 csndCmdCurOff = 0;
@@ -50,7 +53,7 @@ static Result CSND_Shutdown()
        return (Result)cmdbuf[1];
 }
 
-static Result CSND_GetBitmask(u32* bitmask)
+static Result CSND_AcquireSoundChannels(u32* channelMask)
 {
        Result ret=0;
        u32 *cmdbuf = getThreadCommandBuffer();
@@ -59,7 +62,19 @@ static Result CSND_GetBitmask(u32* bitmask)
 
        if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
 
-       *bitmask = cmdbuf[2];
+       *channelMask = cmdbuf[2];
+
+       return (Result)cmdbuf[1];
+}
+
+static Result CSND_ReleaseSoundChannels(void)
+{
+       Result ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x00060000;
+
+       if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
 
        return (Result)cmdbuf[1];
 }
@@ -74,19 +89,32 @@ Result csndInit(void)
        ret = srvGetServiceHandle(&csndHandle, "csnd:SND");
        if (ret != 0) return ret;
 
-       u32 sharedMemSize = csndCmdBlockSize+0x114;
+       u32 offset0 = csndCmdBlockSize;
+       u32 offset1 = offset0 + 8;
+       u32 offset2 = offset1 + 32*sizeof(CSND_ChnInfo);
+       u32 offset3 = offset2 + 0x10;
+       csndSharedMemSize = offset3 + 0x3C;
 
-       ret = CSND_Initialize(sharedMemSize, csndCmdBlockSize, csndCmdBlockSize+8, csndCmdBlockSize+0xc8, csndCmdBlockSize+0xd8);
+       ret = CSND_Initialize(csndSharedMemSize, offset0, offset1, offset2, offset3);
        if (ret != 0) return ret;
 
        ret = svcMapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem, 3, 0x10000000);
        if (ret != 0) return ret;
 
-       memset((void*)csndSharedMem, 0, sharedMemSize);
+       memset((void*)csndSharedMem, 0, csndSharedMemSize);
 
-       ret = CSND_GetBitmask(&csndBitmask);
+       ret = CSND_AcquireSoundChannels(&csndChannels);
        if (ret != 0) return ret;
 
+       // Build index table
+       int i, j = 0;
+       for (i = 0; i < CSND_NUM_CHANNELS; i ++)
+       {
+               csndChnIdx[i] = j;
+               if (csndChannels & BIT(i))
+                       j ++;
+       }
+
        return 0;
 }
 
@@ -94,6 +122,9 @@ Result csndExit(void)
 {
        Result ret;
 
+       ret = CSND_ReleaseSoundChannels();
+       if (ret != 0) return ret;
+
        svcUnmapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem);
        svcCloseHandle(csndSharedMemBlock);
 
@@ -265,6 +296,9 @@ Result CSND_UpdateChnInfo(bool waitDone)
 
 Result csndChnPlaySound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1)
 {
+       if (!(csndChannels & BIT(channel)))
+               return 1;
+
        u32 physaddr0 = 0;
        u32 physaddr1 = 0;
 
@@ -283,28 +317,34 @@ Result csndChnPlaySound(u32 channel, u32 looping, u32 encoding, u32 samplerate,
        return CSND_UpdateChnInfo(false);
 }
 
-Result csndChnGetState(u32 entryindex, u32 *out)
+CSND_ChnInfo* csndChnGetInfo(u32 channel)
+{
+       channel = csndChnIdx[channel];
+       return (CSND_ChnInfo*)(&csndSharedMem[(csndCmdBlockSize+8 + channel*0xc) >> 2]);
+}
+
+Result csndChnGetState(u32 channel, u32 *out)
 {
        Result ret = 0;
+       channel = csndChnIdx[channel];
 
        if((ret = CSND_UpdateChnInfo(true)) != 0)return ret;
 
-       memcpy(out, (const void*)&csndSharedMem[(csndCmdBlockSize+8 + entryindex*0xc) >> 2], 0xc);
+       memcpy(out, (const void*)&csndSharedMem[(csndCmdBlockSize+8 + channel*0xc) >> 2], 0xc);
        //out[2] -= 0x0c000000;
 
        return 0;
 }
 
-Result csndChnIsPlaying(u32 entryindex, u8 *status)
+Result csndChnIsPlaying(u32 channel, u8 *status)
 {
        Result ret;
        struct CSND_CHANNEL_STATUS entry;
 
-       ret = csndChnGetState(entryindex, entry);
+       ret = csndChnGetState(channel, entry);
        if(ret!=0)return ret;
 
        *status = entry.state;
 
        return 0;
 }
-