mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-04 10:32:15 +02:00
Merge remote-tracking branch 'upstream/master' into dev
This commit is contained in:
commit
a06e062928
62
Changelog.md
62
Changelog.md
@ -1,5 +1,67 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Version 3.1.0
|
||||||
|
|
||||||
|
#### system
|
||||||
|
* **Deleted the old and deprecated IPC system**.
|
||||||
|
* **Added wrappers for all missing system calls**.
|
||||||
|
* Corrected signatures of many system calls.
|
||||||
|
* Removed `arm/atomics.h` (use C `<stdatomic.h>` or C++ `<atomic>` instead).
|
||||||
|
* Removed `U64_MAX` define (use `UINT64_MAX` instead).
|
||||||
|
* Added UtilFloat3 struct.
|
||||||
|
|
||||||
|
#### applet
|
||||||
|
* Fixed `__nx_applet_exit_mode` handling.
|
||||||
|
* `apm` is now only used/initialized for `AppletType_Application`.
|
||||||
|
* Simplified `appletGetAppletResourceUserId` to return the aruid directly, or 0 on "failure" (which is not really a failure condition).
|
||||||
|
* Changed `appletSetFocusHandlingMode` to return error if the applet type is not `AppletType_Application`.
|
||||||
|
* Added more fields to `SwkbdType` enum.
|
||||||
|
|
||||||
|
#### filesystem
|
||||||
|
* RomFS code now properly supports reading to uncached buffers.
|
||||||
|
* Added fsdev commands: fsdevMountDeviceSaveData, fsdevMountBcatSaveData, fsdevMountSystemBcatSaveData, fsdevMountTemporaryStorage, fsdevMountCacheStorage, fsdevMountSaveDataReadOnly.
|
||||||
|
* Added commands: fsOpenImageDirectoryFileSystem, fsOpenReadOnlySaveDataFileSystem, fsIsSignedSystemPartitionOnSdCardValid, fsOpen_DeviceSaveData, fsOpen_BcatSaveData, fsOpen_SystemBcatSaveData, fsOpen_TemporaryStorage, fsOpen_CacheStorage, fsOpen_SaveDataReadOnly.
|
||||||
|
* Added enum: FsImageDirectoryId.
|
||||||
|
* Removed path stack copy logic from fsFsQueryEntry.
|
||||||
|
|
||||||
|
#### graphics
|
||||||
|
* Removed bqDetachBuffer calls from nwindowReleaseBuffers as it does nothing in the place it's called.
|
||||||
|
* Fixed nvFence/nvGpu/nvMap to use service guard instead of unsafe reference counting.
|
||||||
|
|
||||||
|
#### hid
|
||||||
|
* **Fixed vibration handling**.
|
||||||
|
* **Added Ring-Con™ support**.
|
||||||
|
* Added hidbus service wrappers.
|
||||||
|
* Added commands: hidSetSixAxisSensorFusionParameters, hidGetSixAxisSensorFusionParameters, hidResetSixAxisSensorFusionParameters, hidSetGyroscopeZeroDriftMode, hidGetGyroscopeZeroDriftMode, hidResetGyroscopeZeroDriftMode.
|
||||||
|
* Majorly overhauled irs service support (infrared camera), with support for features introduced in later system versions.
|
||||||
|
* Added enum: HidGyroscopeZeroDriftMode.
|
||||||
|
* Corrected internal console six-axis sensor initialization function to actually use the right command.
|
||||||
|
* Corrected values of `JOYSTICK_MIN` and `JOYSTICK_MAX`.
|
||||||
|
|
||||||
|
#### other services
|
||||||
|
* Added apm command: apmGetPerformanceMode.
|
||||||
|
* Added caps:a service wrappers.
|
||||||
|
* Added caps:c service wrappers.
|
||||||
|
* Added caps:dc service wrappers.
|
||||||
|
* Added fan service wrappers.
|
||||||
|
* Added many missing lbl commands.
|
||||||
|
* Added nifm commands: nifmGetClientId (with corresponding NifmClientId struct), nifmIsAnyInternetRequestAccepted.
|
||||||
|
* Added nim service wrappers (only nimListSystemUpdateTask/nimDestroySystemUpdateTask for now).
|
||||||
|
* Majorly overhauled ns service support, with countless commands and structures.
|
||||||
|
* Added set:cal service wrappers.
|
||||||
|
* Completed and corrected all set:sys commands.
|
||||||
|
* Added tc service wrappers.
|
||||||
|
* Actually expose ldrShellFlushArguments, ldrDmntFlushArguments, spl\*GetServiceSession.
|
||||||
|
* Corrected minimum sysver for setsysGetHomeMenuScheme.
|
||||||
|
* Corrected minimum sysver for nsListApplicationContentMetaStatus.
|
||||||
|
* Fixed splSslLoadSecureExpModKey/splEsLoadSecureExpModKey/splRsaDecryptPrivateKey/splSslLoadSecureExpModKey/splEsLoadRsaOaepKey/splEsLoadSecureExpModKey/splFsLoadSecureExpModKey on 5.0+.
|
||||||
|
* Fixed plInitialize failure handling.
|
||||||
|
* Removed non-existent fsldrSetCurrentProcess.
|
||||||
|
|
||||||
|
#### miscellaneous
|
||||||
|
* Changed timezone support code to always report `NX` as the timezone name, fixing certain issues.
|
||||||
|
* Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
|
||||||
|
|
||||||
## Version 3.0.0
|
## Version 3.0.0
|
||||||
|
|
||||||
#### system
|
#### system
|
||||||
|
@ -9,7 +9,7 @@ endif
|
|||||||
include $(DEVKITPRO)/devkitA64/base_rules
|
include $(DEVKITPRO)/devkitA64/base_rules
|
||||||
|
|
||||||
export LIBNX_MAJOR := 3
|
export LIBNX_MAJOR := 3
|
||||||
export LIBNX_MINOR := 0
|
export LIBNX_MINOR := 1
|
||||||
export LIBNX_PATCH := 0
|
export LIBNX_PATCH := 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ extern "C" {
|
|||||||
#include "switch/services/pcv.h"
|
#include "switch/services/pcv.h"
|
||||||
#include "switch/services/clkrst.h"
|
#include "switch/services/clkrst.h"
|
||||||
#include "switch/services/fan.h"
|
#include "switch/services/fan.h"
|
||||||
|
#include "switch/services/pgl.h"
|
||||||
#include "switch/services/psm.h"
|
#include "switch/services/psm.h"
|
||||||
#include "switch/services/spsm.h"
|
#include "switch/services/spsm.h"
|
||||||
//#include "switch/services/bsd.h" Use <sys/socket.h> instead
|
//#include "switch/services/bsd.h" Use <sys/socket.h> instead
|
||||||
@ -82,6 +83,7 @@ extern "C" {
|
|||||||
#include "switch/services/vi.h"
|
#include "switch/services/vi.h"
|
||||||
#include "switch/services/nv.h"
|
#include "switch/services/nv.h"
|
||||||
#include "switch/services/nifm.h"
|
#include "switch/services/nifm.h"
|
||||||
|
#include "switch/services/nim.h"
|
||||||
#include "switch/services/ns.h"
|
#include "switch/services/ns.h"
|
||||||
#include "switch/services/ldr.h"
|
#include "switch/services/ldr.h"
|
||||||
#include "switch/services/ro.h"
|
#include "switch/services/ro.h"
|
||||||
@ -107,6 +109,8 @@ extern "C" {
|
|||||||
#include "switch/services/grc.h"
|
#include "switch/services/grc.h"
|
||||||
#include "switch/services/friends.h"
|
#include "switch/services/friends.h"
|
||||||
#include "switch/services/notif.h"
|
#include "switch/services/notif.h"
|
||||||
|
#include "switch/services/mii.h"
|
||||||
|
#include "switch/services/miiimg.h"
|
||||||
|
|
||||||
#include "switch/display/binder.h"
|
#include "switch/display/binder.h"
|
||||||
#include "switch/display/parcel.h"
|
#include "switch/display/parcel.h"
|
||||||
|
@ -96,6 +96,13 @@ typedef struct {
|
|||||||
u32 padding; ///< Padding.
|
u32 padding; ///< Padding.
|
||||||
} MemoryInfo;
|
} MemoryInfo;
|
||||||
|
|
||||||
|
/// Physical memory information structure.
|
||||||
|
typedef struct {
|
||||||
|
u64 physical_address; ///< Physical address.
|
||||||
|
u64 virtual_address; ///< Virtual address.
|
||||||
|
u64 size; ///< Size.
|
||||||
|
} PhysicalMemoryInfo;
|
||||||
|
|
||||||
/// Secure monitor arguments.
|
/// Secure monitor arguments.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 X[8]; ///< Values of X0 through X7.
|
u64 X[8]; ///< Values of X0 through X7.
|
||||||
@ -118,6 +125,12 @@ typedef enum {
|
|||||||
LimitableResource_Sessions=4, ///<How many sessions can a process own.
|
LimitableResource_Sessions=4, ///<How many sessions can a process own.
|
||||||
} LimitableResource;
|
} LimitableResource;
|
||||||
|
|
||||||
|
/// Thread Activity.
|
||||||
|
typedef enum {
|
||||||
|
ThreadActivity_Runnable = 0, ///< Thread can run.
|
||||||
|
ThreadActivity_Paused = 1, ///< Thread is paused.
|
||||||
|
} ThreadActivity;
|
||||||
|
|
||||||
/// Process Information.
|
/// Process Information.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ProcessInfoType_ProcessState=0, ///<What state is a process in.
|
ProcessInfoType_ProcessState=0, ///<What state is a process in.
|
||||||
@ -135,6 +148,12 @@ typedef enum {
|
|||||||
ProcessState_DebugSuspended=7, ///<Process execution suspended by debugger.
|
ProcessState_DebugSuspended=7, ///<Process execution suspended by debugger.
|
||||||
} ProcessState;
|
} ProcessState;
|
||||||
|
|
||||||
|
/// Process Activity.
|
||||||
|
typedef enum {
|
||||||
|
ProcessActivity_Runnable = 0, ///< Process can run.
|
||||||
|
ProcessActivity_Paused = 1, ///< Process is paused.
|
||||||
|
} ProcessActivity;
|
||||||
|
|
||||||
/// Debug Thread Parameters.
|
/// Debug Thread Parameters.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DebugThreadParam_ActualPriority=0,
|
DebugThreadParam_ActualPriority=0,
|
||||||
@ -199,11 +218,11 @@ typedef enum {
|
|||||||
|
|
||||||
/// GetSystemInfo PhysicalMemory Sub IDs.
|
/// GetSystemInfo PhysicalMemory Sub IDs.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PhysicalMemoryInfo_Application = 0, ///< Memory allocated for application usage.
|
PhysicalMemorySystemInfo_Application = 0, ///< Memory allocated for application usage.
|
||||||
PhysicalMemoryInfo_Applet = 1, ///< Memory allocated for applet usage.
|
PhysicalMemorySystemInfo_Applet = 1, ///< Memory allocated for applet usage.
|
||||||
PhysicalMemoryInfo_System = 2, ///< Memory allocated for system usage.
|
PhysicalMemorySystemInfo_System = 2, ///< Memory allocated for system usage.
|
||||||
PhysicalMemoryInfo_SystemUnsafe = 3, ///< Memory allocated for unsafe system usage (accessible to devices).
|
PhysicalMemorySystemInfo_SystemUnsafe = 3, ///< Memory allocated for unsafe system usage (accessible to devices).
|
||||||
} PhysicalMemoryInfo;
|
} PhysicalMemorySystemInfo;
|
||||||
|
|
||||||
/// SleepThread yield types.
|
/// SleepThread yield types.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -242,7 +261,7 @@ typedef struct {
|
|||||||
* @param[out] out_addr Variable to which write the address of the heap (which is randomized and fixed by the kernel)
|
* @param[out] out_addr Variable to which write the address of the heap (which is randomized and fixed by the kernel)
|
||||||
* @param[in] size Size of the heap, must be a multiple of 0x2000000 and [2.0.0+] less than 0x18000000.
|
* @param[in] size Size of the heap, must be a multiple of 0x2000000 and [2.0.0+] less than 0x18000000.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x00.
|
* @note Syscall number 0x01.
|
||||||
*/
|
*/
|
||||||
Result svcSetHeapSize(void** out_addr, u64 size);
|
Result svcSetHeapSize(void** out_addr, u64 size);
|
||||||
|
|
||||||
@ -254,7 +273,7 @@ Result svcSetHeapSize(void** out_addr, u64 size);
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @remark Perm_X is not allowed. Setting write-only is not allowed either (Perm_W).
|
* @remark Perm_X is not allowed. Setting write-only is not allowed either (Perm_W).
|
||||||
* This can be used to move back and forth between Perm_None, Perm_R and Perm_Rw.
|
* This can be used to move back and forth between Perm_None, Perm_R and Perm_Rw.
|
||||||
* @note Syscall number 0x01.
|
* @note Syscall number 0x02.
|
||||||
*/
|
*/
|
||||||
Result svcSetMemoryPermission(void* addr, u64 size, u32 perm);
|
Result svcSetMemoryPermission(void* addr, u64 size, u32 perm);
|
||||||
|
|
||||||
@ -266,7 +285,7 @@ Result svcSetMemoryPermission(void* addr, u64 size, u32 perm);
|
|||||||
* @param[in] val1 State1
|
* @param[in] val1 State1
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @remark See <a href="https://switchbrew.org/wiki/SVC#svcSetMemoryAttribute">switchbrew.org Wiki</a> for more details.
|
* @remark See <a href="https://switchbrew.org/wiki/SVC#svcSetMemoryAttribute">switchbrew.org Wiki</a> for more details.
|
||||||
* @note Syscall number 0x02.
|
* @note Syscall number 0x03.
|
||||||
*/
|
*/
|
||||||
Result svcSetMemoryAttribute(void* addr, u64 size, u32 val0, u32 val1);
|
Result svcSetMemoryAttribute(void* addr, u64 size, u32 val0, u32 val1);
|
||||||
|
|
||||||
@ -345,7 +364,7 @@ void svcSleepThread(s64 nano);
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x0C.
|
* @note Syscall number 0x0C.
|
||||||
*/
|
*/
|
||||||
Result svcGetThreadPriority(u32* priority, Handle handle);
|
Result svcGetThreadPriority(s32* priority, Handle handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets a thread's priority.
|
* @brief Sets a thread's priority.
|
||||||
@ -359,7 +378,7 @@ Result svcSetThreadPriority(Handle handle, u32 priority);
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x0E.
|
* @note Syscall number 0x0E.
|
||||||
*/
|
*/
|
||||||
Result svcGetThreadCoreMask(s32* preferred_core, u32* affinity_mask, Handle handle);
|
Result svcGetThreadCoreMask(s32* preferred_core, u64* affinity_mask, Handle handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets a thread's core mask.
|
* @brief Sets a thread's core mask.
|
||||||
@ -710,7 +729,7 @@ Result svcGetLastThreadInfo(LastThreadContext *out_context, u64 *out_tls_address
|
|||||||
* @note Syscall number 0x30.
|
* @note Syscall number 0x30.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetResourceLimitLimitValue(u64 *out, Handle reslimit_h, LimitableResource which);
|
Result svcGetResourceLimitLimitValue(s64 *out, Handle reslimit_h, LimitableResource which);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the maximum value a LimitableResource can have, for a Resource Limit handle.
|
* @brief Gets the maximum value a LimitableResource can have, for a Resource Limit handle.
|
||||||
@ -718,7 +737,7 @@ Result svcGetResourceLimitLimitValue(u64 *out, Handle reslimit_h, LimitableResou
|
|||||||
* @note Syscall number 0x31.
|
* @note Syscall number 0x31.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetResourceLimitCurrentValue(u64 *out, Handle reslimit_h, LimitableResource which);
|
Result svcGetResourceLimitCurrentValue(s64 *out, Handle reslimit_h, LimitableResource which);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
@ -730,7 +749,7 @@ Result svcGetResourceLimitCurrentValue(u64 *out, Handle reslimit_h, LimitableRes
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x32.
|
* @note Syscall number 0x32.
|
||||||
*/
|
*/
|
||||||
Result svcSetThreadActivity(Handle thread, bool paused);
|
Result svcSetThreadActivity(Handle thread, ThreadActivity paused);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dumps the registers of a thread paused by @ref svcSetThreadActivity (register groups: all).
|
* @brief Dumps the registers of a thread paused by @ref svcSetThreadActivity (register groups: all).
|
||||||
@ -958,7 +977,7 @@ Result svcReadWriteRegister(u32* outVal, u64 regAddr, u32 rwMask, u32 inVal);
|
|||||||
* @note Syscall number 0x4F.
|
* @note Syscall number 0x4F.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcSetProcessActivity(Handle process, bool paused);
|
Result svcSetProcessActivity(Handle process, ProcessActivity paused);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
@ -1008,15 +1027,25 @@ Result svcCreateInterruptEvent(Handle* handle, u64 irqNum, u32 flag);
|
|||||||
* @note Syscall number 0x54.
|
* @note Syscall number 0x54.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcQueryPhysicalAddress(u64 out[3], u64 virtaddr);
|
Result svcQueryPhysicalAddress(PhysicalMemoryInfo *out, u64 virtaddr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a virtual address mapped to a given IO range.
|
* @brief Returns a virtual address mapped to a given IO range.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x55.
|
* @note Syscall number 0x55.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
* @warning Only exists on [10.0.0+]. For older versions use \ref svcLegacyQueryIoMapping.
|
||||||
*/
|
*/
|
||||||
Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
Result svcQueryIoMapping(u64* virtaddr, u64* out_size, u64 physaddr, u64 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a virtual address mapped to a given IO range.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x55.
|
||||||
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
* @warning Only exists on [1.0.0-9.2.0]. For newer versions use \ref svcQueryIoMapping.
|
||||||
|
*/
|
||||||
|
Result svcLegacyQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
@ -1149,7 +1178,7 @@ Result svcTerminateDebugProcess(Handle debug);
|
|||||||
* @note Syscall number 0x63.
|
* @note Syscall number 0x63.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetDebugEvent(u8* event_out, Handle debug);
|
Result svcGetDebugEvent(void* event_out, Handle debug);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Continues a debugging session.
|
* @brief Continues a debugging session.
|
||||||
@ -1206,7 +1235,7 @@ Result svcSetDebugThreadContext(Handle debug, u64 threadID, const ThreadContext*
|
|||||||
* @note Syscall number 0x65.
|
* @note Syscall number 0x65.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetProcessList(u32 *num_out, u64 *pids_out, u32 max_pids);
|
Result svcGetProcessList(s32 *num_out, u64 *pids_out, u32 max_pids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves a list of all threads for a debug handle (or zero).
|
* @brief Retrieves a list of all threads for a debug handle (or zero).
|
||||||
@ -1214,7 +1243,7 @@ Result svcGetProcessList(u32 *num_out, u64 *pids_out, u32 max_pids);
|
|||||||
* @note Syscall number 0x66.
|
* @note Syscall number 0x66.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetThreadList(u32 *num_out, u64 *tids_out, u32 max_tids, Handle debug);
|
Result svcGetThreadList(s32 *num_out, u64 *tids_out, u32 max_tids, Handle debug);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
@ -1423,7 +1452,7 @@ Result svcTerminateProcess(Handle proc);
|
|||||||
* @note Syscall number 0x7C.
|
* @note Syscall number 0x7C.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
*/
|
*/
|
||||||
Result svcGetProcessInfo(u64 *out, Handle proc, ProcessInfoType which);
|
Result svcGetProcessInfo(s64 *out, Handle proc, ProcessInfoType which);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
@ -91,6 +91,12 @@ Result threadResume(Thread* t);
|
|||||||
*/
|
*/
|
||||||
Result threadDumpContext(ThreadContext* ctx, Thread* t);
|
Result threadDumpContext(ThreadContext* ctx, Thread* t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a pointer to the current thread structure.
|
||||||
|
* @return Thread information structure.
|
||||||
|
*/
|
||||||
|
Thread *threadGetSelf(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the raw handle to the current thread.
|
* @brief Gets the raw handle to the current thread.
|
||||||
* @return The current thread's handle.
|
* @return The current thread's handle.
|
||||||
|
@ -30,15 +30,34 @@ NX_CONSTEXPR FsDirectoryEntry* fsdevDirGetEntries(fsdev_dir_t *dir)
|
|||||||
/// Initializes and mounts the sdmc device if accessible.
|
/// Initializes and mounts the sdmc device if accessible.
|
||||||
Result fsdevMountSdmc(void);
|
Result fsdevMountSdmc(void);
|
||||||
|
|
||||||
/// Mounts the specified save data.
|
/// Mounts the specified SaveData.
|
||||||
Result fsdevMountSaveData(const char *name, u64 application_id, AccountUid uid);
|
Result fsdevMountSaveData(const char *name, u64 application_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Mounts the specified SaveData as ReadOnly.
|
||||||
|
/// Only available on [2.0.0+].
|
||||||
|
Result fsdevMountSaveDataReadOnly(const char *name, u64 application_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Mounts the specified BcatSaveData.
|
||||||
|
Result fsdevMountBcatSaveData(const char *name, u64 application_id);
|
||||||
|
|
||||||
/// Mounts the specified DeviceSaveData.
|
/// Mounts the specified DeviceSaveData.
|
||||||
Result fsdevMountDeviceSaveData(const char *name, u64 application_id);
|
Result fsdevMountDeviceSaveData(const char *name, u64 application_id);
|
||||||
|
|
||||||
/// Mounts the specified system save data.
|
/// Mounts the TemporaryStorage for the current process.
|
||||||
|
/// Only available on [3.0.0+].
|
||||||
|
Result fsdevMountTemporaryStorage(const char *name);
|
||||||
|
|
||||||
|
/// Mounts the specified CacheStorage.
|
||||||
|
/// Only available on [3.0.0+].
|
||||||
|
Result fsdevMountCacheStorage(const char *name, u64 application_id, u16 save_data_index);
|
||||||
|
|
||||||
|
/// Mounts the specified SystemSaveData.
|
||||||
Result fsdevMountSystemSaveData(const char *name, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid);
|
Result fsdevMountSystemSaveData(const char *name, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Mounts the specified SystemBcatSaveData.
|
||||||
|
/// Only available on [4.0.0+].
|
||||||
|
Result fsdevMountSystemBcatSaveData(const char *name, u64 system_save_data_id);
|
||||||
|
|
||||||
/// Mounts the input fs with the specified device name. fsdev will handle closing the fs when required, including when fsdevMountDevice() fails.
|
/// Mounts the input fs with the specified device name. fsdev will handle closing the fs when required, including when fsdevMountDevice() fails.
|
||||||
/// Returns -1 when any errors occur.
|
/// Returns -1 when any errors occur.
|
||||||
/// Input device name string shouldn't exceed 31 characters, and shouldn't have a trailing colon.
|
/// Input device name string shouldn't exceed 31 characters, and shouldn't have a trailing colon.
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* @copyright libnx Authors
|
* @copyright libnx Authors
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
|
||||||
struct in_addr;
|
struct in_addr;
|
||||||
|
|
||||||
@ -15,8 +16,20 @@ extern struct in_addr __nxlink_host;
|
|||||||
#define NXLINK_CLIENT_PORT 28771 ///< nxlink TCP client port
|
#define NXLINK_CLIENT_PORT 28771 ///< nxlink TCP client port
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets up stdout/stderr redirection to the nxlink host.
|
* @brief Connects to the nxlink host, setting up an output stream.
|
||||||
|
* @param[in] redirStdout Whether to redirect stdout to nxlink output.
|
||||||
|
* @param[in] redirStderr Whether to redirect stderr to nxlink output.
|
||||||
* @return Socket fd on success, negative number on failure.
|
* @return Socket fd on success, negative number on failure.
|
||||||
* @note The socket should be closed with close() during application cleanup.
|
* @note The socket should be closed with close() during application cleanup.
|
||||||
*/
|
*/
|
||||||
int nxlinkStdio(void);
|
int nxlinkConnectToHost(bool redirStdout, bool redirStderr);
|
||||||
|
|
||||||
|
/// Same as \ref nxlinkConnectToHost but redirecting both stdout/stderr.
|
||||||
|
NX_INLINE int nxlinkStdio(void) {
|
||||||
|
return nxlinkConnectToHost(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as \ref nxlinkConnectToHost but redirecting only stderr.
|
||||||
|
NX_INLINE int nxlinkStdioForDebug(void) {
|
||||||
|
return nxlinkConnectToHost(false, true);
|
||||||
|
}
|
||||||
|
@ -2284,6 +2284,7 @@ Result appletGetHomeButtonDoubleClickEnabled(bool *out);
|
|||||||
/**
|
/**
|
||||||
* @brief Open an \ref AppletApplication for the currently running Application.
|
* @brief Open an \ref AppletApplication for the currently running Application.
|
||||||
* @note Should not be used when no Application is running.
|
* @note Should not be used when no Application is running.
|
||||||
|
* @note Only available on [1.0.0-9.2.0].
|
||||||
* @param[out] a \ref AppletApplication
|
* @param[out] a \ref AppletApplication
|
||||||
*/
|
*/
|
||||||
Result appletOpenMainApplication(AppletApplication *a);
|
Result appletOpenMainApplication(AppletApplication *a);
|
||||||
|
@ -51,6 +51,17 @@ Result audoutAppendAudioOutBuffer(AudioOutBuffer *Buffer);
|
|||||||
Result audoutGetReleasedAudioOutBuffer(AudioOutBuffer **Buffer, u32 *ReleasedBuffersCount);
|
Result audoutGetReleasedAudioOutBuffer(AudioOutBuffer **Buffer, u32 *ReleasedBuffersCount);
|
||||||
Result audoutContainsAudioOutBuffer(AudioOutBuffer *Buffer, bool *ContainsBuffer);
|
Result audoutContainsAudioOutBuffer(AudioOutBuffer *Buffer, bool *ContainsBuffer);
|
||||||
|
|
||||||
|
/// Only available with [4.0.0+].
|
||||||
|
Result audoutGetAudioOutBufferCount(u32 *count);
|
||||||
|
/// Only available with [4.0.0+].
|
||||||
|
Result audoutGetAudioOutPlayedSampleCount(u64 *count);
|
||||||
|
/// Only available with [4.0.0+].
|
||||||
|
Result audoutFlushAudioOutBuffers(bool *flushed);
|
||||||
|
/// Only available with [6.0.0+].
|
||||||
|
Result audoutSetAudioOutVolume(float volume);
|
||||||
|
/// Only available with [6.0.0+].
|
||||||
|
Result audoutGetAudioOutVolume(float *volume);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Submits an audio sample data buffer for playing and waits for it to finish playing.
|
* @brief Submits an audio sample data buffer for playing and waits for it to finish playing.
|
||||||
* @brief Uses \ref audoutAppendAudioOutBuffer and \ref audoutWaitPlayFinish internally.
|
* @brief Uses \ref audoutAppendAudioOutBuffer and \ref audoutWaitPlayFinish internally.
|
||||||
|
@ -24,4 +24,4 @@ Service* bpcGetServiceSession(void);
|
|||||||
|
|
||||||
Result bpcShutdownSystem(void);
|
Result bpcShutdownSystem(void);
|
||||||
Result bpcRebootSystem(void);
|
Result bpcRebootSystem(void);
|
||||||
Result bpcGetSleepButtonState(BpcSleepButtonState *out);
|
Result bpcGetSleepButtonState(BpcSleepButtonState *out); ///< [2.0.0+]
|
||||||
|
@ -75,5 +75,7 @@ ssize_t bsdRead(int fd, void *buf, size_t count);
|
|||||||
int bsdClose(int fd);
|
int bsdClose(int fd);
|
||||||
/// Duplicate a socket (bsd:s).
|
/// Duplicate a socket (bsd:s).
|
||||||
int bsdDuplicateSocket(int sockfd);
|
int bsdDuplicateSocket(int sockfd);
|
||||||
|
int bsdRecvMMsg(int sockfd, void *buf, size_t size, unsigned int vlen, int flags, struct timespec *timeout);
|
||||||
|
int bsdSendMMsg(int sockfd, void *buf, size_t size, unsigned int vlen, int flags);
|
||||||
|
|
||||||
// TODO: Reverse-engineer GetResourceStatistics. Implement sendmmsg/recvmmsg (custom (un)serialization)
|
// TODO: Reverse-engineer GetResourceStatistics.
|
||||||
|
@ -323,16 +323,17 @@ Result fsOpenBisStorage(FsStorage* out, FsBisPartitionId partitionId);
|
|||||||
Result fsOpenSdCardFileSystem(FsFileSystem* out);
|
Result fsOpenSdCardFileSystem(FsFileSystem* out);
|
||||||
|
|
||||||
Result fsCreateSaveDataFileSystemBySystemSaveDataId(const FsSaveDataAttribute* attr, const FsSaveDataCreationInfo* creation_info);
|
Result fsCreateSaveDataFileSystemBySystemSaveDataId(const FsSaveDataAttribute* attr, const FsSaveDataCreationInfo* creation_info);
|
||||||
Result fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId save_data_space_id, u64 saveID); /// [2.0.0+]
|
Result fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId save_data_space_id, u64 saveID); ///< [2.0.0+]
|
||||||
|
|
||||||
Result fsIsExFatSupported(bool* out);
|
Result fsIsExFatSupported(bool* out);
|
||||||
|
|
||||||
Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handle, FsGameCardPartition partition);
|
Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handle, FsGameCardPartition partition);
|
||||||
|
|
||||||
Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId save_data_space_id, u64 saveID, s64 dataSize, s64 journalSize); /// [3.0.0+]
|
Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId save_data_space_id, u64 saveID, s64 dataSize, s64 journalSize); ///< [3.0.0+]
|
||||||
|
|
||||||
Result fsOpenSaveDataFileSystem(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr);
|
Result fsOpenSaveDataFileSystem(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr);
|
||||||
Result fsOpenSaveDataFileSystemBySystemSaveDataId(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr);
|
Result fsOpenSaveDataFileSystemBySystemSaveDataId(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr);
|
||||||
|
Result fsOpenReadOnlySaveDataFileSystem(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr); ///< [2.0.0+].
|
||||||
|
|
||||||
Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId save_data_space_id, u64 saveID);
|
Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId save_data_space_id, u64 saveID);
|
||||||
Result fsReadSaveDataFileSystemExtraData(void* buf, size_t len, u64 saveID);
|
Result fsReadSaveDataFileSystemExtraData(void* buf, size_t len, u64 saveID);
|
||||||
@ -342,7 +343,7 @@ Result fsOpenSaveDataInfoReader(FsSaveDataInfoReader* out, FsSaveDataSpaceId sav
|
|||||||
|
|
||||||
Result fsOpenImageDirectoryFileSystem(FsFileSystem* out, FsImageDirectoryId image_directory_id);
|
Result fsOpenImageDirectoryFileSystem(FsFileSystem* out, FsImageDirectoryId image_directory_id);
|
||||||
Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id);
|
Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id);
|
||||||
Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id); /// [7.0.0+]
|
Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id); ///< [7.0.0+]
|
||||||
|
|
||||||
Result fsOpenDataStorageByCurrentProcess(FsStorage* out);
|
Result fsOpenDataStorageByCurrentProcess(FsStorage* out);
|
||||||
Result fsOpenDataStorageByDataId(FsStorage* out, u64 dataId, NcmStorageId storageId);
|
Result fsOpenDataStorageByDataId(FsStorage* out, u64 dataId, NcmStorageId storageId);
|
||||||
@ -371,14 +372,35 @@ Result fsCreate_SystemSaveData(FsSaveDataSpaceId save_data_space_id, u64 system_
|
|||||||
/// See \ref FsSaveDataAttribute for application_id and uid.
|
/// See \ref FsSaveDataAttribute for application_id and uid.
|
||||||
Result fsOpen_SaveData(FsFileSystem* out, u64 application_id, AccountUid uid);
|
Result fsOpen_SaveData(FsFileSystem* out, u64 application_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Wrapper for fsOpenReadOnlySaveDataFileSystem.
|
||||||
|
/// Only available on [2.0.0+].
|
||||||
|
/// See \ref FsSaveDataAttribute for application_id and uid.
|
||||||
|
Result fsOpen_SaveDataReadOnly(FsFileSystem* out, u64 application_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Wrapper for fsOpenSaveDataFileSystem, for opening BcatSaveData.
|
||||||
|
Result fsOpen_BcatSaveData(FsFileSystem* out, u64 application_id);
|
||||||
|
|
||||||
/// Wrapper for fsOpenSaveDataFileSystem, for opening DeviceSaveData.
|
/// Wrapper for fsOpenSaveDataFileSystem, for opening DeviceSaveData.
|
||||||
/// See \ref FsSaveDataAttribute for application_id.
|
/// See \ref FsSaveDataAttribute for application_id.
|
||||||
Result fsOpen_DeviceSaveData(FsFileSystem* out, u64 application_id);
|
Result fsOpen_DeviceSaveData(FsFileSystem* out, u64 application_id);
|
||||||
|
|
||||||
/// Wrapper for fsOpenSaveDataFileSystemBySystemSaveDataId.
|
/// Wrapper for fsOpenSaveDataFileSystem, for opening TemporaryStorage.
|
||||||
|
/// Only available on [3.0.0+].
|
||||||
|
Result fsOpen_TemporaryStorage(FsFileSystem* out);
|
||||||
|
|
||||||
|
/// Wrapper for fsOpenSaveDataFileSystem, for opening CacheStorage.
|
||||||
|
/// Only available on [3.0.0+].
|
||||||
|
/// See \ref FsSaveDataAttribute for application_id.
|
||||||
|
Result fsOpen_CacheStorage(FsFileSystem* out, u64 application_id, u16 save_data_index);
|
||||||
|
|
||||||
|
/// Wrapper for fsOpenSaveDataFileSystemBySystemSaveDataId, for opening SystemSaveData.
|
||||||
/// WARNING: You can brick when writing to SystemSaveData, if the data is corrupted etc.
|
/// WARNING: You can brick when writing to SystemSaveData, if the data is corrupted etc.
|
||||||
Result fsOpen_SystemSaveData(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid);
|
Result fsOpen_SystemSaveData(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid);
|
||||||
|
|
||||||
|
/// Wrapper for fsOpenSaveDataFileSystemBySystemSaveDataId, for opening SystemBcatSaveData.
|
||||||
|
/// Only available on [4.0.0+].
|
||||||
|
Result fsOpen_SystemBcatSaveData(FsFileSystem* out, u64 system_save_data_id);
|
||||||
|
|
||||||
// IFileSystem
|
// IFileSystem
|
||||||
Result fsFsCreateFile(FsFileSystem* fs, const char* path, s64 size, u32 option);
|
Result fsFsCreateFile(FsFileSystem* fs, const char* path, s64 size, u32 option);
|
||||||
Result fsFsDeleteFile(FsFileSystem* fs, const char* path);
|
Result fsFsDeleteFile(FsFileSystem* fs, const char* path);
|
||||||
|
@ -8,6 +8,14 @@
|
|||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "../sf/service.h"
|
#include "../sf/service.h"
|
||||||
#include "../services/fs.h"
|
#include "../services/fs.h"
|
||||||
|
#include "../crypto/sha256.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 signature[0x100];
|
||||||
|
u8 hash[SHA256_HASH_SIZE];
|
||||||
|
bool is_signed;
|
||||||
|
u8 reserved[3];
|
||||||
|
} FsCodeInfo;
|
||||||
|
|
||||||
/// Initialize fsp-ldr.
|
/// Initialize fsp-ldr.
|
||||||
Result fsldrInitialize(void);
|
Result fsldrInitialize(void);
|
||||||
@ -18,5 +26,5 @@ void fsldrExit(void);
|
|||||||
/// Gets the Service object for the actual fsp-ldr service session.
|
/// Gets the Service object for the actual fsp-ldr service session.
|
||||||
Service* fsldrGetServiceSession(void);
|
Service* fsldrGetServiceSession(void);
|
||||||
|
|
||||||
Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out);
|
Result fsldrOpenCodeFileSystem(FsCodeInfo* out_code_info, u64 tid, const char *path, FsFileSystem* out);
|
||||||
Result fsldrIsArchivedProgram(u64 pid, bool *out);
|
Result fsldrIsArchivedProgram(u64 pid, bool *out);
|
||||||
|
@ -10,44 +10,373 @@
|
|||||||
#include "../sf/service.h"
|
#include "../sf/service.h"
|
||||||
#include "../services/hid.h"
|
#include "../services/hid.h"
|
||||||
|
|
||||||
typedef struct {
|
#define IRS_MAX_CAMERAS 0x9
|
||||||
u64 unk_x0;
|
|
||||||
u8 unk_x8;
|
|
||||||
u8 unk_x9;
|
|
||||||
u8 unk_xa;
|
|
||||||
u8 pad[5];
|
|
||||||
u16 unk_x10;
|
|
||||||
u32 unk_x12;
|
|
||||||
u16 unk_x16;
|
|
||||||
u32 unk_constant;//offset 0x18
|
|
||||||
u8 unk_x1c;
|
|
||||||
u8 unk_x1d;
|
|
||||||
u8 pad2[2];
|
|
||||||
} PACKED IrsPackedMomentProcessorConfig;
|
|
||||||
|
|
||||||
|
/// IrCameraStatus
|
||||||
|
typedef enum {
|
||||||
|
IrsIrCameraStatus_Available = 0, ///< Available
|
||||||
|
IrsIrCameraStatus_Unsupported = 1, ///< Unsupported
|
||||||
|
IrsIrCameraStatus_Unconnected = 2, ///< Unconnected
|
||||||
|
} IrsIrCameraStatus;
|
||||||
|
|
||||||
|
/// IrCameraInternalStatus
|
||||||
|
typedef enum {
|
||||||
|
IrsIrCameraInternalStatus_Stopped = 0, ///< Stopped
|
||||||
|
IrsIrCameraInternalStatus_FirmwareUpdateNeeded = 1, ///< FirmwareUpdateNeeded
|
||||||
|
IrsIrCameraInternalStatus_Unknown2 = 2, ///< Unknown
|
||||||
|
IrsIrCameraInternalStatus_Unknown3 = 3, ///< Unknown
|
||||||
|
IrsIrCameraInternalStatus_Unknown4 = 4, ///< Unknown
|
||||||
|
IrsIrCameraInternalStatus_FirmwareVersionRequested = 5, ///< FirmwareVersionRequested
|
||||||
|
IrsIrCameraInternalStatus_FirmwareVersionIsInvalid = 6, ///< FirmwareVersionIsInvalid
|
||||||
|
IrsIrCameraInternalStatus_Ready = 7, ///< [4.0.0+] Ready
|
||||||
|
IrsIrCameraInternalStatus_Setting = 8, ///< [4.0.0+] Setting
|
||||||
|
} IrsIrCameraInternalStatus;
|
||||||
|
|
||||||
|
/// IrSensorMode
|
||||||
|
typedef enum {
|
||||||
|
IrsIrSensorMode_None = 0, ///< None
|
||||||
|
IrsIrSensorMode_MomentProcessor = 1, ///< MomentProcessor
|
||||||
|
IrsIrSensorMode_ClusteringProcessor = 2, ///< ClusteringProcessor
|
||||||
|
IrsIrSensorMode_ImageTransferProcessor = 3, ///< ImageTransferProcessor
|
||||||
|
IrsIrSensorMode_PointingProcessor = 4, ///< PointingProcessor
|
||||||
|
IrsIrSensorMode_TeraPluginProcessor = 5, ///< TeraPluginProcessor
|
||||||
|
IrsIrSensorMode_IrLedProcessor = 6, ///< IrLedProcessor (doesn't apply to IrsDeviceFormat::ir_sensor_mode)
|
||||||
|
} IrsIrSensorMode;
|
||||||
|
|
||||||
|
/// ImageProcessorStatus
|
||||||
|
typedef enum {
|
||||||
|
IrsImageProcessorStatus_Stopped = 0, ///< Stopped
|
||||||
|
IrsImageProcessorStatus_Running = 1, ///< Running
|
||||||
|
} IrsImageProcessorStatus;
|
||||||
|
|
||||||
|
/// ImageTransferProcessorFormat. IR Sensor image resolution.
|
||||||
|
typedef enum {
|
||||||
|
IrsImageTransferProcessorFormat_320x240 = 0, ///< 320x240
|
||||||
|
IrsImageTransferProcessorFormat_160x120 = 1, ///< 160x120
|
||||||
|
IrsImageTransferProcessorFormat_80x60 = 2, ///< 80x60
|
||||||
|
IrsImageTransferProcessorFormat_40x30 = 3, ///< [4.0.0+] 40x30
|
||||||
|
IrsImageTransferProcessorFormat_20x15 = 4, ///< [4.0.0+] 20x15
|
||||||
|
} IrsImageTransferProcessorFormat;
|
||||||
|
|
||||||
|
/// AdaptiveClusteringMode
|
||||||
|
typedef enum {
|
||||||
|
IrsAdaptiveClusteringMode_StaticFov = 0, ///< StaticFov
|
||||||
|
IrsAdaptiveClusteringMode_DynamicFov = 1, ///< DynamicFov
|
||||||
|
} IrsAdaptiveClusteringMode;
|
||||||
|
|
||||||
|
/// AdaptiveClusteringTargetDistance
|
||||||
|
typedef enum {
|
||||||
|
IrsAdaptiveClusteringTargetDistance_Near = 0, ///< Near
|
||||||
|
IrsAdaptiveClusteringTargetDistance_Middle = 1, ///< Middle
|
||||||
|
IrsAdaptiveClusteringTargetDistance_Far = 2, ///< Far
|
||||||
|
} IrsAdaptiveClusteringTargetDistance;
|
||||||
|
|
||||||
|
/// HandAnalysisMode
|
||||||
|
typedef enum {
|
||||||
|
IrsHandAnalysisMode_Silhouette = 1, ///< Silhouette
|
||||||
|
IrsHandAnalysisMode_Image = 2, ///< Image
|
||||||
|
IrsHandAnalysisMode_SilhouetteAndImage = 3, ///< SilhouetteAndImage
|
||||||
|
IrsHandAnalysisMode_SilhouetteOnly = 4, ///< [4.0.0+] SilhouetteOnly
|
||||||
|
} IrsHandAnalysisMode;
|
||||||
|
|
||||||
|
/// Internal validation callblack.
|
||||||
|
typedef bool (*IrsValidationCb)(void* userdata, void* arg);
|
||||||
|
|
||||||
|
/// IrCameraHandle
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 exposure; ///< IR Sensor exposure time in nanoseconds.
|
u8 player_number; ///< PlayerNumber
|
||||||
u32 ir_leds; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
u8 device_type; ///< DeviceType
|
||||||
u32 digital_gain; ///< IR sensor signal's digital gain.
|
u8 reserved[0x2]; ///< Reserved
|
||||||
u8 color_invert; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
} IrsIrCameraHandle;
|
||||||
u8 pad[7];
|
|
||||||
u32 sensor_res; ///< IR Sensor resolution. 0: 240x320, 1: 120x160, 2: 60x80.
|
/// PackedMcuVersion
|
||||||
|
typedef struct {
|
||||||
|
u16 major_version; ///< MajorVersion
|
||||||
|
u16 minor_version; ///< MinorVersion
|
||||||
|
} IrsPackedMcuVersion;
|
||||||
|
|
||||||
|
/// PackedFunctionLevel
|
||||||
|
typedef struct {
|
||||||
|
u8 ir_sensor_function_level; ///< IrSensorFunctionLevel
|
||||||
|
u8 reserved[0x3]; ///< Reserved
|
||||||
|
} IrsPackedFunctionLevel;
|
||||||
|
|
||||||
|
/// Rect
|
||||||
|
typedef struct {
|
||||||
|
s16 x; ///< X
|
||||||
|
s16 y; ///< Y
|
||||||
|
s16 width; ///< Width
|
||||||
|
s16 height; ///< Height
|
||||||
|
} IrsRect;
|
||||||
|
|
||||||
|
/// IrsMomentProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u32 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u32 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x7]; ///< Reserved.
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
u32 preprocess; ///< Preprocess
|
||||||
|
u32 preprocess_intensity_threshold; ///< PreprocessIntensityThreshold
|
||||||
|
} IrsMomentProcessorConfig;
|
||||||
|
|
||||||
|
/// PackedMomentProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u8 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u8 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x5]; ///< Reserved.
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u8 preprocess; ///< Preprocess
|
||||||
|
u8 preprocess_intensity_threshold; ///< PreprocessIntensityThreshold
|
||||||
|
u8 reserved2[0x2]; ///< Reserved.
|
||||||
|
} IrsPackedMomentProcessorConfig;
|
||||||
|
|
||||||
|
/// ClusteringProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u32 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u32 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x7]; ///< Reserved.
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
u32 object_pixel_count_min; ///< ObjectPixelCountMin
|
||||||
|
u32 object_pixel_count_max; ///< ObjectPixelCountMax
|
||||||
|
u32 object_intensity_min; ///< ObjectIntensityMin
|
||||||
|
u8 is_external_light_filter_enabled; ///< IsExternalLightFilterEnabled
|
||||||
|
} IrsClusteringProcessorConfig;
|
||||||
|
|
||||||
|
/// PackedClusteringProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u8 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u8 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x5]; ///< Reserved.
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u32 object_pixel_count_min; ///< ObjectPixelCountMin
|
||||||
|
u32 object_pixel_count_max; ///< ObjectPixelCountMax
|
||||||
|
u8 object_intensity_min; ///< ObjectIntensityMin
|
||||||
|
u8 is_external_light_filter_enabled; ///< IsExternalLightFilterEnabled
|
||||||
|
u8 reserved2[0x2]; ///< Reserved.
|
||||||
|
} IrsPackedClusteringProcessorConfig;
|
||||||
|
|
||||||
|
/// ImageTransferProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u32 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u32 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x7]; ///< Reserved.
|
||||||
|
u32 format; ///< \ref IrsImageTransferProcessorFormat
|
||||||
} IrsImageTransferProcessorConfig;
|
} IrsImageTransferProcessorConfig;
|
||||||
|
|
||||||
|
/// ImageTransferProcessorExConfig
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 exposure; ///< IR Sensor exposure time in nanoseconds.
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
u8 ir_leds; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
u32 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
u8 digital_gain; ///< IR sensor signal's digital gain.
|
u32 gain; ///< IR sensor signal's digital gain.
|
||||||
u8 color_invert; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
u8 pad[5];
|
u8 reserved[0x7]; ///< Reserved.
|
||||||
u32 unk_constant;//offset 0x10
|
u32 orig_format; ///< OrigFormat \ref IrsImageTransferProcessorFormat
|
||||||
u8 sensor_res; ///< IR Sensor resolution. 0: 240x320, 1: 120x160, 2: 60x80.
|
u32 trimming_format; ///< TrimmingFormat \ref IrsImageTransferProcessorFormat
|
||||||
u8 pad2[3];
|
u16 trimming_start_x; ///< TrimmingStartX
|
||||||
|
u16 trimming_start_y; ///< TrimmingStartY
|
||||||
|
u8 is_external_light_filter_enabled; ///< IsExternalLightFilterEnabled
|
||||||
|
} IrsImageTransferProcessorExConfig;
|
||||||
|
|
||||||
|
/// PackedImageTransferProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
|
u8 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u8 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x5]; ///< Reserved.
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u8 format; ///< \ref IrsImageTransferProcessorFormat
|
||||||
|
u8 reserved2[0x3]; ///< Reserved.
|
||||||
} IrsPackedImageTransferProcessorConfig;
|
} IrsPackedImageTransferProcessorConfig;
|
||||||
|
|
||||||
|
/// PackedImageTransferProcessorExConfig
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 unk_x0[0x10];
|
u64 exposure_time; ///< IR Sensor exposure time in nanoseconds.
|
||||||
} PACKED IrsImageTransferProcessorState;
|
u8 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u8 gain; ///< IR sensor signal's digital gain.
|
||||||
|
u8 is_negative_image_used; ///< Inverts the colors of the captured image. 0: Normal image, 1: Negative image.
|
||||||
|
u8 reserved[0x5]; ///< Reserved.
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u8 orig_format; ///< OrigFormat \ref IrsImageTransferProcessorFormat
|
||||||
|
u8 trimming_format; ///< TrimmingFormat \ref IrsImageTransferProcessorFormat
|
||||||
|
u16 trimming_start_x; ///< TrimmingStartX
|
||||||
|
u16 trimming_start_y; ///< TrimmingStartY
|
||||||
|
u8 is_external_light_filter_enabled; ///< IsExternalLightFilterEnabled
|
||||||
|
u8 reserved2[0x5]; ///< Reserved.
|
||||||
|
} IrsPackedImageTransferProcessorExConfig;
|
||||||
|
|
||||||
|
/// ImageTransferProcessorState
|
||||||
|
typedef struct {
|
||||||
|
u64 sampling_number; ///< SamplingNumber
|
||||||
|
u32 ambient_noise_level; ///< AmbientNoiseLevel
|
||||||
|
u8 reserved[0x4]; ///< Reserved
|
||||||
|
} IrsImageTransferProcessorState;
|
||||||
|
|
||||||
|
/// PackedPointingProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
} IrsPackedPointingProcessorConfig;
|
||||||
|
|
||||||
|
/// TeraPluginProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u8 mode; ///< Mode
|
||||||
|
u8 unk_x1; ///< [6.0.0+] Unknown
|
||||||
|
u8 unk_x2; ///< [6.0.0+] Unknown
|
||||||
|
u8 unk_x3; ///< [6.0.0+] Unknown
|
||||||
|
} IrsTeraPluginProcessorConfig;
|
||||||
|
|
||||||
|
/// PackedTeraPluginProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u8 mode; ///< Mode
|
||||||
|
u8 unk_x5; ///< [6.0.0+] This is set to 0x2 | (IrsTeraPluginProcessorConfig::unk_x1 << 7).
|
||||||
|
u8 unk_x6; ///< [6.0.0+] IrsTeraPluginProcessorConfig::unk_x2
|
||||||
|
u8 unk_x7; ///< [6.0.0+] IrsTeraPluginProcessorConfig::unk_x3
|
||||||
|
} IrsPackedTeraPluginProcessorConfig;
|
||||||
|
|
||||||
|
/// IrLedProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u32 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
} IrsIrLedProcessorConfig;
|
||||||
|
|
||||||
|
/// PackedIrLedProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
IrsPackedMcuVersion required_mcu_version; ///< RequiredMcuVersion
|
||||||
|
u8 light_target; ///< Controls the IR leds. 0: All leds, 1: Bright group, 2: Dim group, 3: None.
|
||||||
|
u8 pad[0x3]; ///< Padding
|
||||||
|
} IrsPackedIrLedProcessorConfig;
|
||||||
|
|
||||||
|
/// AdaptiveClusteringProcessorConfig
|
||||||
|
typedef struct {
|
||||||
|
u32 mode; ///< \ref IrsAdaptiveClusteringMode
|
||||||
|
u32 target_distance; ///< [6.0.0+] \ref IrsAdaptiveClusteringTargetDistance
|
||||||
|
} IrsAdaptiveClusteringProcessorConfig;
|
||||||
|
|
||||||
|
/// HandAnalysisConfig
|
||||||
|
typedef struct {
|
||||||
|
u32 mode; ///< \ref IrsHandAnalysisMode
|
||||||
|
} IrsHandAnalysisConfig;
|
||||||
|
|
||||||
|
/// MomentStatistic
|
||||||
|
typedef struct {
|
||||||
|
float average_intensity; ///< AverageIntensity
|
||||||
|
float centroid_x; ///< CentroidX
|
||||||
|
float centroid_y; ///< CentroidY
|
||||||
|
} IrsMomentStatistic;
|
||||||
|
|
||||||
|
/// MomentProcessorState
|
||||||
|
typedef struct {
|
||||||
|
s64 sampling_number; ///< SamplingNumber
|
||||||
|
u64 timestamp; ///< TimeStamp
|
||||||
|
|
||||||
|
u32 ambient_noise_level; ///< AmbientNoiseLevel
|
||||||
|
u8 reserved[0x4]; ///< Reserved
|
||||||
|
IrsMomentStatistic statistic[0x30]; ///< \ref IrsMomentStatistic
|
||||||
|
} IrsMomentProcessorState;
|
||||||
|
|
||||||
|
/// ClusteringData
|
||||||
|
typedef struct {
|
||||||
|
float average_intensity; ///< AverageIntensity
|
||||||
|
float centroid_x; ///< CentroidX
|
||||||
|
float centroid_y; ///< CentroidY
|
||||||
|
u32 pixel_count; ///< PixelCount
|
||||||
|
u16 bound_x; ///< BoundX
|
||||||
|
u16 bound_y; ///< BoundY
|
||||||
|
u16 boundt_width; ///< BoundtWidth
|
||||||
|
u16 bound_height; ///< BoundHeight
|
||||||
|
} IrsClusteringData;
|
||||||
|
|
||||||
|
/// ClusteringProcessorState
|
||||||
|
typedef struct {
|
||||||
|
s64 sampling_number; ///< SamplingNumber
|
||||||
|
u64 timestamp; ///< TimeStamp
|
||||||
|
|
||||||
|
u8 object_count; ///< ObjectCount
|
||||||
|
u8 reserved[0x3]; ///< Reserved
|
||||||
|
u32 ambient_noise_level; ///< AmbientNoiseLevel
|
||||||
|
IrsClusteringData data[0x10]; ///< \ref IrsClusteringData
|
||||||
|
} IrsClusteringProcessorState;
|
||||||
|
|
||||||
|
/// PointingProcessorMarkerState
|
||||||
|
typedef struct {
|
||||||
|
s64 sampling_number; ///< SamplingNumber
|
||||||
|
u64 timestamp; ///< TimeStamp
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 pointing_status; ///< PointingStatus
|
||||||
|
u8 reserved[0x3]; ///< Reserved
|
||||||
|
u8 unk_x4[0x4]; ///< Unknown
|
||||||
|
float unk_x8; ///< Unknown
|
||||||
|
float position_x; ///< PositionX
|
||||||
|
float position_y; ///< PositionY
|
||||||
|
float unk_x14; ///< Unknown
|
||||||
|
IrsRect window_of_interest; ///< WindowOfInterest
|
||||||
|
} data[3];
|
||||||
|
} IrsPointingProcessorMarkerState;
|
||||||
|
|
||||||
|
/// PointingProcessorState
|
||||||
|
typedef struct {
|
||||||
|
s64 sampling_number; ///< SamplingNumber
|
||||||
|
u64 timestamp; ///< TimeStamp
|
||||||
|
|
||||||
|
u32 pointing_status; ///< PointingStatus
|
||||||
|
float position_x; ///< PositionX
|
||||||
|
float position_y; ///< PositionY
|
||||||
|
u8 reserved[0x4]; ///< Reserved
|
||||||
|
} IrsPointingProcessorState;
|
||||||
|
|
||||||
|
/// TeraPluginProcessorState
|
||||||
|
typedef struct {
|
||||||
|
s64 sampling_number; ///< SamplingNumber
|
||||||
|
u64 timestamp; ///< TimeStamp
|
||||||
|
u32 ambient_noise_level; ///< AmbientNoiseLevel
|
||||||
|
u8 plugin_data[0x12c]; ///< PluginData
|
||||||
|
} IrsTeraPluginProcessorState;
|
||||||
|
|
||||||
|
/// ProcessorState
|
||||||
|
typedef struct {
|
||||||
|
s64 start; ///< Start
|
||||||
|
u32 count; ///< Count
|
||||||
|
u32 pad; ///< Padding
|
||||||
|
|
||||||
|
u8 data[0xe10]; ///< Contains an array of *ProcessorState, depending on IrsDeviceFormat::ir_sensor_mode.
|
||||||
|
} IrsProcessorState;
|
||||||
|
|
||||||
|
/// DeviceFormat
|
||||||
|
typedef struct {
|
||||||
|
u32 ir_camera_status; ///< \ref IrsIrCameraStatus
|
||||||
|
u32 ir_camera_internal_status; ///< \ref IrsIrCameraInternalStatus
|
||||||
|
u32 ir_sensor_mode; ///< \ref IrsIrSensorMode
|
||||||
|
u32 pad; ///< Padding
|
||||||
|
|
||||||
|
IrsProcessorState processor_state; ///< \ref IrsProcessorState
|
||||||
|
} IrsDeviceFormat;
|
||||||
|
|
||||||
|
/// AruidFormat
|
||||||
|
typedef struct {
|
||||||
|
u64 ir_sensor_aruid; ///< IrSensorAruid
|
||||||
|
u32 ir_sensor_aruid_status; ///< IrSensorAruidStatus
|
||||||
|
u32 pad; ///< Padding
|
||||||
|
} IrsAruidFormat;
|
||||||
|
|
||||||
|
/// StatusManager
|
||||||
|
typedef struct {
|
||||||
|
IrsDeviceFormat device_format[IRS_MAX_CAMERAS];
|
||||||
|
IrsAruidFormat aruid_format[0x5];
|
||||||
|
} IrsStatusManager;
|
||||||
|
|
||||||
/// Initialize irs.
|
/// Initialize irs.
|
||||||
Result irsInitialize(void);
|
Result irsInitialize(void);
|
||||||
@ -58,36 +387,188 @@ void irsExit(void);
|
|||||||
/// Gets the Service object for the actual irs service session.
|
/// Gets the Service object for the actual irs service session.
|
||||||
Service* irsGetServiceSession(void);
|
Service* irsGetServiceSession(void);
|
||||||
|
|
||||||
/// Gets the address of the SharedMemory.
|
/// Gets the address of the SharedMemory (\ref IrsStatusManager).
|
||||||
void* irsGetSharedmemAddr(void);
|
void* irsGetSharedmemAddr(void);
|
||||||
|
|
||||||
/// (De)activate the IR sensor, this is automatically used by \ref irsExit. Must be called after irsInitialize() to activate the IR sensor.
|
/// Gets the \ref IrsIrCameraHandle for the specified controller.
|
||||||
Result irsActivateIrsensor(bool activate);
|
Result irsGetIrCameraHandle(IrsIrCameraHandle *handle, HidControllerID id);
|
||||||
|
|
||||||
/// Gets the IrCameraHandle for the specified controller.
|
/// GetIrCameraStatus
|
||||||
Result irsGetIrCameraHandle(u32 *IrCameraHandle, HidControllerID id);
|
Result irsGetIrCameraStatus(IrsIrCameraHandle handle, IrsIrCameraStatus *out);
|
||||||
|
|
||||||
|
/// CheckFirmwareUpdateNecessity
|
||||||
|
/// When successful where the output flag is set, the user should use \ref hidLaShowControllerFirmwareUpdate.
|
||||||
|
/// Only available on [4.0.0+].
|
||||||
|
Result irsCheckFirmwareUpdateNecessity(IrsIrCameraHandle handle, bool *out);
|
||||||
|
|
||||||
|
/// GetImageProcessorStatus
|
||||||
|
/// Only available on [4.0.0+].
|
||||||
|
Result irsGetImageProcessorStatus(IrsIrCameraHandle handle, IrsImageProcessorStatus *out);
|
||||||
|
|
||||||
|
/// Stop the current Processor.
|
||||||
|
/// \ref irsExit calls this with all IrCameraHandles which were not already used with \ref irsStopImageProcessor.
|
||||||
|
Result irsStopImageProcessor(IrsIrCameraHandle handle);
|
||||||
|
|
||||||
|
/// Stop the current Processor, async.
|
||||||
|
/// Only available on [4.0.0+].
|
||||||
|
Result irsStopImageProcessorAsync(IrsIrCameraHandle handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start ImageTransferProcessor.
|
* @brief Run the MomentProcessor.
|
||||||
* @param[in] IrCameraHandle Camera handle.
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunMomentProcessor(IrsIrCameraHandle handle, const IrsMomentProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the states for MomentProcessor or IrLedProcessor.
|
||||||
|
* @note The official GetIrLedProcessorState is essentially the same as this, except it uses hard-coded count=1 with output-array on stack, without returning that data. Hence we don't implement a seperate func for that.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[out] states Output array of \ref IrsMomentProcessorState.
|
||||||
|
* @param[in] count Size of the states array in entries. Must be 1-5.
|
||||||
|
* @param[out] total_out Total output entries.
|
||||||
|
*/
|
||||||
|
Result irsGetMomentProcessorStates(IrsIrCameraHandle handle, IrsMomentProcessorState *states, s32 count, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates an \ref IrsMomentStatistic from the specified region in the input \ref IrsMomentProcessorState.
|
||||||
|
* @param[in] state \ref IrsMomentProcessorState
|
||||||
|
* @param[in] rect \ref IrsRect, containing the image width and height.
|
||||||
|
* @param[in] region_x Region x, must be 0-5 (clamped to this range otherwise). region_x = image_x/6.
|
||||||
|
* @param[in] region_y Region y, must be 0-7 (clamped to this range otherwise). region_y = image_y/8.
|
||||||
|
* @param[in] region_width Region width. region_x+region_width must be <=6 (clamped to this range otherwise).
|
||||||
|
* @param[in] region_height Region height. region_y+region_height must be <=8 (clamped to this range otherwise).
|
||||||
|
*/
|
||||||
|
IrsMomentStatistic irsCalculateMomentRegionStatistic(const IrsMomentProcessorState *state, IrsRect rect, s32 region_x, s32 region_y, s32 region_width, s32 region_height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the ClusteringProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunClusteringProcessor(IrsIrCameraHandle handle, const IrsClusteringProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the states for ClusteringProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[out] states Output array of \ref IrsClusteringProcessorState.
|
||||||
|
* @param[in] count Size of the states array in entries. Must be 1-5.
|
||||||
|
* @param[out] total_out Total output entries.
|
||||||
|
*/
|
||||||
|
Result irsGetClusteringProcessorStates(IrsIrCameraHandle handle, IrsClusteringProcessorState *states, s32 count, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the ImageTransferProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
* @param[in] config Input config.
|
* @param[in] config Input config.
|
||||||
* @param[in] size Work-buffer size, must be 0x1000-byte aligned.
|
* @param[in] size Work-buffer size, must be 0x1000-byte aligned.
|
||||||
* @note Do not use if already started.
|
|
||||||
*/
|
*/
|
||||||
Result irsRunImageTransferProcessor(u32 IrCameraHandle, IrsImageTransferProcessorConfig *config, size_t size);
|
Result irsRunImageTransferProcessor(IrsIrCameraHandle handle, const IrsImageTransferProcessorConfig *config, size_t size);
|
||||||
|
|
||||||
Result irsGetImageTransferProcessorState(u32 IrCameraHandle, void* buffer, size_t size, IrsImageTransferProcessorState *state);
|
|
||||||
|
|
||||||
/// Stop ImageTransferProcessor. Do not use if already stopped.
|
|
||||||
/// \ref irsExit calls this with all IrCameraHandles which were not already used with \ref irsStopImageProcessor.
|
|
||||||
Result irsStopImageProcessor(u32 IrCameraHandle);
|
|
||||||
|
|
||||||
/// "Suspend" ImageTransferProcessor.
|
|
||||||
/// TODO: What does this really do?
|
|
||||||
Result irsSuspendImageProcessor(u32 IrCameraHandle);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default configuration for Image Transfer mode.
|
* @brief Run the ImageTransferExProcessor.
|
||||||
* Defaults are exposure 300us, IR LEDs all ON, 8x digital gain, normal image and resolution 240 x 320.
|
* @note Only available on [4.0.0+].
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
* @param[in] size Work-buffer size, must be 0x1000-byte aligned.
|
||||||
|
*/
|
||||||
|
Result irsRunImageTransferExProcessor(IrsIrCameraHandle handle, const IrsImageTransferProcessorExConfig *config, size_t size);
|
||||||
|
|
||||||
|
/// GetImageTransferProcessorState
|
||||||
|
Result irsGetImageTransferProcessorState(IrsIrCameraHandle handle, void* buffer, size_t size, IrsImageTransferProcessorState *state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the PointingProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
*/
|
||||||
|
Result irsRunPointingProcessor(IrsIrCameraHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the states for PointingProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[out] states Output array of \ref IrsPointingProcessorMarkerState.
|
||||||
|
* @param[in] count Size of the states array in entries. Must be 1-6.
|
||||||
|
* @param[out] total_out Total output entries.
|
||||||
|
*/
|
||||||
|
Result irsGetPointingProcessorMarkerStates(IrsIrCameraHandle handle, IrsPointingProcessorMarkerState *states, s32 count, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the states for \ref IrsPointingProcessorState.
|
||||||
|
* @note This uses \ref irsGetPointingProcessorMarkerStates, then converts the output to \ref IrsPointingProcessorState.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[out] states Output array of \ref IrsPointingProcessorState.
|
||||||
|
* @param[in] count Size of the states array in entries. Must be 1-6.
|
||||||
|
* @param[out] total_out Total output entries.
|
||||||
|
*/
|
||||||
|
Result irsGetPointingProcessorStates(IrsIrCameraHandle handle, IrsPointingProcessorState *states, s32 count, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the TeraPluginProcessor.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunTeraPluginProcessor(IrsIrCameraHandle handle, const IrsTeraPluginProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the states for TeraPluginProcessor, filtered using the input params.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[out] states Output array of \ref IrsTeraPluginProcessorState.
|
||||||
|
* @param[in] count Size of the states array in entries. Must be 1-5.
|
||||||
|
* @param[in] sampling_number Minimum value for IrsTeraPluginProcessorState::sampling_number.
|
||||||
|
* @param[in] prefix_data Only used when prefix_bitcount is not 0. The first prefix_bitcount bits from prefix_data must match the first prefix_bitcount bits in IrsTeraPluginProcessorState::plugin_data.
|
||||||
|
* @param[in] prefix_bitcount Total bits for prefix_data.
|
||||||
|
* @param[out] total_out Total output entries.
|
||||||
|
*/
|
||||||
|
Result irsGetTeraPluginProcessorStates(IrsIrCameraHandle handle, IrsTeraPluginProcessorState *states, s32 count, s64 sampling_number, u32 prefix_data, u32 prefix_bitcount, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the IrLedProcessor.
|
||||||
|
* @note Only available on [4.0.0+].
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunIrLedProcessor(IrsIrCameraHandle handle, const IrsIrLedProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run the AdaptiveClusteringProcessor.
|
||||||
|
* @note Only available on [5.0.0+].
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunAdaptiveClusteringProcessor(IrsIrCameraHandle handle, const IrsAdaptiveClusteringProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run HandAnalysis.
|
||||||
|
* @param[in] handle \ref IrsIrCameraHandle
|
||||||
|
* @param[in] config Input config.
|
||||||
|
*/
|
||||||
|
Result irsRunHandAnalysis(IrsIrCameraHandle handle, const IrsHandAnalysisConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default configuration for MomentProcessor.
|
||||||
|
*/
|
||||||
|
void irsGetMomentProcessorDefaultConfig(IrsMomentProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default configuration for ClusteringProcessor.
|
||||||
|
*/
|
||||||
|
void irsGetClusteringProcessorDefaultConfig(IrsClusteringProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default configuration for ImageTransferProcessor.
|
||||||
|
* Defaults are exposure 300us, 8x digital gain, the rest is all-zero. Format is ::IrsImageTransferProcessorFormat_320x240.
|
||||||
*/
|
*/
|
||||||
void irsGetDefaultImageTransferProcessorConfig(IrsImageTransferProcessorConfig *config);
|
void irsGetDefaultImageTransferProcessorConfig(IrsImageTransferProcessorConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default configuration for ImageTransferProcessorEx.
|
||||||
|
* Defaults are exposure 300us, 8x digital gain, the rest is all-zero. OrigFormat/TrimmingFormat are ::IrsImageTransferProcessorFormat_320x240.
|
||||||
|
*/
|
||||||
|
void irsGetDefaultImageTransferProcessorExConfig(IrsImageTransferProcessorExConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default configuration for IrLedProcessor.
|
||||||
|
*/
|
||||||
|
NX_CONSTEXPR void irsGetIrLedProcessorDefaultConfig(IrsIrLedProcessorConfig *config) {
|
||||||
|
config->light_target = 0;
|
||||||
|
}
|
||||||
|
@ -66,3 +66,4 @@ Result ldrPmCreateProcess(u64 pin_id, u32 flags, Handle reslimit_h, Handle *out_
|
|||||||
Result ldrPmGetProgramInfo(const NcmProgramLocation *loc, LoaderProgramInfo *out_program_info);
|
Result ldrPmGetProgramInfo(const NcmProgramLocation *loc, LoaderProgramInfo *out_program_info);
|
||||||
Result ldrPmPinProgram(const NcmProgramLocation *loc, u64 *out_pin_id);
|
Result ldrPmPinProgram(const NcmProgramLocation *loc, u64 *out_pin_id);
|
||||||
Result ldrPmUnpinProgram(u64 pin_id);
|
Result ldrPmUnpinProgram(u64 pin_id);
|
||||||
|
Result ldrPmSetEnabledProgramVerification(bool enabled); ///< [10.0.0+]
|
||||||
|
@ -42,6 +42,9 @@ Result lrLrResolveApplicationLegalInformationPath(LrLocationResolver* lr, u64 ti
|
|||||||
Result lrLrRedirectApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path);
|
Result lrLrRedirectApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path);
|
||||||
Result lrLrRefresh(LrLocationResolver* lr);
|
Result lrLrRefresh(LrLocationResolver* lr);
|
||||||
|
|
||||||
|
/// Only available on [5.0.0+].
|
||||||
|
Result lrLrEraseProgramRedirection(LrLocationResolver* lr, u64 tid);
|
||||||
|
|
||||||
// IRegisteredLocationResolver
|
// IRegisteredLocationResolver
|
||||||
Result lrRegLrResolveProgramPath(LrRegisteredLocationResolver* reg, u64 tid, char *out);
|
Result lrRegLrResolveProgramPath(LrRegisteredLocationResolver* reg, u64 tid, char *out);
|
||||||
// TODO: Other IRegisteredLocationResolver commands
|
// TODO: Other IRegisteredLocationResolver commands
|
||||||
|
176
nx/include/switch/services/mii.h
Normal file
176
nx/include/switch/services/mii.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/**
|
||||||
|
* @file mii.h
|
||||||
|
* @brief Mii services (mii:*) IPC wrapper.
|
||||||
|
* @author XorTroll
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../sf/service.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MiiServiceType_System = 0, ///< Initializes mii:e.
|
||||||
|
MiiServiceType_User = 1, ///< Initializes mii:u.
|
||||||
|
} MiiServiceType;
|
||||||
|
|
||||||
|
/// Mii age.
|
||||||
|
typedef enum {
|
||||||
|
MiiAge_Young = 0, ///< Young
|
||||||
|
MiiAge_Normal = 1, ///< Normal
|
||||||
|
MiiAge_Old = 2, ///< Old
|
||||||
|
MiiAge_All = 3, ///< All of them
|
||||||
|
} MiiAge;
|
||||||
|
|
||||||
|
/// Mii gender.
|
||||||
|
typedef enum {
|
||||||
|
MiiGender_Male = 0, ///< Male
|
||||||
|
MiiGender_Female = 1, ///< Female
|
||||||
|
MiiGender_All = 2, ///< Both of them
|
||||||
|
} MiiGender;
|
||||||
|
|
||||||
|
/// Mii face color.
|
||||||
|
typedef enum {
|
||||||
|
MiiFaceColor_Black = 0, ///< Black
|
||||||
|
MiiFaceColor_White = 1, ///< White
|
||||||
|
MiiFaceColor_Asian = 2, ///< Asian
|
||||||
|
MiiFaceColor_All = 3, ///< All of them
|
||||||
|
} MiiFaceColor;
|
||||||
|
|
||||||
|
// Mii source flag.
|
||||||
|
typedef enum {
|
||||||
|
MiiSourceFlag_Database = BIT(0), ///< Miis created by the user
|
||||||
|
MiiSourceFlag_Default = BIT(1), ///< Default console miis
|
||||||
|
MiiSourceFlag_All = MiiSourceFlag_Database | MiiSourceFlag_Default, ///< All of them
|
||||||
|
} MiiSourceFlag;
|
||||||
|
|
||||||
|
// Mii special key code
|
||||||
|
typedef enum {
|
||||||
|
MiiSpecialKeyCode_Normal = 0, ///< Normal miis
|
||||||
|
MiiSpecialKeyCode_Special = 0xA523B78F, ///< Special miis
|
||||||
|
} MiiSpecialKeyCode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Service s;
|
||||||
|
} MiiDatabase;
|
||||||
|
|
||||||
|
// Mii create ID.
|
||||||
|
typedef struct {
|
||||||
|
Uuid uuid;
|
||||||
|
} MiiCreateId;
|
||||||
|
|
||||||
|
// Mii data structure.
|
||||||
|
typedef struct {
|
||||||
|
MiiCreateId create_id;
|
||||||
|
u16 mii_name[10+1]; ///< utf-16be, null-terminated
|
||||||
|
u8 unk_x26;
|
||||||
|
u8 mii_color;
|
||||||
|
u8 mii_sex;
|
||||||
|
u8 mii_height;
|
||||||
|
u8 mii_width;
|
||||||
|
u8 unk_x2b[2];
|
||||||
|
u8 mii_face_shape;
|
||||||
|
u8 mii_face_color;
|
||||||
|
u8 mii_wrinkles_style;
|
||||||
|
u8 mii_makeup_style;
|
||||||
|
u8 mii_hair_style;
|
||||||
|
u8 mii_hair_color;
|
||||||
|
u8 mii_has_hair_flipped;
|
||||||
|
u8 mii_eye_style;
|
||||||
|
u8 mii_eye_color;
|
||||||
|
u8 mii_eye_size;
|
||||||
|
u8 mii_eye_thickness;
|
||||||
|
u8 mii_eye_angle;
|
||||||
|
u8 mii_eye_pos_x;
|
||||||
|
u8 mii_eye_pos_y;
|
||||||
|
u8 mii_eyebrow_style;
|
||||||
|
u8 mii_eyebrow_color;
|
||||||
|
u8 mii_eyebrow_size;
|
||||||
|
u8 mii_eyebrow_thickness;
|
||||||
|
u8 mii_eyebrow_angle;
|
||||||
|
u8 mii_eyebrow_pos_x;
|
||||||
|
u8 mii_eyebrow_pos_y;
|
||||||
|
u8 mii_nose_style;
|
||||||
|
u8 mii_nose_size;
|
||||||
|
u8 mii_nose_pos;
|
||||||
|
u8 mii_mouth_style;
|
||||||
|
u8 mii_mouth_color;
|
||||||
|
u8 mii_mouth_size;
|
||||||
|
u8 mii_mouth_thickness;
|
||||||
|
u8 mii_mouth_pos;
|
||||||
|
u8 mii_facial_hair_color;
|
||||||
|
u8 mii_beard_style;
|
||||||
|
u8 mii_mustache_style;
|
||||||
|
u8 mii_mustache_size;
|
||||||
|
u8 mii_mustache_pos;
|
||||||
|
u8 mii_glasses_style;
|
||||||
|
u8 mii_glasses_color;
|
||||||
|
u8 mii_glasses_size;
|
||||||
|
u8 mii_glasses_pos;
|
||||||
|
u8 mii_has_mole;
|
||||||
|
u8 mii_mole_size;
|
||||||
|
u8 mii_mole_pos_x;
|
||||||
|
u8 mii_mole_pos_y;
|
||||||
|
u8 unk_x57;
|
||||||
|
} MiiCharInfo;
|
||||||
|
|
||||||
|
/// Initialize mii.
|
||||||
|
Result miiInitialize(MiiServiceType service_type);
|
||||||
|
|
||||||
|
/// Exit mii.
|
||||||
|
void miiExit(void);
|
||||||
|
|
||||||
|
/// Gets the Service object for the actual mii service session.
|
||||||
|
Service* miiGetServiceSession(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens a mii database.
|
||||||
|
* @param[in] key_code Mii key code filter.
|
||||||
|
* @param[out] out Database.
|
||||||
|
*/
|
||||||
|
Result miiOpenDatabase(MiiDatabase *out, MiiSpecialKeyCode key_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether the mii database is updated.
|
||||||
|
* @param[in] db Database.
|
||||||
|
* @param[in] flag Source flag.
|
||||||
|
* @param[out] out_updated Whether the mii database is updated.
|
||||||
|
*/
|
||||||
|
Result miiDatabaseIsUpdated(MiiDatabase *db, bool *out_updated, MiiSourceFlag flag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether the mii database is full.
|
||||||
|
* @param[in] db Database.
|
||||||
|
* @param[out] out_full Whether the mii database is full.
|
||||||
|
*/
|
||||||
|
Result miiDatabaseIsFull(MiiDatabase *db, bool *out_full);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns number of miis in the database with the specified source flag.
|
||||||
|
* @param[in] db Database.
|
||||||
|
* @param[in] flag Source flag.
|
||||||
|
* @param[out] out_count Out mii count.
|
||||||
|
*/
|
||||||
|
Result miiDatabaseGetCount(MiiDatabase *db, s32 *out_count, MiiSourceFlag flag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads mii charinfo data from the specified source flag.
|
||||||
|
* @param[in] db Database.
|
||||||
|
* @param[in] flag Source flag.
|
||||||
|
* @param[out] out_infos Output mii charinfo array.
|
||||||
|
* @param[in] count Number of mii chainfos to read.
|
||||||
|
* @param[out] total_out Number of mii charinfos which were actually read.
|
||||||
|
*/
|
||||||
|
Result miiDatabaseGet1(MiiDatabase *db, MiiSourceFlag flag, MiiCharInfo *out_infos, s32 count, s32 *total_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates a random mii charinfo (doesn't register it in the console database).
|
||||||
|
* @param[in] db Database.
|
||||||
|
* @param[in] age Mii's age.
|
||||||
|
* @param[in] gender Mii's gender.
|
||||||
|
* @param[in] face_color Mii's face color.
|
||||||
|
* @param[out] out_info Out mii charinfo data.
|
||||||
|
*/
|
||||||
|
Result miiDatabaseBuildRandom(MiiDatabase *db, MiiAge age, MiiGender gender, MiiFaceColor face_color, MiiCharInfo *out_info);
|
||||||
|
|
||||||
|
/// Closes a mii database.
|
||||||
|
void miiDatabaseClose(MiiDatabase *db);
|
71
nx/include/switch/services/miiimg.h
Normal file
71
nx/include/switch/services/miiimg.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* @file miiimg.h
|
||||||
|
* @brief Mii image (miiimg) service IPC wrapper.
|
||||||
|
* @author XorTroll
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../sf/service.h"
|
||||||
|
#include "../services/mii.h"
|
||||||
|
|
||||||
|
/// Image ID.
|
||||||
|
typedef struct {
|
||||||
|
Uuid uuid;
|
||||||
|
} MiiimgImageId;
|
||||||
|
|
||||||
|
/// Image attribute.
|
||||||
|
typedef struct {
|
||||||
|
MiiimgImageId image_id; ///< Image ID.
|
||||||
|
MiiCreateId create_id; ///< Mii's create ID.
|
||||||
|
u32 unk;
|
||||||
|
u16 mii_name[10+1]; ///< utf-16be, null-terminated
|
||||||
|
} PACKED MiiimgImageAttribute;
|
||||||
|
|
||||||
|
/// Initialize miiimg.
|
||||||
|
Result miiimgInitialize(void);
|
||||||
|
|
||||||
|
/// Exit miiimg.
|
||||||
|
void miiimgExit(void);
|
||||||
|
|
||||||
|
/// Gets the Service object for the actual miiimg service session.
|
||||||
|
Service* miiimgGetServiceSession(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reloads the image database.
|
||||||
|
*/
|
||||||
|
Result miiimgReload(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the number of mii images in the database.
|
||||||
|
* @param[out] out_count Mii image count.
|
||||||
|
*/
|
||||||
|
Result miiimgGetCount(s32 *out_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets whether the image database is empty.
|
||||||
|
* @param[out] out_empty Whether the database is empty.
|
||||||
|
*/
|
||||||
|
Result miiimgIsEmpty(bool *out_empty);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets whether the image database is full.
|
||||||
|
* @param[out] out_empty Whether the database is full.
|
||||||
|
*/
|
||||||
|
Result miiimgIsFull(bool *out_full);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the image attribute for the specified image index.
|
||||||
|
* @param[in] index Image index.
|
||||||
|
* @param[out] out_attr Out image attribute.
|
||||||
|
*/
|
||||||
|
Result miiimgGetAttribute(s32 index, MiiimgImageAttribute *out_attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads the image data (raw RGBA8) for the specified image ID.
|
||||||
|
* @note Server doesn't seem to check the image buffer size, but 0x40000 is the optimal size.
|
||||||
|
* @param[in] id Input image ID.
|
||||||
|
* @param[out] out_image Out iamge buffer.
|
||||||
|
* @param[in] out_image_size Out image buffer size.
|
||||||
|
*/
|
||||||
|
Result miiimgLoadImage(MiiimgImageId id, void* out_image, size_t out_image_size);
|
@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "../sf/service.h"
|
#include "../sf/service.h"
|
||||||
|
#include "../services/mii.h"
|
||||||
|
|
||||||
/// NfpServiceType
|
/// NfpServiceType
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -72,61 +73,7 @@ typedef struct {
|
|||||||
} PACKED NfpModelInfo;
|
} PACKED NfpModelInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 unk_x0[0x10]; // Hash?
|
MiiCharInfo mii;
|
||||||
u16 mii_name[10+1]; ///< utf-16be, null-terminated
|
|
||||||
u8 unk_x26;
|
|
||||||
u8 mii_color;
|
|
||||||
u8 mii_sex;
|
|
||||||
u8 mii_height;
|
|
||||||
u8 mii_width;
|
|
||||||
u8 unk_x2b[2];
|
|
||||||
u8 mii_face_shape;
|
|
||||||
u8 mii_face_color;
|
|
||||||
u8 mii_wrinkles_style;
|
|
||||||
u8 mii_makeup_style;
|
|
||||||
u8 mii_hair_style;
|
|
||||||
u8 mii_hair_color;
|
|
||||||
u8 mii_has_hair_flipped;
|
|
||||||
u8 mii_eye_style;
|
|
||||||
u8 mii_eye_color;
|
|
||||||
u8 mii_eye_size;
|
|
||||||
u8 mii_eye_thickness;
|
|
||||||
u8 mii_eye_angle;
|
|
||||||
u8 mii_eye_pos_x;
|
|
||||||
u8 mii_eye_pos_y;
|
|
||||||
u8 mii_eyebrow_style;
|
|
||||||
u8 mii_eyebrow_color;
|
|
||||||
u8 mii_eyebrow_size;
|
|
||||||
u8 mii_eyebrow_thickness;
|
|
||||||
u8 mii_eyebrow_angle;
|
|
||||||
u8 mii_eyebrow_pos_x;
|
|
||||||
u8 mii_eyebrow_pos_y;
|
|
||||||
u8 mii_nose_style;
|
|
||||||
u8 mii_nose_size;
|
|
||||||
u8 mii_nose_pos;
|
|
||||||
u8 mii_mouth_style;
|
|
||||||
u8 mii_mouth_color;
|
|
||||||
u8 mii_mouth_size;
|
|
||||||
u8 mii_mouth_thickness;
|
|
||||||
u8 mii_mouth_pos;
|
|
||||||
u8 mii_facial_hair_color;
|
|
||||||
u8 mii_beard_style;
|
|
||||||
u8 mii_mustache_style;
|
|
||||||
u8 mii_mustache_size;
|
|
||||||
u8 mii_mustache_pos;
|
|
||||||
u8 mii_glasses_style;
|
|
||||||
u8 mii_glasses_color;
|
|
||||||
u8 mii_glasses_size;
|
|
||||||
u8 mii_glasses_pos;
|
|
||||||
u8 mii_has_mole;
|
|
||||||
u8 mii_mole_size;
|
|
||||||
u8 mii_mole_pos_x;
|
|
||||||
u8 mii_mole_pos_y;
|
|
||||||
u8 unk_x57;
|
|
||||||
} PACKED NfpMiiCharInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
NfpMiiCharInfo mii;
|
|
||||||
u16 first_write_year;
|
u16 first_write_year;
|
||||||
u8 first_write_month;
|
u8 first_write_month;
|
||||||
u8 first_write_day;
|
u8 first_write_day;
|
||||||
@ -175,7 +122,7 @@ Result nfpMount(const NfcDeviceHandle *handle, NfpDeviceType device_type, NfpMou
|
|||||||
Result nfpUnmount(const NfcDeviceHandle *handle);
|
Result nfpUnmount(const NfcDeviceHandle *handle);
|
||||||
|
|
||||||
/// Not available with ::NfpServiceType_System.
|
/// Not available with ::NfpServiceType_System.
|
||||||
Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id, u32 *npad_id);
|
Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id);
|
||||||
|
|
||||||
/// Not available with ::NfpServiceType_System.
|
/// Not available with ::NfpServiceType_System.
|
||||||
Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size);
|
Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size);
|
||||||
|
@ -33,6 +33,96 @@ typedef struct {
|
|||||||
u32 id; ///< ClientId
|
u32 id; ///< ClientId
|
||||||
} NifmClientId;
|
} NifmClientId;
|
||||||
|
|
||||||
|
/// IpV4Address
|
||||||
|
typedef struct {
|
||||||
|
u8 addr[4]; ///< IPv4 address, aka struct in_addr.
|
||||||
|
} NifmIpV4Address;
|
||||||
|
|
||||||
|
/// IpAddressSetting
|
||||||
|
typedef struct {
|
||||||
|
u8 is_automatic; ///< Whether this setting is automatic. Ignored by \ref nifmGetCurrentIpConfigInfo.
|
||||||
|
|
||||||
|
NifmIpV4Address current_addr; ///< Current address.
|
||||||
|
NifmIpV4Address subnet_mask; ///< Subnet Mask.
|
||||||
|
NifmIpV4Address gateway; ///< Gateway.
|
||||||
|
} NifmIpAddressSetting;
|
||||||
|
|
||||||
|
/// DnsSetting
|
||||||
|
typedef struct {
|
||||||
|
u8 is_automatic; ///< Whether this setting is automatic. Ignored by \ref nifmGetCurrentIpConfigInfo.
|
||||||
|
|
||||||
|
NifmIpV4Address primary_dns_server; ///< Primary DNS server.
|
||||||
|
NifmIpV4Address secondary_dns_server; ///< Secondary DNS server.
|
||||||
|
} NifmDnsSetting;
|
||||||
|
|
||||||
|
/// ProxySetting
|
||||||
|
typedef struct {
|
||||||
|
u8 enabled; ///< Enables using the proxy when set.
|
||||||
|
u8 pad; ///< Padding
|
||||||
|
u16 port; ///< Port
|
||||||
|
char server[0x64]; ///< Server string, NUL-terminated.
|
||||||
|
u8 auto_auth_enabled; ///< Enables auto-authentication when set, which uses the following two strings.
|
||||||
|
char user[0x20]; ///< User string, NUL-terminated.
|
||||||
|
char password[0x20]; ///< Password string, NUL-terminated.
|
||||||
|
u8 pad2; ///< Padding
|
||||||
|
} NifmProxySetting;
|
||||||
|
|
||||||
|
/// IpSettingData
|
||||||
|
typedef struct {
|
||||||
|
NifmIpAddressSetting ip_address_setting; ///< \ref NifmIpAddressSetting
|
||||||
|
NifmDnsSetting dns_setting; ///< \ref NifmDnsSetting
|
||||||
|
NifmProxySetting proxy_setting; ///< \ref NifmProxySetting
|
||||||
|
u16 mtu; ///< MTU
|
||||||
|
} NifmIpSettingData;
|
||||||
|
|
||||||
|
/// WirelessSettingData
|
||||||
|
typedef struct {
|
||||||
|
u8 ssid_len; ///< NifmSfWirelessSettingData::ssid_len
|
||||||
|
char ssid[0x21]; ///< NifmSfWirelessSettingData::ssid
|
||||||
|
u8 unk_x22; ///< NifmSfWirelessSettingData::unk_x21
|
||||||
|
u8 pad; ///< Padding
|
||||||
|
u32 unk_x24; ///< NifmSfWirelessSettingData::unk_x22
|
||||||
|
u32 unk_x28; ///< NifmSfWirelessSettingData::unk_x23
|
||||||
|
u8 passphrase[0x41]; ///< NifmSfWirelessSettingData::passphrase
|
||||||
|
u8 pad2[0x3]; ///< Padding
|
||||||
|
} NifmWirelessSettingData;
|
||||||
|
|
||||||
|
/// SfWirelessSettingData
|
||||||
|
typedef struct {
|
||||||
|
u8 ssid_len; ///< SSID length.
|
||||||
|
char ssid[0x20]; ///< SSID string.
|
||||||
|
u8 unk_x21; ///< Unknown
|
||||||
|
u8 unk_x22; ///< Unknown
|
||||||
|
u8 unk_x23; ///< Unknown
|
||||||
|
u8 passphrase[0x41]; ///< Passphrase
|
||||||
|
} NifmSfWirelessSettingData;
|
||||||
|
|
||||||
|
/// SfNetworkProfileData. Converted to/from \ref NifmNetworkProfileData.
|
||||||
|
typedef struct {
|
||||||
|
NifmIpSettingData ip_setting_data; ///< \ref NifmIpSettingData
|
||||||
|
Uuid uuid; ///< Uuid
|
||||||
|
char network_name[0x40]; ///< NUL-terminated Network Name string.
|
||||||
|
u8 unk_x112; ///< Unknown
|
||||||
|
u8 unk_x113; ///< Unknown
|
||||||
|
u8 unk_x114; ///< Unknown
|
||||||
|
u8 unk_x115; ///< Unknown
|
||||||
|
NifmSfWirelessSettingData wireless_setting_data; ///< \ref NifmSfWirelessSettingData
|
||||||
|
u8 pad; ///< Padding
|
||||||
|
} NifmSfNetworkProfileData;
|
||||||
|
|
||||||
|
/// NetworkProfileData. Converted from/to \ref NifmSfNetworkProfileData.
|
||||||
|
typedef struct {
|
||||||
|
Uuid uuid; ///< NifmSfNetworkProfileData::uuid
|
||||||
|
char network_name[0x40]; ///< NifmSfNetworkProfileData::network_name
|
||||||
|
u32 unk_x50; ///< NifmSfNetworkProfileData::unk_x112
|
||||||
|
u32 unk_x54; ///< NifmSfNetworkProfileData::unk_x113
|
||||||
|
u8 unk_x58; ///< NifmSfNetworkProfileData::unk_x114
|
||||||
|
u8 unk_x59; ///< NifmSfNetworkProfileData::unk_x115
|
||||||
|
u8 pad[2]; ///< Padding
|
||||||
|
NifmWirelessSettingData wireless_setting_data; ///< \ref NifmWirelessSettingData
|
||||||
|
NifmIpSettingData ip_setting_data; ///< \ref NifmIpSettingData
|
||||||
|
} NifmNetworkProfileData;
|
||||||
|
|
||||||
/// Initialize nifm. This is used automatically by gethostid().
|
/// Initialize nifm. This is used automatically by gethostid().
|
||||||
Result nifmInitialize(NifmServiceType service_type);
|
Result nifmInitialize(NifmServiceType service_type);
|
||||||
|
|
||||||
@ -50,8 +140,43 @@ Service* nifmGetServiceSession_GeneralService(void);
|
|||||||
*/
|
*/
|
||||||
NifmClientId nifmGetClientId(void);
|
NifmClientId nifmGetClientId(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetCurrentNetworkProfile
|
||||||
|
* @param[out] profile \ref NifmNetworkProfileData
|
||||||
|
*/
|
||||||
|
Result nifmGetCurrentNetworkProfile(NifmNetworkProfileData *profile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetNetworkProfile
|
||||||
|
* @param[in] uuid Uuid
|
||||||
|
* @param[out] profile \ref NifmNetworkProfileData
|
||||||
|
*/
|
||||||
|
Result nifmGetNetworkProfile(Uuid uuid, NifmNetworkProfileData *profile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SetNetworkProfile
|
||||||
|
* @note Only available with ::NifmServiceType_Admin.
|
||||||
|
* @param[in] profile \ref NifmNetworkProfileData
|
||||||
|
* @param[out] uuid Uuid
|
||||||
|
*/
|
||||||
|
Result nifmSetNetworkProfile(const NifmNetworkProfileData *profile, Uuid *uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetCurrentIpAddress
|
||||||
|
* @param[out] out IPv4 address (struct in_addr).
|
||||||
|
*/
|
||||||
Result nifmGetCurrentIpAddress(u32* out);
|
Result nifmGetCurrentIpAddress(u32* out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetCurrentIpConfigInfo
|
||||||
|
* @param[out] current_addr Same as \ref nifmGetCurrentIpAddress output.
|
||||||
|
* @param[out] subnet_mask Subnet Mask (struct in_addr).
|
||||||
|
* @param[out] gateway Gateway (struct in_addr).
|
||||||
|
* @param[out] primary_dns_server Primary DNS server IPv4 address (struct in_addr).
|
||||||
|
* @param[out] secondary_dns_server Secondary DNS server IPv4 address (struct in_addr).
|
||||||
|
*/
|
||||||
|
Result nifmGetCurrentIpConfigInfo(u32 *current_addr, u32 *subnet_mask, u32 *gateway, u32 *primary_dns_server, u32 *secondary_dns_server);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note Works only if called from nifm:a or nifm:s.
|
* @note Works only if called from nifm:a or nifm:s.
|
||||||
*/
|
*/
|
||||||
|
26
nx/include/switch/services/nim.h
Normal file
26
nx/include/switch/services/nim.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file nim.h
|
||||||
|
* @brief Network Install Manager (nim) service IPC wrapper.
|
||||||
|
* @author SciresM
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../sf/service.h"
|
||||||
|
|
||||||
|
/// SystemUpdateTaskId
|
||||||
|
typedef struct {
|
||||||
|
alignas(8) Uuid uuid; ///< UUID
|
||||||
|
} NimSystemUpdateTaskId;
|
||||||
|
|
||||||
|
/// Initialize nim.
|
||||||
|
Result nimInitialize(void);
|
||||||
|
|
||||||
|
/// Exit nim.
|
||||||
|
void nimExit(void);
|
||||||
|
|
||||||
|
/// Gets the Service object for the actual nim service session.
|
||||||
|
Service* nimGetServiceSession(void);
|
||||||
|
|
||||||
|
Result nimListSystemUpdateTask(s32 *out_count, NimSystemUpdateTaskId *out_task_ids, size_t max_task_ids);
|
||||||
|
Result nimDestroySystemUpdateTask(const NimSystemUpdateTaskId *task_id);
|
@ -435,6 +435,7 @@ Result nsIsApplicationEntityMovable(u64 application_id, NcmStorageId storage_id,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief MoveApplicationEntity
|
* @brief MoveApplicationEntity
|
||||||
|
* @note Only available on [1.0.0-9.2.0].
|
||||||
* @param[in] application_id ApplicationId.
|
* @param[in] application_id ApplicationId.
|
||||||
* @param[in] storage_id \ref NcmStorageId
|
* @param[in] storage_id \ref NcmStorageId
|
||||||
*/
|
*/
|
||||||
@ -737,7 +738,7 @@ Result nsWithdrawApplicationUpdateRequest(u64 application_id);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief RequestVerifyAddOnContentsRights
|
* @brief RequestVerifyAddOnContentsRights
|
||||||
* @note Only available on [3.0.0+].
|
* @note Only available on [3.0.0-9.2.0].
|
||||||
* @param[out] a \ref NsProgressAsyncResult
|
* @param[out] a \ref NsProgressAsyncResult
|
||||||
* @param[in] application_id ApplicationId.
|
* @param[in] application_id ApplicationId.
|
||||||
*/
|
*/
|
||||||
@ -1318,14 +1319,15 @@ void nsdevExit(void);
|
|||||||
/// Gets the Service object for ns:dev.
|
/// Gets the Service object for ns:dev.
|
||||||
Service* nsdevGetServiceSession(void);
|
Service* nsdevGetServiceSession(void);
|
||||||
|
|
||||||
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags);
|
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags); ///< [1.0.0-9.2.0]
|
||||||
Result nsdevTerminateProcess(u64 pid);
|
Result nsdevTerminateProcess(u64 pid);
|
||||||
Result nsdevTerminateProgram(u64 tid);
|
Result nsdevTerminateProgram(u64 tid); ///< [1.0.0-9.2.0]
|
||||||
Result nsdevGetShellEvent(Event* out_event); ///< Autoclear for nsdevShellEvent is always true.
|
Result nsdevGetShellEvent(Event* out_event); ///< Autoclear for nsdevShellEvent is always true. [1.0.0-9.2.0]
|
||||||
Result nsdevGetShellEventInfo(NsShellEventInfo* out);
|
Result nsdevGetShellEventInfo(NsShellEventInfo* out); ///< [1.0.0-9.2.0]
|
||||||
Result nsdevTerminateApplication(void);
|
Result nsdevTerminateApplication(void);
|
||||||
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len);
|
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len); ///< [1.0.0-9.2.0]
|
||||||
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 application_id, u32 flags);
|
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 application_id, u32 flags); ///< [1.0.0-9.2.0]
|
||||||
|
Result nsdevLaunchApplicationFromHost(u64* out_pid, const char* path, size_t path_len, u32 flags); ///< [10.0.0+]
|
||||||
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 application_id, u32 flags, u8 app_storage_id, u8 patch_storage_id);
|
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 application_id, u32 flags, u8 app_storage_id, u8 patch_storage_id);
|
||||||
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); ///< [6.0.0-8.1.0]
|
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); ///< [6.0.0-8.1.0]
|
||||||
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid); ///< [6.0.0+]
|
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid); ///< [6.0.0+]
|
||||||
|
64
nx/include/switch/services/pgl.h
Normal file
64
nx/include/switch/services/pgl.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* @file pgl.h
|
||||||
|
* @brief PGL service IPC wrapper.
|
||||||
|
* @author SciresM
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../sf/service.h"
|
||||||
|
#include "../services/ncm_types.h"
|
||||||
|
#include "../services/pm.h"
|
||||||
|
|
||||||
|
/// LaunchFlag
|
||||||
|
typedef enum {
|
||||||
|
PglLaunchFlag_None = 0,
|
||||||
|
PglLaunchFlag_EnableDetailedCrashReport = BIT(0),
|
||||||
|
PglLaunchFlag_EnableCrashReportScreenShotForProduction = BIT(1),
|
||||||
|
PglLaunchFlag_EnableCrashReportScreenShotForDevelop = BIT(2),
|
||||||
|
} PglLaunchFlag;
|
||||||
|
|
||||||
|
/// SnapShotDumpType
|
||||||
|
typedef enum {
|
||||||
|
PglSnapShotDumpType_None = 0,
|
||||||
|
PglSnapShotDumpType_Auto = 1,
|
||||||
|
PglSnapShotDumpType_Full = 2,
|
||||||
|
} PglSnapShotDumpType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 id; ///< Program Id
|
||||||
|
u32 version; ///< Version
|
||||||
|
u8 content_type; ///< NcmContentType
|
||||||
|
u8 id_offset; ///< Id Offset
|
||||||
|
u8 reserved_0E[2]; ///< Padding
|
||||||
|
} PglContentMetaInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Service s;
|
||||||
|
} PglEventObserver;
|
||||||
|
|
||||||
|
/// Initialize pgl.
|
||||||
|
Result pglInitialize(void);
|
||||||
|
|
||||||
|
/// Exit pgl.
|
||||||
|
void pglExit(void);
|
||||||
|
|
||||||
|
/// Gets the Service object for the actual pgl service session.
|
||||||
|
Service* pglGetServiceSession(void);
|
||||||
|
|
||||||
|
Result pglLaunchProgram(u64 *out_pid, const NcmProgramLocation *loc, u32 pm_launch_flags, u8 pgl_launch_flags);
|
||||||
|
Result pglTerminateProcess(u64 pid);
|
||||||
|
Result pglLaunchProgramFromHost(u64 *out_pid, const char *content_path, u32 pm_launch_flags);
|
||||||
|
Result pglGetHostContentMetaInfo(PglContentMetaInfo *out, const char *content_path);
|
||||||
|
Result pglGetApplicationProcessId(u64 *out);
|
||||||
|
Result pglBoostSystemMemoryResourceLimit(u64 size);
|
||||||
|
Result pglIsProcessTracked(bool *out, u64 pid);
|
||||||
|
Result pglEnableApplicationCrashReport(bool en);
|
||||||
|
Result pglIsApplicationCrashReportEnabled(bool *out);
|
||||||
|
Result pglEnableApplicationAllThreadDumpOnCrash(bool en);
|
||||||
|
Result pglTriggerApplicationSnapShotDumper(PglSnapShotDumpType dump_type, const char *arg);
|
||||||
|
Result pglGetEventObserver(PglEventObserver *out);
|
||||||
|
|
||||||
|
Result pglEventObserverGetProcessEvent(PglEventObserver *observer, Event *out);
|
||||||
|
Result pglEventObserverGetProcessEventInfo(PglEventObserver *observer, PmProcessEventInfo *out);
|
||||||
|
void pglEventObserverClose(PglEventObserver *observer);
|
@ -8,6 +8,11 @@
|
|||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "../sf/service.h"
|
#include "../sf/service.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PlServiceType_User = 0, ///< Initializes pl:u.
|
||||||
|
PlServiceType_System = 1, ///< Initializes pl:s.
|
||||||
|
} PlServiceType;
|
||||||
|
|
||||||
/// SharedFontType
|
/// SharedFontType
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PlSharedFontType_Standard = 0, ///< Japan, US and Europe
|
PlSharedFontType_Standard = 0, ///< Japan, US and Europe
|
||||||
@ -28,7 +33,7 @@ typedef struct {
|
|||||||
} PlFontData;
|
} PlFontData;
|
||||||
|
|
||||||
/// Initialize pl.
|
/// Initialize pl.
|
||||||
Result plInitialize(void);
|
Result plInitialize(PlServiceType service_type);
|
||||||
|
|
||||||
/// Exit pl.
|
/// Exit pl.
|
||||||
void plExit(void);
|
void plExit(void);
|
||||||
|
@ -124,4 +124,4 @@ Result pmshellClearJitDebugOccured(u64 pid);
|
|||||||
Result pmshellNotifyBootFinished(void);
|
Result pmshellNotifyBootFinished(void);
|
||||||
Result pmshellGetApplicationProcessIdForShell(u64* pid_out);
|
Result pmshellGetApplicationProcessIdForShell(u64* pid_out);
|
||||||
Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size);
|
Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size);
|
||||||
Result pmshellBoostSystemThreadResourceLimit(void);
|
Result pmshellEnableApplicationExtraThread(void);
|
||||||
|
@ -51,9 +51,8 @@ typedef enum {
|
|||||||
SetRegion_USA = 1, ///< The Americas
|
SetRegion_USA = 1, ///< The Americas
|
||||||
SetRegion_EUR = 2, ///< Europe
|
SetRegion_EUR = 2, ///< Europe
|
||||||
SetRegion_AUS = 3, ///< Australia/New Zealand
|
SetRegion_AUS = 3, ///< Australia/New Zealand
|
||||||
SetRegion_CHN = 4, ///< China
|
SetRegion_HTK = 4, ///< Hong Kong/Taiwan/Korea
|
||||||
SetRegion_KOR = 5, ///< Korea
|
SetRegion_CHN = 5, ///< China
|
||||||
SetRegion_TWN = 6, ///< Taiwan
|
|
||||||
} SetRegion;
|
} SetRegion;
|
||||||
|
|
||||||
/// ConnectionFlag
|
/// ConnectionFlag
|
||||||
@ -341,6 +340,11 @@ typedef struct {
|
|||||||
char digest[0x40];
|
char digest[0x40];
|
||||||
} SetSysFirmwareVersionDigest;
|
} SetSysFirmwareVersionDigest;
|
||||||
|
|
||||||
|
/// Structure returned by \ref setsysGetSerialNumber.
|
||||||
|
typedef struct {
|
||||||
|
char number[0x18];
|
||||||
|
} SetSysSerialNumber;
|
||||||
|
|
||||||
/// UserSelectorSettings
|
/// UserSelectorSettings
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 flags; ///< Bitmask with \ref SetSysUserSelectorFlag.
|
u32 flags; ///< Bitmask with \ref SetSysUserSelectorFlag.
|
||||||
@ -821,9 +825,7 @@ typedef struct {
|
|||||||
u32 generation;
|
u32 generation;
|
||||||
} SetCalRsa2048DeviceKey;
|
} SetCalRsa2048DeviceKey;
|
||||||
|
|
||||||
typedef struct {
|
typedef SetSysSerialNumber SetCalSerialNumber;
|
||||||
char number[0x18];
|
|
||||||
} SetCalSerialNumber;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 parameter[0x5A];
|
u8 parameter[0x5A];
|
||||||
@ -1291,9 +1293,9 @@ Result setsysGetBatteryLot(SetBatteryLot *out);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the system's serial number.
|
* @brief Gets the system's serial number.
|
||||||
* @param serial Pointer to output the serial to. (The buffer size needs to be at least 0x19 bytes)
|
* @param[out] out \ref SetSysSerialNumber
|
||||||
*/
|
*/
|
||||||
Result setsysGetSerialNumber(char *serial);
|
Result setsysGetSerialNumber(SetSysSerialNumber *out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GetNfcEnableFlag
|
* @brief GetNfcEnableFlag
|
||||||
|
@ -53,13 +53,18 @@ typedef struct {
|
|||||||
} TimeLocationName;
|
} TimeLocationName;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
s64 time_point; ///< A point in time.
|
s64 time_point; ///< Monotonic count in seconds.
|
||||||
Uuid source_id; ///< An ID representing the clock source.
|
Uuid source_id; ///< An ID representing the clock source.
|
||||||
} TimeSteadyClockTimePoint;
|
} TimeSteadyClockTimePoint;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
s64 time_point;
|
s64 base_time;
|
||||||
TimeSteadyClockTimePoint steady_clock_time_point;
|
Uuid source_id;
|
||||||
|
} TimeStandardSteadyClockTimePointType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
s64 offset;
|
||||||
|
TimeSteadyClockTimePoint timestamp;
|
||||||
} TimeSystemClockContext;
|
} TimeSystemClockContext;
|
||||||
|
|
||||||
/// Initialize time. Used automatically during app startup.
|
/// Initialize time. Used automatically during app startup.
|
||||||
@ -74,9 +79,30 @@ Service* timeGetServiceSession(void);
|
|||||||
/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid.
|
/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid.
|
||||||
Service* timeGetServiceSession_SystemClock(TimeType type);
|
Service* timeGetServiceSession_SystemClock(TimeType type);
|
||||||
|
|
||||||
|
/// Gets the Service object for ISteadyClock.
|
||||||
|
Service* timeGetServiceSession_SteadyClock(void);
|
||||||
|
|
||||||
/// Gets the Service object for ITimeZoneService.
|
/// Gets the Service object for ITimeZoneService.
|
||||||
Service* timeGetServiceSession_TimeZoneService(void);
|
Service* timeGetServiceSession_TimeZoneService(void);
|
||||||
|
|
||||||
|
/// [6.0.0+] Gets the address of the SharedMemory.
|
||||||
|
void* timeGetSharedmemAddr(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the timepoint for the standard steady clock.
|
||||||
|
* @param[out] out Output timepoint (see \ref TimeSteadyClockTimePoint)
|
||||||
|
* @remark The standard steady clock counts time since the RTC was configured (usually this happens during manufacturing).
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
Result timeGetStandardSteadyClockTimePoint(TimeSteadyClockTimePoint *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief [3.0.0+] Gets the internal offset for the standard steady clock.
|
||||||
|
* @param[out] out Output internal offset.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
Result timeGetStandardSteadyClockInternalOffset(s64 *out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the time for the specified clock.
|
* @brief Gets the time for the specified clock.
|
||||||
* @param[in] type Clock to use.
|
* @param[in] type Clock to use.
|
||||||
|
@ -47,6 +47,8 @@ typedef void (*VoidFn)(void); ///< Function without arguments nor return v
|
|||||||
|
|
||||||
typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier.
|
typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier.
|
||||||
|
|
||||||
|
typedef struct { float value[3]; } UtilFloat3; ///< 3 floats.
|
||||||
|
|
||||||
/// Creates a bitmask from a bit number.
|
/// Creates a bitmask from a bit number.
|
||||||
#ifndef BIT
|
#ifndef BIT
|
||||||
#define BIT(n) (1U<<(n))
|
#define BIT(n) (1U<<(n))
|
||||||
|
@ -46,7 +46,7 @@ Result shmemMap(SharedMemory* s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rc = LibnxError_AlreadyMapped;
|
rc = MAKERESULT(Module_Libnx, LibnxError_AlreadyMapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -93,7 +93,7 @@ SVC_BEGIN svcGetThreadCoreMask
|
|||||||
svc 0xE
|
svc 0xE
|
||||||
ldp x3, x4, [sp], #16
|
ldp x3, x4, [sp], #16
|
||||||
str w1, [x3]
|
str w1, [x3]
|
||||||
str w2, [x4]
|
str x2, [x4]
|
||||||
ret
|
ret
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
@ -481,6 +481,15 @@ SVC_BEGIN svcQueryPhysicalAddress
|
|||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcQueryIoMapping
|
SVC_BEGIN svcQueryIoMapping
|
||||||
|
stp x0, x1, [sp, #-16]!
|
||||||
|
svc 0x55
|
||||||
|
ldp x3, x4, [sp], #16
|
||||||
|
str x1, [x3]
|
||||||
|
str x2, [x4]
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcLegacyQueryIoMapping
|
||||||
str x0, [sp, #-16]!
|
str x0, [sp, #-16]!
|
||||||
svc 0x55
|
svc 0x55
|
||||||
ldr x2, [sp], #16
|
ldr x2, [sp], #16
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "kernel/thread.h"
|
#include "kernel/thread.h"
|
||||||
#include "kernel/wait.h"
|
#include "kernel/wait.h"
|
||||||
#include "services/fatal.h"
|
#include "services/fatal.h"
|
||||||
|
#include "runtime/env.h"
|
||||||
#include "../internal.h"
|
#include "../internal.h"
|
||||||
|
|
||||||
#define USER_TLS_BEGIN 0x108
|
#define USER_TLS_BEGIN 0x108
|
||||||
@ -23,6 +24,8 @@ extern u8 __tls_end[];
|
|||||||
static Mutex g_threadMutex;
|
static Mutex g_threadMutex;
|
||||||
static Thread* g_threadList;
|
static Thread* g_threadList;
|
||||||
|
|
||||||
|
static Thread g_mainThread;
|
||||||
|
|
||||||
static u64 g_tlsUsageMask;
|
static u64 g_tlsUsageMask;
|
||||||
static void (* g_tlsDestructors[NUM_TLS_SLOTS])(void*);
|
static void (* g_tlsDestructors[NUM_TLS_SLOTS])(void*);
|
||||||
|
|
||||||
@ -60,6 +63,33 @@ static void _EntryWrap(ThreadEntryArgs* args) {
|
|||||||
threadExit();
|
threadExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __libnx_init_thread(void) {
|
||||||
|
g_mainThread.handle = envGetMainThreadHandle();
|
||||||
|
|
||||||
|
MemoryInfo mem_info = {0};
|
||||||
|
u32 page_info;
|
||||||
|
svcQueryMemory(&mem_info, &page_info, (u64)(&mem_info));
|
||||||
|
|
||||||
|
// Set stack.
|
||||||
|
g_mainThread.owns_stack_mem = false;
|
||||||
|
g_mainThread.stack_mem = NULL;
|
||||||
|
g_mainThread.stack_mirror = (void*)mem_info.addr;
|
||||||
|
g_mainThread.stack_sz = mem_info.size;
|
||||||
|
|
||||||
|
// Set the TLS array.
|
||||||
|
mutexLock(&g_threadMutex);
|
||||||
|
g_mainThread.tls_array = (void**)((u8*)armGetTls() + USER_TLS_BEGIN);
|
||||||
|
g_mainThread.prev_next = &g_threadList;
|
||||||
|
g_mainThread.next = g_threadList;
|
||||||
|
if (g_threadList)
|
||||||
|
g_threadList->prev_next = &g_mainThread.next;
|
||||||
|
g_threadList = &g_mainThread;
|
||||||
|
mutexUnlock(&g_threadMutex);
|
||||||
|
|
||||||
|
// Set thread_ptr.
|
||||||
|
getThreadVars()->thread_ptr = &g_mainThread;
|
||||||
|
}
|
||||||
|
|
||||||
Result threadCreate(
|
Result threadCreate(
|
||||||
Thread* t, ThreadFunc entry, void* arg, void* stack_mem, size_t stack_sz,
|
Thread* t, ThreadFunc entry, void* arg, void* stack_mem, size_t stack_sz,
|
||||||
int prio, int cpuid)
|
int prio, int cpuid)
|
||||||
@ -219,17 +249,21 @@ Result threadClose(Thread* t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result threadPause(Thread* t) {
|
Result threadPause(Thread* t) {
|
||||||
return svcSetThreadActivity(t->handle, 1);
|
return svcSetThreadActivity(t->handle, ThreadActivity_Paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result threadResume(Thread* t) {
|
Result threadResume(Thread* t) {
|
||||||
return svcSetThreadActivity(t->handle, 0);
|
return svcSetThreadActivity(t->handle, ThreadActivity_Runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result threadDumpContext(ThreadContext* ctx, Thread* t) {
|
Result threadDumpContext(ThreadContext* ctx, Thread* t) {
|
||||||
return svcGetThreadContext3(ctx, t->handle);
|
return svcGetThreadContext3(ctx, t->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Thread *threadGetSelf(void) {
|
||||||
|
return getThreadVars()->thread_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
Handle threadGetCurHandle(void) {
|
Handle threadGetCurHandle(void) {
|
||||||
return getThreadVars()->handle;
|
return getThreadVars()->handle;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
#include "runtime/devices/console.h"
|
#include "runtime/devices/console.h"
|
||||||
#include "kernel/svc.h"
|
|
||||||
|
|
||||||
#include "default_font_bin.h"
|
#include "default_font_bin.h"
|
||||||
|
|
||||||
@ -450,62 +449,26 @@ static ssize_t con_write(struct _reent *r,void *fd,const char *ptr, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const devoptab_t dotab_stdout = {
|
static const devoptab_t dotab_stdout = {
|
||||||
"con",
|
.name = "con",
|
||||||
0,
|
.write_r = con_write,
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
con_write,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
const devoptab_t* __nx_get_console_dotab(void) {
|
||||||
static ssize_t debug_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
return &dotab_stdout;
|
||||||
//---------------------------------------------------------------------------------
|
|
||||||
svcOutputDebugString(ptr,len);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const devoptab_t dotab_svc = {
|
|
||||||
"svc",
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
debug_write,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static const devoptab_t dotab_null = {
|
|
||||||
"null",
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
ConsoleRenderer* getDefaultConsoleRenderer(void);
|
ConsoleRenderer* getDefaultConsoleRenderer(void);
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
PrintConsole* consoleInit(PrintConsole* console) {
|
PrintConsole* consoleInit(PrintConsole* console) {
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
|
||||||
static bool firstConsoleInit = true;
|
static bool didFirstConsoleInit = false;
|
||||||
|
|
||||||
if(firstConsoleInit) {
|
if(!didFirstConsoleInit) {
|
||||||
devoptab_list[STD_OUT] = &dotab_stdout;
|
devoptab_list[STD_OUT] = &dotab_stdout;
|
||||||
devoptab_list[STD_ERR] = &dotab_stdout;
|
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
setvbuf(stderr, NULL , _IONBF, 0);
|
didFirstConsoleInit = true;
|
||||||
|
|
||||||
firstConsoleInit = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(console) {
|
if(console) {
|
||||||
@ -551,29 +514,6 @@ void consoleUpdate(PrintConsole* console) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
|
||||||
void consoleDebugInit(debugDevice device) {
|
|
||||||
//---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int buffertype = _IONBF;
|
|
||||||
|
|
||||||
switch(device) {
|
|
||||||
|
|
||||||
case debugDevice_SVC:
|
|
||||||
devoptab_list[STD_ERR] = &dotab_svc;
|
|
||||||
buffertype = _IOLBF;
|
|
||||||
break;
|
|
||||||
case debugDevice_CONSOLE:
|
|
||||||
devoptab_list[STD_ERR] = &dotab_stdout;
|
|
||||||
break;
|
|
||||||
case debugDevice_NULL:
|
|
||||||
devoptab_list[STD_ERR] = &dotab_null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setvbuf(stderr, NULL , buffertype, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
PrintConsole *consoleSelect(PrintConsole* console) {
|
PrintConsole *consoleSelect(PrintConsole* console) {
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
48
nx/source/runtime/devices/console_debug.c
Normal file
48
nx/source/runtime/devices/console_debug.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/iosupport.h>
|
||||||
|
#include "runtime/devices/console.h"
|
||||||
|
#include "kernel/svc.h"
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static ssize_t debug_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
svcOutputDebugString(ptr,len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const devoptab_t dotab_svc = {
|
||||||
|
.name = "svc",
|
||||||
|
.write_r = debug_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const devoptab_t dotab_null = {
|
||||||
|
.name = "null",
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((weak)) const devoptab_t* __nx_get_console_dotab(void) {
|
||||||
|
return &dotab_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
void consoleDebugInit(debugDevice device) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int buffertype = _IONBF;
|
||||||
|
|
||||||
|
switch(device) {
|
||||||
|
|
||||||
|
case debugDevice_SVC:
|
||||||
|
devoptab_list[STD_ERR] = &dotab_svc;
|
||||||
|
buffertype = _IOLBF;
|
||||||
|
break;
|
||||||
|
case debugDevice_CONSOLE:
|
||||||
|
devoptab_list[STD_ERR] = __nx_get_console_dotab();
|
||||||
|
break;
|
||||||
|
case debugDevice_NULL:
|
||||||
|
devoptab_list[STD_ERR] = &dotab_null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setvbuf(stderr, NULL, buffertype, 0);
|
||||||
|
|
||||||
|
}
|
@ -465,6 +465,32 @@ Result fsdevMountSaveData(const char *name, u64 application_id, AccountUid uid)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsdevMountSaveDataReadOnly(const char *name, u64 application_id, AccountUid uid)
|
||||||
|
{
|
||||||
|
FsFileSystem fs;
|
||||||
|
Result rc = fsOpen_SaveDataReadOnly(&fs, application_id, uid);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
int ret = fsdevMountDevice(name, fs);
|
||||||
|
if(ret==-1)
|
||||||
|
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsdevMountBcatSaveData(const char *name, u64 application_id)
|
||||||
|
{
|
||||||
|
FsFileSystem fs;
|
||||||
|
Result rc = fsOpen_BcatSaveData(&fs, application_id);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
int ret = fsdevMountDevice(name, fs);
|
||||||
|
if(ret==-1)
|
||||||
|
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
Result fsdevMountDeviceSaveData(const char *name, u64 application_id)
|
Result fsdevMountDeviceSaveData(const char *name, u64 application_id)
|
||||||
{
|
{
|
||||||
FsFileSystem fs;
|
FsFileSystem fs;
|
||||||
@ -478,6 +504,32 @@ Result fsdevMountDeviceSaveData(const char *name, u64 application_id)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsdevMountTemporaryStorage(const char *name)
|
||||||
|
{
|
||||||
|
FsFileSystem fs;
|
||||||
|
Result rc = fsOpen_TemporaryStorage(&fs);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
int ret = fsdevMountDevice(name, fs);
|
||||||
|
if(ret==-1)
|
||||||
|
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsdevMountCacheStorage(const char *name, u64 application_id, u16 save_data_index)
|
||||||
|
{
|
||||||
|
FsFileSystem fs;
|
||||||
|
Result rc = fsOpen_CacheStorage(&fs, application_id, save_data_index);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
int ret = fsdevMountDevice(name, fs);
|
||||||
|
if(ret==-1)
|
||||||
|
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
Result fsdevMountSystemSaveData(const char *name, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid)
|
Result fsdevMountSystemSaveData(const char *name, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid)
|
||||||
{
|
{
|
||||||
FsFileSystem fs;
|
FsFileSystem fs;
|
||||||
@ -491,6 +543,19 @@ Result fsdevMountSystemSaveData(const char *name, FsSaveDataSpaceId save_data_sp
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsdevMountSystemBcatSaveData(const char *name, u64 system_save_data_id)
|
||||||
|
{
|
||||||
|
FsFileSystem fs;
|
||||||
|
Result rc = fsOpen_SystemBcatSaveData(&fs, system_save_data_id);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
int ret = fsdevMountDevice(name, fs);
|
||||||
|
if(ret==-1)
|
||||||
|
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void __libnx_init_cwd(void)
|
void __libnx_init_cwd(void)
|
||||||
{
|
{
|
||||||
if(envIsNso() || __system_argc==0 || __system_argv[0] == NULL)
|
if(envIsNso() || __system_argc==0 || __system_argv[0] == NULL)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "services/bsd.h"
|
#include "services/bsd.h"
|
||||||
#include "runtime/devices/socket.h"
|
#include "runtime/devices/socket.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
|
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
|
||||||
|
|
||||||
@ -669,39 +671,338 @@ int socketpair(int domain, int type, int protocol, int sv[2]) {
|
|||||||
|
|
||||||
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
|
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
|
||||||
if(msg == NULL) {
|
if(msg == NULL) {
|
||||||
errno = EFAULT;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mmsghdr msgvec = {
|
struct mmsghdr msgvec = {
|
||||||
.msg_hdr = *msg,
|
.msg_hdr = *msg,
|
||||||
.msg_len = 1,
|
.msg_len = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return recvmmsg(sockfd, &msgvec, 1, flags, NULL);
|
ssize_t ret = recvmmsg(sockfd, &msgvec, 1, flags, NULL);
|
||||||
|
if (ret >= 0) {
|
||||||
|
*msg = msgvec.msg_hdr;
|
||||||
|
ret = msgvec.msg_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
|
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
|
||||||
if(msg == NULL) {
|
if(msg == NULL) {
|
||||||
errno = EFAULT;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mmsghdr msgvec = {
|
struct mmsghdr msgvec = {
|
||||||
.msg_hdr = *msg,
|
.msg_hdr = *msg,
|
||||||
.msg_len = 1,
|
.msg_len = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return sendmmsg(sockfd, &msgvec, 1, flags);
|
ssize_t ret = sendmmsg(sockfd, &msgvec, 1, flags);
|
||||||
|
if (ret > 0) ret = msgvec.msg_len;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _serializeMmsg(u8 *outbuf, size_t outbuf_size, struct mmsghdr *msgvec, unsigned int vlen, bool is_send) {
|
||||||
|
void* tmp_ptr = NULL;
|
||||||
|
u8 *dataptr = outbuf;
|
||||||
|
*dataptr++ = 0x8;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<vlen; i++) {
|
||||||
|
socklen_t msg_controllen = msgvec[i].msg_hdr.msg_controllen;
|
||||||
|
|
||||||
|
if (msg_controllen >= sizeof(struct cmsghdr)) {
|
||||||
|
struct cmsghdr *cmsg = msgvec[i].msg_hdr.msg_control;
|
||||||
|
if (cmsg) {
|
||||||
|
if (cmsg->cmsg_level == 0xffff && cmsg->cmsg_type == 1) {
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t msg_namelen = msgvec[i].msg_hdr.msg_namelen;
|
||||||
|
*((socklen_t*)dataptr) = msg_namelen;
|
||||||
|
dataptr+= sizeof(socklen_t);
|
||||||
|
|
||||||
|
if (is_send && (tmp_ptr = msgvec[i].msg_hdr.msg_name)) memcpy(dataptr, tmp_ptr, msg_namelen);
|
||||||
|
dataptr+= msg_namelen;
|
||||||
|
|
||||||
|
int msg_iovlen = msgvec[i].msg_hdr.msg_iovlen;
|
||||||
|
*((int*)dataptr) = msg_iovlen;
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
|
||||||
|
for (int veci=0; veci<msg_iovlen; veci++) {
|
||||||
|
struct iovec *vec = &msgvec[i].msg_hdr.msg_iov[veci];
|
||||||
|
|
||||||
|
u64 iov_len = vec->iov_len;
|
||||||
|
*((u64*)dataptr) = iov_len;
|
||||||
|
dataptr+= sizeof(u64);
|
||||||
|
|
||||||
|
if (is_send) memcpy(dataptr, vec->iov_base, iov_len);
|
||||||
|
dataptr+= iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((socklen_t*)dataptr) = msg_controllen;
|
||||||
|
dataptr+= sizeof(socklen_t);
|
||||||
|
|
||||||
|
if (is_send && (tmp_ptr = msgvec[i].msg_hdr.msg_control)) memcpy(dataptr, tmp_ptr, msg_controllen);
|
||||||
|
dataptr+= msg_controllen;
|
||||||
|
|
||||||
|
*((int*)dataptr) = msgvec[i].msg_hdr.msg_flags;
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
|
||||||
|
*((int*)dataptr) = msgvec[i].msg_len;
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sdknso would verify that dataptr isn't larger than outbuf+outbuf_size (Abort otherwise), but that can't happen anyway since the caller allocates enough space.
|
||||||
|
return (uintptr_t)dataptr-(uintptr_t)outbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _deserializeMmsg(struct mmsghdr *msgvec, unsigned int vlen, u8 *inbuf, size_t inbuf_size, bool is_recv) {
|
||||||
|
bool bounds_flag=0;
|
||||||
|
void* tmp_ptr = NULL;
|
||||||
|
u8 *dataptr = &inbuf[0x1];
|
||||||
|
uintptr_t inbuf_end = (uintptr_t)&inbuf[inbuf_size];
|
||||||
|
|
||||||
|
// sdknso verifies that dataptr isn't larger than outbuf+outbuf_size at the end prior to returning (Abort otherwise). We'll also verify it during the loop, and also verify that sizes from the buffer are not larger than the original msgvec values.
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<vlen; i++) {
|
||||||
|
if ((uintptr_t)dataptr > (uintptr_t)inbuf_end || (uintptr_t)dataptr+sizeof(socklen_t) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t msg_namelen = *((socklen_t*)dataptr);
|
||||||
|
dataptr+= sizeof(socklen_t);
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+msg_namelen > inbuf_end || msg_namelen > msgvec[i].msg_hdr.msg_namelen) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
msgvec[i].msg_hdr.msg_namelen = msg_namelen;
|
||||||
|
|
||||||
|
if (is_recv && (tmp_ptr = msgvec[i].msg_hdr.msg_name)) {
|
||||||
|
memcpy(tmp_ptr, dataptr, msg_namelen);
|
||||||
|
}
|
||||||
|
dataptr+= msg_namelen;
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+sizeof(int) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msg_iovlen = *((int*)dataptr);
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
|
||||||
|
if (msg_iovlen > msgvec[i].msg_hdr.msg_iovlen) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgvec[i].msg_hdr.msg_iovlen = msg_iovlen;
|
||||||
|
|
||||||
|
for (int veci=0; veci<msg_iovlen; veci++) {
|
||||||
|
struct iovec *vec = &msgvec[i].msg_hdr.msg_iov[veci];
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+sizeof(u64) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 iov_len = *((u64*)dataptr);
|
||||||
|
dataptr+= sizeof(u64);
|
||||||
|
if (iov_len > inbuf_size || (uintptr_t)dataptr+iov_len > inbuf_end || iov_len > vec->iov_len) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->iov_len = iov_len;
|
||||||
|
if (is_recv) memcpy(vec->iov_base, dataptr, iov_len);
|
||||||
|
dataptr+= iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds_flag) break;
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+sizeof(socklen_t) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t msg_controllen = *((socklen_t*)dataptr);
|
||||||
|
dataptr+= sizeof(socklen_t);
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+msg_controllen > inbuf_end || msg_controllen > msgvec[i].msg_hdr.msg_controllen) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgvec[i].msg_hdr.msg_controllen = msg_controllen;
|
||||||
|
|
||||||
|
if (is_recv && (tmp_ptr = msgvec[i].msg_hdr.msg_control)) {
|
||||||
|
memcpy(tmp_ptr, dataptr, msg_controllen);
|
||||||
|
}
|
||||||
|
dataptr+= msg_controllen;
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+sizeof(int) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgvec[i].msg_hdr.msg_flags = *((int*)dataptr);
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
|
||||||
|
if ((uintptr_t)dataptr+sizeof(int) > inbuf_end) {
|
||||||
|
bounds_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgvec[i].msg_len = *((int*)dataptr);
|
||||||
|
dataptr+= sizeof(int);
|
||||||
|
|
||||||
|
if (msg_controllen >= sizeof(struct cmsghdr)) {
|
||||||
|
struct cmsghdr *cmsg = msgvec[i].msg_hdr.msg_control;
|
||||||
|
if (cmsg) {
|
||||||
|
if (cmsg->cmsg_level == 0xffff && cmsg->cmsg_type == 1) {
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds_flag || (uintptr_t)dataptr > inbuf_end) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uintptr_t)dataptr-(uintptr_t)inbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _mmsgInitCommon(u8 **buf, size_t *alignsize, struct mmsghdr *msgvec, unsigned int vlen) {
|
||||||
|
size_t msgdatasize_total = 0;
|
||||||
|
size_t bufsize = 1;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<vlen; i++) {
|
||||||
|
bufsize+= sizeof(socklen_t) + msgvec[i].msg_hdr.msg_namelen + sizeof(int);
|
||||||
|
|
||||||
|
int msg_iovlen = msgvec[i].msg_hdr.msg_iovlen;
|
||||||
|
|
||||||
|
for (int veci=0; veci<msg_iovlen; veci++) {
|
||||||
|
size_t iov_len = msgvec[i].msg_hdr.msg_iov[veci].iov_len;
|
||||||
|
bufsize += sizeof(u64) + iov_len;
|
||||||
|
msgdatasize_total += iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufsize+= sizeof(socklen_t) + msgvec[i].msg_hdr.msg_controllen + sizeof(int) + sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgdatasize_total > 0x80000) {
|
||||||
|
errno = EMSGSIZE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*alignsize = (bufsize+0xfff) & ~0xfff;
|
||||||
|
*buf = (u8*)memalign(0x1000, *alignsize);
|
||||||
|
if (*buf == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(*buf, 0, *alignsize);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags) {
|
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags) {
|
||||||
//TODO: do the necessary RE & implement it
|
if (hosversionBefore(7,0,0)) { // This cmd was added with [3.0.0+], but we'll only support the updated [7.0.0+] version of it.
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(msgvec == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vlen < 1 || vlen > 0x20) {
|
||||||
|
errno = EMSGSIZE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockfd = _socketGetFd(sockfd);
|
||||||
|
if(sockfd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ret=0, ret2=0;
|
||||||
|
u8 *buf = NULL;
|
||||||
|
size_t alignsize=0;
|
||||||
|
|
||||||
|
ret = _mmsgInitCommon(&buf, &alignsize, msgvec, vlen);
|
||||||
|
if (ret==-1) return ret;
|
||||||
|
|
||||||
|
ret = _serializeMmsg(buf, alignsize, msgvec, vlen, 1);
|
||||||
|
|
||||||
|
if (ret>=0) ret = _socketParseBsdResult(NULL, bsdSendMMsg(sockfd, buf, alignsize, vlen, flags));
|
||||||
|
|
||||||
|
if (ret>=0 && ret>vlen) { // sdknso doesn't check this, but we will.
|
||||||
|
errno = EFAULT;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret>=0) {
|
||||||
|
ret2 = _deserializeMmsg(msgvec, ret, buf, alignsize, 0);
|
||||||
|
if (ret2==-1) ret = ret2;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {
|
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {
|
||||||
//TODO: do the necessary RE & implement it
|
if (hosversionBefore(7,0,0)) { // This cmd was added with [3.0.0+], but we'll only support the updated [7.0.0+] version of it.
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(msgvec == NULL || (vlen < 1 || vlen > 0x20)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockfd = _socketGetFd(sockfd);
|
||||||
|
if(sockfd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ret=0, ret2=0;
|
||||||
|
u8 *buf = NULL;
|
||||||
|
size_t alignsize=0;
|
||||||
|
|
||||||
|
ret = _mmsgInitCommon(&buf, &alignsize, msgvec, vlen);
|
||||||
|
if (ret==-1) return ret;
|
||||||
|
|
||||||
|
struct timespec tmp_timeout={0};
|
||||||
|
if (timeout) tmp_timeout = *timeout;
|
||||||
|
|
||||||
|
ret = _serializeMmsg(buf, alignsize, msgvec, vlen, 0);
|
||||||
|
|
||||||
|
if (ret>=0) ret = _socketParseBsdResult(NULL, bsdRecvMMsg(sockfd, buf, alignsize, vlen, flags, &tmp_timeout));
|
||||||
|
|
||||||
|
if (ret>=0 && ret>vlen) { // sdknso doesn't check this, but we will.
|
||||||
|
errno = EFAULT;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret>=0) {
|
||||||
|
ret2 = _deserializeMmsg(msgvec, ret, buf, alignsize, 1);
|
||||||
|
if (ret2==-1) ret = ret2;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@ void NORETURN __nx_exit(Result rc, LoaderReturnFn retaddr);
|
|||||||
void virtmemSetup(void);
|
void virtmemSetup(void);
|
||||||
void newlibSetup(void);
|
void newlibSetup(void);
|
||||||
void argvSetup(void);
|
void argvSetup(void);
|
||||||
|
void __libnx_init_thread(void);
|
||||||
void __libnx_init_time(void);
|
void __libnx_init_time(void);
|
||||||
void __libnx_init_cwd(void);
|
void __libnx_init_cwd(void);
|
||||||
|
|
||||||
@ -174,6 +175,7 @@ void __attribute__((weak)) __libnx_init(void* ctx, Handle main_thread, void* sav
|
|||||||
newlibSetup();
|
newlibSetup();
|
||||||
virtmemSetup();
|
virtmemSetup();
|
||||||
__libnx_initheap();
|
__libnx_initheap();
|
||||||
|
__libnx_init_thread();
|
||||||
|
|
||||||
// Build argc/argv if present
|
// Build argc/argv if present
|
||||||
argvSetup();
|
argvSetup();
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
static int sock = -1;
|
static int sock = -1;
|
||||||
|
|
||||||
int nxlinkStdio(void)
|
int nxlinkConnectToHost(bool redirStdout, bool redirStderr)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct sockaddr_in srv_addr;
|
struct sockaddr_in srv_addr;
|
||||||
@ -30,12 +30,17 @@ int nxlinkStdio(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (redirStdout) {
|
||||||
// redirect stdout
|
// redirect stdout
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
dup2(sock, STDOUT_FILENO);
|
dup2(sock, STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirStderr) {
|
||||||
// redirect stderr
|
// redirect stderr
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
dup2(sock, STDERR_FILENO);
|
dup2(sock, STDERR_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
@ -2726,7 +2726,13 @@ IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHomeButtonDoubleClickEnabled(bool *out)
|
|||||||
|
|
||||||
// IDebugFunctions
|
// IDebugFunctions
|
||||||
|
|
||||||
IPC_MAKE_CMD_IMPL(Result appletOpenMainApplication(AppletApplication *a), &g_appletIDebugFunctions, 1, _appletApplicationCreate, a)
|
Result appletOpenMainApplication(AppletApplication *a) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return _appletApplicationCreate(&g_appletIDebugFunctions, a, 1);
|
||||||
|
}
|
||||||
|
|
||||||
IPC_MAKE_CMD_IMPL(Result appletPerformSystemButtonPressing(AppletSystemButtonType type), &g_appletIDebugFunctions, 10, _appletCmdInU32NoOut, type)
|
IPC_MAKE_CMD_IMPL(Result appletPerformSystemButtonPressing(AppletSystemButtonType type), &g_appletIDebugFunctions, 10, _appletCmdInU32NoOut, type)
|
||||||
IPC_MAKE_CMD_IMPL(Result appletInvalidateTransitionLayer(void), &g_appletIDebugFunctions, 20, _appletCmdNoIO)
|
IPC_MAKE_CMD_IMPL(Result appletInvalidateTransitionLayer(void), &g_appletIDebugFunctions, 20, _appletCmdNoIO)
|
||||||
|
|
||||||
|
@ -220,3 +220,41 @@ Result audoutContainsAudioOutBuffer(AudioOutBuffer *Buffer, bool *ContainsBuffer
|
|||||||
if (R_SUCCEEDED(rc) && ContainsBuffer) *ContainsBuffer = out & 1;
|
if (R_SUCCEEDED(rc) && ContainsBuffer) *ContainsBuffer = out & 1;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result audoutGetAudioOutBufferCount(u32 *count) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchOut(&g_audoutIAudioOut, 9, *count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audoutGetAudioOutPlayedSampleCount(u64 *count) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchOut(&g_audoutIAudioOut, 10, *count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audoutFlushAudioOutBuffers(bool *flushed) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
u8 out=0;
|
||||||
|
Result rc = serviceDispatchOut(&g_audoutIAudioOut, 11, out);
|
||||||
|
if (R_SUCCEEDED(rc) && flushed) *flushed = out & 1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audoutSetAudioOutVolume(float volume) {
|
||||||
|
if (hosversionBefore(6,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audoutIAudioOut, 12, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audoutGetAudioOutVolume(float *volume) {
|
||||||
|
if (hosversionBefore(6,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchOut(&g_audoutIAudioOut, 13, *volume);
|
||||||
|
}
|
||||||
|
@ -32,6 +32,9 @@ Result bpcRebootSystem(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result bpcGetSleepButtonState(BpcSleepButtonState *out) {
|
Result bpcGetSleepButtonState(BpcSleepButtonState *out) {
|
||||||
|
if (hosversionBefore(2,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
u8 tmp = 0;
|
u8 tmp = 0;
|
||||||
Result rc = serviceDispatchOut(&g_bpcSrv, 6, tmp);
|
Result rc = serviceDispatchOut(&g_bpcSrv, 6, tmp);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "kernel/rwlock.h"
|
#include "kernel/rwlock.h"
|
||||||
#include "sf/sessionmgr.h"
|
#include "sf/sessionmgr.h"
|
||||||
#include "services/bsd.h"
|
#include "services/bsd.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
typedef struct BsdSelectTimeval {
|
typedef struct BsdSelectTimeval {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -575,3 +576,37 @@ int bsdDuplicateSocket(int sockfd) {
|
|||||||
|
|
||||||
return _bsdDispatchIn(27, in);
|
return _bsdDispatchIn(27, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bsdRecvMMsg(int sockfd, void *buf, size_t size, unsigned int vlen, int flags, struct timespec *timeout) {
|
||||||
|
if (hosversionBefore(7,0,0)) // This cmd was added with [3.0.0+], but we'll only support the updated [7.0.0+] version of it.
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
int sockfd;
|
||||||
|
int vlen;
|
||||||
|
int flags;
|
||||||
|
u32 _padding;
|
||||||
|
struct timespec timeout;
|
||||||
|
} in = { sockfd, vlen, flags, 0, *timeout };
|
||||||
|
|
||||||
|
return _bsdDispatchIn(29, in,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { buf, size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bsdSendMMsg(int sockfd, void *buf, size_t size, unsigned int vlen, int flags) {
|
||||||
|
if (hosversionBefore(7,0,0)) // This cmd was added with [3.0.0+], but we'll only support the updated [7.0.0+] version of it.
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
int sockfd;
|
||||||
|
int vlen;
|
||||||
|
int flags;
|
||||||
|
} in = { sockfd, vlen, flags };
|
||||||
|
|
||||||
|
return _bsdDispatchIn(30, in,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { buf, size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -293,6 +293,22 @@ Result fsOpenSaveDataFileSystemBySystemSaveDataId(FsFileSystem* out, FsSaveDataS
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsOpenReadOnlySaveDataFileSystem(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, const FsSaveDataAttribute *attr) {
|
||||||
|
if (hosversionBefore(2,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
u8 save_data_space_id;
|
||||||
|
u8 pad[7];
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
} in = { (u8)save_data_space_id, {0}, *attr };
|
||||||
|
|
||||||
|
return _fsObjectDispatchIn(&g_fsSrv, 53, in,
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &out->s,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId save_data_space_id, u64 saveID) {
|
Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId save_data_space_id, u64 saveID) {
|
||||||
if (hosversionBefore(3,0,0))
|
if (hosversionBefore(3,0,0))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
@ -483,10 +499,6 @@ Result fsCreate_SystemSaveData(FsSaveDataSpaceId save_data_space_id, u64 system_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper(s) for fsOpenSaveDataFileSystem.
|
// Wrapper(s) for fsOpenSaveDataFileSystem.
|
||||||
static Result _fsOpen_SaveDataFs(FsFileSystem* out, FsSaveDataAttribute *attr) {
|
|
||||||
return fsOpenSaveDataFileSystem(out, FsSaveDataSpaceId_User, attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result fsOpen_SaveData(FsFileSystem* out, u64 application_id, AccountUid uid) {
|
Result fsOpen_SaveData(FsFileSystem* out, u64 application_id, AccountUid uid) {
|
||||||
FsSaveDataAttribute attr;
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
@ -495,7 +507,28 @@ Result fsOpen_SaveData(FsFileSystem* out, u64 application_id, AccountUid uid) {
|
|||||||
attr.uid = uid;
|
attr.uid = uid;
|
||||||
attr.save_data_type = FsSaveDataType_Account;
|
attr.save_data_type = FsSaveDataType_Account;
|
||||||
|
|
||||||
return _fsOpen_SaveDataFs(out, &attr);
|
return fsOpenSaveDataFileSystem(out, FsSaveDataSpaceId_User, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsOpen_SaveDataReadOnly(FsFileSystem* out, u64 application_id, AccountUid uid) {
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.application_id = application_id;
|
||||||
|
attr.uid = uid;
|
||||||
|
attr.save_data_type = FsSaveDataType_Account;
|
||||||
|
|
||||||
|
return fsOpenReadOnlySaveDataFileSystem(out, FsSaveDataSpaceId_User, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsOpen_BcatSaveData(FsFileSystem* out, u64 application_id) {
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.application_id = application_id;
|
||||||
|
attr.save_data_type = FsSaveDataType_Bcat;
|
||||||
|
|
||||||
|
return fsOpenSaveDataFileSystem(out, FsSaveDataSpaceId_User, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsOpen_DeviceSaveData(FsFileSystem* out, u64 application_id) {
|
Result fsOpen_DeviceSaveData(FsFileSystem* out, u64 application_id) {
|
||||||
@ -505,7 +538,33 @@ Result fsOpen_DeviceSaveData(FsFileSystem* out, u64 application_id) {
|
|||||||
attr.application_id = application_id;
|
attr.application_id = application_id;
|
||||||
attr.save_data_type = FsSaveDataType_Device;
|
attr.save_data_type = FsSaveDataType_Device;
|
||||||
|
|
||||||
return _fsOpen_SaveDataFs(out, &attr);
|
return fsOpenSaveDataFileSystem(out, FsSaveDataSpaceId_User, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsOpen_TemporaryStorage(FsFileSystem* out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.save_data_type = FsSaveDataType_Temporary;
|
||||||
|
|
||||||
|
return fsOpenSaveDataFileSystem(out, FsSaveDataType_Temporary, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result fsOpen_CacheStorage(FsFileSystem* out, u64 application_id, u16 save_data_index) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.application_id = application_id;
|
||||||
|
attr.save_data_type = FsSaveDataType_Cache;
|
||||||
|
attr.save_data_index = save_data_index;
|
||||||
|
|
||||||
|
return fsOpenSaveDataFileSystem(out, FsSaveDataSpaceId_User, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsOpen_SystemSaveData(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid) {
|
Result fsOpen_SystemSaveData(FsFileSystem* out, FsSaveDataSpaceId save_data_space_id, u64 system_save_data_id, AccountUid uid) {
|
||||||
@ -519,6 +578,19 @@ Result fsOpen_SystemSaveData(FsFileSystem* out, FsSaveDataSpaceId save_data_spac
|
|||||||
return fsOpenSaveDataFileSystemBySystemSaveDataId(out, save_data_space_id, &attr);
|
return fsOpenSaveDataFileSystemBySystemSaveDataId(out, save_data_space_id, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsOpen_SystemBcatSaveData(FsFileSystem* out, u64 system_save_data_id) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
FsSaveDataAttribute attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.system_save_data_id = system_save_data_id;
|
||||||
|
attr.save_data_type = FsSaveDataType_SystemBcat;
|
||||||
|
|
||||||
|
return fsOpenSaveDataFileSystemBySystemSaveDataId(out, FsSaveDataSpaceId_System, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// IFileSystem
|
// IFileSystem
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -32,14 +32,31 @@ Service* fsldrGetServiceSession(void) {
|
|||||||
return &g_fsldrSrv;
|
return &g_fsldrSrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) {
|
Result fsldrOpenCodeFileSystem(FsCodeInfo* out_code_info, u64 tid, const char *path, FsFileSystem* out) {
|
||||||
|
memset(out_code_info, 0, sizeof(*out_code_info));
|
||||||
|
|
||||||
char send_path[FS_MAX_PATH]={0};
|
char send_path[FS_MAX_PATH]={0};
|
||||||
strncpy(send_path, path, FS_MAX_PATH-1);
|
strncpy(send_path, path, FS_MAX_PATH-1);
|
||||||
|
|
||||||
|
if (hosversionAtLeast(10,0,0)) {
|
||||||
serviceAssumeDomain(&g_fsldrSrv);
|
serviceAssumeDomain(&g_fsldrSrv);
|
||||||
return serviceDispatchIn(&g_fsldrSrv, 0, tid,
|
return serviceDispatchIn(&g_fsldrSrv, 0, tid,
|
||||||
.buffer_attrs = {
|
.buffer_attrs = {
|
||||||
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out,
|
||||||
|
SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ out_code_info, sizeof(*out_code_info) },
|
||||||
|
{ send_path, FS_MAX_PATH },
|
||||||
|
},
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &out->s,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
serviceAssumeDomain(&g_fsldrSrv);
|
||||||
|
return serviceDispatchIn(&g_fsldrSrv, 0, tid,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
},
|
},
|
||||||
.buffers = {
|
.buffers = {
|
||||||
{ send_path, FS_MAX_PATH },
|
{ send_path, FS_MAX_PATH },
|
||||||
@ -49,6 +66,8 @@ Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Result fsldrIsArchivedProgram(u64 pid, bool *out) {
|
Result fsldrIsArchivedProgram(u64 pid, bool *out) {
|
||||||
serviceAssumeDomain(&g_fsldrSrv);
|
serviceAssumeDomain(&g_fsldrSrv);
|
||||||
u8 tmp=0;
|
u8 tmp=0;
|
||||||
|
@ -78,6 +78,9 @@ Result fsprSetCurrentProcess(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result fsprSetEnabledProgramVerification(bool enabled) {
|
Result fsprSetEnabledProgramVerification(bool enabled) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
const u8 in = enabled != 0;
|
const u8 in = enabled != 0;
|
||||||
serviceAssumeDomain(&g_fsprSrv);
|
serviceAssumeDomain(&g_fsprSrv);
|
||||||
return serviceDispatchIn(&g_fsprSrv, 256, in);
|
return serviceDispatchIn(&g_fsprSrv, 256, in);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -92,3 +92,11 @@ Result ldrPmPinProgram(const NcmProgramLocation *loc, u64 *out_pin_id) {
|
|||||||
Result ldrPmUnpinProgram(u64 pin_id) {
|
Result ldrPmUnpinProgram(u64 pin_id) {
|
||||||
return serviceDispatchIn(&g_ldrPmSrv, 3, pin_id);
|
return serviceDispatchIn(&g_ldrPmSrv, 3, pin_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ldrPmSetEnabledProgramVerification(bool enabled) {
|
||||||
|
if (hosversionBefore(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const u8 in = enabled != 0;
|
||||||
|
return serviceDispatchIn(&g_ldrPmSrv, 4, in);
|
||||||
|
}
|
||||||
|
@ -135,6 +135,13 @@ Result lrLrRefresh(LrLocationResolver* lr) {
|
|||||||
return serviceDispatch(&lr->s, 9);
|
return serviceDispatch(&lr->s, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result lrLrEraseProgramRedirection(LrLocationResolver* lr, u64 tid) {
|
||||||
|
if (hosversionBefore(5,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchIn(&lr->s, 12, tid);
|
||||||
|
}
|
||||||
|
|
||||||
Result lrRegLrResolveProgramPath(LrRegisteredLocationResolver* reg, u64 tid, char *out) {
|
Result lrRegLrResolveProgramPath(LrRegisteredLocationResolver* reg, u64 tid, char *out) {
|
||||||
return _lrResolvePath(®->s, tid, out, 0);
|
return _lrResolvePath(®->s, tid, out, 0);
|
||||||
}
|
}
|
||||||
|
80
nx/source/services/mii.c
Normal file
80
nx/source/services/mii.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "services/mii.h"
|
||||||
|
|
||||||
|
static MiiServiceType g_miiServiceType;
|
||||||
|
static Service g_miiSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD_PARAMS(mii, (MiiServiceType service_type), (service_type));
|
||||||
|
|
||||||
|
Result _miiInitialize(MiiServiceType service_type) {
|
||||||
|
Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
|
||||||
|
g_miiServiceType = service_type;
|
||||||
|
switch (g_miiServiceType) {
|
||||||
|
case MiiServiceType_System:
|
||||||
|
rc = smGetService(&g_miiSrv, "mii:e");
|
||||||
|
break;
|
||||||
|
case MiiServiceType_User:
|
||||||
|
rc = smGetService(&g_miiSrv, "mii:u");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _miiCleanup(void) {
|
||||||
|
serviceClose(&g_miiSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* miiGetServiceSession(void) {
|
||||||
|
return &g_miiSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiOpenDatabase(MiiDatabase *out, MiiSpecialKeyCode key_code) {
|
||||||
|
u32 in = (u32)key_code;
|
||||||
|
return serviceDispatchIn(&g_miiSrv, 0, in,
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &out->s,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiDatabaseIsUpdated(MiiDatabase *db, bool *out_updated, MiiSourceFlag flag) {
|
||||||
|
u32 in = (u32)flag;
|
||||||
|
u8 tmp = 0;
|
||||||
|
Result rc = serviceDispatchInOut(&db->s, 0, in, tmp);
|
||||||
|
if (R_SUCCEEDED(rc) && out_updated) *out_updated = tmp & 1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiDatabaseIsFull(MiiDatabase *db, bool *out_full) {
|
||||||
|
u8 tmp = 0;
|
||||||
|
Result rc = serviceDispatchOut(&db->s, 1, tmp);
|
||||||
|
if (R_SUCCEEDED(rc) && out_full) *out_full = tmp & 1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
Result miiDatabaseGetCount(MiiDatabase *db, s32 *out_count, MiiSourceFlag flag) {
|
||||||
|
u32 in = (u32)flag;
|
||||||
|
return serviceDispatchInOut(&db->s, 2, in, *out_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiDatabaseGet1(MiiDatabase *db, MiiSourceFlag flag, MiiCharInfo *out_infos, s32 count, s32 *total_out) {
|
||||||
|
u32 in = (u32)flag;
|
||||||
|
return serviceDispatchInOut(&db->s, 4, in, *total_out,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { out_infos, count * sizeof(MiiCharInfo) } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiDatabaseBuildRandom(MiiDatabase *db, MiiAge age, MiiGender gender, MiiFaceColor face_color, MiiCharInfo *out_info) {
|
||||||
|
const struct {
|
||||||
|
u32 age;
|
||||||
|
u32 gender;
|
||||||
|
u32 face_color;
|
||||||
|
} in = { age, gender, face_color };
|
||||||
|
return serviceDispatchInOut(&db->s, 6, in, *out_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void miiDatabaseClose(MiiDatabase *db) {
|
||||||
|
serviceClose(&db->s);
|
||||||
|
}
|
64
nx/source/services/miiimg.c
Normal file
64
nx/source/services/miiimg.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "services/miiimg.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
|
static Service g_miiimgSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(miiimg);
|
||||||
|
|
||||||
|
static Result _miiimgInitializeCmd(u8 in, u8 *out) {
|
||||||
|
return serviceDispatchInOut(&g_miiimgSrv, 0, in, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result _miiimgInitialize(void) {
|
||||||
|
if (hosversionBefore(5,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
Result rc = smGetService(&g_miiimgSrv, "miiimg");
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
u8 tmp;
|
||||||
|
rc = _miiimgInitializeCmd(1, &tmp);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _miiimgCleanup(void) {
|
||||||
|
serviceClose(&g_miiimgSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* miiimgGetServiceSession(void) {
|
||||||
|
return &g_miiimgSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgReload(void) {
|
||||||
|
return serviceDispatch(&g_miiimgSrv, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgGetCount(s32 *out_count) {
|
||||||
|
return serviceDispatchOut(&g_miiimgSrv, 11, *out_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgIsEmpty(bool *out_empty) {
|
||||||
|
u8 tmp = 0;
|
||||||
|
Result rc = serviceDispatchOut(&g_miiimgSrv, 12, tmp);
|
||||||
|
if (R_SUCCEEDED(rc) && out_empty) *out_empty = tmp & 1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgIsFull(bool *out_full) {
|
||||||
|
u8 tmp = 0;
|
||||||
|
Result rc = serviceDispatchOut(&g_miiimgSrv, 13, tmp);
|
||||||
|
if (R_SUCCEEDED(rc) && out_full) *out_full = tmp & 1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgGetAttribute(s32 index, MiiimgImageAttribute *out_attr) {
|
||||||
|
return serviceDispatchInOut(&g_miiimgSrv, 14, index, *out_attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result miiimgLoadImage(MiiimgImageId id, void* out_image, size_t out_image_size) {
|
||||||
|
return serviceDispatchIn(&g_miiimgSrv, 15, id,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { out_image, out_image_size } },
|
||||||
|
);
|
||||||
|
}
|
@ -236,7 +236,7 @@ Result nfpUnmount(const NfcDeviceHandle *handle) {
|
|||||||
return _nfcCmdInDevhandleNoOut(&g_nfpInterface, handle, 6);
|
return _nfcCmdInDevhandleNoOut(&g_nfpInterface, handle, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id, u32 *npad_id) {
|
Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id) {
|
||||||
if (g_nfpServiceType == NfpServiceType_System)
|
if (g_nfpServiceType == NfpServiceType_System)
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id, u32 *np
|
|||||||
} in = { *handle, app_id };
|
} in = { *handle, app_id };
|
||||||
|
|
||||||
serviceAssumeDomain(&g_nfpInterface);
|
serviceAssumeDomain(&g_nfpInterface);
|
||||||
return serviceDispatchInOut(&g_nfpInterface, 7, in, *npad_id);
|
return serviceDispatchIn(&g_nfpInterface, 7, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size) {
|
Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <string.h>
|
||||||
#include "service_guard.h"
|
#include "service_guard.h"
|
||||||
#include "services/nifm.h"
|
#include "services/nifm.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
@ -65,10 +66,10 @@ static Result _nifmCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _nifmCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
/*static Result _nifmCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
||||||
serviceAssumeDomain(srv);
|
serviceAssumeDomain(srv);
|
||||||
return serviceDispatchOut(srv, cmd_id, *out);
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static Result _nifmCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
|
static Result _nifmCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
|
||||||
serviceAssumeDomain(srv);
|
serviceAssumeDomain(srv);
|
||||||
@ -105,8 +106,54 @@ static Result _nifmCreateGeneralService(Service* srv_out) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _nifmConvertSfToNetworkProfileData(const NifmSfNetworkProfileData *in, NifmNetworkProfileData *out) {
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
|
out->uuid = in->uuid;
|
||||||
|
strncpy(out->network_name, in->network_name, sizeof(in->network_name));
|
||||||
|
out->network_name[sizeof(out->network_name)-1] = 0;
|
||||||
|
|
||||||
|
out->unk_x50 = in->unk_x112;
|
||||||
|
out->unk_x54 = in->unk_x113;
|
||||||
|
out->unk_x58 = in->unk_x114;
|
||||||
|
out->unk_x59 = in->unk_x115;
|
||||||
|
|
||||||
|
out->wireless_setting_data.ssid_len = in->wireless_setting_data.ssid_len;
|
||||||
|
if (out->wireless_setting_data.ssid_len > sizeof(out->wireless_setting_data.ssid)-1) out->wireless_setting_data.ssid_len = sizeof(out->wireless_setting_data.ssid)-1;
|
||||||
|
if (out->wireless_setting_data.ssid_len) memcpy(out->wireless_setting_data.ssid, in->wireless_setting_data.ssid, out->wireless_setting_data.ssid_len);
|
||||||
|
out->wireless_setting_data.unk_x22 = in->wireless_setting_data.unk_x21;
|
||||||
|
out->wireless_setting_data.unk_x24 = in->wireless_setting_data.unk_x22;
|
||||||
|
out->wireless_setting_data.unk_x28 = in->wireless_setting_data.unk_x23;
|
||||||
|
memcpy(out->wireless_setting_data.passphrase, in->wireless_setting_data.passphrase, sizeof(out->wireless_setting_data.passphrase));
|
||||||
|
|
||||||
|
memcpy(&out->ip_setting_data, &in->ip_setting_data, sizeof(out->ip_setting_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _nifmConvertSfFromNetworkProfileData(const NifmNetworkProfileData *in, NifmSfNetworkProfileData *out) {
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
|
out->uuid = in->uuid;
|
||||||
|
strncpy(out->network_name, in->network_name, sizeof(out->network_name));
|
||||||
|
out->network_name[sizeof(out->network_name)-1] = 0;
|
||||||
|
|
||||||
|
out->unk_x112 = in->unk_x50;
|
||||||
|
out->unk_x113 = in->unk_x54;
|
||||||
|
out->unk_x114 = in->unk_x58;
|
||||||
|
out->unk_x115 = in->unk_x59;
|
||||||
|
|
||||||
|
out->wireless_setting_data.ssid_len = in->wireless_setting_data.ssid_len;
|
||||||
|
memcpy(out->wireless_setting_data.ssid, in->wireless_setting_data.ssid, sizeof(out->wireless_setting_data.ssid)-1);
|
||||||
|
out->wireless_setting_data.unk_x21 = in->wireless_setting_data.unk_x22;
|
||||||
|
out->wireless_setting_data.unk_x22 = in->wireless_setting_data.unk_x24;
|
||||||
|
out->wireless_setting_data.unk_x23 = in->wireless_setting_data.unk_x28;
|
||||||
|
memcpy(out->wireless_setting_data.passphrase, in->wireless_setting_data.passphrase, sizeof(out->wireless_setting_data.passphrase));
|
||||||
|
|
||||||
|
memcpy(&out->ip_setting_data, &in->ip_setting_data, sizeof(out->ip_setting_data));
|
||||||
|
}
|
||||||
|
|
||||||
NifmClientId nifmGetClientId(void) {
|
NifmClientId nifmGetClientId(void) {
|
||||||
NifmClientId id={0};
|
NifmClientId id={0};
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
Result rc = serviceDispatch(&g_nifmIGS, 1,
|
Result rc = serviceDispatch(&g_nifmIGS, 1,
|
||||||
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out },
|
||||||
.buffers = { { &id, sizeof(id) } },
|
.buffers = { { &id, sizeof(id) } },
|
||||||
@ -115,8 +162,63 @@ NifmClientId nifmGetClientId(void) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result nifmGetCurrentNetworkProfile(NifmNetworkProfileData *profile) {
|
||||||
|
NifmSfNetworkProfileData tmp={0};
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
|
Result rc = serviceDispatch(&g_nifmIGS, 5,
|
||||||
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out },
|
||||||
|
.buffers = { { &tmp, sizeof(tmp) } },
|
||||||
|
);
|
||||||
|
if (R_SUCCEEDED(rc)) _nifmConvertSfToNetworkProfileData(&tmp, profile);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nifmGetNetworkProfile(Uuid uuid, NifmNetworkProfileData *profile) {
|
||||||
|
NifmSfNetworkProfileData tmp={0};
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
|
Result rc = serviceDispatchIn(&g_nifmIGS, 8, uuid,
|
||||||
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out },
|
||||||
|
.buffers = { { &tmp, sizeof(tmp) } },
|
||||||
|
);
|
||||||
|
if (R_SUCCEEDED(rc)) _nifmConvertSfToNetworkProfileData(&tmp, profile);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nifmSetNetworkProfile(const NifmNetworkProfileData *profile, Uuid *uuid) {
|
||||||
|
NifmSfNetworkProfileData tmp={0};
|
||||||
|
_nifmConvertSfFromNetworkProfileData(profile, &tmp);
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
|
Result rc = serviceDispatchOut(&g_nifmIGS, 9, *uuid,
|
||||||
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
||||||
|
.buffers = { { &tmp, sizeof(tmp) } },
|
||||||
|
);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
Result nifmGetCurrentIpAddress(u32* out) {
|
Result nifmGetCurrentIpAddress(u32* out) {
|
||||||
return _nifmCmdNoInOutU32(&g_nifmIGS, out, 12);
|
NifmIpV4Address tmp={0};
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
|
Result rc = serviceDispatchOut(&g_nifmIGS, 12, tmp);
|
||||||
|
if (R_SUCCEEDED(rc) && out) *out = *((u32*)tmp.addr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nifmGetCurrentIpConfigInfo(u32 *current_addr, u32 *subnet_mask, u32 *gateway, u32 *primary_dns_server, u32 *secondary_dns_server) {
|
||||||
|
struct {
|
||||||
|
NifmIpAddressSetting ip_setting;
|
||||||
|
NifmDnsSetting dns_setting;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
|
Result rc = serviceDispatchOut(&g_nifmIGS, 15, out);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (current_addr) *current_addr = *((u32*)out.ip_setting.current_addr.addr);
|
||||||
|
if (subnet_mask) *subnet_mask = *((u32*)out.ip_setting.subnet_mask.addr);
|
||||||
|
if (gateway) *gateway = *((u32*)out.ip_setting.gateway.addr);
|
||||||
|
if (primary_dns_server) *primary_dns_server = *((u32*)out.dns_setting.primary_dns_server.addr);
|
||||||
|
if (secondary_dns_server) *secondary_dns_server = *((u32*)out.dns_setting.secondary_dns_server.addr);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nifmSetWirelessCommunicationEnabled(bool enable) {
|
Result nifmSetWirelessCommunicationEnabled(bool enable) {
|
||||||
@ -153,6 +255,7 @@ Result nifmIsEthernetCommunicationEnabled(bool* out) {
|
|||||||
|
|
||||||
bool nifmIsAnyInternetRequestAccepted(NifmClientId id) {
|
bool nifmIsAnyInternetRequestAccepted(NifmClientId id) {
|
||||||
u8 tmp=0;
|
u8 tmp=0;
|
||||||
|
serviceAssumeDomain(&g_nifmIGS);
|
||||||
Result rc = serviceDispatchOut(&g_nifmIGS, 21, tmp,
|
Result rc = serviceDispatchOut(&g_nifmIGS, 21, tmp,
|
||||||
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
||||||
.buffers = { { &id, sizeof(id) } },
|
.buffers = { { &id, sizeof(id) } },
|
||||||
|
36
nx/source/services/nim.c
Normal file
36
nx/source/services/nim.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "services/nim.h"
|
||||||
|
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
|
static Service g_nimSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(nim);
|
||||||
|
|
||||||
|
Result _nimInitialize(void) {
|
||||||
|
return smGetService(&g_nimSrv, "nim");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _nimCleanup(void) {
|
||||||
|
serviceClose(&g_nimSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* nimGetServiceSession(void) {
|
||||||
|
return &g_nimSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nimDestroySystemUpdateTask(const NimSystemUpdateTaskId *task_id) {
|
||||||
|
return serviceDispatchIn(&g_nimSrv, 1, *task_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nimListSystemUpdateTask(s32 *out_count, NimSystemUpdateTaskId *out_task_ids, size_t max_task_ids) {
|
||||||
|
return serviceDispatchOut(&g_nimSrv, 2, *out_count,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ out_task_ids, max_task_ids * sizeof(*out_task_ids) },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -729,6 +729,9 @@ Result nsIsApplicationEntityMovable(u64 application_id, NcmStorageId storage_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id) {
|
Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return _nsManCmdInU8U64NoOut(storage_id, application_id, 9);
|
return _nsManCmdInU8U64NoOut(storage_id, application_id, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1226,7 +1229,7 @@ static Result _nsRequestVerifyApplication(NsProgressAsyncResult *a, u64 applicat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsRequestVerifyAddOnContentsRights(NsProgressAsyncResult *a, u64 application_id) {
|
Result nsRequestVerifyAddOnContentsRights(NsProgressAsyncResult *a, u64 application_id) {
|
||||||
if (hosversionBefore(3,0,0))
|
if (!hosversionBetween(3,10))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
Service srv={0};
|
Service srv={0};
|
||||||
@ -2262,6 +2265,9 @@ Service* nsdevGetServiceSession(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) {
|
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
const struct {
|
const struct {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u32 pad;
|
u32 pad;
|
||||||
@ -2276,14 +2282,23 @@ Result nsdevTerminateProcess(u64 pid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevTerminateProgram(u64 tid) {
|
Result nsdevTerminateProgram(u64 tid) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return _nsCmdInU64(&g_nsdevSrv, tid, 2);
|
return _nsCmdInU64(&g_nsdevSrv, tid, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevGetShellEvent(Event* out_event) {
|
Result nsdevGetShellEvent(Event* out_event) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return _nsCmdGetEvent(&g_nsdevSrv, out_event, true, 4);
|
return _nsCmdGetEvent(&g_nsdevSrv, out_event, true, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevGetShellEventInfo(NsShellEventInfo* out) {
|
Result nsdevGetShellEventInfo(NsShellEventInfo* out) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 event;
|
u32 event;
|
||||||
u64 process_id;
|
u64 process_id;
|
||||||
@ -2302,6 +2317,9 @@ Result nsdevTerminateApplication(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len) {
|
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return serviceDispatchOut(&g_nsdevSrv, 7, *out,
|
return serviceDispatchOut(&g_nsdevSrv, 7, *out,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
||||||
.buffers = { { path, path_len } },
|
.buffers = { { path, path_len } },
|
||||||
@ -2309,6 +2327,9 @@ Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 application_id, u32 flags) {
|
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 application_id, u32 flags) {
|
||||||
|
if (hosversionAtLeast(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
const struct {
|
const struct {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u64 application_id;
|
u64 application_id;
|
||||||
@ -2317,6 +2338,16 @@ Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 application_id, u32 fl
|
|||||||
return serviceDispatchInOut(&g_nsdevSrv, 8, in, *out_pid);
|
return serviceDispatchInOut(&g_nsdevSrv, 8, in, *out_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result nsdevLaunchApplicationFromHost(u64* out_pid, const char* path, size_t path_len, u32 flags) {
|
||||||
|
if (hosversionBefore(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchInOut(&g_nsdevSrv, 8, flags, *out_pid,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
||||||
|
.buffers = { { path, path_len } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 application_id, u32 flags, u8 app_storage_id, u8 patch_storage_id) {
|
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 application_id, u32 flags, u8 app_storage_id, u8 patch_storage_id) {
|
||||||
const struct {
|
const struct {
|
||||||
u8 app_storage_id;
|
u8 app_storage_id;
|
||||||
|
134
nx/source/services/pgl.c
Normal file
134
nx/source/services/pgl.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include <string.h>
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "services/pgl.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
|
static Service g_pglSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(pgl);
|
||||||
|
|
||||||
|
Result _pglInitialize(void) {
|
||||||
|
if (hosversionBefore(10,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
return smGetService(&g_pglSrv, "pgl");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pglCleanup(void) {
|
||||||
|
serviceClose(&g_pglSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* pglGetServiceSession(void) {
|
||||||
|
return &g_pglSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _pglCmdInBool(Service* srv, bool inval, u32 cmd_id) {
|
||||||
|
const u8 in = inval;
|
||||||
|
return serviceDispatchIn(srv, cmd_id, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _pglCmdOutBool(Service* srv, bool *out, u32 cmd_id) {
|
||||||
|
u8 outval = 0;
|
||||||
|
Result rc = serviceDispatchOut(srv, cmd_id, outval);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (out) *out = outval & 1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _pglCmdInU64(Service* srv, u64 inval, u32 cmd_id) {
|
||||||
|
return serviceDispatchIn(srv, cmd_id, inval);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglLaunchProgram(u64 *out_pid, const NcmProgramLocation *loc, u32 pm_launch_flags, u8 pgl_launch_flags) {
|
||||||
|
const struct {
|
||||||
|
u8 pgl_flags;
|
||||||
|
u32 pm_flags;
|
||||||
|
NcmProgramLocation loc;
|
||||||
|
} in = { pgl_launch_flags, pm_launch_flags, *loc };
|
||||||
|
return serviceDispatchInOut(&g_pglSrv, 0, in, *out_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglTerminateProcess(u64 pid) {
|
||||||
|
return _pglCmdInU64(&g_pglSrv, pid, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglLaunchProgramFromHost(u64 *out_pid, const char *content_path, u32 pm_launch_flags) {
|
||||||
|
return serviceDispatchInOut(&g_pglSrv, 2, pm_launch_flags, *out_pid,
|
||||||
|
.buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias },
|
||||||
|
.buffers = { { content_path, strlen(content_path) + 1 } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglGetHostContentMetaInfo(PglContentMetaInfo *out, const char *content_path) {
|
||||||
|
return serviceDispatchOut(&g_pglSrv, 4, *out,
|
||||||
|
.buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias },
|
||||||
|
.buffers = { { content_path, strlen(content_path) + 1 } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglGetApplicationProcessId(u64 *out) {
|
||||||
|
return serviceDispatchOut(&g_pglSrv, 5, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglBoostSystemMemoryResourceLimit(u64 size) {
|
||||||
|
return _pglCmdInU64(&g_pglSrv, size, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglIsProcessTracked(bool *out, u64 pid) {
|
||||||
|
u8 outval = 0;
|
||||||
|
Result rc = serviceDispatchInOut(&g_pglSrv, 7, pid, outval);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (out) *out = outval & 1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglEnableApplicationCrashReport(bool en) {
|
||||||
|
return _pglCmdInBool(&g_pglSrv, en, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglIsApplicationCrashReportEnabled(bool *out) {
|
||||||
|
return _pglCmdOutBool(&g_pglSrv, out, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglEnableApplicationAllThreadDumpOnCrash(bool en) {
|
||||||
|
return _pglCmdInBool(&g_pglSrv, en, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglTriggerApplicationSnapShotDumper(PglSnapShotDumpType dump_type, const char *arg) {
|
||||||
|
_Static_assert(sizeof(dump_type) == sizeof(u32), "PglSnapShotDumpType");
|
||||||
|
return serviceDispatchIn(&g_pglSrv, 12, dump_type,
|
||||||
|
.buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias },
|
||||||
|
.buffers = { { arg, strlen(arg) + 1 } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglGetEventObserver(PglEventObserver *out) {
|
||||||
|
return serviceDispatch(&g_pglSrv, 20,
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &out->s,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglEventObserverGetProcessEvent(PglEventObserver *observer, Event *out) {
|
||||||
|
Handle evt_handle;
|
||||||
|
Result rc = serviceDispatch(&observer->s, 0,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = &evt_handle,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
eventLoadRemote(out, evt_handle, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pglEventObserverGetProcessEventInfo(PglEventObserver *observer, PmProcessEventInfo *out) {
|
||||||
|
return serviceDispatchOut(&observer->s, 1, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pglEventObserverClose(PglEventObserver *observer) {
|
||||||
|
serviceClose(&observer->s);
|
||||||
|
}
|
@ -6,18 +6,27 @@
|
|||||||
|
|
||||||
#define SHAREDMEMFONT_SIZE 0x1100000
|
#define SHAREDMEMFONT_SIZE 0x1100000
|
||||||
|
|
||||||
|
static PlServiceType g_plServiceType;
|
||||||
static Service g_plSrv;
|
static Service g_plSrv;
|
||||||
static SharedMemory g_plSharedmem;
|
static SharedMemory g_plSharedmem;
|
||||||
|
|
||||||
static Result _plGetSharedMemoryNativeHandle(Handle* handle_out);
|
static Result _plGetSharedMemoryNativeHandle(Handle* handle_out);
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(pl);
|
NX_GENERATE_SERVICE_GUARD_PARAMS(pl, (PlServiceType service_type), (service_type));
|
||||||
|
|
||||||
Result _plInitialize(void) {
|
Result _plInitialize(PlServiceType service_type) {
|
||||||
Result rc=0;
|
Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
Handle sharedmem_handle=0;
|
Handle sharedmem_handle=0;
|
||||||
|
|
||||||
|
g_plServiceType = service_type;
|
||||||
|
switch (g_plServiceType) {
|
||||||
|
case PlServiceType_User:
|
||||||
rc = smGetService(&g_plSrv, "pl:u");
|
rc = smGetService(&g_plSrv, "pl:u");
|
||||||
|
break;
|
||||||
|
case PlServiceType_System:
|
||||||
|
rc = smGetService(&g_plSrv, "pl:s");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
rc = _plGetSharedMemoryNativeHandle(&sharedmem_handle);
|
rc = _plGetSharedMemoryNativeHandle(&sharedmem_handle);
|
||||||
|
@ -162,7 +162,7 @@ Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size) {
|
|||||||
return serviceDispatchIn(&g_pmshellSrv, cmd_id, boost_size);
|
return serviceDispatchIn(&g_pmshellSrv, cmd_id, boost_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result pmshellBoostSystemThreadResourceLimit(void) {
|
Result pmshellEnableApplicationExtraThread(void) {
|
||||||
if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
return serviceDispatch(&g_pmshellSrv, 8);
|
return serviceDispatch(&g_pmshellSrv, 8);
|
||||||
}
|
}
|
||||||
|
@ -569,15 +569,8 @@ Result setsysGetBatteryLot(SetBatteryLot *out) {
|
|||||||
return serviceDispatchOut(&g_setsysSrv, 67, *out);
|
return serviceDispatchOut(&g_setsysSrv, 67, *out);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetSerialNumber(char *serial) {
|
Result setsysGetSerialNumber(SetSysSerialNumber *out) {
|
||||||
char out[0x18]={0};
|
return serviceDispatchOut(&g_setsysSrv, 68, *out);
|
||||||
|
|
||||||
Result rc = serviceDispatchOut(&g_setsysSrv, 68, out);
|
|
||||||
if (R_SUCCEEDED(rc) && serial) {
|
|
||||||
memcpy(serial, out, 0x18);
|
|
||||||
serial[0x18]=0;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetNfcEnableFlag(bool *out) {
|
Result setsysGetNfcEnableFlag(bool *out) {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include "service_guard.h"
|
#include "service_guard.h"
|
||||||
|
#include "arm/counter.h"
|
||||||
|
#include "kernel/shmem.h"
|
||||||
#include "services/time.h"
|
#include "services/time.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
|
|
||||||
@ -8,10 +12,15 @@ __attribute__((weak)) TimeServiceType __nx_time_service_type = TimeServiceType_U
|
|||||||
static Service g_timeSrv;
|
static Service g_timeSrv;
|
||||||
static Service g_timeUserSystemClock;
|
static Service g_timeUserSystemClock;
|
||||||
static Service g_timeNetworkSystemClock;
|
static Service g_timeNetworkSystemClock;
|
||||||
|
static Service g_timeSteadyClock;
|
||||||
static Service g_timeTimeZoneService;
|
static Service g_timeTimeZoneService;
|
||||||
static Service g_timeLocalSystemClock;
|
static Service g_timeLocalSystemClock;
|
||||||
|
|
||||||
|
static SharedMemory g_timeSharedmem;
|
||||||
|
|
||||||
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id);
|
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id);
|
||||||
|
static Result _timeGetSharedMemoryNativeHandle(Service* srv, Handle* out);
|
||||||
|
static void _timeReadSharedmemObj(void* out, size_t offset, size_t size);
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(time);
|
NX_GENERATE_SERVICE_GUARD(time);
|
||||||
|
|
||||||
@ -41,26 +50,38 @@ Result _timeInitialize(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeUserSystemClock, 0);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeUserSystemClock, 0);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeSteadyClock, 2);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeLocalSystemClock, 4);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeLocalSystemClock, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && hosversionAtLeast(6,0,0)) {
|
||||||
|
Handle shmem;
|
||||||
|
rc = _timeGetSharedMemoryNativeHandle(&g_timeSrv, &shmem);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
shmemLoadRemote(&g_timeSharedmem, shmem, 0x1000, Perm_R);
|
||||||
|
rc = shmemMap(&g_timeSharedmem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _timeCleanup(void) {
|
void _timeCleanup(void) {
|
||||||
|
shmemClose(&g_timeSharedmem);
|
||||||
serviceClose(&g_timeLocalSystemClock);
|
serviceClose(&g_timeLocalSystemClock);
|
||||||
serviceClose(&g_timeTimeZoneService);
|
serviceClose(&g_timeTimeZoneService);
|
||||||
|
serviceClose(&g_timeSteadyClock);
|
||||||
serviceClose(&g_timeNetworkSystemClock);
|
serviceClose(&g_timeNetworkSystemClock);
|
||||||
serviceClose(&g_timeUserSystemClock);
|
serviceClose(&g_timeUserSystemClock);
|
||||||
serviceClose(&g_timeSrv);
|
serviceClose(&g_timeSrv);
|
||||||
@ -85,10 +106,32 @@ Service* timeGetServiceSession_SystemClock(TimeType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Service* timeGetServiceSession_SteadyClock(void) {
|
||||||
|
return &g_timeSteadyClock;
|
||||||
|
}
|
||||||
|
|
||||||
Service* timeGetServiceSession_TimeZoneService(void) {
|
Service* timeGetServiceSession_TimeZoneService(void) {
|
||||||
return &g_timeTimeZoneService;
|
return &g_timeTimeZoneService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* timeGetSharedmemAddr(void) {
|
||||||
|
return shmemGetAddr(&g_timeSharedmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _timeReadSharedmemObj(void* out, size_t offset, size_t size) {
|
||||||
|
void* addr = (u8*)shmemGetAddr(&g_timeSharedmem) + offset;
|
||||||
|
|
||||||
|
vu32* counter = (vu32*)addr;
|
||||||
|
void* data = (u8*)addr + 8;
|
||||||
|
|
||||||
|
u32 cur_counter;
|
||||||
|
do {
|
||||||
|
cur_counter = *counter;
|
||||||
|
memcpy(out, (u8*)data + (cur_counter&1)*size, size);
|
||||||
|
atomic_thread_fence(memory_order_consume);
|
||||||
|
} while (cur_counter != *counter);
|
||||||
|
}
|
||||||
|
|
||||||
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
||||||
return serviceDispatch(srv, cmd_id,
|
return serviceDispatch(srv, cmd_id,
|
||||||
.out_num_objects = 1,
|
.out_num_objects = 1,
|
||||||
@ -96,6 +139,13 @@ static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result _timeGetSharedMemoryNativeHandle(Service* srv, Handle* out) {
|
||||||
|
return serviceDispatch(srv, 20,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = out,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Result _timeCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) {
|
static Result _timeCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) {
|
||||||
return serviceDispatchIn(srv, cmd_id, inval);
|
return serviceDispatchIn(srv, cmd_id, inval);
|
||||||
}
|
}
|
||||||
@ -108,7 +158,45 @@ static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
|||||||
return serviceDispatchOut(srv, cmd_id, *out);
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s64 _timeComputeSteadyClockTimePoint(const TimeStandardSteadyClockTimePointType *context) {
|
||||||
|
return (context->base_time + armTicksToNs(armGetSystemTick())) / 1000000000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result timeGetStandardSteadyClockTimePoint(TimeSteadyClockTimePoint *out) {
|
||||||
|
if (!shmemGetAddr(&g_timeSharedmem)) {
|
||||||
|
return serviceDispatchOut(&g_timeSteadyClock, 0, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeStandardSteadyClockTimePointType context;
|
||||||
|
_timeReadSharedmemObj(&context, 0x00, sizeof(context));
|
||||||
|
out->time_point = _timeComputeSteadyClockTimePoint(&context);
|
||||||
|
out->source_id = context.source_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result timeGetStandardSteadyClockInternalOffset(s64 *out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchOut(&g_timeSteadyClock, 200, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _timeReadClockFromSharedMem(size_t offset, u64 *out) {
|
||||||
|
TimeStandardSteadyClockTimePointType steady;
|
||||||
|
_timeReadSharedmemObj(&steady, 0x00, sizeof(steady));
|
||||||
|
|
||||||
|
TimeSystemClockContext context;
|
||||||
|
_timeReadSharedmemObj(&context, offset, sizeof(context));
|
||||||
|
|
||||||
|
if (memcmp(&context.timestamp.source_id, &steady.source_id, sizeof(Uuid)) != 0)
|
||||||
|
return MAKERESULT(116,102);
|
||||||
|
|
||||||
|
*out = context.offset + _timeComputeSteadyClockTimePoint(&steady);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Result timeGetCurrentTime(TimeType type, u64 *timestamp) {
|
Result timeGetCurrentTime(TimeType type, u64 *timestamp) {
|
||||||
|
if (!shmemGetAddr(&g_timeSharedmem)) {
|
||||||
Service *srv = timeGetServiceSession_SystemClock(type);
|
Service *srv = timeGetServiceSession_SystemClock(type);
|
||||||
|
|
||||||
if (srv==NULL)
|
if (srv==NULL)
|
||||||
@ -117,6 +205,12 @@ Result timeGetCurrentTime(TimeType type, u64 *timestamp) {
|
|||||||
return _timeCmdNoInOutU64(srv, timestamp, 0);
|
return _timeCmdNoInOutU64(srv, timestamp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type != TimeType_NetworkSystemClock)
|
||||||
|
return _timeReadClockFromSharedMem(0x38, timestamp);
|
||||||
|
else
|
||||||
|
return _timeReadClockFromSharedMem(0x80, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
Result timeSetCurrentTime(TimeType type, u64 timestamp) {
|
Result timeSetCurrentTime(TimeType type, u64 timestamp) {
|
||||||
Service *srv = timeGetServiceSession_SystemClock(type);
|
Service *srv = timeGetServiceSession_SystemClock(type);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user