From 9ad290463a17e9f151cba9b002790d9243a432bb Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 25 Oct 2015 15:01:42 +0000 Subject: [PATCH] prepare hook for sub_6DAB4C --- src/hook.c | 22 ++++++++++++-- src/hook.h | 6 +++- src/openrct2.c | 74 ++++++++++++---------------------------------- src/ride/vehicle.c | 14 +++++++-- 4 files changed, 54 insertions(+), 62 deletions(-) diff --git a/src/hook.c b/src/hook.c index 757d873ce7..70d30af2e5 100644 --- a/src/hook.c +++ b/src/hook.c @@ -30,7 +30,9 @@ void* g_hooktableaddress = 0; int g_hooktableoffset = 0; int g_maxhooks = 1000; -void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) +registers _returnRegisters; + +void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister, bool useReturnRegisters) { int i = 0; char data[100]; @@ -155,6 +157,15 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in break; } + if (useReturnRegisters) { + // mov ebx, [_returnRegisters.ebx] + data[i++] = 0x8B; + data[i++] = 0x1C; + data[i++] = 0x25; + *((uint32*)&data[i]) = (uint32)(&_returnRegisters.ebx); + i += 4; + } + data[i++] = 0x83; // sub esp, x data[i++] = 0xEC; data[i++] = (signed char)(stacksize * -4) - rargssize; @@ -198,7 +209,7 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in #endif // _WIN32 } -void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) +void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister, bool useReturnRegisters) { if (!g_hooktableaddress) { size_t size = g_maxhooks * 100; @@ -228,6 +239,11 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int // We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data memcpy((void *)address, data, i); #endif // _WIN32 - hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned, eaxDestinationRegister); + hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned, eaxDestinationRegister, useReturnRegisters); g_hooktableoffset++; } + +void hook_setreturnregisters(registers *regs) +{ + _returnRegisters = *regs; +} diff --git a/src/hook.h b/src/hook.h index 7f2289f059..38cf1d1198 100644 --- a/src/hook.h +++ b/src/hook.h @@ -21,6 +21,9 @@ #ifndef _HOOK_H_ #define _HOOK_H_ +#include "addresses.h" +#include "common.h" + enum REGISTER_ARGS { EAX = 1 << 0, EBX = 1 << 1, @@ -32,6 +35,7 @@ enum REGISTER_ARGS { END = 0 }; -void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister); +void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister, bool useReturnRegisters); +void hook_setreturnregisters(registers *regs); #endif \ No newline at end of file diff --git a/src/openrct2.c b/src/openrct2.c index c35dfb2d17..70055979bd 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -40,14 +40,14 @@ #include "util/util.h" #include "world/mapgen.h" -#if defined(__unix__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include #include #include #include #include #include -#endif // defined(__unix__) +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; utf8 gOpenRCT2StartupActionPath[512] = { 0 }; @@ -59,11 +59,11 @@ bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; -#if defined(__unix__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) void *gDataSegment; void *gTextSegment; int gExeFd; -#endif // defined(__unix__) +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) /** 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__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #define RDATA_OFFSET 0x004A4000 #define DATASEG_OFFSET 0x005E2000 @@ -513,45 +513,8 @@ static bool openrct2_setup_rct2_segment() off_t file_size = 6750208; int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB - int pageSize = getpagesize(); - int numPages = (len + pageSize - 1) / pageSize; - unsigned char *dummy = malloc(numPages); - int err = mincore((void *)0x8a4000, len, dummy); - bool pagesDirty = false; - if (err != 0) - { - err = errno; -#ifdef __linux__ - // On Linux ENOMEM means all requested range is unmapped - if (err != ENOMEM) - { - pagesDirty = true; - perror("mincore"); - } -#else - pagesDirty = true; - perror("mincore"); -#endif // __linux__ - } else { - log_warning("mincore ok"); - for (int i = 0; i < numPages; i++) - { - if (dummy[i] != 0) - { - pagesDirty = true; - void *start = (void *)0x8a4000 + i * pageSize; - void *end = (void *)0x8a4000 + (i + 1) * pageSize - 1; - log_warning("page %p - %p has flags: %x, you're in for bad time!", start, end, dummy[i]); - } - } - } - free(dummy); - if (pagesDirty) - { - log_error("Found already mapped pages in region we want to claim. This means something accessed memory before we got to and following mmap (or next malloc) call will likely fail."); - } // section: rw data - gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0); + gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0); if (gDataSegment != (void *)0x8a4000) { log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); exit(1); @@ -567,7 +530,7 @@ static bool openrct2_setup_rct2_segment() } void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0); - err = errno; + int err = errno; log_warning("mmapped file to %p", fbase); if (fbase == MAP_FAILED) { @@ -585,7 +548,7 @@ static bool openrct2_setup_rct2_segment() err = errno; log_error("Failed to unmap file! errno = %d", err); } -#endif // defined(__unix__) +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // 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 +572,7 @@ static bool openrct2_setup_rct2_segment() static bool openrct2_release_rct2_segment() { bool result = true; -#if defined(__unix__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB int err; err = munmap(gDataSegment, len); @@ -634,7 +597,7 @@ static bool openrct2_release_rct2_segment() log_error("Failed to close file! errno = %d", err); result = false; } -#endif // defined(__unix__) +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) return result; } @@ -643,14 +606,15 @@ static bool openrct2_release_rct2_segment() */ static void openrct2_setup_rct2_hooks() { - addhook(0x006E732D, (int)gfx_set_dirty_blocks, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when all callers are decompiled - 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}, 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 + addhook(0x006E732D, (int)gfx_set_dirty_blocks, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0, false); // remove when all callers are decompiled + addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0, false); // remove when 0x6E7FF3 is decompiled + addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0, 0, false); // remove when all callers are decompiled + addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0, 0, false); // remove when all callers are decompiled + addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX, 0, false); // remove when all callers are decompiled + addhook(0x006C42D9, (int)scrolling_text_setup, 0, (int[]){EAX, ECX, EBP, END}, 0, EBX, false); // remove when all callers are decompiled + addhook(0x006C2321, (int)gfx_get_string_width, 0, (int[]){ESI, END}, 0, ECX, false); // remove when all callers are decompiled + addhook(0x006C2555, (int)format_string, 0, (int[]){EDI, EAX, ECX, END}, 0, 0, false); // remove when all callers are decompiled + addhook(0x006DAB4C, (int)sub_6DAB4C, 0, (int[]){ESI, END}, 0, EAX, true); // remove when all callers are decompiled } #if _MSC_VER >= 1900 diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index 4f66083e0b..7bf795624c 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -623,11 +623,19 @@ bool sub_6DD365(rct_vehicle *vehicle) int sub_6DAB4C(rct_vehicle *vehicle, int *outStation) { registers regs; - regs.esi = (int)vehicle; - RCT2_CALLFUNC_Y(0x006DAB4C, ®s); + regs.esi = vehicle; + regs.edi = vehicle->vehicle_type; + regs.eax = vehicle->ride_subtype; + regs.edi *= 0x65; + regs.eax = GET_RIDE_ENTRY(regs.eax); + regs.edi += regs.eax; - if (outStation != NULL) *outStation = regs.ebx; + RCT2_CALLFUNC_Y(0x006DAB63, ®s); + + // regs.eax = 0; + // regs.ebx = 0; + hook_setreturnregisters(®s); return regs.eax; }