diff --git a/src/addresses.h b/src/addresses.h index b288384800..d2e8321884 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -133,6 +133,8 @@ #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_CURRENT_SOUND_DEVICE 0x009AF280 #define RCT2_ADDRESS_VEHICLE_SOUND_LIST 0x009AF288 @@ -258,6 +260,7 @@ #define RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS 0x00F42B6C #define RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT 0x00F42B70 +#define RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID 0x00F42BBC #define RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER 0x00F42BC0 #define RCT2_ADDRESS_VOLUME_ADJUST_ZOOM 0x00F438AC diff --git a/src/localisation/language.c b/src/localisation/language.c index c6d2533505..5938194336 100644 --- a/src/localisation/language.c +++ b/src/localisation/language.c @@ -233,56 +233,71 @@ const int OpenRCT2LangIdToObjectLangId[] = { /* rct2: 0x006A9E24*/ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/*ecx*/, int index/*ebx*/, int tableindex/*edx*/) { - char* pString; + char* pString = NULL; int result = 0; while (true) { - uint8_t language_code = ((uint8_t*)*pStringTable)[0]; - (*pStringTable)++; + uint8_t language_code = *(*pStringTable)++; + if (language_code == 0xFF) //end of string table break; + + // This is the ideal situation. Language found if (language_code == OpenRCT2LangIdToObjectLangId[gCurrentLanguage])//1) { pString = *pStringTable; result |= 1; } + + // Just in case always load english into pString if (language_code == 0 && !(result & 1)) { pString = *pStringTable; result |= 2; } + + // Failing that fall back to whatever is first string if (!(result & 7)) { pString = *pStringTable; result |= 4; } - while (true) - { - uint8_t character = ((uint8_t*)*pStringTable)[0]; - (*pStringTable)++; - if (character == 0) break; - } + + // Skip over the actual string entry to get to the next + // entry + while (*(*pStringTable)++ != 0); } + + // If not scenario text if (RCT2_GLOBAL(0x9ADAFC, uint8_t) == 0) { - int stringid = 0xD87; - int i; - for (i = 0; i < type; i++) + int stringid = 3463; + for (int i = 0; i < type; i++) { int nrobjects = object_entry_group_counts[i]; - int nrstringtables = RCT2_GLOBAL(0x98DA16 + i * 2, uint16_t);//the number of string tables in a type + int nrstringtables = RCT2_ADDRESS(0x98DA16, uint16)[i];//the number of string tables in a type stringid += nrobjects * nrstringtables; } - stringid += index * RCT2_GLOBAL(0x98DA16 + type * 2, uint16_t); - RCT2_GLOBAL(0x00F42BBC, uint32) = stringid; + stringid += index * RCT2_ADDRESS(0x98DA16, uint16)[type]; + // Used by the object list to allocate name in plugin.dat + RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32) = stringid; stringid += tableindex; - RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable + + //put pointer in stringtable + language_strings[stringid] = pString; + // Until all string related functions are finished copy + // to old array as well. + RCT2_ADDRESS(0x009BF2D4, char*)[stringid] = pString; return stringid; } else { - int stringid = 0xD77 + tableindex; - RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable + int stringid = 3447 + tableindex; + //put pointer in stringtable + language_strings[stringid] = pString; + // Until all string related functions are finished copy + // to old array as well. + RCT2_ADDRESS(0x009BF2D4, char*)[stringid] = pString; return stringid; } } \ No newline at end of file diff --git a/src/object.c b/src/object.c index f37f17ec0c..9e57254275 100644 --- a/src/object.c +++ b/src/object.c @@ -105,10 +105,8 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi return 0; } - int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); - - if (yyy >= 0x4726E){ - log_error("Object Load failed due to yyy failure."); + if (RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) >= 0x4726E){ + log_error("Object Load failed due to too many images loaded."); RCT2_GLOBAL(0x00F42BD9, uint8) = 4; rct2_free(chunk); return 0; @@ -231,9 +229,7 @@ int object_load_packed(FILE *file) return 0; } - int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); - - if (yyy >= 0x4726E){ + if (RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) >= 0x4726E){ rct2_free(chunk); return 0; } @@ -388,7 +384,7 @@ int object_calculate_checksum(const rct_object_entry *entry, const char *data, i /* rct2: 0x006A9ED1 */ int object_chunk_load_image_directory(uint8_t** chunk) { - int image_start_no = RCT2_GLOBAL(0x9ADAF0, uint32_t); + int image_start_no = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32_t); // First dword of chunk is no_images int no_images = *((uint32_t*)(*chunk)); @@ -397,7 +393,7 @@ int object_chunk_load_image_directory(uint8_t** chunk) int length_of_data = *((uint32_t*)(*chunk)); *chunk += 4; - RCT2_GLOBAL(0x9ADAF0, uint32_t) = no_images + image_start_no; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32_t) = no_images + image_start_no; rct_g1_element* g1_dest = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_start_no]; @@ -781,61 +777,63 @@ int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dp //rct2: 0x006A8621 int paint_path_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) { - if ((flags & 0xFF) != 3) - { - if ((flags & 0xFF) != 1) - { - if ((flags & 0xFF) <= 1)//0 - { - uint8_t* pStringTable = (uint8_t*)(esi + 0xE); - ((rct_path_type*)esi)->pad_00 = object_get_localised_text(&pStringTable, ecx, ebx, 0); + if ((flags & 0xFF) == 0){ + // Object Load - int image_id = object_chunk_load_image_directory(&pStringTable); - ((rct_path_type*)esi)->image = image_id; - image_id += 0x6D; - ((rct_path_type*)esi)->pad_06 = image_id; - if (RCT2_GLOBAL(0x9ADAF4, uint32_t) != 0xFFFFFFFF) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0; - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = 0; - int b = -1; - while (true) - { - b++; - if (b >= 0x10) break; - uint8_t* edi = object_entry_groups[5].chunks[ebx]; - if ((uint32_t)edi == 0xFFFFFFFF) continue; - if (!(edi[0xB] & 4)) - { - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = ebx; - break; - } - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = ebx; - } - return flags; - } - else + rct_path_type* path_type = (rct_path_type*)esi; + // String table starts after path entry + // Note there are 2 spare bytes after + // the path entry. + uint8* chunk = (uint8*)(esi + 0xE); + + // Only 1 string table for paths + path_type->string_idx = object_get_localised_text(&chunk, ecx, ebx, 0); + + int image_id = object_chunk_load_image_directory(&chunk); + path_type->image = image_id; + path_type->bridge_image = image_id + 109; + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = 0; + // Set the default path for when opening footpath window + for (int i = 0; i < object_entry_group_counts[OBJECT_TYPE_PATHS]; ++i){ + rct_path_type* path_type_entry = (rct_path_type*)object_entry_groups[OBJECT_TYPE_PATHS].chunks[i]; + if ((uint32)path_type_entry == 0xFFFFFFFF) continue; + if (!(path_type_entry->flags & 4)) { - if (((rct_path_type*)esi)->pad_0A >= 2) return 1;//actually the carry bit should be set (stc) - else return 0; + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; + break; } - } - else - { - ((rct_path_type*)esi)->pad_00 = 0; - ((rct_path_type*)esi)->image = 0; - ((rct_path_type*)esi)->pad_06 = 0; - return flags; + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; + } } - else - { + else if ((flags & 0xFF) == 1){ + // Object Unload + + rct_path_type* path_type = (rct_path_type*)esi; + path_type->string_idx = 0; + path_type->image = 0; + path_type->bridge_image = 0; + } + else if ((flags & 0xFF) == 2){ + + rct_path_type* path_type = (rct_path_type*)esi; + if (path_type->var_0A >= 2) return 1;//actually the carry bit should be set (stc) + else return 0; + } + else if ((flags & 0xFF) == 3){ + rct_path_type* path_type = (rct_path_type*)ebp; if (!((flags >> 8) & 0xFF)) { //Draws preview for scenario editor! - gfx_draw_sprite(dpi, ((rct_path_type*)ebp)->image + 71, ecx - 49, edx - 17, ebp); - gfx_draw_sprite(dpi, ((rct_path_type*)ebp)->image + 72, ecx + 4, edx - 17, ebp); + gfx_draw_sprite(dpi, path_type->image + 71, ecx - 49, edx - 17, ebp); + gfx_draw_sprite(dpi, path_type->image + 72, ecx + 4, edx - 17, ebp); } - return flags; + } + return flags; } //rct2: 0x00666E42 @@ -1051,8 +1049,10 @@ int object_get_scenario_text(rct_object_entry *entry) return 0; } - int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); - RCT2_GLOBAL(0x009ADAF0, uint32) = 0x726E; + 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; @@ -1061,7 +1061,7 @@ int object_get_scenario_text(rct_object_entry *entry) 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; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = total_no_images; return 1; } fclose(file); @@ -1101,7 +1101,7 @@ rct_object_entry *object_get_next(rct_object_entry *entry) // Skip filename while (*pos++); - // Skip + // Skip no of images pos += 4; // Skip name diff --git a/src/object_list.c b/src/object_list.c index 61f2ce8130..27c5688600 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -179,7 +179,7 @@ void sub_6A9FC0() { reset_9E32F8(); - RCT2_GLOBAL(0x009ADAF0, uint32) = 0xF26E; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0xF26E; for (int type = 0; type < 11; ++type){ for (int j = 0; j < object_entry_group_counts[type]; j++){ @@ -606,7 +606,7 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in *((uint16*)(installed_entry_pointer + 9)) = 0; *((uint32*)(installed_entry_pointer + 11)) = 0; - RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0xF26E; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; @@ -648,28 +648,31 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in 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]; + // When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars) + if ((objectType == OBJECT_TYPE_RIDE) && !((((rct_ride_type*)chunk)->var_008) & 0x1000)) { + rct_ride_type* ride_type = (rct_ride_type*)chunk; + rct_string_id obj_string = ride_type->var_00C; if (obj_string == 0xFF){ - obj_string = chunk[13]; + obj_string = ride_type->var_00D; if (obj_string == 0xFF) { - obj_string = chunk[14]; + obj_string = ride_type->var_00E; } } - obj_string += 2; - format_string(installed_entry_pointer, obj_string, 0); + format_string(installed_entry_pointer, obj_string + 2, 0); strcat(installed_entry_pointer, "\t ("); - strcat(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(0x00F42BBC, uint32))); + strcat(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32))); strcat(installed_entry_pointer, ")"); while (*installed_entry_pointer++); } else{ - strcpy(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(0x00F42BBC, uint32))); + strcpy(installed_entry_pointer, language_get_string((rct_string_id)RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32))); while (*installed_entry_pointer++); } - *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x009ADAF0, uint32) - 0xF26E; + + // This is deceptive. Due to setting the total no images earlier to 0xF26E + // this is actually the no_images in this entry. + *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) - 0xF26E; installed_entry_pointer += 4; uint8* esi = RCT2_ADDRESS(0x00F42BDB, uint8); diff --git a/src/world/footpath.h b/src/world/footpath.h index d722d7838f..3bdb3ce8f0 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -29,11 +29,11 @@ enum { }; typedef struct { - uint16 pad_00; - uint32 image; // 0x02 - uint32 pad_06; - uint8 pad_0A; - uint8 flags; // 0x0B + rct_string_id string_idx; // 0x00 + uint32 image; // 0x02 + uint32 bridge_image; // 0x06 + uint8 var_0A; + uint8 flags; // 0x0B } rct_path_type; void game_command_place_footpath(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);