diff --git a/src/addresses.h b/src/addresses.h index d2e8321884..e55b0cee86 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -130,11 +130,23 @@ #define RCT2_ADDRESS_RIDE_ENTRIES 0x009ACFA4 + + +#define RCT2_ADDRESS_SMALL_SCENERY_ENTRIES 0x009AD1A4 +#define RCT2_ADDRESS_LARGE_SCENERY_ENTRIES 0x009AD594 +#define RCT2_ADDRESS_WALL_SCENERY_ENTRIES 0x009AD794 +#define RCT2_ADDRESS_BANNER_SCENERY_ENTRIES 0x009AD994 +#define RCT2_ADDRESS_PATH_TYPES 0x009ADA14 +#define RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES 0x009ADA54 +#define RCT2_ADDRESS_SCENERY_SET_ENTRIES 0x009ADA90 + #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 #define RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST 0x009ADAEC - #define RCT2_ADDRESS_TOTAL_NO_IMAGES 0x009ADAF0 +#define RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK 0x009ADAF8 + + #define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280 #define RCT2_ADDRESS_VEHICLE_SOUND_LIST 0x009AF288 @@ -219,15 +231,6 @@ #define RCT2_ADDRESS_G1_ELEMENTS 0x009EBD28 -#define RCT2_ADDRESS_PATH_TYPES 0x009ADA14 - -#define RCT2_ADDRESS_SMALL_SCENERY_ENTRIES 0x009AD1A4 -#define RCT2_ADDRESS_LARGE_SCENERY_ENTRIES 0x009AD594 -#define RCT2_ADDRESS_WALL_SCENERY_ENTRIES 0x009AD794 -#define RCT2_ADDRESS_BANNER_SCENERY_ENTRIES 0x009AD994 -#define RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES 0x009ADA54 -#define RCT2_ADDRESS_SCENERY_SET_ENTRIES 0x009ADA90 - //Every pixel changed by rain is stored. //32bit (pixel_offset 24 bit)(pixel_colour 8 bit) //Use the rainPixels[] global in drawing.c from now on @@ -263,6 +266,8 @@ #define RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID 0x00F42BBC #define RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER 0x00F42BC0 +#define RCT2_ADDRESS_SCENARIO_TEXT_TEMP_OBJECT 0x00F42BC8 + #define RCT2_ADDRESS_VOLUME_ADJUST_ZOOM 0x00F438AC #define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908 diff --git a/src/editor.c b/src/editor.c index 2a083a00cc..7f85709157 100644 --- a/src/editor.c +++ b/src/editor.c @@ -152,8 +152,9 @@ void editor_convert_save_to_scenario() s6Info->objective_arg_3 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, sint16); climate_reset(RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE, uint8)); - if (RCT2_GLOBAL(0x009ADAE4, uint32) != 0xFFFFFFFF) { - object_unload(0, (rct_object_entry_extended*)0x00F4287C); + rct_stex_entry* stex = g_stexEntries[0]; + if ((int)stex != 0xFFFFFFFF) { + object_unload(0, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); //RCT2_CALLPROC_EBPSAFE(0x006A9FC0); sub_6A9FC0(); @@ -911,8 +912,9 @@ static int editor_read_s6(const char *path) climate_reset(RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE, uint8)); - if (RCT2_GLOBAL(0x009ADAE4, uint32) != 0xFFFFFFFF) { - object_unload(0, (rct_object_entry_extended*)0x00F4287C); + rct_stex_entry* stex = g_stexEntries[0]; + if ((int)stex != 0xFFFFFFFF) { + object_unload(0, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); sub_6A9FC0();//RCT2_CALLPROC_EBPSAFE(0x006A9FC0); format_string(s6Info->details, STR_NO_DETAILS_YET, NULL); diff --git a/src/object.c b/src/object.c index 571534d39d..b6ca848ee6 100644 --- a/src/object.c +++ b/src/object.c @@ -175,12 +175,14 @@ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) * ebx : file * ebp : entry */ -int sub_6A9F42(FILE *file, rct_object_entry* entry){ +int write_object_file(FILE *file, rct_object_entry* entry){ uint8 entryGroupIndex = 0, type = 0; uint8* chunk = 0; if (!find_object_in_entry_group(entry, &type, &entryGroupIndex))return 0; + chunk = object_entry_groups[type].chunks[entryGroupIndex]; + object_paint(type, 1, entryGroupIndex, type, 0, (int)chunk, 0, 0); rct_object_entry_extended* installed_entry = &object_entry_groups[type].entries[entryGroupIndex]; @@ -211,35 +213,39 @@ int object_load_packed(FILE *file) { object_unload_all(); - rct_object_entry* entry = RCT2_ADDRESS(0xF42B84, rct_object_entry); + rct_object_entry entry; - fread((void*)entry, 16, 1, file); + fread(&entry, 16, 1, file); uint8* chunk = rct2_malloc(0x600000); uint32 chunkSize = sawyercoding_read_chunk(file, chunk); chunk = rct2_realloc(chunk, chunkSize); + if (chunk == NULL){ + log_error("Failed to allocate memory for packed object."); return 0; } - if (object_calculate_checksum(entry, chunk, chunkSize) != entry->checksum){ + if (object_calculate_checksum(&entry, chunk, chunkSize) != entry.checksum){ + log_error("Checksum missmatch from packed object: %.8s", entry.name); rct2_free(chunk); return 0; } - if (object_paint(entry->flags & 0x0F, 2, 0, entry->flags & 0x0F, 0, (int)chunk, 0, 0)) { + int type = entry.flags & 0x0F; + + if (object_paint(type, 2, 0, type, 0, (int)chunk, 0, 0)) { + log_error("Packed object failed paint test."); rct2_free(chunk); return 0; } if (RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) >= 0x4726E){ + log_error("Packed object has too many images."); rct2_free(chunk); return 0; } - int type = entry->flags & 0x0F; - - // ecx int entryGroupIndex = 0; for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ @@ -249,21 +255,24 @@ int object_load_packed(FILE *file) } if (entryGroupIndex == object_entry_group_counts[type]){ + // This should never occur. Objects are not loaded before installing a + // packed object. So there is only one object loaded at this point. + log_error("Too many objects of the same type loaded."); rct2_free(chunk); return 0; } + // Copy the entry into the relevant entry group. 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; + rct_object_entry_extended* extended_entry = &object_entry_groups[type].entries[entryGroupIndex]; + memcpy(extended_entry, &entry, sizeof(rct_object_entry)); + extended_entry->chunk_size = chunkSize; - //esi + // Ensure the entry does not already exist. rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)){ for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); ++i){ - if (object_entry_compare(entry, installedObject)){ + if (object_entry_compare(&entry, installedObject)){ object_unload_all(); return 0; } @@ -271,24 +280,23 @@ int object_load_packed(FILE *file) } } - //Installing new data - //format_string(0x141ED68, 3163, 0); - //Code for updating progress bar removed. - + // Convert the entry name to a upper case path name char path[260]; - char objectPath[13] = { 0 }; + char objectPath[9] = { 0 }; for (int i = 0; i < 8; ++i){ - if (entry->name[i] != ' ') - objectPath[i] = toupper(entry->name[i]); + if (entry.name[i] != ' ') + objectPath[i] = toupper(entry.name[i]); else objectPath[i] = '\0'; } subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + // Require pointer to start of filename char* last_char = path + strlen(path); strcat(path, ".DAT"); - // + // Check that file does not exist + // Adjust filename if it does. for (; platform_file_exists(path);){ for (char* curr_char = last_char - 1;; --curr_char){ if (*curr_char == '\\'){ @@ -304,30 +312,19 @@ int object_load_packed(FILE *file) } } - // Removed progress bar code - - // The following section cannot be finished until 6A9F42 is finished - // Run the game once with vanila rct2 to not reach this part of code. - log_verbose("Function might not be finished."); + // Actually write the object to the file FILE* obj_file = fopen(path, "wb"); if (obj_file){ - // Removed progress bar code - sub_6A9F42(obj_file, entry); + uint8 result = write_object_file(obj_file, &entry); + fclose(obj_file); - // Removed progress bar code object_unload_all(); - // Removed progress bar code - return 1; + + return result; } - else{ - object_unload_all(); - return 0; - } - //create 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 1; + + object_unload_all(); + return 0; } /** @@ -341,6 +338,7 @@ void object_unload(int groupIndex, rct_object_entry_extended *entry) int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b) { + // If an official object don't bother checking checksum if (a->flags & 0xF0) { if ((a->flags & 0x0F) != (b->flags & 0x0F)) return 0; @@ -1501,73 +1499,89 @@ int object_get_scenario_text(rct_object_entry *entry) { // RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry); return; - int i; rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - for (i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, 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; - // Skip file name - while (*pos++); - - // 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 total_no_images = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32); - // This is being changed to force the images to be loaded into a different - // image id. - RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, 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(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = total_no_images; - return 1; - } - fclose(file); - } - } - installedObject = object_get_next(installedObject); + installedObject = object_list_find(entry); + + if (installedObject == NULL){ + log_error("Object not found: %.8s", entry->name); + RCT2_GLOBAL(0x00F42BD9, uint8) = 0; + return 0; } + 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)) { + + // Skip over the object entry + char *pos = (char*)installedObject + sizeof(rct_object_entry); + // Skip file name + while (*pos++); + + // 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) { + log_error("Opened object failed calculated checksum."); + RCT2_GLOBAL(0x00F42BD9, uint8) = 2; + free(chunk); + return 0; + } + + if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { + // This is impossible for STEX entries to fail. + log_error("Opened object failed paitn test."); + RCT2_GLOBAL(0x00F42BD9, uint8) = 3; + free(chunk); + return 0; + } + + // Save the real total images. + int total_no_images = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32); + + // This is being changed to force the images to be loaded into a different + // image id. + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0x726E; + RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, uint32) = (int)chunk; + // Not used anywhere. + RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_OBJECT, rct_object_entry) = openedEntry; + + // Tell text to be loaded into a different address + RCT2_GLOBAL(0x009ADAFC, uint8) = 255; + // Not used?? + RCT2_GLOBAL(0x009ADAFD, uint8) = 1; + object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0); + // Tell text to be loaded into normal address + RCT2_GLOBAL(0x009ADAFC, uint8) = 0; + // Not used?? + RCT2_GLOBAL(0x009ADAFD, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = total_no_images; + return 1; + } + log_error("Opened object didn't match."); + fclose(file); + return 0; + } + log_error("File failed to open."); RCT2_GLOBAL(0x00F42BD9, uint8) = 0; return 0; } @@ -1578,9 +1592,9 @@ int object_get_scenario_text(rct_object_entry *entry) */ void object_free_scenario_text() { - if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) { - rct2_free(RCT2_GLOBAL(0x009ADAF8, void*)); - RCT2_GLOBAL(0x009ADAF8, void*) = NULL; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, void*) != NULL) { + rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, void*)); + RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, void*) = NULL; } } @@ -1630,7 +1644,7 @@ char *object_get_name(rct_object_entry *entry) // Skip filename while (*pos++); - // Skip + // Skip no of images pos += 4; return pos; diff --git a/src/object.h b/src/object.h index dfe8e6fbc9..64b0b4d6b5 100644 --- a/src/object.h +++ b/src/object.h @@ -86,7 +86,7 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b); int object_calculate_checksum(const rct_object_entry *entry, const char *data, int dataLength); int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); rct_object_entry *object_get_next(rct_object_entry *entry); -int sub_6A9F42(FILE *file, rct_object_entry* entry); +int write_object_file(FILE *file, rct_object_entry* entry); void sub_6A9FC0(); int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index); diff --git a/src/object_list.c b/src/object_list.c index 27c5688600..8446119101 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -69,16 +69,16 @@ int object_entry_group_encoding[] = { // 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 + (uint8**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery 0x009AD1A4, 0xF2FA3C + (uint8**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery 0x009AD594, 0xF40DEC + (uint8**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls 0x009AD794, 0xF417EC + (uint8**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners 0x009AD994, 0xF421EC + (uint8**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths 0x009ADA14, 0xF4246C + (uint8**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits 0x009ADA54, 0xF425AC + (uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets 0x009ADA90, 0xF426D8 + (uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance 0x009ADADC, 0xF42854 + (uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water 0x009ADAE0, 0xF42868 + (uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text 0x009ADAE4, 0xF4287C }; static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int fileDateModifiedChecksum); diff --git a/src/scenario.c b/src/scenario.c index c506685500..f84f982cb8 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -69,10 +69,10 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in // Checks for a scenario string object (possibly for localisation) if ((info->entry.flags & 0xFF) != 255) { if (object_get_scenario_text(&info->entry)) { - int ebp = RCT2_GLOBAL(0x009ADAF8, uint32); - format_string(info->name, RCT2_GLOBAL(ebp, sint16), NULL); - format_string(info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL); - RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8); + rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); + format_string(info->name, stex_entry->scenario_name, NULL); + format_string(info->details, stex_entry->details, NULL); + RCT2_GLOBAL(0x009AA00C, uint8) = stex_entry->var_06; object_free_scenario_text(); } } @@ -274,11 +274,10 @@ int scenario_load_and_play_from_path(const char *path) strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details); strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name); - if (RCT2_GLOBAL(0x009ADAE4, sint32) != -1) { - char *ebp = RCT2_GLOBAL(0x009ADAE4, char*); - + rct_stex_entry* stex = g_stexEntries[0]; + if ((int)stex != -1) { // - format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 2, uint16), 0); + format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->park_name, 0); // Set park name RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK; @@ -293,12 +292,12 @@ int scenario_load_and_play_from_path(const char *path) *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 28))); // - format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 0, uint16), 0); + format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->scenario_name, 0); strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, 31); ((char*)RCT2_ADDRESS_SCENARIO_NAME)[31] = '\0'; // Set scenario details - format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, RCT2_GLOBAL(ebp + 4, uint16), 0); + format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, stex->details, 0); strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, 255); ((char*)RCT2_ADDRESS_SCENARIO_DETAILS)[255] = '\0'; } @@ -840,11 +839,12 @@ int scenario_prepare_for_save() s6Info->entry.flags = 255; - char *stex = RCT2_GLOBAL(0x009ADAE4, char*); - if (stex != (char*)0xFFFFFFFF) { - format_string(buffer, RCT2_GLOBAL(stex, uint16), NULL); + rct_stex_entry* stex = g_stexEntries[0]; + if ((int)stex != 0xFFFFFFFF) { + format_string(buffer, stex->scenario_name, NULL); strncpy(s6Info->name, buffer, sizeof(s6Info->name)); - s6Info->entry = *((rct_object_entry*)0x00F4287C); + + memcpy(&s6Info->entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry)); } if (s6Info->name[0] == 0) @@ -894,7 +894,7 @@ int scenario_write_packed_objects(FILE *file) if (RCT2_ADDRESS(0x009ACFA4, uint32)[i] == 0xFFFFFFFF || (entry->flags & 0xF0)) continue; - if (!sub_6A9F42(file, (rct_object_entry*)entry)) + if (!write_object_file(file, (rct_object_entry*)entry)) return 0; } diff --git a/src/scenario.h b/src/scenario.h index f6e710c6a6..922680cd24 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -84,11 +84,14 @@ typedef struct { } rct_scenario_basic; typedef struct { - rct_string_id scenario_name; - rct_string_id park_name; - rct_string_id details; + rct_string_id scenario_name; // 0x00 + rct_string_id park_name; // 0x02 + rct_string_id details; // 0x04 + uint8 var_06; } rct_stex_entry; +#define g_stexEntries ((rct_stex_entry**)object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].chunks) + /* This will be useful for backwards compatibility typedef struct { // SC6[0] diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 57a0940249..1f9d69de1c 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -26,6 +26,7 @@ #include "../localisation/localisation.h" #include "../object.h" #include "../ride/track.h" +#include "../scenario.h" #include "error.h" enum { @@ -571,7 +572,9 @@ static void window_editor_object_selection_paint() gfx_draw_string_left(dpi, 3164, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } - if (w->selected_list_item == -1 || RCT2_GLOBAL(0x009ADAF8, sint32) == -1) + rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); + + if (w->selected_list_item == -1 || stex_entry == NULL) return; highlightedEntry = (rct_object_entry*)w->var_494; @@ -581,7 +584,7 @@ static void window_editor_object_selection_paint() widget = &w->widgets[WIDX_PREVIEW]; x = w->x + (widget->left + widget->right) / 2 + 1; y = w->y + (widget->top + widget->bottom) / 2 + 1; - object_paint(type, 3, type, x, y, 0, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32)); + object_paint(type, 3, type, x, y, 0, (int)dpi, (int)stex_entry); // Draw name of object x = w->x + (widget->left + widget->right) / 2 + 1; @@ -629,7 +632,7 @@ static void window_editor_object_selection_paint() // Draw description of object x = w->x + w->widgets[WIDX_LIST].right + 4; y += 15; - object_paint(type, 259, type, x, y, (int)w, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32)); + object_paint(type, 259, type, x, y, (int)w, (int)dpi, (int)stex_entry); // Draw object dat name strcpy(stringBuffer, datName); diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c index abea327c67..bc41e94f7a 100644 --- a/src/windows/editor_objective_options.c +++ b/src/windows/editor_objective_options.c @@ -835,7 +835,7 @@ static void window_editor_objective_options_main_invalidate() window_get_register(w); - stex = RCT2_GLOBAL(0x009ADAE4, rct_stex_entry*); + stex = g_stexEntries[0]; if (stex == (rct_stex_entry*)0xFFFFFFFF) stex = NULL; @@ -920,7 +920,7 @@ static void window_editor_objective_options_main_paint() window_draw_widgets(w, dpi); window_editor_objective_options_draw_tab_images(w, dpi); - stex = RCT2_GLOBAL(0x009ADAE4, rct_stex_entry*); + stex = g_stexEntries[0]; if (stex == (rct_stex_entry*)0xFFFFFFFF) stex = NULL; diff --git a/src/windows/footpath.c b/src/windows/footpath.c index 22b51b4248..15b3e08683 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -354,7 +354,7 @@ static void window_footpath_dropdown() j = 0; for (i = 0; i < 16; i++) { - pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[i]; + pathType = g_pathTypeEntries[i]; if (pathType == (rct_path_type*)-1) continue; if (pathType->flags & flags) @@ -533,7 +533,7 @@ static void window_footpath_invalidate() // Set footpath and queue type button images selectedPath = RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint16); - pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[selectedPath]; + pathType = g_pathTypeEntries[selectedPath]; int pathImage = 71 + pathType->image; window_footpath_widgets[WIDX_FOOTPATH_TYPE].image = pathImage; @@ -570,7 +570,7 @@ static void window_footpath_paint() image = RCT2_ADDRESS(0x0098D7E0, uint8)[image]; selectedPath = RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint16); - pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[selectedPath]; + pathType = g_pathTypeEntries[selectedPath]; image += pathType->image; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) != SELECTED_PATH_TYPE_NORMAL) image += 51; @@ -609,7 +609,7 @@ static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget flags = 0; for (i = 0; i < 16; i++) { - pathType = RCT2_ADDRESS(RCT2_ADDRESS_PATH_TYPES, rct_path_type*)[i]; + pathType = g_pathTypeEntries[i]; if (pathType == (rct_path_type*)-1) continue; if (pathType->flags & flags) diff --git a/src/world/footpath.h b/src/world/footpath.h index 3bdb3ce8f0..8205b91c47 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -23,6 +23,7 @@ #include "../common.h" #include "../interface/viewport.h" +#include "../object.h" enum { PROVISIONAL_PATH_FLAG_SHOW_ARROW = (1 << 0) @@ -36,6 +37,8 @@ typedef struct { uint8 flags; // 0x0B } rct_path_type; +#define g_pathTypeEntries ((rct_path_type**)object_entry_groups[OBJECT_TYPE_PATHS].chunks) + void game_command_place_footpath(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_remove_footpath(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); money32 footpath_place(int type, int x, int y, int z, int slope, int flags); diff --git a/src/world/scenery.h b/src/world/scenery.h index 87383a308e..d1696c10c4 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -22,6 +22,7 @@ #define _SCENERY_H_ #include "../common.h" +#include "../object.h" typedef struct { uint32 flags; // 0x06 @@ -129,12 +130,12 @@ typedef struct { uint32 var_10A; } rct_scenery_set_entry; -#define g_smallSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry*) -#define g_largeSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*) -#define g_wallSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*) -#define g_bannerSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_BANNER_SCENERY_ENTRIES, rct_scenery_entry*) -#define g_pathBitSceneryEntries RCT2_ADDRESS(RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES, rct_scenery_entry*) -#define g_scenerySetEntries RCT2_ADDRESS(RCT2_ADDRESS_SCENERY_SET_ENTRIES, rct_scenery_set_entry*) +#define g_smallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks) +#define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks) +#define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks) +#define g_bannerSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_BANNERS].chunks) +#define g_pathBitSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_PATH_BITS].chunks) +#define g_scenerySetEntries ((rct_scenery_set_entry**)object_entry_groups[OBJECT_TYPE_SCENERY_SETS].chunks) void init_scenery();