mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-09 15:01:00 +01:00
138 lines
4.5 KiB
C++
138 lines
4.5 KiB
C++
#include "processes/dlp.hpp"
|
|
|
|
#include "fake_process.hpp"
|
|
|
|
namespace HLE {
|
|
|
|
namespace OS {
|
|
|
|
struct FakeCECD {
|
|
FakeCECD(FakeThread&);
|
|
|
|
// Applies to cecd:u and cecd:s. cecd:ndm only accepts a single connection
|
|
static constexpr auto session_limit = 4;
|
|
|
|
spdlog::logger& logger;
|
|
|
|
HandleTable::Entry<Event> info_event;
|
|
HandleTable::Entry<Event> state_change_event;
|
|
};
|
|
|
|
|
|
static auto UserCommandHandler(FakeThread& thread, FakeCECD& context, const Platform::IPC::CommandHeader& header) {
|
|
switch (header.command_id) {
|
|
case 0x1: // OpenRawFile
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x1, 2, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
// A non-zero value needs to be returned here, since Home Menu fails to
|
|
// allocate some internal buffers otherwise
|
|
thread.WriteTLS(0x88, 1);
|
|
break;
|
|
|
|
case 0x2: // ReadRawFile
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x1, 2, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
thread.WriteTLS(0x88, 1);
|
|
break;
|
|
|
|
case 0x5: // WriteRawFile
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x5, 1, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
break;
|
|
|
|
case 0x8: // Delete
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x8, 1, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
break;
|
|
|
|
case 0x9:
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x9, 1, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
break;
|
|
|
|
case 0xc: // RunCommandAlt
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0xc, 1, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
break;
|
|
|
|
case 0xe: // GetCecStateAbbreviated
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0xe, 2, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
thread.WriteTLS(0x88, 1); // idle state
|
|
break;
|
|
|
|
case 0xf: // GetCecInfoEventHandle
|
|
{
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0xf, 1, 2).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
thread.WriteTLS(0x88, IPC::TranslationDescriptor::MakeHandles(1).raw);
|
|
thread.WriteTLS(0x8c, context.info_event.first.value);
|
|
break;
|
|
}
|
|
|
|
case 0x10: // GetChangeStateEventHandle
|
|
{
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x10, 1, 2).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
thread.WriteTLS(0x88, IPC::TranslationDescriptor::MakeHandles(1).raw);
|
|
thread.WriteTLS(0x8c, context.info_event.first.value);
|
|
break;
|
|
}
|
|
|
|
case 0x11: // OpenAndWrite
|
|
{
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x11, 1, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
break;
|
|
}
|
|
|
|
case 0x12: // OpenAndRead
|
|
{
|
|
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0x12, 2 + 2, 0).raw);
|
|
thread.WriteTLS(0x84, RESULT_OK);
|
|
thread.WriteTLS(0x88, 1); // Number of bytes read (Home Menu fails to allocate a buffer used later on if we return 0 here)
|
|
thread.WriteTLS(0x8c, 0);
|
|
thread.WriteTLS(0x90, 0);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw std::runtime_error(fmt::format("CECD: Unknown cecd:u command with header {:#x}", header.raw));
|
|
}
|
|
|
|
return ServiceHelper::SendReply;
|
|
}
|
|
|
|
FakeCECD::FakeCECD(FakeThread& thread)
|
|
: logger(*thread.GetLogger()) {
|
|
|
|
// TODO: Should these be OneShot or Sticky events?
|
|
OS::Result result;
|
|
std::tie(result, info_event) = thread.CallSVC(&OS::SVCCreateEvent, ResetType::OneShot);
|
|
if (result != RESULT_OK) {
|
|
throw std::runtime_error("Failed to create CECD info event");
|
|
}
|
|
std::tie(result, state_change_event) = thread.CallSVC(&OS::SVCCreateEvent, ResetType::OneShot);
|
|
if (result != RESULT_OK) {
|
|
throw std::runtime_error("Failed to create CECD state change event");
|
|
}
|
|
|
|
ServiceHelper service;
|
|
service.Append(ServiceUtil::SetupService(thread, "cecd:u", session_limit));
|
|
service.Append(ServiceUtil::SetupService(thread, "cecd:s", session_limit));
|
|
|
|
auto InvokeCommandHandler = [this](FakeThread& thread, uint32_t /* index of signalled handle */) {
|
|
Platform::IPC::CommandHeader header = { thread.ReadTLS(0x80) };
|
|
return UserCommandHandler(thread, *this, header);
|
|
};
|
|
|
|
service.Run(thread, std::move(InvokeCommandHandler));
|
|
}
|
|
|
|
template<> std::shared_ptr<WrappedFakeProcess> CreateFakeProcessViaContext<FakeCECD>(OS& os, Interpreter::Setup& setup, uint32_t pid, const std::string& name) {
|
|
return WrappedFakeProcess::CreateWithContext<FakeCECD>(os, setup, pid, name);
|
|
}
|
|
|
|
} // namespace OS
|
|
|
|
} // namespace HLE
|