mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-27 00:10:31 +00:00
Make all project targets compile on Intel MacOS (#2780)
This commit is contained in:
parent
98bb40d618
commit
cf295952b6
14
.github/workflows/macos-build-clang.yaml
vendored
14
.github/workflows/macos-build-clang.yaml
vendored
@ -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
|
||||
|
26
README.md
26
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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -38,6 +38,13 @@
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <mach-o/dyld.h>
|
||||
#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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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<Function> 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<Function> 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<kheapinfo>(obj));
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
@ -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<Function> make_function_from_c_linux(void* func, bool arg3_is_pp) {
|
||||
Ptr<Function> make_function_from_c_systemv(void* func, bool arg3_is_pp) {
|
||||
auto mem = Ptr<u8>(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<Function> 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<Function> make_stack_arg_function_from_c_linux(void* func) {
|
||||
Ptr<Function> make_stack_arg_function_from_c_systemv(void* func) {
|
||||
// allocate a function object on the global heap
|
||||
auto mem = Ptr<u8>(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<Function> make_stack_arg_function_from_c_win32(void* func) {
|
||||
*/
|
||||
Ptr<Function> 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<Function> make_function_from_c(void* func, bool arg3_is_pp = false) {
|
||||
|
||||
Ptr<Function> 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;
|
||||
|
@ -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<Function> make_function_from_c_linux(void* func, bool arg3_is_pp) {
|
||||
Ptr<Function> make_function_from_c_systemv(void* func, bool arg3_is_pp) {
|
||||
auto mem = Ptr<u8>(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<Function> 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<Function> make_stack_arg_function_from_c_linux(void* func) {
|
||||
Ptr<Function> make_stack_arg_function_from_c_systemv(void* func) {
|
||||
// allocate a function object on the global heap
|
||||
auto mem = Ptr<u8>(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<Function> make_stack_arg_function_from_c_win32(void* func) {
|
||||
*/
|
||||
Ptr<Function> 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<Function> make_function_from_c(void* func, bool arg3_is_pp = false) {
|
||||
|
||||
Ptr<Function> 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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
On exit, the assembly function will grab the return value from `v0` and put it in `rax`.
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user