From cf295952b68eef4466b46b0b29c4f7d2c72a5cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Bergstr=C3=B6m?= Date: Sat, 1 Jul 2023 19:30:11 +0200 Subject: [PATCH] Make all project targets compile on Intel MacOS (#2780) --- .github/workflows/macos-build-clang.yaml | 14 ++------- README.md | 26 +++++++++++++++++ common/cross_os_debug/xdbg.cpp | 11 ++++++-- common/cross_sockets/XSocketServer.cpp | 23 +++++++++------ common/util/FileUtil.cpp | 22 +++++++++++++-- game/common/vu.h | 2 ++ game/kernel/asm_funcs.asm | 29 +++++++++---------- game/kernel/common/kscheme.cpp | 33 +++++++++++++++------- game/kernel/jak1/kscheme.cpp | 36 ++++++++++++++++-------- game/kernel/jak2/kscheme.cpp | 36 ++++++++++++++++-------- game/mips2c/mips2c_private.h | 18 ++++++++---- game/mips2c/mips2c_table.cpp | 10 +++++-- game/mips2c/readme.md | 4 +-- game/sound/CMakeLists.txt | 2 ++ 14 files changed, 184 insertions(+), 82 deletions(-) diff --git a/.github/workflows/macos-build-clang.yaml b/.github/workflows/macos-build-clang.yaml index 6d34e41eab..9b2526cd55 100644 --- a/.github/workflows/macos-build-clang.yaml +++ b/.github/workflows/macos-build-clang.yaml @@ -45,18 +45,8 @@ jobs: -DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache \ -DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache - # Disabled for now, not all build targets are valid - # - name: Build Project - # run: cmake --build build --parallel $((`sysctl -n hw.logicalcpu`)) - - # Temporary, selectively build those that work - - name: Build Working Targets - run: | - cmake --build build --target extractor --parallel $((`sysctl -n hw.logicalcpu`)) && \ - cmake --build build --target offline-test --parallel $((`sysctl -n hw.logicalcpu`)) && \ - cmake --build build --target decompiler --parallel $((`sysctl -n hw.logicalcpu`)) && \ - cmake --build build --target lsp --parallel $((`sysctl -n hw.logicalcpu`)) && \ - cmake --build build --target goalc --parallel $((`sysctl -n hw.logicalcpu`)) + - name: Build Project + run: cmake --build build --parallel $((`sysctl -n hw.logicalcpu`)) - name: Run Tests continue-on-error: true # until macOS is stable diff --git a/README.md b/README.md index bf6631aee1..cef6ea7fb5 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ - [Windows](#windows) - [Required Software](#required-software) - [Using Visual Studio](#using-visual-studio) + - [MacOS](#macos) + - [Intel Based](#intel-based) + - [Apple Silicon](#apple-silicon) - [Building and Running the Game](#building-and-running-the-game) - [Extract Assets](#extract-assets) - [Build the Game](#build-the-game) @@ -234,6 +237,29 @@ Then build the entire project as `Windows Release (clang)`. You can also press C ![](./docs/img/windows/release-build.png) ![](./docs/img/windows/build-all.png) +### MacOS + +> NOTE: At this time you still cannot run the game on macOS due to OpenGL version limitations. But you can build the project and use most of the tooling. + +Ensure that you have Xcode command line tools installed (this installs things like Apple Clang). If you don't, you can run the following command: + +```bash +xcode-select –install +``` + +#### Intel Based + +```bash +brew install go-task/tap/go-task +brew install cmake nasm ninja go-task +cmake -B build --preset=Release-macos-clang +cmake --build build --parallel $((`sysctl -n hw.logicalcpu`)) +``` + +#### Apple Silicon + +**Not Supported at This Time** + ### Building and Running the Game Getting a running game involves 4 steps: diff --git a/common/cross_os_debug/xdbg.cpp b/common/cross_os_debug/xdbg.cpp index 81eaea20fc..40da66b01d 100644 --- a/common/cross_os_debug/xdbg.cpp +++ b/common/cross_os_debug/xdbg.cpp @@ -689,9 +689,16 @@ std::string ThreadID::to_string() const { return "invalid"; } -ThreadID get_current_thread_id(); +ThreadID get_current_thread_id() { + return ThreadID("not implemented on macOS"); +} + bool attach_and_break(const ThreadID& tid); -void allow_debugging(); + +void allow_debugging() { + printf("allow_debugging not implemented on macOS\n"); +} + bool detach_and_resume(const ThreadID& tid) { return false; } diff --git a/common/cross_sockets/XSocketServer.cpp b/common/cross_sockets/XSocketServer.cpp index dd5e5fd9e9..8272189d3e 100644 --- a/common/cross_sockets/XSocketServer.cpp +++ b/common/cross_sockets/XSocketServer.cpp @@ -42,19 +42,26 @@ bool XSocketServer::init_server() { return false; } -#ifdef OS_POSIX - int server_socket_opt = SO_REUSEADDR | SO_REUSEPORT; -#elif _WIN32 - int server_socket_opt = SO_EXCLUSIVEADDRUSE; -#endif + int yes = 1; - int opt = 1; - if (set_socket_option(listening_socket, SOL_SOCKET, server_socket_opt, &opt, sizeof(opt)) < 0) { +#ifdef OS_POSIX + if (set_socket_option(listening_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + close_server_socket(); + return false; + } + // macOS doesn't support setting multiple options at once, so we have to do this separately. + if (set_socket_option(listening_socket, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0) { + close_server_socket(); + return false; + } +#elif _WIN32 + if (set_socket_option(listening_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &yes, sizeof(yes)) < 0) { close_server_socket(); return false; }; +#endif - if (set_socket_option(listening_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &opt, sizeof(opt)) < 0) { + if (set_socket_option(listening_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &yes, sizeof(yes)) < 0) { close_server_socket(); return false; } diff --git a/common/util/FileUtil.cpp b/common/util/FileUtil.cpp index 19c2863953..cd50d820ee 100644 --- a/common/util/FileUtil.cpp +++ b/common/util/FileUtil.cpp @@ -38,6 +38,13 @@ #include "common/log/log.h" #include "common/util/Assert.h" +#ifdef __APPLE__ +#include +#include + +#include +#endif + namespace file_util { fs::path get_user_home_dir() { #ifdef _WIN32 @@ -64,6 +71,9 @@ fs::path get_user_config_dir() { } else { config_base_path = fs::path(config_base_dir); } +#elif __APPLE__ + auto config_base_dir = get_env("HOME"); + config_base_path = fs::path(config_base_dir) / "Library" / "Application Support"; #endif return config_base_path / "OpenGOAL"; } @@ -101,14 +111,22 @@ std::string get_current_executable_path() { return file_path.substr(4); } return file_path; -#else - // do Linux stuff +#elif __linux char buffer[FILENAME_MAX + 1]; auto len = readlink("/proc/self/exe", buffer, FILENAME_MAX); // /proc/self acts like a "virtual folder" containing // information about the current process buffer[len] = '\0'; return std::string(buffer); +#elif __APPLE__ + char buffer[PATH_MAX]; + uint32_t bufsize = sizeof(buffer); + if (_NSGetExecutablePath(buffer, &bufsize) != 0) { + lg::warn("Could not get executable path, trying with _NSGetArgv()[0] instead."); + auto argv = *_NSGetArgv(); + return std::string(argv[0]); + } + return std::string(buffer); #endif } diff --git a/game/common/vu.h b/game/common/vu.h index 0e569aae53..966b4b2f0a 100644 --- a/game/common/vu.h +++ b/game/common/vu.h @@ -28,6 +28,8 @@ enum class Mask { #ifdef __linux__ #define REALLY_INLINE __attribute__((always_inline)) +#elif __APPLE__ +#define REALLY_INLINE __attribute__((always_inline)) #else #define REALLY_INLINE __forceinline #endif diff --git a/game/kernel/asm_funcs.asm b/game/kernel/asm_funcs.asm index 2b94b83744..affce45238 100644 --- a/game/kernel/asm_funcs.asm +++ b/game/kernel/asm_funcs.asm @@ -6,9 +6,9 @@ SECTION .text -;; Call C++ code on linux, from GOAL, using Linux calling convention. -global _arg_call_linux -_arg_call_linux: +;; Call C++ code on unix systems, from GOAL, using System V calling convention. +global _arg_call_systemv +_arg_call_systemv: pop rax push r10 push r11 @@ -43,12 +43,12 @@ _arg_call_linux: ret -;; Call C++ code on linux, from GOAL. Pug arguments on the stack and put a pointer to this array in the first arg. +;; Call C++ code on unix systems, from GOAL. Pug arguments on the stack and put a pointer to this array in the first arg. ;; this function pushes all 8 OpenGOAL registers into a stack array. ;; then it calls the function pointed to by rax with a pointer to this array. ;; it returns the return value of the called function. -global _stack_call_linux -_stack_call_linux: +global _stack_call_systemv +_stack_call_systemv: pop rax ; align stack sub rsp, 8 @@ -105,8 +105,8 @@ _stack_call_linux: ;; Call c++ code through mips2c. ;; GOAL will call a dynamically generated trampoline. ;; The trampoline will have pushed the exec function and stack offset onto the stack -global _mips2c_call_linux -_mips2c_call_linux: +global _mips2c_call_systemv +_mips2c_call_systemv: ;; grab the address to call and put it in xmm0 sub rsp, 8 movaps xmm0, [rsp + 16] @@ -323,9 +323,9 @@ _stack_call_win32: ;; - address of the symbol table ;; - GOAL memory space offset -global _call_goal_asm_linux +global _call_goal_asm_systemv -_call_goal_asm_linux: +_call_goal_asm_systemv: ;; x86 saved registers we need to modify for GOAL should be saved push r13 push r14 @@ -353,9 +353,9 @@ _call_goal_asm_linux: pop r13 ret -global _call_goal8_asm_linux +global _call_goal8_asm_systemv -_call_goal8_asm_linux: +_call_goal8_asm_systemv: ;; x86 saved registers we need to modify for GOAL should be saved push r13 push r14 @@ -395,9 +395,9 @@ _call_goal8_asm_linux: ret ;; Call goal, but switch stacks. -global _call_goal_on_stack_asm_linux +global _call_goal_on_stack_asm_systemv -_call_goal_on_stack_asm_linux: +_call_goal_on_stack_asm_systemv: ;; RDI - stack pointer ;; RSI - unused ;; RDX - unused @@ -436,7 +436,6 @@ _call_goal_on_stack_asm_linux: pop r13 ret - ;; The _call_goal_asm function is used to call a GOAL function from C. ;; It supports up to 3 arguments and a return value. ;; This should be called with the arguments: diff --git a/game/kernel/common/kscheme.cpp b/game/kernel/common/kscheme.cpp index a701696ec3..ae43de721d 100644 --- a/game/kernel/common/kscheme.cpp +++ b/game/kernel/common/kscheme.cpp @@ -85,13 +85,22 @@ u64 goal_malloc(u32 heap, u32 size, u32 flags, u32 name) { extern "C" { // defined in asm_funcs.asm #ifdef __linux__ -uint64_t _call_goal_asm_linux(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); -uint64_t _call_goal_on_stack_asm_linux(u64 rsp, - u64 u0, - u64 u1, - void* fptr, - void* st_ptr, - void* offset); +uint64_t _call_goal_asm_systemv(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); +uint64_t _call_goal_on_stack_asm_systemv(u64 rsp, + u64 u0, + u64 u1, + void* fptr, + void* st_ptr, + void* offset); +#elif defined __APPLE__ && defined __x86_64__ +uint64_t _call_goal_asm_systemv(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset) asm( + "_call_goal_asm_systemv"); +uint64_t _call_goal_on_stack_asm_systemv(u64 rsp, + u64 u0, + u64 u1, + void* fptr, + void* st_ptr, + void* offset) asm("_call_goal_on_stack_asm_systemv"); #elif _WIN32 uint64_t _call_goal_asm_win32(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); uint64_t _call_goal_on_stack_asm_win32(u64 rsp, void* fptr, void* st_ptr, void* offset); @@ -108,7 +117,9 @@ u64 call_goal(Ptr f, u64 a, u64 b, u64 c, u64 st, void* offset) { void* fptr = f.c(); #ifdef __linux__ - return _call_goal_asm_linux(a, b, c, fptr, st_ptr, offset); + return _call_goal_asm_systemv(a, b, c, fptr, st_ptr, offset); +#elif defined __APPLE__ && defined __x86_64__ + return _call_goal_asm_systemv(a, b, c, fptr, st_ptr, offset); #elif _WIN32 return _call_goal_asm_win32(a, b, c, fptr, st_ptr, offset); #endif @@ -122,7 +133,9 @@ u64 call_goal_on_stack(Ptr f, u64 rsp, u64 st, void* offset) { void* fptr = f.c(); #ifdef __linux__ - return _call_goal_on_stack_asm_linux(rsp, 0, 0, fptr, st_ptr, offset); + return _call_goal_on_stack_asm_systemv(rsp, 0, 0, fptr, st_ptr, offset); +#elif defined __APPLE__ && defined __x86_64__ + return _call_goal_on_stack_asm_systemv(rsp, 0, 0, fptr, st_ptr, offset); #elif _WIN32 return _call_goal_on_stack_asm_win32(rsp, fptr, st_ptr, offset); #endif @@ -286,4 +299,4 @@ u64 inspect_vu_function(u32 obj) { u64 inspect_kheap(u32 obj) { kheapstatus(Ptr(obj)); return obj; -} \ No newline at end of file +} diff --git a/game/kernel/jak1/kscheme.cpp b/game/kernel/jak1/kscheme.cpp index c866849a71..d854196fc3 100644 --- a/game/kernel/jak1/kscheme.cpp +++ b/game/kernel/jak1/kscheme.cpp @@ -264,19 +264,23 @@ u64 make_string_from_c(const char* c_str) { } extern "C" { -void _arg_call_linux(); +#ifdef __APPLE__ +void _arg_call_systemv() asm("_arg_call_systemv"); +#else +void _arg_call_systemv(); +#endif } /*! * This creates an OpenGOAL function from a C++ function. Only 6 arguments can be accepted. * But calling this function is fast. It used to be really fast but wrong. */ -Ptr make_function_from_c_linux(void* func, bool arg3_is_pp) { +Ptr make_function_from_c_systemv(void* func, bool arg3_is_pp) { auto mem = Ptr(alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP)); auto f = (uint64_t)func; auto target_function = (u8*)&f; - auto trampoline_function_addr = _arg_call_linux; + auto trampoline_function_addr = _arg_call_systemv; auto trampoline = (u8*)&trampoline_function_addr; // movabs rax, target_function @@ -378,17 +382,22 @@ Ptr make_function_from_c_win32(void* func, bool arg3_is_pp) { } extern "C" { -void _stack_call_linux(); +#ifdef __APPLE__ +void _stack_call_systemv() asm("_stack_call_systemv"); +void _stack_call_win32() asm("_stack_call_win32"); +#else +void _stack_call_systemv(); void _stack_call_win32(); +#endif } -Ptr make_stack_arg_function_from_c_linux(void* func) { +Ptr make_stack_arg_function_from_c_systemv(void* func) { // allocate a function object on the global heap auto mem = Ptr(alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP)); auto f = (uint64_t)func; auto target_function = (u8*)&f; - auto trampoline_function_addr = _stack_call_linux; + auto trampoline_function_addr = _stack_call_systemv; auto trampoline = (u8*)&trampoline_function_addr; // movabs rax, target_function @@ -467,7 +476,9 @@ Ptr make_stack_arg_function_from_c_win32(void* func) { */ Ptr make_function_from_c(void* func, bool arg3_is_pp = false) { #ifdef __linux__ - return make_function_from_c_linux(func, arg3_is_pp); + return make_function_from_c_systemv(func, arg3_is_pp); +#elif __APPLE__ + return make_function_from_c_systemv(func, arg3_is_pp); #elif _WIN32 return make_function_from_c_win32(func, arg3_is_pp); #endif @@ -475,7 +486,9 @@ Ptr make_function_from_c(void* func, bool arg3_is_pp = false) { Ptr make_stack_arg_function_from_c(void* func) { #ifdef __linux__ - return make_stack_arg_function_from_c_linux(func); + return make_stack_arg_function_from_c_systemv(func); +#elif __APPLE__ + return make_stack_arg_function_from_c_systemv(func); #elif _WIN32 return make_stack_arg_function_from_c_win32(func); #endif @@ -1712,10 +1725,9 @@ s32 InitHeapAndSymbol() { // check the kernel version! auto kernel_version = intern_from_c("*kernel-version*")->value; if (!kernel_version || ((kernel_version >> 0x13) != KERNEL_VERSION_MAJOR)) { - MsgErr("\n"); - MsgErr( - "dkernel: compiled C kernel version is %d.%d but the goal kernel is %d.%d\n\tfrom the " - "goal> prompt (:mch) then mkee your kernel in linux.\n", + lg::error( + "Kernel version mismatch! Compiled C kernel version is {}.{} but" + "the goal kernel is {}.{}", KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR, kernel_version >> 0x13, (kernel_version >> 3) & 0xffff); return -1; diff --git a/game/kernel/jak2/kscheme.cpp b/game/kernel/jak2/kscheme.cpp index 6c14b1e26a..dd46172fec 100644 --- a/game/kernel/jak2/kscheme.cpp +++ b/game/kernel/jak2/kscheme.cpp @@ -276,19 +276,23 @@ u64 make_debug_string_from_c(const char* c_str) { } extern "C" { -void _arg_call_linux(); +#ifdef __APPLE__ +void _arg_call_systemv() asm("_arg_call_systemv"); +#else +void _arg_call_systemv(); +#endif } /*! * This creates an OpenGOAL function from a C++ function. Only 6 arguments can be accepted. * But calling this function is fast. It used to be really fast but wrong. */ -Ptr make_function_from_c_linux(void* func, bool arg3_is_pp) { +Ptr make_function_from_c_systemv(void* func, bool arg3_is_pp) { auto mem = Ptr(alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, u32_in_fixed_sym(FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP)); auto f = (uint64_t)func; auto target_function = (u8*)&f; - auto trampoline_function_addr = _arg_call_linux; + auto trampoline_function_addr = _arg_call_systemv; auto trampoline = (u8*)&trampoline_function_addr; // movabs rax, target_function @@ -390,17 +394,22 @@ Ptr make_function_from_c_win32(void* func, bool arg3_is_pp) { } extern "C" { -void _stack_call_linux(); +#ifdef __APPLE__ +void _stack_call_systemv() asm("_stack_call_systemv"); +void _stack_call_win32() asm("_stack_call_win32"); +#else +void _stack_call_systemv(); void _stack_call_win32(); +#endif } -Ptr make_stack_arg_function_from_c_linux(void* func) { +Ptr make_stack_arg_function_from_c_systemv(void* func) { // allocate a function object on the global heap auto mem = Ptr(alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, u32_in_fixed_sym(FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP)); auto f = (uint64_t)func; auto target_function = (u8*)&f; - auto trampoline_function_addr = _stack_call_linux; + auto trampoline_function_addr = _stack_call_systemv; auto trampoline = (u8*)&trampoline_function_addr; // movabs rax, target_function @@ -479,7 +488,9 @@ Ptr make_stack_arg_function_from_c_win32(void* func) { */ Ptr make_function_from_c(void* func, bool arg3_is_pp = false) { #ifdef __linux__ - return make_function_from_c_linux(func, arg3_is_pp); + return make_function_from_c_systemv(func, arg3_is_pp); +#elif __APPLE__ + return make_function_from_c_systemv(func, arg3_is_pp); #elif _WIN32 return make_function_from_c_win32(func, arg3_is_pp); #endif @@ -487,7 +498,9 @@ Ptr make_function_from_c(void* func, bool arg3_is_pp = false) { Ptr make_stack_arg_function_from_c(void* func) { #ifdef __linux__ - return make_stack_arg_function_from_c_linux(func); + return make_stack_arg_function_from_c_systemv(func); +#elif __APPLE__ + return make_stack_arg_function_from_c_systemv(func); #elif _WIN32 return make_stack_arg_function_from_c_win32(func); #endif @@ -1728,10 +1741,9 @@ int InitHeapAndSymbol() { auto kernel_version = intern_from_c("*kernel-version*")->value(); if (!kernel_version || ((kernel_version >> 0x13) != KERNEL_VERSION_MAJOR)) { - MsgErr("\n"); - MsgErr( - "dkernel: compiled C kernel version is %d.%d but the goal kernel is %d.%d\n\tfrom the " - "goal> prompt (:mch) then mkee your kernel in linux.\n", + lg::error( + "Kernel version mismatch! Compiled C kernel version is {}.{} but" + "the goal kernel is {}.{}", KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR, kernel_version >> 0x13, (kernel_version >> 3) & 0xffff); return -1; diff --git a/game/mips2c/mips2c_private.h b/game/mips2c/mips2c_private.h index 419f65826a..634c32e66c 100644 --- a/game/mips2c/mips2c_private.h +++ b/game/mips2c/mips2c_private.h @@ -20,8 +20,14 @@ extern u8* g_ee_main_mem; extern "C" { -u64 _call_goal8_asm_linux(void* func, u64* arg_array, u64 zero, u64 pp, u64 st, void* off); +#ifdef __linux__ +u64 _call_goal8_asm_systemv(void* func, u64* arg_array, u64 zero, u64 pp, u64 st, void* off); +#elif defined __APPLE__ && defined __x86_64__ +u64 _call_goal8_asm_systemv(void* func, u64* arg_array, u64 zero, u64 pp, u64 st, void* off) asm( + "_call_goal8_asm_systemv"); +#elif _WIN32 u64 _call_goal8_asm_win32(void* func, u64* arg_array, u64 zero, u64 pp, u64 st, void* off); +#endif } namespace Mips2C { @@ -344,13 +350,15 @@ struct ExecutionContext { } void jalr(u32 addr) { - // u64 _call_goal8_asm_linux(u64 func, u64* arg_array, u64 zero, u64 pp, u64 st, u64 off); u64 args[8] = {gprs[a0].du64[0], gprs[a1].du64[0], gprs[a2].du64[0], gprs[a3].du64[0], gprs[t0].du64[0], gprs[t1].du64[0], gprs[t2].du64[0], gprs[t3].du64[0]}; -#ifdef __linux__ ASSERT(addr); - gprs[v0].du64[0] = _call_goal8_asm_linux(g_ee_main_mem + addr, args, 0, gprs[s6].du64[0], - gprs[s7].du64[0], g_ee_main_mem); +#ifdef __linux__ + gprs[v0].du64[0] = _call_goal8_asm_systemv(g_ee_main_mem + addr, args, 0, gprs[s6].du64[0], + gprs[s7].du64[0], g_ee_main_mem); +#elif defined __APPLE__ && defined __x86_64__ + gprs[v0].du64[0] = _call_goal8_asm_systemv(g_ee_main_mem + addr, args, 0, gprs[s6].du64[0], + gprs[s7].du64[0], g_ee_main_mem); #elif _WIN32 gprs[v0].du64[0] = _call_goal8_asm_win32(g_ee_main_mem + addr, args, 0, gprs[s6].du64[0], gprs[s7].du64[0], g_ee_main_mem); diff --git a/game/mips2c/mips2c_table.cpp b/game/mips2c/mips2c_table.cpp index a55db5afd7..5a29a0c0a6 100644 --- a/game/mips2c/mips2c_table.cpp +++ b/game/mips2c/mips2c_table.cpp @@ -10,7 +10,11 @@ #include "game/runtime.h" extern "C" { -void _mips2c_call_linux(); +#ifdef __linux__ +void _mips2c_call_systemv(); +#elif defined __APPLE__ && defined __x86_64__ +void _mips2c_call_systemv() asm("_mips2c_call_systemv"); +#endif void _mips2c_call_windows(); } @@ -478,7 +482,9 @@ void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 s // call the other function #ifdef __linux__ - addr = (u64)_mips2c_call_linux; + addr = (u64)_mips2c_call_systemv; +#elif defined __APPLE__ && defined __x86_64__ + addr = (u64)_mips2c_call_systemv; #elif _WIN32 addr = (u64)_mips2c_call_windows; #endif diff --git a/game/mips2c/readme.md b/game/mips2c/readme.md index d2498523b5..6083cca6fd 100644 --- a/game/mips2c/readme.md +++ b/game/mips2c/readme.md @@ -76,7 +76,7 @@ Replace the `defun` with: You can use the same idea for methods with `method-set!`. The method name will be the decompiler name. ## Running Mips2C code -When Mips2C code is linked (for the first time), a small dynamically generated function object is created. This is a very short stub that jumps to a common implementation in `mips2c_call_linux`, that actually sets up the call. +When Mips2C code is linked (for the first time), a small dynamically generated function object is created. This is a very short stub that jumps to a common implementation in `mips2c_call_systemv`, that actually sets up the call. The setup code saves the appropriate registers for the OS, allocates an `ExecutionContext` on the stack, initializes the argument registers, allocates a "fake stack array" on the stack with the requested size, and calls the C++ function. @@ -86,4 +86,4 @@ Unfortunately, throwing all the registers on the stack takes a huge amount of st With some clever tricks it might be possible to do better, but it doesn't seem worth it at this time. -On exit, the assembly function will grab the return value from `v0` and put it in `rax`. \ No newline at end of file +On exit, the assembly function will grab the return value from `v0` and put it in `rax`. diff --git a/game/sound/CMakeLists.txt b/game/sound/CMakeLists.txt index 1c598c2a9f..c1422302c2 100644 --- a/game/sound/CMakeLists.txt +++ b/game/sound/CMakeLists.txt @@ -26,6 +26,8 @@ target_link_libraries(sound PRIVATE fmt cubeb common) add_executable(sndplay 989snd/sndplay.cpp) if(WIN32) target_link_libraries(sndplay PRIVATE sound cubeb) +elseif(APPLE) + target_link_libraries(sndplay PRIVATE sound cubeb) else() target_link_libraries(sndplay PRIVATE sound cubeb stdc++fs) endif()