From f8f70d8d08927748bf48a1335206c04f4bf06328 Mon Sep 17 00:00:00 2001 From: Patrick Wijnings Date: Sun, 15 Jun 2014 15:10:35 +0200 Subject: [PATCH 1/5] rct2.c: port get_file_path. --- src/config.c | 2 +- src/rct2.c | 37 +++++++++++++++++++++++++---- src/rct2.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 7 deletions(-) diff --git a/src/config.c b/src/config.c index 41551d94a5..c82a4cb8b1 100644 --- a/src/config.c +++ b/src/config.c @@ -125,7 +125,7 @@ void config_load() { FILE *fp=NULL; - char* path = get_file_path(PATH_ID_GAMECFG); + const char *path = get_file_path(PATH_ID_GAMECFG); fp = fopen(path, "rb"); diff --git a/src/rct2.c b/src/rct2.c index a7b41aedab..6feea21df6 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -344,13 +344,40 @@ void rct2_endupdate() * * rct2: 0x00674E6C */ -char *get_file_path(int pathId) +const char *get_file_path(int pathId) { - int eax, ebx, ecx, edx, esi, edi, ebp; + static char path[MAX_PATH]; // get_file_path_buffer @ 0x009E3605 - ebx = pathId; - RCT2_CALLFUNC_X(0x00674E6C, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return (char*)ebx; + // The original implementation has a check for 0x009AA0B1 here. That flag is set + // by check_file_path if the file cannot be found in its default location, but this + // only seems to be the case for versions that require a CD-ROM. Therefore it has + // been removed. + strcpy(path, gGeneral_config.game_path); + + // Make sure base path is terminated with a slash + if (strlen(path) == 0 || path[strlen(path) - 1] != '\\') + { + if (strlen(path) >= MAX_PATH - 1) + { + RCT2_ERROR("Path for %s too long", file_paths[pathId]); + path[0] = '\0'; + return path; + } + + strcat(path, "\\"); + } + + // Concatenate file path + if (strlen(path) + strlen(file_paths[pathId]) > MAX_PATH) + { + RCT2_ERROR("Path for %s too long", file_paths[pathId]); + path[0] = '\0'; + return path; + } + + strcat(path, file_paths[pathId]); + + return path; } /** diff --git a/src/rct2.h b/src/rct2.h index f5b765b206..cbb0dbdcfa 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -158,12 +158,77 @@ enum { PATH_ID_CSS44, PATH_ID_CSS45, PATH_ID_CSS46 +}; +static const char * const file_paths[] = +{ + "Data\\G1.DAT", + "Data\\PLUGIN.DAT", + "Data\\CSS1.DAT", + "Data\\CSS2.DAT", + "Data\\CSS4.DAT", + "Data\\CSS5.DAT", + "Data\\CSS6.DAT", + "Data\\CSS7.DAT", + "Data\\CSS8.DAT", + "Data\\CSS9.DAT", + "Data\\CSS10.DAT", + "Data\\CSS11.DAT", + "Data\\CSS12.DAT", + "Data\\CSS13.DAT", + "Data\\CSS14.DAT", + "Data\\CSS15.DAT", + "Data\\CSS16.DAT", + "Data\\CSS3.DAT", + "Data\\GAME.CFG", + "Data\\TUT640A.DAT", + "Data\\TUT640B.DAT", + "Data\\TUT640C.DAT", + "Data\\TUT800A.DAT", + "Data\\TUT800B.DAT", + "Data\\TUT800C.DAT", + "Data\\KANJI.DAT", + "Data\\CSS17.DAT", + "Data\\CSS18.DAT", + "Data\\CSS19.DAT", + "Data\\CSS20.DAT", + "Data\\CSS21.DAT", + "Data\\CSS22.DAT", + "Saved Games\\scores.DAT", + "Data\\CSS23.DAT", + "Data\\CSS24.DAT", + "Data\\CSS25.DAT", + "Data\\CSS26.DAT", + "Data\\CSS27.DAT", + "Data\\CSS28.DAT", + "Data\\CSS29.DAT", + "Data\\CSS30.DAT", + "Data\\CSS31.DAT", + "Data\\CSS32.DAT", + "Data\\CSS33.DAT", + "Data\\CSS34.DAT", + "Data\\CSS35.DAT", + "Data\\CSS36.DAT", + "Data\\CSS37.DAT", + "Data\\CSS38.DAT", + "Data\\CUSTOM1.WAV", + "Data\\CUSTOM2.WAV", + "Data\\CSS39.DAT", + "Data\\CSS40.DAT", + "Tracks\\Tracks.IDX", + "Data\\CSS41.DAT", + "Scenarios\\Six Flags Magic Mountain.SC6", + "Scenarios\\Build your own Six Flags Park.SC6", + "Data\\CSS42.DAT", + "Data\\CSS43.DAT", + "Data\\CSS44.DAT", + "Data\\CSS45.DAT", + "Data\\CSS46.DAT" }; void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); -char *get_file_path(int pathId); +const char *get_file_path(int pathId); void get_system_info(); void get_system_time(); void get_local_time(); From bf8bc151b908574ab6fc48b1ecf29be55411ec6f Mon Sep 17 00:00:00 2001 From: Patrick Wijnings Date: Thu, 19 Jun 2014 13:51:54 +0200 Subject: [PATCH 2/5] rct2.c: port check_mutex(). --- src/rct2.c | 25 ++++++++++++++++++++++++- src/rct2.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/rct2.c b/src/rct2.c index 6feea21df6..15b3715392 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -230,7 +230,12 @@ void subsitute_path(char *dest, const char *path, const char *filename) // rct2: 0x00674B42 void rct2_startup_checks() { - // check if game is already running + // Check if game is already running + if (check_mutex()) + { + RCT2_ERROR("Game is already running"); + RCT2_CALLPROC_X(0x006E3838, 0x343, 0xB2B, 0, 0, 0, 0, 0); // exit_with_error + } RCT2_CALLPROC_EBPSAFE(0x00674C0B); } @@ -303,6 +308,24 @@ void check_cmdline_arg() } } +// rct2: 0x00407DB0 +int check_mutex() +{ + const char * const mutex_name = "RollerCoaster Tycoon 2_GSKMUTEX"; // rct2 @ 0x009AAC3D + 0x009A8B50 + + HANDLE mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, mutex_name); + + if (mutex != NULL) + { + // Already running + CloseHandle(mutex); + return 1; + } + + HANDLE status = CreateMutex(NULL, FALSE, mutex_name); + return 0; +} + void rct2_update_2() { int tick, tick2; diff --git a/src/rct2.h b/src/rct2.h index cbb0dbdcfa..a03d1c7352 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -228,6 +228,7 @@ static const char * const file_paths[] = void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); +int check_mutex(); const char *get_file_path(int pathId); void get_system_info(); void get_system_time(); From 14aba8e7d9eb7dd430723e38bbf14b1f73d94047 Mon Sep 17 00:00:00 2001 From: Patrick Wijnings Date: Thu, 19 Jun 2014 13:52:34 +0200 Subject: [PATCH 3/5] rct2.c: port check_files_integrity(). --- src/rct2.c | 28 +++++++++++++++++++++++++++- src/rct2.h | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/rct2.c b/src/rct2.c index 15b3715392..ceb6b3ef5d 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -237,7 +237,9 @@ void rct2_startup_checks() RCT2_CALLPROC_X(0x006E3838, 0x343, 0xB2B, 0, 0, 0, 0, 0); // exit_with_error } - RCT2_CALLPROC_EBPSAFE(0x00674C0B); + // Check data files + // TODO: implement check_file_paths @ 0x00674C95 + check_files_integrity(); } void rct2_update() @@ -326,6 +328,30 @@ int check_mutex() return 0; } +// rct2: 0x00674C0B +void check_files_integrity() +{ + int i = 0; + while (files_to_check[i].path_id != PATH_ID_END) + { + WIN32_FIND_DATA find_data; + const char * path = get_file_path(files_to_check[i].path_id); + HANDLE file = FindFirstFile(path, &find_data); + + if (file == INVALID_HANDLE_VALUE || find_data.nFileSizeLow != files_to_check[i].file_size) + { + if (file != INVALID_HANDLE_VALUE) + FindClose(file); + RCT2_ERROR("Integrity check failed for %s", path); + RCT2_CALLPROC_X(0x006E3838, 0x343, 0x337, 0, 0, 0, 0, 0); // exit_with_error + } + + FindClose(file); + + i += 1; + } +} + void rct2_update_2() { int tick, tick2; diff --git a/src/rct2.h b/src/rct2.h index a03d1c7352..0ef5a0af91 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -157,9 +157,11 @@ enum { PATH_ID_CSS43, PATH_ID_CSS44, PATH_ID_CSS45, - PATH_ID_CSS46 + PATH_ID_CSS46, + PATH_ID_END }; +// rct2 @ 0x0097F67C static const char * const file_paths[] = { "Data\\G1.DAT", @@ -226,9 +228,42 @@ static const char * const file_paths[] = "Data\\CSS46.DAT" }; +// Files to check (rct2 @ 0x0097FB5A) +static const struct file_to_check +{ + int path_id; // ID of file + unsigned int file_size; // Expected size in bytes +} files_to_check[] = { + { PATH_ID_CSS18, 8429568 }, + { PATH_ID_CSS19, 10143784 }, + { PATH_ID_CSS20, 12271656 }, + { PATH_ID_CSS21, 9680968 }, + { PATH_ID_CSS22, 10062056 }, + { PATH_ID_CSS23, 11067432 }, + { PATH_ID_CSS24, 12427456 }, + { PATH_ID_CSS25, 15181512 }, + { PATH_ID_CSS26, 10694816 }, + { PATH_ID_CSS27, 10421232 }, + { PATH_ID_CSS28, 13118376 }, + { PATH_ID_CSS29, 15310892 }, + { PATH_ID_CSS30, 10215464 }, + { PATH_ID_CSS31, 11510316 }, + { PATH_ID_CSS32, 11771944 }, + { PATH_ID_CSS33, 10759724 }, + { PATH_ID_CSS34, 14030716 }, + { PATH_ID_CSS35, 11642576 }, + { PATH_ID_CSS36, 8953764 }, + { PATH_ID_CSS37, 13303852 }, + { PATH_ID_CSS38, 10093888 }, + { PATH_ID_CSS39, 7531564 }, + { PATH_ID_CSS40, 5291306 }, + { PATH_ID_END, 0 } +}; + void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); int check_mutex(); +void check_files_integrity(); const char *get_file_path(int pathId); void get_system_info(); void get_system_time(); From 7cf1f988274ea4cbfad856a6aa5662605e5c4747 Mon Sep 17 00:00:00 2001 From: Patrick Wijnings Date: Sat, 28 Jun 2014 20:44:33 +0200 Subject: [PATCH 4/5] rct2.c: make naming inside check_files_integrity consistent with get_file_path. --- src/rct2.c | 6 +++--- src/rct2.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rct2.c b/src/rct2.c index ceb6b3ef5d..5b989d9dbf 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -332,13 +332,13 @@ int check_mutex() void check_files_integrity() { int i = 0; - while (files_to_check[i].path_id != PATH_ID_END) + while (files_to_check[i].pathId != PATH_ID_END) { WIN32_FIND_DATA find_data; - const char * path = get_file_path(files_to_check[i].path_id); + const char * path = get_file_path(files_to_check[i].pathId); HANDLE file = FindFirstFile(path, &find_data); - if (file == INVALID_HANDLE_VALUE || find_data.nFileSizeLow != files_to_check[i].file_size) + if (file == INVALID_HANDLE_VALUE || find_data.nFileSizeLow != files_to_check[i].fileSize) { if (file != INVALID_HANDLE_VALUE) FindClose(file); diff --git a/src/rct2.h b/src/rct2.h index 0ef5a0af91..34233aee85 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -231,8 +231,8 @@ static const char * const file_paths[] = // Files to check (rct2 @ 0x0097FB5A) static const struct file_to_check { - int path_id; // ID of file - unsigned int file_size; // Expected size in bytes + int pathId; // ID of file + unsigned int fileSize; // Expected size in bytes } files_to_check[] = { { PATH_ID_CSS18, 8429568 }, { PATH_ID_CSS19, 10143784 }, From eee3118a3a5c4b1b80baa28a7ac5c4996683f695 Mon Sep 17 00:00:00 2001 From: Patrick Wijnings Date: Sat, 28 Jun 2014 20:45:25 +0200 Subject: [PATCH 5/5] rct2.c: port check_file_paths and check_file_path. --- src/rct2.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/rct2.h | 2 ++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/rct2.c b/src/rct2.c index 5b989d9dbf..d532be976f 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -238,7 +238,7 @@ void rct2_startup_checks() } // Check data files - // TODO: implement check_file_paths @ 0x00674C95 + check_file_paths(); check_files_integrity(); } @@ -328,6 +328,57 @@ int check_mutex() return 0; } +// rct2: 0x00674C95 +void check_file_paths() +{ + for (int pathId = 0; pathId < PATH_ID_END; pathId += 1) + { + check_file_path(pathId); + } +} + +// rct2: 0x00674CA5 +void check_file_path(int pathId) +{ + const char * path = get_file_path(pathId); + HANDLE file = CreateFile(path, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + + switch (pathId) + { + case PATH_ID_GAMECFG: + case PATH_ID_SCORES: + // Do nothing; these will be created later if they do not exist yet + break; + + case PATH_ID_CUSTOM1: + if (file != INVALID_HANDLE_VALUE) + RCT2_GLOBAL(0x009AF164, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom1_size @ 0x009AF164 + break; + + case PATH_ID_CUSTOM2: + if (file != INVALID_HANDLE_VALUE) + RCT2_GLOBAL(0x009AF16E, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom2_size @ 0x009AF16E + break; + + default: + if (file == INVALID_HANDLE_VALUE) { + // A data file is missing from the installation directory. The original implementation + // asks for a CD-ROM path at this point and stores it in cdrom_path @ 0x9AA318. + // The file_on_cdrom[pathId] @ 0x009AA0B flag is set to 1 as well. + // For PATH_ID_SIXFLAGS_MAGICMOUNTAIN and PATH_ID_SIXFLAGS_BUILDYOUROWN, + // the original implementation always assumes they are stored on CD-ROM. + // This has been removed for now for the sake of simplicity and could be added + // later in a more convenient way using the INI file. + RCT2_ERROR("Could not find file %s", path); + RCT2_CALLPROC_X(0x006E3838, 0x343, 0x337, 0, 0, 0, 0, 0); // exit_with_error + } + break; + } + + if (file != INVALID_HANDLE_VALUE) + CloseHandle(file); +} + // rct2: 0x00674C0B void check_files_integrity() { @@ -397,10 +448,9 @@ const char *get_file_path(int pathId) { static char path[MAX_PATH]; // get_file_path_buffer @ 0x009E3605 - // The original implementation has a check for 0x009AA0B1 here. That flag is set - // by check_file_path if the file cannot be found in its default location, but this - // only seems to be the case for versions that require a CD-ROM. Therefore it has - // been removed. + // The original implementation checks if the file is on CD-ROM here (file_on_cdrom[pathId] @ 0x009AA0B1). + // If so, the CD-ROM path (cdrom_path @ 0x9AA318) is used instead. This has been removed for now for + // the sake of simplicity. strcpy(path, gGeneral_config.game_path); // Make sure base path is terminated with a slash diff --git a/src/rct2.h b/src/rct2.h index 34233aee85..dcdb81bcc0 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -263,6 +263,8 @@ static const struct file_to_check void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); int check_mutex(); +void check_file_paths(); +void check_file_path(int pathId); void check_files_integrity(); const char *get_file_path(int pathId); void get_system_info();