diff --git a/CMakeLists.txt b/CMakeLists.txt index 14ebfa3de6..36fa04b30d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,9 +61,12 @@ file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "lib/argparse/*.c" "lib/cu if (UNIX) # force 32bit build for now and set necessary flags to compile code as is - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer") - set(CMAKE_SHARED_LINKER_FLAGS "-m32") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") + if (APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -sectcreate rct2_text __text ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_text -sectcreate rct2_data __data ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_data -segaddr rct2_data 0x8a4000 -segprot rct2_data rwx rwx -segaddr rct2_text 0x401000 -segprot rct2_text rwx rwx -fno-pie -read_only_relocs suppress") + endif (APPLE) set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) @@ -101,6 +104,24 @@ if (APPLE) TARGET_LINK_LIBRARIES(${PROJECT} ${ICONV_LIBRARIES}) endif (APPLE) +# handle creating the rct2 text and data files on OS X +if (APPLE) + add_custom_command( + OUTPUT openrct2_text + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_text bs=4096 skip=1 count=1187 + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_command( + OUTPUT openrct2_data + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1188 count=318 + COMMAND dd if=/dev/zero of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 seek=318 count=2630 conv=notrunc + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1506 seek=2948 count=1 conv=notrunc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_target(segfiles DEPENDS openrct2_text openrct2_data) + add_dependencies(${PROJECT} segfiles) +endif (APPLE) + # install into ${CMAKE_INSTALL_PREFIX}/bin/ #install (TARGETS ${PROJECT} DESTINATION bin) diff --git a/src/hook.c b/src/hook.c index be83f39dc3..757d873ce7 100644 --- a/src/hook.c +++ b/src/hook.c @@ -53,73 +53,6 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in int rargssize = numrargs * 4; - data[i++] = 0x50; // push eax - - // move stack down for possible existing arguments - for (int j = 0; j < stacksize; j++) { - data[i++] = 0x8B; // mov eax, [esp+x] - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) + 4); - - data[i++] = 0x89; // mov [esp+x], eax - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) - ((registerssaved + stacksize) * 4)); - } - - if (numrargs > 0) { - // push the registers to be on the stack to access as arguments - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = -((registerssaved + stacksize) * 4) + 4; - - for (signed int j = numrargs - 1; j >= 0; j--) { - switch (registerargs[j]) { - case EAX: data[i++] = 0x50; break; - case EBX: data[i++] = 0x53; break; - case ECX: data[i++] = 0x51; break; - case EDX: data[i++] = 0x52; break; - case ESI: data[i++] = 0x56; break; - case EDI: data[i++] = 0x57; break; - case EBP: data[i++] = 0x55; break; - } - } - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = rargssize + ((registerssaved + stacksize) * 4) - 4; - } - - - data[i++] = 0xE8; // call - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - - int sizec = i; - - data[i++] = 0x8B; // push eax, [esp] - puts eip in eax - data[i++] = 0x04; - data[i++] = 0xE4; - - data[i++] = 0x83; // add eax, x - data[i++] = 0xC0; - int sizeoffset = i; - data[i++] = 0; // set to returnlocation offset later - - data[i++] = 0x89; // mov [esp-20h], eax - put return address on stack - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)(-(registerssaved * 4) - rargssize - (stacksize * 4)) + 4; - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = 4; - - data[i++] = 0x58; // pop eax - if (!(registersreturned & EAX)) { data[i++] = 0x50; // push eax } @@ -142,15 +75,51 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0x57; // push edi } - data[i++] = 0x83; // sub esp, x - data[i++] = 0xEC; - data[i++] = 4 + (stacksize * 4) + rargssize; + data[i++] = 0x50; //push eax + data[i++] = 0x89; //mov eax, esp + data[i++] = 0xE0; + data[i++] = 0x83; //sub eax, (0xC + numargs*4) & 0xF + data[i++] = 0xE8; + data[i++] = (0xC + numrargs * 4) & 0xF; + data[i++] = 0x83; //and eax, 0xC + data[i++] = 0xE0; + data[i++] = 0x0C; + data[i++] = 0xA3; //mov [0x9ABDA8], eax + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + data[i++] = 0x58; //pop eax + data[i++] = 0x2B; //sub esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; - data[i++] = 0xE9; // jmp + // work out distance to nearest 0xC + // (esp - numargs * 4) & 0xC + // move to align - 4 + // save that amount + + if (numrargs > 0) { + // push the registers to be on the stack to access as arguments + for (signed int j = numrargs - 1; j >= 0; j--) { + switch (registerargs[j]) { + case EAX: data[i++] = 0x50; break; + case EBX: data[i++] = 0x53; break; + case ECX: data[i++] = 0x51; break; + case EDX: data[i++] = 0x52; break; + case ESI: data[i++] = 0x56; break; + case EDI: data[i++] = 0x57; break; + case EBP: data[i++] = 0x55; break; + } + } + } + + data[i++] = 0xE8; // call *((int *)&data[i]) = (newaddress - address - i - 4); i += 4; - data[sizeoffset] = i - sizec; - // returnlocation: switch (eaxDestinationRegister) { @@ -190,6 +159,13 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0xEC; data[i++] = (signed char)(stacksize * -4) - rargssize; + data[i++] = 0x03; //add esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + if (!(registersreturned & EDI)) { data[i++] = 0x5F; // pop edi } diff --git a/src/network/network.h b/src/network/network.h index 56260ce5f2..3eefa4f923 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -90,6 +90,12 @@ extern "C" { #define ioctlsocket ioctl #endif // _WIN32 +// Fixes issues on OS X +#if defined(_RCT2_H_) && !defined(_MSC_VER) +// use similar struct packing as MSVC for our structs +#pragma pack(1) +#endif + #ifdef __cplusplus #include diff --git a/src/openrct2.c b/src/openrct2.c index 6bb2fcd81b..74fd4848f5 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -40,14 +40,14 @@ #include "util/util.h" #include "world/mapgen.h" -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) #include #include #include #include #include #include -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; utf8 gOpenRCT2StartupActionPath[512] = { 0 }; @@ -59,11 +59,11 @@ bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) void *gDataSegment; void *gTextSegment; int gExeFd; -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) /** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */ int _finished; @@ -471,7 +471,7 @@ static bool openrct2_setup_rct2_segment() { // POSIX OSes will run OpenRCT2 as a native application and then load in the Windows PE, mapping the appropriate addresses as // necessary. Windows does not need to do this as OpenRCT2 runs as a DLL loaded from the Windows PE. -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) #define RDATA_OFFSET 0x004A4000 #define DATASEG_OFFSET 0x005E2000 @@ -585,7 +585,7 @@ static bool openrct2_setup_rct2_segment() err = errno; log_error("Failed to unmap file! errno = %d", err); } -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) // Check that the expected data is at various addresses. // Start at 0x9a6000, which is start of .data, to skip the region containing addresses to DLL @@ -609,7 +609,7 @@ static bool openrct2_setup_rct2_segment() static bool openrct2_release_rct2_segment() { bool result = true; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB int err; err = munmap(gDataSegment, len); @@ -634,7 +634,7 @@ static bool openrct2_release_rct2_segment() log_error("Failed to close file! errno = %d", err); result = false; } -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) return result; } @@ -647,7 +647,7 @@ static void openrct2_setup_rct2_hooks() addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when 0x6E7FF3 is decompiled addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0, 0); // remove when all callers are decompiled addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0, 0); // remove when all callers are decompiled - addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX, 0); // remove when all callers are decompiled + addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, 0, EAX); // remove when all callers are decompiled addhook(0x006C42D9, (int)scrolling_text_setup, 0, (int[]){EAX, ECX, EBP, END}, 0, EBX); // remove when all callers are decompiled addhook(0x006C2321, (int)gfx_get_string_width, 0, (int[]){ESI, END}, 0, ECX); // remove when all callers are decompiled addhook(0x006C2555, (int)format_string, 0, (int[]){EDI, EAX, ECX, END}, 0, 0); // remove when all callers are decompiled