diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index e136cb411..cd5216f55 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -15,6 +15,10 @@ #include #endif +#ifdef __FreeBSD__ +#include +#endif + #if defined(WIN32) #include #else @@ -1407,7 +1411,7 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co FILESYSTEM_FIND_DATA outData; outData.Attributes = 0; -#if defined(__HAIKU__) || defined(__APPLE__) +#if defined(__HAIKU__) || defined(__APPLE__) || defined(__FreeBSD__) struct stat sDir; if (stat(full_path, &sDir) < 0) continue; @@ -1505,7 +1509,7 @@ bool StatFile(const char* Path, FILESYSTEM_STAT_DATA* pStatData) return false; // stat file -#if defined(__HAIKU__) || defined(__APPLE__) +#if defined(__HAIKU__) || defined(__APPLE__) || defined(__FreeBSD__) struct stat sysStatData; if (stat(Path, &sysStatData) < 0) #else @@ -1539,7 +1543,7 @@ bool StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData) return false; // stat file -#if defined(__HAIKU__) || defined(__APPLE__) +#if defined(__HAIKU__) || defined(__APPLE__) || defined(__FreeBSD__) struct stat sysStatData; if (fstat(fd, &sysStatData) < 0) #else @@ -1573,7 +1577,7 @@ bool FileExists(const char* Path) return false; // stat file -#if defined(__HAIKU__) || defined(__APPLE__) +#if defined(__HAIKU__) || defined(__APPLE__) || defined(__FreeBSD__) struct stat sysStatData; if (stat(Path, &sysStatData) < 0) #else @@ -1595,7 +1599,7 @@ bool DirectoryExists(const char* Path) return false; // stat file -#if defined(__HAIKU__) || defined(__APPLE__) +#if defined(__HAIKU__) || defined(__APPLE__) || defined(__FreeBSD__) struct stat sysStatData; if (stat(Path, &sysStatData) < 0) #else @@ -1752,6 +1756,16 @@ std::string GetProgramPath() buffer = static_cast(std::realloc(buffer, curSize + 1)); } +#elif defined(__FreeBSD__) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + char buffer[PATH_MAX]; + size_t cb = sizeof(buffer) - 1; + int res = sysctl(mib, countof(mib), buffer, &cb, nullptr, 0); + if (res != 0) + return {}; + + buffer[cb] = '\0'; + return buffer; #else return {}; #endif diff --git a/src/common/jit_code_buffer.cpp b/src/common/jit_code_buffer.cpp index 62baf028a..bbb676c41 100644 --- a/src/common/jit_code_buffer.cpp +++ b/src/common/jit_code_buffer.cpp @@ -45,7 +45,7 @@ bool JitCodeBuffer::Allocate(u32 size /* = 64 * 1024 * 1024 */, u32 far_code_siz Log_ErrorPrintf("VirtualAlloc(RWX, %u) for internal buffer failed: %u", m_total_size, GetLastError()); return false; } -#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) +#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__FreeBSD__) m_code_ptr = static_cast( mmap(nullptr, m_total_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); if (!m_code_ptr) @@ -100,7 +100,7 @@ bool JitCodeBuffer::Initialize(void* buffer, u32 size, u32 far_code_size /* = 0 m_code_ptr = static_cast(buffer); m_old_protection = static_cast(old_protect); -#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) +#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__FreeBSD__) if (mprotect(buffer, size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { Log_ErrorPrintf("mprotect(RWX) for external buffer failed: %d", errno); @@ -148,7 +148,7 @@ void JitCodeBuffer::Destroy() { #if defined(WIN32) VirtualFree(m_code_ptr, 0, MEM_RELEASE); -#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) +#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__FreeBSD__) munmap(m_code_ptr, m_total_size); #endif } diff --git a/src/common/memory_arena.cpp b/src/common/memory_arena.cpp index a534f83d5..0b4d6e324 100644 --- a/src/common/memory_arena.cpp +++ b/src/common/memory_arena.cpp @@ -13,7 +13,7 @@ Log_SetChannel(Common::MemoryArena); #include #include #include -#elif defined(__linux__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) #include #include #include @@ -73,7 +73,7 @@ void* MemoryArena::FindBaseAddressForMapping(size_t size) base_address = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE); if (base_address) VirtualFree(base_address, 0, MEM_RELEASE); -#elif defined(__linux__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) base_address = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); if (base_address) munmap(base_address, size); @@ -153,18 +153,25 @@ bool MemoryArena::Create(size_t size, bool writable, bool executable) } return true; -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) const std::string file_mapping_name = StringUtil::StdStringFromFormat("duckstation_%u", static_cast(getpid())); m_shmem_fd = shm_open(file_mapping_name.c_str(), O_CREAT | O_EXCL | (writable ? O_RDWR : O_RDONLY), 0600); +#else + m_shmem_fd = shm_open(SHM_ANON, O_CREAT | O_EXCL | (writable ? O_RDWR : O_RDONLY), 0600); +#endif + if (m_shmem_fd < 0) { Log_ErrorPrintf("shm_open failed: %d", errno); return false; } +#ifdef __APPLE__ // we're not going to be opening this mapping in other processes, so remove the file shm_unlink(file_mapping_name.c_str()); +#endif // ensure it's the correct size if (ftruncate(m_shmem_fd, static_cast(size)) < 0) @@ -187,7 +194,7 @@ void MemoryArena::Destroy() CloseHandle(m_file_handle); m_file_handle = nullptr; } -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) if (m_shmem_fd > 0) { close(m_shmem_fd); @@ -222,7 +229,7 @@ void* MemoryArena::CreateViewPtr(size_t offset, size_t size, bool writable, bool base_pointer = mmap64(fixed_address, size, prot, flags, m_shmem_fd, static_cast(offset)); if (base_pointer == reinterpret_cast(-1)) return nullptr; -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__FreeBSD__) const int flags = (fixed_address != nullptr) ? (MAP_SHARED | MAP_FIXED) : MAP_SHARED; const int prot = PROT_READ | (writable ? PROT_WRITE : 0) | (executable ? PROT_EXEC : 0); base_pointer = mmap(fixed_address, size, prot, flags, m_shmem_fd, static_cast(offset)); @@ -240,7 +247,7 @@ bool MemoryArena::FlushViewPtr(void* address, size_t size) { #if defined(WIN32) return FlushViewOfFile(address, size); -#elif defined(__linux__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) return (msync(address, size, 0) >= 0); #else return false; @@ -252,7 +259,7 @@ bool MemoryArena::ReleaseViewPtr(void* address, size_t size) bool result; #if defined(WIN32) result = static_cast(UnmapViewOfFile(address)); -#elif defined(__linux__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) result = (munmap(address, size) >= 0); #else result = false; @@ -279,7 +286,7 @@ bool MemoryArena::SetPageProtection(void* address, size_t length, bool readable, DWORD old_protect; return static_cast( VirtualProtect(address, length, protection_table[readable][writable][executable], &old_protect)); -#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__FreeBSD__) const int prot = (readable ? PROT_READ : 0) | (writable ? PROT_WRITE : 0) | (executable ? PROT_EXEC : 0); return (mprotect(address, length, prot) >= 0); #else diff --git a/src/common/memory_arena.h b/src/common/memory_arena.h index 93290b4a8..7e08f35ba 100644 --- a/src/common/memory_arena.h +++ b/src/common/memory_arena.h @@ -48,7 +48,7 @@ public: private: #if defined(WIN32) void* m_file_handle = nullptr; -#elif defined(__linux__) || defined(ANDROID) || defined(__APPLE__) +#elif defined(__linux__) || defined(ANDROID) || defined(__APPLE__) || defined(__FreeBSD__) int m_shmem_fd = -1; #endif diff --git a/src/common/page_fault_handler.cpp b/src/common/page_fault_handler.cpp index 1b4f1bf84..c882114a6 100644 --- a/src/common/page_fault_handler.cpp +++ b/src/common/page_fault_handler.cpp @@ -14,7 +14,7 @@ Log_SetChannel(Common::PageFaultHandler); #include #include #define USE_SIGSEGV 1 -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__FreeBSD__) #include #include #define USE_SIGSEGV 1 @@ -36,7 +36,7 @@ static bool IsStoreInstruction(const void* ptr) { u32 bits; std::memcpy(&bits, ptr, sizeof(bits)); - + // TODO return false; } @@ -125,7 +125,7 @@ static void SIGSEGVHandler(int sig, siginfo_t* info, void* ctx) if ((info->si_code != SEGV_MAPERR && info->si_code != SEGV_ACCERR) || s_in_handler) return; -#ifndef __APPLE__ +#if defined(__linux__) || defined(__ANDROID__) void* const exception_address = reinterpret_cast(info->si_addr); #if defined(CPU_X64) @@ -141,7 +141,9 @@ static void SIGSEGVHandler(int sig, siginfo_t* info, void* ctx) void* const exception_pc = nullptr; const bool is_write = false; #endif -#else // __APPLE__ + +#elif defined(__APPLE__) + #if defined(CPU_X64) void* const exception_address = reinterpret_cast(static_cast(ctx)->uc_mcontext->__es.__faultvaddr); @@ -156,7 +158,24 @@ static void SIGSEGVHandler(int sig, siginfo_t* info, void* ctx) void* const exception_pc = nullptr; const bool is_write = false; #endif -#endif // __APPLE__ + +#elif defined(__FreeBSD__) + +#if defined(CPU_X64) + void* const exception_address = reinterpret_cast(static_cast(ctx)->uc_mcontext.mc_addr); + void* const exception_pc = reinterpret_cast(static_cast(ctx)->uc_mcontext.mc_rip); + const bool is_write = (static_cast(ctx)->uc_mcontext.mc_err & 2) != 0; +#elif defined(CPU_AARCH64) + void* const exception_address = reinterpret_cast(static_cast(ctx)->uc_mcontext->__es.__far); + void* const exception_pc = reinterpret_cast(static_cast(ctx)->uc_mcontext->__ss.__pc); + const bool is_write = IsStoreInstruction(exception_pc); +#else + void* const exception_address = reinterpret_cast(info->si_addr); + void* const exception_pc = nullptr; + const bool is_write = false; +#endif + +#endif std::lock_guard guard(m_handler_lock); for (const RegisteredHandler& rh : m_handlers) diff --git a/src/core/cpu_recompiler_types.h b/src/core/cpu_recompiler_types.h index 633e28b26..bc06a10ee 100644 --- a/src/core/cpu_recompiler_types.h +++ b/src/core/cpu_recompiler_types.h @@ -83,7 +83,7 @@ constexpr u32 CODE_STORAGE_ALIGNMENT = 4096; // ABI selection #if defined(WIN32) #define ABI_WIN64 1 -#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) +#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__FreeBSD__) #define ABI_SYSV 1 #else #error Unknown ABI. diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index 100089bb7..f5b8c2bc7 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -889,7 +889,7 @@ void CommonHostInterface::SetUserDirectory() } else { -#ifdef WIN32 +#if defined(WIN32) // On Windows, use My Documents\DuckStation. PWSTR documents_directory; if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory))) @@ -902,7 +902,7 @@ void CommonHostInterface::SetUserDirectory() } CoTaskMemFree(documents_directory); } -#elif __linux__ +#elif defined(__linux__) || defined(__FreeBSD__) // On Linux, use .local/share/duckstation as a user directory by default. const char* xdg_data_home = getenv("XDG_DATA_HOME"); if (xdg_data_home && xdg_data_home[0] == '/') @@ -915,7 +915,7 @@ void CommonHostInterface::SetUserDirectory() if (home_path) m_user_directory = StringUtil::StdStringFromFormat("%s/.local/share/duckstation", home_path); } -#elif __APPLE__ +#elif defined(__APPLE__) // On macOS, default to ~/Library/Application Support/DuckStation. const char* home_path = getenv("HOME"); if (home_path) diff --git a/src/frontend-common/evdev_controller_interface.cpp b/src/frontend-common/evdev_controller_interface.cpp index 5377d6fb9..4798f4470 100644 --- a/src/frontend-common/evdev_controller_interface.cpp +++ b/src/frontend-common/evdev_controller_interface.cpp @@ -5,11 +5,16 @@ #include "core/controller.h" #include "core/host_interface.h" #include "core/system.h" -#include +#include #include #include #include #include + +#ifdef __linux__ +#include +#endif + Log_SetChannel(EvdevControllerInterface); EvdevControllerInterface::EvdevControllerInterface() = default;