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(ENABLE_OPENGL "Enable OpenGL 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_TESTS "Compile unit-tests" 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)
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})
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}

View file

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

View file

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

View file

@ -7,6 +7,7 @@
#include <string>
#include <type_traits>
#include <vector>
#include "helpers.hpp"
#include "memory.hpp"
#include "result.hpp"
@ -55,7 +56,7 @@ namespace ArchiveID {
default: return "Unknown archive";
}
}
}
} // namespace ArchiveID
struct FSPath {
u32 type = PathType::Invalid;
@ -68,9 +69,7 @@ struct FSPath {
FSPath(u32 type, const std::vector<u8>& vec) : type(type) {
switch (type) {
case PathType::Binary:
binary = std::move(vec);
break;
case PathType::Binary: binary = std::move(vec); break;
case PathType::ASCII:
string.resize(vec.size() - 1); // -1 because of the null terminator
@ -82,8 +81,8 @@ struct FSPath {
utf16_string.resize(size);
std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16));
break;
};
}
; }
}
};
@ -105,12 +104,12 @@ struct FileSession {
u32 priority = 0; // TODO: What does this even do
bool isOpen;
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) {}
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) {}
// For cloning a file session
FileSession(const FileSession& other) : archive(other.archive), path(other.path),
archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {}
FileSession(const FileSession& other)
: archive(other.archive), path(other.path), archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {}
};
struct ArchiveSession {
@ -156,7 +155,7 @@ struct DirectorySession {
using FileDescriptor = std::optional<FILE*>;
class ArchiveBase {
public:
public:
struct FormatInfo {
u32 size; // Archive size
u32 numOfDirectories; // Number of directories
@ -164,8 +163,8 @@ public:
bool duplicateData; // Whether to duplicate data or not
};
protected:
using Handle = u32;
protected:
using HandleType = u32;
static constexpr FileDescriptor NoFile = nullptr;
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
// 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 access files outside of the emulator's app data folder
// 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 access files outside of the emulator's app data folder
template <u32 format>
bool isPathSafe(const FSPath& path) {
static_assert(format == PathType::ASCII || format == PathType::UTF16);
@ -216,7 +215,7 @@ protected:
return true;
}
public:
public:
virtual std::string name() = 0;
virtual u64 getFreeBytes() = 0;
virtual HorizonResult createFile(const FSPath& path, u64 size) = 0;
@ -225,7 +224,7 @@ public:
virtual Rust::Result<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) {
Helpers::panic("Unimplemented GetFormatInfo for %s archive", name().c_str());
// Return a dummy struct just to avoid the UB of not returning anything, even if we panic
return Ok(FormatInfo{ .size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false });
return Ok(FormatInfo{.size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false});
}
virtual HorizonResult createDirectory(const FSPath& path) {
@ -242,9 +241,7 @@ public:
return Err(Result::FS::FileNotFoundAlt);
}
virtual void format(const FSPath& path, const FormatInfo& info) {
Helpers::panic("Unimplemented Format for %s archive", name().c_str());
}
virtual void format(const FSPath& path, const FormatInfo& info) { Helpers::panic("Unimplemented Format for %s archive", name().c_str()); }
virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) {
Helpers::panic("Unimplemented RenameFile for %s archive", name().c_str());

View file

@ -1,7 +1,7 @@
#pragma once
#include "helpers.hpp"
using Handle = u32;
using HandleType = u32;
namespace KernelHandles {
enum : u32 {
@ -50,7 +50,7 @@ namespace KernelHandles {
MinServiceHandle = AC,
MaxServiceHandle = Y2R,
GSPSharedMemHandle = MaxServiceHandle + 1, // Handle for the GSP shared memory
GSPSharedMemHandle = MaxServiceHandle + 1, // HandleType for the GSP shared memory
FontSharedMemHandle,
CSNDSharedMemHandle,
APTCaptureSharedMemHandle, // Shared memory for display capture info,
@ -61,17 +61,13 @@ namespace KernelHandles {
};
// Returns whether "handle" belongs to one of the OS services
static constexpr bool isServiceHandle(Handle handle) {
return handle >= MinServiceHandle && handle <= MaxServiceHandle;
}
static constexpr bool isServiceHandle(HandleType handle) { return handle >= MinServiceHandle && handle <= MaxServiceHandle; }
// Returns whether "handle" belongs to one of the OS services' shared memory areas
static constexpr bool isSharedMemHandle(Handle handle) {
return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle;
}
static constexpr bool isSharedMemHandle(HandleType handle) { return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle; }
// 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) {
case AC: return "AC";
case ACT: return "ACT";
@ -110,4 +106,4 @@ namespace KernelHandles {
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");
std::vector<KernelObject> objects;
std::vector<Handle> portHandles;
std::vector<Handle> mutexHandles;
std::vector<Handle> timerHandles;
std::vector<HandleType> portHandles;
std::vector<HandleType> mutexHandles;
std::vector<HandleType> timerHandles;
// Thread indices, sorted by priority
std::vector<int> threadIndices;
Handle currentProcess;
Handle mainThread;
HandleType currentProcess;
HandleType mainThread;
int currentThreadIndex;
Handle srvHandle; // Handle for the special service manager port "srv:"
Handle errorPortHandle; // Handle for the err:f port used for displaying errors
HandleType srvHandle; // HandleType for the special service manager port "srv:"
HandleType errorPortHandle; // HandleType for the err:f port used for displaying errors
u32 arbiterCount;
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
bool needReschedule = false;
Handle makeArbiter();
Handle makeProcess(u32 id);
Handle makePort(const char* name);
Handle makeSession(Handle port);
Handle 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 makeArbiter();
HandleType makeProcess(u32 id);
HandleType makePort(const char* name);
HandleType makeSession(HandleType port);
HandleType makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status = ThreadStatus::Dormant);
HandleType makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
public:
public:
// 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
Handle makeMutex(bool locked = false);
HandleType makeMutex(bool locked = false);
// Needs to be public to be accessible to the service manager port
Handle makeSemaphore(u32 initialCount, u32 maximumCount);
Handle makeTimer(ResetType resetType);
HandleType makeSemaphore(u32 initialCount, u32 maximumCount);
HandleType makeTimer(ResetType resetType);
void pollTimers();
// 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
void runEventCallback(Event::CallbackType callback);
void clearEvent(Handle e) {
void clearEvent(HandleType e) {
KernelObject* object = getObject(e, KernelObjectType::Event);
if (object != nullptr) {
object->getData<Event>()->fired = false;
@ -99,19 +99,19 @@ public:
bool shouldWaitOnObject(KernelObject* object);
void releaseMutex(Mutex* moo);
void cancelTimer(Timer* timer);
void signalTimer(Handle timerHandle, Timer* timer);
void signalTimer(HandleType timerHandle, Timer* timer);
u64 getWakeupTick(s64 ns);
// Wake up the thread with the highest priority out of all threads in the waitlist
// Returns the index of the woken up thread
// Do not call this function with an empty waitlist!!!
int wakeupOneThread(u64 waitlist, Handle handle);
void wakeupAllThreads(u64 waitlist, Handle handle);
int wakeupOneThread(u64 waitlist, HandleType 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);
KernelObject* getProcessFromPID(Handle handle);
KernelObject* getProcessFromPID(HandleType handle);
s32 getCurrentResourceValue(const KernelObject* limit, u32 resourceName);
u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
u32 getTLSPointer();
@ -178,22 +178,22 @@ public:
void waitSynchronizationN();
// File operations
void handleFileOperation(u32 messagePointer, Handle file);
void closeFile(u32 messagePointer, Handle file);
void flushFile(u32 messagePointer, Handle file);
void readFile(u32 messagePointer, Handle file);
void writeFile(u32 messagePointer, Handle file);
void getFileSize(u32 messagePointer, Handle file);
void openLinkFile(u32 messagePointer, Handle file);
void setFileSize(u32 messagePointer, Handle file);
void setFilePriority(u32 messagePointer, Handle file);
void handleFileOperation(u32 messagePointer, HandleType file);
void closeFile(u32 messagePointer, HandleType file);
void flushFile(u32 messagePointer, HandleType file);
void readFile(u32 messagePointer, HandleType file);
void writeFile(u32 messagePointer, HandleType file);
void getFileSize(u32 messagePointer, HandleType file);
void openLinkFile(u32 messagePointer, HandleType file);
void setFileSize(u32 messagePointer, HandleType file);
void setFilePriority(u32 messagePointer, HandleType file);
// Directory operations
void handleDirectoryOperation(u32 messagePointer, Handle directory);
void closeDirectory(u32 messagePointer, Handle directory);
void readDirectory(u32 messagePointer, Handle directory);
void handleDirectoryOperation(u32 messagePointer, HandleType directory);
void closeDirectory(u32 messagePointer, HandleType directory);
void readDirectory(u32 messagePointer, HandleType directory);
public:
public:
Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config);
void initializeFS() { return serviceManager.initializeFS(); }
void setVersion(u8 major, u8 minor);
@ -209,7 +209,7 @@ public:
}
}
Handle makeObject(KernelObjectType type) {
HandleType makeObject(KernelObjectType type) {
if (handleCounter > KernelHandles::Max) [[unlikely]] {
Helpers::panic("Hlep we somehow created enough kernel objects to overflow this thing");
}
@ -219,12 +219,10 @@ public:
return handleCounter++;
}
std::vector<KernelObject>& getObjects() {
return objects;
}
std::vector<KernelObject>& getObjects() { return objects; }
// 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
if (handle >= objects.size()) [[unlikely]] {
return nullptr;
@ -234,7 +232,7 @@ public:
}
// 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]] {
return nullptr;
}

View file

@ -1,23 +1,32 @@
#pragma once
#include <array>
#include <cstring>
#include "fs/archive_base.hpp"
#include "handles.hpp"
#include "helpers.hpp"
#include "result/result.hpp"
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
Event, Mutex, Port, Semaphore, Timer, Thread
Event,
Mutex,
Port,
Semaphore,
Timer,
Thread
};
enum class ResourceLimitCategory : int {
Application = 0,
SystemApplet = 1,
LibraryApplet = 2,
Misc = 3
};
enum class ResourceLimitCategory : int { Application = 0, SystemApplet = 1, LibraryApplet = 2, Misc = 3 };
// Reset types (for use with events and timers)
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.
};
enum class ArbitrationType {
Signal = 0,
WaitIfLess = 1,
DecrementAndWaitIfLess = 2,
WaitIfLessTimeout = 3,
DecrementAndWaitIfLessTimeout = 4
};
enum class ArbitrationType { Signal = 0, WaitIfLess = 1, DecrementAndWaitIfLess = 2, WaitIfLessTimeout = 3, DecrementAndWaitIfLessTimeout = 4 };
enum class ProcessorID : s32 {
AllCPUs = -1,
@ -47,7 +50,7 @@ enum class ProcessorID : s32 {
struct AddressArbiter {};
struct ResourceLimits {
Handle handle;
HandleType handle;
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
// This enum stores what kind of callback they should execute
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
@ -91,8 +95,8 @@ struct Port {
};
struct Session {
Handle portHandle; // The port this session is subscribed to
Session(Handle portHandle) : portHandle(portHandle) {}
HandleType portHandle; // The port this session is subscribed to
Session(HandleType portHandle) : portHandle(portHandle) {}
};
enum class ThreadStatus {
@ -115,14 +119,14 @@ struct Thread {
u32 arg;
ProcessorID processorID;
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
// The waiting address for threads that are waiting on an AddressArbiter
u32 waitingAddress;
// 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
bool waitAll;
// For WaitSynchronizationN: The "out" pointer
@ -162,12 +166,12 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
struct Mutex {
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
Handle handle; // Handle of the mutex itself
HandleType ownerThread = 0; // Index of the thread that holds the mutex if it's locked
HandleType handle; // HandleType of the mutex itself
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not 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 {
@ -197,17 +201,17 @@ struct MemoryBlock {
u32 otherPermission = 0;
bool mapped = false;
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm),
mapped(false) {}
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm)
: addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), mapped(false) {}
};
// Generic kernel object class
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;
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
// Thus, the kernel needs to delete it when appropriate
@ -218,9 +222,7 @@ struct KernelObject {
return static_cast<T*>(data);
}
const char* getTypeName() const {
return kernelObjectTypeToString(type);
}
const char* getTypeName() const { return kernelObjectTypeToString(type); }
// 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
@ -238,8 +240,7 @@ struct KernelObject {
case KernelObjectType::Timer: return getData<Timer>()->waitlist;
// This should be unreachable once we fully implement sync objects
default: [[unlikely]]
Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
default: [[unlikely]] 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 "handles.hpp"
#include "helpers.hpp"
#include "loader/ncsd.hpp"
#include "loader/3dsx.hpp"
#include "loader/ncsd.hpp"
#include "services/region_codes.hpp"
namespace PhysicalAddrs {
@ -86,8 +86,7 @@ namespace KernelMemoryTypes {
u32 state;
u32 end() { return baseAddr + size; }
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size)
, perms(perms), state(state) {}
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size), perms(perms), state(state) {}
};
// 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) {}
};
}
} // namespace KernelMemoryTypes
class Memory {
u8* fcram;
@ -116,14 +115,16 @@ class Memory {
std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo;
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::HIDSharedMemHandle), // HID shared memory
SharedMemoryBlock(0, 0x3000, KernelHandles::CSNDSharedMemHandle), // CSND shared memory
SharedMemoryBlock(0, 0xE7000, KernelHandles::APTCaptureSharedMemHandle), // APT Capture Buffer memory
};
public:
public:
static constexpr u32 pageShift = 12;
static constexpr u32 pageSize = 1 << pageShift;
static constexpr u32 pageMask = pageSize - 1;
@ -138,7 +139,7 @@ public:
static constexpr u32 DSP_CODE_MEMORY_OFFSET = u32(0_KB);
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);
private:
private:
std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
std::optional<u32> findPaddr(u32 size);
u64 timeSince3DSEpoch();
@ -197,24 +198,16 @@ private:
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)
u32 totalSysFCRAM() {
return FCRAM_SIZE - FCRAM_APPLICATION_SIZE;
}
u32 totalSysFCRAM() { return FCRAM_SIZE - FCRAM_APPLICATION_SIZE; }
// Amount of OS-only FCRAM currently available
u32 remainingSysFCRAM() {
return totalSysFCRAM() - usedSystemMemory;
}
u32 remainingSysFCRAM() { return totalSysFCRAM() - usedSystemMemory; }
// 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
u32 sysFCRAMIndex() {
return FCRAM_APPLICATION_SIZE;
}
u32 sysFCRAMIndex() { return FCRAM_APPLICATION_SIZE; }
enum class BatteryLevel {
Empty = 0, AlmostEmpty, OneBar, TwoBars, ThreeBars, FourBars
};
enum class BatteryLevel { Empty = 0, AlmostEmpty, OneBar, TwoBars, ThreeBars, FourBars };
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
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
static constexpr bool isAligned(u32 addr) {
return (addr & pageMask) == 0;
}
static constexpr bool isAligned(u32 addr) { return (addr & pageMask) == 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).
@ -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,
// 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
std::optional<u32> allocateMemory(u32 vaddr, u32 paddr, u32 size, bool linear, bool r = true, bool w = true, bool x = true,
bool adjustsAddrs = false, bool isMap = false);
std::optional<u32> allocateMemory(
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);
// For internal use
@ -266,7 +258,7 @@ private:
// The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for
// TODO: Find out
// 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
// All of the above must be page-aligned.

View file

@ -119,9 +119,10 @@ class MainWindow : public QMainWindow {
void sendMessage(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 usingVk = false;
bool usingMtl = false;
// 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

View file

@ -1,7 +1,7 @@
#pragma once
#include <array>
#include <span>
#include <optional>
#include <span>
#include "PICA/pica_vertex.hpp"
#include "PICA/regs.hpp"
@ -17,6 +17,7 @@ enum class RendererType : s8 {
OpenGL = 1,
Vulkan = 2,
Software = 3,
Metal = 4,
};
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"
class ACService {
Handle handle = KernelHandles::AC;
HandleType handle = KernelHandles::AC;
Memory& mem;
MAKE_LOG_FUNCTION(log, acLogger)
@ -25,7 +25,7 @@ class ACService {
void setClientVersion(u32 messagePointer);
bool connected = false;
std::optional<Handle> disconnectEvent = std::nullopt;
std::optional<HandleType> disconnectEvent = std::nullopt;
public:
ACService(Memory& mem) : mem(mem) {}

View file

@ -6,7 +6,7 @@
#include "result/result.hpp"
class ACTService {
Handle handle = KernelHandles::ACT;
HandleType handle = KernelHandles::ACT;
Memory& mem;
MAKE_LOG_FUNCTION(log, actLogger)
@ -15,7 +15,7 @@ class ACTService {
void generateUUID(u32 messagePointer);
void getAccountDataBlock(u32 messagePointer);
public:
public:
ACTService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

@ -6,7 +6,7 @@
#include "result/result.hpp"
class AMService {
Handle handle = KernelHandles::AM;
HandleType handle = KernelHandles::AM;
Memory& mem;
MAKE_LOG_FUNCTION(log, amLogger)
@ -15,7 +15,7 @@ class AMService {
void getPatchTitleInfo(u32 messagePointer);
void listTitleInfo(u32 messagePointer);
public:
public:
AMService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,14 +8,14 @@
// Please forgive me for how everything in this file is named
// "dlp:SRVR" is not a nice name to work with
class DlpSrvrService {
Handle handle = KernelHandles::DLP_SRVR;
HandleType handle = KernelHandles::DLP_SRVR;
Memory& mem;
MAKE_LOG_FUNCTION(log, dlpSrvrLogger)
// Service commands
void isChild(u32 messagePointer);
public:
public:
DlpSrvrService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

@ -16,7 +16,7 @@
class Kernel;
class FSService {
Handle handle = KernelHandles::FS;
HandleType handle = KernelHandles::FS;
Memory& mem;
Kernel& kernel;
@ -38,9 +38,9 @@ class FSService {
SystemSaveDataArchive systemSaveData;
ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath);
Rust::Result<Handle, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
Rust::Result<Handle, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
Rust::Result<HandleType, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
Rust::Result<HandleType, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
std::optional<HandleType> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
FSPath readPath(u32 type, u32 pointer, u32 size);
const EmulatorConfig& config;
@ -81,7 +81,7 @@ class FSService {
// Used for set/get priority: Not sure what sort of priority this is referring to
u32 priority;
public:
public:
FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config)
: mem(mem), saveData(mem), sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem),
sdmcWriteOnly(mem, true), selfNcch(mem), ncch(mem), userSaveData1(mem, ArchiveID::UserSaveData1),

View file

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

View file

@ -6,13 +6,13 @@
#include "result/result.hpp"
class LCDService {
Handle handle = KernelHandles::LCD;
HandleType handle = KernelHandles::LCD;
Memory& mem;
MAKE_LOG_FUNCTION(log, gspLCDLogger)
// Service commands
public:
public:
LCDService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

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

View file

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

View file

@ -8,7 +8,7 @@
class Kernel;
class LDRService {
Handle handle = KernelHandles::LDR_RO;
HandleType handle = KernelHandles::LDR_RO;
Memory& mem;
Kernel& kernel;
MAKE_LOG_FUNCTION(log, ldrLogger)
@ -22,7 +22,7 @@ class LDRService {
void loadCRR(u32 messagePointer);
void unloadCRO(u32 messagePointer);
public:
public:
LDRService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@
class Kernel;
class NFCService {
Handle handle = KernelHandles::NFC;
HandleType handle = KernelHandles::NFC;
Memory& mem;
Kernel& kernel;
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
std::optional<Handle> tagInRangeEvent, tagOutOfRangeEvent;
std::optional<HandleType> tagInRangeEvent, tagOutOfRangeEvent;
AmiiboDevice device;
Old3DSAdapterStatus adapterStatus;

View file

@ -6,14 +6,14 @@
#include "result/result.hpp"
class NIMService {
Handle handle = KernelHandles::NIM;
HandleType handle = KernelHandles::NIM;
Memory& mem;
MAKE_LOG_FUNCTION(log, nimLogger)
// Service commands
void initialize(u32 messagePointer);
public:
public:
NIMService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

@ -28,10 +28,10 @@
#include "services/mcu/mcu_hwc.hpp"
#include "services/mic.hpp"
#include "services/ndm.hpp"
#include "services/nwm_uds.hpp"
#include "services/news_u.hpp"
#include "services/nfc.hpp"
#include "services/nim.hpp"
#include "services/nwm_uds.hpp"
#include "services/ptm.hpp"
#include "services/soc.hpp"
#include "services/ssl.hpp"
@ -46,7 +46,7 @@ class ServiceManager {
Memory& mem;
Kernel& kernel;
std::optional<Handle> notificationSemaphore;
std::optional<HandleType> notificationSemaphore;
MAKE_LOG_FUNCTION(log, srvLogger)
@ -97,7 +97,7 @@ class ServiceManager {
void handleSyncRequest(u32 messagePointer);
// 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
void sendGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); }

View file

@ -5,7 +5,7 @@
#include "memory.hpp"
class SOCService {
Handle handle = KernelHandles::SOC;
HandleType handle = KernelHandles::SOC;
Memory& mem;
MAKE_LOG_FUNCTION(log, socLogger)
@ -14,7 +14,7 @@ class SOCService {
// Service commands
void initializeSockets(u32 messagePointer);
public:
public:
SOCService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

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

View file

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

View file

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

View file

@ -1,12 +1,13 @@
#if defined(PANDA3DS_DYNAPICA_SUPPORTED) && defined(PANDA3DS_X64_HOST)
#include "PICA/dynapica/shader_rec_emitter_x64.hpp"
#include <immintrin.h>
#include <smmintrin.h>
#include <algorithm>
#include <bit>
#include <cassert>
#include <cstddef>
#include <immintrin.h>
#include <smmintrin.h>
using namespace Xbyak;
using namespace Xbyak::util;
@ -41,9 +42,15 @@ void ShaderEmitter::compile(const PICAShader& shaderUnit) {
// Constants
align(16);
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);
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
align(16);
@ -129,23 +136,15 @@ void ShaderEmitter::compileInstruction(const PICAShader& shaderUnit) {
switch (opcode) {
case ShaderOpcodes::ADD: recADD(shaderUnit, instruction); break;
case ShaderOpcodes::CALL:
recCALL(shaderUnit, instruction);
break;
case ShaderOpcodes::CALLC:
recCALLC(shaderUnit, instruction);
break;
case ShaderOpcodes::CALLU:
recCALLU(shaderUnit, instruction);
break;
case ShaderOpcodes::CMP1: case ShaderOpcodes::CMP2:
recCMP(shaderUnit, instruction);
break;
case ShaderOpcodes::CALL: recCALL(shaderUnit, instruction); break;
case ShaderOpcodes::CALLC: recCALLC(shaderUnit, instruction); 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::DP4: recDP4(shaderUnit, instruction); break;
case ShaderOpcodes::DPH:
case ShaderOpcodes::DPHI:
recDPH(shaderUnit, instruction); break;
case ShaderOpcodes::DPHI: recDPH(shaderUnit, instruction); break;
case ShaderOpcodes::END: recEND(shaderUnit, instruction); break;
case ShaderOpcodes::EX2: recEX2(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;
// 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 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F:
recMAD(shaderUnit, instruction);
break;
case 0x30:
case 0x31:
case 0x32:
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::SLTI:
recSLT(shaderUnit, instruction); break;
case ShaderOpcodes::SLTI: recSLT(shaderUnit, instruction); break;
case ShaderOpcodes::SGE:
case ShaderOpcodes::SGEI:
recSGE(shaderUnit, instruction); break;
case ShaderOpcodes::SGEI: recSGE(shaderUnit, instruction); break;
default:
Helpers::panic("Shader JIT: Unimplemented PICA opcode %X", opcode);
default: 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
negate = (getBit<4>(operandDescriptor)) != 0;
compSwizzle = getBits<5, 8>(operandDescriptor);
}
else if constexpr (sourceIndex == 2) { // SRC2
} else if constexpr (sourceIndex == 2) { // SRC2
negate = (getBit<13>(operandDescriptor)) != 0;
compSwizzle = getBits<14, 8>(operandDescriptor);
}
else if constexpr (sourceIndex == 3) { // SRC3
} else if constexpr (sourceIndex == 3) { // SRC3
negate = (getBit<22>(operandDescriptor)) != 0;
compSwizzle = getBits<23, 8>(operandDescriptor);
}
// 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
u32 convertedSwizzle = ((compSwizzle >> 6) & 0b11) | (((compSwizzle >> 4) & 0b11) << 2) | (((compSwizzle >> 2) & 0b11) << 4) | ((compSwizzle & 0b11) << 6);
// 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
u32 convertedSwizzle =
((compSwizzle >> 6) & 0b11) | (((compSwizzle >> 4) & 0b11) << 2) | (((compSwizzle >> 2) & 0b11) << 4) | ((compSwizzle & 0b11) << 6);
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 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;
}
default:
Helpers::panic("[ShaderJIT]: Unimplemented source index type %d", index);
default: 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
@ -368,13 +376,12 @@ void ShaderEmitter::storeRegister(Xmm source, const PICAShader& shader, u32 dest
movaps(xword[statePointer + offset], temp); // Write back
} else {
// Blend algo referenced from Citra
const u8 selector = (((writeMask & 0b1000) ? 1 : 0) << 0) |
(((writeMask & 0b0100) ? 3 : 2) << 2) |
(((writeMask & 0b0010) ? 0 : 1) << 4) |
const u8 selector = (((writeMask & 0b1000) ? 1 : 0) << 0) | (((writeMask & 0b0100) ? 3 : 2) << 2) | (((writeMask & 0b0010) ? 0 : 1) << 4) |
(((writeMask & 0b0001) ? 2 : 3) << 6);
// 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) {
movaps(scratch1, xword[statePointer + offset]);
movaps(scratch2, source);
@ -399,7 +406,8 @@ void ShaderEmitter::checkCmpRegister(const PICAShader& shader, u32 instruction)
const uint refY = getBit<24>(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);
switch (condition) {
@ -491,12 +499,10 @@ void ShaderEmitter::recMOVA(const PICAShader& shader, u32 instruction) {
if (writeX && writeY) {
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
}
else if (writeX) {
} else if (writeX) {
cvttss2si(eax, src1_xmm); // Convert bottom lane
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
cvttss2si(eax, src1_xmm); // Convert bottom lane
mov(dword[statePointer + addrRegisterYOffset], eax); // Write it back to y component
@ -622,7 +628,7 @@ void ShaderEmitter::recRCP(const PICAShader& shader, u32 instruction) {
// If we only write back the x component to the result, we needn't perform a shuffle to do res = res.xxxx
// Otherwise we do
if (writeMask != 0x8) {// Copy bottom lane to all lanes if we're not simply writing back x
if (writeMask != 0x8) { // Copy bottom lane to all lanes if we're not simply writing back x
shufps(src1_xmm, src1_xmm, 0); // src1_xmm = src1_xmm.xxxx
}
@ -641,7 +647,7 @@ void ShaderEmitter::recRSQ(const PICAShader& shader, u32 instruction) {
// If we only write back the x component to the result, we needn't perform a shuffle to do res = res.xxxx
// Otherwise we do
if (writeMask != 0x8) {// Copy bottom lane to all lanes if we're not simply writing back x
if (writeMask != 0x8) { // Copy bottom lane to all lanes if we're not simply writing back x
shufps(src1_xmm, src1_xmm, 0); // src1_xmm = src1_xmm.xxxx
}
@ -731,20 +737,10 @@ void ShaderEmitter::recCMP(const PICAShader& shader, u32 instruction) {
loadRegister<2>(src2_xmm, shader, src2, 0, operandDescriptor);
// Condition codes for cmpps
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
};
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 };
// 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};
// SSE does not offer GT or GE comparisons in the cmpps instruction, so we need to flip the left and right operands in that case and use LT/LE
const bool invertX = (cmpX == 4 || cmpX == 5);
@ -1147,7 +1143,7 @@ Xbyak::Label ShaderEmitter::emitExp2Func() {
align(16);
L(subroutine);
// Handle edge cases
// HandleType edge cases
ucomiss(src1_xmm, src1_xmm);
jp(retLabel);

View file

@ -15,6 +15,9 @@
#ifdef PANDA3DS_ENABLE_VULKAN
#include "renderer_vk/renderer_vk.hpp"
#endif
#ifdef PANDA3DS_ENABLE_METAL
#include "renderer_mtl/renderer_mtl.hpp"
#endif
constexpr u32 topScreenWidth = 240;
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));
break;
}
#endif
#ifdef PANDA3DS_ENABLE_METAL
case RendererType::Metal: {
renderer.reset(new RendererMTL(*this, regs, externalRegs));
break;
}
#endif
default: {
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);
// 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) {
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);
}
// Handle control flow statements. The ordering is important as the priority goes: LOOP > IF > CALL
// Handle loop
// HandleType control flow statements. The ordering is important as the priority goes: LOOP > IF > CALL
// HandleType loop
if (loopIndex != 0) {
auto& loop = loopInfo[loopIndex - 1];
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) {
auto& info = conditionalInfo[ifIndex - 1];
if (pc == info.endingPC) { // Check if the IF block ended
@ -100,7 +100,7 @@ void PICAShader::run() {
}
}
// Handle calls
// HandleType calls
if (callIndex != 0) {
auto& info = callInfo[callIndex - 1];
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) {
Helpers::panic("Overflowed the number of address arbiters");
}
arbiterCount++;
Handle ret = makeObject(KernelObjectType::AddressArbiter);
HandleType ret = makeObject(KernelObjectType::AddressArbiter);
objects[ret].data = new AddressArbiter();
return ret;
}
// Result CreateAddressArbiter(Handle* arbiter)
// Result CreateAddressArbiter(HandleType* arbiter)
void Kernel::createAddressArbiter() {
logSVC("CreateAddressArbiter\n");
regs[0] = Result::Success;
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() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
const u32 address = regs[1];
const u32 type = regs[2];
const s32 value = s32(regs[3]);
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,
arbitrationTypeToString(type), value, ns);
logSVC(
"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);
if (arbiter == nullptr) [[unlikely]] {
@ -79,12 +81,9 @@ void Kernel::arbitrateAddress() {
break;
}
case ArbitrationType::Signal:
signalArbiter(address, value);
break;
case ArbitrationType::Signal: signalArbiter(address, value); break;
default:
Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
default: Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
}
requireReschedule();
@ -92,7 +91,8 @@ void Kernel::arbitrateAddress() {
// Signal up to "threadCount" threads waiting on the arbiter indicated by "waitingAddress"
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
// Wake threads with the highest priority threads being woken up first

View file

@ -8,10 +8,7 @@
#include "kernel.hpp"
namespace DirectoryOps {
enum : u32 {
Read = 0x08010042,
Close = 0x08020000
};
enum : u32 { Read = 0x08010042, Close = 0x08020000 };
}
// Helper to convert std::string to an 8.3 filename to mimic how Directory::Read works
@ -28,7 +25,7 @@ Filename83 convertTo83(const std::string& path) {
// Convert a character to add it to the 8.3 name
// "Characters such as + are changed to the underscore _, and letters are put in uppercase"
// For now we put letters in uppercase until we find out what is supposed to be converted to _ and so on
auto convertCharacter = [](char c) { return (char) std::toupper(c); };
auto convertCharacter = [](char c) { return (char)std::toupper(c); };
// List of forbidden character for 8.3 filenames, from Citra
// TODO: Use constexpr when C++20 support is solid
@ -87,7 +84,7 @@ Filename83 convertTo83(const std::string& path) {
return {filename, extension};
}
void Kernel::handleDirectoryOperation(u32 messagePointer, Handle directory) {
void Kernel::handleDirectoryOperation(u32 messagePointer, HandleType directory) {
const u32 cmd = mem.read32(messagePointer);
switch (cmd) {
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);
const auto p = getObject(directory, KernelObjectType::Directory);
@ -109,7 +106,7 @@ void Kernel::closeDirectory(u32 messagePointer, Handle directory) {
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 outPointer = mem.read32(messagePointer + 12);
logFileIO("Directory::Read (handle = %X, entry count = %d, out pointer = %08X)\n", directory, entryCount, outPointer);

View file

@ -1,33 +1,20 @@
#include "kernel.hpp"
namespace Commands {
enum : u32 {
Throw = 0x00010800
};
enum : u32 { Throw = 0x00010800 };
}
namespace FatalErrorType {
enum : u32 {
Generic = 0,
Corrupted = 1,
CardRemoved = 2,
Exception = 3,
ResultFailure = 4,
Logged = 5
};
enum : u32 { 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) {
u32 cmd = mem.read32(messagePointer);
switch (cmd) {
case Commands::Throw:
throwError(messagePointer);
break;
case Commands::Throw: throwError(messagePointer); break;
default:
Helpers::panic("Unimplemented err:f command %08X\n", cmd);
break;
default: 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 <utility>
#include "cpu.hpp"
#include "kernel.hpp"
const char* Kernel::resetTypeToString(u32 type) {
switch (type) {
case 0: return "One shot";
@ -12,13 +13,13 @@ const char* Kernel::resetTypeToString(u32 type) {
}
}
Handle Kernel::makeEvent(ResetType resetType, Event::CallbackType callback) {
Handle ret = makeObject(KernelObjectType::Event);
HandleType Kernel::makeEvent(ResetType resetType, Event::CallbackType callback) {
HandleType ret = makeObject(KernelObjectType::Event);
objects[ret].data = new Event(resetType, callback);
return ret;
}
bool Kernel::signalEvent(Handle handle) {
bool Kernel::signalEvent(HandleType handle) {
KernelObject* object = getObject(handle, KernelObjectType::Event);
if (object == nullptr) [[unlikely]] {
Helpers::panic("Tried to signal non-existent event");
@ -52,13 +53,12 @@ bool Kernel::signalEvent(Handle handle) {
return true;
}
// Result CreateEvent(Handle* event, ResetType resetType)
// Result CreateEvent(HandleType* event, ResetType resetType)
void Kernel::svcCreateEvent() {
const u32 outPointer = regs[0];
const u32 resetType = regs[1];
if (resetType > 2)
Helpers::panic("Invalid reset type for event %d", resetType);
if (resetType > 2) Helpers::panic("Invalid reset type for event %d", 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));
}
// Result ClearEvent(Handle event)
// Result ClearEvent(HandleType event)
void Kernel::svcClearEvent() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
const auto event = getObject(handle, KernelObjectType::Event);
logSVC("ClearEvent(event handle = %X)\n", handle);
@ -82,9 +82,9 @@ void Kernel::svcClearEvent() {
regs[0] = Result::Success;
}
// Result SignalEvent(Handle event)
// Result SignalEvent(HandleType event)
void Kernel::svcSignalEvent() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
logSVC("SignalEvent(event handle = %X)\n", handle);
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() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
const s64 ns = s64(u64(regs[2]) | (u64(regs[3]) << 32));
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() {
// TODO: Are these arguments even correct?
s32 ns1 = regs[0];
@ -154,8 +154,7 @@ void Kernel::waitSynchronizationN() {
logSVC("WaitSynchronizationN (handle pointer: %08X, count: %d, timeout = %lld)\n", handles, handleCount, ns);
if (handleCount <= 0)
Helpers::panic("WaitSyncN: Invalid handle count");
if (handleCount <= 0) Helpers::panic("WaitSyncN: Invalid handle count");
// 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
@ -165,7 +164,7 @@ void Kernel::waitSynchronizationN() {
return;
}
using WaitObject = std::pair<Handle, KernelObject*>;
using WaitObject = std::pair<HandleType, KernelObject*>;
std::vector<WaitObject> waitObjects(handleCount);
// 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;
for (s32 i = 0; i < handleCount; i++) {
Handle handle = mem.read32(handles);
handles += sizeof(Handle);
HandleType handle = mem.read32(handles);
handles += sizeof(HandleType);
auto object = getObject(handle);
// 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
if (!isWaitable(object)) [[unlikely]] {
Helpers::panic("Tried to wait on a non waitable object in WaitSyncN. Type: %s, handle: %X\n",
object->getTypeName(), handle);
Helpers::panic("Tried to wait on a non waitable object in WaitSyncN. Type: %s, handle: %X\n", object->getTypeName(), handle);
}
if (shouldWaitOnObject(object)) {

View file

@ -14,8 +14,7 @@ namespace FileOps {
};
}
void Kernel::handleFileOperation(u32 messagePointer, Handle file) {
void Kernel::handleFileOperation(u32 messagePointer, HandleType file) {
const u32 cmd = mem.read32(messagePointer);
switch (cmd) {
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);
const auto p = getObject(fileHandle, KernelObjectType::File);
@ -48,7 +47,7 @@ void Kernel::closeFile(u32 messagePointer, Handle fileHandle) {
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);
const auto p = getObject(fileHandle, KernelObjectType::File);
@ -65,13 +64,12 @@ void Kernel::flushFile(u32 messagePointer, Handle fileHandle) {
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);
u32 size = mem.read32(messagePointer + 12);
u32 dataPointer = mem.read32(messagePointer + 20);
logFileIO("Trying to read %X bytes from file %X, starting from offset %llX into memory address %08X\n",
size, fileHandle, offset, dataPointer);
logFileIO("Trying to read %X bytes from file %X, starting from offset %llX into memory address %08X\n", size, fileHandle, offset, dataPointer);
const auto p = getObject(fileHandle, KernelObjectType::File);
if (p == nullptr) [[unlikely]] {
@ -85,7 +83,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
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) {
std::unique_ptr<u8[]> data(new u8[size]);
IOFile f(file->fd);
@ -94,8 +92,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
if (!success) {
Helpers::panic("Kernel::ReadFile with file descriptor failed");
}
else {
} else {
for (size_t i = 0; i < bytesRead; i++) {
mem.write8(u32(dataPointer + i), data[i]);
}
@ -107,7 +104,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
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;
std::optional<u32> bytesRead = archive->readFile(file, offset, size, dataPointer);
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);
u32 size = mem.read32(messagePointer + 12);
u32 writeOption = mem.read32(messagePointer + 16);
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",
size, fileHandle, offset, dataPointer);
logFileIO("Trying to write %X bytes to file %X, starting from file offset %llX and memory address %08X\n", size, fileHandle, offset, dataPointer);
const auto p = getObject(fileHandle, KernelObjectType::File);
if (p == nullptr) [[unlikely]] {
@ -137,8 +133,7 @@ void Kernel::writeFile(u32 messagePointer, Handle fileHandle) {
Helpers::panic("Tried to write closed file");
}
if (!file->fd)
Helpers::panic("[Kernel::File::WriteFile] Tried to write to file without a valid file descriptor");
if (!file->fd) Helpers::panic("[Kernel::File::WriteFile] Tried to write to file without a valid file descriptor");
std::unique_ptr<u8[]> data(new u8[size]);
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);
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);
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);
const auto p = getObject(fileHandle, KernelObjectType::File);
@ -247,7 +242,7 @@ void Kernel::openLinkFile(u32 messagePointer, Handle fileHandle) {
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);
logFileIO("Setting priority of file %X to %d\n", fileHandle, priority);

View file

@ -1,7 +1,9 @@
#include <cassert>
#include "kernel.hpp"
#include "kernel_types.hpp"
#include <cassert>
#include "cpu.hpp"
#include "kernel_types.hpp"
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) {
@ -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
}
Handle Kernel::makeProcess(u32 id) {
const Handle processHandle = makeObject(KernelObjectType::Process);
const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
HandleType Kernel::makeProcess(u32 id) {
const HandleType processHandle = makeObject(KernelObjectType::Process);
const HandleType resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
// Allocate data
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
// 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]] {
return getObject(currentProcess, KernelObjectType::Process);
} else {
@ -174,14 +176,12 @@ void Kernel::reset() {
}
// Get pointer to thread-local storage
u32 Kernel::getTLSPointer() {
return VirtualAddrs::TLSBase + currentThreadIndex * VirtualAddrs::TLSSize;
}
u32 Kernel::getTLSPointer() { return VirtualAddrs::TLSBase + currentThreadIndex * VirtualAddrs::TLSSize; }
// Result CloseHandle(Handle handle)
// Result CloseHandle(HandleType handle)
void Kernel::svcCloseHandle() {
logSVC("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]);
const Handle handle = regs[0];
const HandleType handle = regs[0];
KernelObject* object = getObject(handle);
if (object != nullptr) {
@ -242,7 +242,7 @@ void Kernel::getProcessID() {
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() {
const auto pid = regs[1];
const auto type = regs[2];
@ -274,21 +274,20 @@ void Kernel::getProcessInfo() {
regs[2] = 0;
break;
default:
Helpers::panic("GetProcessInfo: unimplemented type %d", type);
default: Helpers::panic("GetProcessInfo: unimplemented type %d", type);
}
regs[0] = Result::Success;
}
// Result DuplicateHandle(Handle* out, Handle original)
// Result DuplicateHandle(HandleType* out, HandleType original)
void Kernel::duplicateHandle() {
Handle original = regs[1];
HandleType original = regs[1];
logSVC("DuplicateHandle(handle = %X)\n", original);
if (original == KernelHandles::CurrentThread) {
regs[0] = Result::Success;
Handle ret = makeObject(KernelObjectType::Thread);
HandleType ret = makeObject(KernelObjectType::Thread);
objects[ret].data = &threads[currentThreadIndex];
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)
static constexpr bool isAligned(u32 value) {
return (value & 0xFFF) == 0;
}
static constexpr bool isAligned(u32 value) { return (value & 0xFFF) == 0; }
// Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size,
// MemoryOperation operation, MemoryPermission permissions)
@ -57,33 +55,33 @@ void Kernel::controlMemory() {
bool x = perms & 0b100;
bool linear = operation & Operation::Linear;
if (x)
Helpers::panic("ControlMemory: attempted to allocate executable memory");
if (x) Helpers::panic("ControlMemory: attempted to allocate executable memory");
if (!isAligned(addr0) || !isAligned(addr1) || !isAligned(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",
addr0, addr1, size, operation, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', linear ? ", linear" : ""
logSVC(
"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) {
case Operation::Commit: {
std::optional<u32> address = mem.allocateMemory(addr0, 0, size, linear, r, w, x, true);
if (!address.has_value())
Helpers::panic("ControlMemory: Failed to allocate memory");
if (!address.has_value()) Helpers::panic("ControlMemory: Failed to allocate memory");
regs[1] = address.value();
break;
}
case Operation::Map:
mem.mirrorMapping(addr0, addr1, size);
break;
case Operation::Map: mem.mirrorMapping(addr0, addr1, size); break;
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;
default: Helpers::warn("ControlMemory: unknown operation %X\n", operation); break;
@ -109,9 +107,9 @@ void Kernel::queryMemory() {
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() {
const Handle block = regs[0];
const HandleType block = regs[0];
u32 addr = regs[1];
const u32 myPerms = regs[2];
const u32 otherPerms = regs[3];
@ -127,17 +125,11 @@ void Kernel::mapMemoryBlock() {
// Pass pointer to shared memory to the appropriate service
switch (block) {
case KernelHandles::HIDSharedMemHandle:
serviceManager.setHIDSharedMem(ptr);
break;
case KernelHandles::HIDSharedMemHandle: serviceManager.setHIDSharedMem(ptr); break;
case KernelHandles::GSPSharedMemHandle:
serviceManager.setGSPSharedMem(ptr);
break;
case KernelHandles::GSPSharedMemHandle: serviceManager.setGSPSharedMem(ptr); break;
case KernelHandles::FontSharedMemHandle:
mem.copySharedFont(ptr);
break;
case KernelHandles::FontSharedMemHandle: mem.copySharedFont(ptr); break;
case KernelHandles::CSNDSharedMemHandle:
serviceManager.setCSNDSharedMem(ptr);
@ -154,8 +146,8 @@ void Kernel::mapMemoryBlock() {
regs[0] = Result::Success;
}
Handle Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
Handle ret = makeObject(KernelObjectType::MemoryBlock);
HandleType Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
HandleType ret = makeObject(KernelObjectType::MemoryBlock);
objects[ret].data = new MemoryBlock(addr, size, myPermission, otherPermission);
return ret;
@ -175,8 +167,7 @@ void Kernel::createMemoryBlock() {
case MemoryPermissions::Read:
case MemoryPermissions::Write:
case MemoryPermissions::ReadWrite:
case MemoryPermissions::DontCare:
return true;
case MemoryPermissions::DontCare: return true;
default: // Permissions with the executable flag enabled or invalid permissions are not allowed
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
if (addr == 0)
Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
if (addr == 0) Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
// Implement "Don't care" permission as RW
if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite;
@ -209,7 +199,7 @@ void Kernel::createMemoryBlock() {
}
void Kernel::unmapMemoryBlock() {
Handle block = regs[0];
HandleType block = regs[0];
u32 addr = regs[1];
logSVC("Unmap memory block (block handle = %X, addr = %08X)\n", block, addr);

View file

@ -1,29 +1,30 @@
#include "kernel.hpp"
#include <cstring>
Handle Kernel::makePort(const char* name) {
Handle ret = makeObject(KernelObjectType::Port);
#include "kernel.hpp"
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
objects[ret].data = new Port(name);
return ret;
}
Handle Kernel::makeSession(Handle portHandle) {
HandleType Kernel::makeSession(HandleType portHandle) {
const auto port = getObject(portHandle, KernelObjectType::Port);
if (port == nullptr) [[unlikely]] {
Helpers::panic("Trying to make session for non-existent port");
}
// Allocate data for session
const Handle ret = makeObject(KernelObjectType::Session);
const HandleType ret = makeObject(KernelObjectType::Session);
objects[ret].data = new Session(portHandle);
return ret;
}
// Get the handle of a port based on its name
// 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) {
const auto data = objects[handle].getData<Port>();
if (std::strncmp(name, data->name, Port::maxNameLen) == 0) {
@ -34,7 +35,7 @@ std::optional<Handle> Kernel::getPortHandle(const char* name) {
return std::nullopt;
}
// Result ConnectToPort(Handle* out, const char* portName)
// Result ConnectToPort(HandleType* out, const char* portName)
void Kernel::connectToPort() {
const u32 handlePointer = regs[0];
// 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
std::optional<Handle> optionalHandle = getPortHandle(port.c_str());
std::optional<HandleType> optionalHandle = getPortHandle(port.c_str());
if (!optionalHandle.has_value()) [[unlikely]] {
Helpers::panic("ConnectToPort: Port doesn't exist\n");
regs[0] = Result::Kernel::NotFound;
return;
}
Handle portHandle = optionalHandle.value();
HandleType portHandle = optionalHandle.value();
const auto portData = objects[portHandle].getData<Port>();
if (!portData->isPublic) {
@ -63,13 +64,13 @@ void Kernel::connectToPort() {
}
// TODO: Actually create session
Handle sessionHandle = makeSession(portHandle);
HandleType sessionHandle = makeSession(portHandle);
regs[0] = Result::Success;
regs[1] = sessionHandle;
}
// Result SendSyncRequest(Handle session)
// Result SendSyncRequest(HandleType session)
// Send an IPC message to a port (typically "srv:") or a service
void Kernel::sendSyncRequest() {
const auto handle = regs[0];
@ -115,7 +116,7 @@ void Kernel::sendSyncRequest() {
}
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"
regs[0] = Result::Success;

View file

@ -1,7 +1,8 @@
#include "resource_limits.hpp"
#include "kernel.hpp"
// Result GetResourceLimit(Handle* resourceLimit, Handle process)
// Result GetResourceLimit(HandleType* resourceLimit, HandleType process)
// out: r0 -> result, r1 -> handle
void Kernel::getResourceLimit() {
const auto handlePointer = regs[0];
@ -20,10 +21,10 @@ void Kernel::getResourceLimit() {
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() {
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 count = regs[3]; // Number of resources
@ -49,10 +50,10 @@ void Kernel::getResourceLimitLimitValues() {
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() {
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 count = regs[3]; // Number of resources
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
void Kernel::sortThreads() {
std::vector<int>& v = threadIndices;
std::sort(v.begin(), v.end(), [&](int a, int b) {
return threads[a].priority < threads[b].priority;
});
std::sort(v.begin(), v.end(), [&](int a, int b) { return threads[a].priority < threads[b].priority; });
}
bool Kernel::canThreadRun(const Thread& t) {
if (t.status == ThreadStatus::Ready) {
return true;
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1
|| t.status == ThreadStatus::WaitSyncAny || t.status == ThreadStatus::WaitSyncAll) {
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1 || t.status == ThreadStatus::WaitSyncAny ||
t.status == ThreadStatus::WaitSyncAll) {
// TODO: Set r0 to the correct error code on timeout for WaitSync{1/Any/All}
return cpu.getTicks() >= t.wakeupTick;
}
// Handle timeouts and stuff here
// HandleType timeouts and stuff here
return false;
}
@ -109,7 +107,7 @@ void Kernel::rescheduleThreads() {
}
// 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
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);
Thread& t = threads[index]; // Reference to thread data
Handle ret = makeObject(KernelObjectType::Thread);
HandleType ret = makeObject(KernelObjectType::Thread);
objects[ret].data = &t;
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;
}
Handle Kernel::makeMutex(bool locked) {
Handle ret = makeObject(KernelObjectType::Mutex);
HandleType Kernel::makeMutex(bool locked) {
HandleType ret = makeObject(KernelObjectType::Mutex);
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
@ -201,8 +199,8 @@ void Kernel::releaseMutex(Mutex* moo) {
}
}
Handle Kernel::makeSemaphore(u32 initialCount, u32 maximumCount) {
Handle ret = makeObject(KernelObjectType::Semaphore);
HandleType Kernel::makeSemaphore(u32 initialCount, u32 maximumCount) {
HandleType ret = makeObject(KernelObjectType::Semaphore);
objects[ret].data = new Semaphore(initialCount, maximumCount);
return ret;
@ -252,8 +250,7 @@ void Kernel::acquireSyncObject(KernelObject* object, const Thread& thread) {
break;
}
case KernelObjectType::Thread:
break;
case KernelObjectType::Thread: break;
case KernelObjectType::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
// 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]]
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;
case ThreadStatus::WaitSyncAll:
Helpers::panic("WakeupOneThread: Thread on WaitSyncAll");
break;
case ThreadStatus::WaitSyncAll: Helpers::panic("WakeupOneThread: Thread on WaitSyncAll"); break;
}
return threadIndex;
}
// 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) {
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
@ -344,9 +339,7 @@ void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) {
}
break;
case ThreadStatus::WaitSyncAll:
Helpers::panic("WakeupAllThreads: Thread on WaitSyncAll");
break;
case ThreadStatus::WaitSyncAll: 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
s32 id = static_cast<s32>(regs[4]);
logSVC("CreateThread(entry = %08X, stacktop = %08X, arg = %X, priority = %X, processor ID = %d)\n", entrypoint,
initialSP, arg, priority, id);
logSVC("CreateThread(entry = %08X, stacktop = %08X, arg = %X, priority = %X, processor ID = %d)\n", entrypoint, initialSP, arg, priority, id);
if (priority > 0x3F) [[unlikely]] {
Helpers::panic("Created thread with bad priority value %X", priority);
@ -429,14 +421,14 @@ void Kernel::createThread() {
// void SleepThread(s64 nanoseconds)
void Kernel::svcSleepThread() {
const s64 ns = s64(u64(regs[0]) | (u64(regs[1]) << 32));
//logSVC("SleepThread(ns = %lld)\n", ns);
// logSVC("SleepThread(ns = %lld)\n", ns);
regs[0] = Result::Success;
sleepThread(ns);
}
void Kernel::getThreadID() {
Handle handle = regs[1];
HandleType handle = regs[1];
logSVC("GetThreadID(handle = %X)\n", handle);
if (handle == KernelHandles::CurrentThread) {
@ -456,7 +448,7 @@ void Kernel::getThreadID() {
}
void Kernel::getThreadPriority() {
const Handle handle = regs[1];
const HandleType handle = regs[1];
logSVC("GetThreadPriority (handle = %X)\n", handle);
if (handle == KernelHandles::CurrentThread) {
@ -474,7 +466,7 @@ void Kernel::getThreadPriority() {
}
void Kernel::getThreadIdealProcessor() {
const Handle handle = regs[1]; // Thread handle
const HandleType handle = regs[1]; // Thread 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
@ -490,7 +482,7 @@ void Kernel::getThreadContext() {
}
void Kernel::setThreadPriority() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
const u32 priority = regs[1];
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
switch (id) {
// TODO: This is picked from exheader
case ProcessorID::Default:
ret = static_cast<s32>(ProcessorID::AppCore);
break;
case ProcessorID::Default: ret = static_cast<s32>(ProcessorID::AppCore); break;
case ProcessorID::AllCPUs:
ret = static_cast<s32>(ProcessorID::AppCore);
@ -565,8 +555,7 @@ void Kernel::exitThread() {
// Remove the index of this thread from the thread indices vector
for (int i = 0; i < threadIndices.size(); i++) {
if (threadIndices[i] == currentThreadIndex)
threadIndices.erase(threadIndices.begin() + i);
if (threadIndices[i] == currentThreadIndex) threadIndices.erase(threadIndices.begin() + i);
}
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
// This is how thread joining is implemented in the kernel - you wait on a thread, like any other wait object.
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);
t.threadsWaitingForTermination = 0; // No other threads waiting
}
@ -593,7 +582,7 @@ void Kernel::svcCreateMutex() {
}
void Kernel::svcReleaseMutex() {
const Handle handle = regs[0];
const HandleType handle = regs[0];
logSVC("ReleaseMutex (handle = %x)\n", handle);
const auto object = getObject(handle, KernelObjectType::Mutex);
@ -619,18 +608,16 @@ void Kernel::svcCreateSemaphore() {
s32 maxCount = static_cast<s32>(regs[2]);
logSVC("CreateSemaphore (initial count = %d, max count = %d)\n", initialCount, maxCount);
if (initialCount > maxCount)
Helpers::panic("CreateSemaphore: Initial count higher than max count");
if (initialCount > maxCount) Helpers::panic("CreateSemaphore: Initial count higher than max count");
if (initialCount < 0 || maxCount < 0)
Helpers::panic("CreateSemaphore: Negative count value");
if (initialCount < 0 || maxCount < 0) Helpers::panic("CreateSemaphore: Negative count value");
regs[0] = Result::Success;
regs[1] = makeSemaphore(initialCount, maxCount);
}
void Kernel::svcReleaseSemaphore() {
const Handle handle = regs[1];
const HandleType handle = regs[1];
const s32 releaseCount = static_cast<s32>(regs[2]);
logSVC("ReleaseSemaphore (handle = %X, release count = %d)\n", handle, releaseCount);
@ -641,12 +628,10 @@ void Kernel::svcReleaseSemaphore() {
return;
}
if (releaseCount < 0)
Helpers::panic("ReleaseSemaphore: Negative count");
if (releaseCount < 0) Helpers::panic("ReleaseSemaphore: Negative count");
Semaphore* s = object->getData<Semaphore>();
if (s->maximumCount - s->availableCount < releaseCount)
Helpers::panic("ReleaseSemaphore: Release count too high");
if (s->maximumCount - s->availableCount < releaseCount) Helpers::panic("ReleaseSemaphore: Release count too high");
// Write success and old available count to r0 and r1 respectively
regs[0] = Result::Success;
@ -692,8 +677,6 @@ bool Kernel::shouldWaitOnObject(KernelObject* object) {
case KernelObjectType::Semaphore: // Wait if the semaphore count <= 0
return object->getData<Semaphore>()->availableCount <= 0;
default:
Helpers::panic("Not sure whether to wait on object (type: %s)", object->getTypeName());
return true;
default: 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 "scheduler.hpp"
Handle Kernel::makeTimer(ResetType type) {
Handle ret = makeObject(KernelObjectType::Timer);
HandleType Kernel::makeTimer(ResetType type) {
HandleType ret = makeObject(KernelObjectType::Timer);
objects[ret].data = new Timer(type);
if (type == ResetType::Pulse) {
@ -52,11 +52,9 @@ void Kernel::pollTimers() {
}
}
void Kernel::cancelTimer(Timer* timer) {
timer->running = false;
}
void Kernel::cancelTimer(Timer* timer) { timer->running = false; }
void Kernel::signalTimer(Handle timerHandle, Timer* timer) {
void Kernel::signalTimer(HandleType timerHandle, Timer* timer) {
timer->fired = true;
requireReschedule();
@ -94,7 +92,7 @@ void Kernel::svcCreateTimer() {
}
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
const s64 initial = s64(u64(regs[2]) | (u64(regs[3]) << 32));
const s64 interval = s64(u64(regs[1]) | (u64(regs[4]) << 32));
@ -127,7 +125,7 @@ void Kernel::svcSetTimer() {
}
void Kernel::svcClearTimer() {
Handle handle = regs[0];
HandleType handle = regs[0];
logSVC("ClearTimer (handle = %X)\n", handle);
KernelObject* object = getObject(handle, KernelObjectType::Timer);
@ -141,7 +139,7 @@ void Kernel::svcClearTimer() {
}
void Kernel::svcCancelTimer() {
Handle handle = regs[0];
HandleType handle = regs[0];
logSVC("CancelTimer (handle = %X)\n", handle);
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::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
case ConfigMem::WifiMac:
return (u32(MACAddress[3]) << 24) | (u32(MACAddress[2]) << 16) | (u32(MACAddress[1]) << 8) |
MACAddress[0];
case ConfigMem::WifiMac: 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.
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);
}
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) {
if (e.handle == handle) {
// 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 "ipc.hpp"
namespace ACCommands {
@ -130,7 +131,7 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
const u32 pidHeader = mem.read32(messagePointer + 4);
const u32 copyHandleHeader = mem.read32(messagePointer + 12);
// 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;

View file

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

View file

@ -1,4 +1,5 @@
#include "services/boss.hpp"
#include "ipc.hpp"
namespace BOSSCommands {
@ -31,9 +32,7 @@ namespace BOSSCommands {
};
}
void BOSSService::reset() {
optoutFlag = 0;
}
void BOSSService::reset() { optoutFlag = 0; }
void BOSSService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer);
@ -44,8 +43,7 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
case BOSSCommands::GetNsDataIdList:
case BOSSCommands::GetNsDataIdList1:
case BOSSCommands::GetNsDataIdList2:
case BOSSCommands::GetNsDataIdList3:
getNsDataIdList(messagePointer, command); break;
case BOSSCommands::GetNsDataIdList3: getNsDataIdList(messagePointer, command); break;
case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break;
case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break;
case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break;
@ -173,7 +171,6 @@ void BOSSService::sendProperty(u32 messagePointer) {
// TODO: Should this do anything else?
}
void BOSSService::receiveProperty(u32 messagePointer) {
const u32 id = mem.read32(messagePointer + 4);
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
// I need to update the 3DBrew page when it's known what it does properly
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);
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 size = mem.read32(messagePointer + 12);
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);
log("CAM::SetReceiving (port = %d)\n", portIndex);

View file

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

View file

@ -1,7 +1,8 @@
#include "services/fs.hpp"
#include "kernel/kernel.hpp"
#include "io_file.hpp"
#include "ipc.hpp"
#include "kernel/kernel.hpp"
#include "result/result.hpp"
#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
@ -47,9 +48,7 @@ namespace FSCommands {
};
}
void FSService::reset() {
priority = 0;
}
void FSService::reset() { priority = 0; }
// Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
void FSService::initializeFilesystem() {
@ -61,7 +60,6 @@ void FSService::initializeFilesystem() {
const auto systemSaveDataPath = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
namespace fs = std::filesystem;
if (!fs::is_directory(nandSharedpath)) {
fs::create_directories(nandSharedpath);
}
@ -89,23 +87,19 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
case ArchiveID::SaveData: return &saveData;
case ArchiveID::UserSaveData2: return &userSaveData2;
case ArchiveID::ExtSaveData:
return &extSaveData_sdmc;
case ArchiveID::ExtSaveData: return &extSaveData_sdmc;
case ArchiveID::SharedExtSaveData:
return &sharedExtSaveData_nand;
case ArchiveID::SharedExtSaveData: return &sharedExtSaveData_nand;
case ArchiveID::SystemSaveData: return &systemSaveData;
case ArchiveID::SDMC: return &sdmc;
case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly;
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
default:
Helpers::panic("Unknown archive. ID: %d\n", id);
return nullptr;
default: 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);
if (opened.has_value()) { // If opened doesn't have a value, we failed to open the 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);
if (opened.isOk()) { // If opened doesn't have a value, we failed to open the 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);
if (archive == nullptr) [[unlikely]] {
@ -147,8 +141,7 @@ Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 arc
archiveObject.data = new ArchiveSession(res.unwrap(), path);
return Ok(handle);
}
else {
} else {
return Err(res.unwrapErr());
}
}
@ -157,8 +150,7 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
std::vector<u8> data;
data.resize(size);
for (u32 i = 0; i < size; i++)
data[i] = mem.read8(pointer + i);
for (u32 i = 0; i < size; i++) data[i] = mem.read8(pointer + i);
return FSPath(type, data);
}
@ -217,7 +209,7 @@ void FSService::initializeWithSdkVersion(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);
log("FSService::CloseArchive(handle = %X)\n", handle);
@ -241,7 +233,7 @@ void FSService::openArchive(u32 messagePointer) {
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
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));
if (res.isOk()) {
mem.write32(messagePointer + 4, Result::Success);
@ -254,7 +246,7 @@ void FSService::openArchive(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 filePathSize = mem.read32(messagePointer + 20);
const u32 openFlags = mem.read32(messagePointer + 24);
@ -276,7 +268,7 @@ void FSService::openFile(u32 messagePointer) {
auto filePath = readPath(filePathType, filePathPointer, filePathSize);
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));
if (!handle.has_value()) {
printf("OpenFile failed\n");
@ -291,7 +283,7 @@ void FSService::openFile(u32 messagePointer) {
void FSService::createDirectory(u32 messagePointer) {
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 pathSize = mem.read32(messagePointer + 20);
const u32 pathPointer = mem.read32(messagePointer + 32);
@ -313,7 +305,7 @@ void FSService::createDirectory(u32 messagePointer) {
void FSService::openDirectory(u32 messagePointer) {
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 pathSize = mem.read32(messagePointer + 16);
const u32 pathPointer = mem.read32(messagePointer + 24);
@ -366,7 +358,7 @@ void FSService::openFileDirectly(u32 messagePointer) {
}
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));
if (!handle.has_value()) {
printf("OpenFileDirectly failed\n");
@ -378,7 +370,7 @@ void FSService::openFileDirectly(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 filePathSize = mem.read32(messagePointer + 20);
const u32 attributes = mem.read32(messagePointer + 24);
@ -403,7 +395,7 @@ void FSService::createFile(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 filePathSize = mem.read32(messagePointer + 20);
const u32 filePathPointer = mem.read32(messagePointer + 28);
@ -425,7 +417,7 @@ void FSService::deleteFile(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 filePathSize = mem.read32(messagePointer + 20);
const u32 filePathPointer = mem.read32(messagePointer + 28);
@ -470,8 +462,7 @@ void FSService::formatSaveData(u32 messagePointer) {
log("FS::FormatSaveData\n");
const u32 archiveID = mem.read32(messagePointer + 4);
if (archiveID != ArchiveID::SaveData)
Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
if (archiveID != ArchiveID::SaveData) Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
// Read path and path info
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
const u32 blockSize = mem.read32(messagePointer + 16);
if (blockSize != 0x200 && blockSize != 0x1000)
Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
if (blockSize != 0x200 && blockSize != 0x1000) Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories
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 bool duplicateData = mem.read8(messagePointer + 36) != 0;
ArchiveBase::FormatInfo info {
.size = blockSize * 0x200,
.numOfDirectories = directoryNum,
.numOfFiles = fileNum,
.duplicateData = duplicateData
};
ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
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);
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
// When we properly implement it, it will just be a recursive directory deletion
// 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 When we properly implement it, it will just be a recursive directory deletion
mem.write32(messagePointer + 4, Result::Success);
}
@ -521,7 +506,8 @@ void FSService::createExtSaveData(u32 messagePointer) {
Helpers::warn("Stubbed call to FS::CreateExtSaveData!");
// First 4 words of parameters are the ExtSaveData info
// 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 u64 saveID = mem.read64(messagePointer + 8);
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 bool duplicateData = mem.read8(messagePointer + 24) != 0;
ArchiveBase::FormatInfo info {
.size = blockSize * 0x200,
.numOfDirectories = directoryNum,
.numOfFiles = fileNum,
.duplicateData = duplicateData
};
ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
FSPath emptyPath;
mem.write32(messagePointer, IPC::responseHeader(0x080F, 1, 0));
@ -560,7 +541,7 @@ void FSService::formatThisUserSaveData(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 inputSize = mem.read32(messagePointer + 16);
const u32 outputSize = mem.read32(messagePointer + 20);
@ -587,15 +568,13 @@ void FSService::controlArchive(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
break;
default:
Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action);
break;
default: Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action); break;
}
}
void FSService::getFreeBytes(u32 messagePointer) {
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);
mem.write32(messagePointer, IPC::responseHeader(0x812, 3, 0));
@ -639,7 +618,7 @@ void FSService::getArchiveResource(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);
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));
const Handle sourceArchiveHandle = mem.read64(messagePointer + 8);
const Handle destArchiveHandle = mem.read64(messagePointer + 24);
const HandleType sourceArchiveHandle = mem.read64(messagePointer + 8);
const HandleType destArchiveHandle = mem.read64(messagePointer + 24);
// Read path info
const u32 sourcePathType = mem.read32(messagePointer + 16);

View file

@ -1,7 +1,9 @@
#include "services/hid.hpp"
#include <bit>
#include "ipc.hpp"
#include "kernel.hpp"
#include <bit>
namespace HIDCommands {
enum : u32 {
@ -140,7 +142,7 @@ void HIDService::getIPCHandles(u32 messagePointer) {
// Write HID event handles
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 "ipc.hpp"
#include "kernel.hpp"
#include <cstdio>
#include <string>
#include "ipc.hpp"
#include "kernel.hpp"
namespace LDRCommands {
enum : u32 {
Initialize = 0x000100C2,
@ -65,10 +66,13 @@ namespace SegmentTable {
namespace SegmentID {
enum : u32 {
TEXT, RODATA, DATA, BSS,
TEXT,
RODATA,
DATA,
BSS,
};
}
}
} // namespace SegmentTable
namespace NamedExportTable {
enum : u32 {
@ -129,7 +133,7 @@ namespace RelocationPatch {
AbsoluteAddress = 2,
};
};
};
}; // namespace RelocationPatch
struct CROHeaderEntry {
u32 offset, size;
@ -149,7 +153,7 @@ class CRO {
bool isCRO; // False if CRS
public:
public:
CRO(Memory &mem, u32 croPointer, bool isCRO) : mem(mem), croPointer(croPointer), oldDataSegmentOffset(0), isCRO(isCRO) {}
~CRO() = default;
@ -159,21 +163,13 @@ public:
return mem.readString(moduleName.offset, moduleName.size);
}
u32 getNextCRO() {
return mem.read32(croPointer + CROHeader::NextCRO);
}
u32 getNextCRO() { return mem.read32(croPointer + CROHeader::NextCRO); }
u32 getPrevCRO() {
return mem.read32(croPointer + CROHeader::PrevCRO);
}
u32 getPrevCRO() { return mem.read32(croPointer + CROHeader::PrevCRO); }
void setNextCRO(u32 nextCRO) {
mem.write32(croPointer + CROHeader::NextCRO, nextCRO);
}
void setNextCRO(u32 nextCRO) { mem.write32(croPointer + CROHeader::NextCRO, nextCRO); }
void setPrevCRO(u32 prevCRO) {
mem.write32(croPointer + CROHeader::PrevCRO, prevCRO);
}
void setPrevCRO(u32 prevCRO) { mem.write32(croPointer + CROHeader::PrevCRO, prevCRO); }
void write32(u32 addr, u32 value) {
// Note: some games export symbols to the static module, which doesn't contain any segments.
@ -181,11 +177,11 @@ public:
// can't be accessed via mem.write32()
auto writePointer = mem.getWritePointer(addr);
if (writePointer) {
*(u32*)writePointer = value;
*(u32 *)writePointer = value;
} else {
auto readPointer = mem.getReadPointer(addr);
if (readPointer) {
*(u32*)readPointer = value;
*(u32 *)readPointer = value;
} else {
Helpers::panic("LDR_RO write to invalid address = %X\n", addr);
}
@ -219,11 +215,9 @@ public:
return entryOffset + offset;
}
u32 getOnUnresolvedAddr() {
return getSegmentAddr(mem.read32(croPointer + CROHeader::OnUnresolved));
}
u32 getOnUnresolvedAddr() { 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,
// we won't use it and instead look up the symbol in the named export symbol table
@ -437,13 +431,16 @@ public:
const u32 segmentID = mem.read32(segmentTable.offset + 12 * segment + SegmentTable::ID);
switch (segmentID) {
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::TEXT:
case SegmentTable::SegmentID::RODATA:
if (segmentOffset != 0) segmentOffset += croPointer; break;
default:
Helpers::panic("Unknown segment ID = %u", segmentID);
if (segmentOffset != 0) segmentOffset += croPointer;
break;
default: Helpers::panic("Unknown segment ID = %u", segmentID);
}
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
@ -464,9 +461,9 @@ public:
case SegmentTable::SegmentID::BSS: segmentOffset = 0; break;
case SegmentTable::SegmentID::TEXT:
case SegmentTable::SegmentID::RODATA:
if (segmentOffset != 0) segmentOffset -= croPointer; break;
default:
Helpers::panic("Unknown segment ID = %u", segmentID);
if (segmentOffset != 0) segmentOffset -= croPointer;
break;
default: Helpers::panic("Unknown segment ID = %u", segmentID);
}
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
@ -630,7 +627,9 @@ public:
u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
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);
if (relocationOffset != 0) {
mem.write32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer);
mem.write32(
anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer
);
}
}
@ -652,7 +653,7 @@ public:
}
bool relocateInternalSymbols(u32 oldDataVaddr) {
const u8* header = (u8*)mem.getReadPointer(croPointer);
const u8 *header = (u8 *)mem.getReadPointer(croPointer);
const CROHeaderEntry relocationPatchTable = getHeaderEntry(CROHeader::RelocationPatchTableOffset);
const CROHeaderEntry segmentTable = getHeaderEntry(CROHeader::SegmentTableOffset);
@ -1189,9 +1190,7 @@ public:
}
};
void LDRService::reset() {
loadedCRS = 0;
}
void LDRService::reset() { loadedCRS = 0; }
void LDRService::handleSyncRequest(u32 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 size = mem.read32(messagePointer + 8);
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);
@ -1258,7 +1257,7 @@ void LDRService::initialize(u32 messagePointer) {
void LDRService::linkCRO(u32 messagePointer) {
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);
@ -1287,7 +1286,7 @@ void LDRService::linkCRO(u32 messagePointer) {
void LDRService::loadCRR(u32 messagePointer) {
const u32 crrPointer = mem.read32(messagePointer + 4);
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);
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 bool autoLink = mem.read32(messagePointer + 36) != 0;
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
if (size < CRO_HEADER_SIZE) {
@ -1362,7 +1363,7 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
void LDRService::unloadCRO(u32 messagePointer) {
const u32 mapVaddr = mem.read32(messagePointer + 4);
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);

View file

@ -8,8 +8,8 @@
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),
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),
news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
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), news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
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
// messagePointer: The base pointer for the IPC message
void ServiceManager::handleSyncRequest(u32 messagePointer) {
@ -93,7 +93,7 @@ void ServiceManager::registerClient(u32 messagePointer) {
}
// clang-format off
static std::map<std::string, Handle> serviceMap = {
static std::map<std::string, HandleType> serviceMap = {
{ "ac:u", KernelHandles::AC },
{ "act:a", 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 + 4, Result::Success); // Result code
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());
}
@ -195,7 +195,7 @@ void ServiceManager::unsubscribe(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}
void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
void ServiceManager::sendCommandToService(u32 messagePointer, HandleType handle) {
switch (handle) {
// 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;

View file

@ -21,7 +21,7 @@ void SOCService::handleSyncRequest(u32 messagePointer) {
void SOCService::initializeSockets(u32 messagePointer) {
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);
// 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 "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");
// Enable drop events for loading ROMs
setAcceptDrops(true);
@ -90,6 +91,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
const RendererType rendererType = emu->getConfig().rendererType;
usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null);
usingVk = (rendererType == RendererType::Vulkan);
usingMtl = (rendererType == RendererType::Metal);
if (usingGL) {
// Make GL context current for this thread, enable VSync
@ -100,6 +102,8 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
emu->initGraphicsContext(glContext);
} else if (usingVk) {
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 {
Helpers::panic("Unsupported graphics backend for Qt frontend!");
}
@ -264,8 +268,7 @@ void MainWindow::dumpDspFirmware() {
case DSPService::ComponentDumpResult::Success: break;
case DSPService::ComponentDumpResult::NotLoaded: {
QMessageBox messageBox(
QMessageBox::Icon::Warning, tr("No DSP firmware loaded"),
tr("The currently loaded app has not uploaded a firmware to the DSP")
QMessageBox::Icon::Warning, tr("No DSP firmware loaded"), tr("The currently loaded app has not uploaded a firmware to the DSP")
);
QAbstractButton* button = messageBox.addButton(tr("OK"), QMessageBox::ButtonRole::YesRole);

View file

@ -63,6 +63,16 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
}
#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);
}
@ -240,7 +250,7 @@ void FrontendSDL::run() {
case SDL_MOUSEMOTION: {
if (emu.romType == ROMType::None) break;
// Handle "dragging" across the touchscreen
// HandleType "dragging" across the touchscreen
if (hid.isTouchScreenPressed()) {
const s32 x = event.motion.x;
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},
{"vk", RendererType::Vulkan}, {"vulkan", RendererType::Vulkan}, {"vulcan", RendererType::Vulkan},
{"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()) {
@ -34,6 +34,7 @@ const char* Renderer::typeToString(RendererType rendererType) {
case RendererType::OpenGL: return "opengl";
case RendererType::Vulkan: return "vulkan";
case RendererType::Software: return "software";
case RendererType::Metal: return "metal";
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