prepare hook for sub_6DAB4C

This commit is contained in:
IntelOrca 2015-10-25 15:01:42 +00:00
parent 67f612c18c
commit 9ad290463a
4 changed files with 54 additions and 62 deletions

View File

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

View File

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

View File

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

View File

@ -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, &regs);
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, &regs);
// regs.eax = 0;
// regs.ebx = 0;
hook_setreturnregisters(&regs);
return regs.eax;
}