service/csnd: Moved into csnd folder and stubbed a few functions (#4006)
* service/csnd: Moved into csnd folder and stubbed a few functions * service/csnd: Addresed comment about missing rb.Skip
This commit is contained in:
202
src/core/hle/service/csnd/csnd_snd.cpp
Normal file
202
src/core/hle/service/csnd/csnd_snd.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
// Copyright 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/csnd/csnd_snd.h"
|
||||
|
||||
namespace Service {
|
||||
namespace CSND {
|
||||
|
||||
void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x01, 5, 0);
|
||||
const u32 size = Common::AlignUp(rp.Pop<u32>(), Memory::PAGE_SIZE);
|
||||
const u32 offset0 = rp.Pop<u32>();
|
||||
const u32 offset1 = rp.Pop<u32>();
|
||||
const u32 offset2 = rp.Pop<u32>();
|
||||
const u32 offset3 = rp.Pop<u32>();
|
||||
|
||||
using Kernel::MemoryPermission;
|
||||
mutex = Kernel::Mutex::Create(false, "CSND:mutex");
|
||||
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite,
|
||||
MemoryPermission::ReadWrite, 0,
|
||||
Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushCopyObjects(mutex, shared_memory);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CSND_SND::Shutdown(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x02, 0, 0);
|
||||
|
||||
if (mutex)
|
||||
mutex = nullptr;
|
||||
if (shared_memory)
|
||||
shared_memory = nullptr;
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void CSND_SND::ExecuteCommands(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x03, 1, 0);
|
||||
const u32 addr = rp.Pop<u32>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
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;
|
||||
|
||||
std::memcpy(&command, ptr, sizeof(Type0Command));
|
||||
command.finished |= 1;
|
||||
std::memcpy(ptr, &command, sizeof(Type0Command));
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called, addr=0x{:08X}", addr);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
||||
}
|
||||
|
||||
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::AcquireCapUnit(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x7, 0, 0);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
if (capture_units[0] && capture_units[1]) {
|
||||
LOG_WARNING(Service_CSND, "No more capture units available");
|
||||
rb.Push(ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::CSND,
|
||||
ErrorSummary::OutOfResource, ErrorLevel::Status));
|
||||
rb.Skip(1, false);
|
||||
return;
|
||||
}
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
if (capture_units[0]) {
|
||||
capture_units[1] = true;
|
||||
rb.Push<u32>(1);
|
||||
} else {
|
||||
capture_units[0] = true;
|
||||
rb.Push<u32>(0);
|
||||
}
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void CSND_SND::ReleaseCapUnit(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x8, 1, 0);
|
||||
const u32 index = rp.Pop<u32>();
|
||||
|
||||
capture_units[index] = false;
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called, capture_unit_index={}", index);
|
||||
}
|
||||
|
||||
void CSND_SND::FlushDataCache(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x9, 2, 2);
|
||||
const VAddr address = rp.Pop<u32>();
|
||||
const u32 size = rp.Pop<u32>();
|
||||
const auto process = rp.PopObject<Kernel::Process>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_TRACE(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);
|
||||
const VAddr address = rp.Pop<u32>();
|
||||
const u32 size = rp.Pop<u32>();
|
||||
const auto process = rp.PopObject<Kernel::Process>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_TRACE(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);
|
||||
const VAddr address = rp.Pop<u32>();
|
||||
const u32 size = rp.Pop<u32>();
|
||||
const auto process = rp.PopObject<Kernel::Process>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_TRACE(Service_CSND, "(STUBBED) called address=0x{:08X}, size=0x{:08X}, process={}", address,
|
||||
size, process->process_id);
|
||||
}
|
||||
|
||||
void CSND_SND::Reset(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0xC, 0, 0);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_WARNING(Service_CSND, "(STUBBED) called");
|
||||
}
|
||||
|
||||
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"},
|
||||
{0x00060000, &CSND_SND::ReleaseSoundChannels, "ReleaseSoundChannels"},
|
||||
{0x00070000, &CSND_SND::AcquireCapUnit, "AcquireCapUnit"},
|
||||
{0x00080040, &CSND_SND::ReleaseCapUnit, "ReleaseCapUnit"},
|
||||
{0x00090082, &CSND_SND::FlushDataCache, "FlushDataCache"},
|
||||
{0x000A0082, &CSND_SND::StoreDataCache, "StoreDataCache"},
|
||||
{0x000B0082, &CSND_SND::InvalidateDataCache, "InvalidateDataCache"},
|
||||
{0x000C0000, &CSND_SND::Reset, "Reset"},
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RegisterHandlers(functions);
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<CSND_SND>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace CSND
|
||||
} // namespace Service
|
185
src/core/hle/service/csnd/csnd_snd.h
Normal file
185
src/core/hle/service/csnd/csnd_snd.h
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/mutex.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
namespace CSND {
|
||||
|
||||
class CSND_SND final : public ServiceFramework<CSND_SND> {
|
||||
public:
|
||||
CSND_SND();
|
||||
~CSND_SND() = default;
|
||||
|
||||
private:
|
||||
/**
|
||||
* CSND_SND::Initialize service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00010140]
|
||||
* 1 : Shared memory block size, for mem-block creation
|
||||
* 2 : Offset0 located in the shared-memory, region size=8
|
||||
* 3 : Offset1 located in the shared-memory, region size=12*num_channels
|
||||
* 4 : Offset2 located in the shared-memory, region size=8*num_capturedevices
|
||||
* 5 : Offset3 located in the shared-memory.
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : Handle-list header
|
||||
* 3 : Mutex handle
|
||||
* 4 : Shared memory block handle
|
||||
*/
|
||||
void Initialize(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::Shutdown service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00020000]
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void Shutdown(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void ExecuteCommands(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::ExecuteType1Commands service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00040080]
|
||||
* 1 : unknown
|
||||
* 2 : unknown
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void ExecuteType1Commands(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void AcquireSoundChannels(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::ReleaseSoundChannels service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00060000]
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void ReleaseSoundChannels(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::AcquireCapUnit service function
|
||||
* This function tries to acquire one capture device (max: 2).
|
||||
* Returns index of which capture device was acquired.
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00070000]
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : Capture Unit
|
||||
*/
|
||||
void AcquireCapUnit(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::ReleaseCapUnit service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00080040]
|
||||
* 1 : Capture Unit
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void ReleaseCapUnit(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::FlushDataCache service function
|
||||
*
|
||||
* This Function is a no-op, We aren't emulating the CPU cache any time soon.
|
||||
*
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00090082]
|
||||
* 1 : Address
|
||||
* 2 : Size
|
||||
* 3 : Value 0, some descriptor for the KProcess Handle
|
||||
* 4 : KProcess handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void FlushDataCache(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::StoreDataCache service function
|
||||
*
|
||||
* This Function is a no-op, We aren't emulating the CPU cache any time soon.
|
||||
*
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x000A0082]
|
||||
* 1 : Address
|
||||
* 2 : Size
|
||||
* 3 : Value 0, some descriptor for the KProcess Handle
|
||||
* 4 : KProcess handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void StoreDataCache(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::InvalidateDataCache service function
|
||||
*
|
||||
* This Function is a no-op, We aren't emulating the CPU cache any time soon.
|
||||
*
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x000B0082]
|
||||
* 1 : Address
|
||||
* 2 : Size
|
||||
* 3 : Value 0, some descriptor for the KProcess Handle
|
||||
* 4 : KProcess handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void InvalidateDataCache(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* CSND_SND::Reset service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x000C0000]
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void Reset(Kernel::HLERequestContext& ctx);
|
||||
|
||||
struct Type0Command {
|
||||
// command id and next command offset
|
||||
u32 command_id;
|
||||
u32 finished;
|
||||
u32 flags;
|
||||
u8 parameters[20];
|
||||
};
|
||||
static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong");
|
||||
|
||||
Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr;
|
||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr;
|
||||
|
||||
static constexpr u32 MaxCaptureUnits = 2;
|
||||
std::array<bool, MaxCaptureUnits> capture_units = {false, false};
|
||||
};
|
||||
|
||||
/// Initializes the CSND_SND Service
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace CSND
|
||||
} // namespace Service
|
Reference in New Issue
Block a user