diff --git a/src/addresses.h b/src/addresses.h index 63d03c17a3..672d4f3a12 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -27,6 +27,7 @@ #define RCT2_ADDRESS(address, type) ((type*)(address)) #define RCT2_GLOBAL(address, type) (*((type*)(address))) +#ifdef _WIN32 #define RCT2_CALLPROC(address) (((void(*)())(address))()) #define RCT2_CALLFUNC(address, returnType) (((returnType(*)())(address))()) @@ -36,6 +37,16 @@ #define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) (((returnType(*)(a1, a2, a3, a4))(address))(v1, v2, v3, v4)) #define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) (((returnType(*)(a1, a2, a3, a4, a5))(address))(v1, v2, v3, v4, v5)) #define RCT2_CALLFUNC_6(address, returnType, a1, a2, a3, a4, a5, a6, v1, v2, v3, v4, v5, v6) (((returnType(*)(a1, a2, a3, a4, a5, a6))(address))(v1, v2, v3, v4, v5, v6)) +#else +#define RCT2_CALLPROC(address) +#define RCT2_CALLFUNC(address, returnType) +#define RCT2_CALLFUNC_1(address, returnType, a1, v1) +#define RCT2_CALLFUNC_2(address, returnType, a1, a2, v1, v2) +#define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) +#define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) +#define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) +#define RCT2_CALLFUNC_6(address, returnType, a1, a2, a3, a4, a5, a6, v1, v2, v3, v4, v5, v6) +#endif // _WIN32 #define RCT2_CALLPROC_1(address, a1, v1) RCT2_CALLFUNC_1(address, void, a1, v1) #define RCT2_CALLPROC_2(address, a1, a2, v1, v2) RCT2_CALLFUNC_2(address, void, a1, a2, v1, v2) diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index 26470fe369..4faad9c126 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -545,9 +545,13 @@ Channel* Mixer::Play(Source& source, int loop, bool deleteondone, bool deletesou void Mixer::Stop(Channel& channel) { +#ifdef _WIN32 Lock(); channel.stopping = true; Unlock(); +#else +#warning unimplemented +#endif // _WIN32 } bool Mixer::LoadMusic(int pathid) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 34f06e0026..73a2fbc7a8 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -271,7 +271,11 @@ 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*)){ diff --git a/src/interface/window.c b/src/interface/window.c index 3e9b3e3a0e..699cd15477 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -2420,7 +2420,11 @@ void textinput_cancel() // The following code is only necessary for the old Windows text input dialog. In theory this isn't used anymore, but can // still be triggered via original code paths. +#ifdef _WIN32 RCT2_CALLPROC_EBPSAFE(0x0040701D); +#else + log_warning("there should be something called here (0x0040701D)"); +#endif // _WIN32 if (RCT2_GLOBAL(0x009DEB8C, uint8) != 255) { RCT2_CALLPROC_EBPSAFE(0x006EE4E2); w = window_find_by_number( diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index e39c58a3d9..9f44cf7454 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -855,7 +855,7 @@ int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength) MultiByteToWideChar(CP_ACP, 0, src, -1, intermediateBuffer, bufferCount); int result = WideCharToMultiByte(CP_UTF8, 0, intermediateBuffer, -1, dst, maxBufferLength, NULL, NULL); #else - STUB(); + //STUB(); // we cannot walk past maxBufferLength, but in case we have still space left // we need one byte for null terminator int result = strnlen(src, maxBufferLength) + 1; diff --git a/src/openrct2.c b/src/openrct2.c index c6d7a80570..7eede9d930 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -40,6 +40,15 @@ #include "util/util.h" #include "world/mapgen.h" +#ifdef __linux__ +#include +#include +#include +#include +#include +#include +#endif // __linux__ + int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; utf8 gOpenRCT2StartupActionPath[512] = { 0 }; utf8 gExePath[MAX_PATH]; @@ -175,6 +184,86 @@ bool openrct2_initialise() return false; } +#ifdef __linux__ + #define DATA_OFFSET 0x004A4000 + + const char *exepath = "../openrct2.exe"; + int fd = open(exepath, O_RDONLY); + if (fd < 0) { + log_fatal("failed to open %s, errno = %d", exepath, errno); + exit(1); + } + + // Using PE-bear I was able to figure out all the needed addresses to be filled. + // There are three sections to be loaded: .rdata, .data and .text, plus another + // one to be mapped: DATASEG. + // Out of the three, two can simply be mmapped into memory, while the third one, + // .data has a virtual size which is much completely different to its file size + // (even when taking page-alignment into consideration) + // + // The sections are as follows (dump from gdb) + // [0] 0x401000->0x6f7000 at 0x00001000: .text ALLOC LOAD READONLY CODE HAS_CONTENTS + // [1] 0x6f7000->0x8a325d at 0x002f7000: CODESEG ALLOC LOAD READONLY CODE HAS_CONTENTS + // [2] 0x8a4000->0x9a5894 at 0x004a4000: .rdata ALLOC LOAD DATA HAS_CONTENTS + // [3] 0x9a6000->0x9e2000 at 0x005a6000: .data ALLOC LOAD DATA HAS_CONTENTS + // [4] 0x1428000->0x14282bc at 0x005e2000: DATASEG ALLOC LOAD DATA HAS_CONTENTS + // [5] 0x1429000->0x1452000 at 0x005e3000: .cms_t ALLOC LOAD READONLY CODE HAS_CONTENTS + // [6] 0x1452000->0x14aaf3e at 0x0060c000: .cms_d ALLOC LOAD DATA HAS_CONTENTS + // [7] 0x14ab000->0x14ac58a at 0x00665000: .idata ALLOC LOAD READONLY DATA HAS_CONTENTS + // [8] 0x14ad000->0x14b512f at 0x00667000: .rsrc ALLOC LOAD DATA HAS_CONTENTS + // + // .data section, however, has virtual size of 0xA81C3C, and so + // 0x9a6000 + 0xA81C3C = 0x1427C3C, which after alignment to page size becomes + // 0x1428000, which can be seen as next section, DATASEG + // + // Since mmap does not provide a way to create a mapping with virtual size, + // I resorted to creating a one large map for data and memcpy'ing data where + // required. + // Another section is needed for .text, as it requires PROT_EXEC flag. + + // TODO: UGLY, UGLY HACK! + off_t file_size = 6750208; + + int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB + // section: rw data + void *base = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); + log_warning("base = %x, 0x01423b40 >= base == %i, 0x01423b40 < base + len == %i", base, (void *)0x01423b40 >= base, (void *)0x01423b40 < base + len); + if (base == MAP_FAILED) { + log_warning("errno = %i", errno); + exit(1); + } + + len = 0x004A3000; + // section: text + void *base2 = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE, fd, 0x1000); + if (base2 != (void *)(0x401000)) + { + log_fatal("mmap failed to get required offset! got %p, expected %p, errno = %d", base2, (void *)(0x401000), errno); + exit(1); + } + + void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0); + int err = errno; + log_warning("mmapped file to %p", fbase); + if (fbase == MAP_FAILED) + { + log_fatal("mmap failed to get required offset! got %p, errno = %d", fbase, err); + exit(1); + } + // .rdata and real part of .data + // 0x9e2000 - 0x8a4000 = 0x13e000 + memcpy(base, fbase + DATA_OFFSET, 0x13e000); +#endif // __linux__ + const uint32 c1 = sawyercoding_calculate_checksum((void *)0x009ACFA4, 128); + const uint32 c2 = sawyercoding_calculate_checksum((void *)0x009ACFA4, 720 * 4); + const uint32 exp_c1 = 32640; + const uint32 exp_c2 = 734400; + log_warning("c1 = %u, expected %u, match %d", c1, exp_c1, c1 == exp_c1); + log_warning("c1 = %u, expected %u, match %d", c2, exp_c2, c2 == exp_c2); + if (c1 != exp_c1 || c2 != exp_c2) + { + exit(1); + } openrct2_set_exe_path(); config_set_defaults(); diff --git a/src/platform/linux.c b/src/platform/linux.c index f9320bdb24..055d6c01b8 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -517,7 +517,6 @@ void platform_show_cursor() void platform_get_cursor_position(int *x, int *y) { - STUB(); } diff --git a/src/rct2.c b/src/rct2.c index f0f5224f8f..025f329a52 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -567,7 +567,12 @@ void get_local_time() */ void *rct2_malloc(size_t numBytes) { + #ifdef _WIN32 return RCT2_CALLFUNC_1(0x004068B2, void*, size_t, numBytes); + #else + //log_warning("call rct's function"); + return malloc(numBytes); + #endif // _WIN32 } /** @@ -577,7 +582,12 @@ void *rct2_malloc(size_t numBytes) */ void *rct2_realloc(void *block, size_t numBytes) { + #ifdef _WIN32 return RCT2_CALLFUNC_2(0x004068BD, void*, void*, size_t, block, numBytes); + #else + //log_warning("call rct's function"); + return realloc(block, numBytes); + #endif // _WIN32 } /** @@ -586,5 +596,10 @@ void *rct2_realloc(void *block, size_t numBytes) */ void rct2_free(void *block) { + #ifdef _WIN32 RCT2_CALLPROC_1(0x004068CD, void*, block); + #else + //log_warning("call rct's function"); + free(block); + #endif // _WIN32 }