diff --git a/src/hook.c b/src/hook.c
index 0471ad3037..be83f39dc3 100644
--- a/src/hook.c
+++ b/src/hook.c
@@ -8,18 +8,20 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*****************************************************************************/
#ifdef _WIN32
-#include
+ #include
+#else
+ #include
#endif // _WIN32
#include "hook.h"
#include "platform/platform.h"
@@ -28,7 +30,6 @@ void* g_hooktableaddress = 0;
int g_hooktableoffset = 0;
int g_maxhooks = 1000;
-#ifdef _WIN32
void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister)
{
int i = 0;
@@ -96,7 +97,7 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in
data[i++] = 0x00;
data[i++] = 0x00;
data[i++] = 0x00;
-
+
int sizec = i;
data[i++] = 0x8B; // push eax, [esp] - puts eip in eax
@@ -140,7 +141,7 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in
if (!(registersreturned & EDI)) {
data[i++] = 0x57; // push edi
}
-
+
data[i++] = 0x83; // sub esp, x
data[i++] = 0xEC;
data[i++] = 4 + (stacksize * 4) + rargssize;
@@ -210,18 +211,31 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in
if (!(registersreturned & EAX)) {
data[i++] = 0x58; // pop eax
}
-
+
data[i++] = 0xC3; // retn
+#ifdef _WIN32
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
-}
+#else
+ // We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data
+ memcpy((void *)address, data, i);
#endif // _WIN32
+}
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister)
{
-#ifdef _WIN32
if (!g_hooktableaddress) {
- g_hooktableaddress = VirtualAllocEx(GetCurrentProcess(), NULL, g_maxhooks * 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ size_t size = g_maxhooks * 100;
+#ifdef _WIN32
+ g_hooktableaddress = VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+#else
+ g_hooktableaddress = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (g_hooktableaddress == MAP_FAILED)
+ {
+ perror("mmap");
+ exit(1);
+ }
+#endif // _WIN32
}
if (g_hooktableoffset > g_maxhooks) {
return;
@@ -232,10 +246,12 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int
data[i++] = 0xE9; // jmp
*((int *)&data[i]) = hookaddress - address - i - 4; i += 4;
data[i++] = 0xC3; // retn
+#ifdef _WIN32
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
+#else
+ // 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);
g_hooktableoffset++;
-#else
- STUB();
-#endif // _WIN32
}
diff --git a/src/interface/viewport.c b/src/interface/viewport.c
index 5ec11bf5a4..11175a52d6 100644
--- a/src/interface/viewport.c
+++ b/src/interface/viewport.c
@@ -271,11 +271,7 @@ void sub_689174(sint16* x, sint16* y, sint16 *z)
void sub_6E7FF3(rct_window *w, rct_viewport *viewport, int x, int y)
{
-#ifdef _WIN32
RCT2_CALLPROC_X(0x006E7FF3, 0, 0, 0, x, (int)viewport, (int)w, y);
-#else
- STUB();
-#endif // _WIN32
// int zoom = 1 << viewport->zoom;
// if (w >= RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*)){