diff --git a/src/object.c b/src/object.c index 092047756a..03ce1d7d80 100644 --- a/src/object.c +++ b/src/object.c @@ -42,9 +42,9 @@ int object_load_entry(const char *path, rct_object_entry *outEntry) return 1; } -static int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSize, const rct_object_entry *installedObject) +int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSize, const rct_object_entry *installedObject) { - int i, objectType; + uint8 objectType; rct_object_entry openedEntry; char path[260]; FILE *file; @@ -64,13 +64,12 @@ static int object_load_file(int groupIndex, const rct_object_entry *entry, int* } // Get chunk size - char *pos = (char*)installedObject + 16; - do { - pos++; - } while (*(pos - 1) != 0); + uint8 *installedObject_pointer = (uint8*)installedObject + 16; + // Skip file name + while (*installedObject_pointer++); - // Read chunk - *chunkSize = *((uint32*)pos); + // Read chunk size + *chunkSize = *((uint32*)installedObject_pointer); char *chunk; if (*chunkSize == 0xFFFFFFFF) { @@ -94,7 +93,9 @@ static int object_load_file(int groupIndex, const rct_object_entry *entry, int* return 0; } - if (object_paint(openedEntry.flags & 0x0F, 2, 0, openedEntry.flags & 0x0F, 0, (int)chunk, 0, 0)) { + objectType = openedEntry.flags & 0x0F; + + if (object_paint(objectType, 2, 0, objectType, 0, (int)chunk, 0, 0)) { log_error("Object Load failed due to paint failure."); RCT2_GLOBAL(0x00F42BD9, uint8) = 3; rct2_free(chunk); @@ -109,31 +110,29 @@ static int object_load_file(int groupIndex, const rct_object_entry *entry, int* rct2_free(chunk); return 0; } - //B84 is openedEntry - objectType = openedEntry.flags & 0x0F; - int esi = RCT2_ADDRESS(0x98D97C, uint32)[objectType * 2]; + + uint8** chunk_list = object_entry_groups[objectType].chunks; if (groupIndex == -1) { - for (i = 0; ((sint32*)esi)[i] != -1; i++) { - if (i + 1 >= object_entry_group_counts[objectType]) { - log_error("Object Load failed due to ??? failure."); + for (groupIndex = 0; chunk_list[groupIndex] != (uint8*)-1; groupIndex++) { + if (groupIndex + 1 >= object_entry_group_counts[objectType]) { + log_error("Object Load failed due to too many objects of a certain type."); RCT2_GLOBAL(0x00F42BD9, uint8) = 5; rct2_free(chunk); return 0; } } - groupIndex = i; } - ((char**)esi)[groupIndex] = chunk; + chunk_list[groupIndex] = chunk; - int* edx = (int*)(groupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[objectType * 2]); - memcpy(edx, (int*)&openedEntry, 20); + rct_object_entry_extended* extended_entry = &object_entry_groups[objectType].entries[groupIndex]; + + memcpy(extended_entry, &openedEntry, sizeof(rct_object_entry)); + extended_entry->chunk_size = *chunkSize; RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, char*) = chunk; - if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0) - return 1; - - object_paint(objectType, 0, groupIndex, objectType, 0, (int)chunk, 0, 0); + if (RCT2_GLOBAL(0x9ADAFD, uint8) != 0) + object_paint(objectType, 0, groupIndex, objectType, 0, (int)chunk, 0, 0); return 1; } @@ -180,20 +179,20 @@ int sub_6A9F42(FILE *file, rct_object_entry* entry){ object_paint(type, 1, entryGroupIndex, type, edx, chunk, edi, ebp); - rct_object_entry* installed_entry = (rct_object_entry*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + rct_object_entry_extended* installed_entry = &object_entry_groups[type].entries[entryGroupIndex]; uint8* dst_buffer = malloc(0x600000); - memcpy(dst_buffer, (void*)installed_entry, 16); + memcpy(dst_buffer, (uint8*)installed_entry, sizeof(rct_object_entry)); - uint32 size_dst = 16; + uint32 size_dst = sizeof(rct_object_entry); sawyercoding_chunk_header chunkHeader; // Encoding type (not used anymore) RCT2_GLOBAL(0x9E3CBD, uint8) = object_entry_group_encoding[type]; chunkHeader.encoding = object_entry_group_encoding[type]; - chunkHeader.length = *(uint32*)(((uint8*)installed_entry + 16)); + chunkHeader.length = installed_entry->chunk_size; - size_dst += sawyercoding_write_chunk_buffer(dst_buffer+16, (uint8*)chunk, chunkHeader); + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), (uint8*)chunk, chunkHeader); fwrite(dst_buffer, 1, size_dst, file); free(dst_buffer); @@ -242,7 +241,7 @@ int object_load_packed(FILE *file) int entryGroupIndex = 0; for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ - if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][entryGroupIndex] == -1){ + if (object_entry_groups[type].chunks[entryGroupIndex] == (uint8*)-1){ break; } } @@ -252,10 +251,10 @@ int object_load_packed(FILE *file) return 0; } - RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][entryGroupIndex] = chunk; - int* edx = (int*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); - memcpy(edx, (int*)entry, 16); - *(edx + 4) = chunkSize; + object_entry_groups[type].chunks[entryGroupIndex] = chunk; + rct_object_entry_extended* edx = &object_entry_groups[type].entries[entryGroupIndex]; + memcpy(edx, (int*)entry, sizeof(rct_object_entry)); + edx->chunk_size = chunkSize; //esi rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); @@ -307,7 +306,7 @@ int object_load_packed(FILE *file) // The following section cannot be finished until 6A9F42 is finished // Run the game once with vanila rct2 to not reach this part of code. - RCT2_ERROR("Function not finished. Please run this save once with vanila rct2."); + log_verbose("Function might not be finished."); FILE* obj_file = fopen(path, "wb"); if (obj_file){ // Removed progress bar code @@ -326,7 +325,7 @@ int object_load_packed(FILE *file) //6aa48C int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; //RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return eax; + return 1; } /** @@ -407,7 +406,7 @@ int object_scenario_load_custom_text(char* chunk){ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp) { - //if (type == 10){ + //if (type == OBJECT_TYPE_SCENARIO_TEXT){ // if (eax == 0) return object_scenario_load_custom_text((char*)esi); //} return RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp) & 0x100; @@ -437,9 +436,8 @@ int object_get_scenario_text(rct_object_entry *entry) // Get chunk size char *pos = (char*)installedObject + 16; - do { - pos++; - } while (*(pos - 1) != 0); + // Skip file name + while (*pos++); // Read chunk int chunkSize = *((uint32*)pos); @@ -515,17 +513,13 @@ rct_object_entry *object_get_next(rct_object_entry *entry) pos += 16; // Skip filename - do { - pos++; - } while (*(pos - 1) != 0); + while (*pos++); // Skip pos += 4; // Skip name - do { - pos++; - } while (*(pos - 1) != 0); + while (*pos++); // Skip size of chunk pos += 4; @@ -540,4 +534,4 @@ rct_object_entry *object_get_next(rct_object_entry *entry) pos += 4; return (rct_object_entry*)pos; -} +} \ No newline at end of file diff --git a/src/object.h b/src/object.h index fc9bcb37a5..70be1a0f5a 100644 --- a/src/object.h +++ b/src/object.h @@ -23,6 +23,21 @@ #include "common.h" +// First 0xF of rct_object_entry->flags +typedef enum{ + OBJECT_TYPE_RIDE, + OBJECT_TYPE_SMALL_SCENERY, + OBJECT_TYPE_LARGE_SCENERY, + OBJECT_TYPE_WALLS, + OBJECT_TYPE_BANNERS, + OBJECT_TYPE_PATHS, + OBJECT_TYPE_PATH_BITS, + OBJECT_TYPE_SCENERY_SETS, + OBJECT_TYPE_PARK_ENTRANCE, + OBJECT_TYPE_WATER, + OBJECT_TYPE_SCENARIO_TEXT +}OBJECT_TYPE; + /** * Object entry structure. * size: 0x10 @@ -41,12 +56,19 @@ typedef struct { uint32 flags; char name[8]; uint32 checksum; - uint32 extended; + uint32 chunk_size; } rct_object_entry_extended; extern int object_entry_group_counts[]; extern int object_entry_group_encoding[]; +typedef struct { + uint8 **chunks; + rct_object_entry_extended *entries; +} rct_object_entry_group; + +extern rct_object_entry_group object_entry_groups[]; + int object_load_entry(const char *path, rct_object_entry *outEntry); void object_list_load(); void set_load_objects_fail_reason(); @@ -55,6 +77,7 @@ int object_load_packed(FILE *file); void object_unload_all(); int object_load(int groupIndex, rct_object_entry *entry, int* chunk_size); +int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSize, const rct_object_entry *installedObject); void object_unload(int groupIndex, rct_object_entry_extended *entry); int object_get_scenario_text(rct_object_entry *entry); void object_free_scenario_text(); @@ -67,4 +90,4 @@ int sub_6A9F42(FILE *file, rct_object_entry* entry); rct_object_entry *object_list_find(rct_object_entry *entry); -#endif +#endif \ No newline at end of file diff --git a/src/object_list.c b/src/object_list.c index 2890e1b8da..70b0b037b7 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -67,24 +67,26 @@ int object_entry_group_encoding[] = { CHUNK_ENCODING_ROTATE }; -struct { void **data; rct_object_entry_extended *entries; } object_entry_groups[] = { - (void**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides - (void**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery - (void**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery - (void**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls - (void**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners - (void**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths - (void**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits - (void**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets - (void**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance - (void**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water - (void**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text +// 0x98D97C chunk address', 0x98D980 object_entries +rct_object_entry_group object_entry_groups[] = { + (uint8**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides + (uint8**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery + (uint8**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery + (uint8**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls + (uint8**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners + (uint8**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths + (uint8**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits + (uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets + (uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance + (uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water + (uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text }; static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int fileDateModifiedChecksum); static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileDateModifiedChecksum, int currentItemOffset); void object_list_create_hash_table(); +static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path); static void get_plugin_path(char *path) { @@ -132,58 +134,13 @@ void sub_6A9FC0() for (int type = 0; type < 11; ++type){ for (int j = 0; j < object_entry_group_counts[type]; j++){ - rct_object_entry* entry = (rct_object_entry*)object_entry_groups[type].data[j]; - if (entry != (rct_object_entry*)0xFFFFFFFF) - object_paint(type, 0, 0, 0, 0, (int)entry, 0, 0); + uint8* chunk = object_entry_groups[type].chunks[j]; + if (chunk != (uint8*)-1) + object_paint(type, 0, 0, 0, 0, (int)chunk, 0, 0); } } } -int object_copy(uint8 *destination_object, uint8 *installed_object) -{ - uint8 *original_dest = destination_object; - - memcpy(destination_object, installed_object, sizeof(rct_object_entry)); - destination_object += sizeof(rct_object_entry); - installed_object += sizeof(rct_object_entry); - - do { - *destination_object++ = *installed_object++; - } while (*(destination_object - 1)); - - *((sint32*)destination_object) = *((sint32*)installed_object); - destination_object += 4; - installed_object += 4; - - do { - *destination_object++ = *installed_object++; - } while (*(destination_object - 1)); - - *((sint32*)destination_object) = *((sint32*)installed_object); - destination_object += 4; - installed_object += 4; - - uint8 no_obj_unk = *installed_object++; - *destination_object++ = no_obj_unk; - - memcpy(destination_object, installed_object, no_obj_unk * sizeof(rct_object_entry)); - destination_object += no_obj_unk * sizeof(rct_object_entry); - installed_object += no_obj_unk * sizeof(rct_object_entry); - - uint8 no_obj_theme = *installed_object++; - *destination_object++ = no_obj_theme; - - memcpy(destination_object, installed_object, no_obj_theme*sizeof(rct_object_entry)); - destination_object += no_obj_theme * sizeof(rct_object_entry); - installed_object += no_obj_theme * sizeof(rct_object_entry); - - *((sint32*)destination_object) = *((sint32*)installed_object); - destination_object += 4; - installed_object += 4; - - return destination_object - original_dest; -} - static int object_list_query_directory(int *outTotalFiles, uint64 *outTotalFileSize, int *outFileDateModifiedChecksum) { int enumFileHandle, totalFiles, fileDateModifiedChecksum; @@ -261,13 +218,13 @@ void object_list_load() enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char)); if (enumFileHandle != INVALID_HANDLE) { uint32 installed_buffer_size = 0x1000; - + while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) { fileCount++; if ((installed_buffer_size - current_item_offset) <= 2842){ installed_buffer_size += 0x1000; - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size); + RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size); if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0); return; @@ -281,152 +238,9 @@ void object_list_load() if (!object_load_entry(path, entry)) continue; - RCT2_GLOBAL(0xF42BC4, uint32) = current_item_offset; + rct_object_entry* installed_entry = (rct_object_entry*)(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset); - uint8* installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset; - - memcpy(installed_entry_pointer, entry, sizeof(rct_object_entry)); - installed_entry_pointer += sizeof(rct_object_entry); - - strcpy(installed_entry_pointer, enumFileInfo.path); - while (*installed_entry_pointer++); - - // Chunk size is set to unknown - *((sint32*)installed_entry_pointer) = -1; - *(installed_entry_pointer + 4) = 0; - *((sint32*)(installed_entry_pointer + 5)) = 0; - *((uint16*)(installed_entry_pointer + 9)) = 0; - *((uint32*)(installed_entry_pointer + 11)) = 0; - - RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E; - - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; - - // This is a variable used by object_load to decide if it should - // use object_paint on the entry. - RCT2_GLOBAL(0x009ADAFD, uint8) = 1; - - // Probably used by object paint. - RCT2_GLOBAL(0x009ADAF4, uint32) = 0xF42BDB; - - int chunk_size; - if (!object_load(-1, entry, &chunk_size)){ - RCT2_GLOBAL(0x009ADAF4, sint32) = -1; - RCT2_GLOBAL(0x009ADAFD, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; - continue; - } - - int objectType = entry->flags & 0xF; - - // See above note - RCT2_GLOBAL(0x009ADAF4, sint32) = -1; - RCT2_GLOBAL(0x009ADAFD, uint8) = 0; - - if ((entry->flags & 0xF0) == 0x80) { - RCT2_GLOBAL(0x00F42B70, uint32)++; - if (RCT2_GLOBAL(0x00F42B70, uint32) > 772){ - RCT2_GLOBAL(0x00F42B70, uint32)--; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; - continue; - } - } - *((sint32*)installed_entry_pointer) = chunk_size; - installed_entry_pointer += 4; - - uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load - - // When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars); - if (objectType == 0 && !(*((uint32*)(chunk + 8)) & 0x1000)) { - rct_string_id obj_string = chunk[12]; - if (obj_string == 0xFF){ - obj_string = chunk[13]; - if (obj_string == 0xFF) { - obj_string = chunk[14]; - } - } - - obj_string += 2; - format_string(installed_entry_pointer, obj_string, 0); - strcat(installed_entry_pointer, "\t ("); - strcat(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0x00F42BBC, uint32))); - strcat(installed_entry_pointer, ")"); - while (*installed_entry_pointer++); - } else{ - strcpy(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0x00F42BBC, uint32))); - while (*installed_entry_pointer++); - } - *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x009ADAF0, uint32) - 0xF26E; - installed_entry_pointer += 4; - - uint8* esi = RCT2_ADDRESS(0x00F42BDB, uint8); - uint8 num_unk_objects = *esi++; - *installed_entry_pointer++ = num_unk_objects; - if (num_unk_objects > 0) { - memcpy(installed_entry_pointer, esi, num_unk_objects * sizeof(rct_object_entry)); - installed_entry_pointer += num_unk_objects * sizeof(rct_object_entry); - } - - uint8 no_theme_objects = *esi++; - *installed_entry_pointer++ = no_theme_objects ; - if (no_theme_objects > 0) { - memcpy(installed_entry_pointer, esi, no_theme_objects * sizeof(rct_object_entry)); - installed_entry_pointer += no_theme_objects * sizeof(rct_object_entry); - } - - *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x00F433DD, uint32); - installed_entry_pointer += 4; - - int size_of_object = installed_entry_pointer - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) - current_item_offset; - - object_unload(objectType, (rct_object_entry_extended*)entry); - - // Return pointer to start of entry - installed_entry_pointer -= size_of_object; - - uint8* copied_entry = RCT2_ADDRESS(0x0140E9AC, uint8); - - size_of_object = object_copy(copied_entry, installed_entry_pointer); - - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; - copied_entry += sizeof(rct_object_entry); - // Skip filename - while (*copied_entry++); - - // Skip - copied_entry += 4; - - installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*); - - for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); ++i){ - - uint8* temp_installed_entry = installed_entry_pointer; - temp_installed_entry += sizeof(rct_object_entry); - - // Skip filename - while (*temp_installed_entry++); - - // Skip - temp_installed_entry += 4; - - if (strcmp(temp_installed_entry, copied_entry) <= 0)break; - - installed_entry_pointer = (uint8*)(object_get_next((rct_object_entry*)installed_entry_pointer)); - } - - // Difference to new location - int numBytesToMove = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset - installed_entry_pointer; - - uint8 *curr_location = installed_entry_pointer; - uint8 *move_location = installed_entry_pointer + size_of_object; - - if (numBytesToMove > 0) - memmove(move_location, curr_location, numBytesToMove); - - copied_entry = RCT2_ADDRESS(0x0140E9AC, uint8); - memcpy(installed_entry_pointer, copied_entry, size_of_object); - current_item_offset += size_of_object; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; + current_item_offset += install_object_entry(entry, installed_entry, enumFileInfo.path); } platform_enumerate_files_end(enumFileHandle); } @@ -614,7 +428,7 @@ void object_unload_all() for (i = 0; i < OBJECT_ENTRY_GROUP_COUNT; i++) for (j = 0; j < object_entry_group_counts[i]; j++) - if (object_entry_groups[i].data[j] != (void**)0xFFFFFFFF) + if (object_entry_groups[i].chunks[j] != (uint8*)0xFFFFFFFF) object_unload(j, &object_entry_groups[i].entries[j]); sub_6A9FC0(); @@ -659,6 +473,7 @@ void object_list_create_hash_table() while (_installedObjectHashTable[index] != NULL) { _installedObjectHashTableCollisions++; index++; + if (index >= _installedObjectHashTableSize) index = 0; } // Set hash table slot @@ -675,11 +490,122 @@ rct_object_entry *object_list_find(rct_object_entry *entry) uint32 index = hash % _installedObjectHashTableSize; while (_installedObjectHashTable[index] != NULL) { - if (object_entry_compare(entry, _installedObjectHashTable[index])) + if (object_entry_compare( _installedObjectHashTable[index], entry)) return _installedObjectHashTable[index]; index++; + if (index >= _installedObjectHashTableSize) index = 0; } return NULL; +} + +/* Installs an object_entry at the desired installed_entry address + * Returns the size of the new entry. Will return 0 on failure. + */ +static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path){ + uint8* installed_entry_pointer = (uint8*) installed_entry; + + /** Copy all known information into the install entry **/ + memcpy(installed_entry_pointer, entry, sizeof(rct_object_entry)); + installed_entry_pointer += sizeof(rct_object_entry); + + strcpy(installed_entry_pointer, path); + while (*installed_entry_pointer++); + + // Chunk size is set to unknown + *((sint32*)installed_entry_pointer) = -1; + *(installed_entry_pointer + 4) = 0; + *((sint32*)(installed_entry_pointer + 5)) = 0; + *((uint16*)(installed_entry_pointer + 9)) = 0; + *((uint32*)(installed_entry_pointer + 11)) = 0; + + RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E; + + RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; + + // This is a variable used by object_load to decide if it should + // use object_paint on the entry. + RCT2_GLOBAL(0x009ADAFD, uint8) = 1; + + // Probably used by object paint. + RCT2_GLOBAL(0x009ADAF4, uint32) = 0xF42BDB; + + /** Use object_load_file to fill in missing chunk information **/ + int chunk_size; + if (!object_load_file(-1, entry, &chunk_size, installed_entry)){ + RCT2_GLOBAL(0x009ADAF4, sint32) = -1; + RCT2_GLOBAL(0x009ADAFD, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; + return 0; + } + + uint8 objectType = entry->flags & 0xF; + + // See above note + RCT2_GLOBAL(0x009ADAF4, sint32) = -1; + RCT2_GLOBAL(0x009ADAFD, uint8) = 0; + + if ((entry->flags & 0xF0) == 0x80) { + RCT2_GLOBAL(0x00F42B70, uint32)++; + if (RCT2_GLOBAL(0x00F42B70, uint32) > 772){ + RCT2_GLOBAL(0x00F42B70, uint32)--; + RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; + object_unload(objectType, (rct_object_entry_extended*)entry); + return 0; + } + } + *((sint32*)installed_entry_pointer) = chunk_size; + installed_entry_pointer += 4; + + uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load + + // When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars); + if (objectType == OBJECT_TYPE_RIDE && !(*((uint32*)(chunk + 8)) & 0x1000)) { + rct_string_id obj_string = chunk[12]; + if (obj_string == 0xFF){ + obj_string = chunk[13]; + if (obj_string == 0xFF) { + obj_string = chunk[14]; + } + } + + obj_string += 2; + format_string(installed_entry_pointer, obj_string, 0); + strcat(installed_entry_pointer, "\t ("); + strcat(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0x00F42BBC, uint32))); + strcat(installed_entry_pointer, ")"); + while (*installed_entry_pointer++); + } + else{ + strcpy(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0x00F42BBC, uint32))); + while (*installed_entry_pointer++); + } + *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x009ADAF0, uint32) - 0xF26E; + installed_entry_pointer += 4; + + uint8* esi = RCT2_ADDRESS(0x00F42BDB, uint8); + uint8 num_unk_objects = *esi++; + *installed_entry_pointer++ = num_unk_objects; + if (num_unk_objects > 0) { + memcpy(installed_entry_pointer, esi, num_unk_objects * sizeof(rct_object_entry)); + installed_entry_pointer += num_unk_objects * sizeof(rct_object_entry); + esi += num_unk_objects * sizeof(rct_object_entry); + } + + uint8 no_theme_objects = *esi++; + *installed_entry_pointer++ = no_theme_objects; + if (no_theme_objects > 0) { + memcpy(installed_entry_pointer, esi, no_theme_objects * sizeof(rct_object_entry)); + installed_entry_pointer += no_theme_objects * sizeof(rct_object_entry); + } + + *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x00F433DD, uint32); + installed_entry_pointer += 4; + + uint32 size_of_object = installed_entry_pointer - (uint8*)installed_entry; + + object_unload(objectType, (rct_object_entry_extended*)entry); + + return size_of_object; } \ No newline at end of file diff --git a/src/rct2.c b/src/rct2.c index cd641836c1..916bceb320 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -84,6 +84,7 @@ int rct2_init() RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; // config_load(); // RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap + object_list_load(); scenario_load_list();