Merge pull request #2456 from LRFLEW/osx

Finished fixing support for OS X
This commit is contained in:
Duncan 2015-12-11 08:54:47 +00:00
commit 3ba4677bd9
4 changed files with 88 additions and 85 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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 <list>

View File

@ -40,14 +40,14 @@
#include "util/util.h"
#include "world/mapgen.h"
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#if defined(__unix__)
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#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