diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index b83673f631..614544af5b 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -342,7 +342,8 @@ Ptr make_function_from_c_linux(void* func) { * Create a GOAL function from a C function. This doesn't export it as a global function, it just * creates a function object on the global heap. * - * The implementation is to create a simple trampoline function which jumps to the C function. + * This creates a simple trampoline function which jumps to the C function and reorders the + * arguments to be correct for Windows. */ Ptr make_function_from_c_win32(void* func) { // allocate a function object on the global heap @@ -386,6 +387,10 @@ Ptr make_function_from_c_win32(void* func) { return mem.cast(); } +/*! + * Create a GOAL function from a C function. This calls a windows function, but doesn't scramble + * the argument order. It's supposed to be used with _format_win32 which assumes GOAL order. + */ Ptr make_function_for_format_from_c_win32(void* func) { // allocate a function object on the global heap auto mem = Ptr( @@ -401,6 +406,12 @@ Ptr make_function_for_format_from_c_win32(void* func) { mem.c()[i++] = fp[j]; } + /* + * sub rsp, 40 + * call rax + * add rsp, 40 + * ret + */ for (auto x : {0x48, 0x83, 0xEC, 0x28, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x28, 0xC3}) { mem.c()[i++] = x; } @@ -462,6 +473,17 @@ Ptr make_function_symbol_from_c(const char* name, void* f) { return func; } +/*! + * Given a C function and a name, create a GOAL function and store it in the symbol with the given + * name. This is designed for _format_win32, which is special because it takes 8 arguments. + */ +Ptr make_format_function_symbol_from_c_win32(const char* name, void* f) { + auto sym = intern_from_c(name); + auto func = make_function_for_format_from_c_win32(f); + sym->value = func.offset; + return func; +} + /*! * Set the named symbol to the value. This isn't specific to functions. */ @@ -1800,7 +1822,7 @@ s32 InitHeapAndSymbol() { #ifdef __linux__ make_function_symbol_from_c("_format", (void*)_format_linux); #elif _WIN32 - make_function_for_format_from_c_win32("_format", (void*)_format_win32); + make_format_function_symbol_from_c_win32("_format", (void*)_format_win32); #endif // allocations