From 4405116324fda4895ccdc1ec6bc32ee253b16261 Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Sun, 24 Dec 2023 00:25:01 +0100 Subject: [PATCH 01/12] GDBStub: Support watchpoints on linux (#1030) * GDBStub: Support watchpoints on linux * GDBStub: Use `TCP_NODELAY` --- src/Cafe/CMakeLists.txt | 1 + .../HW/Espresso/Debugger/GDBBreakpoints.cpp | 304 ++++++++++++++++++ .../HW/Espresso/Debugger/GDBBreakpoints.h | 211 +----------- src/Cafe/HW/Espresso/Debugger/GDBStub.cpp | 8 + src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 31 +- .../ExceptionHandler_posix.cpp | 13 + 6 files changed, 371 insertions(+), 197 deletions(-) create mode 100644 src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 29c5a0b3..9e20bb33 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(CemuCafe HW/Espresso/Debugger/DebugSymbolStorage.h HW/Espresso/Debugger/GDBStub.h HW/Espresso/Debugger/GDBStub.cpp + HW/Espresso/Debugger/GDBBreakpoints.cpp HW/Espresso/Debugger/GDBBreakpoints.h HW/Espresso/EspressoISA.h HW/Espresso/Interpreter/PPCInterpreterALU.hpp diff --git a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp new file mode 100644 index 00000000..675050d3 --- /dev/null +++ b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp @@ -0,0 +1,304 @@ +#include "GDBBreakpoints.h" +#include "Debugger.h" +#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h" + +#if defined(ARCH_X86_64) && BOOST_OS_LINUX +#include +#include +#include + +DRType _GetDR(pid_t tid, int drIndex) +{ + size_t drOffset = offsetof(struct user, u_debugreg) + drIndex * sizeof(user::u_debugreg[0]); + + long v; + v = ptrace(PTRACE_PEEKUSER, tid, drOffset, nullptr); + if (v == -1) + perror("ptrace(PTRACE_PEEKUSER)"); + + return (DRType)v; +} + +void _SetDR(pid_t tid, int drIndex, DRType newValue) +{ + size_t drOffset = offsetof(struct user, u_debugreg) + drIndex * sizeof(user::u_debugreg[0]); + + long rc = ptrace(PTRACE_POKEUSER, tid, drOffset, newValue); + if (rc == -1) + perror("ptrace(PTRACE_POKEUSER)"); +} + +DRType _ReadDR6() +{ + pid_t tid = gettid(); + + // linux doesn't let us attach to the current thread / threads in the current thread group + // we have to create a child process which then modifies the debug registers and quits + pid_t child = fork(); + if (child == -1) + { + perror("fork"); + return 0; + } + + if (child == 0) + { + if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr)) + { + perror("attach"); + _exit(0); + } + + waitpid(tid, NULL, 0); + + uint64_t dr6 = _GetDR(tid, 6); + + if (ptrace(PTRACE_DETACH, tid, nullptr, nullptr)) + perror("detach"); + + // since the status code only uses the lower 8 bits, we have to discard the rest of DR6 + // this should be fine though, since the lower 4 bits of DR6 contain all the bp conditions + _exit(dr6 & 0xff); + } + + // wait for child process + int wstatus; + waitpid(child, &wstatus, 0); + + return (DRType)WEXITSTATUS(wstatus); +} +#endif + +GDBServer::ExecutionBreakpoint::ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason) + : m_address(address), m_removedAfterInterrupt(false), m_reason(std::move(reason)) +{ + if (type == BreakpointType::BP_SINGLE) + { + this->m_pauseThreads = true; + this->m_restoreAfterInterrupt = false; + this->m_deleteAfterAnyInterrupt = false; + this->m_pauseOnNextInterrupt = false; + this->m_visible = visible; + } + else if (type == BreakpointType::BP_PERSISTENT) + { + this->m_pauseThreads = true; + this->m_restoreAfterInterrupt = true; + this->m_deleteAfterAnyInterrupt = false; + this->m_pauseOnNextInterrupt = false; + this->m_visible = visible; + } + else if (type == BreakpointType::BP_RESTORE_POINT) + { + this->m_pauseThreads = false; + this->m_restoreAfterInterrupt = false; + this->m_deleteAfterAnyInterrupt = false; + this->m_pauseOnNextInterrupt = false; + this->m_visible = false; + } + else if (type == BreakpointType::BP_STEP_POINT) + { + this->m_pauseThreads = false; + this->m_restoreAfterInterrupt = false; + this->m_deleteAfterAnyInterrupt = true; + this->m_pauseOnNextInterrupt = true; + this->m_visible = false; + } + + this->m_origOpCode = memory_readU32(address); + memory_writeU32(address, DEBUGGER_BP_T_GDBSTUB_TW); + PPCRecompiler_invalidateRange(address, address + 4); +} + +GDBServer::ExecutionBreakpoint::~ExecutionBreakpoint() +{ + memory_writeU32(this->m_address, this->m_origOpCode); + PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); +} + +uint32 GDBServer::ExecutionBreakpoint::GetVisibleOpCode() const +{ + if (this->m_visible) + return memory_readU32(this->m_address); + else + return this->m_origOpCode; +} + +void GDBServer::ExecutionBreakpoint::RemoveTemporarily() +{ + memory_writeU32(this->m_address, this->m_origOpCode); + PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); + this->m_restoreAfterInterrupt = true; +} + +void GDBServer::ExecutionBreakpoint::Restore() +{ + memory_writeU32(this->m_address, DEBUGGER_BP_T_GDBSTUB_TW); + PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); + this->m_restoreAfterInterrupt = false; +} + +namespace coreinit +{ +#if BOOST_OS_LINUX + std::vector& OSGetSchedulerThreadIds(); +#endif + + std::vector& OSGetSchedulerThreads(); +} + +GDBServer::AccessBreakpoint::AccessBreakpoint(MPTR address, AccessPointType type) + : m_address(address), m_type(type) +{ +#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS + for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) + { + HANDLE hThread = (HANDLE)hThreadNH; + CONTEXT ctx{}; + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + SuspendThread(hThread); + GetThreadContext(hThread, &ctx); + + // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already + ctx.Dr2 = (DWORD64)memory_getPointerFromVirtualOffset(address); + ctx.Dr3 = (DWORD64)memory_getPointerFromVirtualOffset(address); + // breakpoint 2 + SetBits(ctx.Dr7, 4, 1, 1); // breakpoint #3 enabled: true + SetBits(ctx.Dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write) + SetBits(ctx.Dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes) + // breakpoint 3 + SetBits(ctx.Dr7, 6, 1, 1); // breakpoint #4 enabled: true + SetBits(ctx.Dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write) + SetBits(ctx.Dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes) + + SetThreadContext(hThread, &ctx); + ResumeThread(hThread); + } +#elif defined(ARCH_X86_64) && BOOST_OS_LINUX + // linux doesn't let us attach to threads which are in the same thread group as our current thread + // we have to create a child process which then modifies the debug registers and quits + pid_t child = fork(); + if (child == -1) + { + perror("fork"); + return; + } + + if (child == 0) + { + for (pid_t tid : coreinit::OSGetSchedulerThreadIds()) + { + long rc = ptrace(PTRACE_ATTACH, tid, nullptr, nullptr); + if (rc == -1) + perror("ptrace(PTRACE_ATTACH)"); + + waitpid(tid, nullptr, 0); + + DRType dr7 = _GetDR(tid, 7); + // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already + DRType dr2 = (uint64)memory_getPointerFromVirtualOffset(address); + DRType dr3 = (uint64)memory_getPointerFromVirtualOffset(address); + // breakpoint 2 + SetBits(dr7, 4, 1, 1); // breakpoint #3 enabled: true + SetBits(dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write) + SetBits(dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes) + // breakpoint 3 + SetBits(dr7, 6, 1, 1); // breakpoint #4 enabled: true + SetBits(dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write) + SetBits(dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes) + + _SetDR(tid, 2, dr2); + _SetDR(tid, 3, dr3); + _SetDR(tid, 7, dr7); + + rc = ptrace(PTRACE_DETACH, tid, nullptr, nullptr); + if (rc == -1) + perror("ptrace(PTRACE_DETACH)"); + } + + // exit child process + _exit(0); + } + + // wait for child process + waitpid(child, nullptr, 0); +#else + cemuLog_log(LogType::Force, "Debugger read/write breakpoints are not supported on non-x86 CPUs yet."); +#endif +} + +GDBServer::AccessBreakpoint::~AccessBreakpoint() +{ +#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS + for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) + { + HANDLE hThread = (HANDLE)hThreadNH; + CONTEXT ctx{}; + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + SuspendThread(hThread); + GetThreadContext(hThread, &ctx); + + // reset BP 2/3 to zero + ctx.Dr2 = (DWORD64)0; + ctx.Dr3 = (DWORD64)0; + // breakpoint 2 + SetBits(ctx.Dr7, 4, 1, 0); + SetBits(ctx.Dr7, 24, 2, 0); + SetBits(ctx.Dr7, 26, 2, 0); + // breakpoint 3 + SetBits(ctx.Dr7, 6, 1, 0); + SetBits(ctx.Dr7, 28, 2, 0); + SetBits(ctx.Dr7, 30, 2, 0); + SetThreadContext(hThread, &ctx); + ResumeThread(hThread); + } +#elif defined(ARCH_X86_64) && BOOST_OS_LINUX + // linux doesn't let us attach to threads which are in the same thread group as our current thread + // we have to create a child process which then modifies the debug registers and quits + pid_t child = fork(); + if (child == -1) + { + perror("fork"); + return; + } + + if (child == 0) + { + for (pid_t tid : coreinit::OSGetSchedulerThreadIds()) + { + long rc = ptrace(PTRACE_ATTACH, tid, nullptr, nullptr); + if (rc == -1) + perror("ptrace(PTRACE_ATTACH)"); + + waitpid(tid, nullptr, 0); + + DRType dr7 = _GetDR(tid, 7); + // reset BP 2/3 to zero + DRType dr2 = 0; + DRType dr3 = 0; + // breakpoint 2 + SetBits(dr7, 4, 1, 0); + SetBits(dr7, 24, 2, 0); + SetBits(dr7, 26, 2, 0); + // breakpoint 3 + SetBits(dr7, 6, 1, 0); + SetBits(dr7, 28, 2, 0); + SetBits(dr7, 30, 2, 0); + + _SetDR(tid, 2, dr2); + _SetDR(tid, 3, dr3); + _SetDR(tid, 7, dr7); + + rc = ptrace(PTRACE_DETACH, tid, nullptr, nullptr); + if (rc == -1) + perror("ptrace(PTRACE_DETACH)"); + } + + // exit child process + _exit(0); + } + + // wait for child process + waitpid(child, nullptr, 0); +#endif +} diff --git a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h index b86bd9a6..f94365c2 100644 --- a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h +++ b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h @@ -1,33 +1,18 @@ +#pragma once +#include "GDBStub.h" #include -#if defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE -#include -#include -#include +#if defined(ARCH_X86_64) && BOOST_OS_LINUX +#include // helpers for accessing debug register typedef unsigned long DRType; -DRType _GetDR(pid_t tid, int drIndex) -{ - unsigned long v; - v = ptrace (PTRACE_PEEKUSER, tid, offsetof (struct user, u_debugreg[drIndex]), 0); - return (DRType)v; -} - -void _SetDR(pid_t tid, int drIndex, DRType newValue) -{ - unsigned long v = newValue; - ptrace (PTRACE_POKEUSER, tid, offsetof (struct user, u_debugreg[drIndex]), v); -} - +DRType _GetDR(pid_t tid, int drIndex); +void _SetDR(pid_t tid, int drIndex, DRType newValue); +DRType _ReadDR6(); #endif -namespace coreinit -{ - std::vector& OSGetSchedulerThreads(); -} - enum class BreakpointType { BP_SINGLE, @@ -38,59 +23,10 @@ enum class BreakpointType class GDBServer::ExecutionBreakpoint { public: - ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason) - : m_address(address), m_removedAfterInterrupt(false), m_reason(std::move(reason)) - { - if (type == BreakpointType::BP_SINGLE) - { - this->m_pauseThreads = true; - this->m_restoreAfterInterrupt = false; - this->m_deleteAfterAnyInterrupt = false; - this->m_pauseOnNextInterrupt = false; - this->m_visible = visible; - } - else if (type == BreakpointType::BP_PERSISTENT) - { - this->m_pauseThreads = true; - this->m_restoreAfterInterrupt = true; - this->m_deleteAfterAnyInterrupt = false; - this->m_pauseOnNextInterrupt = false; - this->m_visible = visible; - } - else if (type == BreakpointType::BP_RESTORE_POINT) - { - this->m_pauseThreads = false; - this->m_restoreAfterInterrupt = false; - this->m_deleteAfterAnyInterrupt = false; - this->m_pauseOnNextInterrupt = false; - this->m_visible = false; - } - else if (type == BreakpointType::BP_STEP_POINT) - { - this->m_pauseThreads = false; - this->m_restoreAfterInterrupt = false; - this->m_deleteAfterAnyInterrupt = true; - this->m_pauseOnNextInterrupt = true; - this->m_visible = false; - } + ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason); + ~ExecutionBreakpoint(); - this->m_origOpCode = memory_readU32(address); - memory_writeU32(address, DEBUGGER_BP_T_GDBSTUB_TW); - PPCRecompiler_invalidateRange(address, address + 4); - }; - ~ExecutionBreakpoint() - { - memory_writeU32(this->m_address, this->m_origOpCode); - PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); - }; - - [[nodiscard]] uint32 GetVisibleOpCode() const - { - if (this->m_visible) - return memory_readU32(this->m_address); - else - return this->m_origOpCode; - }; + [[nodiscard]] uint32 GetVisibleOpCode() const; [[nodiscard]] bool ShouldBreakThreads() const { return this->m_pauseThreads; @@ -118,18 +54,8 @@ public: return m_reason; }; - void RemoveTemporarily() - { - memory_writeU32(this->m_address, this->m_origOpCode); - PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); - this->m_restoreAfterInterrupt = true; - }; - void Restore() - { - memory_writeU32(this->m_address, DEBUGGER_BP_T_GDBSTUB_TW); - PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4); - this->m_restoreAfterInterrupt = false; - }; + void RemoveTemporarily(); + void Restore(); void PauseOnNextInterrupt() { this->m_pauseOnNextInterrupt = true; @@ -162,115 +88,8 @@ enum class AccessPointType class GDBServer::AccessBreakpoint { public: - AccessBreakpoint(MPTR address, AccessPointType type) - : m_address(address), m_type(type) - { -#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS - for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) - { - HANDLE hThread = (HANDLE)hThreadNH; - CONTEXT ctx{}; - ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; - SuspendThread(hThread); - GetThreadContext(hThread, &ctx); - - // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already - ctx.Dr2 = (DWORD64)memory_getPointerFromVirtualOffset(address); - ctx.Dr3 = (DWORD64)memory_getPointerFromVirtualOffset(address); - // breakpoint 2 - SetBits(ctx.Dr7, 4, 1, 1); // breakpoint #3 enabled: true - SetBits(ctx.Dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write) - SetBits(ctx.Dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes) - // breakpoint 3 - SetBits(ctx.Dr7, 6, 1, 1); // breakpoint #4 enabled: true - SetBits(ctx.Dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write) - SetBits(ctx.Dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes) - - SetThreadContext(hThread, &ctx); - ResumeThread(hThread); - } - // todo: port the following code to all unix platforms, they seem to differ quite a bit -#elif defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE - for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) - { - pid_t pid = (pid_t)(uintptr_t)hThreadNH; - ptrace(PTRACE_ATTACH, pid, nullptr, nullptr); - waitpid(pid, nullptr, 0); - - DRType dr7 = _GetDR(pid, 7); - // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already - DRType dr2 = (uint64)memory_getPointerFromVirtualOffset(address); - DRType dr3 = (uint64)memory_getPointerFromVirtualOffset(address); - // breakpoint 2 - SetBits(dr7, 4, 1, 1); // breakpoint #3 enabled: true - SetBits(dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write) - SetBits(dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes) - // breakpoint 3 - SetBits(dr7, 6, 1, 1); // breakpoint #4 enabled: true - SetBits(dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write) - SetBits(dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes) - - _SetDR(pid, 2, dr2); - _SetDR(pid, 3, dr3); - _SetDR(pid, 7, dr7); - ptrace(PTRACE_DETACH, pid, nullptr, nullptr); - } -#else - cemuLog_log(LogType::Force, "Debugger read/write breakpoints are not supported on non-x86 CPUs yet."); -#endif - }; - ~AccessBreakpoint() - { -#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS - for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) - { - HANDLE hThread = (HANDLE)hThreadNH; - CONTEXT ctx{}; - ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; - SuspendThread(hThread); - GetThreadContext(hThread, &ctx); - - // reset BP 2/3 to zero - ctx.Dr2 = (DWORD64)0; - ctx.Dr3 = (DWORD64)0; - // breakpoint 2 - SetBits(ctx.Dr7, 4, 1, 0); - SetBits(ctx.Dr7, 24, 2, 0); - SetBits(ctx.Dr7, 26, 2, 0); - // breakpoint 3 - SetBits(ctx.Dr7, 6, 1, 0); - SetBits(ctx.Dr7, 28, 2, 0); - SetBits(ctx.Dr7, 30, 2, 0); - SetThreadContext(hThread, &ctx); - ResumeThread(hThread); - } -#elif defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE - for (auto& hThreadNH : coreinit::OSGetSchedulerThreads()) - { - pid_t pid = (pid_t)(uintptr_t)hThreadNH; - ptrace(PTRACE_ATTACH, pid, nullptr, nullptr); - waitpid(pid, nullptr, 0); - - DRType dr7 = _GetDR(pid, 7); - // reset BP 2/3 to zero - DRType dr2 = 0; - DRType dr3 = 0; - // breakpoint 2 - SetBits(dr7, 4, 1, 0); - SetBits(dr7, 24, 2, 0); - SetBits(dr7, 26, 2, 0); - // breakpoint 3 - SetBits(dr7, 6, 1, 0); - SetBits(dr7, 28, 2, 0); - SetBits(dr7, 30, 2, 0); - - _SetDR(pid, 2, dr2); - _SetDR(pid, 3, dr3); - _SetDR(pid, 7, dr7); - ptrace(PTRACE_DETACH, pid, nullptr, nullptr); - } -#endif - }; + AccessBreakpoint(MPTR address, AccessPointType type); + ~AccessBreakpoint(); MPTR GetAddress() const { @@ -284,4 +103,4 @@ public: private: const MPTR m_address; const AccessPointType m_type; -}; \ No newline at end of file +}; diff --git a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp index c8308594..6cddae01 100644 --- a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp +++ b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp @@ -263,6 +263,14 @@ bool GDBServer::Initialize() return false; } + int nodelayEnabled = TRUE; + if (setsockopt(m_server_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelayEnabled, sizeof(nodelayEnabled)) == SOCKET_ERROR) + { + closesocket(m_server_socket); + m_server_socket = INVALID_SOCKET; + return false; + } + memset(&m_server_addr, 0, sizeof(m_server_addr)); m_server_addr.sin_family = AF_INET; m_server_addr.sin_addr.s_addr = htonl(INADDR_ANY); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp index d9b33dca..3701a4d7 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp @@ -5,6 +5,7 @@ #include "Cafe/OS/libs/coreinit/coreinit_Time.h" #include "Cafe/OS/libs/coreinit/coreinit_Alarm.h" #include "Cafe/OS/libs/snd_core/ax.h" +#include "Cafe/HW/Espresso/Debugger/GDBStub.h" #include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h" #include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h" @@ -1153,6 +1154,18 @@ namespace coreinit } } +#if BOOST_OS_LINUX + #include + #include + + std::vector g_schedulerThreadIds; + + std::vector& OSGetSchedulerThreadIds() + { + return g_schedulerThreadIds; + } +#endif + void OSSchedulerCoreEmulationThread(void* _assignedCoreIndex) { SetThreadName(fmt::format("OSSchedulerThread[core={}]", (uintptr_t)_assignedCoreIndex).c_str()); @@ -1160,8 +1173,21 @@ namespace coreinit #if defined(ARCH_X86_64) _mm_setcsr(_mm_getcsr() | 0x8000); // flush denormals to zero #endif + +#if BOOST_OS_LINUX + if (g_gdbstub) + { + // need to allow the GDBStub to attach to our thread + prctl(PR_SET_DUMPABLE, (unsigned long)1); + prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY); + } + + pid_t tid = gettid(); + g_schedulerThreadIds.emplace_back(tid); +#endif + t_schedulerFiber = Fiber::PrepareCurrentThread(); - + // create scheduler idle fiber and switch to it g_idleLoopFiber[t_assignedCoreIndex] = new Fiber(__OSThreadCoreIdle, nullptr, nullptr); cemu_assert_debug(PPCInterpreter_getCurrentInstance() == nullptr); @@ -1211,6 +1237,9 @@ namespace coreinit threadItr.join(); sSchedulerThreads.clear(); g_schedulerThreadHandles.clear(); +#if BOOST_OS_LINUX + g_schedulerThreadIds.clear(); +#endif // clean up all fibers for (auto& it : g_idleLoopFiber) { diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp index 34430e37..cf547110 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp @@ -6,6 +6,9 @@ #include "util/helpers/StringHelpers.h" #include "ExceptionHandler.h" +#include "Cafe/HW/Espresso/Debugger/GDBStub.h" +#include "Cafe/HW/Espresso/Debugger/GDBBreakpoints.h" + #if BOOST_OS_LINUX #include "ELFSymbolTable.h" #endif @@ -61,6 +64,16 @@ void DemangleAndPrintBacktrace(char** backtrace, size_t size) // handle signals that would dump core, print stacktrace and then dump depending on config void handlerDumpingSignal(int sig, siginfo_t *info, void *context) { +#if defined(ARCH_X86_64) && BOOST_OS_LINUX + // Check for hardware breakpoints + if (info->si_signo == SIGTRAP && info->si_code == TRAP_HWBKPT) + { + uint64 dr6 = _ReadDR6(); + g_gdbstub->HandleAccessException(dr6); + return; + } +#endif + if(!CrashLog_Create()) return; // give up if crashlog was already created From 223833cac4512c41a9d53ef630c1bd7b1bb1960c Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:37:10 +0100 Subject: [PATCH 02/12] Update libraries --- dependencies/vcpkg | 2 +- .../vcpkg_overlay_ports/sdl2/deps.patch | 13 -- .../vcpkg_overlay_ports/sdl2/portfile.cmake | 130 ------------------ dependencies/vcpkg_overlay_ports/sdl2/usage | 8 -- .../vcpkg_overlay_ports/sdl2/vcpkg.json | 58 -------- .../vcpkg_overlay_ports_linux/sdl2/deps.patch | 13 -- .../sdl2/portfile.cmake | 130 ------------------ .../vcpkg_overlay_ports_linux/sdl2/usage | 8 -- .../vcpkg_overlay_ports_linux/sdl2/vcpkg.json | 58 -------- src/Cafe/CMakeLists.txt | 6 +- vcpkg.json | 2 +- 11 files changed, 5 insertions(+), 423 deletions(-) delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/deps.patch delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/usage delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/usage delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json diff --git a/dependencies/vcpkg b/dependencies/vcpkg index b81bc3a8..53bef899 160000 --- a/dependencies/vcpkg +++ b/dependencies/vcpkg @@ -1 +1 @@ -Subproject commit b81bc3a83fdbdffe80325eeabb2ec735a1f3c29d +Subproject commit 53bef8994c541b6561884a8395ea35715ece75db diff --git a/dependencies/vcpkg_overlay_ports/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports/sdl2/deps.patch deleted file mode 100644 index a8637d8c..00000000 --- a/dependencies/vcpkg_overlay_ports/sdl2/deps.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake -index 65a98efbe..2f99f28f1 100644 ---- a/cmake/sdlchecks.cmake -+++ b/cmake/sdlchecks.cmake -@@ -352,7 +352,7 @@ endmacro() - # - HAVE_SDL_LOADSO opt - macro(CheckLibSampleRate) - if(SDL_LIBSAMPLERATE) -- find_package(SampleRate QUIET) -+ find_package(SampleRate CONFIG REQUIRED) - if(SampleRate_FOUND AND TARGET SampleRate::samplerate) - set(HAVE_LIBSAMPLERATE TRUE) - set(HAVE_LIBSAMPLERATE_H TRUE) diff --git a/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake deleted file mode 100644 index 39a724c5..00000000 --- a/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake +++ /dev/null @@ -1,130 +0,0 @@ -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO libsdl-org/SDL - REF "release-${VERSION}" - SHA512 90858ae8c5fdddd5e13724e05ad0970e11bbab1df8a0201c3f4ce354dc6018e5d4ab7279402a263c716aacdaa52745f78531dc225d48d790ee9307e2f6198695 - HEAD_REF main - PATCHES - deps.patch -) - -string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC) -string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED) -string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT) - -vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS - FEATURES - vulkan SDL_VULKAN - x11 SDL_X11 - wayland SDL_WAYLAND - samplerate SDL_LIBSAMPLERATE - ibus SDL_IBUS -) - -if ("x11" IN_LIST FEATURES) - message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n") -endif() -if ("wayland" IN_LIST FEATURES) - message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n") -endif() -if ("ibus" IN_LIST FEATURES) - message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n") -endif() - -if(VCPKG_TARGET_IS_UWP) - set(configure_opts WINDOWS_USE_MSBUILD) -endif() - -vcpkg_cmake_configure( - SOURCE_PATH "${SOURCE_PATH}" - ${configure_opts} - OPTIONS ${FEATURE_OPTIONS} - -DSDL_STATIC=${SDL_STATIC} - -DSDL_SHARED=${SDL_SHARED} - -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT} - -DSDL_LIBC=ON - -DSDL_TEST=OFF - -DSDL_INSTALL_CMAKEDIR="cmake" - -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON - -DSDL_LIBSAMPLERATE_SHARED=OFF - MAYBE_UNUSED_VARIABLES - SDL_FORCE_STATIC_VCRT -) - -vcpkg_cmake_install() -vcpkg_cmake_config_fixup(CONFIG_PATH cmake) - -file(REMOVE_RECURSE - "${CURRENT_PACKAGES_DIR}/debug/include" - "${CURRENT_PACKAGES_DIR}/debug/share" - "${CURRENT_PACKAGES_DIR}/bin/sdl2-config" - "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config" - "${CURRENT_PACKAGES_DIR}/SDL2.framework" - "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework" - "${CURRENT_PACKAGES_DIR}/share/licenses" - "${CURRENT_PACKAGES_DIR}/share/aclocal" -) - -file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*") -if(NOT BINS) - file(REMOVE_RECURSE - "${CURRENT_PACKAGES_DIR}/bin" - "${CURRENT_PACKAGES_DIR}/debug/bin" - ) -endif() - -if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link") - file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link") - file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib") - endif() - - file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake") - foreach(SHARE_FILE ${SHARE_FILES}) - vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main") - endforeach() -endif() - -vcpkg_copy_pdbs() - -set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)") -set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)") -file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX}) -file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX}) -string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}") -string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}") - -if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ") -endif() - -if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ") - endif() -endif() - -if(VCPKG_TARGET_IS_UWP) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:") - endif() -endif() - -vcpkg_fixup_pkgconfig() - -file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") -vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt") diff --git a/dependencies/vcpkg_overlay_ports/sdl2/usage b/dependencies/vcpkg_overlay_ports/sdl2/usage deleted file mode 100644 index 1cddcd46..00000000 --- a/dependencies/vcpkg_overlay_ports/sdl2/usage +++ /dev/null @@ -1,8 +0,0 @@ -sdl2 provides CMake targets: - - find_package(SDL2 CONFIG REQUIRED) - target_link_libraries(main - PRIVATE - $ - $,SDL2::SDL2,SDL2::SDL2-static> - ) diff --git a/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json deleted file mode 100644 index de2eb9b9..00000000 --- a/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "sdl2", - "version": "2.26.5", - "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.", - "homepage": "https://www.libsdl.org/download-2.0.php", - "license": "Zlib", - "dependencies": [ - { - "name": "vcpkg-cmake", - "host": true - }, - { - "name": "vcpkg-cmake-config", - "host": true - } - ], - "default-features": [ - "base" - ], - "features": { - "base": { - "description": "Base functionality for SDL", - "dependencies": [ - { - "name": "sdl2", - "default-features": false, - "features": [ - "ibus", - "wayland", - "x11" - ], - "platform": "linux" - } - ] - }, - "ibus": { - "description": "Build with ibus IME support", - "supports": "linux" - }, - "samplerate": { - "description": "Use libsamplerate for audio rate conversion", - "dependencies": [ - "libsamplerate" - ] - }, - "vulkan": { - "description": "Vulkan functionality for SDL" - }, - "wayland": { - "description": "Build with Wayland support", - "supports": "linux" - }, - "x11": { - "description": "Build with X11 support", - "supports": "!windows" - } - } -} diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch deleted file mode 100644 index a8637d8c..00000000 --- a/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake -index 65a98efbe..2f99f28f1 100644 ---- a/cmake/sdlchecks.cmake -+++ b/cmake/sdlchecks.cmake -@@ -352,7 +352,7 @@ endmacro() - # - HAVE_SDL_LOADSO opt - macro(CheckLibSampleRate) - if(SDL_LIBSAMPLERATE) -- find_package(SampleRate QUIET) -+ find_package(SampleRate CONFIG REQUIRED) - if(SampleRate_FOUND AND TARGET SampleRate::samplerate) - set(HAVE_LIBSAMPLERATE TRUE) - set(HAVE_LIBSAMPLERATE_H TRUE) diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake deleted file mode 100644 index 39a724c5..00000000 --- a/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake +++ /dev/null @@ -1,130 +0,0 @@ -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO libsdl-org/SDL - REF "release-${VERSION}" - SHA512 90858ae8c5fdddd5e13724e05ad0970e11bbab1df8a0201c3f4ce354dc6018e5d4ab7279402a263c716aacdaa52745f78531dc225d48d790ee9307e2f6198695 - HEAD_REF main - PATCHES - deps.patch -) - -string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC) -string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED) -string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT) - -vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS - FEATURES - vulkan SDL_VULKAN - x11 SDL_X11 - wayland SDL_WAYLAND - samplerate SDL_LIBSAMPLERATE - ibus SDL_IBUS -) - -if ("x11" IN_LIST FEATURES) - message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n") -endif() -if ("wayland" IN_LIST FEATURES) - message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n") -endif() -if ("ibus" IN_LIST FEATURES) - message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n") -endif() - -if(VCPKG_TARGET_IS_UWP) - set(configure_opts WINDOWS_USE_MSBUILD) -endif() - -vcpkg_cmake_configure( - SOURCE_PATH "${SOURCE_PATH}" - ${configure_opts} - OPTIONS ${FEATURE_OPTIONS} - -DSDL_STATIC=${SDL_STATIC} - -DSDL_SHARED=${SDL_SHARED} - -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT} - -DSDL_LIBC=ON - -DSDL_TEST=OFF - -DSDL_INSTALL_CMAKEDIR="cmake" - -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON - -DSDL_LIBSAMPLERATE_SHARED=OFF - MAYBE_UNUSED_VARIABLES - SDL_FORCE_STATIC_VCRT -) - -vcpkg_cmake_install() -vcpkg_cmake_config_fixup(CONFIG_PATH cmake) - -file(REMOVE_RECURSE - "${CURRENT_PACKAGES_DIR}/debug/include" - "${CURRENT_PACKAGES_DIR}/debug/share" - "${CURRENT_PACKAGES_DIR}/bin/sdl2-config" - "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config" - "${CURRENT_PACKAGES_DIR}/SDL2.framework" - "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework" - "${CURRENT_PACKAGES_DIR}/share/licenses" - "${CURRENT_PACKAGES_DIR}/share/aclocal" -) - -file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*") -if(NOT BINS) - file(REMOVE_RECURSE - "${CURRENT_PACKAGES_DIR}/bin" - "${CURRENT_PACKAGES_DIR}/debug/bin" - ) -endif() - -if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link") - file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link") - file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib") - endif() - - file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake") - foreach(SHARE_FILE ${SHARE_FILES}) - vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main") - endforeach() -endif() - -vcpkg_copy_pdbs() - -set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)") -set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)") -file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX}) -file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX}) -string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}") -string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}") - -if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ") -endif() - -if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ") - endif() -endif() - -if(VCPKG_TARGET_IS_UWP) - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:") - endif() - if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d") - vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:") - endif() -endif() - -vcpkg_fixup_pkgconfig() - -file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") -vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt") diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/usage b/dependencies/vcpkg_overlay_ports_linux/sdl2/usage deleted file mode 100644 index 1cddcd46..00000000 --- a/dependencies/vcpkg_overlay_ports_linux/sdl2/usage +++ /dev/null @@ -1,8 +0,0 @@ -sdl2 provides CMake targets: - - find_package(SDL2 CONFIG REQUIRED) - target_link_libraries(main - PRIVATE - $ - $,SDL2::SDL2,SDL2::SDL2-static> - ) diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json deleted file mode 100644 index de2eb9b9..00000000 --- a/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "sdl2", - "version": "2.26.5", - "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.", - "homepage": "https://www.libsdl.org/download-2.0.php", - "license": "Zlib", - "dependencies": [ - { - "name": "vcpkg-cmake", - "host": true - }, - { - "name": "vcpkg-cmake-config", - "host": true - } - ], - "default-features": [ - "base" - ], - "features": { - "base": { - "description": "Base functionality for SDL", - "dependencies": [ - { - "name": "sdl2", - "default-features": false, - "features": [ - "ibus", - "wayland", - "x11" - ], - "platform": "linux" - } - ] - }, - "ibus": { - "description": "Build with ibus IME support", - "supports": "linux" - }, - "samplerate": { - "description": "Use libsamplerate for audio rate conversion", - "dependencies": [ - "libsamplerate" - ] - }, - "vulkan": { - "description": "Vulkan functionality for SDL" - }, - "wayland": { - "description": "Build with Wayland support", - "supports": "linux" - }, - "x11": { - "description": "Build with X11 support", - "supports": "!windows" - } - } -} diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 9e20bb33..20853789 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -535,9 +535,9 @@ endif() if (ENABLE_NSYSHID_LIBUSB) if (ENABLE_VCPKG) - find_package(libusb CONFIG REQUIRED) - target_include_directories(CemuCafe PRIVATE ${LIBUSB_INCLUDE_DIRS}) - target_link_libraries(CemuCafe PRIVATE ${LIBUSB_LIBRARIES}) + find_package(PkgConfig REQUIRED) + pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0) + target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb) else () find_package(libusb MODULE REQUIRED) target_link_libraries(CemuCafe PRIVATE libusb::libusb) diff --git a/vcpkg.json b/vcpkg.json index d14a1a8a..48742b4a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "name": "cemu", "version-string": "1.0", - "builtin-baseline": "b81bc3a83fdbdffe80325eeabb2ec735a1f3c29d", + "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db", "dependencies": [ "pugixml", "zlib", From 9b0a1d53dc449fedebd5eb6255a312aa334ffad9 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:40:29 +0100 Subject: [PATCH 03/12] Latte: Fix syntax error in generated GLSL --- .../LatteDecompilerEmitGLSL.cpp | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp index aa7b7162..f3d2c7a8 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp @@ -246,6 +246,22 @@ static void _appendPVPS(LatteDecompilerShaderContext* shaderContext, StringBuf* _appendChannel(src, aluUnit); } +std::string _FormatFloatAsGLSLConstant(float f) +{ + char floatAsStr[64]; + size_t floatAsStrLen = fmt::format_to_n(floatAsStr, 64, "{:#}", f).size; + size_t floatAsStrLenOrg = floatAsStrLen; + if(floatAsStrLen > 0 && floatAsStr[floatAsStrLen-1] == '.') + { + floatAsStr[floatAsStrLen] = '0'; + floatAsStrLen++; + } + cemu_assert(floatAsStrLen < 50); // constant suspiciously long? + floatAsStr[floatAsStrLen] = '\0'; + cemu_assert_debug(floatAsStrLen >= 3); // shortest possible form is "0.0" + return floatAsStr; +} + // tracks PV/PS and register backups struct ALUClauseTemporariesState { @@ -926,15 +942,7 @@ void _emitOperandInputCode(LatteDecompilerShaderContext* shaderContext, LatteDec exponent -= 127; if ((constVal & 0xFF) == 0 && exponent >= -10 && exponent <= 10) { - char floatAsStr[32]; - size_t floatAsStrLen = fmt::format_to_n(floatAsStr, 32, "{:#}", *(float*)&constVal).size; - if(floatAsStrLen > 0 && floatAsStr[floatAsStrLen-1] == '.') - { - floatAsStr[floatAsStrLen] = '0'; - floatAsStrLen++; - } - cemu_assert_debug(floatAsStrLen >= 3); // shortest possible form is "0.0" - src->add(std::string_view(floatAsStr, floatAsStrLen)); + src->add(_FormatFloatAsGLSLConstant(*(float*)&constVal)); } else src->addFmt("intBitsToFloat(0x{:08x})", constVal); @@ -2561,13 +2569,11 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt // lod or lod bias parameter if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L) { + src->add(","); if(texOpcode == GPU7_TEX_INST_SAMPLE_LB) - src->addFmt("{}", (float)texInstruction->textureFetch.lodBias / 16.0f); + src->add(_FormatFloatAsGLSLConstant((float)texInstruction->textureFetch.lodBias / 16.0f)); else - { - src->add(","); _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT); - } } else if( texOpcode == GPU7_TEX_INST_SAMPLE_LZ || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ ) { From f39a5e757b1d82c509c12ba67e88916cf7341573 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:14:42 +0100 Subject: [PATCH 04/12] Add "Open MLC folder" option Also updated Patron supporter list --- src/gui/MainWindow.cpp | 14 ++++++++++---- src/gui/MainWindow.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 92594d00..dc9ff0a8 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -75,6 +75,7 @@ enum MAINFRAME_MENU_ID_FILE_LOAD = 20100, MAINFRAME_MENU_ID_FILE_INSTALL_UPDATE, MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, + MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER, MAINFRAME_MENU_ID_FILE_EXIT, MAINFRAME_MENU_ID_FILE_END_EMULATION, MAINFRAME_MENU_ID_FILE_RECENT_0, @@ -166,7 +167,8 @@ EVT_MOVE(MainWindow::OnMove) // file menu EVT_MENU(MAINFRAME_MENU_ID_FILE_LOAD, MainWindow::OnFileMenu) EVT_MENU(MAINFRAME_MENU_ID_FILE_INSTALL_UPDATE, MainWindow::OnInstallUpdate) -EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, MainWindow::OnOpenCemuFolder) +EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, MainWindow::OnOpenFolder) +EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER, MainWindow::OnOpenFolder) EVT_MENU(MAINFRAME_MENU_ID_FILE_EXIT, MainWindow::OnFileExit) EVT_MENU(MAINFRAME_MENU_ID_FILE_END_EMULATION, MainWindow::OnFileMenu) EVT_MENU_RANGE(MAINFRAME_MENU_ID_FILE_RECENT_0 + 0, MAINFRAME_MENU_ID_FILE_RECENT_LAST, MainWindow::OnFileMenu) @@ -684,9 +686,12 @@ void MainWindow::OnFileMenu(wxCommandEvent& event) } } -void MainWindow::OnOpenCemuFolder(wxCommandEvent& event) +void MainWindow::OnOpenFolder(wxCommandEvent& event) { - wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetUserDataPath())); + if(event.GetId() == MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER) + wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetUserDataPath())); + else if(event.GetId() == MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER) + wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetMlcPath())); } void MainWindow::OnInstallUpdate(wxCommandEvent& event) @@ -2015,7 +2020,7 @@ public: , "Faris Leonhart", "MahvZero", "PlaguedGuardian", "Stuffie", "CaptainLester", "Qtech", "Zaurexus", "Leonidas", "Artifesto" , "Alca259", "SirWestofAsh", "Loli Co.", "The Technical Revolutionary", "MegaYama", "mitori", "Seymordius", "Adrian Josh Cruz", "Manuel Hoenings", "Just A Jabb" , "pgantonio", "CannonXIII", "Lonewolf00708", "AlexsDesign.com", "NoskLo", "MrSirHaku", "xElite_V AKA William H. Johnson", "Zalnor", "Pig", "James \"SE4LS\"", "DairyOrange", "Horoko Lawrence", "bloodmc", "Officer Jenny", "Quasar", "Postposterous", "Jake Jackson", "Kaydax", "CthePredatorG" - , "Hengi", "Pyrochaser"}; + , "Hengi", "Pyrochaser", "luma.x3"}; wxString nameListLeft, nameListRight; for (size_t i = 0; i < patreonSupporterNames.size(); i++) @@ -2107,6 +2112,7 @@ void MainWindow::RecreateMenu() } m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, _("&Open Cemu folder")); + m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER, _("&Open MLC folder")); m_fileMenu->AppendSeparator(); m_exitMenuItem = m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_EXIT, _("&Exit")); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 07189b52..25100b72 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -92,7 +92,7 @@ public: void OnMouseWheel(wxMouseEvent& event); void OnClose(wxCloseEvent& event); void OnFileMenu(wxCommandEvent& event); - void OnOpenCemuFolder(wxCommandEvent& event); + void OnOpenFolder(wxCommandEvent& event); void OnLaunchFromFile(wxLaunchGameEvent& event); void OnInstallUpdate(wxCommandEvent& event); void OnFileExit(wxCommandEvent& event); From f58b260cbd566f1f76506246b3b9cd247b1ca511 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:31:59 +0100 Subject: [PATCH 05/12] Fix macos missing dylib file --- src/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de9a6600..b7711018 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,7 +78,7 @@ if (MACOS_BUNDLE) set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu") set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION}) set(MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION}) - set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2023 Cemu Project") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project") set(MACOSX_BUNDLE_CATEGORY "public.app-category.games") set(MACOSX_MINIMUM_SYSTEM_VERSION "12.0") @@ -100,6 +100,9 @@ if (MACOS_BUNDLE) add_custom_command (TARGET CemuBin POST_BUILD COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") + + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") endif() set_target_properties(CemuBin PROPERTIES From 7e778042ee0aa053f6daa6a0c23f7ff0c74b5f6e Mon Sep 17 00:00:00 2001 From: Live session user Date: Mon, 15 Jan 2024 17:46:56 -0800 Subject: [PATCH 06/12] Fix macos missing dylib file --- CMakeLists.txt | 2 + dependencies/vcpkg_overlay_ports_mac/.gitkeep | 0 .../libusb/portfile.cmake | 71 +++++++++++++++++++ .../vcpkg_overlay_ports_mac/libusb/usage | 5 ++ .../vcpkg_overlay_ports_mac/libusb/vcpkg.json | 8 +++ src/CMakeLists.txt | 11 ++- 6 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 dependencies/vcpkg_overlay_ports_mac/.gitkeep create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/usage create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index c988508c..ec6abedc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ endif() if (ENABLE_VCPKG) if(UNIX AND NOT APPLE) set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux") + elseif(APPLE) + set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_mac") else() set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports") endif() diff --git a/dependencies/vcpkg_overlay_ports_mac/.gitkeep b/dependencies/vcpkg_overlay_ports_mac/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake b/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake new file mode 100644 index 00000000..7b76bba0 --- /dev/null +++ b/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake @@ -0,0 +1,71 @@ +set(VCPKG_LIBRARY_LINKAGE dynamic) + +if(VCPKG_TARGET_IS_LINUX) + message("${PORT} currently requires the following tools and libraries from the system package manager:\n autoreconf\n libudev\n\nThese can be installed on Ubuntu systems via apt-get install autoconf libudev-dev") +endif() + +set(VERSION 1.0.26) +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO libusb/libusb + REF fcf0c710ef5911ae37fbbf1b39d48a89f6f14e8a # v1.0.26.11791 2023-03-12 + SHA512 0aa6439f7988487adf2a3bff473fec80b5c722a47f117a60696d2aa25c87cc3f20fb6aaca7c66e49be25db6a35eb0bb5f71ed7b211d1b8ee064c5d7f1b985c73 + HEAD_REF master +) + +if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) + + if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + set(LIBUSB_PROJECT_TYPE dll) + else() + set(LIBUSB_PROJECT_TYPE static) + endif() + + # The README.md file in the archive is a symlink to README + # which causes issues with the windows MSBUILD process + file(REMOVE "${SOURCE_PATH}/README.md") + + vcpkg_msbuild_install( + SOURCE_PATH "${SOURCE_PATH}" + PROJECT_SUBPATH msvc/libusb_${LIBUSB_PROJECT_TYPE}.vcxproj + ) + + file(INSTALL "${SOURCE_PATH}/libusb/libusb.h" DESTINATION "${CURRENT_PACKAGES_DIR}/include/libusb-1.0") + set(prefix "") + set(exec_prefix [[${prefix}]]) + set(libdir [[${prefix}/lib]]) + set(includedir [[${prefix}/include]]) + configure_file("${SOURCE_PATH}/libusb-1.0.pc.in" "${CURRENT_PACKAGES_DIR}/lib/pkgconfig/libusb-1.0.pc" @ONLY) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/libusb-1.0.pc" " -lusb-1.0" " -llibusb-1.0") + if(NOT VCPKG_BUILD_TYPE) + set(includedir [[${prefix}/../include]]) + configure_file("${SOURCE_PATH}/libusb-1.0.pc.in" "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libusb-1.0.pc" @ONLY) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libusb-1.0.pc" " -lusb-1.0" " -llibusb-1.0") + endif() +else() + vcpkg_list(SET MAKE_OPTIONS) + vcpkg_list(SET LIBUSB_LINK_LIBRARIES) + if(VCPKG_TARGET_IS_EMSCRIPTEN) + vcpkg_list(APPEND MAKE_OPTIONS BUILD_TRIPLET --host=wasm32) + endif() + if("udev" IN_LIST FEATURES) + vcpkg_list(APPEND MAKE_OPTIONS "--enable-udev") + vcpkg_list(APPEND LIBUSB_LINK_LIBRARIES udev) + else() + vcpkg_list(APPEND MAKE_OPTIONS "--disable-udev") + endif() + vcpkg_configure_make( + SOURCE_PATH "${SOURCE_PATH}" + AUTOCONFIG + OPTIONS + ${MAKE_OPTIONS} + "--enable-examples-build=no" + "--enable-tests-build=no" + ) + vcpkg_install_make() +endif() + +vcpkg_fixup_pkgconfig() + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/COPYING") diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/usage b/dependencies/vcpkg_overlay_ports_mac/libusb/usage new file mode 100644 index 00000000..87e6e860 --- /dev/null +++ b/dependencies/vcpkg_overlay_ports_mac/libusb/usage @@ -0,0 +1,5 @@ +libusb can be imported via CMake FindPkgConfig module: + find_package(PkgConfig REQUIRED) + pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0) + + target_link_libraries(main PRIVATE PkgConfig::libusb) diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json b/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json new file mode 100644 index 00000000..efc70f3d --- /dev/null +++ b/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json @@ -0,0 +1,8 @@ +{ + "name": "libusb", + "version": "1.0.26.11791", + "port-version": 7, + "description": "a cross-platform library to access USB devices", + "homepage": "https://github.com/libusb/libusb", + "license": "LGPL-2.1-or-later" +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7711018..7442e37c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -96,13 +96,10 @@ if (MACOS_BUNDLE) endforeach(folder) add_custom_command (TARGET CemuBin POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib") - - add_custom_command (TARGET CemuBin POST_BUILD - COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") - - add_custom_command (TARGET CemuBin POST_BUILD - COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") + COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib" + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib" + COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}" + COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") endif() set_target_properties(CemuBin PROPERTIES From f899ab7c34035bc3746112b6459bd15a4a181dd4 Mon Sep 17 00:00:00 2001 From: Colin Kinloch Date: Wed, 17 Jan 2024 01:09:56 +0000 Subject: [PATCH 07/12] Vulkan: Check for 0 size before wayland resize Fixes "Launching games directly with the --title-id argument doesn't work in Wayland" (#999) --- src/gui/canvas/VulkanCanvas.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/canvas/VulkanCanvas.cpp b/src/gui/canvas/VulkanCanvas.cpp index eb56b3c4..8b0c8506 100644 --- a/src/gui/canvas/VulkanCanvas.cpp +++ b/src/gui/canvas/VulkanCanvas.cpp @@ -66,6 +66,10 @@ void VulkanCanvas::OnPaint(wxPaintEvent& event) void VulkanCanvas::OnResize(wxSizeEvent& event) { + const wxSize size = GetSize(); + if (size.GetWidth() == 0 || size.GetHeight() == 0) + return; + #if BOOST_OS_LINUX && HAS_WAYLAND if(m_subsurface) { @@ -73,9 +77,6 @@ void VulkanCanvas::OnResize(wxSizeEvent& event) m_subsurface->setSize(sRect.GetX(), sRect.GetY(), sRect.GetWidth(), sRect.GetHeight()); } #endif - const wxSize size = GetSize(); - if (size.GetWidth() == 0 || size.GetHeight() == 0) - return; const wxRect refreshRect(size); RefreshRect(refreshRect, false); From e53c63b828e856cb4bf11729cdf90fe12544ac9f Mon Sep 17 00:00:00 2001 From: Colin Kinloch Date: Wed, 17 Jan 2024 01:18:07 +0000 Subject: [PATCH 08/12] Flatpak: Create shortcuts that launch flatpak --- src/gui/components/wxGameList.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp index 2c78ea3c..5ceaf71f 100644 --- a/src/gui/components/wxGameList.cpp +++ b/src/gui/components/wxGameList.cpp @@ -1235,6 +1235,7 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo) { const auto title_id = gameInfo.GetBaseTitleId(); const auto title_name = gameInfo.GetTitleName(); auto exe_path = ActiveSettings::GetExecutablePath(); + const char *flatpak_id = getenv("FLATPAK_ID"); // GetExecutablePath returns the AppImage's temporary mount location, instead of its actual path wxString appimage_path; @@ -1292,22 +1293,31 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo) { } } } + + std::string desktop_exec_entry; + if (flatpak_id) + desktop_exec_entry = fmt::format("/usr/bin/flatpak run {0} --title-id {1:016x}", flatpak_id, title_id); + else + desktop_exec_entry = fmt::format("{0:?} --title-id {1:016x}", _pathToUtf8(exe_path), title_id); + // 'Icon' accepts spaces in file name, does not accept quoted file paths // 'Exec' does not accept non-escaped spaces, and can accept quoted file paths - const auto desktop_entry_string = + auto desktop_entry_string = fmt::format("[Desktop Entry]\n" "Name={0}\n" "Comment=Play {0} on Cemu\n" - "Exec={1:?} --title-id {2:016x}\n" - "Icon={3}\n" + "Exec={1}\n" + "Icon={2}\n" "Terminal=false\n" "Type=Application\n" - "Categories=Game;", + "Categories=Game;\n", title_name, - _pathToUtf8(exe_path), - title_id, + desktop_exec_entry, _pathToUtf8(icon_path.value_or(""))); + if (flatpak_id) + desktop_entry_string += fmt::format("X-Flatpak={}\n", flatpak_id); + std::ofstream output_stream(output_path); if (!output_stream.good()) { From 72aacbdcecc064ea7c3b158c433e4803496ac296 Mon Sep 17 00:00:00 2001 From: Mike Lothian Date: Fri, 19 Jan 2024 01:03:57 +0000 Subject: [PATCH 09/12] Vulkan: Don't use glslang internal headers Signed-off-by: Mike Lothian --- src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp | 3 +-- src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp index e9936c43..72a1be4c 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp @@ -3,7 +3,6 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h" #include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h" -#include #include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" @@ -91,4 +90,4 @@ PipelineInfo::~PipelineInfo() // remove from cache VulkanRenderer::GetInstance()->unregisterGraphicsPipeline(this); -} \ No newline at end of file +} diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 44214606..616f57e2 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -26,7 +26,7 @@ #include "Cafe/HW/Latte/Core/LatteTiming.h" // vsync control -#include +#include #include From 18679af4ec641a4c59753d54751dcab257777eef Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Fri, 19 Jan 2024 14:07:17 +0000 Subject: [PATCH 10/12] Ignore Wii U pro controller --- src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index a5701f56..db185675 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -1,9 +1,11 @@ #include "HidapiWiimote.h" +#include static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; static constexpr uint16 WIIMOTE_MP_PRODUCT_ID = 0x0330; static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 22; +static constexpr auto PRO_CONTROLLER_NAME = L"Nintendo RVL-CNT-01-UC"; HidapiWiimote::HidapiWiimote(hid_device* dev, std::string_view path) : m_handle(dev), m_path(path) { @@ -30,6 +32,8 @@ std::vector HidapiWiimote::get_devices() { for (auto it = device_enumeration; it != nullptr; it = it->next){ if (it->product_id != WIIMOTE_PRODUCT_ID && it->product_id != WIIMOTE_MP_PRODUCT_ID) continue; + if (std::wcscmp(it->product_string, PRO_CONTROLLER_NAME) == 0) + continue; auto dev = hid_open_path(it->path); if (!dev){ cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr))); From 4e4ac0de51b82c455aec71060c109f9e5a1888d9 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Fri, 19 Jan 2024 23:32:24 +0100 Subject: [PATCH 11/12] CI: For the Windows build use as many cores as available --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d23faa31..3c01ba7a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -183,7 +183,7 @@ jobs: - name: "Build Cemu" run: | cd build - cmake --build . --config ${{ env.BUILD_MODE }} -j 2 + cmake --build . --config ${{ env.BUILD_MODE }} - name: Prepare artifact if: ${{ inputs.deploymode == 'release' }} From ca01e923bf03573d5023feb0f4464ce015910ea6 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sat, 20 Jan 2024 00:33:36 +0100 Subject: [PATCH 12/12] Update issue templates --- .../bug-report-feature-request.md | 34 --------- .github/ISSUE_TEMPLATE/config.yml | 2 +- .../ISSUE_TEMPLATE/emulation_bug_report.yaml | 69 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_report.yaml | 28 ++++++++ 4 files changed, 98 insertions(+), 35 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-report-feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/emulation_bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature_report.yaml diff --git a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md b/.github/ISSUE_TEMPLATE/bug-report-feature-request.md deleted file mode 100644 index 61bd5d06..00000000 --- a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: Bug Report / Feature Request -about: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with Cemu or you are requesting a feature you believe would make Cemu better. -title: '' -labels: '' -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d33d87ed..d71e22d0 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,4 @@ blank_issues_enabled: false contact_links: - name: Cemu Discord url: https://discord.com/invite/5psYsup - about: If you are experiencing an issue with Cemu, and you need tech support, or if you have a general question, try asking in the official Cemu Discord linked here. Piracy is not allowed. + about: If you need technical support with Cemu or have other questions the best place to ask is on the official Cemu Discord linked here diff --git a/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml b/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml new file mode 100644 index 00000000..75928607 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml @@ -0,0 +1,69 @@ +# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +name: Bug Report +description: Report an issue with Cemu emulator +title: "Enter a title for the bug report here" +labels: bug +body: + - type: markdown + id: md_readme + attributes: + value: | + ## Important: Read First + + If you discovered a bug you can report it here. Please make sure of the following first: + - That you are using the latest version of Cemu + - Only report something if you are sure it's a bug and not any technical issue on your end. For troubleshooting help see the [links page](https://github.com/cemu-project/Cemu#links) + - Problems specific to a single game should be reported on the [compatibility wiki](https://wiki.cemu.info/wiki/Main_Page) instead + - Verify that your problem isn't already mentioned on the [issue tracker](https://github.com/cemu-project/Cemu/issues) + + Additionally, be aware that graphic packs can also causes issues. There is a separate issue tracker for graphic pack bugs over at the [graphic pack repository](https://github.com/cemu-project/cemu_graphic_packs) + - type: textarea + id: current_behavior + attributes: + label: Current Behavior + description: "What the bug is, in a brief description" + validations: + required: true + - type: textarea + id: expected_behavior + attributes: + label: Expected Behavior + description: "What did you expect to happen?" + validations: + required: true + + - type: textarea + id: steps_to_reproduce + attributes: + label: Steps to Reproduce + description: "How to reproduce the issue" + validations: + required: true + - type: textarea + id: sys_info + attributes: + label: System Info (Optional) + description: "Your PC specifications. Usually only the operating system and graphics card is important. But feel free to add more info." + placeholder: | + Info + OS: Windows 10 + GPU: NVIDIA GeForce RTX 4090 + value: | + OS: + GPU: + - type: textarea + id: emulation_settings + attributes: + label: Emulation Settings (Optional) + description: | + Any non-default settings. You can leave this empty if you didn't change anything other than input settings. + validations: + required: false + - type: textarea + id: logs_files + attributes: + label: "Logs (Optional)" + description: | + "Attach `log.txt` from your Cemu folder (*File > Open Cemu folder*)". + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_report.yaml b/.github/ISSUE_TEMPLATE/feature_report.yaml new file mode 100644 index 00000000..a5d8705c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_report.yaml @@ -0,0 +1,28 @@ +# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +name: Feature suggestion +description: Suggest a new feature +title: "Enter a title for the suggestion here" +labels: feature request +body: + - type: markdown + id: md_readme + attributes: + value: | + ## Important: Read First + + While we appreciate suggestions, it is important to note that we are a very small team and there are already many more ideas than we could ever implement in the near future. Therefore, please only suggest something if you believe it is a great addition and the idea is reasonably unique. + + *Avoid* to create suggestions for: + - Overly obvious features ("Game xyz does not work and should be fixed", "Wiimote support should be improved", "You should add an Android port", "Copy feature xyz from another emulator", "A button to pause/stop emulation") + - Niche features which are only interesting to a tiny percentage of users + - Large scale features ("Add a Metal backend for MacOS", "Add ARM support", "Add savestates") + + Note that this doesn't mean we aren't interested in these ideas, but rather we likely have them planned anyway and it's mostly up to finding the time to implement them. + If you believe your idea is worthwhile even if it doesn't meet all the criteria above, you can still try suggesting it but we might close it. + - type: textarea + id: idea_suggestion + attributes: + label: Your suggestion + description: "Describe what your suggestion is in as much detail as possible" + validations: + required: true