From 59009d531db7b27c02b6371be553871a3b4ba401 Mon Sep 17 00:00:00 2001 From: fincs Date: Thu, 1 Jan 2015 20:04:31 +0100 Subject: [PATCH] Partially fix csndChnGetState() and csndChnIsPlaying() --- libctru/include/3ds/services/csnd.h | 27 ++++++++++-- libctru/source/services/csnd.c | 66 +++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/libctru/include/3ds/services/csnd.h b/libctru/include/3ds/services/csnd.h index ef6656d..a28fc19 100644 --- a/libctru/include/3ds/services/csnd.h +++ b/libctru/include/3ds/services/csnd.h @@ -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); diff --git a/libctru/source/services/csnd.c b/libctru/source/services/csnd.c index 59ce9a1..0237c3f 100644 --- a/libctru/source/services/csnd.c +++ b/libctru/source/services/csnd.c @@ -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; } -