|
|
@ -4,7 +4,6 @@ |
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
#include <cstring>
|
|
|
#include "common/alignment.h"
|
|
|
#include "common/alignment.h"
|
|
|
#include "core/hle/hle.h"
|
|
|
|
|
|
#include "core/hle/kernel/mutex.h"
|
|
|
#include "core/hle/kernel/mutex.h"
|
|
|
#include "core/hle/kernel/shared_memory.h"
|
|
|
#include "core/hle/kernel/shared_memory.h"
|
|
|
#include "core/hle/service/csnd_snd.h"
|
|
|
#include "core/hle/service/csnd_snd.h"
|
|
|
@ -12,72 +11,129 @@ |
|
|
namespace Service { |
|
|
namespace Service { |
|
|
namespace CSND { |
|
|
namespace CSND { |
|
|
|
|
|
|
|
|
const Interface::FunctionInfo FunctionTable[] = { |
|
|
|
|
|
{0x00010140, Initialize, "Initialize"}, |
|
|
|
|
|
{0x00020000, Shutdown, "Shutdown"}, |
|
|
|
|
|
{0x00030040, ExecuteType0Commands, "ExecuteType0Commands"}, |
|
|
|
|
|
{0x00040080, nullptr, "ExecuteType1Commands"}, |
|
|
|
|
|
{0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, |
|
|
|
|
|
{0x00060000, nullptr, "ReleaseSoundChannels"}, |
|
|
|
|
|
{0x00070000, nullptr, "AcquireCaptureDevice"}, |
|
|
|
|
|
{0x00080040, nullptr, "ReleaseCaptureDevice"}, |
|
|
|
|
|
{0x00090082, nullptr, "FlushDataCache"}, |
|
|
|
|
|
{0x000A0082, nullptr, "StoreDataCache"}, |
|
|
|
|
|
{0x000B0082, nullptr, "InvalidateDataCache"}, |
|
|
|
|
|
{0x000C0000, nullptr, "Reset"}, |
|
|
|
|
|
|
|
|
struct Type0Command { |
|
|
|
|
|
// command id and next command offset
|
|
|
|
|
|
u32 command_id; |
|
|
|
|
|
u32 finished; |
|
|
|
|
|
u32 flags; |
|
|
|
|
|
u8 parameters[20]; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
CSND_SND::CSND_SND() { |
|
|
|
|
|
Register(FunctionTable); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong"); |
|
|
|
|
|
|
|
|
static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr; |
|
|
static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr; |
|
|
static Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr; |
|
|
static Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr; |
|
|
|
|
|
|
|
|
void Initialize(Interface* self) { |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* CSND_SND::Initialize service function |
|
|
|
|
|
* Inputs: |
|
|
|
|
|
* 0 : Header Code[0x00010140] |
|
|
|
|
|
* 1 : Shared memory block size, for mem-block creation |
|
|
|
|
|
* Outputs: |
|
|
|
|
|
* 1 : Result of function, 0 on success, otherwise error code |
|
|
|
|
|
* 2 : Handle-list header |
|
|
|
|
|
* 3 : Mutex handle |
|
|
|
|
|
* 4 : Shared memory block handle |
|
|
|
|
|
*/ |
|
|
|
|
|
static void Initialize(Interface* self) { |
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
|
|
|
|
|
|
u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); |
|
|
u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); |
|
|
|
|
|
|
|
|
using Kernel::MemoryPermission; |
|
|
using Kernel::MemoryPermission; |
|
|
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite, |
|
|
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite, |
|
|
MemoryPermission::ReadWrite, 0, |
|
|
MemoryPermission::ReadWrite, 0, |
|
|
Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); |
|
|
Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); |
|
|
|
|
|
|
|
|
mutex = Kernel::Mutex::Create(false); |
|
|
|
|
|
|
|
|
mutex = Kernel::Mutex::Create(false, "CSND:mutex"); |
|
|
|
|
|
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw; |
|
|
cmd_buff[1] = RESULT_SUCCESS.raw; |
|
|
cmd_buff[2] = IPC::CopyHandleDesc(2); |
|
|
cmd_buff[2] = IPC::CopyHandleDesc(2); |
|
|
cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom(); |
|
|
cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom(); |
|
|
cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom(); |
|
|
cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom(); |
|
|
|
|
|
|
|
|
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ExecuteType0Commands(Interface* self) { |
|
|
|
|
|
u32* const cmd_buff = Kernel::GetCommandBuffer(); |
|
|
|
|
|
u8* const ptr = shared_memory->GetPointer(cmd_buff[1]); |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* CSND_SND::Shutdown service function |
|
|
|
|
|
* Inputs: |
|
|
|
|
|
* 0 : Header Code[0x00020000] |
|
|
|
|
|
* Outputs: |
|
|
|
|
|
* 1 : Result of function, 0 on success, otherwise error code |
|
|
|
|
|
*/ |
|
|
|
|
|
static void Shutdown(Interface* self) { |
|
|
|
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
|
|
|
|
|
|
if (shared_memory != nullptr && ptr != nullptr) { |
|
|
|
|
|
Type0Command command; |
|
|
|
|
|
std::memcpy(&command, ptr, sizeof(Type0Command)); |
|
|
|
|
|
|
|
|
shared_memory = nullptr; |
|
|
|
|
|
mutex = nullptr; |
|
|
|
|
|
|
|
|
LOG_WARNING(Service, "(STUBBED) CSND_SND::ExecuteType0Commands"); |
|
|
|
|
|
command.finished |= 1; |
|
|
|
|
|
cmd_buff[1] = 0; |
|
|
|
|
|
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw; |
|
|
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
std::memcpy(ptr, &command, sizeof(Type0Command)); |
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* CSND_SND::ExecuteCommands service function |
|
|
|
|
|
* Inputs: |
|
|
|
|
|
* 0 : Header Code[0x00030040] |
|
|
|
|
|
* 1 : Command offset in shared memory. |
|
|
|
|
|
* Outputs: |
|
|
|
|
|
* 1 : Result of function, 0 on success, otherwise error code |
|
|
|
|
|
* 2 : Available channel bit mask |
|
|
|
|
|
*/ |
|
|
|
|
|
static void ExecuteCommands(Interface* self) { |
|
|
|
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
|
|
|
|
|
|
|
|
|
if (shared_memory == nullptr) { |
|
|
cmd_buff[1] = 1; |
|
|
cmd_buff[1] = 1; |
|
|
|
|
|
LOG_ERROR(Service_CSND, "called, shared memory not allocated"); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
VAddr addr = cmd_buff[1]; |
|
|
|
|
|
u8* ptr = shared_memory->GetPointer(addr); |
|
|
|
|
|
|
|
|
|
|
|
Type0Command command; |
|
|
|
|
|
std::memcpy(&command, ptr, sizeof(Type0Command)); |
|
|
|
|
|
command.finished |= 1; |
|
|
|
|
|
std::memcpy(ptr, &command, sizeof(Type0Command)); |
|
|
|
|
|
|
|
|
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw; |
|
|
|
|
|
|
|
|
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called, addr=0x%08X", addr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void AcquireSoundChannels(Interface* self) { |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* CSND_SND::AcquireSoundChannels service function |
|
|
|
|
|
* Inputs: |
|
|
|
|
|
* 0 : Header Code[0x00050000] |
|
|
|
|
|
* Outputs: |
|
|
|
|
|
* 1 : Result of function, 0 on success, otherwise error code |
|
|
|
|
|
* 2 : Available channel bit mask |
|
|
|
|
|
*/ |
|
|
|
|
|
static void AcquireSoundChannels(Interface* self) { |
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
u32* cmd_buff = Kernel::GetCommandBuffer(); |
|
|
cmd_buff[1] = 0; |
|
|
|
|
|
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw; |
|
|
cmd_buff[2] = 0xFFFFFF00; |
|
|
cmd_buff[2] = 0xFFFFFF00; |
|
|
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Shutdown(Interface* self) { |
|
|
|
|
|
shared_memory = nullptr; |
|
|
|
|
|
mutex = nullptr; |
|
|
|
|
|
|
|
|
const Interface::FunctionInfo FunctionTable[] = { |
|
|
|
|
|
{0x00010140, Initialize, "Initialize"}, |
|
|
|
|
|
{0x00020000, Shutdown, "Shutdown"}, |
|
|
|
|
|
{0x00030040, ExecuteCommands, "ExecuteCommands"}, |
|
|
|
|
|
{0x00040080, nullptr, "ExecuteType1Commands"}, |
|
|
|
|
|
{0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, |
|
|
|
|
|
{0x00060000, nullptr, "ReleaseSoundChannels"}, |
|
|
|
|
|
{0x00070000, nullptr, "AcquireCaptureDevice"}, |
|
|
|
|
|
{0x00080040, nullptr, "ReleaseCaptureDevice"}, |
|
|
|
|
|
{0x00090082, nullptr, "FlushDataCache"}, |
|
|
|
|
|
{0x000A0082, nullptr, "StoreDataCache"}, |
|
|
|
|
|
{0x000B0082, nullptr, "InvalidateDataCache"}, |
|
|
|
|
|
{0x000C0000, nullptr, "Reset"}, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
CSND_SND::CSND_SND() { |
|
|
|
|
|
Register(FunctionTable); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} // namespace CSND
|
|
|
} // namespace CSND
|
|
|
|