libNX Applet Manager Initalization

This commit completes the 'am' initialization for libNX
This commit is contained in:
◱ PixelyIon 2019-09-27 21:39:48 +05:30
parent a5d63c9bbb
commit f7effe86ae
15 changed files with 301 additions and 16 deletions

View File

@ -31,6 +31,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/kernel/services/set/sys.cpp
${source_DIR}/skyline/kernel/services/apm/apm.cpp
${source_DIR}/skyline/kernel/services/am/appletOE.cpp
${source_DIR}/skyline/kernel/services/fatal/fatal.cpp
)
target_link_libraries(skyline fmt tinyxml2)
target_compile_options(skyline PRIVATE -Wno-c++17-extensions)

View File

@ -1,5 +1,4 @@
#include <jni.h>
#include <pthread.h>
#include <csignal>
#include <string>
#include <thread>
@ -12,7 +11,7 @@ bool Halt = false;
void ThreadMain(const std::string romPath, const std::string prefPath, const std::string logPath) {
auto logger = std::make_shared<skyline::Logger>(logPath);
auto settings = std::make_shared<skyline::Settings>(prefPath);
//settings->List(log); // (Uncomment when you want to print out all settings strings)
//settings->List(logger); // (Uncomment when you want to print out all settings strings)
auto start = std::chrono::steady_clock::now();
try {
skyline::kernel::OS os(logger, settings);

View File

@ -71,7 +71,7 @@ namespace skyline::kernel::ipc {
}
if (payload->magic != constant::SfciMagic)
state.logger->Write(Logger::Warn, "Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
state.logger->Write(Logger::Debug, "Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
if (header->c_flag == static_cast<u8>(BufferCFlag::SingleDescriptor)) {
vecBufC.push_back(reinterpret_cast<BufferDescriptorC *>(currPtr));

View File

@ -13,8 +13,11 @@ namespace skyline::kernel::service::am {
{0x0, SFunc(IApplicationProxy::GetCommonStateGetter)},
{0x1, SFunc(IApplicationProxy::GetSelfController)},
{0x2, SFunc(IApplicationProxy::GetWindowController)},
{0x3, SFunc(IApplicationProxy::GetAudioController)},
{0x4, SFunc(IApplicationProxy::GetDisplayController)},
{0xB, SFunc(IApplicationProxy::GetLibraryAppletCreator)},
{0x14, SFunc(IApplicationProxy::GetApplicationFunctions)}
{0x14, SFunc(IApplicationProxy::GetApplicationFunctions)},
{0x3E8, SFunc(IApplicationProxy::GetDisplayController)}
}) {}
void IApplicationProxy::GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
@ -29,6 +32,14 @@ namespace skyline::kernel::service::am {
manager.NewService(Service::am_IWindowController, session, response);
}
void IApplicationProxy::GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.NewService(Service::am_IAudioController, session, response);
}
void IApplicationProxy::GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.NewService(Service::am_IDisplayController, session, response);
}
void IApplicationProxy::GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.NewService(Service::am_ILibraryAppletCreator, session, response);
}
@ -37,18 +48,77 @@ namespace skyline::kernel::service::am {
manager.NewService(Service::am_IApplicationFunctions, session, response);
}
void IApplicationProxy::IDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.NewService(Service::am_IDebugFunctions, session, response);
}
ICommonStateGetter::ICommonStateGetter(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_ICommonStateGetter, {
}) {}
{0x0, SFunc(ICommonStateGetter::GetEventHandle)},
{0x9, SFunc(ICommonStateGetter::GetCurrentFocusState)},
{0x5, SFunc(ICommonStateGetter::GetOperationMode)},
{0x6, SFunc(ICommonStateGetter::GetPerformanceMode)}
}) {
operationMode = static_cast<OperationMode>(state.settings->GetBool("operation_mode"));
state.logger->Write(Logger::Info, "Switch on mode: {}", static_cast<bool>(operationMode) ? "Docked" : "Handheld");
}
void ICommonStateGetter::GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
messageEvent = state.thisProcess->NewHandle<type::KEvent>();
response.copyHandles.push_back(messageEvent->handle);
}
void ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.WriteValue<u8>(static_cast<u8>(ApplicationStatus::InFocus));
}
void ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.WriteValue<u8>(static_cast<u8>(operationMode));
}
void ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.WriteValue<u32>(static_cast<u32>(operationMode));
}
ISelfController::ISelfController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_ISelfController, {
{0xB, SFunc(ISelfController::SetOperationModeChangedNotification)},
{0xC, SFunc(ISelfController::SetPerformanceModeChangedNotification)},
{0xD, SFunc(ISelfController::SetFocusHandlingMode)}
}) {}
void ISelfController::SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ISelfController::SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ISelfController::SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
IWindowController::IWindowController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IWindowController, {
{0x1, SFunc(IWindowController::GetAppletResourceUserId)},
{0xA, SFunc(IWindowController::AcquireForegroundRights)}
}) {}
void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.WriteValue(static_cast<u64>(state.thisProcess->mainThread));
}
void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
IAudioController::IAudioController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IAudioController, {
}) {}
IDisplayController::IDisplayController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IDisplayController, {
}) {}
ILibraryAppletCreator::ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_ILibraryAppletCreator, {
}) {}
IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IApplicationFunctions, {
{0x28, SFunc(IApplicationFunctions::NotifyRunning)}
}) {}
void IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.WriteValue<u8>(1);
}
IDebugFunctions::IDebugFunctions(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IDebugFunctions, {
}) {}
}

