metal: initial support

This commit is contained in:
Samuliak 2024-07-02 08:28:41 +02:00
parent 29d9ed7224
commit f0547d1a71
167 changed files with 28839 additions and 1271 deletions

View file

@ -32,6 +32,7 @@ option(DISABLE_PANIC_DEV "Make a build with fewer and less intrusive asserts" ON
option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF) option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF)
option(ENABLE_OPENGL "Enable OpenGL rendering backend" ON) option(ENABLE_OPENGL "Enable OpenGL rendering backend" ON)
option(ENABLE_VULKAN "Enable Vulkan rendering backend" ON) option(ENABLE_VULKAN "Enable Vulkan rendering backend" ON)
option(ENABLE_METAL "Enable Metal rendering backend (if available)" ON)
option(ENABLE_LTO "Enable link-time optimization" OFF) option(ENABLE_LTO "Enable link-time optimization" OFF)
option(ENABLE_TESTS "Compile unit-tests" OFF) option(ENABLE_TESTS "Compile unit-tests" OFF)
option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF) option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF)
@ -400,6 +401,34 @@ if(ENABLE_VULKAN)
target_link_libraries(AlberCore PRIVATE Vulkan::Vulkan resources_renderer_vk) target_link_libraries(AlberCore PRIVATE Vulkan::Vulkan resources_renderer_vk)
endif() endif()
if(ENABLE_METAL AND APPLE)
set(RENDERER_MTL_INCLUDE_FILES include/renderer_mtl/renderer_mtl.hpp
)
set(RENDERER_MTL_SOURCE_FILES src/core/renderer_mtl/metal_cpp_impl.cpp
src/core/renderer_mtl/renderer_mtl.cpp
src/host_shaders/metal_display.metal
)
set(HEADER_FILES ${HEADER_FILES} ${RENDERER_MTL_INCLUDE_FILES})
source_group("Source Files\\Core\\Metal Renderer" FILES ${RENDERER_MTL_SOURCE_FILES})
# TODO: compile Metal shaders to .metallib
cmrc_add_resource_library(
resources_renderer_mtl
NAMESPACE RendererMTL
WHENCE "src/host_shaders/"
"src/host_shaders/metal_display.metal"
)
target_sources(AlberCore PRIVATE ${RENDERER_MTL_SOURCE_FILES})
target_compile_definitions(AlberCore PUBLIC "PANDA3DS_ENABLE_METAL=1")
target_include_directories(AlberCore PRIVATE third_party/metal-cpp)
# TODO: check if all of them are needed
target_link_libraries(AlberCore PRIVATE "-framework Metal" "-framework Foundation" "-framework QuartzCore" resources_renderer_mtl)
endif()
source_group("Header Files\\Core" FILES ${HEADER_FILES}) source_group("Header Files\\Core" FILES ${HEADER_FILES})
set(ALL_SOURCES ${SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES} set(ALL_SOURCES ${SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES}
${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES} ${APPLET_SOURCE_FILES} ${RENDERER_SW_SOURCE_FILES} ${PICA_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES} ${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES} ${APPLET_SOURCE_FILES} ${RENDERER_SW_SOURCE_FILES} ${PICA_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES}

View file

@ -136,7 +136,7 @@ namespace Audio {
const auto counter0 = dspRam.region0.frameCounter; const auto counter0 = dspRam.region0.frameCounter;
const auto counter1 = dspRam.region1.frameCounter; const auto counter1 = dspRam.region1.frameCounter;
// Handle wraparound cases first // HandleType wraparound cases first
if (counter0 == 0xffff && counter1 != 0xfffe) { if (counter0 == 0xffff && counter1 != 0xfffe) {
return 1; return 1;
} else if (counter1 == 0xffff && counter0 != 0xfffe) { } else if (counter1 == 0xffff && counter0 != 0xfffe) {

View file

@ -8,7 +8,7 @@
namespace Common { namespace Common {
class CapstoneDisassembler { class CapstoneDisassembler {
csh handle; // Handle to our disassembler object csh handle; // HandleType to our disassembler object
cs_insn* instructions = nullptr; // Pointer to instruction object cs_insn* instructions = nullptr; // Pointer to instruction object
bool initialized = false; bool initialized = false;

View file

@ -7,6 +7,7 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include "helpers.hpp" #include "helpers.hpp"
#include "memory.hpp" #include "memory.hpp"
#include "result.hpp" #include "result.hpp"
@ -55,7 +56,7 @@ namespace ArchiveID {
default: return "Unknown archive"; default: return "Unknown archive";
} }
} }
} } // namespace ArchiveID
struct FSPath { struct FSPath {
u32 type = PathType::Invalid; u32 type = PathType::Invalid;
@ -68,9 +69,7 @@ struct FSPath {
FSPath(u32 type, const std::vector<u8>& vec) : type(type) { FSPath(u32 type, const std::vector<u8>& vec) : type(type) {
switch (type) { switch (type) {
case PathType::Binary: case PathType::Binary: binary = std::move(vec); break;
binary = std::move(vec);
break;
case PathType::ASCII: case PathType::ASCII:
string.resize(vec.size() - 1); // -1 because of the null terminator string.resize(vec.size() - 1); // -1 because of the null terminator
@ -82,8 +81,8 @@ struct FSPath {
utf16_string.resize(size); utf16_string.resize(size);
std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16)); std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16));
break; break;
};
} }
; }
} }
}; };
@ -105,12 +104,12 @@ struct FileSession {
u32 priority = 0; // TODO: What does this even do u32 priority = 0; // TODO: What does this even do
bool isOpen; bool isOpen;
FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true) : FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true)
archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {} : archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {}
// For cloning a file session // For cloning a file session
FileSession(const FileSession& other) : archive(other.archive), path(other.path), FileSession(const FileSession& other)
archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {} : archive(other.archive), path(other.path), archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {}
}; };
struct ArchiveSession { struct ArchiveSession {
@ -165,7 +164,7 @@ public:
}; };
protected: protected:
using Handle = u32; using HandleType = u32;
static constexpr FileDescriptor NoFile = nullptr; static constexpr FileDescriptor NoFile = nullptr;
static constexpr FileDescriptor FileError = std::nullopt; static constexpr FileDescriptor FileError = std::nullopt;
@ -173,8 +172,8 @@ protected:
// Returns if a specified 3DS path in UTF16 or ASCII format is safe or not // Returns if a specified 3DS path in UTF16 or ASCII format is safe or not
// A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs // A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs
// And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory tree // And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory
// And access files outside of the emulator's app data folder // tree And access files outside of the emulator's app data folder
template <u32 format> template <u32 format>
bool isPathSafe(const FSPath& path) { bool isPathSafe(const FSPath& path) {
static_assert(format == PathType::ASCII || format == PathType::UTF16); static_assert(format == PathType::ASCII || format == PathType::UTF16);
@ -242,9 +241,7 @@ public:
return Err(Result::FS::FileNotFoundAlt); return Err(Result::FS::FileNotFoundAlt);
} }
virtual void format(const FSPath& path, const FormatInfo& info) { virtual void format(const FSPath& path, const FormatInfo& info) { Helpers::panic("Unimplemented Format for %s archive", name().c_str()); }
Helpers::panic("Unimplemented Format for %s archive", name().c_str());
}
virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) { virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) {
Helpers::panic("Unimplemented RenameFile for %s archive", name().c_str()); Helpers::panic("Unimplemented RenameFile for %s archive", name().c_str());

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "helpers.hpp" #include "helpers.hpp"
using Handle = u32; using HandleType = u32;
namespace KernelHandles { namespace KernelHandles {
enum : u32 { enum : u32 {
@ -50,7 +50,7 @@ namespace KernelHandles {
MinServiceHandle = AC, MinServiceHandle = AC,
MaxServiceHandle = Y2R, MaxServiceHandle = Y2R,
GSPSharedMemHandle = MaxServiceHandle + 1, // Handle for the GSP shared memory GSPSharedMemHandle = MaxServiceHandle + 1, // HandleType for the GSP shared memory
FontSharedMemHandle, FontSharedMemHandle,
CSNDSharedMemHandle, CSNDSharedMemHandle,
APTCaptureSharedMemHandle, // Shared memory for display capture info, APTCaptureSharedMemHandle, // Shared memory for display capture info,
@ -61,17 +61,13 @@ namespace KernelHandles {
}; };
// Returns whether "handle" belongs to one of the OS services // Returns whether "handle" belongs to one of the OS services
static constexpr bool isServiceHandle(Handle handle) { static constexpr bool isServiceHandle(HandleType handle) { return handle >= MinServiceHandle && handle <= MaxServiceHandle; }
return handle >= MinServiceHandle && handle <= MaxServiceHandle;
}
// Returns whether "handle" belongs to one of the OS services' shared memory areas // Returns whether "handle" belongs to one of the OS services' shared memory areas
static constexpr bool isSharedMemHandle(Handle handle) { static constexpr bool isSharedMemHandle(HandleType handle) { return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle; }
return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle;
}
// Returns the name of a handle as a string based on the given handle // Returns the name of a handle as a string based on the given handle
static const char* getServiceName(Handle handle) { static const char* getServiceName(HandleType handle) {
switch (handle) { switch (handle) {
case AC: return "AC"; case AC: return "AC";
case ACT: return "ACT"; case ACT: return "ACT";
@ -110,4 +106,4 @@ namespace KernelHandles {
default: return "Unknown"; default: return "Unknown";
} }
} }
} } // namespace KernelHandles

View file

@ -34,18 +34,18 @@ class Kernel {
static_assert(appResourceLimits.maxThreads <= 63, "The waitlist system is built on the premise that <= 63 threads max can be active"); static_assert(appResourceLimits.maxThreads <= 63, "The waitlist system is built on the premise that <= 63 threads max can be active");
std::vector<KernelObject> objects; std::vector<KernelObject> objects;
std::vector<Handle> portHandles; std::vector<HandleType> portHandles;
std::vector<Handle> mutexHandles; std::vector<HandleType> mutexHandles;
std::vector<Handle> timerHandles; std::vector<HandleType> timerHandles;
// Thread indices, sorted by priority // Thread indices, sorted by priority
std::vector<int> threadIndices; std::vector<int> threadIndices;
Handle currentProcess; HandleType currentProcess;
Handle mainThread; HandleType mainThread;
int currentThreadIndex; int currentThreadIndex;
Handle srvHandle; // Handle for the special service manager port "srv:" HandleType srvHandle; // HandleType for the special service manager port "srv:"
Handle errorPortHandle; // Handle for the err:f port used for displaying errors HandleType errorPortHandle; // HandleType for the err:f port used for displaying errors
u32 arbiterCount; u32 arbiterCount;
u32 threadCount; // How many threads in our thread pool have been used as of now (Up to 32) u32 threadCount; // How many threads in our thread pool have been used as of now (Up to 32)
@ -58,29 +58,29 @@ class Kernel {
// Shows whether a reschedule will be need // Shows whether a reschedule will be need
bool needReschedule = false; bool needReschedule = false;
Handle makeArbiter(); HandleType makeArbiter();
Handle makeProcess(u32 id); HandleType makeProcess(u32 id);
Handle makePort(const char* name); HandleType makePort(const char* name);
Handle makeSession(Handle port); HandleType makeSession(HandleType port);
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg,ThreadStatus status = ThreadStatus::Dormant); HandleType makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status = ThreadStatus::Dormant);
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission); HandleType makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
public: public:
// Needs to be public to be accessible to the APT/HID services // Needs to be public to be accessible to the APT/HID services
Handle makeEvent(ResetType resetType, Event::CallbackType callback = Event::CallbackType::None); HandleType makeEvent(ResetType resetType, Event::CallbackType callback = Event::CallbackType::None);
// Needs to be public to be accessible to the APT/DSP services // Needs to be public to be accessible to the APT/DSP services
Handle makeMutex(bool locked = false); HandleType makeMutex(bool locked = false);
// Needs to be public to be accessible to the service manager port // Needs to be public to be accessible to the service manager port
Handle makeSemaphore(u32 initialCount, u32 maximumCount); HandleType makeSemaphore(u32 initialCount, u32 maximumCount);
Handle makeTimer(ResetType resetType); HandleType makeTimer(ResetType resetType);
void pollTimers(); void pollTimers();
// Signals an event, returns true on success or false if the event does not exist // Signals an event, returns true on success or false if the event does not exist
bool signalEvent(Handle e); bool signalEvent(HandleType e);
// Run the callback for "special" events that have callbacks // Run the callback for "special" events that have callbacks
void runEventCallback(Event::CallbackType callback); void runEventCallback(Event::CallbackType callback);
void clearEvent(Handle e) { void clearEvent(HandleType e) {
KernelObject* object = getObject(e, KernelObjectType::Event); KernelObject* object = getObject(e, KernelObjectType::Event);
if (object != nullptr) { if (object != nullptr) {
object->getData<Event>()->fired = false; object->getData<Event>()->fired = false;
@ -99,19 +99,19 @@ public:
bool shouldWaitOnObject(KernelObject* object); bool shouldWaitOnObject(KernelObject* object);
void releaseMutex(Mutex* moo); void releaseMutex(Mutex* moo);
void cancelTimer(Timer* timer); void cancelTimer(Timer* timer);
void signalTimer(Handle timerHandle, Timer* timer); void signalTimer(HandleType timerHandle, Timer* timer);
u64 getWakeupTick(s64 ns); u64 getWakeupTick(s64 ns);
// Wake up the thread with the highest priority out of all threads in the waitlist // Wake up the thread with the highest priority out of all threads in the waitlist
// Returns the index of the woken up thread // Returns the index of the woken up thread
// Do not call this function with an empty waitlist!!! // Do not call this function with an empty waitlist!!!
int wakeupOneThread(u64 waitlist, Handle handle); int wakeupOneThread(u64 waitlist, HandleType handle);
void wakeupAllThreads(u64 waitlist, Handle handle); void wakeupAllThreads(u64 waitlist, HandleType handle);
std::optional<Handle> getPortHandle(const char* name); std::optional<HandleType> getPortHandle(const char* name);
void deleteObjectData(KernelObject& object); void deleteObjectData(KernelObject& object);
KernelObject* getProcessFromPID(Handle handle); KernelObject* getProcessFromPID(HandleType handle);
s32 getCurrentResourceValue(const KernelObject* limit, u32 resourceName); s32 getCurrentResourceValue(const KernelObject* limit, u32 resourceName);
u32 getMaxForResource(const KernelObject* limit, u32 resourceName); u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
u32 getTLSPointer(); u32 getTLSPointer();
@ -178,20 +178,20 @@ public:
void waitSynchronizationN(); void waitSynchronizationN();
// File operations // File operations
void handleFileOperation(u32 messagePointer, Handle file); void handleFileOperation(u32 messagePointer, HandleType file);
void closeFile(u32 messagePointer, Handle file); void closeFile(u32 messagePointer, HandleType file);
void flushFile(u32 messagePointer, Handle file); void flushFile(u32 messagePointer, HandleType file);
void readFile(u32 messagePointer, Handle file); void readFile(u32 messagePointer, HandleType file);
void writeFile(u32 messagePointer, Handle file); void writeFile(u32 messagePointer, HandleType file);
void getFileSize(u32 messagePointer, Handle file); void getFileSize(u32 messagePointer, HandleType file);
void openLinkFile(u32 messagePointer, Handle file); void openLinkFile(u32 messagePointer, HandleType file);
void setFileSize(u32 messagePointer, Handle file); void setFileSize(u32 messagePointer, HandleType file);
void setFilePriority(u32 messagePointer, Handle file); void setFilePriority(u32 messagePointer, HandleType file);
// Directory operations // Directory operations
void handleDirectoryOperation(u32 messagePointer, Handle directory); void handleDirectoryOperation(u32 messagePointer, HandleType directory);
void closeDirectory(u32 messagePointer, Handle directory); void closeDirectory(u32 messagePointer, HandleType directory);
void readDirectory(u32 messagePointer, Handle directory); void readDirectory(u32 messagePointer, HandleType directory);
public: public:
Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config); Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config);
@ -209,7 +209,7 @@ public:
} }
} }
Handle makeObject(KernelObjectType type) { HandleType makeObject(KernelObjectType type) {
if (handleCounter > KernelHandles::Max) [[unlikely]] { if (handleCounter > KernelHandles::Max) [[unlikely]] {
Helpers::panic("Hlep we somehow created enough kernel objects to overflow this thing"); Helpers::panic("Hlep we somehow created enough kernel objects to overflow this thing");
} }
@ -219,12 +219,10 @@ public:
return handleCounter++; return handleCounter++;
} }
std::vector<KernelObject>& getObjects() { std::vector<KernelObject>& getObjects() { return objects; }
return objects;
}
// Get pointer to the object with the specified handle // Get pointer to the object with the specified handle
KernelObject* getObject(Handle handle) { KernelObject* getObject(HandleType handle) {
// Accessing an object that has not been created // Accessing an object that has not been created
if (handle >= objects.size()) [[unlikely]] { if (handle >= objects.size()) [[unlikely]] {
return nullptr; return nullptr;
@ -234,7 +232,7 @@ public:
} }
// Get pointer to the object with the specified handle and type // Get pointer to the object with the specified handle and type
KernelObject* getObject(Handle handle, KernelObjectType type) { KernelObject* getObject(HandleType handle, KernelObjectType type) {
if (handle >= objects.size() || objects[handle].type != type) [[unlikely]] { if (handle >= objects.size() || objects[handle].type != type) [[unlikely]] {
return nullptr; return nullptr;
} }

View file

@ -1,23 +1,32 @@
#pragma once #pragma once
#include <array> #include <array>
#include <cstring> #include <cstring>
#include "fs/archive_base.hpp" #include "fs/archive_base.hpp"
#include "handles.hpp" #include "handles.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "result/result.hpp" #include "result/result.hpp"
enum class KernelObjectType : u8 { enum class KernelObjectType : u8 {
AddressArbiter, Archive, Directory, File, MemoryBlock, Process, ResourceLimit, Session, Dummy, AddressArbiter,
Archive,
Directory,
File,
MemoryBlock,
Process,
ResourceLimit,
Session,
Dummy,
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better // Bundle waitable objects together in the enum to let the compiler optimize certain checks better
Event, Mutex, Port, Semaphore, Timer, Thread Event,
Mutex,
Port,
Semaphore,
Timer,
Thread
}; };
enum class ResourceLimitCategory : int { enum class ResourceLimitCategory : int { Application = 0, SystemApplet = 1, LibraryApplet = 2, Misc = 3 };
Application = 0,
SystemApplet = 1,
LibraryApplet = 2,
Misc = 3
};
// Reset types (for use with events and timers) // Reset types (for use with events and timers)
enum class ResetType { enum class ResetType {
@ -26,13 +35,7 @@ enum class ResetType {
Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once. Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once.
}; };
enum class ArbitrationType { enum class ArbitrationType { Signal = 0, WaitIfLess = 1, DecrementAndWaitIfLess = 2, WaitIfLessTimeout = 3, DecrementAndWaitIfLessTimeout = 4 };
Signal = 0,
WaitIfLess = 1,
DecrementAndWaitIfLess = 2,
WaitIfLessTimeout = 3,
DecrementAndWaitIfLessTimeout = 4
};
enum class ProcessorID : s32 { enum class ProcessorID : s32 {
AllCPUs = -1, AllCPUs = -1,
@ -47,7 +50,7 @@ enum class ProcessorID : s32 {
struct AddressArbiter {}; struct AddressArbiter {};
struct ResourceLimits { struct ResourceLimits {
Handle handle; HandleType handle;
s32 currentCommit = 0; s32 currentCommit = 0;
}; };
@ -65,7 +68,8 @@ struct Event {
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled // Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
// This enum stores what kind of callback they should execute // This enum stores what kind of callback they should execute
enum class CallbackType : u32 { enum class CallbackType : u32 {
None, DSPSemaphore, None,
DSPSemaphore,
}; };
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
@ -91,8 +95,8 @@ struct Port {
}; };
struct Session { struct Session {
Handle portHandle; // The port this session is subscribed to HandleType portHandle; // The port this session is subscribed to
Session(Handle portHandle) : portHandle(portHandle) {} Session(HandleType portHandle) : portHandle(portHandle) {}
}; };
enum class ThreadStatus { enum class ThreadStatus {
@ -115,14 +119,14 @@ struct Thread {
u32 arg; u32 arg;
ProcessorID processorID; ProcessorID processorID;
ThreadStatus status; ThreadStatus status;
Handle handle; // OS handle for this thread HandleType handle; // OS handle for this thread
int index; // Index of the thread. 0 for the first thread, 1 for the second, and so on int index; // Index of the thread. 0 for the first thread, 1 for the second, and so on
// The waiting address for threads that are waiting on an AddressArbiter // The waiting address for threads that are waiting on an AddressArbiter
u32 waitingAddress; u32 waitingAddress;
// For WaitSynchronization(N): A vector of objects this thread is waiting for // For WaitSynchronization(N): A vector of objects this thread is waiting for
std::vector<Handle> waitList; std::vector<HandleType> waitList;
// For WaitSynchronizationN: Shows whether the object should wait for all objects in the wait list or just one // For WaitSynchronizationN: Shows whether the object should wait for all objects in the wait list or just one
bool waitAll; bool waitAll;
// For WaitSynchronizationN: The "out" pointer // For WaitSynchronizationN: The "out" pointer
@ -162,12 +166,12 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
struct Mutex { struct Mutex {
u64 waitlist; // Refer to the getWaitlist function below for documentation u64 waitlist; // Refer to the getWaitlist function below for documentation
Handle ownerThread = 0; // Index of the thread that holds the mutex if it's locked HandleType ownerThread = 0; // Index of the thread that holds the mutex if it's locked
Handle handle; // Handle of the mutex itself HandleType handle; // HandleType of the mutex itself
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked
bool locked; bool locked;
Mutex(bool lock, Handle handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {} Mutex(bool lock, HandleType handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {}
}; };
struct Semaphore { struct Semaphore {
@ -197,17 +201,17 @@ struct MemoryBlock {
u32 otherPermission = 0; u32 otherPermission = 0;
bool mapped = false; bool mapped = false;
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm)
mapped(false) {} : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), mapped(false) {}
}; };
// Generic kernel object class // Generic kernel object class
struct KernelObject { struct KernelObject {
Handle handle = 0; // A u32 the OS will use to identify objects HandleType handle = 0; // A u32 the OS will use to identify objects
void* data = nullptr; void* data = nullptr;
KernelObjectType type; KernelObjectType type;
KernelObject(Handle handle, KernelObjectType type) : handle(handle), type(type) {} KernelObject(HandleType handle, KernelObjectType type) : handle(handle), type(type) {}
// Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded // Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded
// Thus, the kernel needs to delete it when appropriate // Thus, the kernel needs to delete it when appropriate
@ -218,9 +222,7 @@ struct KernelObject {
return static_cast<T*>(data); return static_cast<T*>(data);
} }
const char* getTypeName() const { const char* getTypeName() const { return kernelObjectTypeToString(type); }
return kernelObjectTypeToString(type);
}
// Retrieves a reference to the waitlist for a specified object // Retrieves a reference to the waitlist for a specified object
// We return a reference because this function is only called in the kernel threading internals // We return a reference because this function is only called in the kernel threading internals
@ -238,8 +240,7 @@ struct KernelObject {
case KernelObjectType::Timer: return getData<Timer>()->waitlist; case KernelObjectType::Timer: return getData<Timer>()->waitlist;
// This should be unreachable once we fully implement sync objects // This should be unreachable once we fully implement sync objects
default: [[unlikely]] default: [[unlikely]] Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
} }
} }
}; };

View file

@ -10,8 +10,8 @@
#include "crypto/aes_engine.hpp" #include "crypto/aes_engine.hpp"
#include "handles.hpp" #include "handles.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "loader/ncsd.hpp"
#include "loader/3dsx.hpp" #include "loader/3dsx.hpp"
#include "loader/ncsd.hpp"
#include "services/region_codes.hpp" #include "services/region_codes.hpp"
namespace PhysicalAddrs { namespace PhysicalAddrs {
@ -86,8 +86,7 @@ namespace KernelMemoryTypes {
u32 state; u32 state;
u32 end() { return baseAddr + size; } u32 end() { return baseAddr + size; }
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size) MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size), perms(perms), state(state) {}
, perms(perms), state(state) {}
}; };
// Shared memory block for HID, GSP:GPU etc // Shared memory block for HID, GSP:GPU etc
@ -99,7 +98,7 @@ namespace KernelMemoryTypes {
SharedMemoryBlock(u32 paddr, u32 size, u32 handle) : paddr(paddr), size(size), handle(handle), mapped(false) {} SharedMemoryBlock(u32 paddr, u32 size, u32 handle) : paddr(paddr), size(size), handle(handle), mapped(false) {}
}; };
} } // namespace KernelMemoryTypes
class Memory { class Memory {
u8* fcram; u8* fcram;
@ -116,7 +115,9 @@ class Memory {
std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo; std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo;
std::array<SharedMemoryBlock, 5> sharedMemBlocks = { std::array<SharedMemoryBlock, 5> sharedMemBlocks = {
SharedMemoryBlock(0, 0, KernelHandles::FontSharedMemHandle), // Shared memory for the system font (size is 0 because we read the size from the cmrc filesystem SharedMemoryBlock(
0, 0, KernelHandles::FontSharedMemHandle
), // Shared memory for the system font (size is 0 because we read the size from the cmrc filesystem
SharedMemoryBlock(0, 0x1000, KernelHandles::GSPSharedMemHandle), // GSP shared memory SharedMemoryBlock(0, 0x1000, KernelHandles::GSPSharedMemHandle), // GSP shared memory
SharedMemoryBlock(0, 0x1000, KernelHandles::HIDSharedMemHandle), // HID shared memory SharedMemoryBlock(0, 0x1000, KernelHandles::HIDSharedMemHandle), // HID shared memory
SharedMemoryBlock(0, 0x3000, KernelHandles::CSNDSharedMemHandle), // CSND shared memory SharedMemoryBlock(0, 0x3000, KernelHandles::CSNDSharedMemHandle), // CSND shared memory
@ -197,24 +198,16 @@ private:
u8* getFCRAM() { return fcram; } u8* getFCRAM() { return fcram; }
// Total amount of OS-only FCRAM available (Can vary depending on how much FCRAM the app requests via the cart exheader) // Total amount of OS-only FCRAM available (Can vary depending on how much FCRAM the app requests via the cart exheader)
u32 totalSysFCRAM() { u32 totalSysFCRAM() { return FCRAM_SIZE - FCRAM_APPLICATION_SIZE; }
return FCRAM_SIZE - FCRAM_APPLICATION_SIZE;
}
// Amount of OS-only FCRAM currently available // Amount of OS-only FCRAM currently available
u32 remainingSysFCRAM() { u32 remainingSysFCRAM() { return totalSysFCRAM() - usedSystemMemory; }
return totalSysFCRAM() - usedSystemMemory;
}
// Physical FCRAM index to the start of OS FCRAM // Physical FCRAM index to the start of OS FCRAM
// We allocate the first part of physical FCRAM for the application, and the rest to the OS. So the index for the OS = application ram size // We allocate the first part of physical FCRAM for the application, and the rest to the OS. So the index for the OS = application ram size
u32 sysFCRAMIndex() { u32 sysFCRAMIndex() { return FCRAM_APPLICATION_SIZE; }
return FCRAM_APPLICATION_SIZE;
}
enum class BatteryLevel { enum class BatteryLevel { Empty = 0, AlmostEmpty, OneBar, TwoBars, ThreeBars, FourBars };
Empty = 0, AlmostEmpty, OneBar, TwoBars, ThreeBars, FourBars
};
u8 getBatteryState(bool adapterConnected, bool charging, BatteryLevel batteryLevel) { u8 getBatteryState(bool adapterConnected, bool charging, BatteryLevel batteryLevel) {
u8 value = static_cast<u8>(batteryLevel) << 2; // Bits 2:4 are the battery level from 0 to 5 u8 value = static_cast<u8>(batteryLevel) << 2; // Bits 2:4 are the battery level from 0 to 5
if (adapterConnected) value |= 1 << 0; // Bit 0 shows if the charger is connected if (adapterConnected) value |= 1 << 0; // Bit 0 shows if the charger is connected
@ -240,9 +233,7 @@ private:
} }
// Returns whether "addr" is aligned to a page (4096 byte) boundary // Returns whether "addr" is aligned to a page (4096 byte) boundary
static constexpr bool isAligned(u32 addr) { static constexpr bool isAligned(u32 addr) { return (addr & pageMask) == 0; }
return (addr & pageMask) == 0;
}
// Allocate "size" bytes of RAM starting from FCRAM index "paddr" (We pick it ourself if paddr == 0) // Allocate "size" bytes of RAM starting from FCRAM index "paddr" (We pick it ourself if paddr == 0)
// And map them to virtual address "vaddr" (We also pick it ourself if vaddr == 0). // And map them to virtual address "vaddr" (We also pick it ourself if vaddr == 0).
@ -253,8 +244,9 @@ private:
// isMap: Shows whether this is a reserve operation, that allocates memory and maps it to the addr space, or if it's a map operation, // isMap: Shows whether this is a reserve operation, that allocates memory and maps it to the addr space, or if it's a map operation,
// which just maps memory from paddr to vaddr without hassle. The latter is useful for shared memory mapping, the "map" ControlMemory, op, etc // which just maps memory from paddr to vaddr without hassle. The latter is useful for shared memory mapping, the "map" ControlMemory, op, etc
// Returns the vaddr the FCRAM was mapped to or nullopt if allocation failed // Returns the vaddr the FCRAM was mapped to or nullopt if allocation failed
std::optional<u32> allocateMemory(u32 vaddr, u32 paddr, u32 size, bool linear, bool r = true, bool w = true, bool x = true, std::optional<u32> allocateMemory(
bool adjustsAddrs = false, bool isMap = false); u32 vaddr, u32 paddr, u32 size, bool linear, bool r = true, bool w = true, bool x = true, bool adjustsAddrs = false, bool isMap = false
);
KernelMemoryTypes::MemoryInfo queryMemory(u32 vaddr); KernelMemoryTypes::MemoryInfo queryMemory(u32 vaddr);
// For internal use // For internal use
@ -266,7 +258,7 @@ private:
// The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for // The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for
// TODO: Find out // TODO: Find out
// Returns a pointer to the FCRAM block used for the memory if allocation succeeded // Returns a pointer to the FCRAM block used for the memory if allocation succeeded
u8* mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms); u8* mapSharedMemory(HandleType handle, u32 vaddr, u32 myPerms, u32 otherPerms);
// Mirrors the page mapping for "size" bytes starting from sourceAddress, to "size" bytes in destAddress // Mirrors the page mapping for "size" bytes starting from sourceAddress, to "size" bytes in destAddress
// All of the above must be page-aligned. // All of the above must be page-aligned.

View file

@ -119,9 +119,10 @@ class MainWindow : public QMainWindow {
void sendMessage(const EmulatorMessage& message); void sendMessage(const EmulatorMessage& message);
void dispatchMessage(const EmulatorMessage& message); void dispatchMessage(const EmulatorMessage& message);
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer // Tracks whether we are using an OpenGL-backed renderer, a Vulkan-backed renderer or a Metal-backed renderer
bool usingGL = false; bool usingGL = false;
bool usingVk = false; bool usingVk = false;
bool usingMtl = false;
// Variables to keep track of whether the user is controlling the 3DS analog stick with their keyboard // Variables to keep track of whether the user is controlling the 3DS analog stick with their keyboard
// This is done so when a gamepad is connected, we won't automatically override the 3DS analog stick settings with the gamepad's state // This is done so when a gamepad is connected, we won't automatically override the 3DS analog stick settings with the gamepad's state

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <span>
#include <optional> #include <optional>
#include <span>
#include "PICA/pica_vertex.hpp" #include "PICA/pica_vertex.hpp"
#include "PICA/regs.hpp" #include "PICA/regs.hpp"
@ -17,6 +17,7 @@ enum class RendererType : s8 {
OpenGL = 1, OpenGL = 1,
Vulkan = 2, Vulkan = 2,
Software = 3, Software = 3,
Metal = 4,
}; };
class GPU; class GPU;

View file

@ -0,0 +1,32 @@
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include "renderer.hpp"
class GPU;
class RendererMTL final : public Renderer {
public:
RendererMTL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
~RendererMTL() override;
void reset() override;
void display() override;
void initGraphicsContext(SDL_Window* window) override;
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override;
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override;
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
void screenshot(const std::string& name) override;
void deinitGraphicsContext() override;
#ifdef PANDA3DS_FRONTEND_QT
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {}
#endif
private:
CA::MetalLayer* metalLayer;
MTL::Device* device;
MTL::CommandQueue* commandQueue;
};

View file

@ -8,7 +8,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class ACService { class ACService {
Handle handle = KernelHandles::AC; HandleType handle = KernelHandles::AC;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, acLogger) MAKE_LOG_FUNCTION(log, acLogger)
@ -25,7 +25,7 @@ class ACService {
void setClientVersion(u32 messagePointer); void setClientVersion(u32 messagePointer);
bool connected = false; bool connected = false;
std::optional<Handle> disconnectEvent = std::nullopt; std::optional<HandleType> disconnectEvent = std::nullopt;
public: public:
ACService(Memory& mem) : mem(mem) {} ACService(Memory& mem) : mem(mem) {}

View file

@ -6,7 +6,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class ACTService { class ACTService {
Handle handle = KernelHandles::ACT; HandleType handle = KernelHandles::ACT;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, actLogger) MAKE_LOG_FUNCTION(log, actLogger)

View file

@ -6,7 +6,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class AMService { class AMService {
Handle handle = KernelHandles::AM; HandleType handle = KernelHandles::AM;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, amLogger) MAKE_LOG_FUNCTION(log, amLogger)

View file

@ -1,19 +1,17 @@
#pragma once #pragma once
#include <optional> #include <optional>
#include "applets/applet_manager.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "memory.hpp" #include "memory.hpp"
#include "result/result.hpp" #include "result/result.hpp"
#include "applets/applet_manager.hpp"
// Yay, more circular dependencies // Yay, more circular dependencies
class Kernel; class Kernel;
enum class ConsoleModel : u32 { enum class ConsoleModel : u32 { Old3DS, New3DS };
Old3DS, New3DS
};
// https://www.3dbrew.org/wiki/NS_and_APT_Services#Command // https://www.3dbrew.org/wiki/NS_and_APT_Services#Command
namespace APT::Transitions { namespace APT::Transitions {
@ -41,13 +39,13 @@ namespace APT::Transitions {
} }
class APTService { class APTService {
Handle handle = KernelHandles::APT; HandleType handle = KernelHandles::APT;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
std::optional<Handle> lockHandle = std::nullopt; std::optional<HandleType> lockHandle = std::nullopt;
std::optional<Handle> notificationEvent = std::nullopt; std::optional<HandleType> notificationEvent = std::nullopt;
std::optional<Handle> resumeEvent = std::nullopt; std::optional<HandleType> resumeEvent = std::nullopt;
ConsoleModel model = ConsoleModel::Old3DS; ConsoleModel model = ConsoleModel::Old3DS;
Applets::AppletManager appletManager; Applets::AppletManager appletManager;

View file

@ -6,7 +6,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class BOSSService { class BOSSService {
Handle handle = KernelHandles::BOSS; HandleType handle = KernelHandles::BOSS;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, bossLogger) MAKE_LOG_FUNCTION(log, bossLogger)
@ -35,6 +35,7 @@ class BOSSService {
void unregisterTask(u32 messagePointer); void unregisterTask(u32 messagePointer);
s8 optoutFlag; s8 optoutFlag;
public: public:
BOSSService(Memory& mem) : mem(mem) {} BOSSService(Memory& mem) : mem(mem) {}
void reset(); void reset();

View file

@ -12,7 +12,7 @@
class Kernel; class Kernel;
class CAMService { class CAMService {
using Event = std::optional<Handle>; using Event = std::optional<HandleType>;
struct Port { struct Port {
Event bufferErrorInterruptEvent = std::nullopt; Event bufferErrorInterruptEvent = std::nullopt;
@ -26,7 +26,7 @@ class CAMService {
} }
}; };
Handle handle = KernelHandles::CAM; HandleType handle = KernelHandles::CAM;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, camLogger) MAKE_LOG_FUNCTION(log, camLogger)

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <optional> #include <optional>
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
#include "logger.hpp" #include "logger.hpp"
@ -9,12 +10,12 @@
class Kernel; class Kernel;
class CECDService { class CECDService {
Handle handle = KernelHandles::CECD; HandleType handle = KernelHandles::CECD;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, cecdLogger) MAKE_LOG_FUNCTION(log, cecdLogger)
std::optional<Handle> infoEvent; std::optional<HandleType> infoEvent;
// Service commands // Service commands
void getInfoEventHandle(u32 messagePointer); void getInfoEventHandle(u32 messagePointer);

View file

@ -10,13 +10,13 @@
class Kernel; class Kernel;
class CSNDService { class CSNDService {
Handle handle = KernelHandles::CSND; HandleType handle = KernelHandles::CSND;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, csndLogger) MAKE_LOG_FUNCTION(log, csndLogger)
u8* sharedMemory = nullptr; u8* sharedMemory = nullptr;
std::optional<Handle> csndMutex = std::nullopt; std::optional<HandleType> csndMutex = std::nullopt;
size_t sharedMemSize = 0; size_t sharedMemSize = 0;
bool initialized = false; bool initialized = false;
@ -30,7 +30,5 @@ class CSNDService {
void reset(); void reset();
void handleSyncRequest(u32 messagePointer); void handleSyncRequest(u32 messagePointer);
void setSharedMemory(u8* ptr) { void setSharedMemory(u8* ptr) { sharedMemory = ptr; }
sharedMemory = ptr;
}
}; };

View file

@ -8,7 +8,7 @@
// Please forgive me for how everything in this file is named // Please forgive me for how everything in this file is named
// "dlp:SRVR" is not a nice name to work with // "dlp:SRVR" is not a nice name to work with
class DlpSrvrService { class DlpSrvrService {
Handle handle = KernelHandles::DLP_SRVR; HandleType handle = KernelHandles::DLP_SRVR;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, dlpSrvrLogger) MAKE_LOG_FUNCTION(log, dlpSrvrLogger)

View file

@ -14,7 +14,7 @@
class Kernel; class Kernel;
class DSPService { class DSPService {
Handle handle = KernelHandles::DSP; HandleType handle = KernelHandles::DSP;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
Audio::DSPCore* dsp = nullptr; Audio::DSPCore* dsp = nullptr;
@ -24,7 +24,7 @@ class DSPService {
static constexpr size_t pipeCount = 8; static constexpr size_t pipeCount = 8;
// DSP service event handles // DSP service event handles
using DSPEvent = std::optional<Handle>; using DSPEvent = std::optional<HandleType>;
DSPEvent semaphoreEvent; DSPEvent semaphoreEvent;
DSPEvent interrupt0; DSPEvent interrupt0;

View file

@ -16,7 +16,7 @@
class Kernel; class Kernel;
class FSService { class FSService {
Handle handle = KernelHandles::FS; HandleType handle = KernelHandles::FS;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
@ -38,9 +38,9 @@ class FSService {
SystemSaveDataArchive systemSaveData; SystemSaveDataArchive systemSaveData;
ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath); ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath);
Rust::Result<Handle, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path); Rust::Result<HandleType, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
Rust::Result<Handle, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path); Rust::Result<HandleType, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms); std::optional<HandleType> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
FSPath readPath(u32 type, u32 pointer, u32 size); FSPath readPath(u32 type, u32 pointer, u32 size);
const EmulatorConfig& config; const EmulatorConfig& config;

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstring> #include <cstring>
#include <optional> #include <optional>
#include "PICA/gpu.hpp" #include "PICA/gpu.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
@ -22,7 +23,7 @@ enum class GPUInterrupt : u8 {
class Kernel; class Kernel;
class GPUService { class GPUService {
Handle handle = KernelHandles::GPU; HandleType handle = KernelHandles::GPU;
Memory& mem; Memory& mem;
GPU& gpu; GPU& gpu;
Kernel& kernel; Kernel& kernel;
@ -32,7 +33,7 @@ class GPUService {
// At any point in time only 1 process has privileges to use rendering functions // At any point in time only 1 process has privileges to use rendering functions
// This is the PID of that process // This is the PID of that process
u32 privilegedProcess; u32 privilegedProcess;
std::optional<Handle> interruptEvent; std::optional<HandleType> interruptEvent;
// Number of threads registered via RegisterInterruptRelayQueue // Number of threads registered via RegisterInterruptRelayQueue
u32 gspThreadCount = 0; u32 gspThreadCount = 0;
@ -107,8 +108,7 @@ class GPUService {
FramebufferUpdate* getBottomFramebufferInfo() { return getFramebufferInfo(1); } FramebufferUpdate* getBottomFramebufferInfo() { return getFramebufferInfo(1); }
public: public:
GPUService(Memory& mem, GPU& gpu, Kernel& kernel, u32& currentPID) : mem(mem), gpu(gpu), GPUService(Memory& mem, GPU& gpu, Kernel& kernel, u32& currentPID) : mem(mem), gpu(gpu), kernel(kernel), currentPID(currentPID) {}
kernel(kernel), currentPID(currentPID) {}
void reset(); void reset();
void handleSyncRequest(u32 messagePointer); void handleSyncRequest(u32 messagePointer);
void requestInterrupt(GPUInterrupt type); void requestInterrupt(GPUInterrupt type);

View file

@ -6,7 +6,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class LCDService { class LCDService {
Handle handle = KernelHandles::LCD; HandleType handle = KernelHandles::LCD;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, gspLCDLogger) MAKE_LOG_FUNCTION(log, gspLCDLogger)

View file

@ -38,7 +38,7 @@ namespace HID::Keys {
class Kernel; class Kernel;
class HIDService { class HIDService {
Handle handle = KernelHandles::HID; HandleType handle = KernelHandles::HID;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
u8* sharedMem = nullptr; // Pointer to HID shared memory u8* sharedMem = nullptr; // Pointer to HID shared memory
@ -60,7 +60,7 @@ class HIDService {
bool gyroEnabled; bool gyroEnabled;
bool touchScreenPressed; bool touchScreenPressed;
std::array<std::optional<Handle>, 5> events; std::array<std::optional<HandleType>, 5> events;
MAKE_LOG_FUNCTION(log, hidLogger) MAKE_LOG_FUNCTION(log, hidLogger)
@ -141,9 +141,7 @@ class HIDService {
touchScreenPressed = true; touchScreenPressed = true;
} }
void releaseTouchScreen() { void releaseTouchScreen() { touchScreenPressed = false; }
touchScreenPressed = false;
}
bool isTouchScreenPressed() { return touchScreenPressed; } bool isTouchScreenPressed() { return touchScreenPressed; }
}; };

View file

@ -5,7 +5,7 @@
#include "memory.hpp" #include "memory.hpp"
class HTTPService { class HTTPService {
Handle handle = KernelHandles::HTTP; HandleType handle = KernelHandles::HTTP;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, httpLogger) MAKE_LOG_FUNCTION(log, httpLogger)

View file

@ -15,7 +15,7 @@ class IRUserService {
CirclePadPro = 1, CirclePadPro = 1,
}; };
Handle handle = KernelHandles::IR_USER; HandleType handle = KernelHandles::IR_USER;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, irUserLogger) MAKE_LOG_FUNCTION(log, irUserLogger)
@ -29,7 +29,7 @@ class IRUserService {
void requireConnection(u32 messagePointer); void requireConnection(u32 messagePointer);
void sendIrnop(u32 messagePointer); void sendIrnop(u32 messagePointer);
using IREvent = std::optional<Handle>; using IREvent = std::optional<HandleType>;
IREvent connectionStatusEvent = std::nullopt; IREvent connectionStatusEvent = std::nullopt;
IREvent receiveEvent = std::nullopt; IREvent receiveEvent = std::nullopt;

View file

@ -8,7 +8,7 @@
class Kernel; class Kernel;
class LDRService { class LDRService {
Handle handle = KernelHandles::LDR_RO; HandleType handle = KernelHandles::LDR_RO;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, ldrLogger) MAKE_LOG_FUNCTION(log, ldrLogger)

View file

@ -7,7 +7,7 @@
namespace MCU { namespace MCU {
class HWCService { class HWCService {
Handle handle = KernelHandles::MCU_HWC; HandleType handle = KernelHandles::MCU_HWC;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, mcuLogger) MAKE_LOG_FUNCTION(log, mcuLogger)

View file

@ -9,7 +9,7 @@
class Kernel; class Kernel;
class MICService { class MICService {
Handle handle = KernelHandles::MIC; HandleType handle = KernelHandles::MIC;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, micLogger) MAKE_LOG_FUNCTION(log, micLogger)
@ -34,7 +34,7 @@ class MICService {
bool shouldClamp = false; bool shouldClamp = false;
bool currentlySampling = false; bool currentlySampling = false;
std::optional<Handle> eventHandle; std::optional<HandleType> eventHandle;
public: public:
MICService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} MICService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}

View file

@ -8,7 +8,7 @@
class NDMService { class NDMService {
enum class ExclusiveState : u32 { None = 0, Infrastructure = 1, LocalComms = 2, StreetPass = 3, StreetPassData = 4 }; enum class ExclusiveState : u32 { None = 0, Infrastructure = 1, LocalComms = 2, StreetPass = 3, StreetPassData = 4 };
Handle handle = KernelHandles::NDM; HandleType handle = KernelHandles::NDM;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, ndmLogger) MAKE_LOG_FUNCTION(log, ndmLogger)

View file

@ -5,7 +5,7 @@
#include "memory.hpp" #include "memory.hpp"
class NewsUService { class NewsUService {
Handle handle = KernelHandles::NEWS_U; HandleType handle = KernelHandles::NEWS_U;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, newsLogger) MAKE_LOG_FUNCTION(log, newsLogger)

View file

@ -12,7 +12,7 @@
class Kernel; class Kernel;
class NFCService { class NFCService {
Handle handle = KernelHandles::NFC; HandleType handle = KernelHandles::NFC;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, nfcLogger) MAKE_LOG_FUNCTION(log, nfcLogger)
@ -34,7 +34,7 @@ class NFCService {
}; };
// Kernel events signaled when an NFC tag goes in and out of range respectively // Kernel events signaled when an NFC tag goes in and out of range respectively
std::optional<Handle> tagInRangeEvent, tagOutOfRangeEvent; std::optional<HandleType> tagInRangeEvent, tagOutOfRangeEvent;
AmiiboDevice device; AmiiboDevice device;
Old3DSAdapterStatus adapterStatus; Old3DSAdapterStatus adapterStatus;

View file

@ -6,7 +6,7 @@
#include "result/result.hpp" #include "result/result.hpp"
class NIMService { class NIMService {
Handle handle = KernelHandles::NIM; HandleType handle = KernelHandles::NIM;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, nimLogger) MAKE_LOG_FUNCTION(log, nimLogger)

View file

@ -10,13 +10,13 @@
class Kernel; class Kernel;
class NwmUdsService { class NwmUdsService {
Handle handle = KernelHandles::NWM_UDS; HandleType handle = KernelHandles::NWM_UDS;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, nwmUdsLogger) MAKE_LOG_FUNCTION(log, nwmUdsLogger)
bool initialized = false; bool initialized = false;
std::optional<Handle> eventHandle = std::nullopt; std::optional<HandleType> eventHandle = std::nullopt;
// Service commands // Service commands
void initializeWithVersion(u32 messagePointer); void initializeWithVersion(u32 messagePointer);

View file

@ -28,10 +28,10 @@
#include "services/mcu/mcu_hwc.hpp" #include "services/mcu/mcu_hwc.hpp"
#include "services/mic.hpp" #include "services/mic.hpp"
#include "services/ndm.hpp" #include "services/ndm.hpp"
#include "services/nwm_uds.hpp"
#include "services/news_u.hpp" #include "services/news_u.hpp"
#include "services/nfc.hpp" #include "services/nfc.hpp"
#include "services/nim.hpp" #include "services/nim.hpp"
#include "services/nwm_uds.hpp"
#include "services/ptm.hpp" #include "services/ptm.hpp"
#include "services/soc.hpp" #include "services/soc.hpp"
#include "services/ssl.hpp" #include "services/ssl.hpp"
@ -46,7 +46,7 @@ class ServiceManager {
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
std::optional<Handle> notificationSemaphore; std::optional<HandleType> notificationSemaphore;
MAKE_LOG_FUNCTION(log, srvLogger) MAKE_LOG_FUNCTION(log, srvLogger)
@ -97,7 +97,7 @@ class ServiceManager {
void handleSyncRequest(u32 messagePointer); void handleSyncRequest(u32 messagePointer);
// Forward a SendSyncRequest IPC message to the service with the respective handle // Forward a SendSyncRequest IPC message to the service with the respective handle
void sendCommandToService(u32 messagePointer, Handle handle); void sendCommandToService(u32 messagePointer, HandleType handle);
// Wrappers for communicating with certain services // Wrappers for communicating with certain services
void sendGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); } void sendGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); }

View file

@ -5,7 +5,7 @@
#include "memory.hpp" #include "memory.hpp"
class SOCService { class SOCService {
Handle handle = KernelHandles::SOC; HandleType handle = KernelHandles::SOC;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, socLogger) MAKE_LOG_FUNCTION(log, socLogger)

View file

@ -1,13 +1,13 @@
#pragma once #pragma once
#include <random>
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "memory.hpp" #include "memory.hpp"
#include <random>
class SSLService { class SSLService {
Handle handle = KernelHandles::SSL; HandleType handle = KernelHandles::SSL;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, sslLogger) MAKE_LOG_FUNCTION(log, sslLogger)

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <optional> #include <optional>
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
#include "logger.hpp" #include "logger.hpp"
@ -10,18 +11,15 @@
class Kernel; class Kernel;
class Y2RService { class Y2RService {
Handle handle = KernelHandles::Y2R; HandleType handle = KernelHandles::Y2R;
Memory& mem; Memory& mem;
Kernel& kernel; Kernel& kernel;
MAKE_LOG_FUNCTION(log, y2rLogger) MAKE_LOG_FUNCTION(log, y2rLogger)
std::optional<Handle> transferEndEvent; std::optional<HandleType> transferEndEvent;
bool transferEndInterruptEnabled; bool transferEndInterruptEnabled;
enum class BusyStatus : u32 { enum class BusyStatus : u32 { NotBusy = 0, Busy = 1 };
NotBusy = 0,
Busy = 1
};
enum class InputFormat : u32 { enum class InputFormat : u32 {
YUV422_Individual8 = 0, YUV422_Individual8 = 0,
@ -31,20 +29,10 @@ class Y2RService {
YUV422_Batch = 4, YUV422_Batch = 4,
}; };
enum class OutputFormat : u32 { enum class OutputFormat : u32 { RGB32 = 0, RGB24 = 1, RGB15 = 2, RGB565 = 3 };
RGB32 = 0,
RGB24 = 1,
RGB15 = 2,
RGB565 = 3
};
// Clockwise rotation // Clockwise rotation
enum class Rotation : u32 { enum class Rotation : u32 { None = 0, Rotate90 = 1, Rotate180 = 2, Rotate270 = 3 };
None = 0,
Rotate90 = 1,
Rotate180 = 2,
Rotate270 = 3
};
enum class BlockAlignment : u32 { enum class BlockAlignment : u32 {
Line = 0, // Output buffer's pixels are arranged linearly. Used when outputting to the framebuffer. Line = 0, // Output buffer's pixels are arranged linearly. Used when outputting to the framebuffer.

View file

@ -40,7 +40,7 @@ void CPU::runFrame() {
execute: execute:
const auto exitReason = jit->Run(); const auto exitReason = jit->Run();
// Handle any scheduler events that need handling. // HandleType any scheduler events that need handling.
emu.pollScheduler(); emu.pollScheduler();
if (static_cast<u32>(exitReason) != 0) [[unlikely]] { if (static_cast<u32>(exitReason) != 0) [[unlikely]] {

View file

@ -1,12 +1,13 @@
#if defined(PANDA3DS_DYNAPICA_SUPPORTED) && defined(PANDA3DS_X64_HOST) #if defined(PANDA3DS_DYNAPICA_SUPPORTED) && defined(PANDA3DS_X64_HOST)
#include "PICA/dynapica/shader_rec_emitter_x64.hpp" #include "PICA/dynapica/shader_rec_emitter_x64.hpp"
#include <immintrin.h>
#include <smmintrin.h>
#include <algorithm> #include <algorithm>
#include <bit> #include <bit>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <immintrin.h>
#include <smmintrin.h>
using namespace Xbyak; using namespace Xbyak;
using namespace Xbyak::util; using namespace Xbyak::util;
@ -41,9 +42,15 @@ void ShaderEmitter::compile(const PICAShader& shaderUnit) {
// Constants // Constants
align(16); align(16);
L(negateVector); L(negateVector);
dd(0x80000000); dd(0x80000000); dd(0x80000000); dd(0x80000000); // -0.0 4 times dd(0x80000000);
dd(0x80000000);
dd(0x80000000);
dd(0x80000000); // -0.0 4 times
L(onesVector); L(onesVector);
dd(0x3f800000); dd(0x3f800000); dd(0x3f800000); dd(0x3f800000); // 1.0 4 times dd(0x3f800000);
dd(0x3f800000);
dd(0x3f800000);
dd(0x3f800000); // 1.0 4 times
// Emit prologue first // Emit prologue first
align(16); align(16);
@ -129,23 +136,15 @@ void ShaderEmitter::compileInstruction(const PICAShader& shaderUnit) {
switch (opcode) { switch (opcode) {
case ShaderOpcodes::ADD: recADD(shaderUnit, instruction); break; case ShaderOpcodes::ADD: recADD(shaderUnit, instruction); break;
case ShaderOpcodes::CALL: case ShaderOpcodes::CALL: recCALL(shaderUnit, instruction); break;
recCALL(shaderUnit, instruction); case ShaderOpcodes::CALLC: recCALLC(shaderUnit, instruction); break;
break; case ShaderOpcodes::CALLU: recCALLU(shaderUnit, instruction); break;
case ShaderOpcodes::CALLC: case ShaderOpcodes::CMP1:
recCALLC(shaderUnit, instruction); case ShaderOpcodes::CMP2: recCMP(shaderUnit, instruction); break;
break;
case ShaderOpcodes::CALLU:
recCALLU(shaderUnit, instruction);
break;
case ShaderOpcodes::CMP1: case ShaderOpcodes::CMP2:
recCMP(shaderUnit, instruction);
break;
case ShaderOpcodes::DP3: recDP3(shaderUnit, instruction); break; case ShaderOpcodes::DP3: recDP3(shaderUnit, instruction); break;
case ShaderOpcodes::DP4: recDP4(shaderUnit, instruction); break; case ShaderOpcodes::DP4: recDP4(shaderUnit, instruction); break;
case ShaderOpcodes::DPH: case ShaderOpcodes::DPH:
case ShaderOpcodes::DPHI: case ShaderOpcodes::DPHI: recDPH(shaderUnit, instruction); break;
recDPH(shaderUnit, instruction); break;
case ShaderOpcodes::END: recEND(shaderUnit, instruction); break; case ShaderOpcodes::END: recEND(shaderUnit, instruction); break;
case ShaderOpcodes::EX2: recEX2(shaderUnit, instruction); break; case ShaderOpcodes::EX2: recEX2(shaderUnit, instruction); break;
case ShaderOpcodes::FLR: recFLR(shaderUnit, instruction); break; case ShaderOpcodes::FLR: recFLR(shaderUnit, instruction); break;
@ -176,21 +175,30 @@ void ShaderEmitter::compileInstruction(const PICAShader& shaderUnit) {
case ShaderOpcodes::BREAKC: Helpers::warn("[Shader JIT] Unimplemented BREAK(C) instruction!"); break; case ShaderOpcodes::BREAKC: Helpers::warn("[Shader JIT] Unimplemented BREAK(C) instruction!"); break;
// We consider both MAD and MADI to be the same instruction and decode which one we actually have in recMAD // We consider both MAD and MADI to be the same instruction and decode which one we actually have in recMAD
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x30:
case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: case 0x31:
recMAD(shaderUnit, instruction); case 0x32:
break; case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F: recMAD(shaderUnit, instruction); break;
case ShaderOpcodes::SLT: case ShaderOpcodes::SLT:
case ShaderOpcodes::SLTI: case ShaderOpcodes::SLTI: recSLT(shaderUnit, instruction); break;
recSLT(shaderUnit, instruction); break;
case ShaderOpcodes::SGE: case ShaderOpcodes::SGE:
case ShaderOpcodes::SGEI: case ShaderOpcodes::SGEI: recSGE(shaderUnit, instruction); break;
recSGE(shaderUnit, instruction); break;
default: default: Helpers::panic("Shader JIT: Unimplemented PICA opcode %X", opcode);
Helpers::panic("Shader JIT: Unimplemented PICA opcode %X", opcode);
} }
} }
@ -225,23 +233,24 @@ void ShaderEmitter::loadRegister(Xmm dest, const PICAShader& shader, u32 src, u3
if constexpr (sourceIndex == 1) { // SRC1 if constexpr (sourceIndex == 1) { // SRC1
negate = (getBit<4>(operandDescriptor)) != 0; negate = (getBit<4>(operandDescriptor)) != 0;
compSwizzle = getBits<5, 8>(operandDescriptor); compSwizzle = getBits<5, 8>(operandDescriptor);
} } else if constexpr (sourceIndex == 2) { // SRC2
else if constexpr (sourceIndex == 2) { // SRC2
negate = (getBit<13>(operandDescriptor)) != 0; negate = (getBit<13>(operandDescriptor)) != 0;
compSwizzle = getBits<14, 8>(operandDescriptor); compSwizzle = getBits<14, 8>(operandDescriptor);
} } else if constexpr (sourceIndex == 3) { // SRC3
else if constexpr (sourceIndex == 3) { // SRC3
negate = (getBit<22>(operandDescriptor)) != 0; negate = (getBit<22>(operandDescriptor)) != 0;
compSwizzle = getBits<23, 8>(operandDescriptor); compSwizzle = getBits<23, 8>(operandDescriptor);
} }
// TODO: Do indexes get applied if src < 0x20? // TODO: Do indexes get applied if src < 0x20?
// PICA has the swizzle descriptor inverted in comparison to x86. For the PICA, the descriptor is (lowest to highest bits) wzyx while it's xyzw for x86 // PICA has the swizzle descriptor inverted in comparison to x86. For the PICA, the descriptor is (lowest to highest bits) wzyx while it's xyzw
u32 convertedSwizzle = ((compSwizzle >> 6) & 0b11) | (((compSwizzle >> 4) & 0b11) << 2) | (((compSwizzle >> 2) & 0b11) << 4) | ((compSwizzle & 0b11) << 6); // for x86
u32 convertedSwizzle =
((compSwizzle >> 6) & 0b11) | (((compSwizzle >> 4) & 0b11) << 2) | (((compSwizzle >> 2) & 0b11) << 4) | ((compSwizzle & 0b11) << 6);
switch (index) { switch (index) {
case 0: [[likely]] { // Keep src as is, no need to offset it case 0:
[[likely]] { // Keep src as is, no need to offset it
const vec4f& srcRef = getSourceRef(shader, src); const vec4f& srcRef = getSourceRef(shader, src);
const uintptr_t offset = uintptr_t(&srcRef) - uintptr_t(&shader); // Calculate offset of register from start of the state struct const uintptr_t offset = uintptr_t(&srcRef) - uintptr_t(&shader); // Calculate offset of register from start of the state struct
@ -275,8 +284,7 @@ void ShaderEmitter::loadRegister(Xmm dest, const PICAShader& shader, u32 src, u3
break; break;
} }
default: default: Helpers::panic("[ShaderJIT]: Unimplemented source index type %d", index);
Helpers::panic("[ShaderJIT]: Unimplemented source index type %d", index);
} }
// Swizzle and load register into dest, from [state pointer + rcx + offset] and apply the relevant swizzle // Swizzle and load register into dest, from [state pointer + rcx + offset] and apply the relevant swizzle
@ -368,13 +376,12 @@ void ShaderEmitter::storeRegister(Xmm source, const PICAShader& shader, u32 dest
movaps(xword[statePointer + offset], temp); // Write back movaps(xword[statePointer + offset], temp); // Write back
} else { } else {
// Blend algo referenced from Citra // Blend algo referenced from Citra
const u8 selector = (((writeMask & 0b1000) ? 1 : 0) << 0) | const u8 selector = (((writeMask & 0b1000) ? 1 : 0) << 0) | (((writeMask & 0b0100) ? 3 : 2) << 2) | (((writeMask & 0b0010) ? 0 : 1) << 4) |
(((writeMask & 0b0100) ? 3 : 2) << 2) |
(((writeMask & 0b0010) ? 0 : 1) << 4) |
(((writeMask & 0b0001) ? 2 : 3) << 6); (((writeMask & 0b0001) ? 2 : 3) << 6);
// Reorder instructions based on whether the source == scratch1. This is to avoid overwriting scratch1 if it's the source, // Reorder instructions based on whether the source == scratch1. This is to avoid overwriting scratch1 if it's the source,
// While also having the memory load come first to mitigate execution hazards and give the load more time to complete before reading if possible // While also having the memory load come first to mitigate execution hazards and give the load more time to complete before reading if
// possible
if (source != scratch1) { if (source != scratch1) {
movaps(scratch1, xword[statePointer + offset]); movaps(scratch1, xword[statePointer + offset]);
movaps(scratch2, source); movaps(scratch2, source);
@ -399,7 +406,8 @@ void ShaderEmitter::checkCmpRegister(const PICAShader& shader, u32 instruction)
const uint refY = getBit<24>(instruction); const uint refY = getBit<24>(instruction);
const uint refX = getBit<25>(instruction); const uint refX = getBit<25>(instruction);
// refX in the bottom byte, refY in the top byte. This is done for condition codes 0 and 1 which check both x and y, so we can emit a single instruction that checks both // refX in the bottom byte, refY in the top byte. This is done for condition codes 0 and 1 which check both x and y, so we can emit a single
// instruction that checks both
const u16 refX_refY_merged = refX | (refY << 8); const u16 refX_refY_merged = refX | (refY << 8);
switch (condition) { switch (condition) {
@ -491,12 +499,10 @@ void ShaderEmitter::recMOVA(const PICAShader& shader, u32 instruction) {
if (writeX && writeY) { if (writeX && writeY) {
cvttps2dq(scratch1, src1_xmm); // Convert all lanes of src1 with truncation cvttps2dq(scratch1, src1_xmm); // Convert all lanes of src1 with truncation
movsd(qword[statePointer + addrRegisterOffset], scratch1); // Write back bottom 2 to addr register x and ys movsd(qword[statePointer + addrRegisterOffset], scratch1); // Write back bottom 2 to addr register x and ys
} } else if (writeX) {
else if (writeX) {
cvttss2si(eax, src1_xmm); // Convert bottom lane cvttss2si(eax, src1_xmm); // Convert bottom lane
mov(dword[statePointer + addrRegisterOffset], eax); // Write it back mov(dword[statePointer + addrRegisterOffset], eax); // Write it back
} } else if (writeY) {
else if (writeY) {
psrldq(src1_xmm, sizeof(float)); // Shift y component to bottom lane psrldq(src1_xmm, sizeof(float)); // Shift y component to bottom lane
cvttss2si(eax, src1_xmm); // Convert bottom lane cvttss2si(eax, src1_xmm); // Convert bottom lane
mov(dword[statePointer + addrRegisterYOffset], eax); // Write it back to y component mov(dword[statePointer + addrRegisterYOffset], eax); // Write it back to y component
@ -731,17 +737,7 @@ void ShaderEmitter::recCMP(const PICAShader& shader, u32 instruction) {
loadRegister<2>(src2_xmm, shader, src2, 0, operandDescriptor); loadRegister<2>(src2_xmm, shader, src2, 0, operandDescriptor);
// Condition codes for cmpps // Condition codes for cmpps
enum : u8 { enum : u8 { CMP_EQ = 0, CMP_LT = 1, CMP_LE = 2, CMP_UNORD = 3, CMP_NEQ = 4, CMP_NLT = 5, CMP_NLE = 6, CMP_ORD = 7, CMP_TRUE = 15 };
CMP_EQ = 0,
CMP_LT = 1,
CMP_LE = 2,
CMP_UNORD = 3,
CMP_NEQ = 4,
CMP_NLT = 5,
CMP_NLE = 6,
CMP_ORD = 7,
CMP_TRUE = 15
};
// Map from PICA condition codes (used as index) to x86 condition codes // Map from PICA condition codes (used as index) to x86 condition codes
static constexpr std::array<u8, 8> conditionCodes = {CMP_EQ, CMP_NEQ, CMP_LT, CMP_LE, CMP_LT, CMP_LE, CMP_TRUE, CMP_TRUE}; static constexpr std::array<u8, 8> conditionCodes = {CMP_EQ, CMP_NEQ, CMP_LT, CMP_LE, CMP_LT, CMP_LE, CMP_TRUE, CMP_TRUE};
@ -1147,7 +1143,7 @@ Xbyak::Label ShaderEmitter::emitExp2Func() {
align(16); align(16);
L(subroutine); L(subroutine);
// Handle edge cases // HandleType edge cases
ucomiss(src1_xmm, src1_xmm); ucomiss(src1_xmm, src1_xmm);
jp(retLabel); jp(retLabel);

View file

@ -15,6 +15,9 @@
#ifdef PANDA3DS_ENABLE_VULKAN #ifdef PANDA3DS_ENABLE_VULKAN
#include "renderer_vk/renderer_vk.hpp" #include "renderer_vk/renderer_vk.hpp"
#endif #endif
#ifdef PANDA3DS_ENABLE_METAL
#include "renderer_mtl/renderer_mtl.hpp"
#endif
constexpr u32 topScreenWidth = 240; constexpr u32 topScreenWidth = 240;
constexpr u32 topScreenHeight = 400; constexpr u32 topScreenHeight = 400;
@ -52,6 +55,12 @@ GPU::GPU(Memory& mem, EmulatorConfig& config) : mem(mem), config(config) {
renderer.reset(new RendererVK(*this, regs, externalRegs)); renderer.reset(new RendererVK(*this, regs, externalRegs));
break; break;
} }
#endif
#ifdef PANDA3DS_ENABLE_METAL
case RendererType::Metal: {
renderer.reset(new RendererMTL(*this, regs, externalRegs));
break;
}
#endif #endif
default: { default: {
Helpers::panic("Rendering backend not supported: %s", Renderer::typeToString(config.rendererType)); Helpers::panic("Rendering backend not supported: %s", Renderer::typeToString(config.rendererType));

View file

@ -232,7 +232,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
const u32 primType = getBits<8, 2>(primConfig); const u32 primType = getBits<8, 2>(primConfig);
// If we've reached 3 verts, issue a draw call // If we've reached 3 verts, issue a draw call
// Handle rendering depending on the primitive type // HandleType rendering depending on the primitive type
if (immediateModeVertIndex == 3) { if (immediateModeVertIndex == 3) {
renderer->drawVertices(PICA::PrimType::TriangleList, immediateModeVertices); renderer->drawVertices(PICA::PrimType::TriangleList, immediateModeVertices);

View file

@ -77,8 +77,8 @@ void PICAShader::run() {
default: Helpers::panic("Unimplemented PICA instruction %08X (Opcode = %02X)", instruction, opcode); default: Helpers::panic("Unimplemented PICA instruction %08X (Opcode = %02X)", instruction, opcode);
} }
// Handle control flow statements. The ordering is important as the priority goes: LOOP > IF > CALL // HandleType control flow statements. The ordering is important as the priority goes: LOOP > IF > CALL
// Handle loop // HandleType loop
if (loopIndex != 0) { if (loopIndex != 0) {
auto& loop = loopInfo[loopIndex - 1]; auto& loop = loopInfo[loopIndex - 1];
if (pc == loop.endingPC) { // Check if the loop needs to start over if (pc == loop.endingPC) { // Check if the loop needs to start over
@ -91,7 +91,7 @@ void PICAShader::run() {
} }
} }
// Handle ifs // HandleType ifs
if (ifIndex != 0) { if (ifIndex != 0) {
auto& info = conditionalInfo[ifIndex - 1]; auto& info = conditionalInfo[ifIndex - 1];
if (pc == info.endingPC) { // Check if the IF block ended if (pc == info.endingPC) { // Check if the IF block ended
@ -100,7 +100,7 @@ void PICAShader::run() {
} }
} }
// Handle calls // HandleType calls
if (callIndex != 0) { if (callIndex != 0) {
auto& info = callInfo[callIndex - 1]; auto& info = callInfo[callIndex - 1];
if (pc == info.endingPC) { // Check if the CALL block ended if (pc == info.endingPC) { // Check if the CALL block ended

View file

@ -12,34 +12,36 @@ static const char* arbitrationTypeToString(u32 type) {
} }
} }
Handle Kernel::makeArbiter() { HandleType Kernel::makeArbiter() {
if (arbiterCount >= appResourceLimits.maxAddressArbiters) { if (arbiterCount >= appResourceLimits.maxAddressArbiters) {
Helpers::panic("Overflowed the number of address arbiters"); Helpers::panic("Overflowed the number of address arbiters");
} }
arbiterCount++; arbiterCount++;
Handle ret = makeObject(KernelObjectType::AddressArbiter); HandleType ret = makeObject(KernelObjectType::AddressArbiter);
objects[ret].data = new AddressArbiter(); objects[ret].data = new AddressArbiter();
return ret; return ret;
} }
// Result CreateAddressArbiter(Handle* arbiter) // Result CreateAddressArbiter(HandleType* arbiter)
void Kernel::createAddressArbiter() { void Kernel::createAddressArbiter() {
logSVC("CreateAddressArbiter\n"); logSVC("CreateAddressArbiter\n");
regs[0] = Result::Success; regs[0] = Result::Success;
regs[1] = makeArbiter(); regs[1] = makeArbiter();
} }
// Result ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds) // Result ArbitrateAddress(HandleType arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds)
void Kernel::arbitrateAddress() { void Kernel::arbitrateAddress() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
const u32 address = regs[1]; const u32 address = regs[1];
const u32 type = regs[2]; const u32 type = regs[2];
const s32 value = s32(regs[3]); const s32 value = s32(regs[3]);
const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32)); const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32));
logSVC("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address, logSVC(
arbitrationTypeToString(type), value, ns); "ArbitrateAddress(HandleType = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address, arbitrationTypeToString(type),
value, ns
);
const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter); const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter);
if (arbiter == nullptr) [[unlikely]] { if (arbiter == nullptr) [[unlikely]] {
@ -79,12 +81,9 @@ void Kernel::arbitrateAddress() {
break; break;
} }
case ArbitrationType::Signal: case ArbitrationType::Signal: signalArbiter(address, value); break;
signalArbiter(address, value);
break;
default: default: Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
} }
requireReschedule(); requireReschedule();
@ -92,7 +91,8 @@ void Kernel::arbitrateAddress() {
// Signal up to "threadCount" threads waiting on the arbiter indicated by "waitingAddress" // Signal up to "threadCount" threads waiting on the arbiter indicated by "waitingAddress"
void Kernel::signalArbiter(u32 waitingAddress, s32 threadCount) { void Kernel::signalArbiter(u32 waitingAddress, s32 threadCount) {
if (threadCount == 0) [[unlikely]] return; if (threadCount == 0) [[unlikely]]
return;
s32 count = 0; // Number of threads we've woken up s32 count = 0; // Number of threads we've woken up
// Wake threads with the highest priority threads being woken up first // Wake threads with the highest priority threads being woken up first

View file

@ -8,10 +8,7 @@
#include "kernel.hpp" #include "kernel.hpp"
namespace DirectoryOps { namespace DirectoryOps {
enum : u32 { enum : u32 { Read = 0x08010042, Close = 0x08020000 };
Read = 0x08010042,
Close = 0x08020000
};
} }
// Helper to convert std::string to an 8.3 filename to mimic how Directory::Read works // Helper to convert std::string to an 8.3 filename to mimic how Directory::Read works
@ -87,7 +84,7 @@ Filename83 convertTo83(const std::string& path) {
return {filename, extension}; return {filename, extension};
} }
void Kernel::handleDirectoryOperation(u32 messagePointer, Handle directory) { void Kernel::handleDirectoryOperation(u32 messagePointer, HandleType directory) {
const u32 cmd = mem.read32(messagePointer); const u32 cmd = mem.read32(messagePointer);
switch (cmd) { switch (cmd) {
case DirectoryOps::Close: closeDirectory(messagePointer, directory); break; case DirectoryOps::Close: closeDirectory(messagePointer, directory); break;
@ -96,7 +93,7 @@ void Kernel::handleDirectoryOperation(u32 messagePointer, Handle directory) {
} }
} }
void Kernel::closeDirectory(u32 messagePointer, Handle directory) { void Kernel::closeDirectory(u32 messagePointer, HandleType directory) {
logFileIO("Closed directory %X\n", directory); logFileIO("Closed directory %X\n", directory);
const auto p = getObject(directory, KernelObjectType::Directory); const auto p = getObject(directory, KernelObjectType::Directory);
@ -109,7 +106,7 @@ void Kernel::closeDirectory(u32 messagePointer, Handle directory) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
void Kernel::readDirectory(u32 messagePointer, Handle directory) { void Kernel::readDirectory(u32 messagePointer, HandleType directory) {
const u32 entryCount = mem.read32(messagePointer + 4); const u32 entryCount = mem.read32(messagePointer + 4);
const u32 outPointer = mem.read32(messagePointer + 12); const u32 outPointer = mem.read32(messagePointer + 12);
logFileIO("Directory::Read (handle = %X, entry count = %d, out pointer = %08X)\n", directory, entryCount, outPointer); logFileIO("Directory::Read (handle = %X, entry count = %d, out pointer = %08X)\n", directory, entryCount, outPointer);

View file

@ -1,33 +1,20 @@
#include "kernel.hpp" #include "kernel.hpp"
namespace Commands { namespace Commands {
enum : u32 { enum : u32 { Throw = 0x00010800 };
Throw = 0x00010800
};
} }
namespace FatalErrorType { namespace FatalErrorType {
enum : u32 { enum : u32 { Generic = 0, Corrupted = 1, CardRemoved = 2, Exception = 3, ResultFailure = 4, Logged = 5 };
Generic = 0,
Corrupted = 1,
CardRemoved = 2,
Exception = 3,
ResultFailure = 4,
Logged = 5
};
} }
// Handle SendSyncRequest targetting the err:f port // HandleType SendSyncRequest targetting the err:f port
void Kernel::handleErrorSyncRequest(u32 messagePointer) { void Kernel::handleErrorSyncRequest(u32 messagePointer) {
u32 cmd = mem.read32(messagePointer); u32 cmd = mem.read32(messagePointer);
switch (cmd) { switch (cmd) {
case Commands::Throw: case Commands::Throw: throwError(messagePointer); break;
throwError(messagePointer);
break;
default: default: Helpers::panic("Unimplemented err:f command %08X\n", cmd); break;
Helpers::panic("Unimplemented err:f command %08X\n", cmd);
break;
} }
} }

View file

@ -1,8 +1,9 @@
#include "kernel.hpp"
#include "cpu.hpp"
#include <bit> #include <bit>
#include <utility> #include <utility>
#include "cpu.hpp"
#include "kernel.hpp"
const char* Kernel::resetTypeToString(u32 type) { const char* Kernel::resetTypeToString(u32 type) {
switch (type) { switch (type) {
case 0: return "One shot"; case 0: return "One shot";
@ -12,13 +13,13 @@ const char* Kernel::resetTypeToString(u32 type) {
} }
} }
Handle Kernel::makeEvent(ResetType resetType, Event::CallbackType callback) { HandleType Kernel::makeEvent(ResetType resetType, Event::CallbackType callback) {
Handle ret = makeObject(KernelObjectType::Event); HandleType ret = makeObject(KernelObjectType::Event);
objects[ret].data = new Event(resetType, callback); objects[ret].data = new Event(resetType, callback);
return ret; return ret;
} }
bool Kernel::signalEvent(Handle handle) { bool Kernel::signalEvent(HandleType handle) {
KernelObject* object = getObject(handle, KernelObjectType::Event); KernelObject* object = getObject(handle, KernelObjectType::Event);
if (object == nullptr) [[unlikely]] { if (object == nullptr) [[unlikely]] {
Helpers::panic("Tried to signal non-existent event"); Helpers::panic("Tried to signal non-existent event");
@ -52,13 +53,12 @@ bool Kernel::signalEvent(Handle handle) {
return true; return true;
} }
// Result CreateEvent(Handle* event, ResetType resetType) // Result CreateEvent(HandleType* event, ResetType resetType)
void Kernel::svcCreateEvent() { void Kernel::svcCreateEvent() {
const u32 outPointer = regs[0]; const u32 outPointer = regs[0];
const u32 resetType = regs[1]; const u32 resetType = regs[1];
if (resetType > 2) if (resetType > 2) Helpers::panic("Invalid reset type for event %d", resetType);
Helpers::panic("Invalid reset type for event %d", resetType);
logSVC("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType)); logSVC("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType));
@ -66,9 +66,9 @@ void Kernel::svcCreateEvent() {
regs[1] = makeEvent(static_cast<ResetType>(resetType)); regs[1] = makeEvent(static_cast<ResetType>(resetType));
} }
// Result ClearEvent(Handle event) // Result ClearEvent(HandleType event)
void Kernel::svcClearEvent() { void Kernel::svcClearEvent() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
const auto event = getObject(handle, KernelObjectType::Event); const auto event = getObject(handle, KernelObjectType::Event);
logSVC("ClearEvent(event handle = %X)\n", handle); logSVC("ClearEvent(event handle = %X)\n", handle);
@ -82,9 +82,9 @@ void Kernel::svcClearEvent() {
regs[0] = Result::Success; regs[0] = Result::Success;
} }
// Result SignalEvent(Handle event) // Result SignalEvent(HandleType event)
void Kernel::svcSignalEvent() { void Kernel::svcSignalEvent() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
logSVC("SignalEvent(event handle = %X)\n", handle); logSVC("SignalEvent(event handle = %X)\n", handle);
KernelObject* object = getObject(handle, KernelObjectType::Event); KernelObject* object = getObject(handle, KernelObjectType::Event);
@ -98,9 +98,9 @@ void Kernel::svcSignalEvent() {
} }
} }
// Result WaitSynchronization1(Handle handle, s64 timeout_nanoseconds) // Result WaitSynchronization1(HandleType handle, s64 timeout_nanoseconds)
void Kernel::waitSynchronization1() { void Kernel::waitSynchronization1() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
const s64 ns = s64(u64(regs[2]) | (u64(regs[3]) << 32)); const s64 ns = s64(u64(regs[2]) | (u64(regs[3]) << 32));
logSVC("WaitSynchronization1(handle = %X, ns = %lld)\n", handle, ns); logSVC("WaitSynchronization1(handle = %X, ns = %lld)\n", handle, ns);
@ -141,7 +141,7 @@ void Kernel::waitSynchronization1() {
} }
} }
// Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds) // Result WaitSynchronizationN(s32* out, HandleType* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds)
void Kernel::waitSynchronizationN() { void Kernel::waitSynchronizationN() {
// TODO: Are these arguments even correct? // TODO: Are these arguments even correct?
s32 ns1 = regs[0]; s32 ns1 = regs[0];
@ -154,8 +154,7 @@ void Kernel::waitSynchronizationN() {
logSVC("WaitSynchronizationN (handle pointer: %08X, count: %d, timeout = %lld)\n", handles, handleCount, ns); logSVC("WaitSynchronizationN (handle pointer: %08X, count: %d, timeout = %lld)\n", handles, handleCount, ns);
if (handleCount <= 0) if (handleCount <= 0) Helpers::panic("WaitSyncN: Invalid handle count");
Helpers::panic("WaitSyncN: Invalid handle count");
// Temporary hack: Until we implement service sessions properly, don't bother sleeping when WaitSyncN targets a service handle // Temporary hack: Until we implement service sessions properly, don't bother sleeping when WaitSyncN targets a service handle
// This is necessary because a lot of games use WaitSyncN with eg the CECD service // This is necessary because a lot of games use WaitSyncN with eg the CECD service
@ -165,7 +164,7 @@ void Kernel::waitSynchronizationN() {
return; return;
} }
using WaitObject = std::pair<Handle, KernelObject*>; using WaitObject = std::pair<HandleType, KernelObject*>;
std::vector<WaitObject> waitObjects(handleCount); std::vector<WaitObject> waitObjects(handleCount);
// We don't actually need to wait if waitAll == true unless one of the objects is not ready // We don't actually need to wait if waitAll == true unless one of the objects is not ready
@ -177,8 +176,8 @@ void Kernel::waitSynchronizationN() {
s32 firstReadyObjectIndex = 0; s32 firstReadyObjectIndex = 0;
for (s32 i = 0; i < handleCount; i++) { for (s32 i = 0; i < handleCount; i++) {
Handle handle = mem.read32(handles); HandleType handle = mem.read32(handles);
handles += sizeof(Handle); handles += sizeof(HandleType);
auto object = getObject(handle); auto object = getObject(handle);
// Panic if one of the objects is not even an object // Panic if one of the objects is not even an object
@ -190,8 +189,7 @@ void Kernel::waitSynchronizationN() {
// Panic if one of the objects is not a valid sync object // Panic if one of the objects is not a valid sync object
if (!isWaitable(object)) [[unlikely]] { if (!isWaitable(object)) [[unlikely]] {
Helpers::panic("Tried to wait on a non waitable object in WaitSyncN. Type: %s, handle: %X\n", Helpers::panic("Tried to wait on a non waitable object in WaitSyncN. Type: %s, handle: %X\n", object->getTypeName(), handle);
object->getTypeName(), handle);
} }
if (shouldWaitOnObject(object)) { if (shouldWaitOnObject(object)) {

View file

@ -14,8 +14,7 @@ namespace FileOps {
}; };
} }
void Kernel::handleFileOperation(u32 messagePointer, HandleType file) {
void Kernel::handleFileOperation(u32 messagePointer, Handle file) {
const u32 cmd = mem.read32(messagePointer); const u32 cmd = mem.read32(messagePointer);
switch (cmd) { switch (cmd) {
case FileOps::Close: closeFile(messagePointer, file); break; case FileOps::Close: closeFile(messagePointer, file); break;
@ -30,7 +29,7 @@ void Kernel::handleFileOperation(u32 messagePointer, Handle file) {
} }
} }
void Kernel::closeFile(u32 messagePointer, Handle fileHandle) { void Kernel::closeFile(u32 messagePointer, HandleType fileHandle) {
logFileIO("Closed file %X\n", fileHandle); logFileIO("Closed file %X\n", fileHandle);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
@ -48,7 +47,7 @@ void Kernel::closeFile(u32 messagePointer, Handle fileHandle) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
void Kernel::flushFile(u32 messagePointer, Handle fileHandle) { void Kernel::flushFile(u32 messagePointer, HandleType fileHandle) {
logFileIO("Flushed file %X\n", fileHandle); logFileIO("Flushed file %X\n", fileHandle);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
@ -65,13 +64,12 @@ void Kernel::flushFile(u32 messagePointer, Handle fileHandle) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
void Kernel::readFile(u32 messagePointer, Handle fileHandle) { void Kernel::readFile(u32 messagePointer, HandleType fileHandle) {
u64 offset = mem.read64(messagePointer + 4); u64 offset = mem.read64(messagePointer + 4);
u32 size = mem.read32(messagePointer + 12); u32 size = mem.read32(messagePointer + 12);
u32 dataPointer = mem.read32(messagePointer + 20); u32 dataPointer = mem.read32(messagePointer + 20);
logFileIO("Trying to read %X bytes from file %X, starting from offset %llX into memory address %08X\n", logFileIO("Trying to read %X bytes from file %X, starting from offset %llX into memory address %08X\n", size, fileHandle, offset, dataPointer);
size, fileHandle, offset, dataPointer);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
if (p == nullptr) [[unlikely]] { if (p == nullptr) [[unlikely]] {
@ -85,7 +83,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
Helpers::panic("Tried to read closed file"); Helpers::panic("Tried to read closed file");
} }
// Handle files with their own file descriptors by just fread'ing the data // HandleType files with their own file descriptors by just fread'ing the data
if (file->fd) { if (file->fd) {
std::unique_ptr<u8[]> data(new u8[size]); std::unique_ptr<u8[]> data(new u8[size]);
IOFile f(file->fd); IOFile f(file->fd);
@ -94,8 +92,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
if (!success) { if (!success) {
Helpers::panic("Kernel::ReadFile with file descriptor failed"); Helpers::panic("Kernel::ReadFile with file descriptor failed");
} } else {
else {
for (size_t i = 0; i < bytesRead; i++) { for (size_t i = 0; i < bytesRead; i++) {
mem.write8(u32(dataPointer + i), data[i]); mem.write8(u32(dataPointer + i), data[i]);
} }
@ -107,7 +104,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
return; return;
} }
// Handle files without their own FD, such as SelfNCCH files // HandleType files without their own FD, such as SelfNCCH files
auto archive = file->archive; auto archive = file->archive;
std::optional<u32> bytesRead = archive->readFile(file, offset, size, dataPointer); std::optional<u32> bytesRead = archive->readFile(file, offset, size, dataPointer);
if (!bytesRead.has_value()) { if (!bytesRead.has_value()) {
@ -118,14 +115,13 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
} }
} }
void Kernel::writeFile(u32 messagePointer, Handle fileHandle) { void Kernel::writeFile(u32 messagePointer, HandleType fileHandle) {
u64 offset = mem.read64(messagePointer + 4); u64 offset = mem.read64(messagePointer + 4);
u32 size = mem.read32(messagePointer + 12); u32 size = mem.read32(messagePointer + 12);
u32 writeOption = mem.read32(messagePointer + 16); u32 writeOption = mem.read32(messagePointer + 16);
u32 dataPointer = mem.read32(messagePointer + 24); u32 dataPointer = mem.read32(messagePointer + 24);
logFileIO("Trying to write %X bytes to file %X, starting from file offset %llX and memory address %08X\n", logFileIO("Trying to write %X bytes to file %X, starting from file offset %llX and memory address %08X\n", size, fileHandle, offset, dataPointer);
size, fileHandle, offset, dataPointer);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
if (p == nullptr) [[unlikely]] { if (p == nullptr) [[unlikely]] {
@ -137,8 +133,7 @@ void Kernel::writeFile(u32 messagePointer, Handle fileHandle) {
Helpers::panic("Tried to write closed file"); Helpers::panic("Tried to write closed file");
} }
if (!file->fd) if (!file->fd) Helpers::panic("[Kernel::File::WriteFile] Tried to write to file without a valid file descriptor");
Helpers::panic("[Kernel::File::WriteFile] Tried to write to file without a valid file descriptor");
std::unique_ptr<u8[]> data(new u8[size]); std::unique_ptr<u8[]> data(new u8[size]);
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -162,7 +157,7 @@ void Kernel::writeFile(u32 messagePointer, Handle fileHandle) {
} }
} }
void Kernel::setFileSize(u32 messagePointer, Handle fileHandle) { void Kernel::setFileSize(u32 messagePointer, HandleType fileHandle) {
logFileIO("Setting size of file %X\n", fileHandle); logFileIO("Setting size of file %X\n", fileHandle);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
@ -191,7 +186,7 @@ void Kernel::setFileSize(u32 messagePointer, Handle fileHandle) {
} }
} }
void Kernel::getFileSize(u32 messagePointer, Handle fileHandle) { void Kernel::getFileSize(u32 messagePointer, HandleType fileHandle) {
logFileIO("Getting size of file %X\n", fileHandle); logFileIO("Getting size of file %X\n", fileHandle);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
@ -220,7 +215,7 @@ void Kernel::getFileSize(u32 messagePointer, Handle fileHandle) {
} }
} }
void Kernel::openLinkFile(u32 messagePointer, Handle fileHandle) { void Kernel::openLinkFile(u32 messagePointer, HandleType fileHandle) {
logFileIO("Open link file (clone) of file %X\n", fileHandle); logFileIO("Open link file (clone) of file %X\n", fileHandle);
const auto p = getObject(fileHandle, KernelObjectType::File); const auto p = getObject(fileHandle, KernelObjectType::File);
@ -247,7 +242,7 @@ void Kernel::openLinkFile(u32 messagePointer, Handle fileHandle) {
mem.write32(messagePointer + 12, handle); mem.write32(messagePointer + 12, handle);
} }
void Kernel::setFilePriority(u32 messagePointer, Handle fileHandle) { void Kernel::setFilePriority(u32 messagePointer, HandleType fileHandle) {
const u32 priority = mem.read32(messagePointer + 4); const u32 priority = mem.read32(messagePointer + 4);
logFileIO("Setting priority of file %X to %d\n", fileHandle, priority); logFileIO("Setting priority of file %X to %d\n", fileHandle, priority);

View file

@ -1,7 +1,9 @@
#include <cassert>
#include "kernel.hpp" #include "kernel.hpp"
#include "kernel_types.hpp"
#include <cassert>
#include "cpu.hpp" #include "cpu.hpp"
#include "kernel_types.hpp"
Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config) Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config)
: cpu(cpu), regs(cpu.regs()), mem(mem), handleCounter(0), serviceManager(regs, mem, gpu, currentProcess, *this, config) { : cpu(cpu), regs(cpu.regs()), mem(mem), handleCounter(0), serviceManager(regs, mem, gpu, currentProcess, *this, config) {
@ -82,9 +84,9 @@ void Kernel::setVersion(u8 major, u8 minor) {
mem.kernelVersion = descriptor; // The memory objects needs a copy because you can read the kernel ver from config mem mem.kernelVersion = descriptor; // The memory objects needs a copy because you can read the kernel ver from config mem
} }
Handle Kernel::makeProcess(u32 id) { HandleType Kernel::makeProcess(u32 id) {
const Handle processHandle = makeObject(KernelObjectType::Process); const HandleType processHandle = makeObject(KernelObjectType::Process);
const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit); const HandleType resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
// Allocate data // Allocate data
objects[processHandle].data = new Process(id); objects[processHandle].data = new Process(id);
@ -98,7 +100,7 @@ Handle Kernel::makeProcess(u32 id) {
// Get a pointer to the process indicated by handle, taking into account that 0xFFFF8001 always refers to the current process // Get a pointer to the process indicated by handle, taking into account that 0xFFFF8001 always refers to the current process
// Returns nullptr if the handle does not correspond to a process // Returns nullptr if the handle does not correspond to a process
KernelObject* Kernel::getProcessFromPID(Handle handle) { KernelObject* Kernel::getProcessFromPID(HandleType handle) {
if (handle == KernelHandles::CurrentProcess) [[likely]] { if (handle == KernelHandles::CurrentProcess) [[likely]] {
return getObject(currentProcess, KernelObjectType::Process); return getObject(currentProcess, KernelObjectType::Process);
} else { } else {
@ -174,14 +176,12 @@ void Kernel::reset() {
} }
// Get pointer to thread-local storage // Get pointer to thread-local storage
u32 Kernel::getTLSPointer() { u32 Kernel::getTLSPointer() { return VirtualAddrs::TLSBase + currentThreadIndex * VirtualAddrs::TLSSize; }
return VirtualAddrs::TLSBase + currentThreadIndex * VirtualAddrs::TLSSize;
}
// Result CloseHandle(Handle handle) // Result CloseHandle(HandleType handle)
void Kernel::svcCloseHandle() { void Kernel::svcCloseHandle() {
logSVC("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]); logSVC("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]);
const Handle handle = regs[0]; const HandleType handle = regs[0];
KernelObject* object = getObject(handle); KernelObject* object = getObject(handle);
if (object != nullptr) { if (object != nullptr) {
@ -242,7 +242,7 @@ void Kernel::getProcessID() {
regs[1] = process->getData<Process>()->id; regs[1] = process->getData<Process>()->id;
} }
// Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type) // Result GetProcessInfo(s64* out, HandleType process, ProcessInfoType type)
void Kernel::getProcessInfo() { void Kernel::getProcessInfo() {
const auto pid = regs[1]; const auto pid = regs[1];
const auto type = regs[2]; const auto type = regs[2];
@ -274,21 +274,20 @@ void Kernel::getProcessInfo() {
regs[2] = 0; regs[2] = 0;
break; break;
default: default: Helpers::panic("GetProcessInfo: unimplemented type %d", type);
Helpers::panic("GetProcessInfo: unimplemented type %d", type);
} }
regs[0] = Result::Success; regs[0] = Result::Success;
} }
// Result DuplicateHandle(Handle* out, Handle original) // Result DuplicateHandle(HandleType* out, HandleType original)
void Kernel::duplicateHandle() { void Kernel::duplicateHandle() {
Handle original = regs[1]; HandleType original = regs[1];
logSVC("DuplicateHandle(handle = %X)\n", original); logSVC("DuplicateHandle(handle = %X)\n", original);
if (original == KernelHandles::CurrentThread) { if (original == KernelHandles::CurrentThread) {
regs[0] = Result::Success; regs[0] = Result::Success;
Handle ret = makeObject(KernelObjectType::Thread); HandleType ret = makeObject(KernelObjectType::Thread);
objects[ret].data = &threads[currentThreadIndex]; objects[ret].data = &threads[currentThreadIndex];
regs[1] = ret; regs[1] = ret;

View file

@ -31,9 +31,7 @@ namespace MemoryPermissions {
} }
// Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes) // Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes)
static constexpr bool isAligned(u32 value) { static constexpr bool isAligned(u32 value) { return (value & 0xFFF) == 0; }
return (value & 0xFFF) == 0;
}
// Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, // Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size,
// MemoryOperation operation, MemoryPermission permissions) // MemoryOperation operation, MemoryPermission permissions)
@ -57,33 +55,33 @@ void Kernel::controlMemory() {
bool x = perms & 0b100; bool x = perms & 0b100;
bool linear = operation & Operation::Linear; bool linear = operation & Operation::Linear;
if (x) if (x) Helpers::panic("ControlMemory: attempted to allocate executable memory");
Helpers::panic("ControlMemory: attempted to allocate executable memory");
if (!isAligned(addr0) || !isAligned(addr1) || !isAligned(size)) { if (!isAligned(addr0) || !isAligned(addr1) || !isAligned(size)) {
Helpers::panic("ControlMemory: Unaligned parameters\nAddr0: %08X\nAddr1: %08X\nSize: %08X", addr0, addr1, size); Helpers::panic("ControlMemory: Unaligned parameters\nAddr0: %08X\nAddr1: %08X\nSize: %08X", addr0, addr1, size);
} }
logSVC("ControlMemory(addr0 = %08X, addr1 = %08X, size = %08X, operation = %X (%c%c%c)%s\n", logSVC(
addr0, addr1, size, operation, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', linear ? ", linear" : "" "ControlMemory(addr0 = %08X, addr1 = %08X, size = %08X, operation = %X (%c%c%c)%s\n", addr0, addr1, size, operation, r ? 'r' : '-',
w ? 'w' : '-', x ? 'x' : '-', linear ? ", linear" : ""
); );
switch (operation & 0xFF) { switch (operation & 0xFF) {
case Operation::Commit: { case Operation::Commit: {
std::optional<u32> address = mem.allocateMemory(addr0, 0, size, linear, r, w, x, true); std::optional<u32> address = mem.allocateMemory(addr0, 0, size, linear, r, w, x, true);
if (!address.has_value()) if (!address.has_value()) Helpers::panic("ControlMemory: Failed to allocate memory");
Helpers::panic("ControlMemory: Failed to allocate memory");
regs[1] = address.value(); regs[1] = address.value();
break; break;
} }
case Operation::Map: case Operation::Map: mem.mirrorMapping(addr0, addr1, size); break;
mem.mirrorMapping(addr0, addr1, size);
break;
case Operation::Protect: case Operation::Protect:
Helpers::warn("Ignoring mprotect! Hope nothing goes wrong but if the game accesses invalid memory or crashes then we prolly need to implement this\n"); Helpers::warn(
"Ignoring mprotect! Hope nothing goes wrong but if the game accesses invalid memory or crashes then we prolly need to implement "
"this\n"
);
break; break;
default: Helpers::warn("ControlMemory: unknown operation %X\n", operation); break; default: Helpers::warn("ControlMemory: unknown operation %X\n", operation); break;
@ -109,9 +107,9 @@ void Kernel::queryMemory() {
regs[5] = 0; // page flags regs[5] = 0; // page flags
} }
// Result MapMemoryBlock(Handle memblock, u32 addr, MemoryPermission myPermissions, MemoryPermission otherPermission) // Result MapMemoryBlock(HandleType memblock, u32 addr, MemoryPermission myPermissions, MemoryPermission otherPermission)
void Kernel::mapMemoryBlock() { void Kernel::mapMemoryBlock() {
const Handle block = regs[0]; const HandleType block = regs[0];
u32 addr = regs[1]; u32 addr = regs[1];
const u32 myPerms = regs[2]; const u32 myPerms = regs[2];
const u32 otherPerms = regs[3]; const u32 otherPerms = regs[3];
@ -127,17 +125,11 @@ void Kernel::mapMemoryBlock() {
// Pass pointer to shared memory to the appropriate service // Pass pointer to shared memory to the appropriate service
switch (block) { switch (block) {
case KernelHandles::HIDSharedMemHandle: case KernelHandles::HIDSharedMemHandle: serviceManager.setHIDSharedMem(ptr); break;
serviceManager.setHIDSharedMem(ptr);
break;
case KernelHandles::GSPSharedMemHandle: case KernelHandles::GSPSharedMemHandle: serviceManager.setGSPSharedMem(ptr); break;
serviceManager.setGSPSharedMem(ptr);
break;
case KernelHandles::FontSharedMemHandle: case KernelHandles::FontSharedMemHandle: mem.copySharedFont(ptr); break;
mem.copySharedFont(ptr);
break;
case KernelHandles::CSNDSharedMemHandle: case KernelHandles::CSNDSharedMemHandle:
serviceManager.setCSNDSharedMem(ptr); serviceManager.setCSNDSharedMem(ptr);
@ -154,8 +146,8 @@ void Kernel::mapMemoryBlock() {
regs[0] = Result::Success; regs[0] = Result::Success;
} }
Handle Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) { HandleType Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
Handle ret = makeObject(KernelObjectType::MemoryBlock); HandleType ret = makeObject(KernelObjectType::MemoryBlock);
objects[ret].data = new MemoryBlock(addr, size, myPermission, otherPermission); objects[ret].data = new MemoryBlock(addr, size, myPermission, otherPermission);
return ret; return ret;
@ -175,8 +167,7 @@ void Kernel::createMemoryBlock() {
case MemoryPermissions::Read: case MemoryPermissions::Read:
case MemoryPermissions::Write: case MemoryPermissions::Write:
case MemoryPermissions::ReadWrite: case MemoryPermissions::ReadWrite:
case MemoryPermissions::DontCare: case MemoryPermissions::DontCare: return true;
return true;
default: // Permissions with the executable flag enabled or invalid permissions are not allowed default: // Permissions with the executable flag enabled or invalid permissions are not allowed
return false; return false;
@ -197,8 +188,7 @@ void Kernel::createMemoryBlock() {
// TODO: The address needs to be in a specific range otherwise it throws an invalid address error // TODO: The address needs to be in a specific range otherwise it throws an invalid address error
if (addr == 0) if (addr == 0) Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
// Implement "Don't care" permission as RW // Implement "Don't care" permission as RW
if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite; if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite;
@ -209,7 +199,7 @@ void Kernel::createMemoryBlock() {
} }
void Kernel::unmapMemoryBlock() { void Kernel::unmapMemoryBlock() {
Handle block = regs[0]; HandleType block = regs[0];
u32 addr = regs[1]; u32 addr = regs[1];
logSVC("Unmap memory block (block handle = %X, addr = %08X)\n", block, addr); logSVC("Unmap memory block (block handle = %X, addr = %08X)\n", block, addr);

View file

@ -1,29 +1,30 @@
#include "kernel.hpp"
#include <cstring> #include <cstring>
Handle Kernel::makePort(const char* name) { #include "kernel.hpp"
Handle ret = makeObject(KernelObjectType::Port);
HandleType Kernel::makePort(const char* name) {
HandleType ret = makeObject(KernelObjectType::Port);
portHandles.push_back(ret); // Push the port handle to our cache of port handles portHandles.push_back(ret); // Push the port handle to our cache of port handles
objects[ret].data = new Port(name); objects[ret].data = new Port(name);
return ret; return ret;
} }
Handle Kernel::makeSession(Handle portHandle) { HandleType Kernel::makeSession(HandleType portHandle) {
const auto port = getObject(portHandle, KernelObjectType::Port); const auto port = getObject(portHandle, KernelObjectType::Port);
if (port == nullptr) [[unlikely]] { if (port == nullptr) [[unlikely]] {
Helpers::panic("Trying to make session for non-existent port"); Helpers::panic("Trying to make session for non-existent port");
} }
// Allocate data for session // Allocate data for session
const Handle ret = makeObject(KernelObjectType::Session); const HandleType ret = makeObject(KernelObjectType::Session);
objects[ret].data = new Session(portHandle); objects[ret].data = new Session(portHandle);
return ret; return ret;
} }
// Get the handle of a port based on its name // Get the handle of a port based on its name
// If there's no such port, return nullopt // If there's no such port, return nullopt
std::optional<Handle> Kernel::getPortHandle(const char* name) { std::optional<HandleType> Kernel::getPortHandle(const char* name) {
for (auto handle : portHandles) { for (auto handle : portHandles) {
const auto data = objects[handle].getData<Port>(); const auto data = objects[handle].getData<Port>();
if (std::strncmp(name, data->name, Port::maxNameLen) == 0) { if (std::strncmp(name, data->name, Port::maxNameLen) == 0) {
@ -34,7 +35,7 @@ std::optional<Handle> Kernel::getPortHandle(const char* name) {
return std::nullopt; return std::nullopt;
} }
// Result ConnectToPort(Handle* out, const char* portName) // Result ConnectToPort(HandleType* out, const char* portName)
void Kernel::connectToPort() { void Kernel::connectToPort() {
const u32 handlePointer = regs[0]; const u32 handlePointer = regs[0];
// Read up to max + 1 characters to see if the name is too long // Read up to max + 1 characters to see if the name is too long
@ -48,14 +49,14 @@ void Kernel::connectToPort() {
} }
// Try getting a handle to the port // Try getting a handle to the port
std::optional<Handle> optionalHandle = getPortHandle(port.c_str()); std::optional<HandleType> optionalHandle = getPortHandle(port.c_str());
if (!optionalHandle.has_value()) [[unlikely]] { if (!optionalHandle.has_value()) [[unlikely]] {
Helpers::panic("ConnectToPort: Port doesn't exist\n"); Helpers::panic("ConnectToPort: Port doesn't exist\n");
regs[0] = Result::Kernel::NotFound; regs[0] = Result::Kernel::NotFound;
return; return;
} }
Handle portHandle = optionalHandle.value(); HandleType portHandle = optionalHandle.value();
const auto portData = objects[portHandle].getData<Port>(); const auto portData = objects[portHandle].getData<Port>();
if (!portData->isPublic) { if (!portData->isPublic) {
@ -63,13 +64,13 @@ void Kernel::connectToPort() {
} }
// TODO: Actually create session // TODO: Actually create session
Handle sessionHandle = makeSession(portHandle); HandleType sessionHandle = makeSession(portHandle);
regs[0] = Result::Success; regs[0] = Result::Success;
regs[1] = sessionHandle; regs[1] = sessionHandle;
} }
// Result SendSyncRequest(Handle session) // Result SendSyncRequest(HandleType session)
// Send an IPC message to a port (typically "srv:") or a service // Send an IPC message to a port (typically "srv:") or a service
void Kernel::sendSyncRequest() { void Kernel::sendSyncRequest() {
const auto handle = regs[0]; const auto handle = regs[0];
@ -115,7 +116,7 @@ void Kernel::sendSyncRequest() {
} }
const auto sessionData = static_cast<Session*>(session->data); const auto sessionData = static_cast<Session*>(session->data);
const Handle portHandle = sessionData->portHandle; const HandleType portHandle = sessionData->portHandle;
if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port" if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port"
regs[0] = Result::Success; regs[0] = Result::Success;

View file

@ -1,7 +1,8 @@
#include "resource_limits.hpp" #include "resource_limits.hpp"
#include "kernel.hpp" #include "kernel.hpp"
// Result GetResourceLimit(Handle* resourceLimit, Handle process) // Result GetResourceLimit(HandleType* resourceLimit, HandleType process)
// out: r0 -> result, r1 -> handle // out: r0 -> result, r1 -> handle
void Kernel::getResourceLimit() { void Kernel::getResourceLimit() {
const auto handlePointer = regs[0]; const auto handlePointer = regs[0];
@ -20,10 +21,10 @@ void Kernel::getResourceLimit() {
regs[1] = processData->limits.handle; regs[1] = processData->limits.handle;
} }
// Result GetResourceLimitLimitValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) // Result GetResourceLimitLimitValues(s64* values, HandleType resourceLimit, LimitableResource* names, s32 nameCount)
void Kernel::getResourceLimitLimitValues() { void Kernel::getResourceLimitLimitValues() {
u32 values = regs[0]; // Pointer to values (The resource limits get output here) u32 values = regs[0]; // Pointer to values (The resource limits get output here)
const Handle resourceLimit = regs[1]; const HandleType resourceLimit = regs[1];
u32 names = regs[2]; // Pointer to resources that we should return u32 names = regs[2]; // Pointer to resources that we should return
u32 count = regs[3]; // Number of resources u32 count = regs[3]; // Number of resources
@ -49,10 +50,10 @@ void Kernel::getResourceLimitLimitValues() {
regs[0] = Result::Success; regs[0] = Result::Success;
} }
// Result GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) // Result GetResourceLimitCurrentValues(s64* values, HandleType resourceLimit, LimitableResource* names, s32 nameCount)
void Kernel::getResourceLimitCurrentValues() { void Kernel::getResourceLimitCurrentValues() {
u32 values = regs[0]; // Pointer to values (The resource limits get output here) u32 values = regs[0]; // Pointer to values (The resource limits get output here)
const Handle resourceLimit = regs[1]; const HandleType resourceLimit = regs[1];
u32 names = regs[2]; // Pointer to resources that we should return u32 names = regs[2]; // Pointer to resources that we should return
u32 count = regs[3]; // Number of resources u32 count = regs[3]; // Number of resources
logSVC("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count); logSVC("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count);

View file

@ -42,21 +42,19 @@ void Kernel::switchThread(int newThreadIndex) {
// The threads with higher priority (aka the ones with a lower priority value) should come first in the vector // The threads with higher priority (aka the ones with a lower priority value) should come first in the vector
void Kernel::sortThreads() { void Kernel::sortThreads() {
std::vector<int>& v = threadIndices; std::vector<int>& v = threadIndices;
std::sort(v.begin(), v.end(), [&](int a, int b) { std::sort(v.begin(), v.end(), [&](int a, int b) { return threads[a].priority < threads[b].priority; });
return threads[a].priority < threads[b].priority;
});
} }
bool Kernel::canThreadRun(const Thread& t) { bool Kernel::canThreadRun(const Thread& t) {
if (t.status == ThreadStatus::Ready) { if (t.status == ThreadStatus::Ready) {
return true; return true;
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1 } else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1 || t.status == ThreadStatus::WaitSyncAny ||
|| t.status == ThreadStatus::WaitSyncAny || t.status == ThreadStatus::WaitSyncAll) { t.status == ThreadStatus::WaitSyncAll) {
// TODO: Set r0 to the correct error code on timeout for WaitSync{1/Any/All} // TODO: Set r0 to the correct error code on timeout for WaitSync{1/Any/All}
return cpu.getTicks() >= t.wakeupTick; return cpu.getTicks() >= t.wakeupTick;
} }
// Handle timeouts and stuff here // HandleType timeouts and stuff here
return false; return false;
} }
@ -109,7 +107,7 @@ void Kernel::rescheduleThreads() {
} }
// Internal OS function to spawn a thread // Internal OS function to spawn a thread
Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status) { HandleType Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status) {
int index; // Index of the created thread in the threads array int index; // Index of the created thread in the threads array
if (threadCount < appResourceLimits.maxThreads) [[likely]] { // If we have not yet created over too many threads if (threadCount < appResourceLimits.maxThreads) [[likely]] { // If we have not yet created over too many threads
@ -129,7 +127,7 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, Processor
threadIndices.push_back(index); threadIndices.push_back(index);
Thread& t = threads[index]; // Reference to thread data Thread& t = threads[index]; // Reference to thread data
Handle ret = makeObject(KernelObjectType::Thread); HandleType ret = makeObject(KernelObjectType::Thread);
objects[ret].data = &t; objects[ret].data = &t;
const bool isThumb = (entrypoint & 1) != 0; // Whether the thread starts in thumb mode or not const bool isThumb = (entrypoint & 1) != 0; // Whether the thread starts in thumb mode or not
@ -161,8 +159,8 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, Processor
return ret; return ret;
} }
Handle Kernel::makeMutex(bool locked) { HandleType Kernel::makeMutex(bool locked) {
Handle ret = makeObject(KernelObjectType::Mutex); HandleType ret = makeObject(KernelObjectType::Mutex);
objects[ret].data = new Mutex(locked, ret); objects[ret].data = new Mutex(locked, ret);
// If the mutex is initially locked, store the index of the thread that owns it and set lock count to 1 // If the mutex is initially locked, store the index of the thread that owns it and set lock count to 1
@ -201,8 +199,8 @@ void Kernel::releaseMutex(Mutex* moo) {
} }
} }
Handle Kernel::makeSemaphore(u32 initialCount, u32 maximumCount) { HandleType Kernel::makeSemaphore(u32 initialCount, u32 maximumCount) {
Handle ret = makeObject(KernelObjectType::Semaphore); HandleType ret = makeObject(KernelObjectType::Semaphore);
objects[ret].data = new Semaphore(initialCount, maximumCount); objects[ret].data = new Semaphore(initialCount, maximumCount);
return ret; return ret;
@ -252,8 +250,7 @@ void Kernel::acquireSyncObject(KernelObject* object, const Thread& thread) {
break; break;
} }
case KernelObjectType::Thread: case KernelObjectType::Thread: break;
break;
case KernelObjectType::Timer: { case KernelObjectType::Timer: {
Timer* timer = object->getData<Timer>(); Timer* timer = object->getData<Timer>();
@ -269,7 +266,7 @@ void Kernel::acquireSyncObject(KernelObject* object, const Thread& thread) {
// Wake up one of the threads in the waitlist (the one with highest prio) and return its index // Wake up one of the threads in the waitlist (the one with highest prio) and return its index
// Must not be called with an empty waitlist // Must not be called with an empty waitlist
int Kernel::wakeupOneThread(u64 waitlist, Handle handle) { int Kernel::wakeupOneThread(u64 waitlist, HandleType handle) {
if (waitlist == 0) [[unlikely]] if (waitlist == 0) [[unlikely]]
Helpers::panic("[Internal error] It shouldn't be possible to call wakeupOneThread when there's 0 threads waiting!"); Helpers::panic("[Internal error] It shouldn't be possible to call wakeupOneThread when there's 0 threads waiting!");
@ -309,16 +306,14 @@ int Kernel::wakeupOneThread(u64 waitlist, Handle handle) {
} }
break; break;
case ThreadStatus::WaitSyncAll: case ThreadStatus::WaitSyncAll: Helpers::panic("WakeupOneThread: Thread on WaitSyncAll"); break;
Helpers::panic("WakeupOneThread: Thread on WaitSyncAll");
break;
} }
return threadIndex; return threadIndex;
} }
// Wake up every single thread in the waitlist using a bit scanning algorithm // Wake up every single thread in the waitlist using a bit scanning algorithm
void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) { void Kernel::wakeupAllThreads(u64 waitlist, HandleType handle) {
while (waitlist != 0) { while (waitlist != 0) {
const uint index = std::countr_zero(waitlist); // Get one of the set bits to see which thread is waiting const uint index = std::countr_zero(waitlist); // Get one of the set bits to see which thread is waiting
waitlist ^= (1ull << index); // Remove thread from waitlist by toggling its bit waitlist ^= (1ull << index); // Remove thread from waitlist by toggling its bit
@ -344,9 +339,7 @@ void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) {
} }
break; break;
case ThreadStatus::WaitSyncAll: case ThreadStatus::WaitSyncAll: Helpers::panic("WakeupAllThreads: Thread on WaitSyncAll"); break;
Helpers::panic("WakeupAllThreads: Thread on WaitSyncAll");
break;
} }
} }
} }
@ -408,8 +401,7 @@ void Kernel::createThread() {
u32 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes u32 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes
s32 id = static_cast<s32>(regs[4]); s32 id = static_cast<s32>(regs[4]);
logSVC("CreateThread(entry = %08X, stacktop = %08X, arg = %X, priority = %X, processor ID = %d)\n", entrypoint, logSVC("CreateThread(entry = %08X, stacktop = %08X, arg = %X, priority = %X, processor ID = %d)\n", entrypoint, initialSP, arg, priority, id);
initialSP, arg, priority, id);
if (priority > 0x3F) [[unlikely]] { if (priority > 0x3F) [[unlikely]] {
Helpers::panic("Created thread with bad priority value %X", priority); Helpers::panic("Created thread with bad priority value %X", priority);
@ -436,7 +428,7 @@ void Kernel::svcSleepThread() {
} }
void Kernel::getThreadID() { void Kernel::getThreadID() {
Handle handle = regs[1]; HandleType handle = regs[1];
logSVC("GetThreadID(handle = %X)\n", handle); logSVC("GetThreadID(handle = %X)\n", handle);
if (handle == KernelHandles::CurrentThread) { if (handle == KernelHandles::CurrentThread) {
@ -456,7 +448,7 @@ void Kernel::getThreadID() {
} }
void Kernel::getThreadPriority() { void Kernel::getThreadPriority() {
const Handle handle = regs[1]; const HandleType handle = regs[1];
logSVC("GetThreadPriority (handle = %X)\n", handle); logSVC("GetThreadPriority (handle = %X)\n", handle);
if (handle == KernelHandles::CurrentThread) { if (handle == KernelHandles::CurrentThread) {
@ -474,7 +466,7 @@ void Kernel::getThreadPriority() {
} }
void Kernel::getThreadIdealProcessor() { void Kernel::getThreadIdealProcessor() {
const Handle handle = regs[1]; // Thread handle const HandleType handle = regs[1]; // Thread handle
logSVC("GetThreadIdealProcessor (handle = %X)\n", handle); logSVC("GetThreadIdealProcessor (handle = %X)\n", handle);
// TODO: Not documented what this is or what it does. Citra doesn't implement it at all. Return AppCore as the ideal processor for now // TODO: Not documented what this is or what it does. Citra doesn't implement it at all. Return AppCore as the ideal processor for now
@ -490,7 +482,7 @@ void Kernel::getThreadContext() {
} }
void Kernel::setThreadPriority() { void Kernel::setThreadPriority() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
const u32 priority = regs[1]; const u32 priority = regs[1];
logSVC("SetThreadPriority (handle = %X, priority = %X)\n", handle, priority); logSVC("SetThreadPriority (handle = %X, priority = %X)\n", handle, priority);
@ -524,9 +516,7 @@ void Kernel::getCurrentProcessorNumber() {
// Until we properly implement per-core schedulers, return whatever processor ID passed to svcCreateThread // Until we properly implement per-core schedulers, return whatever processor ID passed to svcCreateThread
switch (id) { switch (id) {
// TODO: This is picked from exheader // TODO: This is picked from exheader
case ProcessorID::Default: case ProcessorID::Default: ret = static_cast<s32>(ProcessorID::AppCore); break;
ret = static_cast<s32>(ProcessorID::AppCore);
break;
case ProcessorID::AllCPUs: case ProcessorID::AllCPUs:
ret = static_cast<s32>(ProcessorID::AppCore); ret = static_cast<s32>(ProcessorID::AppCore);
@ -565,8 +555,7 @@ void Kernel::exitThread() {
// Remove the index of this thread from the thread indices vector // Remove the index of this thread from the thread indices vector
for (int i = 0; i < threadIndices.size(); i++) { for (int i = 0; i < threadIndices.size(); i++) {
if (threadIndices[i] == currentThreadIndex) if (threadIndices[i] == currentThreadIndex) threadIndices.erase(threadIndices.begin() + i);
threadIndices.erase(threadIndices.begin() + i);
} }
Thread& t = threads[currentThreadIndex]; Thread& t = threads[currentThreadIndex];
@ -576,7 +565,7 @@ void Kernel::exitThread() {
// Check if any threads are sleeping, waiting for this thread to terminate, and wake them up // Check if any threads are sleeping, waiting for this thread to terminate, and wake them up
// This is how thread joining is implemented in the kernel - you wait on a thread, like any other wait object. // This is how thread joining is implemented in the kernel - you wait on a thread, like any other wait object.
if (t.threadsWaitingForTermination != 0) { if (t.threadsWaitingForTermination != 0) {
// TODO: Handle cloned handles? Not sure how those interact with wait object signalling // TODO: HandleType cloned handles? Not sure how those interact with wait object signalling
wakeupAllThreads(t.threadsWaitingForTermination, t.handle); wakeupAllThreads(t.threadsWaitingForTermination, t.handle);
t.threadsWaitingForTermination = 0; // No other threads waiting t.threadsWaitingForTermination = 0; // No other threads waiting
} }
@ -593,7 +582,7 @@ void Kernel::svcCreateMutex() {
} }
void Kernel::svcReleaseMutex() { void Kernel::svcReleaseMutex() {
const Handle handle = regs[0]; const HandleType handle = regs[0];
logSVC("ReleaseMutex (handle = %x)\n", handle); logSVC("ReleaseMutex (handle = %x)\n", handle);
const auto object = getObject(handle, KernelObjectType::Mutex); const auto object = getObject(handle, KernelObjectType::Mutex);
@ -619,18 +608,16 @@ void Kernel::svcCreateSemaphore() {
s32 maxCount = static_cast<s32>(regs[2]); s32 maxCount = static_cast<s32>(regs[2]);
logSVC("CreateSemaphore (initial count = %d, max count = %d)\n", initialCount, maxCount); logSVC("CreateSemaphore (initial count = %d, max count = %d)\n", initialCount, maxCount);
if (initialCount > maxCount) if (initialCount > maxCount) Helpers::panic("CreateSemaphore: Initial count higher than max count");
Helpers::panic("CreateSemaphore: Initial count higher than max count");
if (initialCount < 0 || maxCount < 0) if (initialCount < 0 || maxCount < 0) Helpers::panic("CreateSemaphore: Negative count value");
Helpers::panic("CreateSemaphore: Negative count value");
regs[0] = Result::Success; regs[0] = Result::Success;
regs[1] = makeSemaphore(initialCount, maxCount); regs[1] = makeSemaphore(initialCount, maxCount);
} }
void Kernel::svcReleaseSemaphore() { void Kernel::svcReleaseSemaphore() {
const Handle handle = regs[1]; const HandleType handle = regs[1];
const s32 releaseCount = static_cast<s32>(regs[2]); const s32 releaseCount = static_cast<s32>(regs[2]);
logSVC("ReleaseSemaphore (handle = %X, release count = %d)\n", handle, releaseCount); logSVC("ReleaseSemaphore (handle = %X, release count = %d)\n", handle, releaseCount);
@ -641,12 +628,10 @@ void Kernel::svcReleaseSemaphore() {
return; return;
} }
if (releaseCount < 0) if (releaseCount < 0) Helpers::panic("ReleaseSemaphore: Negative count");
Helpers::panic("ReleaseSemaphore: Negative count");
Semaphore* s = object->getData<Semaphore>(); Semaphore* s = object->getData<Semaphore>();
if (s->maximumCount - s->availableCount < releaseCount) if (s->maximumCount - s->availableCount < releaseCount) Helpers::panic("ReleaseSemaphore: Release count too high");
Helpers::panic("ReleaseSemaphore: Release count too high");
// Write success and old available count to r0 and r1 respectively // Write success and old available count to r0 and r1 respectively
regs[0] = Result::Success; regs[0] = Result::Success;
@ -692,8 +677,6 @@ bool Kernel::shouldWaitOnObject(KernelObject* object) {
case KernelObjectType::Semaphore: // Wait if the semaphore count <= 0 case KernelObjectType::Semaphore: // Wait if the semaphore count <= 0
return object->getData<Semaphore>()->availableCount <= 0; return object->getData<Semaphore>()->availableCount <= 0;
default: default: Helpers::panic("Not sure whether to wait on object (type: %s)", object->getTypeName()); return true;
Helpers::panic("Not sure whether to wait on object (type: %s)", object->getTypeName());
return true;
} }
} }

View file

@ -4,8 +4,8 @@
#include "kernel.hpp" #include "kernel.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
Handle Kernel::makeTimer(ResetType type) { HandleType Kernel::makeTimer(ResetType type) {
Handle ret = makeObject(KernelObjectType::Timer); HandleType ret = makeObject(KernelObjectType::Timer);
objects[ret].data = new Timer(type); objects[ret].data = new Timer(type);
if (type == ResetType::Pulse) { if (type == ResetType::Pulse) {
@ -52,11 +52,9 @@ void Kernel::pollTimers() {
} }
} }
void Kernel::cancelTimer(Timer* timer) { void Kernel::cancelTimer(Timer* timer) { timer->running = false; }
timer->running = false;
}
void Kernel::signalTimer(Handle timerHandle, Timer* timer) { void Kernel::signalTimer(HandleType timerHandle, Timer* timer) {
timer->fired = true; timer->fired = true;
requireReschedule(); requireReschedule();
@ -94,7 +92,7 @@ void Kernel::svcCreateTimer() {
} }
void Kernel::svcSetTimer() { void Kernel::svcSetTimer() {
Handle handle = regs[0]; HandleType handle = regs[0];
// TODO: Is this actually s64 or u64? 3DBrew says s64, but u64 makes more sense // TODO: Is this actually s64 or u64? 3DBrew says s64, but u64 makes more sense
const s64 initial = s64(u64(regs[2]) | (u64(regs[3]) << 32)); const s64 initial = s64(u64(regs[2]) | (u64(regs[3]) << 32));
const s64 interval = s64(u64(regs[1]) | (u64(regs[4]) << 32)); const s64 interval = s64(u64(regs[1]) | (u64(regs[4]) << 32));
@ -127,7 +125,7 @@ void Kernel::svcSetTimer() {
} }
void Kernel::svcClearTimer() { void Kernel::svcClearTimer() {
Handle handle = regs[0]; HandleType handle = regs[0];
logSVC("ClearTimer (handle = %X)\n", handle); logSVC("ClearTimer (handle = %X)\n", handle);
KernelObject* object = getObject(handle, KernelObjectType::Timer); KernelObject* object = getObject(handle, KernelObjectType::Timer);
@ -141,7 +139,7 @@ void Kernel::svcClearTimer() {
} }
void Kernel::svcCancelTimer() { void Kernel::svcCancelTimer() {
Handle handle = regs[0]; HandleType handle = regs[0];
logSVC("CancelTimer (handle = %X)\n", handle); logSVC("CancelTimer (handle = %X)\n", handle);
KernelObject* object = getObject(handle, KernelObjectType::Timer); KernelObject* object = getObject(handle, KernelObjectType::Timer);

View file

@ -171,11 +171,10 @@ u32 Memory::read32(u32 vaddr) {
case ConfigMem::AppMemAlloc: return appResourceLimits.maxCommit; case ConfigMem::AppMemAlloc: return appResourceLimits.maxCommit;
case ConfigMem::SyscoreVer: return 2; case ConfigMem::SyscoreVer: return 2;
case 0x1FF81000: return 0; // TODO: Figure out what this config mem address does case 0x1FF81000:
return 0; // TODO: Figure out what this config mem address does
// Wifi MAC: First 4 bytes of MAC Address // Wifi MAC: First 4 bytes of MAC Address
case ConfigMem::WifiMac: case ConfigMem::WifiMac: return (u32(MACAddress[3]) << 24) | (u32(MACAddress[2]) << 16) | (u32(MACAddress[1]) << 8) | MACAddress[0];
return (u32(MACAddress[3]) << 24) | (u32(MACAddress[2]) << 16) | (u32(MACAddress[1]) << 8) |
MACAddress[0];
// 3D slider. Float in range 0.0 = off, 1.0 = max. // 3D slider. Float in range 0.0 = off, 1.0 = max.
case ConfigMem::SliderState3D: return Helpers::bit_cast<u32, float>(0.0f); case ConfigMem::SliderState3D: return Helpers::bit_cast<u32, float>(0.0f);
@ -440,7 +439,7 @@ MemoryInfo Memory::queryMemory(u32 vaddr) {
return MemoryInfo(vaddr, pageSize, 0, KernelMemoryTypes::Free); return MemoryInfo(vaddr, pageSize, 0, KernelMemoryTypes::Free);
} }
u8* Memory::mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms) { u8* Memory::mapSharedMemory(HandleType handle, u32 vaddr, u32 myPerms, u32 otherPerms) {
for (auto& e : sharedMemBlocks) { for (auto& e : sharedMemBlocks) {
if (e.handle == handle) { if (e.handle == handle) {
// Virtual Console titles trigger this. TODO: Investigate how it should work // Virtual Console titles trigger this. TODO: Investigate how it should work

View file

@ -0,0 +1,6 @@
#define NS_PRIVATE_IMPLEMENTATION
#define CA_PRIVATE_IMPLEMENTATION
#define MTL_PRIVATE_IMPLEMENTATION
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>

View file

@ -0,0 +1,41 @@
#include "renderer_mtl/renderer_mtl.hpp"
RendererMTL::RendererMTL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs)
: Renderer(gpu, internalRegs, externalRegs) {}
RendererMTL::~RendererMTL() {}
void RendererMTL::reset() {
// TODO: implement
}
void RendererMTL::display() {
// TODO: implement
}
void RendererMTL::initGraphicsContext(SDL_Window* window) {
// TODO: implement
}
void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
// TODO: implement
}
void RendererMTL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) {
// TODO: implement
}
void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) {
// TODO: implement
}
void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) {
// TODO: implement
}
void RendererMTL::screenshot(const std::string& name) {
// TODO: implement
}
void RendererMTL::deinitGraphicsContext() {
// TODO: implement
}

View file

@ -1,4 +1,5 @@
#include "services/ac.hpp" #include "services/ac.hpp"
#include "ipc.hpp" #include "ipc.hpp"
namespace ACCommands { namespace ACCommands {
@ -130,7 +131,7 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
const u32 pidHeader = mem.read32(messagePointer + 4); const u32 pidHeader = mem.read32(messagePointer + 4);
const u32 copyHandleHeader = mem.read32(messagePointer + 12); const u32 copyHandleHeader = mem.read32(messagePointer + 12);
// Event signaled when disconnecting from AC. TODO: Properly implement it. // Event signaled when disconnecting from AC. TODO: Properly implement it.
const Handle eventHandle = mem.read32(messagePointer + 16); const HandleType eventHandle = mem.read32(messagePointer + 16);
disconnectEvent = eventHandle; disconnectEvent = eventHandle;

View file

@ -1,10 +1,11 @@
#include "services/apt.hpp" #include "services/apt.hpp"
#include "ipc.hpp"
#include "kernel.hpp"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include "ipc.hpp"
#include "kernel.hpp"
namespace APTCommands { namespace APTCommands {
enum : u32 { enum : u32 {
GetLockHandle = 0x00010040, GetLockHandle = 0x00010040,
@ -84,8 +85,7 @@ void APTService::appletUtility(u32 messagePointer) {
u32 outputSize = mem.read32(messagePointer + 12); u32 outputSize = mem.read32(messagePointer + 12);
u32 inputPointer = mem.read32(messagePointer + 20); u32 inputPointer = mem.read32(messagePointer + 20);
log("APT::AppletUtility(utility = %d, input size = %x, output size = %x, inputPointer = %08X)\n", utility, inputSize, outputSize, log("APT::AppletUtility(utility = %d, input size = %x, output size = %x, inputPointer = %08X)\n", utility, inputSize, outputSize, inputPointer);
inputPointer);
std::vector<u8> out(outputSize); std::vector<u8> out(outputSize);
const u32 outputBuffer = mem.read32(messagePointer + 0x104); const u32 outputBuffer = mem.read32(messagePointer + 0x104);
@ -144,7 +144,7 @@ void APTService::prepareToStartLibraryApplet(u32 messagePointer) {
void APTService::startLibraryApplet(u32 messagePointer) { void APTService::startLibraryApplet(u32 messagePointer) {
const u32 appID = mem.read32(messagePointer + 4); const u32 appID = mem.read32(messagePointer + 4);
const u32 bufferSize = mem.read32(messagePointer + 8); const u32 bufferSize = mem.read32(messagePointer + 8);
const Handle parameters = mem.read32(messagePointer + 16); const HandleType parameters = mem.read32(messagePointer + 16);
const u32 buffer = mem.read32(messagePointer + 24); const u32 buffer = mem.read32(messagePointer + 24);
log("APT::StartLibraryApplet (app ID = %X)\n", appID); log("APT::StartLibraryApplet (app ID = %X)\n", appID);
@ -213,8 +213,8 @@ void APTService::initialize(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 3)); mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 3));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 0x04000000); // Translation descriptor mem.write32(messagePointer + 8, 0x04000000); // Translation descriptor
mem.write32(messagePointer + 12, notificationEvent.value()); // Notification Event Handle mem.write32(messagePointer + 12, notificationEvent.value()); // Notification Event HandleType
mem.write32(messagePointer + 16, resumeEvent.value()); // Resume Event Handle mem.write32(messagePointer + 16, resumeEvent.value()); // Resume Event HandleType
} }
void APTService::inquireNotification(u32 messagePointer) { void APTService::inquireNotification(u32 messagePointer) {
@ -412,8 +412,7 @@ void APTService::getWirelessRebootInfo(u32 messagePointer) {
const u32 size = mem.read32(messagePointer + 4); // Size of data to read const u32 size = mem.read32(messagePointer + 4); // Size of data to read
log("APT::GetWirelessRebootInfo (size = %X)\n", size); log("APT::GetWirelessRebootInfo (size = %X)\n", size);
if (size > 0x10) if (size > 0x10) Helpers::panic("APT::GetWirelessInfo with size > 0x10 bytes");
Helpers::panic("APT::GetWirelessInfo with size > 0x10 bytes");
mem.write32(messagePointer, IPC::responseHeader(0x45, 1, 2)); mem.write32(messagePointer, IPC::responseHeader(0x45, 1, 2));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);

View file

@ -1,4 +1,5 @@
#include "services/boss.hpp" #include "services/boss.hpp"
#include "ipc.hpp" #include "ipc.hpp"
namespace BOSSCommands { namespace BOSSCommands {
@ -31,9 +32,7 @@ namespace BOSSCommands {
}; };
} }
void BOSSService::reset() { void BOSSService::reset() { optoutFlag = 0; }
optoutFlag = 0;
}
void BOSSService::handleSyncRequest(u32 messagePointer) { void BOSSService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
@ -44,8 +43,7 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
case BOSSCommands::GetNsDataIdList: case BOSSCommands::GetNsDataIdList:
case BOSSCommands::GetNsDataIdList1: case BOSSCommands::GetNsDataIdList1:
case BOSSCommands::GetNsDataIdList2: case BOSSCommands::GetNsDataIdList2:
case BOSSCommands::GetNsDataIdList3: case BOSSCommands::GetNsDataIdList3: getNsDataIdList(messagePointer, command); break;
getNsDataIdList(messagePointer, command); break;
case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break; case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break;
case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break; case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break;
case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break; case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break;
@ -173,7 +171,6 @@ void BOSSService::sendProperty(u32 messagePointer) {
// TODO: Should this do anything else? // TODO: Should this do anything else?
} }
void BOSSService::receiveProperty(u32 messagePointer) { void BOSSService::receiveProperty(u32 messagePointer) {
const u32 id = mem.read32(messagePointer + 4); const u32 id = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
@ -188,7 +185,7 @@ void BOSSService::receiveProperty(u32 messagePointer) {
// This seems to accept a KEvent as a parameter and register it for something Spotpass related // This seems to accept a KEvent as a parameter and register it for something Spotpass related
// I need to update the 3DBrew page when it's known what it does properly // I need to update the 3DBrew page when it's known what it does properly
void BOSSService::registerNewArrivalEvent(u32 messagePointer) { void BOSSService::registerNewArrivalEvent(u32 messagePointer) {
const Handle eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register const HandleType eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register
log("BOSS::RegisterNewArrivalEvent (handle = %X)\n", eventHandle); log("BOSS::RegisterNewArrivalEvent (handle = %X)\n", eventHandle);
mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0));

View file

@ -312,7 +312,7 @@ void CAMService::setReceiving(u32 messagePointer) {
const u32 portIndex = mem.read8(messagePointer + 8); const u32 portIndex = mem.read8(messagePointer + 8);
const u32 size = mem.read32(messagePointer + 12); const u32 size = mem.read32(messagePointer + 12);
const u16 transferUnit = mem.read16(messagePointer + 16); const u16 transferUnit = mem.read16(messagePointer + 16);
const Handle process = mem.read32(messagePointer + 24); const HandleType process = mem.read32(messagePointer + 24);
const PortSelect port(portIndex); const PortSelect port(portIndex);
log("CAM::SetReceiving (port = %d)\n", portIndex); log("CAM::SetReceiving (port = %d)\n", portIndex);

View file

@ -1,10 +1,11 @@
#include "services/dsp.hpp" #include "services/dsp.hpp"
#include "ipc.hpp"
#include "kernel.hpp"
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
#include "ipc.hpp"
#include "kernel.hpp"
namespace DSPCommands { namespace DSPCommands {
enum : u32 { enum : u32 {
RecvData = 0x00010040, RecvData = 0x00010040,
@ -25,10 +26,7 @@ namespace DSPCommands {
} }
namespace Result { namespace Result {
enum : u32 { enum : u32 { HeadphonesNotInserted = 0, HeadphonesInserted = 1 };
HeadphonesNotInserted = 0,
HeadphonesInserted = 1
};
} }
void DSPService::reset() { void DSPService::reset() {
@ -153,12 +151,10 @@ DSPService::DSPEvent& DSPService::getEventRef(u32 type, u32 pipe) {
case 1: return interrupt1; case 1: return interrupt1;
case 2: case 2:
if (pipe >= pipeCount) if (pipe >= pipeCount) Helpers::panic("Tried to access the event of an invalid pipe");
Helpers::panic("Tried to access the event of an invalid pipe");
return pipeEvents[pipe]; return pipeEvents[pipe];
default: default: Helpers::panic("Unknown type for DSP::getEventRef");
Helpers::panic("Unknown type for DSP::getEventRef");
} }
} }
@ -249,7 +245,7 @@ void DSPService::writeProcessPipe(u32 messagePointer) {
void DSPService::flushDataCache(u32 messagePointer) { void DSPService::flushDataCache(u32 messagePointer) {
const u32 address = mem.read32(messagePointer + 4); const u32 address = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
const Handle process = mem.read32(messagePointer + 16); const HandleType process = mem.read32(messagePointer + 16);
log("DSP::FlushDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process); log("DSP::FlushDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process);
mem.write32(messagePointer, IPC::responseHeader(0x13, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x13, 1, 0));
@ -259,7 +255,7 @@ void DSPService::flushDataCache(u32 messagePointer) {
void DSPService::invalidateDCache(u32 messagePointer) { void DSPService::invalidateDCache(u32 messagePointer) {
const u32 address = mem.read32(messagePointer + 4); const u32 address = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
const Handle process = mem.read32(messagePointer + 16); const HandleType process = mem.read32(messagePointer + 16);
log("DSP::InvalidateDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process); log("DSP::InvalidateDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process);
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0));

View file

@ -1,7 +1,8 @@
#include "services/fs.hpp" #include "services/fs.hpp"
#include "kernel/kernel.hpp"
#include "io_file.hpp" #include "io_file.hpp"
#include "ipc.hpp" #include "ipc.hpp"
#include "kernel/kernel.hpp"
#include "result/result.hpp" #include "result/result.hpp"
#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does. #ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
@ -47,9 +48,7 @@ namespace FSCommands {
}; };
} }
void FSService::reset() { void FSService::reset() { priority = 0; }
priority = 0;
}
// Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM. // Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
void FSService::initializeFilesystem() { void FSService::initializeFilesystem() {
@ -61,7 +60,6 @@ void FSService::initializeFilesystem() {
const auto systemSaveDataPath = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData"; const auto systemSaveDataPath = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
namespace fs = std::filesystem; namespace fs = std::filesystem;
if (!fs::is_directory(nandSharedpath)) { if (!fs::is_directory(nandSharedpath)) {
fs::create_directories(nandSharedpath); fs::create_directories(nandSharedpath);
} }
@ -89,23 +87,19 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
case ArchiveID::SaveData: return &saveData; case ArchiveID::SaveData: return &saveData;
case ArchiveID::UserSaveData2: return &userSaveData2; case ArchiveID::UserSaveData2: return &userSaveData2;
case ArchiveID::ExtSaveData: case ArchiveID::ExtSaveData: return &extSaveData_sdmc;
return &extSaveData_sdmc;
case ArchiveID::SharedExtSaveData: case ArchiveID::SharedExtSaveData: return &sharedExtSaveData_nand;
return &sharedExtSaveData_nand;
case ArchiveID::SystemSaveData: return &systemSaveData; case ArchiveID::SystemSaveData: return &systemSaveData;
case ArchiveID::SDMC: return &sdmc; case ArchiveID::SDMC: return &sdmc;
case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly; case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly;
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
default: default: Helpers::panic("Unknown archive. ID: %d\n", id); return nullptr;
Helpers::panic("Unknown archive. ID: %d\n", id);
return nullptr;
} }
} }
std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms) { std::optional<HandleType> FSService::openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms) {
FileDescriptor opened = archive->openFile(path, perms); FileDescriptor opened = archive->openFile(path, perms);
if (opened.has_value()) { // If opened doesn't have a value, we failed to open the file if (opened.has_value()) { // If opened doesn't have a value, we failed to open the file
auto handle = kernel.makeObject(KernelObjectType::File); auto handle = kernel.makeObject(KernelObjectType::File);
@ -119,7 +113,7 @@ std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPa
} }
} }
Rust::Result<Handle, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) { Rust::Result<HandleType, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) {
Rust::Result<DirectorySession, Result::HorizonResult> opened = archive->openDirectory(path); Rust::Result<DirectorySession, Result::HorizonResult> opened = archive->openDirectory(path);
if (opened.isOk()) { // If opened doesn't have a value, we failed to open the directory if (opened.isOk()) { // If opened doesn't have a value, we failed to open the directory
auto handle = kernel.makeObject(KernelObjectType::Directory); auto handle = kernel.makeObject(KernelObjectType::Directory);
@ -132,7 +126,7 @@ Rust::Result<Handle, Result::HorizonResult> FSService::openDirectoryHandle(Archi
} }
} }
Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) { Rust::Result<HandleType, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
ArchiveBase* archive = getArchiveFromID(archiveID, path); ArchiveBase* archive = getArchiveFromID(archiveID, path);
if (archive == nullptr) [[unlikely]] { if (archive == nullptr) [[unlikely]] {
@ -147,8 +141,7 @@ Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 arc
archiveObject.data = new ArchiveSession(res.unwrap(), path); archiveObject.data = new ArchiveSession(res.unwrap(), path);
return Ok(handle); return Ok(handle);
} } else {
else {
return Err(res.unwrapErr()); return Err(res.unwrapErr());
} }
} }
@ -157,8 +150,7 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
std::vector<u8> data; std::vector<u8> data;
data.resize(size); data.resize(size);
for (u32 i = 0; i < size; i++) for (u32 i = 0; i < size; i++) data[i] = mem.read8(pointer + i);
data[i] = mem.read8(pointer + i);
return FSPath(type, data); return FSPath(type, data);
} }
@ -217,7 +209,7 @@ void FSService::initializeWithSdkVersion(u32 messagePointer) {
} }
void FSService::closeArchive(u32 messagePointer) { void FSService::closeArchive(u32 messagePointer) {
const Handle handle = static_cast<u32>(mem.read64(messagePointer + 4)); // TODO: archive handles should be 64-bit const HandleType handle = static_cast<u32>(mem.read64(messagePointer + 4)); // TODO: archive handles should be 64-bit
const auto object = kernel.getObject(handle, KernelObjectType::Archive); const auto object = kernel.getObject(handle, KernelObjectType::Archive);
log("FSService::CloseArchive(handle = %X)\n", handle); log("FSService::CloseArchive(handle = %X)\n", handle);
@ -241,7 +233,7 @@ void FSService::openArchive(u32 messagePointer) {
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize); auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType); log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType);
Rust::Result<Handle, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath); Rust::Result<HandleType, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
mem.write32(messagePointer, IPC::responseHeader(0x80C, 3, 0)); mem.write32(messagePointer, IPC::responseHeader(0x80C, 3, 0));
if (res.isOk()) { if (res.isOk()) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
@ -254,7 +246,7 @@ void FSService::openArchive(u32 messagePointer) {
} }
void FSService::openFile(u32 messagePointer) { void FSService::openFile(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8)); const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
const u32 filePathType = mem.read32(messagePointer + 16); const u32 filePathType = mem.read32(messagePointer + 16);
const u32 filePathSize = mem.read32(messagePointer + 20); const u32 filePathSize = mem.read32(messagePointer + 20);
const u32 openFlags = mem.read32(messagePointer + 24); const u32 openFlags = mem.read32(messagePointer + 24);
@ -276,7 +268,7 @@ void FSService::openFile(u32 messagePointer) {
auto filePath = readPath(filePathType, filePathPointer, filePathSize); auto filePath = readPath(filePathType, filePathPointer, filePathSize);
const FilePerms perms(openFlags); const FilePerms perms(openFlags);
std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms); std::optional<HandleType> handle = openFileHandle(archive, filePath, archivePath, perms);
mem.write32(messagePointer, IPC::responseHeader(0x802, 1, 2)); mem.write32(messagePointer, IPC::responseHeader(0x802, 1, 2));
if (!handle.has_value()) { if (!handle.has_value()) {
printf("OpenFile failed\n"); printf("OpenFile failed\n");
@ -291,7 +283,7 @@ void FSService::openFile(u32 messagePointer) {
void FSService::createDirectory(u32 messagePointer) { void FSService::createDirectory(u32 messagePointer) {
log("FS::CreateDirectory\n"); log("FS::CreateDirectory\n");
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 8); const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 8);
const u32 pathType = mem.read32(messagePointer + 16); const u32 pathType = mem.read32(messagePointer + 16);
const u32 pathSize = mem.read32(messagePointer + 20); const u32 pathSize = mem.read32(messagePointer + 20);
const u32 pathPointer = mem.read32(messagePointer + 32); const u32 pathPointer = mem.read32(messagePointer + 32);
@ -313,7 +305,7 @@ void FSService::createDirectory(u32 messagePointer) {
void FSService::openDirectory(u32 messagePointer) { void FSService::openDirectory(u32 messagePointer) {
log("FS::OpenDirectory\n"); log("FS::OpenDirectory\n");
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 4); const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 4);
const u32 pathType = mem.read32(messagePointer + 12); const u32 pathType = mem.read32(messagePointer + 12);
const u32 pathSize = mem.read32(messagePointer + 16); const u32 pathSize = mem.read32(messagePointer + 16);
const u32 pathPointer = mem.read32(messagePointer + 24); const u32 pathPointer = mem.read32(messagePointer + 24);
@ -366,7 +358,7 @@ void FSService::openFileDirectly(u32 messagePointer) {
} }
archive = res.unwrap(); archive = res.unwrap();
std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms); std::optional<HandleType> handle = openFileHandle(archive, filePath, archivePath, perms);
mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2)); mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2));
if (!handle.has_value()) { if (!handle.has_value()) {
printf("OpenFileDirectly failed\n"); printf("OpenFileDirectly failed\n");
@ -378,7 +370,7 @@ void FSService::openFileDirectly(u32 messagePointer) {
} }
void FSService::createFile(u32 messagePointer) { void FSService::createFile(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8)); const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
const u32 filePathType = mem.read32(messagePointer + 16); const u32 filePathType = mem.read32(messagePointer + 16);
const u32 filePathSize = mem.read32(messagePointer + 20); const u32 filePathSize = mem.read32(messagePointer + 20);
const u32 attributes = mem.read32(messagePointer + 24); const u32 attributes = mem.read32(messagePointer + 24);
@ -403,7 +395,7 @@ void FSService::createFile(u32 messagePointer) {
} }
void FSService::deleteFile(u32 messagePointer) { void FSService::deleteFile(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8)); const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
const u32 filePathType = mem.read32(messagePointer + 16); const u32 filePathType = mem.read32(messagePointer + 16);
const u32 filePathSize = mem.read32(messagePointer + 20); const u32 filePathSize = mem.read32(messagePointer + 20);
const u32 filePathPointer = mem.read32(messagePointer + 28); const u32 filePathPointer = mem.read32(messagePointer + 28);
@ -425,7 +417,7 @@ void FSService::deleteFile(u32 messagePointer) {
} }
void FSService::deleteDirectory(u32 messagePointer) { void FSService::deleteDirectory(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8)); const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
const u32 filePathType = mem.read32(messagePointer + 16); const u32 filePathType = mem.read32(messagePointer + 16);
const u32 filePathSize = mem.read32(messagePointer + 20); const u32 filePathSize = mem.read32(messagePointer + 20);
const u32 filePathPointer = mem.read32(messagePointer + 28); const u32 filePathPointer = mem.read32(messagePointer + 28);
@ -470,8 +462,7 @@ void FSService::formatSaveData(u32 messagePointer) {
log("FS::FormatSaveData\n"); log("FS::FormatSaveData\n");
const u32 archiveID = mem.read32(messagePointer + 4); const u32 archiveID = mem.read32(messagePointer + 4);
if (archiveID != ArchiveID::SaveData) if (archiveID != ArchiveID::SaveData) Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
// Read path and path info // Read path and path info
const u32 pathType = mem.read32(messagePointer + 8); const u32 pathType = mem.read32(messagePointer + 8);
@ -481,8 +472,7 @@ void FSService::formatSaveData(u32 messagePointer) {
// Size of a block. Seems to always be 0x200 // Size of a block. Seems to always be 0x200
const u32 blockSize = mem.read32(messagePointer + 16); const u32 blockSize = mem.read32(messagePointer + 16);
if (blockSize != 0x200 && blockSize != 0x1000) if (blockSize != 0x200 && blockSize != 0x1000) Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories
const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files
@ -490,12 +480,7 @@ void FSService::formatSaveData(u32 messagePointer) {
const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here
const bool duplicateData = mem.read8(messagePointer + 36) != 0; const bool duplicateData = mem.read8(messagePointer + 36) != 0;
ArchiveBase::FormatInfo info { ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
.size = blockSize * 0x200,
.numOfDirectories = directoryNum,
.numOfFiles = fileNum,
.duplicateData = duplicateData
};
saveData.format(path, info); saveData.format(path, info);
@ -512,8 +497,8 @@ void FSService::deleteExtSaveData(u32 messagePointer) {
log("FS::DeleteExtSaveData (media type = %d, saveID = %llx) (stubbed)\n", mediaType, saveID); log("FS::DeleteExtSaveData (media type = %d, saveID = %llx) (stubbed)\n", mediaType, saveID);
mem.write32(messagePointer, IPC::responseHeader(0x0852, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x0852, 1, 0));
// TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required for Planet Robobot // TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required
// When we properly implement it, it will just be a recursive directory deletion // for Planet Robobot When we properly implement it, it will just be a recursive directory deletion
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
@ -521,7 +506,8 @@ void FSService::createExtSaveData(u32 messagePointer) {
Helpers::warn("Stubbed call to FS::CreateExtSaveData!"); Helpers::warn("Stubbed call to FS::CreateExtSaveData!");
// First 4 words of parameters are the ExtSaveData info // First 4 words of parameters are the ExtSaveData info
// https://www.3dbrew.org/wiki/Filesystem_services#ExtSaveDataInfo // https://www.3dbrew.org/wiki/Filesystem_services#ExtSaveDataInfo
// This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created directory. // This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created
// directory.
const u8 mediaType = mem.read8(messagePointer + 4); const u8 mediaType = mem.read8(messagePointer + 4);
const u64 saveID = mem.read64(messagePointer + 8); const u64 saveID = mem.read64(messagePointer + 8);
const u32 numOfDirectories = mem.read32(messagePointer + 20); const u32 numOfDirectories = mem.read32(messagePointer + 20);
@ -547,12 +533,7 @@ void FSService::formatThisUserSaveData(u32 messagePointer) {
const u32 fileBucketNum = mem.read32(messagePointer + 20); // Same here const u32 fileBucketNum = mem.read32(messagePointer + 20); // Same here
const bool duplicateData = mem.read8(messagePointer + 24) != 0; const bool duplicateData = mem.read8(messagePointer + 24) != 0;
ArchiveBase::FormatInfo info { ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
.size = blockSize * 0x200,
.numOfDirectories = directoryNum,
.numOfFiles = fileNum,
.duplicateData = duplicateData
};
FSPath emptyPath; FSPath emptyPath;
mem.write32(messagePointer, IPC::responseHeader(0x080F, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x080F, 1, 0));
@ -560,7 +541,7 @@ void FSService::formatThisUserSaveData(u32 messagePointer) {
} }
void FSService::controlArchive(u32 messagePointer) { void FSService::controlArchive(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 4)); const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 4));
const u32 action = mem.read32(messagePointer + 12); const u32 action = mem.read32(messagePointer + 12);
const u32 inputSize = mem.read32(messagePointer + 16); const u32 inputSize = mem.read32(messagePointer + 16);
const u32 outputSize = mem.read32(messagePointer + 20); const u32 outputSize = mem.read32(messagePointer + 20);
@ -587,15 +568,13 @@ void FSService::controlArchive(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
break; break;
default: default: Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action); break;
Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action);
break;
} }
} }
void FSService::getFreeBytes(u32 messagePointer) { void FSService::getFreeBytes(u32 messagePointer) {
log("FS::GetFreeBytes\n"); log("FS::GetFreeBytes\n");
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 4); const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 4);
auto session = kernel.getObject(archiveHandle, KernelObjectType::Archive); auto session = kernel.getObject(archiveHandle, KernelObjectType::Archive);
mem.write32(messagePointer, IPC::responseHeader(0x812, 3, 0)); mem.write32(messagePointer, IPC::responseHeader(0x812, 3, 0));
@ -639,7 +618,7 @@ void FSService::getArchiveResource(u32 messagePointer) {
} }
void FSService::setArchivePriority(u32 messagePointer) { void FSService::setArchivePriority(u32 messagePointer) {
Handle archive = mem.read64(messagePointer + 4); HandleType archive = mem.read64(messagePointer + 4);
const u32 value = mem.read32(messagePointer + 12); const u32 value = mem.read32(messagePointer + 12);
log("FS::SetArchivePriority (priority = %d, archive handle = %X)\n", value, handle); log("FS::SetArchivePriority (priority = %d, archive handle = %X)\n", value, handle);
@ -731,8 +710,8 @@ void FSService::renameFile(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x805, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x805, 1, 0));
const Handle sourceArchiveHandle = mem.read64(messagePointer + 8); const HandleType sourceArchiveHandle = mem.read64(messagePointer + 8);
const Handle destArchiveHandle = mem.read64(messagePointer + 24); const HandleType destArchiveHandle = mem.read64(messagePointer + 24);
// Read path info // Read path info
const u32 sourcePathType = mem.read32(messagePointer + 16); const u32 sourcePathType = mem.read32(messagePointer + 16);

View file

@ -1,7 +1,9 @@
#include "services/hid.hpp" #include "services/hid.hpp"
#include <bit>
#include "ipc.hpp" #include "ipc.hpp"
#include "kernel.hpp" #include "kernel.hpp"
#include <bit>
namespace HIDCommands { namespace HIDCommands {
enum : u32 { enum : u32 {
@ -140,7 +142,7 @@ void HIDService::getIPCHandles(u32 messagePointer) {
// Write HID event handles // Write HID event handles
for (int i = 0; i < events.size(); i++) { for (int i = 0; i < events.size(); i++) {
mem.write32(messagePointer + 16 + sizeof(Handle) * i, events[i].value()); mem.write32(messagePointer + 16 + sizeof(HandleType) * i, events[i].value());
} }
} }

View file

@ -1,10 +1,11 @@
#include "services/ldr_ro.hpp" #include "services/ldr_ro.hpp"
#include "ipc.hpp"
#include "kernel.hpp"
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "ipc.hpp"
#include "kernel.hpp"
namespace LDRCommands { namespace LDRCommands {
enum : u32 { enum : u32 {
Initialize = 0x000100C2, Initialize = 0x000100C2,
@ -65,10 +66,13 @@ namespace SegmentTable {
namespace SegmentID { namespace SegmentID {
enum : u32 { enum : u32 {
TEXT, RODATA, DATA, BSS, TEXT,
RODATA,
DATA,
BSS,
}; };
} }
} } // namespace SegmentTable
namespace NamedExportTable { namespace NamedExportTable {
enum : u32 { enum : u32 {
@ -129,7 +133,7 @@ namespace RelocationPatch {
AbsoluteAddress = 2, AbsoluteAddress = 2,
}; };
}; };
}; }; // namespace RelocationPatch
struct CROHeaderEntry { struct CROHeaderEntry {
u32 offset, size; u32 offset, size;
@ -159,21 +163,13 @@ public:
return mem.readString(moduleName.offset, moduleName.size); return mem.readString(moduleName.offset, moduleName.size);
} }
u32 getNextCRO() { u32 getNextCRO() { return mem.read32(croPointer + CROHeader::NextCRO); }
return mem.read32(croPointer + CROHeader::NextCRO);
}
u32 getPrevCRO() { u32 getPrevCRO() { return mem.read32(croPointer + CROHeader::PrevCRO); }
return mem.read32(croPointer + CROHeader::PrevCRO);
}
void setNextCRO(u32 nextCRO) { void setNextCRO(u32 nextCRO) { mem.write32(croPointer + CROHeader::NextCRO, nextCRO); }
mem.write32(croPointer + CROHeader::NextCRO, nextCRO);
}
void setPrevCRO(u32 prevCRO) { void setPrevCRO(u32 prevCRO) { mem.write32(croPointer + CROHeader::PrevCRO, prevCRO); }
mem.write32(croPointer + CROHeader::PrevCRO, prevCRO);
}
void write32(u32 addr, u32 value) { void write32(u32 addr, u32 value) {
// Note: some games export symbols to the static module, which doesn't contain any segments. // Note: some games export symbols to the static module, which doesn't contain any segments.
@ -219,9 +215,7 @@ public:
return entryOffset + offset; return entryOffset + offset;
} }
u32 getOnUnresolvedAddr() { u32 getOnUnresolvedAddr() { return getSegmentAddr(mem.read32(croPointer + CROHeader::OnUnresolved)); }
return getSegmentAddr(mem.read32(croPointer + CROHeader::OnUnresolved));
}
u32 getNamedExportSymbolAddr(const std::string &symbolName) { u32 getNamedExportSymbolAddr(const std::string &symbolName) {
// Note: The CRO contains a trie for fast symbol lookup. For simplicity, // Note: The CRO contains a trie for fast symbol lookup. For simplicity,
@ -437,13 +431,16 @@ public:
const u32 segmentID = mem.read32(segmentTable.offset + 12 * segment + SegmentTable::ID); const u32 segmentID = mem.read32(segmentTable.offset + 12 * segment + SegmentTable::ID);
switch (segmentID) { switch (segmentID) {
case SegmentTable::SegmentID::DATA: case SegmentTable::SegmentID::DATA:
*oldDataVaddr = segmentOffset + croPointer; oldDataSegmentOffset = segmentOffset; segmentOffset = dataVaddr; break; *oldDataVaddr = segmentOffset + croPointer;
oldDataSegmentOffset = segmentOffset;
segmentOffset = dataVaddr;
break;
case SegmentTable::SegmentID::BSS: segmentOffset = bssVaddr; break; case SegmentTable::SegmentID::BSS: segmentOffset = bssVaddr; break;
case SegmentTable::SegmentID::TEXT: case SegmentTable::SegmentID::TEXT:
case SegmentTable::SegmentID::RODATA: case SegmentTable::SegmentID::RODATA:
if (segmentOffset != 0) segmentOffset += croPointer; break; if (segmentOffset != 0) segmentOffset += croPointer;
default: break;
Helpers::panic("Unknown segment ID = %u", segmentID); default: Helpers::panic("Unknown segment ID = %u", segmentID);
} }
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset); mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
@ -464,9 +461,9 @@ public:
case SegmentTable::SegmentID::BSS: segmentOffset = 0; break; case SegmentTable::SegmentID::BSS: segmentOffset = 0; break;
case SegmentTable::SegmentID::TEXT: case SegmentTable::SegmentID::TEXT:
case SegmentTable::SegmentID::RODATA: case SegmentTable::SegmentID::RODATA:
if (segmentOffset != 0) segmentOffset -= croPointer; break; if (segmentOffset != 0) segmentOffset -= croPointer;
default: break;
Helpers::panic("Unknown segment ID = %u", segmentID); default: Helpers::panic("Unknown segment ID = %u", segmentID);
} }
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset); mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
@ -630,7 +627,9 @@ public:
u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset); u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
if (relocationOffset != 0) { if (relocationOffset != 0) {
mem.write32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset + croPointer); mem.write32(
anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset + croPointer
);
} }
} }
@ -644,7 +643,9 @@ public:
u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset); u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
if (relocationOffset != 0) { if (relocationOffset != 0) {
mem.write32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer); mem.write32(
anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer
);
} }
} }
@ -1189,9 +1190,7 @@ public:
} }
}; };
void LDRService::reset() { void LDRService::reset() { loadedCRS = 0; }
loadedCRS = 0;
}
void LDRService::handleSyncRequest(u32 messagePointer) { void LDRService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
@ -1210,7 +1209,7 @@ void LDRService::initialize(u32 messagePointer) {
const u32 crsPointer = mem.read32(messagePointer + 4); const u32 crsPointer = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
const u32 mapVaddr = mem.read32(messagePointer + 12); const u32 mapVaddr = mem.read32(messagePointer + 12);
const Handle process = mem.read32(messagePointer + 20); const HandleType process = mem.read32(messagePointer + 20);
log("LDR_RO::Initialize (buffer = %08X, size = %08X, vaddr = %08X, process = %X)\n", crsPointer, size, mapVaddr, process); log("LDR_RO::Initialize (buffer = %08X, size = %08X, vaddr = %08X, process = %X)\n", crsPointer, size, mapVaddr, process);
@ -1258,7 +1257,7 @@ void LDRService::initialize(u32 messagePointer) {
void LDRService::linkCRO(u32 messagePointer) { void LDRService::linkCRO(u32 messagePointer) {
const u32 mapVaddr = mem.read32(messagePointer + 4); const u32 mapVaddr = mem.read32(messagePointer + 4);
const Handle process = mem.read32(messagePointer + 12); const HandleType process = mem.read32(messagePointer + 12);
log("LDR_RO::LinkCRO (vaddr = %X, process = %X)\n", mapVaddr, process); log("LDR_RO::LinkCRO (vaddr = %X, process = %X)\n", mapVaddr, process);
@ -1287,7 +1286,7 @@ void LDRService::linkCRO(u32 messagePointer) {
void LDRService::loadCRR(u32 messagePointer) { void LDRService::loadCRR(u32 messagePointer) {
const u32 crrPointer = mem.read32(messagePointer + 4); const u32 crrPointer = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
const Handle process = mem.read32(messagePointer + 20); const HandleType process = mem.read32(messagePointer + 20);
log("LDR_RO::LoadCRR (buffer = %08X, size = %08X, process = %X)\n", crrPointer, size, process); log("LDR_RO::LoadCRR (buffer = %08X, size = %08X, process = %X)\n", crrPointer, size, process);
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
@ -1304,9 +1303,11 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
const u32 bssSize = mem.read32(messagePointer + 32); const u32 bssSize = mem.read32(messagePointer + 32);
const bool autoLink = mem.read32(messagePointer + 36) != 0; const bool autoLink = mem.read32(messagePointer + 36) != 0;
const u32 fixLevel = mem.read32(messagePointer + 40); const u32 fixLevel = mem.read32(messagePointer + 40);
const Handle process = mem.read32(messagePointer + 52); const HandleType process = mem.read32(messagePointer + 52);
log("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size = %08X, auto link = %d, fix level = %X, process = %X)\n", isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process); log("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size "
"= %08X, auto link = %d, fix level = %X, process = %X)\n",
isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process);
// Sanity checks // Sanity checks
if (size < CRO_HEADER_SIZE) { if (size < CRO_HEADER_SIZE) {
@ -1362,7 +1363,7 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
void LDRService::unloadCRO(u32 messagePointer) { void LDRService::unloadCRO(u32 messagePointer) {
const u32 mapVaddr = mem.read32(messagePointer + 4); const u32 mapVaddr = mem.read32(messagePointer + 4);
const u32 croPointer = mem.read32(messagePointer + 12); const u32 croPointer = mem.read32(messagePointer + 12);
const Handle process = mem.read32(messagePointer + 20); const HandleType process = mem.read32(messagePointer + 20);
log("LDR_RO::UnloadCRO (vaddr = %08X, buffer = %08X, process = %X)\n", mapVaddr, croPointer, process); log("LDR_RO::UnloadCRO (vaddr = %08X, buffer = %08X, process = %X)\n", mapVaddr, croPointer, process);

View file

@ -8,8 +8,8 @@
ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config) ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config)
: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem), : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem),
csnd(mem, kernel), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config), csnd(mem, kernel), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config),
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem),
news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {} ndm(mem), news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
static constexpr int MAX_NOTIFICATION_COUNT = 16; static constexpr int MAX_NOTIFICATION_COUNT = 16;
@ -68,7 +68,7 @@ namespace Commands {
}; };
} }
// Handle an IPC message issued using the SendSyncRequest SVC // HandleType an IPC message issued using the SendSyncRequest SVC
// The parameters are stored in thread-local storage in this format: https://www.3dbrew.org/wiki/IPC#Message_Structure // The parameters are stored in thread-local storage in this format: https://www.3dbrew.org/wiki/IPC#Message_Structure
// messagePointer: The base pointer for the IPC message // messagePointer: The base pointer for the IPC message
void ServiceManager::handleSyncRequest(u32 messagePointer) { void ServiceManager::handleSyncRequest(u32 messagePointer) {
@ -93,7 +93,7 @@ void ServiceManager::registerClient(u32 messagePointer) {
} }
// clang-format off // clang-format off
static std::map<std::string, Handle> serviceMap = { static std::map<std::string, HandleType> serviceMap = {
{ "ac:u", KernelHandles::AC }, { "ac:u", KernelHandles::AC },
{ "act:a", KernelHandles::ACT }, { "act:a", KernelHandles::ACT },
{ "act:u", KernelHandles::ACT }, { "act:u", KernelHandles::ACT },
@ -167,7 +167,7 @@ void ServiceManager::enableNotification(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 2)); mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 2));
mem.write32(messagePointer + 4, Result::Success); // Result code mem.write32(messagePointer + 4, Result::Success); // Result code
mem.write32(messagePointer + 8, 0); // Translation descriptor mem.write32(messagePointer + 8, 0); // Translation descriptor
// Handle to semaphore signaled on process notification // HandleType to semaphore signaled on process notification
mem.write32(messagePointer + 12, notificationSemaphore.value()); mem.write32(messagePointer + 12, notificationSemaphore.value());
} }
@ -195,7 +195,7 @@ void ServiceManager::unsubscribe(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) { void ServiceManager::sendCommandToService(u32 messagePointer, HandleType handle) {
switch (handle) { switch (handle) {
// Breaking alphabetical order a bit to place the ones I think are most common at the top // Breaking alphabetical order a bit to place the ones I think are most common at the top
case KernelHandles::GPU: [[likely]] gsp_gpu.handleSyncRequest(messagePointer); break; case KernelHandles::GPU: [[likely]] gsp_gpu.handleSyncRequest(messagePointer); break;

View file

@ -21,7 +21,7 @@ void SOCService::handleSyncRequest(u32 messagePointer) {
void SOCService::initializeSockets(u32 messagePointer) { void SOCService::initializeSockets(u32 messagePointer) {
const u32 memoryBlockSize = mem.read32(messagePointer + 4); const u32 memoryBlockSize = mem.read32(messagePointer + 4);
const Handle sharedMemHandle = mem.read32(messagePointer + 20); const HandleType sharedMemHandle = mem.read32(messagePointer + 20);
log("SOC::InitializeSockets (memory block size = %08X, shared mem handle = %08X)\n", memoryBlockSize, sharedMemHandle); log("SOC::InitializeSockets (memory block size = %08X, shared mem handle = %08X)\n", memoryBlockSize, sharedMemHandle);
// TODO: Does double initialization return an error code? // TODO: Does double initialization return an error code?

View file

@ -0,0 +1,16 @@
struct VertexOut {
float4 position [[position]];
float2 uv;
};
vertex VertexOut vertexMain(uint vid [[vertex_id]]) {
VertexOut out;
out.uv = float2((vid << 1) & 2, vid & 2);
out.position = float4(out.uv * 2.0f + -1.0f, 0.0f, 1.0f);
return out;
}
fragment float4 fragmentMain(VertexOut in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler samplr [[sampler(0)]]) {
return tex.sample(samplr, in.uv);
}

View file

@ -11,7 +11,8 @@
#include "input_mappings.hpp" #include "input_mappings.hpp"
#include "services/dsp.hpp" #include "services/dsp.hpp"
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()), screen(this) { MainWindow::MainWindow(QApplication* app, QWidget* parent)
: QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()), screen(this) {
setWindowTitle("Alber"); setWindowTitle("Alber");
// Enable drop events for loading ROMs // Enable drop events for loading ROMs
setAcceptDrops(true); setAcceptDrops(true);
@ -90,6 +91,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
const RendererType rendererType = emu->getConfig().rendererType; const RendererType rendererType = emu->getConfig().rendererType;
usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null); usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null);
usingVk = (rendererType == RendererType::Vulkan); usingVk = (rendererType == RendererType::Vulkan);
usingMtl = (rendererType == RendererType::Metal);
if (usingGL) { if (usingGL) {
// Make GL context current for this thread, enable VSync // Make GL context current for this thread, enable VSync
@ -100,6 +102,8 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
emu->initGraphicsContext(glContext); emu->initGraphicsContext(glContext);
} else if (usingVk) { } else if (usingVk) {
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!"); Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
} else if (usingMtl) {
Helpers::panic("Metal on Qt is currently WIP, try the SDL frontend instead!");
} else { } else {
Helpers::panic("Unsupported graphics backend for Qt frontend!"); Helpers::panic("Unsupported graphics backend for Qt frontend!");
} }
@ -264,8 +268,7 @@ void MainWindow::dumpDspFirmware() {
case DSPService::ComponentDumpResult::Success: break; case DSPService::ComponentDumpResult::Success: break;
case DSPService::ComponentDumpResult::NotLoaded: { case DSPService::ComponentDumpResult::NotLoaded: {
QMessageBox messageBox( QMessageBox messageBox(
QMessageBox::Icon::Warning, tr("No DSP firmware loaded"), QMessageBox::Icon::Warning, tr("No DSP firmware loaded"), tr("The currently loaded app has not uploaded a firmware to the DSP")
tr("The currently loaded app has not uploaded a firmware to the DSP")
); );
QAbstractButton* button = messageBox.addButton(tr("OK"), QMessageBox::ButtonRole::YesRole); QAbstractButton* button = messageBox.addButton(tr("OK"), QMessageBox::ButtonRole::YesRole);

View file

@ -63,6 +63,16 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
} }
#endif #endif
#ifdef PANDA3DS_ENABLE_METAL
if (config.rendererType == RendererType::Metal) {
window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_METAL);
if (window == nullptr) {
Helpers::warn("Window creation failed: %s", SDL_GetError());
}
}
#endif
emu.initGraphicsContext(window); emu.initGraphicsContext(window);
} }
@ -240,7 +250,7 @@ void FrontendSDL::run() {
case SDL_MOUSEMOTION: { case SDL_MOUSEMOTION: {
if (emu.romType == ROMType::None) break; if (emu.romType == ROMType::None) break;
// Handle "dragging" across the touchscreen // HandleType "dragging" across the touchscreen
if (hid.isTouchScreenPressed()) { if (hid.isTouchScreenPressed()) {
const s32 x = event.motion.x; const s32 x = event.motion.x;
const s32 y = event.motion.y; const s32 y = event.motion.y;

View file

@ -18,7 +18,7 @@ std::optional<RendererType> Renderer::typeFromString(std::string inString) {
{"gl", RendererType::OpenGL}, {"ogl", RendererType::OpenGL}, {"opengl", RendererType::OpenGL}, {"gl", RendererType::OpenGL}, {"ogl", RendererType::OpenGL}, {"opengl", RendererType::OpenGL},
{"vk", RendererType::Vulkan}, {"vulkan", RendererType::Vulkan}, {"vulcan", RendererType::Vulkan}, {"vk", RendererType::Vulkan}, {"vulkan", RendererType::Vulkan}, {"vulcan", RendererType::Vulkan},
{"sw", RendererType::Software}, {"soft", RendererType::Software}, {"software", RendererType::Software}, {"sw", RendererType::Software}, {"soft", RendererType::Software}, {"software", RendererType::Software},
{"softrast", RendererType::Software}, {"softrast", RendererType::Software}, {"mtl", RendererType::Metal}, {"metal", RendererType::Metal}
}; };
if (auto search = map.find(inString); search != map.end()) { if (auto search = map.find(inString); search != map.end()) {
@ -34,6 +34,7 @@ const char* Renderer::typeToString(RendererType rendererType) {
case RendererType::OpenGL: return "opengl"; case RendererType::OpenGL: return "opengl";
case RendererType::Vulkan: return "vulkan"; case RendererType::Vulkan: return "vulkan";
case RendererType::Software: return "software"; case RendererType::Software: return "software";
case RendererType::Metal: return "metal";
default: return "Invalid"; default: return "Invalid";
} }
} }

View file

@ -0,0 +1,47 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/Foundation.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSArray.hpp"
#include "NSAutoreleasePool.hpp"
#include "NSBundle.hpp"
#include "NSData.hpp"
#include "NSDate.hpp"
#include "NSDefines.hpp"
#include "NSDictionary.hpp"
#include "NSEnumerator.hpp"
#include "NSError.hpp"
#include "NSLock.hpp"
#include "NSNotification.hpp"
#include "NSNumber.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSProcessInfo.hpp"
#include "NSRange.hpp"
#include "NSSet.hpp"
#include "NSSharedPtr.hpp"
#include "NSString.hpp"
#include "NSTypes.hpp"
#include "NSURL.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,115 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSArray.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class Array : public Copying<Array>
{
public:
static Array* array();
static Array* array(const Object* pObject);
static Array* array(const Object* const* pObjects, UInteger count);
static Array* alloc();
Array* init();
Array* init(const Object* const* pObjects, UInteger count);
Array* init(const class Coder* pCoder);
template <class _Object = Object>
_Object* object(UInteger index) const;
UInteger count() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::array()
{
return Object::sendMessage<Array*>(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(array));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::array(const Object* pObject)
{
return Object::sendMessage<Array*>(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(arrayWithObject_), pObject);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::array(const Object* const* pObjects, UInteger count)
{
return Object::sendMessage<Array*>(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(arrayWithObjects_count_), pObjects, count);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::alloc()
{
return NS::Object::alloc<Array>(_NS_PRIVATE_CLS(NSArray));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::init()
{
return NS::Object::init<Array>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::init(const Object* const* pObjects, UInteger count)
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(initWithObjects_count_), pObjects, count);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Array::init(const class Coder* pCoder)
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Array::count() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(count));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Object>
_NS_INLINE _Object* NS::Array::object(UInteger index) const
{
return Object::sendMessage<_Object*>(this, _NS_PRIVATE_SEL(objectAtIndex_), index);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,83 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSAutoreleasePool.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class AutoreleasePool : public Object
{
public:
static AutoreleasePool* alloc();
AutoreleasePool* init();
void drain();
void addObject(Object* pObject);
static void showPools();
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::AutoreleasePool* NS::AutoreleasePool::alloc()
{
return NS::Object::alloc<AutoreleasePool>(_NS_PRIVATE_CLS(NSAutoreleasePool));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::AutoreleasePool* NS::AutoreleasePool::init()
{
return NS::Object::init<AutoreleasePool>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::AutoreleasePool::drain()
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(drain));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::AutoreleasePool::addObject(Object* pObject)
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(addObject_), pObject);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::AutoreleasePool::showPools()
{
Object::sendMessage<void>(_NS_PRIVATE_CLS(NSAutoreleasePool), _NS_PRIVATE_SEL(showPools));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,374 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSBundle.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSNotification.hpp"
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
_NS_CONST(NotificationName, BundleDidLoadNotification);
_NS_CONST(NotificationName, BundleResourceRequestLowDiskSpaceNotification);
class String* LocalizedString(const String* pKey, const String*);
class String* LocalizedStringFromTable(const String* pKey, const String* pTbl, const String*);
class String* LocalizedStringFromTableInBundle(const String* pKey, const String* pTbl, const class Bundle* pBdle, const String*);
class String* LocalizedStringWithDefaultValue(const String* pKey, const String* pTbl, const class Bundle* pBdle, const String* pVal, const String*);
class Bundle : public Referencing<Bundle>
{
public:
static Bundle* mainBundle();
static Bundle* bundle(const class String* pPath);
static Bundle* bundle(const class URL* pURL);
static Bundle* alloc();
Bundle* init(const class String* pPath);
Bundle* init(const class URL* pURL);
class Array* allBundles() const;
class Array* allFrameworks() const;
bool load();
bool unload();
bool isLoaded() const;
bool preflightAndReturnError(class Error** pError) const;
bool loadAndReturnError(class Error** pError);
class URL* bundleURL() const;
class URL* resourceURL() const;
class URL* executableURL() const;
class URL* URLForAuxiliaryExecutable(const class String* pExecutableName) const;
class URL* privateFrameworksURL() const;
class URL* sharedFrameworksURL() const;
class URL* sharedSupportURL() const;
class URL* builtInPlugInsURL() const;
class URL* appStoreReceiptURL() const;
class String* bundlePath() const;
class String* resourcePath() const;
class String* executablePath() const;
class String* pathForAuxiliaryExecutable(const class String* pExecutableName) const;
class String* privateFrameworksPath() const;
class String* sharedFrameworksPath() const;
class String* sharedSupportPath() const;
class String* builtInPlugInsPath() const;
class String* bundleIdentifier() const;
class Dictionary* infoDictionary() const;
class Dictionary* localizedInfoDictionary() const;
class Object* objectForInfoDictionaryKey(const class String* pKey);
class String* localizedString(const class String* pKey, const class String* pValue = nullptr, const class String* pTableName = nullptr) const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_PRIVATE_DEF_CONST(NS::NotificationName, BundleDidLoadNotification);
_NS_PRIVATE_DEF_CONST(NS::NotificationName, BundleResourceRequestLowDiskSpaceNotification);
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::LocalizedString(const String* pKey, const String*)
{
return Bundle::mainBundle()->localizedString(pKey, nullptr, nullptr);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::LocalizedStringFromTable(const String* pKey, const String* pTbl, const String*)
{
return Bundle::mainBundle()->localizedString(pKey, nullptr, pTbl);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::LocalizedStringFromTableInBundle(const String* pKey, const String* pTbl, const Bundle* pBdl, const String*)
{
return pBdl->localizedString(pKey, nullptr, pTbl);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::LocalizedStringWithDefaultValue(const String* pKey, const String* pTbl, const Bundle* pBdl, const String* pVal, const String*)
{
return pBdl->localizedString(pKey, pVal, pTbl);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::mainBundle()
{
return Object::sendMessage<Bundle*>(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(mainBundle));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::bundle(const class String* pPath)
{
return Object::sendMessage<Bundle*>(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(bundleWithPath_), pPath);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::bundle(const class URL* pURL)
{
return Object::sendMessage<Bundle*>(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(bundleWithURL_), pURL);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::alloc()
{
return Object::sendMessage<Bundle*>(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(alloc));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::init(const String* pPath)
{
return Object::sendMessage<Bundle*>(this, _NS_PRIVATE_SEL(initWithPath_), pPath);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Bundle* NS::Bundle::init(const URL* pURL)
{
return Object::sendMessage<Bundle*>(this, _NS_PRIVATE_SEL(initWithURL_), pURL);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Bundle::allBundles() const
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(allBundles));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Bundle::allFrameworks() const
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(allFrameworks));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Bundle::load()
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(load));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Bundle::unload()
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(unload));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Bundle::isLoaded() const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(isLoaded));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Bundle::preflightAndReturnError(Error** pError) const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(preflightAndReturnError_), pError);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Bundle::loadAndReturnError(Error** pError)
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(loadAndReturnError_), pError);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::bundleURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(bundleURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::resourceURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(resourceURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::executableURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(executableURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::URLForAuxiliaryExecutable(const String* pExecutableName) const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(URLForAuxiliaryExecutable_), pExecutableName);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::privateFrameworksURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(privateFrameworksURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::sharedFrameworksURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(sharedFrameworksURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::sharedSupportURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(sharedSupportURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::builtInPlugInsURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(builtInPlugInsURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::Bundle::appStoreReceiptURL() const
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(appStoreReceiptURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::bundlePath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(bundlePath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::resourcePath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(resourcePath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::executablePath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(executablePath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::pathForAuxiliaryExecutable(const String* pExecutableName) const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(pathForAuxiliaryExecutable_), pExecutableName);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::privateFrameworksPath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(privateFrameworksPath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::sharedFrameworksPath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(sharedFrameworksPath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::sharedSupportPath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(sharedSupportPath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::builtInPlugInsPath() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(builtInPlugInsPath));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::bundleIdentifier() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(bundleIdentifier));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Bundle::infoDictionary() const
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(infoDictionary));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Bundle::localizedInfoDictionary() const
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(localizedInfoDictionary));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Object* NS::Bundle::objectForInfoDictionaryKey(const String* pKey)
{
return Object::sendMessage<Object*>(this, _NS_PRIVATE_SEL(objectForInfoDictionaryKey_), pKey);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Bundle::localizedString(const String* pKey, const String* pValue /* = nullptr */, const String* pTableName /* = nullptr */) const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(localizedStringForKey_value_table_), pKey, pValue, pTableName);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,54 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSData.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class Data : public Copying<Data>
{
public:
void* mutableBytes() const;
UInteger length() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void* NS::Data::mutableBytes() const
{
return Object::sendMessage<void*>(this, _NS_PRIVATE_SEL(mutableBytes));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Data::length() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(length));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,53 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSDate.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
using TimeInterval = double;
class Date : public Copying<Date>
{
public:
static Date* dateWithTimeIntervalSinceNow(TimeInterval secs);
};
} // NS
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Date* NS::Date::dateWithTimeIntervalSinceNow(NS::TimeInterval secs)
{
return NS::Object::sendMessage<NS::Date*>(_NS_PRIVATE_CLS(NSDate), _NS_PRIVATE_SEL(dateWithTimeIntervalSinceNow_), secs);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,45 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSDefines.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#define _NS_WEAK_IMPORT __attribute__((weak_import))
#ifdef METALCPP_SYMBOL_VISIBILITY_HIDDEN
#define _NS_EXPORT __attribute__((visibility("hidden")))
#else
#define _NS_EXPORT __attribute__((visibility("default")))
#endif // METALCPP_SYMBOL_VISIBILITY_HIDDEN
#define _NS_EXTERN extern "C" _NS_EXPORT
#define _NS_INLINE inline __attribute__((always_inline))
#define _NS_PACKED __attribute__((packed))
#define _NS_CONST(type, name) _NS_EXTERN type const name
#define _NS_ENUM(type, name) enum name : type
#define _NS_OPTIONS(type, name) \
using name = type; \
enum : name
#define _NS_CAST_TO_UINT(value) static_cast<NS::UInteger>(value)
#define _NS_VALIDATE_SIZE(ns, name) static_assert(sizeof(ns::name) == sizeof(ns##name), "size mismatch " #ns "::" #name)
#define _NS_VALIDATE_ENUM(ns, name) static_assert(_NS_CAST_TO_UINT(ns::name) == _NS_CAST_TO_UINT(ns##name), "value mismatch " #ns "::" #name)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,128 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSDictionary.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSEnumerator.hpp"
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class Dictionary : public NS::Copying<Dictionary>
{
public:
static Dictionary* dictionary();
static Dictionary* dictionary(const Object* pObject, const Object* pKey);
static Dictionary* dictionary(const Object* const* pObjects, const Object* const* pKeys, UInteger count);
static Dictionary* alloc();
Dictionary* init();
Dictionary* init(const Object* const* pObjects, const Object* const* pKeys, UInteger count);
Dictionary* init(const class Coder* pCoder);
template <class _KeyType = Object>
Enumerator<_KeyType>* keyEnumerator() const;
template <class _Object = Object>
_Object* object(const Object* pKey) const;
UInteger count() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary()
{
return Object::sendMessage<Dictionary*>(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionary));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary(const Object* pObject, const Object* pKey)
{
return Object::sendMessage<Dictionary*>(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionaryWithObject_forKey_), pObject, pKey);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary(const Object* const* pObjects, const Object* const* pKeys, UInteger count)
{
return Object::sendMessage<Dictionary*>(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionaryWithObjects_forKeys_count_),
pObjects, pKeys, count);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::alloc()
{
return NS::Object::alloc<Dictionary>(_NS_PRIVATE_CLS(NSDictionary));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::init()
{
return NS::Object::init<Dictionary>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::init(const Object* const* pObjects, const Object* const* pKeys, UInteger count)
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(initWithObjects_forKeys_count_), pObjects, pKeys, count);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Dictionary::init(const class Coder* pCoder)
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _KeyType>
_NS_INLINE NS::Enumerator<_KeyType>* NS::Dictionary::keyEnumerator() const
{
return Object::sendMessage<Enumerator<_KeyType>*>(this, _NS_PRIVATE_SEL(keyEnumerator));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Object>
_NS_INLINE _Object* NS::Dictionary::object(const Object* pKey) const
{
return Object::sendMessage<_Object*>(this, _NS_PRIVATE_SEL(objectForKey_), pKey);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Dictionary::count() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(count));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,78 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSEnumerator.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
struct FastEnumerationState
{
unsigned long state;
Object** itemsPtr;
unsigned long* mutationsPtr;
unsigned long extra[5];
} _NS_PACKED;
class FastEnumeration : public Referencing<FastEnumeration>
{
public:
NS::UInteger countByEnumerating(FastEnumerationState* pState, Object** pBuffer, NS::UInteger len);
};
template <class _ObjectType>
class Enumerator : public Referencing<Enumerator<_ObjectType>, FastEnumeration>
{
public:
_ObjectType* nextObject();
class Array* allObjects();
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::FastEnumeration::countByEnumerating(FastEnumerationState* pState, Object** pBuffer, NS::UInteger len)
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(countByEnumeratingWithState_objects_count_), pState, pBuffer, len);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _ObjectType>
_NS_INLINE _ObjectType* NS::Enumerator<_ObjectType>::nextObject()
{
return Object::sendMessage<_ObjectType*>(this, _NS_PRIVATE_SEL(nextObject));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _ObjectType>
_NS_INLINE NS::Array* NS::Enumerator<_ObjectType>::allObjects()
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(allObjects));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,173 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSError.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
using ErrorDomain = class String*;
_NS_CONST(ErrorDomain, CocoaErrorDomain);
_NS_CONST(ErrorDomain, POSIXErrorDomain);
_NS_CONST(ErrorDomain, OSStatusErrorDomain);
_NS_CONST(ErrorDomain, MachErrorDomain);
using ErrorUserInfoKey = class String*;
_NS_CONST(ErrorUserInfoKey, UnderlyingErrorKey);
_NS_CONST(ErrorUserInfoKey, LocalizedDescriptionKey);
_NS_CONST(ErrorUserInfoKey, LocalizedFailureReasonErrorKey);
_NS_CONST(ErrorUserInfoKey, LocalizedRecoverySuggestionErrorKey);
_NS_CONST(ErrorUserInfoKey, LocalizedRecoveryOptionsErrorKey);
_NS_CONST(ErrorUserInfoKey, RecoveryAttempterErrorKey);
_NS_CONST(ErrorUserInfoKey, HelpAnchorErrorKey);
_NS_CONST(ErrorUserInfoKey, DebugDescriptionErrorKey);
_NS_CONST(ErrorUserInfoKey, LocalizedFailureErrorKey);
_NS_CONST(ErrorUserInfoKey, StringEncodingErrorKey);
_NS_CONST(ErrorUserInfoKey, URLErrorKey);
_NS_CONST(ErrorUserInfoKey, FilePathErrorKey);
class Error : public Copying<Error>
{
public:
static Error* error(ErrorDomain domain, Integer code, class Dictionary* pDictionary);
static Error* alloc();
Error* init();
Error* init(ErrorDomain domain, Integer code, class Dictionary* pDictionary);
Integer code() const;
ErrorDomain domain() const;
class Dictionary* userInfo() const;
class String* localizedDescription() const;
class Array* localizedRecoveryOptions() const;
class String* localizedRecoverySuggestion() const;
class String* localizedFailureReason() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, CocoaErrorDomain);
_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, POSIXErrorDomain);
_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, OSStatusErrorDomain);
_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, MachErrorDomain);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, UnderlyingErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedDescriptionKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedFailureReasonErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedRecoverySuggestionErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedRecoveryOptionsErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, RecoveryAttempterErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, HelpAnchorErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, DebugDescriptionErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedFailureErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, StringEncodingErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, URLErrorKey);
_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, FilePathErrorKey);
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Error* NS::Error::error(ErrorDomain domain, Integer code, class Dictionary* pDictionary)
{
return Object::sendMessage<Error*>(_NS_PRIVATE_CLS(NSError), _NS_PRIVATE_SEL(errorWithDomain_code_userInfo_), domain, code, pDictionary);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Error* NS::Error::alloc()
{
return Object::alloc<Error>(_NS_PRIVATE_CLS(NSError));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Error* NS::Error::init()
{
return Object::init<Error>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Error* NS::Error::init(ErrorDomain domain, Integer code, class Dictionary* pDictionary)
{
return Object::sendMessage<Error*>(this, _NS_PRIVATE_SEL(initWithDomain_code_userInfo_), domain, code, pDictionary);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Integer NS::Error::code() const
{
return Object::sendMessage<Integer>(this, _NS_PRIVATE_SEL(code));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::ErrorDomain NS::Error::domain() const
{
return Object::sendMessage<ErrorDomain>(this, _NS_PRIVATE_SEL(domain));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Error::userInfo() const
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(userInfo));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Error::localizedDescription() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(localizedDescription));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::Error::localizedRecoveryOptions() const
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(localizedRecoveryOptions));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Error::localizedRecoverySuggestion() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(localizedRecoverySuggestion));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Error::localizedFailureReason() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(localizedFailureReason));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,118 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSLock.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
#include "NSDate.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
template <class _Class, class _Base = class Object>
class Locking : public _Base
{
public:
void lock();
void unlock();
};
class Condition : public Locking<Condition>
{
public:
static Condition* alloc();
Condition* init();
void wait();
bool waitUntilDate(Date* pLimit);
void signal();
void broadcast();
};
} // NS
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template<class _Class, class _Base /* = NS::Object */>
_NS_INLINE void NS::Locking<_Class, _Base>::lock()
{
NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(lock));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template<class _Class, class _Base /* = NS::Object */>
_NS_INLINE void NS::Locking<_Class, _Base>::unlock()
{
NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(unlock));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Condition* NS::Condition::alloc()
{
return NS::Object::alloc<NS::Condition>(_NS_PRIVATE_CLS(NSCondition));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Condition* NS::Condition::init()
{
return NS::Object::init<NS::Condition>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::Condition::wait()
{
NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(wait));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Condition::waitUntilDate(NS::Date* pLimit)
{
return NS::Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(waitUntilDate_), pLimit);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::Condition::signal()
{
NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(signal));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::Condition::broadcast()
{
NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(broadcast));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,110 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSNotification.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSDictionary.hpp"
#include "NSObject.hpp"
#include "NSString.hpp"
#include "NSTypes.hpp"
#include <functional>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
using NotificationName = class String*;
class Notification : public NS::Referencing<Notification>
{
public:
NS::String* name() const;
NS::Object* object() const;
NS::Dictionary* userInfo() const;
};
using ObserverBlock = void(^)(Notification*);
using ObserverFunction = std::function<void(Notification*)>;
class NotificationCenter : public NS::Referencing<NotificationCenter>
{
public:
static class NotificationCenter* defaultCenter();
Object* addObserver(NotificationName name, Object* pObj, void* pQueue, ObserverBlock block);
Object* addObserver(NotificationName name, Object* pObj, void* pQueue, ObserverFunction &handler);
void removeObserver(Object* pObserver);
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Notification::name() const
{
return Object::sendMessage<NS::String*>(this, _NS_PRIVATE_SEL(name));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Object* NS::Notification::object() const
{
return Object::sendMessage<NS::Object*>(this, _NS_PRIVATE_SEL(object));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::Notification::userInfo() const
{
return Object::sendMessage<NS::Dictionary*>(this, _NS_PRIVATE_SEL(userInfo));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::NotificationCenter* NS::NotificationCenter::defaultCenter()
{
return NS::Object::sendMessage<NS::NotificationCenter*>(_NS_PRIVATE_CLS(NSNotificationCenter), _NS_PRIVATE_SEL(defaultCenter));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Object* NS::NotificationCenter::addObserver(NS::NotificationName name, Object* pObj, void* pQueue, NS::ObserverBlock block)
{
return NS::Object::sendMessage<Object*>(this, _NS_PRIVATE_SEL(addObserverName_object_queue_block_), name, pObj, pQueue, block);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Object* NS::NotificationCenter::addObserver(NS::NotificationName name, Object* pObj, void* pQueue, NS::ObserverFunction &handler)
{
__block ObserverFunction blockFunction = handler;
return addObserver(name, pObj, pQueue, ^(NS::Notification* pNotif) {blockFunction(pNotif);});
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::NotificationCenter::removeObserver(Object* pObserver)
{
return NS::Object::sendMessage<void>(this, _NS_PRIVATE_SEL(removeObserver_), pObserver);
}

View file

@ -0,0 +1,501 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSNumber.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSObjCRuntime.hpp"
#include "NSObject.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class Value : public Copying<Value>
{
public:
static Value* value(const void* pValue, const char* pType);
static Value* value(const void* pPointer);
static Value* alloc();
Value* init(const void* pValue, const char* pType);
Value* init(const class Coder* pCoder);
void getValue(void* pValue, UInteger size) const;
const char* objCType() const;
bool isEqualToValue(Value* pValue) const;
void* pointerValue() const;
};
class Number : public Copying<Number, Value>
{
public:
static Number* number(char value);
static Number* number(unsigned char value);
static Number* number(short value);
static Number* number(unsigned short value);
static Number* number(int value);
static Number* number(unsigned int value);
static Number* number(long value);
static Number* number(unsigned long value);
static Number* number(long long value);
static Number* number(unsigned long long value);
static Number* number(float value);
static Number* number(double value);
static Number* number(bool value);
static Number* alloc();
Number* init(const class Coder* pCoder);
Number* init(char value);
Number* init(unsigned char value);
Number* init(short value);
Number* init(unsigned short value);
Number* init(int value);
Number* init(unsigned int value);
Number* init(long value);
Number* init(unsigned long value);
Number* init(long long value);
Number* init(unsigned long long value);
Number* init(float value);
Number* init(double value);
Number* init(bool value);
char charValue() const;
unsigned char unsignedCharValue() const;
short shortValue() const;
unsigned short unsignedShortValue() const;
int intValue() const;
unsigned int unsignedIntValue() const;
long longValue() const;
unsigned long unsignedLongValue() const;
long long longLongValue() const;
unsigned long long unsignedLongLongValue() const;
float floatValue() const;
double doubleValue() const;
bool boolValue() const;
Integer integerValue() const;
UInteger unsignedIntegerValue() const;
class String* stringValue() const;
ComparisonResult compare(const Number* pOtherNumber) const;
bool isEqualToNumber(const Number* pNumber) const;
class String* descriptionWithLocale(const Object* pLocale) const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Value* NS::Value::value(const void* pValue, const char* pType)
{
return Object::sendMessage<Value*>(_NS_PRIVATE_CLS(NSValue), _NS_PRIVATE_SEL(valueWithBytes_objCType_), pValue, pType);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Value* NS::Value::value(const void* pPointer)
{
return Object::sendMessage<Value*>(_NS_PRIVATE_CLS(NSValue), _NS_PRIVATE_SEL(valueWithPointer_), pPointer);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Value* NS::Value::alloc()
{
return NS::Object::alloc<Value>(_NS_PRIVATE_CLS(NSValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Value* NS::Value::init(const void* pValue, const char* pType)
{
return Object::sendMessage<Value*>(this, _NS_PRIVATE_SEL(initWithBytes_objCType_), pValue, pType);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Value* NS::Value::init(const class Coder* pCoder)
{
return Object::sendMessage<Value*>(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::Value::getValue(void* pValue, UInteger size) const
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(getValue_size_), pValue, size);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE const char* NS::Value::objCType() const
{
return Object::sendMessage<const char*>(this, _NS_PRIVATE_SEL(objCType));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Value::isEqualToValue(Value* pValue) const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqualToValue_), pValue);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void* NS::Value::pointerValue() const
{
return Object::sendMessage<void*>(this, _NS_PRIVATE_SEL(pointerValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(char value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithChar_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(unsigned char value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedChar_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(short value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithShort_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(unsigned short value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedShort_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(int value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithInt_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(unsigned int value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedInt_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(long value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(unsigned long value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(long long value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithLongLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(unsigned long long value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedLongLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(float value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithFloat_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(double value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithDouble_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::number(bool value)
{
return Object::sendMessage<Number*>(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithBool_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::alloc()
{
return NS::Object::alloc<Number>(_NS_PRIVATE_CLS(NSNumber));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(const Coder* pCoder)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(char value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithChar_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(unsigned char value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithUnsignedChar_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(short value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithShort_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(unsigned short value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithUnsignedShort_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(int value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithInt_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(unsigned int value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithUnsignedInt_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(long value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(unsigned long value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithUnsignedLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(long long value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithLongLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(unsigned long long value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithUnsignedLongLong_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(float value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithFloat_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(double value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithDouble_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Number* NS::Number::init(bool value)
{
return Object::sendMessage<Number*>(this, _NS_PRIVATE_SEL(initWithBool_), value);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE char NS::Number::charValue() const
{
return Object::sendMessage<char>(this, _NS_PRIVATE_SEL(charValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned char NS::Number::unsignedCharValue() const
{
return Object::sendMessage<unsigned char>(this, _NS_PRIVATE_SEL(unsignedCharValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE short NS::Number::shortValue() const
{
return Object::sendMessage<short>(this, _NS_PRIVATE_SEL(shortValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned short NS::Number::unsignedShortValue() const
{
return Object::sendMessage<unsigned short>(this, _NS_PRIVATE_SEL(unsignedShortValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE int NS::Number::intValue() const
{
return Object::sendMessage<int>(this, _NS_PRIVATE_SEL(intValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned int NS::Number::unsignedIntValue() const
{
return Object::sendMessage<unsigned int>(this, _NS_PRIVATE_SEL(unsignedIntValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE long NS::Number::longValue() const
{
return Object::sendMessage<long>(this, _NS_PRIVATE_SEL(longValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned long NS::Number::unsignedLongValue() const
{
return Object::sendMessage<unsigned long>(this, _NS_PRIVATE_SEL(unsignedLongValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE long long NS::Number::longLongValue() const
{
return Object::sendMessage<long long>(this, _NS_PRIVATE_SEL(longLongValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned long long NS::Number::unsignedLongLongValue() const
{
return Object::sendMessage<unsigned long long>(this, _NS_PRIVATE_SEL(unsignedLongLongValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE float NS::Number::floatValue() const
{
return Object::sendMessage<float>(this, _NS_PRIVATE_SEL(floatValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE double NS::Number::doubleValue() const
{
return Object::sendMessage<double>(this, _NS_PRIVATE_SEL(doubleValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Number::boolValue() const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(boolValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Integer NS::Number::integerValue() const
{
return Object::sendMessage<Integer>(this, _NS_PRIVATE_SEL(integerValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Number::unsignedIntegerValue() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(unsignedIntegerValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Number::stringValue() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(stringValue));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::ComparisonResult NS::Number::compare(const Number* pOtherNumber) const
{
return Object::sendMessage<ComparisonResult>(this, _NS_PRIVATE_SEL(compare_), pOtherNumber);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Number::isEqualToNumber(const Number* pNumber) const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqualToNumber_), pNumber);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Number::descriptionWithLocale(const Object* pLocale) const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(descriptionWithLocale_), pLocale);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,43 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSObjCRuntime.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
_NS_ENUM(Integer, ComparisonResult) {
OrderedAscending = -1L,
OrderedSame,
OrderedDescending
};
const Integer NotFound = IntegerMax;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,302 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSObject.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
#include <objc/message.h>
#include <objc/runtime.h>
#include <type_traits>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
template <class _Class, class _Base = class Object>
class _NS_EXPORT Referencing : public _Base
{
public:
_Class* retain();
void release();
_Class* autorelease();
UInteger retainCount() const;
};
template <class _Class, class _Base = class Object>
class Copying : public Referencing<_Class, _Base>
{
public:
_Class* copy() const;
};
template <class _Class, class _Base = class Object>
class SecureCoding : public Referencing<_Class, _Base>
{
};
class Object : public Referencing<Object, objc_object>
{
public:
UInteger hash() const;
bool isEqual(const Object* pObject) const;
class String* description() const;
class String* debugDescription() const;
protected:
friend class Referencing<Object, objc_object>;
template <class _Class>
static _Class* alloc(const char* pClassName);
template <class _Class>
static _Class* alloc(const void* pClass);
template <class _Class>
_Class* init();
template <class _Dst>
static _Dst bridgingCast(const void* pObj);
static class MethodSignature* methodSignatureForSelector(const void* pObj, SEL selector);
static bool respondsToSelector(const void* pObj, SEL selector);
template <typename _Type>
static constexpr bool doesRequireMsgSendStret();
template <typename _Ret, typename... _Args>
static _Ret sendMessage(const void* pObj, SEL selector, _Args... args);
template <typename _Ret, typename... _Args>
static _Ret sendMessageSafe(const void* pObj, SEL selector, _Args... args);
private:
Object() = delete;
Object(const Object&) = delete;
~Object() = delete;
Object& operator=(const Object&) = delete;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class, class _Base /* = Object */>
_NS_INLINE _Class* NS::Referencing<_Class, _Base>::retain()
{
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(retain));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class, class _Base /* = Object */>
_NS_INLINE void NS::Referencing<_Class, _Base>::release()
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(release));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class, class _Base /* = Object */>
_NS_INLINE _Class* NS::Referencing<_Class, _Base>::autorelease()
{
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(autorelease));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class, class _Base /* = Object */>
_NS_INLINE NS::UInteger NS::Referencing<_Class, _Base>::retainCount() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(retainCount));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class, class _Base /* = Object */>
_NS_INLINE _Class* NS::Copying<_Class, _Base>::copy() const
{
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(copy));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Dst>
_NS_INLINE _Dst NS::Object::bridgingCast(const void* pObj)
{
#ifdef __OBJC__
return (__bridge _Dst)pObj;
#else
return (_Dst)pObj;
#endif // __OBJC__
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <typename _Type>
_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret()
{
#if (defined(__i386__) || defined(__x86_64__))
constexpr size_t kStructLimit = (sizeof(std::uintptr_t) << 1);
return sizeof(_Type) > kStructLimit;
#elif defined(__arm64__)
return false;
#elif defined(__arm__)
constexpr size_t kStructLimit = sizeof(std::uintptr_t);
return std::is_class(_Type) && (sizeof(_Type) > kStructLimit);
#else
#error "Unsupported architecture!"
#endif
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <>
_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret<void>()
{
return false;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <typename _Ret, typename... _Args>
_NS_INLINE _Ret NS::Object::sendMessage(const void* pObj, SEL selector, _Args... args)
{
#if (defined(__i386__) || defined(__x86_64__))
if constexpr (std::is_floating_point<_Ret>())
{
using SendMessageProcFpret = _Ret (*)(const void*, SEL, _Args...);
const SendMessageProcFpret pProc = reinterpret_cast<SendMessageProcFpret>(&objc_msgSend_fpret);
return (*pProc)(pObj, selector, args...);
}
else
#endif // ( defined( __i386__ ) || defined( __x86_64__ ) )
#if !defined(__arm64__)
if constexpr (doesRequireMsgSendStret<_Ret>())
{
using SendMessageProcStret = void (*)(_Ret*, const void*, SEL, _Args...);
const SendMessageProcStret pProc = reinterpret_cast<SendMessageProcStret>(&objc_msgSend_stret);
_Ret ret;
(*pProc)(&ret, pObj, selector, args...);
return ret;
}
else
#endif // !defined( __arm64__ )
{
using SendMessageProc = _Ret (*)(const void*, SEL, _Args...);
const SendMessageProc pProc = reinterpret_cast<SendMessageProc>(&objc_msgSend);
return (*pProc)(pObj, selector, args...);
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::MethodSignature* NS::Object::methodSignatureForSelector(const void* pObj, SEL selector)
{
return sendMessage<MethodSignature*>(pObj, _NS_PRIVATE_SEL(methodSignatureForSelector_), selector);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Object::respondsToSelector(const void* pObj, SEL selector)
{
return sendMessage<bool>(pObj, _NS_PRIVATE_SEL(respondsToSelector_), selector);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <typename _Ret, typename... _Args>
_NS_INLINE _Ret NS::Object::sendMessageSafe(const void* pObj, SEL selector, _Args... args)
{
if ((respondsToSelector(pObj, selector)) || (nullptr != methodSignatureForSelector(pObj, selector)))
{
return sendMessage<_Ret>(pObj, selector, args...);
}
if constexpr (!std::is_void<_Ret>::value)
{
return _Ret(0);
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class>
_NS_INLINE _Class* NS::Object::alloc(const char* pClassName)
{
return sendMessage<_Class*>(objc_lookUpClass(pClassName), _NS_PRIVATE_SEL(alloc));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class>
_NS_INLINE _Class* NS::Object::alloc(const void* pClass)
{
return sendMessage<_Class*>(pClass, _NS_PRIVATE_SEL(alloc));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
template <class _Class>
_NS_INLINE _Class* NS::Object::init()
{
return sendMessage<_Class*>(this, _NS_PRIVATE_SEL(init));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Object::hash() const
{
return sendMessage<UInteger>(this, _NS_PRIVATE_SEL(hash));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Object::isEqual(const Object* pObject) const
{
return sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqual_), pObject);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Object::description() const
{
return sendMessage<String*>(this, _NS_PRIVATE_SEL(description));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::Object::debugDescription() const
{
return sendMessageSafe<String*>(this, _NS_PRIVATE_SEL(debugDescription));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,507 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSPrivate.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <objc/runtime.h>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#define _NS_PRIVATE_CLS(symbol) (Private::Class::s_k##symbol)
#define _NS_PRIVATE_SEL(accessor) (Private::Selector::s_k##accessor)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#if defined(NS_PRIVATE_IMPLEMENTATION)
#ifdef METALCPP_SYMBOL_VISIBILITY_HIDDEN
#define _NS_PRIVATE_VISIBILITY __attribute__((visibility("hidden")))
#else
#define _NS_PRIVATE_VISIBILITY __attribute__((visibility("default")))
#endif // METALCPP_SYMBOL_VISIBILITY_HIDDEN
#define _NS_PRIVATE_IMPORT __attribute__((weak_import))
#ifdef __OBJC__
#define _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol) ((__bridge void*)objc_lookUpClass(#symbol))
#define _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol) ((__bridge void*)objc_getProtocol(#symbol))
#else
#define _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol) objc_lookUpClass(#symbol)
#define _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol) objc_getProtocol(#symbol)
#endif // __OBJC__
#define _NS_PRIVATE_DEF_CLS(symbol) void* s_k##symbol _NS_PRIVATE_VISIBILITY = _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol)
#define _NS_PRIVATE_DEF_PRO(symbol) void* s_k##symbol _NS_PRIVATE_VISIBILITY = _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol)
#define _NS_PRIVATE_DEF_SEL(accessor, symbol) SEL s_k##accessor _NS_PRIVATE_VISIBILITY = sel_registerName(symbol)
#define _NS_PRIVATE_DEF_CONST(type, symbol) \
_NS_EXTERN type const NS##symbol _NS_PRIVATE_IMPORT; \
type const NS::symbol = (nullptr != &NS##symbol) ? NS##symbol : nullptr
#else
#define _NS_PRIVATE_DEF_CLS(symbol) extern void* s_k##symbol
#define _NS_PRIVATE_DEF_PRO(symbol) extern void* s_k##symbol
#define _NS_PRIVATE_DEF_SEL(accessor, symbol) extern SEL s_k##accessor
#define _NS_PRIVATE_DEF_CONST(type, symbol) extern type const NS::symbol
#endif // NS_PRIVATE_IMPLEMENTATION
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
namespace Private
{
namespace Class
{
_NS_PRIVATE_DEF_CLS(NSArray);
_NS_PRIVATE_DEF_CLS(NSAutoreleasePool);
_NS_PRIVATE_DEF_CLS(NSBundle);
_NS_PRIVATE_DEF_CLS(NSCondition);
_NS_PRIVATE_DEF_CLS(NSDate);
_NS_PRIVATE_DEF_CLS(NSDictionary);
_NS_PRIVATE_DEF_CLS(NSError);
_NS_PRIVATE_DEF_CLS(NSNotificationCenter);
_NS_PRIVATE_DEF_CLS(NSNumber);
_NS_PRIVATE_DEF_CLS(NSObject);
_NS_PRIVATE_DEF_CLS(NSProcessInfo);
_NS_PRIVATE_DEF_CLS(NSSet);
_NS_PRIVATE_DEF_CLS(NSString);
_NS_PRIVATE_DEF_CLS(NSURL);
_NS_PRIVATE_DEF_CLS(NSValue);
} // Class
} // Private
} // MTL
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
namespace Private
{
namespace Protocol
{
} // Protocol
} // Private
} // NS
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
namespace Private
{
namespace Selector
{
_NS_PRIVATE_DEF_SEL(addObject_,
"addObject:");
_NS_PRIVATE_DEF_SEL(addObserverName_object_queue_block_,
"addObserverForName:object:queue:usingBlock:");
_NS_PRIVATE_DEF_SEL(activeProcessorCount,
"activeProcessorCount");
_NS_PRIVATE_DEF_SEL(allBundles,
"allBundles");
_NS_PRIVATE_DEF_SEL(allFrameworks,
"allFrameworks");
_NS_PRIVATE_DEF_SEL(allObjects,
"allObjects");
_NS_PRIVATE_DEF_SEL(alloc,
"alloc");
_NS_PRIVATE_DEF_SEL(appStoreReceiptURL,
"appStoreReceiptURL");
_NS_PRIVATE_DEF_SEL(arguments,
"arguments");
_NS_PRIVATE_DEF_SEL(array,
"array");
_NS_PRIVATE_DEF_SEL(arrayWithObject_,
"arrayWithObject:");
_NS_PRIVATE_DEF_SEL(arrayWithObjects_count_,
"arrayWithObjects:count:");
_NS_PRIVATE_DEF_SEL(automaticTerminationSupportEnabled,
"automaticTerminationSupportEnabled");
_NS_PRIVATE_DEF_SEL(autorelease,
"autorelease");
_NS_PRIVATE_DEF_SEL(beginActivityWithOptions_reason_,
"beginActivityWithOptions:reason:");
_NS_PRIVATE_DEF_SEL(boolValue,
"boolValue");
_NS_PRIVATE_DEF_SEL(broadcast,
"broadcast");
_NS_PRIVATE_DEF_SEL(builtInPlugInsPath,
"builtInPlugInsPath");
_NS_PRIVATE_DEF_SEL(builtInPlugInsURL,
"builtInPlugInsURL");
_NS_PRIVATE_DEF_SEL(bundleIdentifier,
"bundleIdentifier");
_NS_PRIVATE_DEF_SEL(bundlePath,
"bundlePath");
_NS_PRIVATE_DEF_SEL(bundleURL,
"bundleURL");
_NS_PRIVATE_DEF_SEL(bundleWithPath_,
"bundleWithPath:");
_NS_PRIVATE_DEF_SEL(bundleWithURL_,
"bundleWithURL:");
_NS_PRIVATE_DEF_SEL(caseInsensitiveCompare_,
"caseInsensitiveCompare:");
_NS_PRIVATE_DEF_SEL(characterAtIndex_,
"characterAtIndex:");
_NS_PRIVATE_DEF_SEL(charValue,
"charValue");
_NS_PRIVATE_DEF_SEL(countByEnumeratingWithState_objects_count_,
"countByEnumeratingWithState:objects:count:");
_NS_PRIVATE_DEF_SEL(cStringUsingEncoding_,
"cStringUsingEncoding:");
_NS_PRIVATE_DEF_SEL(code,
"code");
_NS_PRIVATE_DEF_SEL(compare_,
"compare:");
_NS_PRIVATE_DEF_SEL(copy,
"copy");
_NS_PRIVATE_DEF_SEL(count,
"count");
_NS_PRIVATE_DEF_SEL(dateWithTimeIntervalSinceNow_,
"dateWithTimeIntervalSinceNow:");
_NS_PRIVATE_DEF_SEL(defaultCenter,
"defaultCenter");
_NS_PRIVATE_DEF_SEL(descriptionWithLocale_,
"descriptionWithLocale:");
_NS_PRIVATE_DEF_SEL(disableAutomaticTermination_,
"disableAutomaticTermination:");
_NS_PRIVATE_DEF_SEL(disableSuddenTermination,
"disableSuddenTermination");
_NS_PRIVATE_DEF_SEL(debugDescription,
"debugDescription");
_NS_PRIVATE_DEF_SEL(description,
"description");
_NS_PRIVATE_DEF_SEL(dictionary,
"dictionary");
_NS_PRIVATE_DEF_SEL(dictionaryWithObject_forKey_,
"dictionaryWithObject:forKey:");
_NS_PRIVATE_DEF_SEL(dictionaryWithObjects_forKeys_count_,
"dictionaryWithObjects:forKeys:count:");
_NS_PRIVATE_DEF_SEL(domain,
"domain");
_NS_PRIVATE_DEF_SEL(doubleValue,
"doubleValue");
_NS_PRIVATE_DEF_SEL(drain,
"drain");
_NS_PRIVATE_DEF_SEL(enableAutomaticTermination_,
"enableAutomaticTermination:");
_NS_PRIVATE_DEF_SEL(enableSuddenTermination,
"enableSuddenTermination");
_NS_PRIVATE_DEF_SEL(endActivity_,
"endActivity:");
_NS_PRIVATE_DEF_SEL(environment,
"environment");
_NS_PRIVATE_DEF_SEL(errorWithDomain_code_userInfo_,
"errorWithDomain:code:userInfo:");
_NS_PRIVATE_DEF_SEL(executablePath,
"executablePath");
_NS_PRIVATE_DEF_SEL(executableURL,
"executableURL");
_NS_PRIVATE_DEF_SEL(fileSystemRepresentation,
"fileSystemRepresentation");
_NS_PRIVATE_DEF_SEL(fileURLWithPath_,
"fileURLWithPath:");
_NS_PRIVATE_DEF_SEL(floatValue,
"floatValue");
_NS_PRIVATE_DEF_SEL(fullUserName,
"fullUserName");
_NS_PRIVATE_DEF_SEL(getValue_size_,
"getValue:size:");
_NS_PRIVATE_DEF_SEL(globallyUniqueString,
"globallyUniqueString");
_NS_PRIVATE_DEF_SEL(hash,
"hash");
_NS_PRIVATE_DEF_SEL(hostName,
"hostName");
_NS_PRIVATE_DEF_SEL(infoDictionary,
"infoDictionary");
_NS_PRIVATE_DEF_SEL(init,
"init");
_NS_PRIVATE_DEF_SEL(initFileURLWithPath_,
"initFileURLWithPath:");
_NS_PRIVATE_DEF_SEL(initWithBool_,
"initWithBool:");
_NS_PRIVATE_DEF_SEL(initWithBytes_objCType_,
"initWithBytes:objCType:");
_NS_PRIVATE_DEF_SEL(initWithBytesNoCopy_length_encoding_freeWhenDone_,
"initWithBytesNoCopy:length:encoding:freeWhenDone:");
_NS_PRIVATE_DEF_SEL(initWithChar_,
"initWithChar:");
_NS_PRIVATE_DEF_SEL(initWithCoder_,
"initWithCoder:");
_NS_PRIVATE_DEF_SEL(initWithCString_encoding_,
"initWithCString:encoding:");
_NS_PRIVATE_DEF_SEL(initWithDomain_code_userInfo_,
"initWithDomain:code:userInfo:");
_NS_PRIVATE_DEF_SEL(initWithDouble_,
"initWithDouble:");
_NS_PRIVATE_DEF_SEL(initWithFloat_,
"initWithFloat:");
_NS_PRIVATE_DEF_SEL(initWithInt_,
"initWithInt:");
_NS_PRIVATE_DEF_SEL(initWithLong_,
"initWithLong:");
_NS_PRIVATE_DEF_SEL(initWithLongLong_,
"initWithLongLong:");
_NS_PRIVATE_DEF_SEL(initWithObjects_count_,
"initWithObjects:count:");
_NS_PRIVATE_DEF_SEL(initWithObjects_forKeys_count_,
"initWithObjects:forKeys:count:");
_NS_PRIVATE_DEF_SEL(initWithPath_,
"initWithPath:");
_NS_PRIVATE_DEF_SEL(initWithShort_,
"initWithShort:");
_NS_PRIVATE_DEF_SEL(initWithString_,
"initWithString:");
_NS_PRIVATE_DEF_SEL(initWithUnsignedChar_,
"initWithUnsignedChar:");
_NS_PRIVATE_DEF_SEL(initWithUnsignedInt_,
"initWithUnsignedInt:");
_NS_PRIVATE_DEF_SEL(initWithUnsignedLong_,
"initWithUnsignedLong:");
_NS_PRIVATE_DEF_SEL(initWithUnsignedLongLong_,
"initWithUnsignedLongLong:");
_NS_PRIVATE_DEF_SEL(initWithUnsignedShort_,
"initWithUnsignedShort:");
_NS_PRIVATE_DEF_SEL(initWithURL_,
"initWithURL:");
_NS_PRIVATE_DEF_SEL(integerValue,
"integerValue");
_NS_PRIVATE_DEF_SEL(intValue,
"intValue");
_NS_PRIVATE_DEF_SEL(isEqual_,
"isEqual:");
_NS_PRIVATE_DEF_SEL(isEqualToNumber_,
"isEqualToNumber:");
_NS_PRIVATE_DEF_SEL(isEqualToString_,
"isEqualToString:");
_NS_PRIVATE_DEF_SEL(isEqualToValue_,
"isEqualToValue:");
_NS_PRIVATE_DEF_SEL(isiOSAppOnMac,
"isiOSAppOnMac");
_NS_PRIVATE_DEF_SEL(isLoaded,
"isLoaded");
_NS_PRIVATE_DEF_SEL(isLowPowerModeEnabled,
"isLowPowerModeEnabled");
_NS_PRIVATE_DEF_SEL(isMacCatalystApp,
"isMacCatalystApp");
_NS_PRIVATE_DEF_SEL(isOperatingSystemAtLeastVersion_,
"isOperatingSystemAtLeastVersion:");
_NS_PRIVATE_DEF_SEL(keyEnumerator,
"keyEnumerator");
_NS_PRIVATE_DEF_SEL(length,
"length");
_NS_PRIVATE_DEF_SEL(lengthOfBytesUsingEncoding_,
"lengthOfBytesUsingEncoding:");
_NS_PRIVATE_DEF_SEL(load,
"load");
_NS_PRIVATE_DEF_SEL(loadAndReturnError_,
"loadAndReturnError:");
_NS_PRIVATE_DEF_SEL(localizedDescription,
"localizedDescription");
_NS_PRIVATE_DEF_SEL(localizedFailureReason,
"localizedFailureReason");
_NS_PRIVATE_DEF_SEL(localizedInfoDictionary,
"localizedInfoDictionary");
_NS_PRIVATE_DEF_SEL(localizedRecoveryOptions,
"localizedRecoveryOptions");
_NS_PRIVATE_DEF_SEL(localizedRecoverySuggestion,
"localizedRecoverySuggestion");
_NS_PRIVATE_DEF_SEL(localizedStringForKey_value_table_,
"localizedStringForKey:value:table:");
_NS_PRIVATE_DEF_SEL(lock,
"lock");
_NS_PRIVATE_DEF_SEL(longValue,
"longValue");
_NS_PRIVATE_DEF_SEL(longLongValue,
"longLongValue");
_NS_PRIVATE_DEF_SEL(mainBundle,
"mainBundle");
_NS_PRIVATE_DEF_SEL(maximumLengthOfBytesUsingEncoding_,
"maximumLengthOfBytesUsingEncoding:");
_NS_PRIVATE_DEF_SEL(methodSignatureForSelector_,
"methodSignatureForSelector:");
_NS_PRIVATE_DEF_SEL(mutableBytes,
"mutableBytes");
_NS_PRIVATE_DEF_SEL(name,
"name");
_NS_PRIVATE_DEF_SEL(nextObject,
"nextObject");
_NS_PRIVATE_DEF_SEL(numberWithBool_,
"numberWithBool:");
_NS_PRIVATE_DEF_SEL(numberWithChar_,
"numberWithChar:");
_NS_PRIVATE_DEF_SEL(numberWithDouble_,
"numberWithDouble:");
_NS_PRIVATE_DEF_SEL(numberWithFloat_,
"numberWithFloat:");
_NS_PRIVATE_DEF_SEL(numberWithInt_,
"numberWithInt:");
_NS_PRIVATE_DEF_SEL(numberWithLong_,
"numberWithLong:");
_NS_PRIVATE_DEF_SEL(numberWithLongLong_,
"numberWithLongLong:");
_NS_PRIVATE_DEF_SEL(numberWithShort_,
"numberWithShort:");
_NS_PRIVATE_DEF_SEL(numberWithUnsignedChar_,
"numberWithUnsignedChar:");
_NS_PRIVATE_DEF_SEL(numberWithUnsignedInt_,
"numberWithUnsignedInt:");
_NS_PRIVATE_DEF_SEL(numberWithUnsignedLong_,
"numberWithUnsignedLong:");
_NS_PRIVATE_DEF_SEL(numberWithUnsignedLongLong_,
"numberWithUnsignedLongLong:");
_NS_PRIVATE_DEF_SEL(numberWithUnsignedShort_,
"numberWithUnsignedShort:");
_NS_PRIVATE_DEF_SEL(objCType,
"objCType");
_NS_PRIVATE_DEF_SEL(object,
"object");
_NS_PRIVATE_DEF_SEL(objectAtIndex_,
"objectAtIndex:");
_NS_PRIVATE_DEF_SEL(objectEnumerator,
"objectEnumerator");
_NS_PRIVATE_DEF_SEL(objectForInfoDictionaryKey_,
"objectForInfoDictionaryKey:");
_NS_PRIVATE_DEF_SEL(objectForKey_,
"objectForKey:");
_NS_PRIVATE_DEF_SEL(operatingSystem,
"operatingSystem");
_NS_PRIVATE_DEF_SEL(operatingSystemVersion,
"operatingSystemVersion");
_NS_PRIVATE_DEF_SEL(operatingSystemVersionString,
"operatingSystemVersionString");
_NS_PRIVATE_DEF_SEL(pathForAuxiliaryExecutable_,
"pathForAuxiliaryExecutable:");
_NS_PRIVATE_DEF_SEL(performActivityWithOptions_reason_usingBlock_,
"performActivityWithOptions:reason:usingBlock:");
_NS_PRIVATE_DEF_SEL(performExpiringActivityWithReason_usingBlock_,
"performExpiringActivityWithReason:usingBlock:");
_NS_PRIVATE_DEF_SEL(physicalMemory,
"physicalMemory");
_NS_PRIVATE_DEF_SEL(pointerValue,
"pointerValue");
_NS_PRIVATE_DEF_SEL(preflightAndReturnError_,
"preflightAndReturnError:");
_NS_PRIVATE_DEF_SEL(privateFrameworksPath,
"privateFrameworksPath");
_NS_PRIVATE_DEF_SEL(privateFrameworksURL,
"privateFrameworksURL");
_NS_PRIVATE_DEF_SEL(processIdentifier,
"processIdentifier");
_NS_PRIVATE_DEF_SEL(processInfo,
"processInfo");
_NS_PRIVATE_DEF_SEL(processName,
"processName");
_NS_PRIVATE_DEF_SEL(processorCount,
"processorCount");
_NS_PRIVATE_DEF_SEL(rangeOfString_options_,
"rangeOfString:options:");
_NS_PRIVATE_DEF_SEL(release,
"release");
_NS_PRIVATE_DEF_SEL(removeObserver_,
"removeObserver:");
_NS_PRIVATE_DEF_SEL(resourcePath,
"resourcePath");
_NS_PRIVATE_DEF_SEL(resourceURL,
"resourceURL");
_NS_PRIVATE_DEF_SEL(respondsToSelector_,
"respondsToSelector:");
_NS_PRIVATE_DEF_SEL(retain,
"retain");
_NS_PRIVATE_DEF_SEL(retainCount,
"retainCount");
_NS_PRIVATE_DEF_SEL(setAutomaticTerminationSupportEnabled_,
"setAutomaticTerminationSupportEnabled:");
_NS_PRIVATE_DEF_SEL(setProcessName_,
"setProcessName:");
_NS_PRIVATE_DEF_SEL(sharedFrameworksPath,
"sharedFrameworksPath");
_NS_PRIVATE_DEF_SEL(sharedFrameworksURL,
"sharedFrameworksURL");
_NS_PRIVATE_DEF_SEL(sharedSupportPath,
"sharedSupportPath");
_NS_PRIVATE_DEF_SEL(sharedSupportURL,
"sharedSupportURL");
_NS_PRIVATE_DEF_SEL(shortValue,
"shortValue");
_NS_PRIVATE_DEF_SEL(showPools,
"showPools");
_NS_PRIVATE_DEF_SEL(signal,
"signal");
_NS_PRIVATE_DEF_SEL(string,
"string");
_NS_PRIVATE_DEF_SEL(stringValue,
"stringValue");
_NS_PRIVATE_DEF_SEL(stringWithString_,
"stringWithString:");
_NS_PRIVATE_DEF_SEL(stringWithCString_encoding_,
"stringWithCString:encoding:");
_NS_PRIVATE_DEF_SEL(stringByAppendingString_,
"stringByAppendingString:");
_NS_PRIVATE_DEF_SEL(systemUptime,
"systemUptime");
_NS_PRIVATE_DEF_SEL(thermalState,
"thermalState");
_NS_PRIVATE_DEF_SEL(unload,
"unload");
_NS_PRIVATE_DEF_SEL(unlock,
"unlock");
_NS_PRIVATE_DEF_SEL(unsignedCharValue,
"unsignedCharValue");
_NS_PRIVATE_DEF_SEL(unsignedIntegerValue,
"unsignedIntegerValue");
_NS_PRIVATE_DEF_SEL(unsignedIntValue,
"unsignedIntValue");
_NS_PRIVATE_DEF_SEL(unsignedLongValue,
"unsignedLongValue");
_NS_PRIVATE_DEF_SEL(unsignedLongLongValue,
"unsignedLongLongValue");
_NS_PRIVATE_DEF_SEL(unsignedShortValue,
"unsignedShortValue");
_NS_PRIVATE_DEF_SEL(URLForAuxiliaryExecutable_,
"URLForAuxiliaryExecutable:");
_NS_PRIVATE_DEF_SEL(userInfo,
"userInfo");
_NS_PRIVATE_DEF_SEL(userName,
"userName");
_NS_PRIVATE_DEF_SEL(UTF8String,
"UTF8String");
_NS_PRIVATE_DEF_SEL(valueWithBytes_objCType_,
"valueWithBytes:objCType:");
_NS_PRIVATE_DEF_SEL(valueWithPointer_,
"valueWithPointer:");
_NS_PRIVATE_DEF_SEL(wait,
"wait");
_NS_PRIVATE_DEF_SEL(waitUntilDate_,
"waitUntilDate:");
} // Class
} // Private
} // MTL
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,354 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSProcessInfo.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSNotification.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
#include <functional>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
_NS_CONST(NotificationName, ProcessInfoThermalStateDidChangeNotification);
_NS_CONST(NotificationName, ProcessInfoPowerStateDidChangeNotification);
_NS_ENUM(NS::Integer, ProcessInfoThermalState) {
ProcessInfoThermalStateNominal = 0,
ProcessInfoThermalStateFair = 1,
ProcessInfoThermalStateSerious = 2,
ProcessInfoThermalStateCritical = 3
};
_NS_OPTIONS(std::uint64_t, ActivityOptions) {
ActivityIdleDisplaySleepDisabled = (1ULL << 40),
ActivityIdleSystemSleepDisabled = (1ULL << 20),
ActivitySuddenTerminationDisabled = (1ULL << 14),
ActivityAutomaticTerminationDisabled = (1ULL << 15),
ActivityUserInitiated = (0x00FFFFFFULL | ActivityIdleSystemSleepDisabled),
ActivityUserInitiatedAllowingIdleSystemSleep = (ActivityUserInitiated & ~ActivityIdleSystemSleepDisabled),
ActivityBackground = 0x000000FFULL,
ActivityLatencyCritical = 0xFF00000000ULL,
};
class ProcessInfo : public Referencing<ProcessInfo>
{
public:
static ProcessInfo* processInfo();
class Array* arguments() const;
class Dictionary* environment() const;
class String* hostName() const;
class String* processName() const;
void setProcessName(const String* pString);
int processIdentifier() const;
class String* globallyUniqueString() const;
class String* userName() const;
class String* fullUserName() const;
UInteger operatingSystem() const;
OperatingSystemVersion operatingSystemVersion() const;
class String* operatingSystemVersionString() const;
bool isOperatingSystemAtLeastVersion(OperatingSystemVersion version) const;
UInteger processorCount() const;
UInteger activeProcessorCount() const;
unsigned long long physicalMemory() const;
TimeInterval systemUptime() const;
void disableSuddenTermination();
void enableSuddenTermination();
void disableAutomaticTermination(const class String* pReason);
void enableAutomaticTermination(const class String* pReason);
bool automaticTerminationSupportEnabled() const;
void setAutomaticTerminationSupportEnabled(bool enabled);
class Object* beginActivity(ActivityOptions options, const class String* pReason);
void endActivity(class Object* pActivity);
void performActivity(ActivityOptions options, const class String* pReason, void (^block)(void));
void performActivity(ActivityOptions options, const class String* pReason, const std::function<void()>& func);
void performExpiringActivity(const class String* pReason, void (^block)(bool expired));
void performExpiringActivity(const class String* pReason, const std::function<void(bool expired)>& func);
ProcessInfoThermalState thermalState() const;
bool isLowPowerModeEnabled() const;
bool isiOSAppOnMac() const;
bool isMacCatalystApp() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_PRIVATE_DEF_CONST(NS::NotificationName, ProcessInfoThermalStateDidChangeNotification);
_NS_PRIVATE_DEF_CONST(NS::NotificationName, ProcessInfoPowerStateDidChangeNotification);
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::ProcessInfo* NS::ProcessInfo::processInfo()
{
return Object::sendMessage<ProcessInfo*>(_NS_PRIVATE_CLS(NSProcessInfo), _NS_PRIVATE_SEL(processInfo));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Array* NS::ProcessInfo::arguments() const
{
return Object::sendMessage<Array*>(this, _NS_PRIVATE_SEL(arguments));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Dictionary* NS::ProcessInfo::environment() const
{
return Object::sendMessage<Dictionary*>(this, _NS_PRIVATE_SEL(environment));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::hostName() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(hostName));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::processName() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(processName));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::setProcessName(const String* pString)
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(setProcessName_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE int NS::ProcessInfo::processIdentifier() const
{
return Object::sendMessage<int>(this, _NS_PRIVATE_SEL(processIdentifier));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::globallyUniqueString() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(globallyUniqueString));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::userName() const
{
return Object::sendMessageSafe<String*>(this, _NS_PRIVATE_SEL(userName));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::fullUserName() const
{
return Object::sendMessageSafe<String*>(this, _NS_PRIVATE_SEL(fullUserName));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::ProcessInfo::operatingSystem() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(operatingSystem));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::OperatingSystemVersion NS::ProcessInfo::operatingSystemVersion() const
{
return Object::sendMessage<OperatingSystemVersion>(this, _NS_PRIVATE_SEL(operatingSystemVersion));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::ProcessInfo::operatingSystemVersionString() const
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(operatingSystemVersionString));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::ProcessInfo::isOperatingSystemAtLeastVersion(OperatingSystemVersion version) const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(isOperatingSystemAtLeastVersion_), version);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::ProcessInfo::processorCount() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(processorCount));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::ProcessInfo::activeProcessorCount() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(activeProcessorCount));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE unsigned long long NS::ProcessInfo::physicalMemory() const
{
return Object::sendMessage<unsigned long long>(this, _NS_PRIVATE_SEL(physicalMemory));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::TimeInterval NS::ProcessInfo::systemUptime() const
{
return Object::sendMessage<TimeInterval>(this, _NS_PRIVATE_SEL(systemUptime));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::disableSuddenTermination()
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(disableSuddenTermination));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::enableSuddenTermination()
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(enableSuddenTermination));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::disableAutomaticTermination(const String* pReason)
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(disableAutomaticTermination_), pReason);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::enableAutomaticTermination(const String* pReason)
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(enableAutomaticTermination_), pReason);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::ProcessInfo::automaticTerminationSupportEnabled() const
{
return Object::sendMessageSafe<bool>(this, _NS_PRIVATE_SEL(automaticTerminationSupportEnabled));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::setAutomaticTerminationSupportEnabled(bool enabled)
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(setAutomaticTerminationSupportEnabled_), enabled);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Object* NS::ProcessInfo::beginActivity(ActivityOptions options, const String* pReason)
{
return Object::sendMessage<Object*>(this, _NS_PRIVATE_SEL(beginActivityWithOptions_reason_), options, pReason);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::endActivity(Object* pActivity)
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(endActivity_), pActivity);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::performActivity(ActivityOptions options, const String* pReason, void (^block)(void))
{
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(performActivityWithOptions_reason_usingBlock_), options, pReason, block);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::performActivity(ActivityOptions options, const String* pReason, const std::function<void()>& function)
{
__block std::function<void()> blockFunction = function;
performActivity(options, pReason, ^() { blockFunction(); });
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::performExpiringActivity(const String* pReason, void (^block)(bool expired))
{
Object::sendMessageSafe<void>(this, _NS_PRIVATE_SEL(performExpiringActivityWithReason_usingBlock_), pReason, block);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE void NS::ProcessInfo::performExpiringActivity(const String* pReason, const std::function<void(bool expired)>& function)
{
__block std::function<void(bool expired)> blockFunction = function;
performExpiringActivity(pReason, ^(bool expired) { blockFunction(expired); });
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::ProcessInfoThermalState NS::ProcessInfo::thermalState() const
{
return Object::sendMessage<ProcessInfoThermalState>(this, _NS_PRIVATE_SEL(thermalState));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::ProcessInfo::isLowPowerModeEnabled() const
{
return Object::sendMessageSafe<bool>(this, _NS_PRIVATE_SEL(isLowPowerModeEnabled));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::ProcessInfo::isiOSAppOnMac() const
{
return Object::sendMessageSafe<bool>(this, _NS_PRIVATE_SEL(isiOSAppOnMac));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::ProcessInfo::isMacCatalystApp() const
{
return Object::sendMessageSafe<bool>(this, _NS_PRIVATE_SEL(isMacCatalystApp));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,83 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSRange.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
struct Range
{
static Range Make(UInteger loc, UInteger len);
Range(UInteger loc, UInteger len);
bool Equal(const Range& range) const;
bool LocationInRange(UInteger loc) const;
UInteger Max() const;
UInteger location;
UInteger length;
} _NS_PACKED;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Range::Range(UInteger loc, UInteger len)
: location(loc)
, length(len)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Range NS::Range::Make(UInteger loc, UInteger len)
{
return Range(loc, len);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Range::Equal(const Range& range) const
{
return (location == range.location) && (length == range.length);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::Range::LocationInRange(UInteger loc) const
{
return (!(loc < location)) && ((loc - location) < length);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Range::Max() const
{
return location + length;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,87 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSSet.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSObject.hpp"
#include "NSEnumerator.hpp"
/*****Immutable Set*******/
namespace NS
{
class Set : public NS::Copying <Set>
{
public:
UInteger count() const;
Enumerator<Object>* objectEnumerator() const;
static Set* alloc();
Set* init();
Set* init(const Object* const* pObjects, UInteger count);
Set* init(const class Coder* pCoder);
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::Set::count() const
{
return NS::Object::sendMessage<NS::UInteger>(this, _NS_PRIVATE_SEL(count));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Enumerator<NS::Object>* NS::Set::objectEnumerator() const
{
return NS::Object::sendMessage<Enumerator<NS::Object>*>(this, _NS_PRIVATE_SEL(objectEnumerator));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Set* NS::Set::alloc()
{
return NS::Object::alloc<Set>(_NS_PRIVATE_CLS(NSSet));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Set* NS::Set::init()
{
return NS::Object::init<Set>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Set* NS::Set::init(const Object* const* pObjects, NS::UInteger count)
{
return NS::Object::sendMessage<Set*>(this, _NS_PRIVATE_SEL(initWithObjects_count_), pObjects, count);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Set* NS::Set::init(const class Coder* pCoder)
{
return Object::sendMessage<Set*>(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder);
}

View file

@ -0,0 +1,311 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSSharedPtr.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
#include "NSDefines.hpp"
namespace NS
{
template <class _Class>
class SharedPtr
{
public:
/**
* Create a new null pointer.
*/
SharedPtr();
/**
* Destroy this SharedPtr, decreasing the reference count.
*/
~SharedPtr();
/**
* SharedPtr copy constructor.
*/
SharedPtr(const SharedPtr<_Class>& other) noexcept;
/**
* Construction from another pointee type.
*/
template <class _OtherClass>
SharedPtr(const SharedPtr<_OtherClass>& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> * = nullptr) noexcept;
/**
* SharedPtr move constructor.
*/
SharedPtr(SharedPtr<_Class>&& other) noexcept;
/**
* Move from another pointee type.
*/
template <class _OtherClass>
SharedPtr(SharedPtr<_OtherClass>&& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> * = nullptr) noexcept;
/**
* Copy assignment operator.
* Copying increases reference count. Only releases previous pointee if objects are different.
*/
SharedPtr& operator=(const SharedPtr<_Class>& other);
/**
* Copy-assignment from different pointee.
* Copying increases reference count. Only releases previous pointee if objects are different.
*/
template <class _OtherClass>
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, SharedPtr &>
operator=(const SharedPtr<_OtherClass>& other);
/**
* Move assignment operator.
* Move without affecting reference counts, unless pointees are equal. Moved-from object is reset to nullptr.
*/
SharedPtr& operator=(SharedPtr<_Class>&& other);
/**
* Move-asignment from different pointee.
* Move without affecting reference counts, unless pointees are equal. Moved-from object is reset to nullptr.
*/
template <class _OtherClass>
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, SharedPtr &>
operator=(SharedPtr<_OtherClass>&& other);
/**
* Access raw pointee.
* @warning Avoid wrapping the returned value again, as it may lead double frees unless this object becomes detached.
*/
_Class* get() const;
/**
* Call operations directly on the pointee.
*/
_Class* operator->() const;
/**
* Implicit cast to bool.
*/
explicit operator bool() const;
/**
* Reset this SharedPtr to null, decreasing the reference count.
*/
void reset();
/**
* Detach the SharedPtr from the pointee, without decreasing the reference count.
*/
void detach();
template <class _OtherClass>
friend SharedPtr<_OtherClass> RetainPtr(_OtherClass* ptr);
template <class _OtherClass>
friend SharedPtr<_OtherClass> TransferPtr(_OtherClass* ptr);
private:
_Class* m_pObject;
};
/**
* Create a SharedPtr by retaining an existing raw pointer.
* Increases the reference count of the passed-in object.
* If the passed-in object was in an AutoreleasePool, it will be removed from it.
*/
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class> RetainPtr(_Class* pObject)
{
NS::SharedPtr<_Class> ret;
ret.m_pObject = pObject->retain();
return ret;
}
/*
* Create a SharedPtr by transfering the ownership of an existing raw pointer to SharedPtr.
* Does not increase the reference count of the passed-in pointer, it is assumed to be >= 1.
* This method does not remove objects from an AutoreleasePool.
*/
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class> TransferPtr(_Class* pObject)
{
NS::SharedPtr<_Class> ret;
ret.m_pObject = pObject;
return ret;
}
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr()
: m_pObject(nullptr)
{
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>::~SharedPtr<_Class>()
{
if (m_pObject)
{
m_pObject->release();
}
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(const NS::SharedPtr<_Class>& other) noexcept
: m_pObject(other.m_pObject->retain())
{
}
template <class _Class>
template <class _OtherClass>
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(const NS::SharedPtr<_OtherClass>& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> *) noexcept
: m_pObject(reinterpret_cast<_Class*>(other.get()->retain()))
{
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(NS::SharedPtr<_Class>&& other) noexcept
: m_pObject(other.m_pObject)
{
other.m_pObject = nullptr;
}
template <class _Class>
template <class _OtherClass>
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(NS::SharedPtr<_OtherClass>&& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> *) noexcept
: m_pObject(reinterpret_cast<_Class*>(other.get()))
{
other.detach();
}
template <class _Class>
_NS_INLINE _Class* NS::SharedPtr<_Class>::get() const
{
return m_pObject;
}
template <class _Class>
_NS_INLINE _Class* NS::SharedPtr<_Class>::operator->() const
{
return m_pObject;
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>::operator bool() const
{
return nullptr != m_pObject;
}
template <class _Class>
_NS_INLINE void NS::SharedPtr<_Class>::reset()
{
m_pObject->release();
m_pObject = nullptr;
}
template <class _Class>
_NS_INLINE void NS::SharedPtr<_Class>::detach()
{
m_pObject = nullptr;
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>& NS::SharedPtr<_Class>::operator=(const SharedPtr<_Class>& other)
{
if (m_pObject != other.m_pObject)
{
if (m_pObject)
{
m_pObject->release();
}
m_pObject = other.m_pObject->retain();
}
return *this;
}
template <class _Class>
template <class _OtherClass>
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, NS::SharedPtr<_Class> &>
_NS_INLINE NS::SharedPtr<_Class>::operator=(const SharedPtr<_OtherClass>& other)
{
if (m_pObject != other.get())
{
if (m_pObject)
{
m_pObject->release();
}
m_pObject = reinterpret_cast<_Class*>(other.get()->retain());
}
return *this;
}
template <class _Class>
_NS_INLINE NS::SharedPtr<_Class>& NS::SharedPtr<_Class>::operator=(SharedPtr<_Class>&& other)
{
if (m_pObject != other.m_pObject)
{
if (m_pObject)
{
m_pObject->release();
}
m_pObject = other.m_pObject;
}
else
{
m_pObject = other.m_pObject;
other.m_pObject->release();
}
other.m_pObject = nullptr;
return *this;
}
template <class _Class>
template <class _OtherClass>
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, NS::SharedPtr<_Class> &>
_NS_INLINE NS::SharedPtr<_Class>::operator=(SharedPtr<_OtherClass>&& other)
{
if (m_pObject != other.get())
{
if (m_pObject)
{
m_pObject->release();
}
m_pObject = reinterpret_cast<_Class*>(other.get());
other.detach();
}
else
{
m_pObject = other.get();
other.reset();
}
return *this;
}
template <class _ClassLhs, class _ClassRhs>
_NS_INLINE bool operator==(const NS::SharedPtr<_ClassLhs>& lhs, const NS::SharedPtr<_ClassRhs>& rhs)
{
return lhs.get() == rhs.get();
}
template <class _ClassLhs, class _ClassRhs>
_NS_INLINE bool operator!=(const NS::SharedPtr<_ClassLhs>& lhs, const NS::SharedPtr<_ClassRhs>& rhs)
{
return lhs.get() != rhs.get();
}

View file

@ -0,0 +1,255 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSString.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObjCRuntime.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSRange.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
_NS_ENUM(NS::UInteger, StringEncoding) {
ASCIIStringEncoding = 1,
NEXTSTEPStringEncoding = 2,
JapaneseEUCStringEncoding = 3,
UTF8StringEncoding = 4,
ISOLatin1StringEncoding = 5,
SymbolStringEncoding = 6,
NonLossyASCIIStringEncoding = 7,
ShiftJISStringEncoding = 8,
ISOLatin2StringEncoding = 9,
UnicodeStringEncoding = 10,
WindowsCP1251StringEncoding = 11,
WindowsCP1252StringEncoding = 12,
WindowsCP1253StringEncoding = 13,
WindowsCP1254StringEncoding = 14,
WindowsCP1250StringEncoding = 15,
ISO2022JPStringEncoding = 21,
MacOSRomanStringEncoding = 30,
UTF16StringEncoding = UnicodeStringEncoding,
UTF16BigEndianStringEncoding = 0x90000100,
UTF16LittleEndianStringEncoding = 0x94000100,
UTF32StringEncoding = 0x8c000100,
UTF32BigEndianStringEncoding = 0x98000100,
UTF32LittleEndianStringEncoding = 0x9c000100
};
_NS_OPTIONS(NS::UInteger, StringCompareOptions) {
CaseInsensitiveSearch = 1,
LiteralSearch = 2,
BackwardsSearch = 4,
AnchoredSearch = 8,
NumericSearch = 64,
DiacriticInsensitiveSearch = 128,
WidthInsensitiveSearch = 256,
ForcedOrderingSearch = 512,
RegularExpressionSearch = 1024
};
using unichar = unsigned short;
class String : public Copying<String>
{
public:
static String* string();
static String* string(const String* pString);
static String* string(const char* pString, StringEncoding encoding);
static String* alloc();
String* init();
String* init(const String* pString);
String* init(const char* pString, StringEncoding encoding);
String* init(void* pBytes, UInteger len, StringEncoding encoding, bool freeBuffer);
unichar character(UInteger index) const;
UInteger length() const;
const char* cString(StringEncoding encoding) const;
const char* utf8String() const;
UInteger maximumLengthOfBytes(StringEncoding encoding) const;
UInteger lengthOfBytes(StringEncoding encoding) const;
bool isEqualToString(const String* pString) const;
Range rangeOfString(const String* pString, StringCompareOptions options) const;
const char* fileSystemRepresentation() const;
String* stringByAppendingString(const String* pString) const;
ComparisonResult caseInsensitiveCompare(const String* pString) const;
};
/// Create an NS::String* from a string literal.
#define MTLSTR(literal) (NS::String*)__builtin___CFStringMakeConstantString("" literal "")
template <std::size_t _StringLen>
[[deprecated("please use MTLSTR(str)")]] constexpr const String* MakeConstantString(const char (&str)[_StringLen])
{
return reinterpret_cast<const String*>(__CFStringMakeConstantString(str));
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::string()
{
return Object::sendMessage<String*>(_NS_PRIVATE_CLS(NSString), _NS_PRIVATE_SEL(string));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::string(const String* pString)
{
return Object::sendMessage<String*>(_NS_PRIVATE_CLS(NSString), _NS_PRIVATE_SEL(stringWithString_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::string(const char* pString, StringEncoding encoding)
{
return Object::sendMessage<String*>(_NS_PRIVATE_CLS(NSString), _NS_PRIVATE_SEL(stringWithCString_encoding_), pString, encoding);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::alloc()
{
return Object::alloc<String>(_NS_PRIVATE_CLS(NSString));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::init()
{
return Object::init<String>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::init(const String* pString)
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(initWithString_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::init(const char* pString, StringEncoding encoding)
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(initWithCString_encoding_), pString, encoding);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::init(void* pBytes, UInteger len, StringEncoding encoding, bool freeBuffer)
{
return Object::sendMessage<String*>(this, _NS_PRIVATE_SEL(initWithBytesNoCopy_length_encoding_freeWhenDone_), pBytes, len, encoding, freeBuffer);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::unichar NS::String::character(UInteger index) const
{
return Object::sendMessage<unichar>(this, _NS_PRIVATE_SEL(characterAtIndex_), index);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::String::length() const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(length));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE const char* NS::String::cString(StringEncoding encoding) const
{
return Object::sendMessage<const char*>(this, _NS_PRIVATE_SEL(cStringUsingEncoding_), encoding);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE const char* NS::String::utf8String() const
{
return Object::sendMessage<const char*>(this, _NS_PRIVATE_SEL(UTF8String));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::String::maximumLengthOfBytes(StringEncoding encoding) const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(maximumLengthOfBytesUsingEncoding_), encoding);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::UInteger NS::String::lengthOfBytes(StringEncoding encoding) const
{
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(lengthOfBytesUsingEncoding_), encoding);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE bool NS::String::isEqualToString(const NS::String* pString) const
{
return Object::sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqualToString_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::Range NS::String::rangeOfString(const NS::String* pString, NS::StringCompareOptions options) const
{
return Object::sendMessage<Range>(this, _NS_PRIVATE_SEL(rangeOfString_options_), pString, options);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE const char* NS::String::fileSystemRepresentation() const
{
return Object::sendMessage<const char*>(this, _NS_PRIVATE_SEL(fileSystemRepresentation));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::String* NS::String::stringByAppendingString(const String* pString) const
{
return Object::sendMessage<NS::String*>(this, _NS_PRIVATE_SEL(stringByAppendingString_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::ComparisonResult NS::String::caseInsensitiveCompare(const String* pString) const
{
return Object::sendMessage<NS::ComparisonResult>(this, _NS_PRIVATE_SEL(caseInsensitiveCompare_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,51 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSTypes.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include <CoreFoundation/CoreFoundation.h>
#include <cstdint>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
using TimeInterval = double;
using Integer = std::intptr_t;
using UInteger = std::uintptr_t;
const Integer IntegerMax = INTPTR_MAX;
const Integer IntegerMin = INTPTR_MIN;
const UInteger UIntegerMax = UINTPTR_MAX;
struct OperatingSystemVersion
{
Integer majorVersion;
Integer minorVersion;
Integer patchVersion;
} _NS_PACKED;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,90 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Foundation/NSURL.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "NSDefines.hpp"
#include "NSObject.hpp"
#include "NSPrivate.hpp"
#include "NSTypes.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace NS
{
class URL : public Copying<URL>
{
public:
static URL* fileURLWithPath(const class String* pPath);
static URL* alloc();
URL* init();
URL* init(const class String* pString);
URL* initFileURLWithPath(const class String* pPath);
const char* fileSystemRepresentation() const;
};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::URL::fileURLWithPath(const String* pPath)
{
return Object::sendMessage<URL*>(_NS_PRIVATE_CLS(NSURL), _NS_PRIVATE_SEL(fileURLWithPath_), pPath);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::URL::alloc()
{
return Object::alloc<URL>(_NS_PRIVATE_CLS(NSURL));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::URL::init()
{
return Object::init<URL>();
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::URL::init(const String* pString)
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(initWithString_), pString);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE NS::URL* NS::URL::initFileURLWithPath(const String* pPath)
{
return Object::sendMessage<URL*>(this, _NS_PRIVATE_SEL(initFileURLWithPath_), pPath);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_NS_INLINE const char* NS::URL::fileSystemRepresentation() const
{
return Object::sendMessage<const char*>(this, _NS_PRIVATE_SEL(fileSystemRepresentation));
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

202
third_party/metal-cpp/LICENSE.txt vendored Normal file
View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright © 2023 Apple Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,290 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Metal/MTLAccelerationStructureCommandEncoder.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
#include "MTLDefines.hpp"
#include "MTLHeaderBridge.hpp"
#include "MTLPrivate.hpp"
#include <Foundation/Foundation.hpp>
#include "MTLAccelerationStructureCommandEncoder.hpp"
#include "MTLArgument.hpp"
#include "MTLCommandEncoder.hpp"
namespace MTL
{
_MTL_OPTIONS(NS::UInteger, AccelerationStructureRefitOptions) {
AccelerationStructureRefitOptionVertexData = 1,
AccelerationStructureRefitOptionPerPrimitiveData = 2,
};
class AccelerationStructureCommandEncoder : public NS::Referencing<AccelerationStructureCommandEncoder, CommandEncoder>
{
public:
void buildAccelerationStructure(const class AccelerationStructure* accelerationStructure, const class AccelerationStructureDescriptor* descriptor, const class Buffer* scratchBuffer, NS::UInteger scratchBufferOffset);
void refitAccelerationStructure(const class AccelerationStructure* sourceAccelerationStructure, const class AccelerationStructureDescriptor* descriptor, const class AccelerationStructure* destinationAccelerationStructure, const class Buffer* scratchBuffer, NS::UInteger scratchBufferOffset);
void refitAccelerationStructure(const class AccelerationStructure* sourceAccelerationStructure, const class AccelerationStructureDescriptor* descriptor, const class AccelerationStructure* destinationAccelerationStructure, const class Buffer* scratchBuffer, NS::UInteger scratchBufferOffset, MTL::AccelerationStructureRefitOptions options);
void copyAccelerationStructure(const class AccelerationStructure* sourceAccelerationStructure, const class AccelerationStructure* destinationAccelerationStructure);
void writeCompactedAccelerationStructureSize(const class AccelerationStructure* accelerationStructure, const class Buffer* buffer, NS::UInteger offset);
void writeCompactedAccelerationStructureSize(const class AccelerationStructure* accelerationStructure, const class Buffer* buffer, NS::UInteger offset, MTL::DataType sizeDataType);
void copyAndCompactAccelerationStructure(const class AccelerationStructure* sourceAccelerationStructure, const class AccelerationStructure* destinationAccelerationStructure);
void updateFence(const class Fence* fence);
void waitForFence(const class Fence* fence);
void useResource(const class Resource* resource, MTL::ResourceUsage usage);
void useResources(const class Resource* const resources[], NS::UInteger count, MTL::ResourceUsage usage);
void useHeap(const class Heap* heap);
void useHeaps(const class Heap* const heaps[], NS::UInteger count);
void sampleCountersInBuffer(const class CounterSampleBuffer* sampleBuffer, NS::UInteger sampleIndex, bool barrier);
};
class AccelerationStructurePassSampleBufferAttachmentDescriptor : public NS::Copying<AccelerationStructurePassSampleBufferAttachmentDescriptor>
{
public:
static class AccelerationStructurePassSampleBufferAttachmentDescriptor* alloc();
class AccelerationStructurePassSampleBufferAttachmentDescriptor* init();
class CounterSampleBuffer* sampleBuffer() const;
void setSampleBuffer(const class CounterSampleBuffer* sampleBuffer);
NS::UInteger startOfEncoderSampleIndex() const;
void setStartOfEncoderSampleIndex(NS::UInteger startOfEncoderSampleIndex);
NS::UInteger endOfEncoderSampleIndex() const;
void setEndOfEncoderSampleIndex(NS::UInteger endOfEncoderSampleIndex);
};
class AccelerationStructurePassSampleBufferAttachmentDescriptorArray : public NS::Referencing<AccelerationStructurePassSampleBufferAttachmentDescriptorArray>
{
public:
static class AccelerationStructurePassSampleBufferAttachmentDescriptorArray* alloc();
class AccelerationStructurePassSampleBufferAttachmentDescriptorArray* init();
class AccelerationStructurePassSampleBufferAttachmentDescriptor* object(NS::UInteger attachmentIndex);
void setObject(const class AccelerationStructurePassSampleBufferAttachmentDescriptor* attachment, NS::UInteger attachmentIndex);
};
class AccelerationStructurePassDescriptor : public NS::Copying<AccelerationStructurePassDescriptor>
{
public:
static class AccelerationStructurePassDescriptor* alloc();
class AccelerationStructurePassDescriptor* init();
static class AccelerationStructurePassDescriptor* accelerationStructurePassDescriptor();
class AccelerationStructurePassSampleBufferAttachmentDescriptorArray* sampleBufferAttachments() const;
};
}
// method: buildAccelerationStructure:descriptor:scratchBuffer:scratchBufferOffset:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::buildAccelerationStructure(const MTL::AccelerationStructure* accelerationStructure, const MTL::AccelerationStructureDescriptor* descriptor, const MTL::Buffer* scratchBuffer, NS::UInteger scratchBufferOffset)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(buildAccelerationStructure_descriptor_scratchBuffer_scratchBufferOffset_), accelerationStructure, descriptor, scratchBuffer, scratchBufferOffset);
}
// method: refitAccelerationStructure:descriptor:destination:scratchBuffer:scratchBufferOffset:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::refitAccelerationStructure(const MTL::AccelerationStructure* sourceAccelerationStructure, const MTL::AccelerationStructureDescriptor* descriptor, const MTL::AccelerationStructure* destinationAccelerationStructure, const MTL::Buffer* scratchBuffer, NS::UInteger scratchBufferOffset)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset_), sourceAccelerationStructure, descriptor, destinationAccelerationStructure, scratchBuffer, scratchBufferOffset);
}
// method: refitAccelerationStructure:descriptor:destination:scratchBuffer:scratchBufferOffset:options:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::refitAccelerationStructure(const MTL::AccelerationStructure* sourceAccelerationStructure, const MTL::AccelerationStructureDescriptor* descriptor, const MTL::AccelerationStructure* destinationAccelerationStructure, const MTL::Buffer* scratchBuffer, NS::UInteger scratchBufferOffset, MTL::AccelerationStructureRefitOptions options)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset_options_), sourceAccelerationStructure, descriptor, destinationAccelerationStructure, scratchBuffer, scratchBufferOffset, options);
}
// method: copyAccelerationStructure:toAccelerationStructure:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::copyAccelerationStructure(const MTL::AccelerationStructure* sourceAccelerationStructure, const MTL::AccelerationStructure* destinationAccelerationStructure)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(copyAccelerationStructure_toAccelerationStructure_), sourceAccelerationStructure, destinationAccelerationStructure);
}
// method: writeCompactedAccelerationStructureSize:toBuffer:offset:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::writeCompactedAccelerationStructureSize(const MTL::AccelerationStructure* accelerationStructure, const MTL::Buffer* buffer, NS::UInteger offset)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(writeCompactedAccelerationStructureSize_toBuffer_offset_), accelerationStructure, buffer, offset);
}
// method: writeCompactedAccelerationStructureSize:toBuffer:offset:sizeDataType:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::writeCompactedAccelerationStructureSize(const MTL::AccelerationStructure* accelerationStructure, const MTL::Buffer* buffer, NS::UInteger offset, MTL::DataType sizeDataType)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(writeCompactedAccelerationStructureSize_toBuffer_offset_sizeDataType_), accelerationStructure, buffer, offset, sizeDataType);
}
// method: copyAndCompactAccelerationStructure:toAccelerationStructure:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::copyAndCompactAccelerationStructure(const MTL::AccelerationStructure* sourceAccelerationStructure, const MTL::AccelerationStructure* destinationAccelerationStructure)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(copyAndCompactAccelerationStructure_toAccelerationStructure_), sourceAccelerationStructure, destinationAccelerationStructure);
}
// method: updateFence:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::updateFence(const MTL::Fence* fence)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(updateFence_), fence);
}
// method: waitForFence:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::waitForFence(const MTL::Fence* fence)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(waitForFence_), fence);
}
// method: useResource:usage:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::useResource(const MTL::Resource* resource, MTL::ResourceUsage usage)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useResource_usage_), resource, usage);
}
// method: useResources:count:usage:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::useResources(const MTL::Resource* const resources[], NS::UInteger count, MTL::ResourceUsage usage)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useResources_count_usage_), resources, count, usage);
}
// method: useHeap:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::useHeap(const MTL::Heap* heap)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useHeap_), heap);
}
// method: useHeaps:count:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::useHeaps(const MTL::Heap* const heaps[], NS::UInteger count)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useHeaps_count_), heaps, count);
}
// method: sampleCountersInBuffer:atSampleIndex:withBarrier:
_MTL_INLINE void MTL::AccelerationStructureCommandEncoder::sampleCountersInBuffer(const MTL::CounterSampleBuffer* sampleBuffer, NS::UInteger sampleIndex, bool barrier)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(sampleCountersInBuffer_atSampleIndex_withBarrier_), sampleBuffer, sampleIndex, barrier);
}
// static method: alloc
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::alloc()
{
return NS::Object::alloc<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor>(_MTL_PRIVATE_CLS(MTLAccelerationStructurePassSampleBufferAttachmentDescriptor));
}
// method: init
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::init()
{
return NS::Object::init<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor>();
}
// property: sampleBuffer
_MTL_INLINE MTL::CounterSampleBuffer* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::sampleBuffer() const
{
return Object::sendMessage<MTL::CounterSampleBuffer*>(this, _MTL_PRIVATE_SEL(sampleBuffer));
}
_MTL_INLINE void MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::setSampleBuffer(const MTL::CounterSampleBuffer* sampleBuffer)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setSampleBuffer_), sampleBuffer);
}
// property: startOfEncoderSampleIndex
_MTL_INLINE NS::UInteger MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::startOfEncoderSampleIndex() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(startOfEncoderSampleIndex));
}
_MTL_INLINE void MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::setStartOfEncoderSampleIndex(NS::UInteger startOfEncoderSampleIndex)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setStartOfEncoderSampleIndex_), startOfEncoderSampleIndex);
}
// property: endOfEncoderSampleIndex
_MTL_INLINE NS::UInteger MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::endOfEncoderSampleIndex() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(endOfEncoderSampleIndex));
}
_MTL_INLINE void MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor::setEndOfEncoderSampleIndex(NS::UInteger endOfEncoderSampleIndex)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setEndOfEncoderSampleIndex_), endOfEncoderSampleIndex);
}
// static method: alloc
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray::alloc()
{
return NS::Object::alloc<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray>(_MTL_PRIVATE_CLS(MTLAccelerationStructurePassSampleBufferAttachmentDescriptorArray));
}
// method: init
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray::init()
{
return NS::Object::init<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray>();
}
// method: objectAtIndexedSubscript:
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor* MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray::object(NS::UInteger attachmentIndex)
{
return Object::sendMessage<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor*>(this, _MTL_PRIVATE_SEL(objectAtIndexedSubscript_), attachmentIndex);
}
// method: setObject:atIndexedSubscript:
_MTL_INLINE void MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray::setObject(const MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor* attachment, NS::UInteger attachmentIndex)
{
Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setObject_atIndexedSubscript_), attachment, attachmentIndex);
}
// static method: alloc
_MTL_INLINE MTL::AccelerationStructurePassDescriptor* MTL::AccelerationStructurePassDescriptor::alloc()
{
return NS::Object::alloc<MTL::AccelerationStructurePassDescriptor>(_MTL_PRIVATE_CLS(MTLAccelerationStructurePassDescriptor));
}
// method: init
_MTL_INLINE MTL::AccelerationStructurePassDescriptor* MTL::AccelerationStructurePassDescriptor::init()
{
return NS::Object::init<MTL::AccelerationStructurePassDescriptor>();
}
// static method: accelerationStructurePassDescriptor
_MTL_INLINE MTL::AccelerationStructurePassDescriptor* MTL::AccelerationStructurePassDescriptor::accelerationStructurePassDescriptor()
{
return Object::sendMessage<MTL::AccelerationStructurePassDescriptor*>(_MTL_PRIVATE_CLS(MTLAccelerationStructurePassDescriptor), _MTL_PRIVATE_SEL(accelerationStructurePassDescriptor));
}
// property: sampleBufferAttachments
_MTL_INLINE MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray* MTL::AccelerationStructurePassDescriptor::sampleBufferAttachments() const
{
return Object::sendMessage<MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray*>(this, _MTL_PRIVATE_SEL(sampleBufferAttachments));
}

View file

@ -0,0 +1,169 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Metal/MTLAccelerationStructureTypes.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "MTLDefines.hpp"
#include "MTLPrivate.hpp"
#include "MTLResource.hpp"
#include "MTLStageInputOutputDescriptor.hpp"
#include "../Foundation/NSRange.hpp"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace MTL
{
struct PackedFloat3
{
PackedFloat3();
PackedFloat3(float x, float y, float z);
float& operator[](int idx);
float operator[](int idx) const;
union
{
struct
{
float x;
float y;
float z;
};
float elements[3];
};
} _MTL_PACKED;
struct PackedFloat4x3
{
PackedFloat4x3();
PackedFloat4x3(const PackedFloat3& col0, const PackedFloat3& col1, const PackedFloat3& col2, const PackedFloat3& col3);
PackedFloat3& operator[](int idx);
const PackedFloat3& operator[](int idx) const;
PackedFloat3 columns[4];
} _MTL_PACKED;
struct AxisAlignedBoundingBox
{
AxisAlignedBoundingBox();
AxisAlignedBoundingBox(PackedFloat3 p);
AxisAlignedBoundingBox(PackedFloat3 min, PackedFloat3 max);
PackedFloat3 min;
PackedFloat3 max;
} _MTL_PACKED;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::PackedFloat3::PackedFloat3()
: x(0.0f)
, y(0.0f)
, z(0.0f)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::PackedFloat3::PackedFloat3(float _x, float _y, float _z)
: x(_x)
, y(_y)
, z(_z)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE float& MTL::PackedFloat3::operator[](int idx)
{
return elements[idx];
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE float MTL::PackedFloat3::operator[](int idx) const
{
return elements[idx];
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::PackedFloat4x3::PackedFloat4x3()
{
columns[0] = PackedFloat3(0.0f, 0.0f, 0.0f);
columns[1] = PackedFloat3(0.0f, 0.0f, 0.0f);
columns[2] = PackedFloat3(0.0f, 0.0f, 0.0f);
columns[3] = PackedFloat3(0.0f, 0.0f, 0.0f);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::PackedFloat4x3::PackedFloat4x3(const PackedFloat3& col0, const PackedFloat3& col1, const PackedFloat3& col2, const PackedFloat3& col3)
{
columns[0] = col0;
columns[1] = col1;
columns[2] = col2;
columns[3] = col3;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::PackedFloat3& MTL::PackedFloat4x3::operator[](int idx)
{
return columns[idx];
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE const MTL::PackedFloat3& MTL::PackedFloat4x3::operator[](int idx) const
{
return columns[idx];
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::AxisAlignedBoundingBox::AxisAlignedBoundingBox()
: min(INFINITY, INFINITY, INFINITY)
, max(-INFINITY, -INFINITY, -INFINITY)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::AxisAlignedBoundingBox::AxisAlignedBoundingBox(PackedFloat3 p)
: min(p)
, max(p)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
_MTL_INLINE MTL::AxisAlignedBoundingBox::AxisAlignedBoundingBox(PackedFloat3 _min, PackedFloat3 _max)
: min(_min)
, max(_max)
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,848 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//
// Metal/MTLArgument.hpp
//
// Copyright 2020-2023 Apple Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#pragma once
#include "MTLDefines.hpp"
#include "MTLHeaderBridge.hpp"
#include "MTLPrivate.hpp"
#include <Foundation/Foundation.hpp>
#include "MTLArgument.hpp"
#include "MTLTexture.hpp"
namespace MTL
{
_MTL_ENUM(NS::UInteger, DataType) {
DataTypeNone = 0,
DataTypeStruct = 1,
DataTypeArray = 2,
DataTypeFloat = 3,
DataTypeFloat2 = 4,
DataTypeFloat3 = 5,
DataTypeFloat4 = 6,
DataTypeFloat2x2 = 7,
DataTypeFloat2x3 = 8,
DataTypeFloat2x4 = 9,
DataTypeFloat3x2 = 10,
DataTypeFloat3x3 = 11,
DataTypeFloat3x4 = 12,
DataTypeFloat4x2 = 13,
DataTypeFloat4x3 = 14,
DataTypeFloat4x4 = 15,
DataTypeHalf = 16,
DataTypeHalf2 = 17,
DataTypeHalf3 = 18,
DataTypeHalf4 = 19,
DataTypeHalf2x2 = 20,
DataTypeHalf2x3 = 21,
DataTypeHalf2x4 = 22,
DataTypeHalf3x2 = 23,
DataTypeHalf3x3 = 24,
DataTypeHalf3x4 = 25,
DataTypeHalf4x2 = 26,
DataTypeHalf4x3 = 27,
DataTypeHalf4x4 = 28,
DataTypeInt = 29,
DataTypeInt2 = 30,
DataTypeInt3 = 31,
DataTypeInt4 = 32,
DataTypeUInt = 33,
DataTypeUInt2 = 34,
DataTypeUInt3 = 35,
DataTypeUInt4 = 36,
DataTypeShort = 37,
DataTypeShort2 = 38,
DataTypeShort3 = 39,
DataTypeShort4 = 40,
DataTypeUShort = 41,
DataTypeUShort2 = 42,
DataTypeUShort3 = 43,
DataTypeUShort4 = 44,
DataTypeChar = 45,
DataTypeChar2 = 46,
DataTypeChar3 = 47,
DataTypeChar4 = 48,
DataTypeUChar = 49,
DataTypeUChar2 = 50,
DataTypeUChar3 = 51,
DataTypeUChar4 = 52,
DataTypeBool = 53,
DataTypeBool2 = 54,
DataTypeBool3 = 55,
DataTypeBool4 = 56,
DataTypeTexture = 58,
DataTypeSampler = 59,
DataTypePointer = 60,
DataTypeR8Unorm = 62,
DataTypeR8Snorm = 63,
DataTypeR16Unorm = 64,
DataTypeR16Snorm = 65,
DataTypeRG8Unorm = 66,
DataTypeRG8Snorm = 67,
DataTypeRG16Unorm = 68,
DataTypeRG16Snorm = 69,
DataTypeRGBA8Unorm = 70,
DataTypeRGBA8Unorm_sRGB = 71,
DataTypeRGBA8Snorm = 72,
DataTypeRGBA16Unorm = 73,
DataTypeRGBA16Snorm = 74,
DataTypeRGB10A2Unorm = 75,
DataTypeRG11B10Float = 76,
DataTypeRGB9E5Float = 77,
DataTypeRenderPipeline = 78,
DataTypeComputePipeline = 79,
DataTypeIndirectCommandBuffer = 80,
DataTypeLong = 81,
DataTypeLong2 = 82,
DataTypeLong3 = 83,
DataTypeLong4 = 84,
DataTypeULong = 85,
DataTypeULong2 = 86,
DataTypeULong3 = 87,
DataTypeULong4 = 88,
DataTypeVisibleFunctionTable = 115,
DataTypeIntersectionFunctionTable = 116,
DataTypePrimitiveAccelerationStructure = 117,
DataTypeInstanceAccelerationStructure = 118,
DataTypeBFloat = 121,
DataTypeBFloat2 = 122,
DataTypeBFloat3 = 123,
DataTypeBFloat4 = 124,
};
_MTL_ENUM(NS::Integer, BindingType) {
BindingTypeBuffer = 0,
BindingTypeThreadgroupMemory = 1,
BindingTypeTexture = 2,
BindingTypeSampler = 3,
BindingTypeImageblockData = 16,
BindingTypeImageblock = 17,
BindingTypeVisibleFunctionTable = 24,
BindingTypePrimitiveAccelerationStructure = 25,
BindingTypeInstanceAccelerationStructure = 26,
BindingTypeIntersectionFunctionTable = 27,
BindingTypeObjectPayload = 34,
};
_MTL_ENUM(NS::UInteger, ArgumentType) {
ArgumentTypeBuffer = 0,
ArgumentTypeThreadgroupMemory = 1,
ArgumentTypeTexture = 2,
ArgumentTypeSampler = 3,
ArgumentTypeImageblockData = 16,
ArgumentTypeImageblock = 17,
ArgumentTypeVisibleFunctionTable = 24,
ArgumentTypePrimitiveAccelerationStructure = 25,
ArgumentTypeInstanceAccelerationStructure = 26,
ArgumentTypeIntersectionFunctionTable = 27,
};
_MTL_ENUM(NS::UInteger, BindingAccess) {
BindingAccessReadOnly = 0,
BindingAccessReadWrite = 1,
BindingAccessWriteOnly = 2,
ArgumentAccessReadOnly = 0,
ArgumentAccessReadWrite = 1,
ArgumentAccessWriteOnly = 2,
};
class Type : public NS::Referencing<Type>
{
public:
static class Type* alloc();
class Type* init();
MTL::DataType dataType() const;
};
class StructMember : public NS::Referencing<StructMember>
{
public:
static class StructMember* alloc();
class StructMember* init();
NS::String* name() const;
NS::UInteger offset() const;
MTL::DataType dataType() const;
class StructType* structType();
class ArrayType* arrayType();
class TextureReferenceType* textureReferenceType();
class PointerType* pointerType();
NS::UInteger argumentIndex() const;
};
class StructType : public NS::Referencing<StructType, Type>
{
public:
static class StructType* alloc();
class StructType* init();
NS::Array* members() const;
class StructMember* memberByName(const NS::String* name);
};
class ArrayType : public NS::Referencing<ArrayType, Type>
{
public:
static class ArrayType* alloc();
class ArrayType* init();
MTL::DataType elementType() const;
NS::UInteger arrayLength() const;
NS::UInteger stride() const;
NS::UInteger argumentIndexStride() const;
class StructType* elementStructType();
class ArrayType* elementArrayType();
class TextureReferenceType* elementTextureReferenceType();
class PointerType* elementPointerType();
};
class PointerType : public NS::Referencing<PointerType, Type>
{
public:
static class PointerType* alloc();
class PointerType* init();
MTL::DataType elementType() const;
MTL::BindingAccess access() const;
NS::UInteger alignment() const;
NS::UInteger dataSize() const;
bool elementIsArgumentBuffer() const;
class StructType* elementStructType();
class ArrayType* elementArrayType();
};
class TextureReferenceType : public NS::Referencing<TextureReferenceType, Type>
{
public:
static class TextureReferenceType* alloc();
class TextureReferenceType* init();
MTL::DataType textureDataType() const;
MTL::TextureType textureType() const;
MTL::BindingAccess access() const;
bool isDepthTexture() const;
};
class Argument : public NS::Referencing<Argument>
{
public:
static class Argument* alloc();
class Argument* init();
NS::String* name() const;
MTL::ArgumentType type() const;
MTL::BindingAccess access() const;
NS::UInteger index() const;
bool active() const;
NS::UInteger bufferAlignment() const;
NS::UInteger bufferDataSize() const;
MTL::DataType bufferDataType() const;
class StructType* bufferStructType() const;
class PointerType* bufferPointerType() const;
NS::UInteger threadgroupMemoryAlignment() const;
NS::UInteger threadgroupMemoryDataSize() const;
MTL::TextureType textureType() const;
MTL::DataType textureDataType() const;
bool isDepthTexture() const;
NS::UInteger arrayLength() const;
};
class Binding : public NS::Referencing<Binding>
{
public:
NS::String* name() const;
MTL::BindingType type() const;
MTL::BindingAccess access() const;
NS::UInteger index() const;
bool used() const;
bool argument() const;
};
class BufferBinding : public NS::Referencing<BufferBinding, Binding>
{
public:
NS::UInteger bufferAlignment() const;
NS::UInteger bufferDataSize() const;
MTL::DataType bufferDataType() const;
class StructType* bufferStructType() const;
class PointerType* bufferPointerType() const;
};
class ThreadgroupBinding : public NS::Referencing<ThreadgroupBinding, Binding>
{
public:
NS::UInteger threadgroupMemoryAlignment() const;
NS::UInteger threadgroupMemoryDataSize() const;
};
class TextureBinding : public NS::Referencing<TextureBinding, Binding>
{
public:
MTL::TextureType textureType() const;
MTL::DataType textureDataType() const;
bool depthTexture() const;
NS::UInteger arrayLength() const;
};
class ObjectPayloadBinding : public NS::Referencing<ObjectPayloadBinding, Binding>
{
public:
NS::UInteger objectPayloadAlignment() const;
NS::UInteger objectPayloadDataSize() const;
};
}
// static method: alloc
_MTL_INLINE MTL::Type* MTL::Type::alloc()
{
return NS::Object::alloc<MTL::Type>(_MTL_PRIVATE_CLS(MTLType));
}
// method: init
_MTL_INLINE MTL::Type* MTL::Type::init()
{
return NS::Object::init<MTL::Type>();
}
// property: dataType
_MTL_INLINE MTL::DataType MTL::Type::dataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(dataType));
}
// static method: alloc
_MTL_INLINE MTL::StructMember* MTL::StructMember::alloc()
{
return NS::Object::alloc<MTL::StructMember>(_MTL_PRIVATE_CLS(MTLStructMember));
}
// method: init
_MTL_INLINE MTL::StructMember* MTL::StructMember::init()
{
return NS::Object::init<MTL::StructMember>();
}
// property: name
_MTL_INLINE NS::String* MTL::StructMember::name() const
{
return Object::sendMessage<NS::String*>(this, _MTL_PRIVATE_SEL(name));
}
// property: offset
_MTL_INLINE NS::UInteger MTL::StructMember::offset() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(offset));
}
// property: dataType
_MTL_INLINE MTL::DataType MTL::StructMember::dataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(dataType));
}
// method: structType
_MTL_INLINE MTL::StructType* MTL::StructMember::structType()
{
return Object::sendMessage<MTL::StructType*>(this, _MTL_PRIVATE_SEL(structType));
}
// method: arrayType
_MTL_INLINE MTL::ArrayType* MTL::StructMember::arrayType()
{
return Object::sendMessage<MTL::ArrayType*>(this, _MTL_PRIVATE_SEL(arrayType));
}
// method: textureReferenceType
_MTL_INLINE MTL::TextureReferenceType* MTL::StructMember::textureReferenceType()
{
return Object::sendMessage<MTL::TextureReferenceType*>(this, _MTL_PRIVATE_SEL(textureReferenceType));
}
// method: pointerType
_MTL_INLINE MTL::PointerType* MTL::StructMember::pointerType()
{
return Object::sendMessage<MTL::PointerType*>(this, _MTL_PRIVATE_SEL(pointerType));
}
// property: argumentIndex
_MTL_INLINE NS::UInteger MTL::StructMember::argumentIndex() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(argumentIndex));
}
// static method: alloc
_MTL_INLINE MTL::StructType* MTL::StructType::alloc()
{
return NS::Object::alloc<MTL::StructType>(_MTL_PRIVATE_CLS(MTLStructType));
}
// method: init
_MTL_INLINE MTL::StructType* MTL::StructType::init()
{
return NS::Object::init<MTL::StructType>();
}
// property: members
_MTL_INLINE NS::Array* MTL::StructType::members() const
{
return Object::sendMessage<NS::Array*>(this, _MTL_PRIVATE_SEL(members));
}
// method: memberByName:
_MTL_INLINE MTL::StructMember* MTL::StructType::memberByName(const NS::String* name)
{
return Object::sendMessage<MTL::StructMember*>(this, _MTL_PRIVATE_SEL(memberByName_), name);
}
// static method: alloc
_MTL_INLINE MTL::ArrayType* MTL::ArrayType::alloc()
{
return NS::Object::alloc<MTL::ArrayType>(_MTL_PRIVATE_CLS(MTLArrayType));
}
// method: init
_MTL_INLINE MTL::ArrayType* MTL::ArrayType::init()
{
return NS::Object::init<MTL::ArrayType>();
}
// property: elementType
_MTL_INLINE MTL::DataType MTL::ArrayType::elementType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(elementType));
}
// property: arrayLength
_MTL_INLINE NS::UInteger MTL::ArrayType::arrayLength() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(arrayLength));
}
// property: stride
_MTL_INLINE NS::UInteger MTL::ArrayType::stride() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(stride));
}
// property: argumentIndexStride
_MTL_INLINE NS::UInteger MTL::ArrayType::argumentIndexStride() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(argumentIndexStride));
}
// method: elementStructType
_MTL_INLINE MTL::StructType* MTL::ArrayType::elementStructType()
{
return Object::sendMessage<MTL::StructType*>(this, _MTL_PRIVATE_SEL(elementStructType));
}
// method: elementArrayType
_MTL_INLINE MTL::ArrayType* MTL::ArrayType::elementArrayType()
{
return Object::sendMessage<MTL::ArrayType*>(this, _MTL_PRIVATE_SEL(elementArrayType));
}
// method: elementTextureReferenceType
_MTL_INLINE MTL::TextureReferenceType* MTL::ArrayType::elementTextureReferenceType()
{
return Object::sendMessage<MTL::TextureReferenceType*>(this, _MTL_PRIVATE_SEL(elementTextureReferenceType));
}
// method: elementPointerType
_MTL_INLINE MTL::PointerType* MTL::ArrayType::elementPointerType()
{
return Object::sendMessage<MTL::PointerType*>(this, _MTL_PRIVATE_SEL(elementPointerType));
}
// static method: alloc
_MTL_INLINE MTL::PointerType* MTL::PointerType::alloc()
{
return NS::Object::alloc<MTL::PointerType>(_MTL_PRIVATE_CLS(MTLPointerType));
}
// method: init
_MTL_INLINE MTL::PointerType* MTL::PointerType::init()
{
return NS::Object::init<MTL::PointerType>();
}
// property: elementType
_MTL_INLINE MTL::DataType MTL::PointerType::elementType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(elementType));
}
// property: access
_MTL_INLINE MTL::BindingAccess MTL::PointerType::access() const
{
return Object::sendMessage<MTL::BindingAccess>(this, _MTL_PRIVATE_SEL(access));
}
// property: alignment
_MTL_INLINE NS::UInteger MTL::PointerType::alignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(alignment));
}
// property: dataSize
_MTL_INLINE NS::UInteger MTL::PointerType::dataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(dataSize));
}
// property: elementIsArgumentBuffer
_MTL_INLINE bool MTL::PointerType::elementIsArgumentBuffer() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(elementIsArgumentBuffer));
}
// method: elementStructType
_MTL_INLINE MTL::StructType* MTL::PointerType::elementStructType()
{
return Object::sendMessage<MTL::StructType*>(this, _MTL_PRIVATE_SEL(elementStructType));
}
// method: elementArrayType
_MTL_INLINE MTL::ArrayType* MTL::PointerType::elementArrayType()
{
return Object::sendMessage<MTL::ArrayType*>(this, _MTL_PRIVATE_SEL(elementArrayType));
}
// static method: alloc
_MTL_INLINE MTL::TextureReferenceType* MTL::TextureReferenceType::alloc()
{
return NS::Object::alloc<MTL::TextureReferenceType>(_MTL_PRIVATE_CLS(MTLTextureReferenceType));
}
// method: init
_MTL_INLINE MTL::TextureReferenceType* MTL::TextureReferenceType::init()
{
return NS::Object::init<MTL::TextureReferenceType>();
}
// property: textureDataType
_MTL_INLINE MTL::DataType MTL::TextureReferenceType::textureDataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(textureDataType));
}
// property: textureType
_MTL_INLINE MTL::TextureType MTL::TextureReferenceType::textureType() const
{
return Object::sendMessage<MTL::TextureType>(this, _MTL_PRIVATE_SEL(textureType));
}
// property: access
_MTL_INLINE MTL::BindingAccess MTL::TextureReferenceType::access() const
{
return Object::sendMessage<MTL::BindingAccess>(this, _MTL_PRIVATE_SEL(access));
}
// property: isDepthTexture
_MTL_INLINE bool MTL::TextureReferenceType::isDepthTexture() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isDepthTexture));
}
// static method: alloc
_MTL_INLINE MTL::Argument* MTL::Argument::alloc()
{
return NS::Object::alloc<MTL::Argument>(_MTL_PRIVATE_CLS(MTLArgument));
}
// method: init
_MTL_INLINE MTL::Argument* MTL::Argument::init()
{
return NS::Object::init<MTL::Argument>();
}
// property: name
_MTL_INLINE NS::String* MTL::Argument::name() const
{
return Object::sendMessage<NS::String*>(this, _MTL_PRIVATE_SEL(name));
}
// property: type
_MTL_INLINE MTL::ArgumentType MTL::Argument::type() const
{
return Object::sendMessage<MTL::ArgumentType>(this, _MTL_PRIVATE_SEL(type));
}
// property: access
_MTL_INLINE MTL::BindingAccess MTL::Argument::access() const
{
return Object::sendMessage<MTL::BindingAccess>(this, _MTL_PRIVATE_SEL(access));
}
// property: index
_MTL_INLINE NS::UInteger MTL::Argument::index() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(index));
}
// property: active
_MTL_INLINE bool MTL::Argument::active() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isActive));
}
// property: bufferAlignment
_MTL_INLINE NS::UInteger MTL::Argument::bufferAlignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(bufferAlignment));
}
// property: bufferDataSize
_MTL_INLINE NS::UInteger MTL::Argument::bufferDataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(bufferDataSize));
}
// property: bufferDataType
_MTL_INLINE MTL::DataType MTL::Argument::bufferDataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(bufferDataType));
}
// property: bufferStructType
_MTL_INLINE MTL::StructType* MTL::Argument::bufferStructType() const
{
return Object::sendMessage<MTL::StructType*>(this, _MTL_PRIVATE_SEL(bufferStructType));
}
// property: bufferPointerType
_MTL_INLINE MTL::PointerType* MTL::Argument::bufferPointerType() const
{
return Object::sendMessage<MTL::PointerType*>(this, _MTL_PRIVATE_SEL(bufferPointerType));
}
// property: threadgroupMemoryAlignment
_MTL_INLINE NS::UInteger MTL::Argument::threadgroupMemoryAlignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(threadgroupMemoryAlignment));
}
// property: threadgroupMemoryDataSize
_MTL_INLINE NS::UInteger MTL::Argument::threadgroupMemoryDataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(threadgroupMemoryDataSize));
}
// property: textureType
_MTL_INLINE MTL::TextureType MTL::Argument::textureType() const
{
return Object::sendMessage<MTL::TextureType>(this, _MTL_PRIVATE_SEL(textureType));
}
// property: textureDataType
_MTL_INLINE MTL::DataType MTL::Argument::textureDataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(textureDataType));
}
// property: isDepthTexture
_MTL_INLINE bool MTL::Argument::isDepthTexture() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isDepthTexture));
}
// property: arrayLength
_MTL_INLINE NS::UInteger MTL::Argument::arrayLength() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(arrayLength));
}
// property: name
_MTL_INLINE NS::String* MTL::Binding::name() const
{
return Object::sendMessage<NS::String*>(this, _MTL_PRIVATE_SEL(name));
}
// property: type
_MTL_INLINE MTL::BindingType MTL::Binding::type() const
{
return Object::sendMessage<MTL::BindingType>(this, _MTL_PRIVATE_SEL(type));
}
// property: access
_MTL_INLINE MTL::BindingAccess MTL::Binding::access() const
{
return Object::sendMessage<MTL::BindingAccess>(this, _MTL_PRIVATE_SEL(access));
}
// property: index
_MTL_INLINE NS::UInteger MTL::Binding::index() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(index));
}
// property: used
_MTL_INLINE bool MTL::Binding::used() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isUsed));
}
// property: argument
_MTL_INLINE bool MTL::Binding::argument() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isArgument));
}
// property: bufferAlignment
_MTL_INLINE NS::UInteger MTL::BufferBinding::bufferAlignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(bufferAlignment));
}
// property: bufferDataSize
_MTL_INLINE NS::UInteger MTL::BufferBinding::bufferDataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(bufferDataSize));
}
// property: bufferDataType
_MTL_INLINE MTL::DataType MTL::BufferBinding::bufferDataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(bufferDataType));
}
// property: bufferStructType
_MTL_INLINE MTL::StructType* MTL::BufferBinding::bufferStructType() const
{
return Object::sendMessage<MTL::StructType*>(this, _MTL_PRIVATE_SEL(bufferStructType));
}
// property: bufferPointerType
_MTL_INLINE MTL::PointerType* MTL::BufferBinding::bufferPointerType() const
{
return Object::sendMessage<MTL::PointerType*>(this, _MTL_PRIVATE_SEL(bufferPointerType));
}
// property: threadgroupMemoryAlignment
_MTL_INLINE NS::UInteger MTL::ThreadgroupBinding::threadgroupMemoryAlignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(threadgroupMemoryAlignment));
}
// property: threadgroupMemoryDataSize
_MTL_INLINE NS::UInteger MTL::ThreadgroupBinding::threadgroupMemoryDataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(threadgroupMemoryDataSize));
}
// property: textureType
_MTL_INLINE MTL::TextureType MTL::TextureBinding::textureType() const
{
return Object::sendMessage<MTL::TextureType>(this, _MTL_PRIVATE_SEL(textureType));
}
// property: textureDataType
_MTL_INLINE MTL::DataType MTL::TextureBinding::textureDataType() const
{
return Object::sendMessage<MTL::DataType>(this, _MTL_PRIVATE_SEL(textureDataType));
}
// property: depthTexture
_MTL_INLINE bool MTL::TextureBinding::depthTexture() const
{
return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(isDepthTexture));
}
// property: arrayLength
_MTL_INLINE NS::UInteger MTL::TextureBinding::arrayLength() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(arrayLength));
}
// property: objectPayloadAlignment
_MTL_INLINE NS::UInteger MTL::ObjectPayloadBinding::objectPayloadAlignment() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(objectPayloadAlignment));
}
// property: objectPayloadDataSize
_MTL_INLINE NS::UInteger MTL::ObjectPayloadBinding::objectPayloadDataSize() const
{
return Object::sendMessage<NS::UInteger>(this, _MTL_PRIVATE_SEL(objectPayloadDataSize));
}

Some files were not shown because too many files have changed in this diff Show more