diff --git a/src/object.c b/src/object.c
index c09c3de10a..58f4dd33b6 100644
--- a/src/object.c
+++ b/src/object.c
@@ -18,8 +18,11 @@
* along with this program. If not, see .
*****************************************************************************/
+#include
+#include
#include "addresses.h"
#include "object.h"
+#include "sawyercoding.h"
/**
*
@@ -47,19 +50,188 @@ void object_unload(int groupIndex, rct_object_entry_extended *entry)
RCT2_CALLPROC_X(0x006A9CAF, 0, groupIndex, 0, 0, 0, 0, (int)entry);
}
+static int object_entry_compare(rct_object_entry *a, rct_object_entry *b)
+{
+ if (a->flags & 0xF0) {
+ if ((a->flags & 0x0F) != (b->flags & 0x0F))
+ return 0;
+ if (*((uint32*)a->name) != *((uint32*)b->name))
+ return 0;
+ if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
+ return 0;
+ } else {
+ if (a->flags != b->flags)
+ return 0;
+ if (*((uint32*)a->name) != *((uint32*)b->name))
+ return 0;
+ if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
+ return 0;
+ if (a->checksum != b->checksum)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength)
+{
+ int i;
+ char *eee = (char*)entry;
+ int checksum = 0xF369A75B;
+ char *ccc = (char*)&checksum;
+
+ *ccc ^= eee[0];
+ checksum = rol32(checksum, 11);
+ for (i = 4; i < 12; i++) {
+ *ccc ^= eee[i];
+ checksum = rol32(checksum, 11);
+ }
+ for (i = 0; i < dataLength; i++) {
+ *ccc ^= data[i];
+ checksum = rol32(checksum, 11);
+ }
+
+ return checksum;
+}
+
+int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp)
+{
+ RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp);
+ #ifdef _MSC_VER
+ __asm jb success
+ #else
+ __asm__ goto ( "jb %l0" : : : : success );
+ #endif
+ return 0;
+success:
+ return 1;
+}
+
/**
*
* rct2: 0x006A9428
*/
-int sub_6A9428(rct_object_entry* entry)
+int object_get_scenario_text(rct_object_entry *entry)
{
- RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry);
- #ifdef _MSC_VER
- __asm jb fail
- #else
- __asm__ goto ( "jb %l0" : : : : fail );
- #endif
- return 1;
-fail:
+ // RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry); return;
+
+ int i;
+ rct_object_entry *installedObject = RCT2_GLOBAL(0x009ADAE8, rct_object_entry*);
+ for (i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
+ if (object_entry_compare(installedObject, entry)) {
+ char path[260];
+ char *objectPath = (char*)installedObject + 16;
+ subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath);
+
+ rct_object_entry openedEntry;
+ FILE *file = fopen(path, "rb");
+ if (file != NULL) {
+ fread(&openedEntry, sizeof(rct_object_entry), 1, file);
+ if (object_entry_compare(&openedEntry, entry)) {
+
+ // Get chunk size
+ char *pos = (char*)installedObject + 16;
+ do {
+ pos++;
+ } while (*(pos - 1) != 0);
+
+ // Read chunk
+ int chunkSize = *((uint32*)pos);
+ char *chunk;
+ if (chunkSize == 0xFFFFFFFF) {
+ chunk = malloc(0x600000);
+ chunkSize = sawyercoding_read_chunk(file, chunk);
+ chunk = realloc(chunk, chunkSize);
+ } else {
+ chunk = malloc(chunkSize);
+ sawyercoding_read_chunk(file, chunk);
+ }
+ fclose(file);
+
+ // Calculate and check checksum
+ if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) {
+ RCT2_GLOBAL(0x00F42BD9, uint8) = 2;
+ free(chunk);
+ return 0;
+ }
+
+ if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) {
+ RCT2_GLOBAL(0x00F42BD9, uint8) = 3;
+ free(chunk);
+ return 0;
+ }
+
+ int yyy = RCT2_GLOBAL(0x009ADAF0, uint32);
+ RCT2_GLOBAL(0x009ADAF0, uint32) = 0x726E;
+ RCT2_GLOBAL(0x009ADAF8, uint32) = (int)chunk;
+ *((rct_object_entry*)0x00F42BC8) = openedEntry;
+
+ RCT2_GLOBAL(0x009ADAFC, uint8) = 255;
+ RCT2_GLOBAL(0x009ADAFD, uint8) = 1;
+ object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0);
+ RCT2_GLOBAL(0x009ADAFC, uint8) = 0;
+ RCT2_GLOBAL(0x009ADAFD, uint8) = 0;
+ RCT2_GLOBAL(0x009ADAF0, uint32) = yyy;
+ return 1;
+ }
+ fclose(file);
+ }
+ }
+ installedObject = object_get_next(installedObject);
+ }
+
+ RCT2_GLOBAL(0x00F42BD9, uint8) = 0;
return 0;
+}
+
+/**
+ *
+ * rct2: 0x006A982D
+ */
+void object_free_scenario_text()
+{
+ if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) {
+ free(RCT2_GLOBAL(0x009ADAF8, void*));
+ RCT2_GLOBAL(0x009ADAF8, void*) = NULL;
+ }
+}
+
+int object_get_length(rct_object_entry *entry)
+{
+ return (int)object_get_next(entry) - (int)entry;
+}
+
+rct_object_entry *object_get_next(rct_object_entry *entry)
+{
+ char *pos = (char*)entry;
+
+ // Skip
+ pos += 16;
+
+ // Skip filename
+ do {
+ pos++;
+ } while (*(pos - 1) != 0);
+
+ // Skip
+ pos += 4;
+
+ // Skip name
+ do {
+ pos++;
+ } while (*(pos - 1) != 0);
+
+ // Skip
+ pos += 4;
+
+ // Skip
+ pos += *pos++ * 16;
+
+ // Skip theme objects
+ pos += *pos++ * 16;
+
+ // Skip
+ pos += 4;
+
+ return (rct_object_entry*)pos;
}
\ No newline at end of file
diff --git a/src/object.h b/src/object.h
index ea6f47103f..a9d8bdbdfc 100644
--- a/src/object.h
+++ b/src/object.h
@@ -52,6 +52,9 @@ void object_unload_all();
int object_load(int groupIndex, rct_object_entry *entry);
void object_unload(int groupIndex, rct_object_entry_extended *entry);
-int sub_6A9428(rct_object_entry* entry);
+int object_get_scenario_text(rct_object_entry *entry);
+void object_free_scenario_text();
+int object_get_length(rct_object_entry *entry);
+rct_object_entry *object_get_next(rct_object_entry *entry);
#endif
diff --git a/src/object_list.c b/src/object_list.c
index 0a318e71e8..78d5686d07 100644
--- a/src/object_list.c
+++ b/src/object_list.c
@@ -69,42 +69,14 @@ struct { void **data; rct_object_entry_extended *entries; } object_entry_groups[
static void object_list_examine()
{
int i;
- char *object;
+ rct_object_entry *object;
- object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, char*);
+ object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
for (i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
- if (*object & 0xF0)
+ if (object->flags & 0xF0)
RCT2_GLOBAL(0x00F42BDA, uint8) |= 1;
- // Skip
- object += 16;
-
- // Skip filename
- // printf("%d %s : ", i, object);
- do {
- object++;
- } while (*(object - 1) != 0);
-
- // Skip
- object += 4;
-
- // Skip name
- // printf("%s\n", object);
- do {
- object++;
- } while (*(object - 1) != 0);
-
- // Skip
- object += 4;
-
- // Skip
- object += *object++ * 16;
-
- // Skip theme objects
- object += *object++ * 16;
-
- // Skip
- object += 4;
+ object = object_get_next(object);
}
}
diff --git a/src/scenario.c b/src/scenario.c
index 9fdd0c0003..c6a9c4d6d3 100644
--- a/src/scenario.c
+++ b/src/scenario.c
@@ -59,14 +59,12 @@ int scenario_load_basic(const char *path)
// Checks for a scenario string object (possibly for localisation)
if ((s6Info->entry.flags & 0xFF) != 255) {
- if (sub_6A9428(&s6Info->entry)) {
+ if (object_get_scenario_text(&s6Info->entry)) {
int ebp = RCT2_GLOBAL(0x009ADAF8, uint32);
format_string(s6Info->name, RCT2_GLOBAL(ebp, sint16), NULL);
format_string(s6Info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL);
RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8);
-
- // Disposes the scenario string object (0x009ADAF8)
- RCT2_CALLPROC_EBPSAFE(0x006A982D);
+ object_free_scenario_text();
}
}
return 1;