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);