2014-11-12 22:13:08 +01:00
|
|
|
// Copyright 2014 Citra Emulator Project
|
2014-12-17 06:38:14 +01:00
|
|
|
// Licensed under GPLv2 or any later version
|
2014-11-12 22:13:08 +01:00
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2016-04-18 04:07:52 +02:00
|
|
|
#include "common/alignment.h"
|
2018-07-01 21:40:28 +02:00
|
|
|
#include "core/hle/ipc_helpers.h"
|
2016-09-21 08:52:38 +02:00
|
|
|
#include "core/hle/service/csnd_snd.h"
|
2014-11-12 22:13:08 +01:00
|
|
|
|
2016-12-10 13:51:50 +01:00
|
|
|
namespace Service {
|
|
|
|
namespace CSND {
|
2014-11-12 22:13:08 +01:00
|
|
|
|
2016-12-08 10:11:54 +01:00
|
|
|
struct Type0Command {
|
|
|
|
// command id and next command offset
|
|
|
|
u32 command_id;
|
|
|
|
u32 finished;
|
|
|
|
u32 flags;
|
|
|
|
u8 parameters[20];
|
2014-11-12 22:13:08 +01:00
|
|
|
};
|
2016-12-08 10:11:54 +01:00
|
|
|
static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong");
|
2014-11-12 22:13:08 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x01, 5, 0);
|
|
|
|
u32 size = Common::AlignUp(rp.Pop<u32>(), Memory::PAGE_SIZE);
|
2018-07-03 04:09:10 +02:00
|
|
|
u32 offset0 = rp.Pop<u32>();
|
|
|
|
u32 offset1 = rp.Pop<u32>();
|
|
|
|
u32 offset2 = rp.Pop<u32>();
|
|
|
|
u32 offset3 = rp.Pop<u32>();
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2016-04-18 04:07:52 +02:00
|
|
|
using Kernel::MemoryPermission;
|
2018-07-01 21:40:28 +02:00
|
|
|
mutex = Kernel::Mutex::Create(false, "CSND:mutex");
|
2016-09-18 02:38:01 +02:00
|
|
|
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite,
|
|
|
|
MemoryPermission::ReadWrite, 0,
|
|
|
|
Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
|
2015-10-27 22:40:34 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushCopyObjects(mutex, shared_memory);
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-07-01 22:41:25 +02:00
|
|
|
LOG_WARNING(Service_CSND,
|
|
|
|
"(STUBBED) called, size=0x{:08X} "
|
|
|
|
"offset0=0x{:08X} offset1=0x{:08X} offset2=0x{:08X} offset3=0x{:08X}",
|
|
|
|
size, offset0, offset1, offset2, offset3);
|
2015-10-27 22:40:34 +01:00
|
|
|
}
|
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
void CSND_SND::Shutdown(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x02, 0, 0);
|
|
|
|
|
2018-07-01 22:16:34 +02:00
|
|
|
if (mutex)
|
|
|
|
mutex = nullptr;
|
|
|
|
if (shared_memory)
|
|
|
|
shared_memory = nullptr;
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2015-10-28 21:10:21 +01:00
|
|
|
|
2018-06-29 13:18:07 +02:00
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
2016-12-08 10:11:54 +01:00
|
|
|
}
|
2015-10-28 21:10:21 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
void CSND_SND::ExecuteCommands(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x03, 1, 0);
|
2018-07-03 04:09:10 +02:00
|
|
|
u32 addr = rp.Pop<u32>();
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-07-03 04:09:10 +02:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
2018-07-01 21:40:28 +02:00
|
|
|
if (!shared_memory) {
|
|
|
|
rb.Push<u32>(1);
|
|
|
|
LOG_ERROR(Service_CSND, "called, shared memory not allocated");
|
|
|
|
} else {
|
|
|
|
u8* ptr = shared_memory->GetPointer(addr);
|
|
|
|
Type0Command command;
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
std::memcpy(&command, ptr, sizeof(Type0Command));
|
|
|
|
command.finished |= 1;
|
|
|
|
std::memcpy(ptr, &command, sizeof(Type0Command));
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
2016-12-08 10:11:54 +01:00
|
|
|
|
2018-06-29 13:18:07 +02:00
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called, addr=0x{:08X}", addr);
|
2015-10-27 22:40:34 +01:00
|
|
|
}
|
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
void CSND_SND::AcquireSoundChannels(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x05, 0, 0);
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u32>(0xFFFFFF00);
|
|
|
|
|
2018-06-29 13:18:07 +02:00
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
2015-10-27 22:40:34 +01:00
|
|
|
}
|
|
|
|
|
2018-07-01 22:16:34 +02:00
|
|
|
void CSND_SND::ReleaseSoundChannels(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x06, 0, 0);
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSND_SND::FlushDataCache(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x9, 2, 2);
|
2018-07-03 04:09:10 +02:00
|
|
|
VAddr address = rp.Pop<u32>();
|
2018-07-01 22:16:34 +02:00
|
|
|
u32 size = rp.Pop<u32>();
|
|
|
|
auto process = rp.PopObject<Kernel::Process>();
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_CSND, "(STUBBED) called address=0x{:08X}, size=0x{:08X}, process={}", address,
|
|
|
|
size, process->process_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSND_SND::StoreDataCache(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0xA, 2, 2);
|
2018-07-03 04:09:10 +02:00
|
|
|
VAddr address = rp.Pop<u32>();
|
2018-07-01 22:16:34 +02:00
|
|
|
u32 size = rp.Pop<u32>();
|
|
|
|
auto process = rp.PopObject<Kernel::Process>();
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_CSND, "(STUBBED) called address=0x{:08X}, size=0x{:08X}, process={}", address,
|
|
|
|
size, process->process_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSND_SND::InvalidateDataCache(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0xB, 2, 2);
|
2018-07-03 04:09:10 +02:00
|
|
|
VAddr address = rp.Pop<u32>();
|
2018-07-01 22:16:34 +02:00
|
|
|
u32 size = rp.Pop<u32>();
|
|
|
|
auto process = rp.PopObject<Kernel::Process>();
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_CSND, "(STUBBED) called address=0x{:08X}, size=0x{:08X}, process={}", address,
|
|
|
|
size, process->process_id);
|
|
|
|
}
|
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
CSND_SND::CSND_SND() : ServiceFramework("csnd:SND", 4) {
|
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
// clang-format off
|
|
|
|
{0x00010140, &CSND_SND::Initialize, "Initialize"},
|
|
|
|
{0x00020000, &CSND_SND::Shutdown, "Shutdown"},
|
|
|
|
{0x00030040, &CSND_SND::ExecuteCommands, "ExecuteCommands"},
|
|
|
|
{0x00040080, nullptr, "ExecuteType1Commands"},
|
|
|
|
{0x00050000, &CSND_SND::AcquireSoundChannels, "AcquireSoundChannels"},
|
2018-07-01 22:16:34 +02:00
|
|
|
{0x00060000, &CSND_SND::ReleaseSoundChannels, "ReleaseSoundChannels"},
|
2018-07-01 21:40:28 +02:00
|
|
|
{0x00070000, nullptr, "AcquireCaptureDevice"},
|
|
|
|
{0x00080040, nullptr, "ReleaseCaptureDevice"},
|
2018-07-01 22:16:34 +02:00
|
|
|
{0x00090082, &CSND_SND::FlushDataCache, "FlushDataCache"},
|
|
|
|
{0x000A0082, &CSND_SND::StoreDataCache, "StoreDataCache"},
|
|
|
|
{0x000B0082, &CSND_SND::InvalidateDataCache, "InvalidateDataCache"},
|
2018-07-01 21:40:28 +02:00
|
|
|
{0x000C0000, nullptr, "Reset"},
|
|
|
|
// clang-format on
|
|
|
|
};
|
|
|
|
|
|
|
|
RegisterHandlers(functions);
|
2016-12-08 10:11:54 +01:00
|
|
|
};
|
|
|
|
|
2018-07-01 21:40:28 +02:00
|
|
|
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
|
|
|
std::make_shared<CSND_SND>()->InstallAsService(service_manager);
|
2015-10-27 22:40:34 +01:00
|
|
|
}
|
|
|
|
|
2016-12-10 13:51:50 +01:00
|
|
|
} // namespace CSND
|
|
|
|
} // namespace Service
|