From ec26631e5d6b20599232b9e6a0f70dbd90f046fc Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Sat, 15 Oct 2022 21:30:38 +0300 Subject: [PATCH] [APT] Implement some functions for Metroid 2 --- include/services/apt.hpp | 7 +++++ src/core/kernel/resource_limits.cpp | 2 +- src/core/services/apt.cpp | 43 ++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/services/apt.hpp b/include/services/apt.hpp index db4e773e..3dc80019 100644 --- a/include/services/apt.hpp +++ b/include/services/apt.hpp @@ -11,11 +11,18 @@ class APTService { // Service commands void appletUtility(u32 messagePointer); + void getApplicationCpuTimeLimit(u32 messagePointer); void getLockHandle(u32 messagePointer); void checkNew3DS(u32 messagePointer); + void checkNew3DSApp(u32 messagePointer); void enable(u32 messagePointer); void notifyToWait(u32 messagePointer); void receiveParameter(u32 messagePointer); + void replySleepQuery(u32 messagePointer); + void setApplicationCpuTimeLimit(u32 messagePointer); + + // Percentage of the syscore available to the application, between 5% and 89% + u32 cpuTimeLimit; public: APTService(Memory& mem) : mem(mem) {} diff --git a/src/core/kernel/resource_limits.cpp b/src/core/kernel/resource_limits.cpp index fa4abbc1..11497a0b 100644 --- a/src/core/kernel/resource_limits.cpp +++ b/src/core/kernel/resource_limits.cpp @@ -55,6 +55,7 @@ void Kernel::getResourceLimitCurrentValues() { const Handle resourceLimit = regs[1]; u32 names = regs[2]; // Pointer to resources that we should return u32 count = regs[3]; // Number of resources + logSVC("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count); const KernelObject* limit = getObject(resourceLimit, KernelObjectType::ResourceLimit); if (limit == nullptr) [[unlikely]] { @@ -62,7 +63,6 @@ void Kernel::getResourceLimitCurrentValues() { return; } - logSVC("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count); while (count != 0) { const u32 name = mem.read32(names); // TODO: Unsure if this is supposed to be s32 or u32. Shouldn't matter as the kernel can't create so many resources diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index 57393648..5de34664 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -5,8 +5,12 @@ namespace APTCommands { GetLockHandle = 0x00010040, Enable = 0x00030040, ReceiveParameter = 0x000D0080, + ReplySleepQuery = 0x003E0080, NotifyToWait = 0x00430040, AppletUtility = 0x004B00C2, + SetApplicationCpuTimeLimit = 0x004F0080, + GetApplicationCpuTimeLimit = 0x00500040, + CheckNew3DSApp = 0x01010000, CheckNew3DS = 0x01020000 }; } @@ -25,17 +29,24 @@ namespace Result { }; } -void APTService::reset() {} +void APTService::reset() { + // Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default + cpuTimeLimit = 30; +} void APTService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { case APTCommands::AppletUtility: appletUtility(messagePointer); break; case APTCommands::CheckNew3DS: checkNew3DS(messagePointer); break; + case APTCommands::CheckNew3DSApp: checkNew3DSApp(messagePointer); break; case APTCommands::Enable: enable(messagePointer); break; + case APTCommands::GetApplicationCpuTimeLimit: getApplicationCpuTimeLimit(messagePointer); break; case APTCommands::GetLockHandle: getLockHandle(messagePointer); break; case APTCommands::NotifyToWait: notifyToWait(messagePointer); break; case APTCommands::ReceiveParameter: receiveParameter(messagePointer); break; + case APTCommands::ReplySleepQuery: replySleepQuery(messagePointer); break; + case APTCommands::SetApplicationCpuTimeLimit: setApplicationCpuTimeLimit(messagePointer); break; default: Helpers::panic("APT service requested. Command: %08X\n", command); } } @@ -57,6 +68,12 @@ void APTService::checkNew3DS(u32 messagePointer) { mem.write8(messagePointer + 8, Model::Old3DS); // u8, Status (0 = Old 3DS, 1 = New 3DS) } +// TODO: Figure out the slight way this differs from APT::CheckNew3DS +void APTService::checkNew3DSApp(u32 messagePointer) { + log("APT::CheckNew3DSApp\n"); + checkNew3DS(messagePointer); +} + void APTService::enable(u32 messagePointer) { log("APT::Enable\n"); mem.write32(messagePointer + 4, Result::Success); @@ -89,4 +106,28 @@ void APTService::receiveParameter(u32 messagePointer) { mem.write32(messagePointer + 20, 0); mem.write32(messagePointer + 24, 0); mem.write32(messagePointer + 28, 0); +} + +void APTService::replySleepQuery(u32 messagePointer) { + log("APT::ReplySleepQuery (Stubbed)\n"); + mem.write32(messagePointer + 4, Result::Success); +} + +void APTService::setApplicationCpuTimeLimit(u32 messagePointer) { + u32 fixed = mem.read32(messagePointer + 4); // MUST be 1. + u32 percentage = mem.read32(messagePointer + 8); // CPU time percentage between 5% and 89% + log("APT::SetApplicationCpuTimeLimit (percentage = %d%%)\n", percentage); + + if (percentage < 5 || percentage > 89 || fixed != 1) { + Helpers::panic("Invalid parameters passed to APT::SetApplicationCpuTimeLimit"); + } else { + mem.write32(messagePointer + 4, Result::Success); + cpuTimeLimit = percentage; + } +} + +void APTService::getApplicationCpuTimeLimit(u32 messagePointer) { + log("APT::GetApplicationCpuTimeLimit\n"); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, cpuTimeLimit); } \ No newline at end of file