diff --git a/CMakeLists.txt b/CMakeLists.txt index 26f133133e..20a9c6416a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ if (UNIX) # force 32bit build for now and set necessary flags to compile code as is set(CMAKE_C_FLAGS "-m32 -std=gnu99") set(CMAKE_CXX_FLAGS "-m32 -std=gnu++11") - set(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,-melf_i386") + set(CMAKE_SHARED_LINKER_FLAGS "-m32") set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) diff --git a/src/input.c b/src/input.c index 88fab3a384..24c66838b6 100644 --- a/src/input.c +++ b/src/input.c @@ -543,6 +543,8 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int int scroll_part, scroll_id; int x2, y2; + assert(w != NULL); + widget = &w->widgets[widgetIndex]; if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){ invalidate_scroll(); @@ -662,6 +664,7 @@ static void input_scroll_part_update_hthumb(rct_window *w, int widgetIndex, int */ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int y, int scroll_id) { + assert(w != NULL); rct_widget *widget = &w->widgets[widgetIndex]; int newTop; @@ -699,6 +702,7 @@ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int */ static void input_scroll_part_update_hleft(rct_window *w, int widgetIndex, int scroll_id) { + assert(w != NULL); if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= HSCROLLBAR_LEFT_PRESSED; if (w->scrolls[scroll_id].h_left < 0) @@ -716,6 +720,7 @@ static void input_scroll_part_update_hleft(rct_window *w, int widgetIndex, int s */ static void input_scroll_part_update_hright(rct_window *w, int widgetIndex, int scroll_id) { + assert(w != NULL); rct_widget *widget = &w->widgets[widgetIndex]; if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= HSCROLLBAR_RIGHT_PRESSED; @@ -739,7 +744,8 @@ static void input_scroll_part_update_hright(rct_window *w, int widgetIndex, int * rct: 0x006E9C37 */ static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int scroll_id) -{; +{ + assert(w != NULL); if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= VSCROLLBAR_UP_PRESSED; if (w->scrolls[scroll_id].v_top < 0) @@ -757,6 +763,7 @@ static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int sc */ static void input_scroll_part_update_vbottom(rct_window *w, int widgetIndex, int scroll_id) { + assert(w != NULL); rct_widget *widget = &w->widgets[widgetIndex]; if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= VSCROLLBAR_DOWN_PRESSED; diff --git a/src/openrct2.c b/src/openrct2.c index a48b5ef83f..8271397a2f 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -58,6 +58,12 @@ bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; +#if defined(__linux__) +void *gDataSegment; +void *gTextSegment; +int gExeFd; +#endif // defined(__linux__) + /** 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; @@ -66,6 +72,7 @@ static struct { sint16 x, y, z; } _spritelocations1[MAX_SPRITES], _spritelocatio static void openrct2_loop(); static bool openrct2_setup_rct2_segment(); +static bool openrct2_release_rct2_segment(); static void openrct2_setup_rct2_hooks(); static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *newDirectory, const utf8 *extension) @@ -308,6 +315,7 @@ void openrct2_dispose() network_close(); http_dispose(); language_close_all(); + openrct2_release_rct2_segment(); platform_free(); } @@ -465,8 +473,8 @@ static bool openrct2_setup_rct2_segment() #define DATA_OFFSET 0x004A4000 const char *exepath = "openrct2.exe"; - int fd = open(exepath, O_RDONLY); - if (fd < 0) { + gExeFd = open(exepath, O_RDONLY); + if (gExeFd < 0) { log_fatal("failed to open %s, errno = %d", exepath, errno); exit(1); } @@ -503,23 +511,22 @@ static bool openrct2_setup_rct2_segment() 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); + 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); } len = 0x004A3000; // section: text - void *base2 = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE, fd, 0x1000); - if (base2 != (void *)(0x401000)) + gTextSegment = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); + if (gTextSegment != (void *)(0x401000)) { - log_fatal("mmap failed to get required offset! got %p, expected %p, errno = %d", base2, (void *)(0x401000), errno); + log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); exit(1); } - void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0); + void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0); int err = errno; log_warning("mmapped file to %p", fbase); if (fbase == MAP_FAILED) @@ -529,7 +536,13 @@ static bool openrct2_setup_rct2_segment() } // .rdata and real part of .data // 0x9e2000 - 0x8a4000 = 0x13e000 - memcpy(base, fbase + DATA_OFFSET, 0x13e000); + memcpy(gDataSegment, fbase + DATA_OFFSET, 0x13e000); + err = munmap(fbase, file_size); + if (err != 0) + { + err = errno; + log_error("Failed to unmap file! errno = %d", err); + } #endif // __linux__ // Check that the expected data is at various addresses. @@ -546,6 +559,41 @@ static bool openrct2_setup_rct2_segment() return true; } +/** + * Releases segments created with @ref openrct2_setup_rct2_segment, if any. + */ +static bool openrct2_release_rct2_segment() +{ + bool result = true; +#if defined(__linux__) + int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB + int err; + err = munmap(gDataSegment, len); + if (err != 0) + { + err = errno; + log_error("Failed to unmap data segment! errno = %d", err); + result = false; + } + len = 0x004A3000; + err = munmap(gTextSegment, len); + if (err != 0) + { + err = errno; + log_error("Failed to unmap text segment! errno = %d", err); + result = false; + } + err = close(gExeFd); + if (err != 0) + { + err = errno; + log_error("Failed to close file! errno = %d", err); + result = false; + } +#endif // defined(__linux__) + return result; +} + /** * Setup hooks to allow RCT2 to call OpenRCT2 functions instead. */ diff --git a/src/platform/linux.c b/src/platform/linux.c index 4fd11fc530..f68740a3fe 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -96,7 +96,7 @@ bool platform_file_exists(const utf8 *path) wcstombs(buffer, wPath, len); buffer[len] = '\0'; free(wPath); - int exists = access(buffer, F_OK) != -1; + bool exists = access(buffer, F_OK) != -1; log_warning("file '%s' exists = %i", buffer, exists); return exists; } @@ -114,9 +114,9 @@ bool platform_directory_exists(const utf8 *path) log_verbose("checking dir %s, result = %d, is_dir = %d", buffer, result, S_ISDIR(dirinfo.st_mode)); if ((result != 0) || !S_ISDIR(dirinfo.st_mode)) { - return 0; + return false; } - return 1; + return true; } bool platform_original_game_data_exists(const utf8 *path) @@ -159,13 +159,13 @@ bool platform_ensure_directory_exists(const utf8 *path) bool platform_directory_delete(const utf8 *path) { STUB(); - return 1; + return true; } bool platform_lock_single_instance() { STUB(); - return 1; + return true; } typedef struct { @@ -203,7 +203,6 @@ static int winfilter(const struct dirent *d) int platform_enumerate_files_begin(const utf8 *pattern) { - int i; enumerate_file_info *enumFileInfo; wchar_t *wpattern = utf8_to_widechar(pattern); int length = min(utf8_length(pattern), MAX_PATH); @@ -266,7 +265,7 @@ int platform_enumerate_files_begin(const utf8 *pattern) } log_warning("looking for file matching %s", g_file_pattern); int cnt; - for (i = 0; i < countof(_enumerateFileInfoList); i++) { + for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { strncpy(enumFileInfo->pattern, npattern, length); @@ -317,16 +316,15 @@ int platform_enumerate_files_begin(const utf8 *pattern) bool platform_enumerate_files_next(int handle, file_info *outFileInfo) { - bool result = true; - enumerate_file_info *enumFileInfo; if (handle < 0) { - result = false; + return false; } - enumFileInfo = &_enumerateFileInfoList[handle]; + enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle]; + bool result; - if (result && (enumFileInfo->handle < enumFileInfo->cnt)) { + if (enumFileInfo->handle < enumFileInfo->cnt) { result = true; } else { result = false; @@ -341,29 +339,26 @@ bool platform_enumerate_files_next(int handle, file_info *outFileInfo) statRes = stat(fileName, &fileInfo); if (statRes == -1) { log_error("failed to stat file '%s'! errno = %i", fileName, errno); - return 0; + return false; } outFileInfo->path = basename(fileName); outFileInfo->size = fileInfo.st_size; outFileInfo->last_modified = fileInfo.st_mtime; - return 1; + return true; } else { - return 0; + return false; } } void platform_enumerate_files_end(int handle) { - int i; - enumerate_file_info *enumFileInfo; - if (handle < 0) { return; } - enumFileInfo = &_enumerateFileInfoList[handle]; + enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle]; int cnt = enumFileInfo->cnt; - for (i = 0; i < cnt; i++) { + for (int i = 0; i < cnt; i++) { free(enumFileInfo->fileListTemp[i]); free(enumFileInfo->paths[i]); } @@ -380,7 +375,7 @@ static int dirfilter(const struct dirent *d) if (d->d_name[0] == '.') { return 0; } -#ifdef _DIRENT_HAVE_D_TYPE +#if defined(_DIRENT_HAVE_D_TYPE) || defined(DT_UNKNOWN) if (d->d_type == DT_DIR) { return 1; @@ -389,12 +384,11 @@ static int dirfilter(const struct dirent *d) } #else #error implement dirfilter! -#endif // _DIRENT_HAVE_D_TYPE +#endif // defined(_DIRENT_HAVE_D_TYPE) || defined(DT_UNKNOWN) } int platform_enumerate_directories_begin(const utf8 *directory) { - int i; enumerate_file_info *enumFileInfo; wchar_t *wpattern = utf8_to_widechar(directory); int length = min(utf8_length(directory), MAX_PATH); @@ -410,7 +404,7 @@ int platform_enumerate_directories_begin(const utf8 *directory) // TODO: add some checking for stringness and directoryness int cnt; - for (i = 0; i < countof(_enumerateFileInfoList); i++) { + for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { strncpy(enumFileInfo->pattern, npattern, length); @@ -455,13 +449,16 @@ int platform_enumerate_directories_begin(const utf8 *directory) bool platform_enumerate_directories_next(int handle, utf8 *path) { - bool result; - enumerate_file_info *enumFileInfo; + if (handle < 0) + { + return false; + } - enumFileInfo = &_enumerateFileInfoList[handle]; + bool result; + enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle]; log_verbose("handle = %d", handle); - if ((handle >= 0) && (enumFileInfo->handle < enumFileInfo->cnt)) { + if (enumFileInfo->handle < enumFileInfo->cnt) { result = true; } else { result = false; @@ -470,36 +467,32 @@ bool platform_enumerate_directories_next(int handle, utf8 *path) if (result) { int entryIdx = enumFileInfo->handle++; struct stat fileInfo; - log_verbose("trying handle %d", entryIdx); char *fileName = enumFileInfo->paths[entryIdx]; int statRes; statRes = stat(fileName, &fileInfo); if (statRes == -1) { log_error("failed to stat file '%s'! errno = %i", fileName, errno); - return 0; + return false; } // so very, very wrong… strncpy(path, basename(fileName), MAX_PATH); strncat(path, "/", MAX_PATH); path[MAX_PATH - 1] = '\0'; - return 1; + return true; } else { - return 0; + return false; } } void platform_enumerate_directories_end(int handle) { - int i; - enumerate_file_info *enumFileInfo; - if (handle < 0) { return; } - enumFileInfo = &_enumerateFileInfoList[handle]; + enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle]; int cnt = enumFileInfo->cnt; - for (i = 0; i < cnt; i++) { + for (int i = 0; i < cnt; i++) { free(enumFileInfo->fileListTemp[i]); free(enumFileInfo->paths[i]); }