diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 6b3bb9f23a..505725ffa4 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -66,6 +66,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index c095b394ad..e71a9b1250 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -299,6 +299,9 @@ Source Files + + Source Files + diff --git a/src/addresses.h b/src/addresses.h index bf7e95c7f8..296a1b44ae 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -86,6 +86,8 @@ #define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319 +#define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 + #define RCT2_ADDRESS_INPUT_STATE 0x009DE51D #define RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS 0x009DE51F #define RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER 0x009DE520 diff --git a/src/game.c b/src/game.c index ef6cca9b84..fd6fa75af7 100644 --- a/src/game.c +++ b/src/game.c @@ -1494,7 +1494,7 @@ int game_load_save() for (i = 0; i < s6Header->num_packed_objects; i++) j += object_load_packed(); if (j > 0) - object_load_list(); + object_list_load(); } } diff --git a/src/object.c b/src/object.c index 1a98a2a482..63093aabf4 100644 --- a/src/object.c +++ b/src/object.c @@ -16,45 +16,4 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . - *****************************************************************************/ - -#include "addresses.h" -#include "object.h" - -/** - * - * rct2: 0x006A8B40 - */ -void object_load_list() -{ - RCT2_CALLPROC_EBPSAFE(0x006A8B40); -} - -/** - * - * rct2: 0x006AA0C6 - */ -void object_read_and_load_entries(HANDLE hFile) -{ - RCT2_CALLPROC_EBPSAFE(0x006AA0C6); - - // int i; - // rct_object_entry *entries; - // entries = malloc(721 * sizeof(rct_object_entry)); - // sawyercoding_read_chunk(hFile, entries); - // for (i = 0; i < 721; i++) { - // RCT2_CALLPROC_X(0x006A985D, 0, 0, i, 0, 0, 0, 0); - // } - // free(entries); -} - -/** - * - * rct2: 0x006AA2B7 - */ -int object_load_packed() -{ - int eax, ebx, ecx, edx, esi, edi, ebp; - RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return eax; -} + *****************************************************************************/ \ No newline at end of file diff --git a/src/object.h b/src/object.h index 3549548bab..6479909f8d 100644 --- a/src/object.h +++ b/src/object.h @@ -34,7 +34,7 @@ typedef struct { uint32 var_0C; } rct_object_entry; -void object_load_list(); +void object_list_load(); void object_read_and_load_entries(HANDLE hFile); int object_load_packed(); diff --git a/src/object_list.c b/src/object_list.c new file mode 100644 index 0000000000..9df99a6889 --- /dev/null +++ b/src/object_list.c @@ -0,0 +1,162 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * 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 . + *****************************************************************************/ + +#include +#include "addresses.h" +#include "object.h" + +typedef struct { + uint32 total_files; + uint32 total_file_size; + uint32 date_modified_checksum; + uint32 object_list_size; + uint32 var_10; +} rct_plugin_header; + +/** + * + * rct2: 0x006A93CD + */ +static void object_list_examine() +{ + int i; + char *object; + + object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, char*); + for (i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) { + if (*object & 0xF0) + RCT2_GLOBAL(0x00F42BDA, uint8) |= 1; + object += 16; + + // Skip filename + // printf("%d %s : ", i, object); + do { + object++; + } while (*(object - 1) != 0); + object += 4; + + // Skip name + // printf("%s\n", object); + do { + object++; + } while (*(object - 1) != 0); + object += 4; + + object += *object++ * 16; + object += *object++ * 16; + object += 4; + } +} + +/** + * + * rct2: 0x006A8B40 + */ +void object_list_load() +{ + HANDLE hFindFile; + WIN32_FIND_DATAA findFileData; + int totalFiles = 0, totalFileSize = 0, fileDateModifiedChecksum = 0; + + // Enumerate through each object in the directory + hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); + if (hFindFile != INVALID_HANDLE_VALUE) { + do { + totalFiles++; + totalFileSize += findFileData.nFileSizeLow; + fileDateModifiedChecksum ^= + findFileData.ftLastWriteTime.dwLowDateTime ^ + findFileData.ftLastWriteTime.dwHighDateTime; + fileDateModifiedChecksum = ror32(fileDateModifiedChecksum, 5); + } while (FindNextFile(hFindFile, &findFileData)); + FindClose(hFindFile); + } + + totalFiles = ror32(totalFiles, 24); + totalFiles = (totalFiles & ~0xFF) | 1; + totalFiles = rol32(totalFiles, 24); + + // Read plugin header + rct_plugin_header pluginHeader; + FILE *file = fopen(get_file_path(PATH_ID_PLUGIN), "rb"); + if (file != NULL) { + if (fread(&pluginHeader, sizeof(pluginHeader), 1, file) == 1) { + // Check if object repository has changed in anyway + if ( + totalFiles == pluginHeader.total_files && + totalFileSize == pluginHeader.total_file_size && + fileDateModifiedChecksum == pluginHeader.date_modified_checksum + ) { + // Dispose installed object list + if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { + rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); + RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; + } + + // Read installed object list + RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(pluginHeader.object_list_size); + if (fread(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), pluginHeader.object_list_size, 1, file) == 1) { + RCT2_GLOBAL(0x00F42B6C, uint32) = pluginHeader.var_10; + + fclose(file); + RCT2_CALLPROC_EBPSAFE(0x006A9FC0); + object_list_examine(); + return; + } + } + } + fclose(file); + } + + // Reload object list + RCT2_GLOBAL(0x00F42B94, uint32) = totalFiles; + RCT2_GLOBAL(0x00F42B98, uint32) = totalFileSize; + RCT2_GLOBAL(0x00F42B9C, uint32) = fileDateModifiedChecksum; + RCT2_CALLPROC_EBPSAFE(0x006A8D8F); +} + +/** + * + * rct2: 0x006AA0C6 + */ +void object_read_and_load_entries(HANDLE hFile) +{ + RCT2_CALLPROC_EBPSAFE(0x006AA0C6); + + // int i; + // rct_object_entry *entries; + // entries = malloc(721 * sizeof(rct_object_entry)); + // sawyercoding_read_chunk(hFile, entries); + // for (i = 0; i < 721; i++) { + // RCT2_CALLPROC_X(0x006A985D, 0, 0, i, 0, 0, 0, 0); + // } + // free(entries); +} + +/** + * + * rct2: 0x006AA2B7 + */ +int object_load_packed() +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return eax; +} diff --git a/src/rct2.c b/src/rct2.c index 239a264ac5..6bd29dc5c3 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -145,7 +145,7 @@ void rct2_init() RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; config_load(); // RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap - object_load_list(); + object_list_load(); scenario_load_list(); track_load_list(253); gfx_load_g1(); diff --git a/src/scenario.c b/src/scenario.c index 4ecb88ca17..fb1efc6f08 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -147,7 +147,7 @@ void scenario_load(const char *path) for (i = 0; i < s6Header->num_packed_objects; i++) j += object_load_packed(); if (j > 0) - object_load_list(); + object_list_load(); } object_read_and_load_entries(hFile);