mirror of https://github.com/OpenRCT2/OpenRCT2.git
fix vehicle-update after merge with sub_6DAB4C
This commit is contained in:
parent
c00669c942
commit
a941e67df6
144
src/hook.c
144
src/hook.c
|
@ -30,9 +30,7 @@ void* g_hooktableaddress = 0;
|
|||
int g_hooktableoffset = 0;
|
||||
int g_maxhooks = 1000;
|
||||
|
||||
registers _returnRegisters;
|
||||
|
||||
void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister, bool useReturnRegisters)
|
||||
void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister)
|
||||
{
|
||||
int i = 0;
|
||||
char data[100];
|
||||
|
@ -55,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
|
||||
}
|
||||
|
@ -144,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) {
|
||||
|
@ -188,19 +155,17 @@ 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;
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -233,7 +198,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, bool useReturnRegisters)
|
||||
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister)
|
||||
{
|
||||
if (!g_hooktableaddress) {
|
||||
size_t size = g_maxhooks * 100;
|
||||
|
@ -263,11 +228,6 @@ 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, useReturnRegisters);
|
||||
hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned, eaxDestinationRegister);
|
||||
g_hooktableoffset++;
|
||||
}
|
||||
|
||||
void hook_setreturnregisters(registers *regs)
|
||||
{
|
||||
_returnRegisters = *regs;
|
||||
}
|
|
@ -21,9 +21,6 @@
|
|||
#ifndef _HOOK_H_
|
||||
#define _HOOK_H_
|
||||
|
||||
#include "addresses.h"
|
||||
#include "common.h"
|
||||
|
||||
enum REGISTER_ARGS {
|
||||
EAX = 1 << 0,
|
||||
EBX = 1 << 1,
|
||||
|
@ -35,7 +32,6 @@ enum REGISTER_ARGS {
|
|||
END = 0
|
||||
};
|
||||
|
||||
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister, bool useReturnRegisters);
|
||||
void hook_setreturnregisters(registers *regs);
|
||||
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister);
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
||||
|
@ -513,8 +513,45 @@ 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, 0, 0);
|
||||
gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 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);
|
||||
|
@ -530,7 +567,7 @@ static bool openrct2_setup_rct2_segment()
|
|||
}
|
||||
|
||||
void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0);
|
||||
int err = errno;
|
||||
err = errno;
|
||||
log_warning("mmapped file to %p", fbase);
|
||||
if (fbase == MAP_FAILED)
|
||||
{
|
||||
|
@ -548,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
|
||||
|
@ -572,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);
|
||||
|
@ -597,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;
|
||||
}
|
||||
|
||||
|
@ -606,14 +643,14 @@ 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, 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(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
|
||||
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
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
|
@ -628,4 +665,4 @@ FILE **__iob_func()
|
|||
streams[2] = stderr;
|
||||
return streams;
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -5927,6 +5927,13 @@ int sub_6DAB4C(rct_vehicle *vehicle, int *outStation)
|
|||
{
|
||||
registers regs = { 0 };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
regs.esi = (int)vehicle;
|
||||
RCT2_CALLFUNC_Y(0x006DAB4C, ®s);
|
||||
if (outStation != NULL) *outStation = regs.ebx;
|
||||
return regs.eax;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
rct_ride *ride = GET_RIDE(vehicle->ride);
|
||||
rct_ride_type *rideEntry = GET_RIDE_ENTRY(vehicle->ride_subtype);
|
||||
rct_ride_type_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle);
|
||||
|
@ -7421,7 +7428,7 @@ loc_6DD069:
|
|||
regs.ebx = RCT2_GLOBAL(0x00F64E1C, uint32);
|
||||
|
||||
end:
|
||||
hook_setreturnregisters(®s);
|
||||
// hook_setreturnregisters(®s);
|
||||
return regs.eax;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue