SuperMarioOdysseyOnline/include/nn/os.h
2022-06-16 14:33:18 -07:00

265 lines
7.6 KiB
C++

/**
* @file os.h
* @brief Operating System implementations.
*/
#pragma once
#include <type_traits>
#include <nn/time.h>
#include <types.h>
namespace nn {
namespace os {
namespace detail {
struct InternalCriticalSection {
u32 Image;
};
struct InternalConditionVariable {
u32 Image;
};
} // namespace detail
typedef u64 Tick;
struct LightEventType {
std::aligned_storage_t<0xc, 4> storage;
};
// https://github.com/misson20000/nn-types/blob/master/nn_os.h
struct EventType {
nn::os::EventType* _x0;
nn::os::EventType* _x8;
bool isSignaled;
bool initiallySignaled;
bool shouldAutoClear;
bool isInit;
u32 signalCounter;
u32 signalCounter2;
nn::os::detail::InternalCriticalSection crit;
nn::os::detail::InternalConditionVariable condvar;
};
typedef EventType Event;
// https://github.com/misson20000/nn-types/blob/master/nn_os.h
struct ThreadType {
u64 field_8;
u64 field_10;
u64 field_18;
char field_20[32];
uint32_t thread_status;
char field_41;
u16 field_42;
uint32_t thread_prio_shift;
uint64_t thread_stack_base_addr;
uint64_t thread_stack_base_addr_mirror;
uint64_t thread_stack_size;
uint64_t thread_param;
uint64_t thread_func;
u64 field_70;
u64 field_78;
u64 field_80;
char field_88[0x100];
char thread_name[0x20];
const char* thread_name_addr;
nn::os::detail::InternalCriticalSection crit;
nn::os::detail::InternalConditionVariable condvar;
u32 thread_handle;
};
#ifdef SWITCH
static_assert(sizeof(ThreadType) == 0x1C0, "Wrong size");
#endif
struct MessageQueueType {
u64 _x0;
u64 _x8;
u64 _x10;
u64 _x18;
void* Buffer;
u32 MaxCount;
u32 Count;
u32 Offset;
bool Initialized;
detail::InternalCriticalSection _x38;
detail::InternalConditionVariable _x3C;
detail::InternalConditionVariable _x40;
};
struct ConditionVariableType {};
struct SemaphoreType {
std::aligned_storage_t<0x28, 8> storage;
};
struct SystemEvent;
struct SystemEventType;
// ARG
void SetHostArgc(s32);
s32 GetHostArgc();
void SetHostArgv(char**);
char** GetHostArgv();
// MEMORY
void InitializeVirtualAddressMemory();
Result AllocateAddressRegion(u64*, u64);
Result AllocateMemory(u64*, u64);
Result AllocateMemoryPages(u64, u64);
void AllocateMemoryBlock(u64*, u64);
void FreeMemoryBlock(u64, u64);
void SetMemoryHeapSize(u64);
// MUTEX
struct MutexType {
u8 curState; // _0
bool isRecursiveMutex; // _1
s32 lockLevel; // _2
u8 _6[0x20 - 0xE];
};
void InitializeMutex(nn::os::MutexType*, bool, s32);
void FinalizeMutex(nn::os::MutexType*);
void LockMutex(nn::os::MutexType*);
bool TryLockMutex(nn::os::MutexType*);
void UnlockMutex(nn::os::MutexType*);
bool IsMutexLockedByCurrentThread(nn::os::MutexType const*);
// QUEUE
void InitializeMessageQueue(nn::os::MessageQueueType*, u64* buf, u64 queueCount);
void FinalizeMessageQueue(nn::os::MessageQueueType*);
bool TrySendMessageQueue(MessageQueueType*, u64);
void SendMessageQueue(MessageQueueType*, u64);
bool TimedSendMessageQueue(MessageQueueType*, u64, nn::TimeSpan);
bool TryReceiveMessageQueue(u64* out, MessageQueueType*);
void ReceiveMessageQueue(u64* out, MessageQueueType*);
bool TimedReceiveMessageQueue(u64* out, MessageQueueType*, nn::TimeSpan);
bool TryPeekMessageQueue(u64*, MessageQueueType const*);
void PeekMessageQueue(u64*, MessageQueueType const*);
bool TimedPeekMessageQueue(u64*, MessageQueueType const*);
bool TryJamMessageQueue(nn::os::MessageQueueType*, u64);
void JamMessageQueue(nn::os::MessageQueueType*, u64);
bool TimedJamMessageQueue(nn::os::MessageQueueType*, u64, nn::TimeSpan);
// CONDITION VARIABLE
void InitializeConditionVariable(ConditionVariableType*);
void FinalizeConditionVariable(ConditionVariableType*);
void SignalConditionVariable(ConditionVariableType*);
void BroadcastConditionVariable(ConditionVariableType*);
void WaitConditionVariable(ConditionVariableType*);
u8 TimedWaitConditionVariable(ConditionVariableType*, MutexType*, nn::TimeSpan);
// THREAD
Result CreateThread(nn::os::ThreadType*, void (*)(void*), void* arg, void* srcStack, u64 stackSize,
s32 priority, s32 coreNum);
Result CreateThread(nn::os::ThreadType*, void (*)(void*), void* arg, void* srcStack, u64 stackSize,
s32 priority);
void DestroyThread(nn::os::ThreadType*);
void StartThread(nn::os::ThreadType*);
void SetThreadName(nn::os::ThreadType*, char const* threadName);
void SetThreadNamePointer(nn::os::ThreadType*, char const*);
char* GetThreadNamePointer(nn::os::ThreadType const*);
nn::os::ThreadType* GetCurrentThread();
void GetCurrentStackInfo(uintptr_t* stack_addr, size_t* stack_size);
s32 ChangeThreadPriority(nn::os::ThreadType* thread, s32 priority);
s32 GetThreadPriority(nn::os::ThreadType const* thread);
u64 GetThreadId(const nn::os::ThreadType* thread);
void YieldThread();
void SuspendThread(nn::os::ThreadType*);
void ResumeThread(nn::os::ThreadType*);
void SleepThread(nn::TimeSpan);
void WaitThread(nn::os::ThreadType*);
void SetThreadCoreMask(nn::os::ThreadType*, int, u64 mask);
// EVENTS
void InitializeEvent(EventType*, bool initiallySignaled, bool autoclear);
void FinalizeEvent(EventType*);
void SignalEvent(EventType*);
void WaitEvent(EventType*);
bool TryWaitEvent(EventType*);
bool TimedWaitEvent(EventType*, nn::TimeSpan);
void ClearEvent(EventType*);
// LIGHT EVENTS
void InitializeLightEvent(LightEventType*, bool initiallySignaled, bool autoclear);
void FinalizeLightEvent(LightEventType*);
void SignalLightEvent(LightEventType*);
void WaitLightEvent(LightEventType*);
bool TimedWaitLightEvent(LightEventType*, nn::TimeSpan);
void ClearLightEvent(LightEventType*);
TimeSpan ConvertToTimeSpan(Tick ticks);
// SEMAPHORES
void InitializeSemaphore(SemaphoreType* semaphore, s32 initial_count, s32 max_count);
void FinalizeSemaphore(SemaphoreType* semaphore);
void AcquireSemaphore(SemaphoreType* semaphore);
bool TryAcquireSemaphore(SemaphoreType* semaphore);
void ReleaseSemaphore(SemaphoreType* semaphore);
// EXCEPTION HANDLING
typedef union {
u64 x; ///< 64-bit AArch64 register view.
u32 w; ///< 32-bit AArch64 register view.
u32 r; ///< AArch32 register view.
} CpuRegister;
/// Armv8 NEON register.
typedef union {
u128 v; ///< 128-bit vector view.
double d; ///< 64-bit double-precision view.
float s; ///< 32-bit single-precision view.
} FpuRegister;
struct UserExceptionInfo {
u32 ErrorDescription; ///< See \ref ThreadExceptionDesc.
u32 pad[3];
CpuRegister CpuRegisters[29]; ///< GPRs 0..28. Note: also contains AArch32 registers.
CpuRegister FP; ///< Frame pointer.
CpuRegister LR; ///< Link register.
CpuRegister SP; ///< Stack pointer.
CpuRegister PC; ///< Program counter (elr_el1).
u64 padding;
FpuRegister FpuRegisters[32]; ///< 32 general-purpose NEON registers.
u32 PState; ///< pstate & 0xFF0FFE20
u32 AFSR0;
u32 AFSR1;
u32 ESR;
CpuRegister FAR; ///< Fault Address Register.
};
void SetUserExceptionHandler(void (*)(UserExceptionInfo*), void*, ulong, UserExceptionInfo*);
// OTHER
void GenerateRandomBytes(void*, u64);
nn::os::Tick GetSystemTick();
nn::os::Tick GetSystemTickFrequency();
u64 GetThreadAvailableCoreMask();
void SetMemoryHeapSize(u64 size);
// Thread-local storage
struct TlsSlot {
u32 slot;
};
Result AllocateTlsSlot(TlsSlot* slot_out, void (*)(u64));
void FreeTlsSlot(TlsSlot slot);
u64 GetTlsValue(TlsSlot slot);
void SetTlsValue(TlsSlot slot, u64 value);
u32 GetCurrentCoreNumber();
namespace detail {
extern s32 g_CommandLineParameter;
extern char** g_CommandLineParameterArgv;
}; // namespace detail
}; // namespace os
}; // namespace nn