View File

@ -2,6 +2,8 @@
#include "../base_service.h"
#include "../serviceman.h"
#include "../../types/KProcess.h"
#include "../../types/KEvent.h"
namespace skyline::kernel::service::am {
/**
@ -39,6 +41,16 @@ namespace skyline::kernel::service::am {
*/
void GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns #IAudioController (https://switchbrew.org/wiki/Applet_Manager_services#IAudioController)
*/
void GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns #IDisplayController (https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController)
*/
void GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns #ILibraryAppletCreator (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator)
*/
@ -48,30 +60,134 @@ namespace skyline::kernel::service::am {
* @brief This returns #IApplicationFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions)
*/
void GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns #IDebugFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions)
*/
void IDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter
*/
class ICommonStateGetter : public BaseService {
private:
std::shared_ptr<type::KEvent> messageEvent{};
enum class ApplicationStatus : u8 {
InFocus = 1, OutOfFocus = 2
};
enum class OperationMode : u8 {
Handheld = 0, Docked = 1
} operationMode;
public:
ICommonStateGetter(const DeviceState &state, ServiceManager &manager);
/**
* @brief This returns the handle to a KEvent object that is signalled whenever RecieveMessage has a message (https://switchbrew.org/wiki/Applet_Manager_services#GetEventHandle)
*/
void GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns if an application is in focus or not. It always returns in focus on the emulator (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
*/
void GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns the current OperationMode (https://switchbrew.org/wiki/Applet_Manager_services#GetOperationMode)
*/
void GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns the current PerformanceMode (Same as operationMode but u32) (https://switchbrew.org/wiki/Applet_Manager_services#GetPerformanceMode)
*/
void GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#ISelfController
*/
class ISelfController : public BaseService {
public:
ISelfController(const DeviceState &state, ServiceManager &manager);
/**
* @brief This function inputs a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOperationModeChangedNotification)
*/
void SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function inputs a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetPerformanceModeChangedNotification)
*/
void SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function inputs 3 unknown u8 values and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
*/
void SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#IWindowController
*/
class IWindowController : public BaseService {
public:
IWindowController(const DeviceState &state, ServiceManager &manager);
/**
* @brief This returns the PID of the current application (https://switchbrew.org/wiki/Applet_Manager_services#GetAppletResourceUserId)
*/
void GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function has mo inputs or outputs (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#AcquireForegroundRights)
*/
void AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#IAudioController
*/
class IAudioController : public BaseService {
public:
IAudioController(const DeviceState &state, ServiceManager &manager);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController
*/
class IDisplayController : public BaseService {
public:
IDisplayController(const DeviceState &state, ServiceManager &manager);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator
*/
class ILibraryAppletCreator : public BaseService {
public:
ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions
*/
class IApplicationFunctions : public BaseService {
public:
IApplicationFunctions(const DeviceState &state, ServiceManager &manager);
/**
* @brief This just returns 1 regardless of input (https://switchbrew.org/wiki/Applet_Manager_services#NotifyRunning)
*/
void NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
/**
* @brief https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions
*/
class IDebugFunctions : public BaseService {
public:
IDebugFunctions(const DeviceState &state, ServiceManager &manager);
};
}

View File

@ -14,7 +14,21 @@ namespace skyline::kernel::service {
* @brief This contains an enum for every service that's present
*/
enum class Service {
sm, set_sys, apm, apm_ISession, am_appletOE, am_IApplicationProxy, am_ICommonStateGetter, am_IApplicationFunctions, am_ISelfController, am_IWindowController, am_ILibraryAppletCreator
sm,
fatal_u,
set_sys,
apm,
apm_ISession,
am_appletOE,
am_IApplicationProxy,
am_ICommonStateGetter,
am_IApplicationFunctions,
am_ISelfController,
am_IWindowController,
am_IAudioController,
am_IDisplayController,
am_ILibraryAppletCreator,
am_IDebugFunctions,
};
/**
@ -22,6 +36,7 @@ namespace skyline::kernel::service {
*/
const static std::unordered_map<std::string, Service> ServiceString = {
{"sm:", Service::sm},
{"fatal:u", Service::fatal_u},
{"set:sys", Service::set_sys},
{"apm", Service::apm},
{"apm:ISession", Service::apm_ISession},
@ -30,8 +45,11 @@ namespace skyline::kernel::service {
{"am:ICommonStateGetter", Service::am_ICommonStateGetter},
{"am:ISelfController", Service::am_ISelfController},
{"am:IWindowController", Service::am_IWindowController},
{"am:IAudioController", Service::am_IAudioController},
{"am:IDisplayController", Service::am_IDisplayController},
{"am:ILibraryAppletCreator", Service::am_ILibraryAppletCreator},
{"am:IApplicationFunctions", Service::am_IApplicationFunctions},
{"am:IDebugFunctions", Service::am_IDebugFunctions},
};
class ServiceManager;
@ -73,10 +91,17 @@ namespace skyline::kernel::service {
* @param response The corresponding IpcResponse object
*/
void HandleRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
std::function<void(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)> function;
try {
vTable.at(request.payload->value)(session, request, response);
function = vTable.at(request.payload->value);
} catch (std::out_of_range&) {
state.logger->Write(Logger::Warn, "Cannot find function in service '{0}' (Type: {1}): 0x{2:X} ({2})", getName(), serviceType, u32(request.payload->value));
return;
}
try {
function(session, request, response);
} catch (std::exception& e) {
throw exception(e.what());
}
};

View File

@ -0,0 +1,11 @@
#include "fatal.h"
namespace skyline::kernel::service::fatal {
fatalU::fatalU(const DeviceState &state, ServiceManager& manager) : BaseService(state, manager, false, Service::fatal_u, {
{0x0, SFunc(fatalU::ThrowFatal)}
}) {}
void fatalU::ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
throw exception("A fatal error has caused emulation to stop");
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "../base_service.h"
#include "../serviceman.h"
namespace skyline::kernel::service::fatal {
/**
* @brief fatal_u is used by applications to throw errors (https://switchbrew.org/wiki/Fatal_services#fatal:u)
*/
class fatalU : public BaseService {
public:
fatalU(const DeviceState &state, ServiceManager& manager);
/**
* @brief This throws an exception so that emulation will quit
*/
void ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -4,6 +4,7 @@
#include "set/sys.h"
#include "apm/apm.h"
#include "am/appletOE.h"
#include "fatal/fatal.h"
namespace skyline::kernel::service {
ServiceManager::ServiceManager(const DeviceState &state) : state(state) {}
@ -15,6 +16,9 @@ namespace skyline::kernel::service {
case Service::sm:
serviceMap[serviceType] = std::make_shared<sm::sm>(state, *this);
break;
case Service::fatal_u:
serviceMap[serviceType] = std::make_shared<fatal::fatalU>(state, *this);
break;
case Service::set_sys:
serviceMap[serviceType] = std::make_shared<set::sys>(state, *this);
break;
@ -36,6 +40,12 @@ namespace skyline::kernel::service {
case Service::am_IWindowController:
serviceMap[serviceType] = std::make_shared<am::IWindowController>(state, *this);
break;
case Service::am_IAudioController:
serviceMap[serviceType] = std::make_shared<am::IAudioController>(state, *this);
break;
case Service::am_IDisplayController:
serviceMap[serviceType] = std::make_shared<am::IDisplayController>(state, *this);
break;
case Service::am_ISelfController:
serviceMap[serviceType] = std::make_shared<am::ISelfController>(state, *this);
break;
@ -45,6 +55,9 @@ namespace skyline::kernel::service {
case Service::am_IApplicationFunctions:
serviceMap[serviceType] = std::make_shared<am::IApplicationFunctions>(state, *this);
break;
case Service::am_IDebugFunctions:
serviceMap[serviceType] = std::make_shared<am::IDebugFunctions>(state, *this);
break;
}
serviceObj = serviceMap[serviceType];
} else

View File

@ -0,0 +1,18 @@
#pragma once
#include "KSyncObject.h"
namespace skyline::kernel::type {
/**
* @brief KEvent is an object that's signalled on an repeatable event occurring (https://switchbrew.org/wiki/Kernel_objects#KEvent)
*/
class KEvent : public KSyncObject {
public:
/**
* @param handle The handle of the object in the handle table
* @param pid The PID of the main thread
* @param state The state of the device
*/
KEvent(skyline::handle_t handle, pid_t pid, const DeviceState &state) : KSyncObject(handle, pid, state, KType::KEvent) {}
};
}

View File

@ -7,7 +7,7 @@ namespace skyline::kernel::type {
* @brief These types are used to perform runtime evaluation of a kernel object's type when converting from base class
*/
enum class KType {
KThread, KProcess, KSharedMemory, KPrivateMemory, KSession
KThread, KProcess, KSharedMemory, KPrivateMemory, KSession, KEvent
};
/**

View File

@ -5,8 +5,7 @@ namespace skyline::kernel::type {
KSyncObject::KSyncObject(skyline::handle_t handle, pid_t pid, const skyline::DeviceState &state, skyline::kernel::type::KType type) : KObject(handle, pid, state, type) {}
void KSyncObject::Signal() {
for (auto&[tid, process] : state.os->threadMap) {
auto &thread = process->threadMap.at(tid);
for (auto&[tid, thread] : state.os->threadMap.at(ownerPid)->threadMap) {
if (thread->status == type::KThread::ThreadStatus::Waiting) {
for (auto &waitHandle : thread->waitHandles) {
if (handle == waitHandle) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -14,12 +14,6 @@
<string name="no_rom">Cannot find any ROMs</string>
<string name="nro">NROs</string>
<string name="nso">NSOs</string>
<!-- Settings -->
<string name="search_location">Search Location</string>
<string name="logging">Logging</string>
<string name="log_level">Log Level</string>
<string name="localization">Localization</string>
<string name="localization_language">Language</string>
<!-- Toolbar Logger -->
<string name="clear">Clear</string>
<string name="share">Share</string>
@ -28,4 +22,14 @@
<string name="io_error">An I/O error has occurred</string>
<string name="share_error">An error has occurred while sharing</string>
<string name="cleared">The logs have been cleared</string>
<!-- Settings -->
<string name="search_location">Search Location</string>
<string name="logging">Logging</string>
<string name="log_level">Log Level</string>
<string name="localization">Localization</string>
<string name="localization_language">Language</string>
<string name="system">System</string>
<string name="use_docked">Use Docked Mode</string>
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
<string name="docked_enabled">The system will emulate being in docked mode</string>
</resources>

View File

@ -36,6 +36,16 @@
app:title="@string/log_level"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
<PreferenceCategory
android:key="category_system"
android:title="@string/system">
<CheckBoxPreference
app:key="operation_mode"
app:title="@string/use_docked"
android:defaultValue="true"
android:summaryOn="@string/docked_enabled"
android:summaryOff="@string/handheld_enabled"/>
</PreferenceCategory>
<PreferenceCategory
android:key="category_localization"
android:title="@string/localization">