mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-09 15:01:00 +01:00
229 lines
12 KiB
C++
229 lines
12 KiB
C++
|
#include "ns_hpv.hpp"
|
||
|
#include "os_hypervisor_private.hpp"
|
||
|
#include "os.hpp"
|
||
|
|
||
|
#include <platform/ns.hpp>
|
||
|
|
||
|
namespace HLE {
|
||
|
|
||
|
namespace OS {
|
||
|
|
||
|
namespace HPV {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
const char* ToString(Platform::NS::AppletPos pos) {
|
||
|
using namespace Platform::NS;
|
||
|
|
||
|
switch (pos) {
|
||
|
case AppletPos::App: return "App";
|
||
|
case AppletPos::AppLib: return "AppLib";
|
||
|
case AppletPos::Sys: return "Sys";
|
||
|
case AppletPos::SysLib: return "SysLib";
|
||
|
case AppletPos::Resident: return "Resident";
|
||
|
case AppletPos::AppLib2: return "AppLib2";
|
||
|
case static_cast<AppletPos>(0xff): return "None?"; // Observed by swkbd during initialization
|
||
|
case static_cast<AppletPos>(0xffffffff): return "None?"; // Observed by ctrulib when switching to home menu
|
||
|
default: throw std::runtime_error("Unknown AppletPos");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct AptService : SessionToPort {
|
||
|
AptService(RefCounted<Port> port_, NSContext& context_) : SessionToPort(port_, context_) {
|
||
|
}
|
||
|
|
||
|
void OnRequest(Hypervisor& hypervisor, Thread& thread, Handle session) override {
|
||
|
using namespace Platform::NS;
|
||
|
|
||
|
const uint32_t command_header = thread.ReadTLS(0x80);
|
||
|
auto dispatcher = RequestDispatcher<> { thread, *this, command_header };
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::GetLockHandle>([&](auto& response, uint32_t flags) {
|
||
|
auto description = fmt::format( "GetLockHandle, flags={:#x}", flags);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
|
||
|
response.OnResponse([=](Hypervisor& hv, Thread& thread, Result result, AppletAttr attr, uint32_t /* power_button_state */, Handle lock_handle) {
|
||
|
if (result != RESULT_OK) {
|
||
|
throw std::runtime_error("GetLockHandle failed");
|
||
|
}
|
||
|
|
||
|
hv.SetObjectTag(thread, lock_handle, fmt::format("APTLock_{:#x}", Meta::to_underlying(attr.pos()())));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::Initialize>([&](auto& response, AppId app_id, AppletAttr attr) {
|
||
|
auto description = fmt::format( "Initialize, app_id={:#x}, attr={:#x}",
|
||
|
Meta::to_underlying(app_id), attr.value);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
|
||
|
response.OnResponse([=](Hypervisor& hv, Thread& thread, Result result, std::array<Handle, 2> event_handles) {
|
||
|
if (result != RESULT_OK) {
|
||
|
throw std::runtime_error("Initialize failed");
|
||
|
}
|
||
|
|
||
|
hv.SetObjectTag(thread, event_handles[0], fmt::format("APTNotificationEvent_{:#x}", Meta::to_underlying(app_id)));
|
||
|
hv.SetObjectTag(thread, event_handles[1], fmt::format("APTParameterReadyEvent_{:#x}", Meta::to_underlying(app_id)));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::Enable>([&](auto&, AppletAttr attr) {
|
||
|
auto description = fmt::format( "Enable, attr={:#x}", attr.value);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::GetAppletManInfo>([&](auto&, AppletPos pos) {
|
||
|
auto description = fmt::format( "GetAppletManInfo, pos={}", ToString(pos));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::GetAppletInfo>([&](auto&, AppId app_id) {
|
||
|
auto description = fmt::format( "GetAppletInfo, app_id={:#x}", Meta::to_underlying(app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::IsRegistered>([&](auto&, AppId app_id) {
|
||
|
auto description = fmt::format( "IsRegistered, app_id={:#x}", Meta::to_underlying(app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::SendParameter>([&]( auto&, AppId source, AppId target,
|
||
|
AppletCommand command, uint32_t data_size,
|
||
|
Handle /*handle*/, IPC::StaticBuffer /*data*/) {
|
||
|
auto description = fmt::format( "SendParameter, source_app_id={:#x}, dest_app_id={:#x}, command={:#x}, data_size={:#x}",
|
||
|
Meta::to_underlying(source), Meta::to_underlying(target), Meta::to_underlying(command), data_size);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::ReceiveParameter>([&](auto&, AppId target, uint32_t bytes_to_receive) {
|
||
|
auto description = fmt::format( "ReceiveParameter, target_app_id={:#x}, buffer_size={:#x}",
|
||
|
Meta::to_underlying(target), bytes_to_receive);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::GlanceParameter>([&](auto&, AppId target, uint32_t bytes_to_receive) {
|
||
|
auto description = fmt::format( "GlanceParameter, target_app_id={:#x}, buffer_size={:#x}",
|
||
|
Meta::to_underlying(target), bytes_to_receive);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::CancelParameter>([&](auto&, bool check_source, AppId source_app_id, uint32_t check_target, AppId target_app_id) {
|
||
|
auto description = fmt::format( "CancelParameter, check_source={:#x}, source_app_id={:#x}, check_target={:#x}, target_app_id={:#x}",
|
||
|
check_source, Meta::to_underlying(source_app_id),
|
||
|
check_target, Meta::to_underlying(target_app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::PrepareToStartApplication>([&](auto&, const Platform::PXI::PM::ProgramInfo& program_info, uint32_t flags) {
|
||
|
auto description = fmt::format( "PrepareToStartApplication, program_id={:#x} (media type {}), flags {:#x}",
|
||
|
program_info.program_id, program_info.media_type, flags);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::FinishPreloadingLibraryApplet>([&](auto&, AppId app_id) {
|
||
|
auto description = fmt::format( "FinishPreloadingLibraryApplet, app_id={:#x}",
|
||
|
Meta::to_underlying(app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::PrepareToStartLibraryApplet>([&](auto&, AppId app_id) {
|
||
|
auto description = fmt::format( "PrepareToStartLibraryApplet, app_id={:#x}",
|
||
|
Meta::to_underlying(app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::StartLibraryApplet>([&](auto&, AppId app_id, uint32_t data_size, Handle /*handle*/, IPC::StaticBuffer /*data*/) {
|
||
|
auto description = fmt::format( "StartLibraryApplet, app_id={:#x}, data_size={:#x}",
|
||
|
Meta::to_underlying(app_id), data_size);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::PrepareToCloseApplication>([&](auto&, uint32_t cancel_preload) {
|
||
|
auto description = fmt::format( "PrepareToCloseApplication, cancel_preload={:#x}", cancel_preload);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::PrepareToCloseLibraryApplet>([&](auto&, uint32_t unknown_flag, uint32_t caller_exiting, uint32_t jump_to_home) {
|
||
|
auto description = fmt::format( "PrepareToCloseLibraryApplet, unknown_flag={:#x}, caller_exiting={:#x}, jump_to_home={:#x}",
|
||
|
unknown_flag, caller_exiting, jump_to_home);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::CloseLibraryApplet>([&](auto&, uint32_t param_size, Handle /*handle*/, IPC::StaticBuffer /*data*/) {
|
||
|
auto description = fmt::format( "CloseLibraryApplet, param_size={:#x}", param_size);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::PrepareToJumpToHomeMenu>([&](auto&) {
|
||
|
auto description = fmt::format( "PrepareToJumpToHomeMenu");
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::JumpToHomeMenu>([&](auto&, uint32_t param_size, Handle /*handle*/, IPC::StaticBuffer /*data*/) {
|
||
|
auto description = fmt::format( "JumpToHomeMenu, param_size={:#x}", param_size);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::StartApplication>([&](auto&, uint32_t param_size, uint32_t hmac_size,
|
||
|
uint32_t launch_paused, IPC::StaticBuffer /*param_buffer*/,
|
||
|
IPC::StaticBuffer /*hmac_buffer*/) {
|
||
|
auto description = fmt::format( "StartApplication, param_size={:#x}, hmac_size={:#x}, paused={:#x}",
|
||
|
param_size, hmac_size, launch_paused);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::SendCaptureBufferInfo>([&](auto&, uint32_t size, IPC::StaticBuffer /*buffer*/) {
|
||
|
auto description = fmt::format( "SendCaptureBufferInfo, info_size={:#x}", size);
|
||
|
// TODO: Print out the actual buffer
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::ReceiveCaptureBufferInfo>([&](auto&, uint32_t size) {
|
||
|
auto description = fmt::format( "ReceiveCaptureBufferInfo, info_size={:#x}", size);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::NotifyToWait>([&](auto&, AppId app_id) {
|
||
|
auto description = fmt::format( "NotifyToWait, app_id={:#x}", Meta::to_underlying(app_id));
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
|
||
|
dispatcher.DecodeRequest<APT::GetSharedFont>([&](auto&) {
|
||
|
Session::OnRequest(hypervisor, thread, session, "GetSharedFont");
|
||
|
// TODO: On response, check that the font has actually finished loading. Otherwise, recommend booting through Home Menu
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct NsService : SessionToPort {
|
||
|
NsService(RefCounted<Port> port_, NSContext& context_) : SessionToPort(port_, context_) {
|
||
|
}
|
||
|
|
||
|
void OnRequest(Hypervisor& hypervisor, Thread& thread, Handle session) override {
|
||
|
using namespace Platform::NS;
|
||
|
|
||
|
const uint32_t command_header = thread.ReadTLS(0x80);
|
||
|
auto dispatcher = RequestDispatcher<> { thread, *this, command_header };
|
||
|
|
||
|
dispatcher.DecodeRequest<NS::LaunchTitle>([&](auto&, uint64_t title_id, uint32_t flags) {
|
||
|
auto description = fmt::format( "LaunchTitle, title_id={:#x}, flags={:#x}", title_id, flags);
|
||
|
Session::OnRequest(hypervisor, thread, session, description);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // anonymous namespace
|
||
|
|
||
|
HPV::RefCounted<Object> CreateAPTService(RefCounted<Port> port, NSContext& context) {
|
||
|
return HPV::RefCounted<Object>(new AptService(port, context));
|
||
|
}
|
||
|
|
||
|
HPV::RefCounted<Object> CreateNSService(RefCounted<Port> port, NSContext& context) {
|
||
|
return HPV::RefCounted<Object>(new NsService(port, context));
|
||
|
}
|
||
|
|
||
|
} // namespace HPV
|
||
|
|
||
|
} // namespace HOS
|
||
|
|
||
|
} // namespace HLE
|