From 8b5b9778886ae40f8f6f38e0cff15a89fcee4b45 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 7 Dec 2025 00:39:38 +0000 Subject: [PATCH] more stupid stuff --- src/common/virtual_buffer.cpp | 71 +++++++++++++++++++++++------------ src/yuzu_cmd/yuzu.cpp | 5 +++ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp index 3e5f327245..d444e81edf 100644 --- a/src/common/virtual_buffer.cpp +++ b/src/common/virtual_buffer.cpp @@ -11,7 +11,9 @@ #endif #ifdef __OPENORBIS__ +#include #include +#include #endif #include "common/assert.h" @@ -28,10 +30,54 @@ # ifndef MAP_VOID # define MAP_VOID 0x100 # endif +// sigaction(2) has a motherfucking bug on musl where the thing isnt even properly prefixed +# undef sa_sigaction +# define sa_sigaction __sa_handler.__sa_sigaction #endif namespace Common { +#ifdef __OPENORBIS__ +static struct sigaction old_sa_segv; +static boost::container::static_vector, 16> swap_regions; +static void SwapHandler(int sig, siginfo_t* si, void* raw_context) { + if (std::ranges::find_if(swap_regions, [addr = si->si_addr](auto const& e) { + return uintptr_t(addr) >= uintptr_t(e.first) && uintptr_t(addr) < uintptr_t(e.first) + e.second; + }) != swap_regions.end()) { + size_t const page_size = 4096; + size_t const page_mask = ~0xfff; + // should replace the existing mapping... ugh + void* aligned_addr = reinterpret_cast(uintptr_t(si->si_addr) & page_mask); + void* res = mmap(aligned_addr, page_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + ASSERT(res != MAP_FAILED); + } else { + struct sigaction* retry_sa = &old_sa_segv; + if ((retry_sa->sa_flags & SA_SIGINFO) != 0) { + retry_sa->sa_sigaction(sig, si, raw_context); + } else if (retry_sa->sa_handler == SIG_DFL) { + signal(sig, SIG_DFL); + } else if (retry_sa->sa_handler == SIG_IGN) { + // ignore? + } else { + retry_sa->sa_handler(sig); + } + } +} + +bool InitSwap() noexcept { + struct sigaction sa; + sa.sa_handler = NULL; + sa.sa_sigaction = &SwapHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_RESTART; + return sigaction(SIGSEGV, &sa, &old_sa_segv) == 0; +} +#else +bool InitSwap() noexcept { + return true; +} +#endif + void* AllocateMemoryPages(std::size_t size) noexcept { #ifdef _WIN32 void* addr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE); @@ -39,6 +85,7 @@ void* AllocateMemoryPages(std::size_t size) noexcept { #elif defined(__OPENORBIS__) void* addr = mmap(nullptr, size, PROT_NONE, MAP_VOID | MAP_PRIVATE, -1, 0); ASSERT(addr != MAP_FAILED); + swap_regions.emplace_back(addr, size); #else void* addr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); ASSERT(addr != MAP_FAILED); @@ -50,33 +97,11 @@ void FreeMemoryPages(void* addr, [[maybe_unused]] std::size_t size) noexcept { if (!addr) return; #ifdef _WIN32 - VirtualFree(addr, 0, MEM_RELEASE) + VirtualFree(addr, 0, MEM_RELEASE); #else int rc = munmap(addr, size); ASSERT(rc == 0); #endif } -#ifdef __OPENORBIS__ -static struct sigaction old_sa_segv; -static void SwapHandler(int sig, siginfo_t* si, void* raw_context) { - void* aligned_addr = reinterpret_cast(uintptr_t(si->si_addr) & ~0xfff); - void* res = mmap(aligned_addr, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); - ASSERT(res != MAP_FAILED); -} - -bool InitSwap() noexcept { - struct sigaction sa; - sa.sa_handler = NULL; - sa.__sa_handler.__sa_sigaction = &SwapHandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO | SA_RESTART; - return sigaction(SIGSEGV, &sa, &old_sa_segv) == 0; -} -#else -bool InitSwap() noexcept { - return true; -} -#endif - } // namespace Common diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index da2fd84c15..0a50e44d85 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -236,6 +236,11 @@ int main(int argc, char** argv) { // clang-format on }; +#ifdef __OPENORBIS__ + // PS4 will use this path by default UNLESS overriden; this is so users + // can quickly launch whatever they want. + filepath = "/data/eden/games/test.nro"; +#endif while (optind < argc) { int arg = getopt_long(argc, argv, "g:fhvp::c:u:d:", long_options, &option_index); if (arg != -1) {