diff --git a/src/addresses.h b/src/addresses.h index 5eed5c0e08..a0965b6896 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -129,6 +129,7 @@ #define RCT2_ADDRESS_RIDE_ENTRIES 0x009ACFA4 #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 +#define RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST 0x009ADAEC #define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280 @@ -253,10 +254,11 @@ #define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908 -#define RCT2_ADDRESS_TRACK_LIST 0x00F44105 -#define RCT2_ADDRESS_TRACK_LIST_CACHE 0x00F44109 -#define RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX 0x00F44119 +#define RCT2_ADDRESS_TRACK_DESIGN_CACHE 0x00F44105 +#define RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE 0x00F44109 +#define RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE 0x00F44119 +#define RCT2_ADDRESS_TRACK_LIST 0x00F441EC #define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8 #define RCT2_ADDRESS_CURRENT_MONTH_TICKS 0x00F663AA diff --git a/src/object.h b/src/object.h index 70be1a0f5a..239ce2658b 100644 --- a/src/object.h +++ b/src/object.h @@ -87,6 +87,8 @@ int object_calculate_checksum(const rct_object_entry *entry, const char *data, i 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); +void sub_6A9FC0(); +int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index); rct_object_entry *object_list_find(rct_object_entry *entry); diff --git a/src/object_list.c b/src/object_list.c index 2edf1c88fa..b2f4edf889 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -136,7 +136,7 @@ void sub_6A9FC0() for (int j = 0; j < object_entry_group_counts[type]; j++){ uint8* chunk = object_entry_groups[type].chunks[j]; if (chunk != (uint8*)-1) - object_paint(type, 0, 0, 0, 0, (int)chunk, 0, 0); + object_paint(type, 0, j, type, 0, (int)chunk, 0, 0); } } } @@ -488,6 +488,30 @@ void object_list_create_hash_table() } } +/* 0x006A9DA2 + * bl = entry_index + * ecx = entry_type + */ +int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index){ + *entry_type = entry->flags & 0xF; + + rct_object_entry_group entry_group = object_entry_groups[*entry_type]; + for (*entry_index = 0; + *entry_index < object_entry_group_counts[*entry_type]; + ++(*entry_index), + entry_group.chunks++, + entry_group.entries++){ + + if (*entry_group.chunks == (uint8*)-1) continue; + + if (object_entry_compare((rct_object_entry*)entry_group.entries, entry))break; + } + + if (*entry_index == object_entry_group_counts[*entry_type])return 0; + return 1; +} + + rct_object_entry *object_list_find(rct_object_entry *entry) { uint32 hash = object_get_hash_code(entry); diff --git a/src/rct1.h b/src/rct1.h index cbcb265f4e..466e5fc184 100644 --- a/src/rct1.h +++ b/src/rct1.h @@ -209,5 +209,139 @@ typedef struct { uint32 expansion_pack_checksum; } rct1_s4; +enum { + RCT1_RIDE_TYPE_NULL = 255, + RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER = 0, + RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER, + RCT1_RIDE_TYPE_SUSPENDED_ROLLER_COASTER, + RCT1_RIDE_TYPE_INVERTED_ROLLER_COASTER, + RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER, + RCT1_RIDE_TYPE_MINIATURE_RAILROAD, + RCT1_RIDE_TYPE_MONORAIL, + RCT1_RIDE_TYPE_SUSPENDED_SINGLE_RAIL_ROLLER_COASTER, + RCT1_RIDE_TYPE_BOAT_HIRE, + RCT1_RIDE_TYPE_WOODEN_CRAZY_RODENT_ROLLER_COASTER, + RCT1_RIDE_TYPE_SINGLE_RAIL_ROLLER_COASTER, + RCT1_RIDE_TYPE_CAR_RIDE, + RCT1_RIDE_TYPE_WHOA_BELLY, + RCT1_RIDE_TYPE_BOBSLED_ROLLER_COASTER, + RCT1_RIDE_TYPE_OBSERVATION_TOWER, + RCT1_RIDE_TYPE_STEEL_ROLLER_COASTER, + RCT1_RIDE_TYPE_WATER_SLIDE, + RCT1_RIDE_TYPE_MINE_TRAIN_ROLLER_COASTER, + RCT1_RIDE_TYPE_CHAIRLIFT, + RCT1_RIDE_TYPE_STEEL_CORKSCREW_ROLLER_COASTER, + RCT1_RIDE_TYPE_HEDGE_MAZE, + RCT1_RIDE_TYPE_SPIRAL_SLIDE, + RCT1_RIDE_TYPE_GO_KARTS, + RCT1_RIDE_TYPE_LOG_FLUME, + RCT1_RIDE_TYPE_RIVER_RAPIDS, + RCT1_RIDE_TYPE_BUMPER_CARS, + RCT1_RIDE_TYPE_SWINGING_SHIP, + RCT1_RIDE_TYPE_SWINGING_INVERTER_SHIP, + RCT1_RIDE_TYPE_ICE_CREAM_STALL, + RCT1_RIDE_TYPE_FRIES_STALL, + RCT1_RIDE_TYPE_DRINK_STALL, + RCT1_RIDE_TYPE_COTTON_CANDY_STALL, + RCT1_RIDE_TYPE_BURGER_BAR, + RCT1_RIDE_TYPE_MERRY_GO_ROUND, + RCT1_RIDE_TYPE_BALLOON_STALL, + RCT1_RIDE_TYPE_INFORMATION_KIOSK, + RCT1_RIDE_TYPE_BATHROOM, + RCT1_RIDE_TYPE_FERRIS_WHEEL, + RCT1_RIDE_TYPE_MOTION_SIMULATOR, + RCT1_RIDE_TYPE_3D_CINEMA, + RCT1_RIDE_TYPE_GRAVITRON, + RCT1_RIDE_TYPE_SPACE_RINGS, + RCT1_RIDE_TYPE_REVERSE_WHOA_BELLY_ROLLER_COASTER, + RCT1_RIDE_TYPE_SOUVENIR_STALL, + RCT1_RIDE_TYPE_VERTICAL_ROLLER_COASTER, + RCT1_RIDE_TYPE_PIZZA_STALL, + RCT1_RIDE_TYPE_SCRAMBLED_EGGS, + RCT1_RIDE_TYPE_HAUNTED_HOUSE, + RCT1_RIDE_TYPE_POPCORN_STALL, + RCT1_RIDE_TYPE_CIRCUS_SHOW, + RCT1_RIDE_TYPE_GHOST_TRAIN, + RCT1_RIDE_TYPE_STEEL_TWISTER_ROLLER_COASTER, + RCT1_RIDE_TYPE_WOODEN_TWISTER_ROLLER_COASTER, + RCT1_RIDE_TYPE_WOODEN_SIDE_FRICTION_ROLLER_COASTER, + RCT1_RIDE_TYPE_STEEL_WILD_MOUSE_ROLLER_COASTER, + RCT1_RIDE_TYPE_HOT_DOG_STALL, + RCT1_RIDE_TYPE_EXOTIC_SEA_FOOD_STALL, + RCT1_RIDE_TYPE_HAT_STALL, + RCT1_RIDE_TYPE_CANDY_APPLE_STAND, + RCT1_RIDE_TYPE_VIRGINIA_REEL, + RCT1_RIDE_TYPE_RIVER_RIDE, + RCT1_RIDE_TYPE_CYCLE_MONORAIL, + RCT1_RIDE_TYPE_FLYING_ROLLER_COASTER, + RCT1_RIDE_TYPE_SUSPENDED_MONORAIL, + RCT1_RIDE_TYPE_40, + RCT1_RIDE_TYPE_WOODEN_REVERSER_ROLLER_COASTER, + RCT1_RIDE_TYPE_HEARTLINE_TWISTER_ROLLER_COASTER, + RCT1_RIDE_TYPE_MINIATURE_GOLF, + RCT1_RIDE_TYPE_44, + RCT1_RIDE_TYPE_ROTO_DROP, + RCT1_RIDE_TYPE_FLYING_SAUCERS, + RCT1_RIDE_TYPE_CROOKED_HOUSE, + RCT1_RIDE_TYPE_CYCLE_RAILWAY, + RCT1_RIDE_TYPE_SUSPENDED_LOOPING_ROLLER_COASTER, + RCT1_RIDE_TYPE_WATER_COASTER, + RCT1_RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER, + RCT1_RIDE_TYPE_INVERTED_WILD_MOUSE_COASTER, + RCT1_RIDE_TYPE_JET_SKIS, + RCT1_RIDE_TYPE_T_SHIRT_STALL, + RCT1_RIDE_TYPE_RAFT_RIDE, + RCT1_RIDE_TYPE_DOUGHNUT_SHOP, + RCT1_RIDE_TYPE_ENTERPRISE, + RCT1_RIDE_TYPE_COFFEE_SHOP, + RCT1_RIDE_TYPE_FRIED_CHICKEN_STALL, + RCT1_RIDE_TYPE_LEMONADE_STALL +}; + +typedef struct{ + uint8 type; // 0x00 + uint8 vehicle_type; // 0x01 + uint32 special_track_flags; // 0x02 + uint8 operating_mode; // 0x06 + uint8 vehicle_colour_version; // 0x07 Vehicle colour type in first two bits, Version in bits 3,4 + uint8 body_trim_colour[24]; // 0x08 + uint8 track_spine_colour_rct1; // 0x20 + uint8 track_rail_colour_rct1; // 0x21 + uint8 track_support_colour_rct1; // 0x22 + uint8 departure_control_flags; // 0x23 + uint8 number_of_trains; // 0x24 + uint8 cars_per_train; // 0x25 + uint8 min_wait_time; // 0x26 + uint8 max_wait_time; // 0x27 + uint8 speed; // 0x28 + uint8 max_speed; // 0x29 + uint8 average_speed; // 0x2A + uint16 ride_length; // 0x2B + uint8 max_positive_vertical_g; // 0x2D + uint8 max_negitive_vertical_g; // 0x2E + uint8 max_lateral_g; // 0x2F + union { + uint8 inversions; // 0x30 + uint8 holes; // 0x30 + }; + uint8 drops; // 0x31 + uint8 highest_drop_height; // 0x32 + uint8 excitement; // 0x33 + uint8 intensity; // 0x34 + uint8 nausea; // 0x35 + uint8 pad_36[2]; + union{ + uint16 start_track_data_original; // 0x38 + uint8 track_spine_colour[4]; // 0x38 + }; + uint8 track_rail_colour[4]; // 0x3C + union{ + uint8 track_support_colour[4]; // 0x40 + uint8 wall_type[4]; // 0x40 + }; + uint8 pad_41[0x83]; + uint16 start_track_data_AA_CF; // 0xC4 +}rct_track_td4; // Information based off RCTTechDepot + #endif \ No newline at end of file diff --git a/src/ride/track.c b/src/ride/track.c index c3956d0ab8..44a079cf13 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -22,8 +22,10 @@ #include "../platform/osinterface.h" #include "../util/sawyercoding.h" #include "../util/util.h" +#include "../rct1.h" #include "ride.h" #include "track.h" +#include "../platform/platform.h" /** * @@ -220,13 +222,223 @@ const rct_trackdefinition gTrackDefinitions[] = { { TRACK_HALF_LOOP_2, TRACK_DOWN_25, TRACK_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_LEFT_LARGE_HALF_LOOP_DOWN }; +uint32* sub_6AB49A(rct_object_entry* entry){ + rct_object_entry* object_list_entry = object_list_find(entry); + + if (object_list_entry == NULL) return NULL; + + // Return the address of the last value of the list entry + return (((uint32*)object_get_next(object_list_entry)) - 1); +} + +static void get_track_idx_path(char *path) +{ + char *homePath = osinterface_get_orct2_homefolder(); + sprintf(path, "%s%c%s", homePath, osinterface_get_path_separator(), "Tracks.IDX"); + free(homePath); +} + +static void track_list_query_directory(int *outTotalFiles){ + int enumFileHandle; + file_info enumFileInfo; + + *outTotalFiles = 0; + + // Enumerate through each track in the directory + enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char)); + if (enumFileHandle == INVALID_HANDLE) + return; + + while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) { + (*outTotalFiles)++; + } + platform_enumerate_files_end(enumFileHandle); +} + +static int track_list_cache_save(int fileCount, uint8* track_list_cache, uint32 track_list_size){ + char path[MAX_PATH]; + FILE *file; + + log_verbose("saving track list cache (tracks.idx)"); + get_track_idx_path(path); + file = fopen(path, "wb"); + if (file == NULL) { + log_error("Failed to save %s", path); + return 0; + } + + fwrite(&fileCount, sizeof(int), 1, file); + fwrite(track_list_cache, track_list_size, 1, file); + uint8 last_entry = 0xFE; + fwrite(&last_entry, 1, 1, file); + fclose(file); + return 1; +} + +static uint8* track_list_cache_load(int totalFiles){ + char path[MAX_PATH]; + FILE *file; + + log_verbose("loading track list cache (tracks.idx)"); + get_track_idx_path(path); + file = fopen(path, "rb"); + if (file == NULL) { + log_error("Failed to load %s", path); + return 0; + } + + uint8* track_list_cache; + uint32 fileCount; + // Remove 4 for the file count variable + long track_list_size = fsize(file) - 4; + + if (track_list_size < 0) return 0; + + fread(&fileCount, 4, 1, file); + + if (fileCount != totalFiles){ + log_verbose("Track file count is different."); + return 0; + } + + track_list_cache = malloc(track_list_size); + fread(track_list_cache, track_list_size, 1, file); + return track_list_cache; +} + +void track_list_populate(ride_list_item item, uint8* track_list_cache){ + uint8* track_pointer = track_list_cache; + + uint8 cur_track_entry_index = 0; + for (uint8 track_type = *track_pointer++; track_type != 0xFE; + track_pointer += strlen(track_pointer) + 1, + track_type = *track_pointer++){ + rct_object_entry* track_object = (rct_object_entry*)track_pointer; + track_pointer += sizeof(rct_object_entry); + + if (track_type != item.type){ + continue; + } + + uint8 entry_type, entry_index; + if (item.entry_index != 0xFF){ + + if (!find_object_in_entry_group(track_object, &entry_type, &entry_index))continue; + + if (item.entry_index != entry_index)continue; + } + else{ + if (find_object_in_entry_group(track_object, &entry_type, &entry_index)){ + if (GET_RIDE_ENTRY(entry_index)->var_008 & 0x3000)continue; + } + else{ + uint32* esi = sub_6AB49A(track_object); + if (esi == NULL) continue; + if (*esi & 0x1000000)continue; + } + } + + // If cur_track_entry_index is greater than max number of tracks + if (cur_track_entry_index >= 1000){ + RCT2_GLOBAL(0xF635ED, uint8) |= 1; + break; + } + + uint8 track_entry_index = 0; + uint8 isBelow = 0; + for (; track_entry_index != cur_track_entry_index; track_entry_index++){ + if (strcicmp(track_pointer, &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128]) < 0){ + isBelow = 1; + break; + } + } + + if (isBelow == 1){ + memmove( + &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128 + 128], + &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128], + (cur_track_entry_index - track_entry_index) * 128); + } + + strcpy(&RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128], track_pointer); + cur_track_entry_index++; + } + + RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[cur_track_entry_index * 128] = '\0'; + free(track_list_cache); +} + /** * * rct2: 0x006CED50 */ void track_load_list(ride_list_item item) { - RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0); + RCT2_GLOBAL(0xF635ED, uint8) = 0; + + if (item.type < 0x80){ + rct_ride_type* ride_type = gRideTypeList[item.entry_index]; + if (!(ride_type->var_008 & 0x2000)){ + item.entry_index = 0xFF; + } + } + + int totalFiles; + + track_list_query_directory(&totalFiles); + + uint8* track_list_cache; + + if (item.type == 0xFC || !(track_list_cache = track_list_cache_load(totalFiles))){ + uint8* new_track_file; + + new_track_file = malloc(0x40000); + + uint8* new_file_pointer = new_track_file; + file_info enumFileInfo; + + int enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char)); + if (enumFileHandle == INVALID_HANDLE) + return; + + while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) { + if (new_file_pointer > new_track_file + 0x3FF00)break; + + char path[MAX_PATH]; + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), enumFileInfo.path); + + rct_track_td6* loaded_track = load_track_design(path); + if (loaded_track){ + *new_file_pointer++ = loaded_track->type; + } + else{ + *new_file_pointer++ = 0xFF; + } + memcpy(new_file_pointer, &loaded_track->vehicle_object, sizeof(rct_object_entry)); + new_file_pointer += sizeof(rct_object_entry); + + int file_name_length = strlen(enumFileInfo.path); + strcpy(new_file_pointer, enumFileInfo.path); + new_file_pointer += file_name_length + 1; + } + platform_enumerate_files_end(enumFileHandle); + + if (!track_list_cache_save(totalFiles, new_track_file, new_file_pointer - new_track_file)){ + log_error("Track list failed to save."); + return; + } + free(new_track_file); + + track_list_cache = track_list_cache_load(totalFiles); + if (!track_list_cache){ + log_error("Track list failed to load after new save"); + return; + } + } + + track_list_populate(item, track_list_cache); + free(track_list_cache); + //RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0); } static void read(void *dst, void **src, int length) @@ -240,7 +452,7 @@ static void read(void *dst, void **src, int length) * rct2: 0x0067726A * path: 0x0141EF68 */ -rct_track_design* load_track_design(const char *path) +rct_track_td6* load_track_design(const char *path) { FILE *fp; long fpLength; @@ -270,72 +482,87 @@ rct_track_design* load_track_design(const char *path) realloc(decoded, decodedLength); free(fpBuffer); - rct_track_design* track_design = RCT2_ADDRESS(0x009D8178, rct_track_design); + rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6); // Read decoded data src = decoded; - // Clear top of track_design as this is not loaded from the file - memset(&track_design->pad_60, 0, 67); + // Clear top of track_design as this is not loaded from the td4 files + memset(&track_design->track_spine_colour, 0, 67); // Read start of track_design read(track_design, &src, 32); - uint8 al = track_design->var_07 >> 2; - if (al >= 2) - read(&track_design->pad_20, &src, 40); + uint8 version = track_design->var_07 >> 2; + + if (version > 2){ + free(decoded); + return NULL; + } + + // In td6 there are 32 sets of two byte vehicle colour specifiers + // In td4 there are 12 sets so the remaining 20 need to be read. + if (version == 2) + read(&track_design->vehicle_colours[12], &src, 40); read(&track_design->pad_48, &src, 24); - al = track_design->var_07 >> 2; - if (al != 0) - read(&track_design->pad_60, &src, al == 1 ? 140 : 67); - read(&track_design->preview, &src, 24572); - al = track_design->var_07 >> 2; - if (al < 2) { - if (track_design->type == RIDE_TYPE_MAZE) { - edi = (uint8*)(&track_design->preview); - while (*edi != 0) { - edi += 4; - } - edi += 4; - memset(edi, 255, ((uint8*)&track_design->pad_9F) - edi); - } else { - edi = (uint8*)(&track_design->preview); - while (*edi != 255) { - edi += 2; - } - edi++; - memset(edi, 255, ((uint8*)&track_design->pad_9F) - edi); - } - } + // In td4 (version AA/CF) and td6 both start actual track data at 0xA3 + if (version > 0) + read(&track_design->track_spine_colour, &src, version == 1 ? 140 : 67); + + uint8* track_elements = RCT2_ADDRESS(0x9D821B, uint8); + // Read the actual track data. + read(track_elements, &src, 24572); + + uint8* final_track_element_location = track_elements + 24572; free(decoded); - // - al = track_design->var_07 >> 2; - if (al > 2) - return NULL; + // td4 files require some work to be recognised as td6. + if (version < 2) { - if (al <= 1) { - edi = (uint8*)&track_design->pad_08; + // Set any element passed the tracks to 0xFF + if (track_design->type == RIDE_TYPE_MAZE) { + uint32* maze_element = (uint32*)track_elements; + while (*maze_element != 0) { + maze_element++; + } + maze_element++; + memset(maze_element, 255, final_track_element_location - (uint8*)maze_element); + } else { + uint8* track_element = track_elements; + while (*track_element != 255) { + track_element += 2; + } + track_element++; + memset(track_element, 255, final_track_element_location - track_element); + } + + // Edit the colours to use the new versions + // Unsure why it is 67 + edi = (uint8*)&track_design->vehicle_colours; for (i = 0; i < 67; i++) *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi]; - edi = (uint8*)&track_design->pad_60; + // Edit the colours to use the new versions + edi = (uint8*)&track_design->track_spine_colour; for (i = 0; i < 12; i++) *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi]; + // Highest drop height is 1bit = 3/4 a meter in td6 + // Highest drop height is 1bit = 1/3 a meter in td4 + // Not sure if this is correct?? track_design->highest_drop_height >>= 1; - if (!RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0)) - track_design->type = 255; - - if (track_design->type == RIDE_TYPE_JUNIOR_ROLLER_COASTER) + if (0x100 & RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0)) track_design->type = RIDE_TYPE_NULL; - if (track_design->type == RIDE_TYPE_SPIRAL_ROLLER_COASTER) + if (track_design->type == RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER) + track_design->type = RIDE_TYPE_NULL; + + if (track_design->type == RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER) track_design->type = RIDE_TYPE_WOODEN_ROLLER_COASTER; if (track_design->type == RIDE_TYPE_CORKSCREW_ROLLER_COASTER) { if (track_design->var_06 == 3) track_design->var_06 = 35; - if (track_design->var_01 == 79) { + if (track_design->vehicle_type == 79) { if (track_design->var_06 == 2) track_design->var_06 = 1; } @@ -345,15 +572,15 @@ rct_track_design* load_track_design(const char *path) if (track_design->type == RIDE_TYPE_MAZE) { vehicle_object = RCT2_ADDRESS(0x0097F66C, rct_object_entry); } else { - int var_01 = track_design->var_01; - if (var_01 == 3 && track_design->type == 3) - var_01 = 80; - vehicle_object = &RCT2_ADDRESS(0x0097F0DC, rct_object_entry)[var_01]; + int vehicle_type = track_design->vehicle_type; + if (vehicle_type == 3 && track_design->type == RIDE_TYPE_INVERTED_ROLLER_COASTER) + vehicle_type = 80; + vehicle_object = &RCT2_ADDRESS(0x0097F0DC, rct_object_entry)[vehicle_type]; } memcpy(&track_design->vehicle_object, vehicle_object, sizeof(rct_object_entry)); for (i = 0; i < 32; i++) - track_design->pad_82[i] = track_design->pad_08[1 + i * 2]; + track_design->vehicle_additional_colour[i] = track_design->vehicle_colours[i].trim_colour; track_design->space_required_x = 255; track_design->space_required_y = 255; @@ -370,11 +597,11 @@ rct_track_design* load_track_design(const char *path) /* rct2: 0x006D1DCE*/ void reset_track_list_cache(){ - int* track_list_cache = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, int); + int* track_list_cache = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, int); for (int i = 0; i < 4; ++i){ track_list_cache[i] = -1; } - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0; } /** @@ -385,49 +612,49 @@ void reset_track_list_cache(){ rct_track_design *track_get_info(int index, uint8** preview) { rct_track_design *trackDesign; - uint8 *trackDesignList = (uint8*)0x00F441EC; + uint8 *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); int i; trackDesign = NULL; // Check if track design has already been loaded for (i = 0; i < 4; i++) { - if (index == RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, uint32)[i]) { - trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, rct_track_design*)[i]; + if (index == RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i]) { + trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, rct_track_design*)[i]; break; } } if (trackDesign == NULL) { // Load track design - i = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32)++; - if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) >= 4) - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) = 0; + i = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32)++; + if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) >= 4) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0; - RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, uint32)[i] = index; + RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i] = index; char track_path[MAX_PATH] = { 0 }; subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128)); - rct_track_design* loaded_design = NULL; + rct_track_td6* loaded_track = NULL; log_verbose("Loading track: %s", trackDesignList + (index * 128)); - if (!(loaded_design = load_track_design(track_path))) { + if (!(loaded_track = load_track_design(track_path))) { if (preview != NULL) *preview = NULL; log_error("Failed to load track: %s", trackDesignList + (index * 128)); return NULL; } - trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, rct_track_design*)[i]; - + trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, rct_track_design*)[i]; + // Copy the track design apart from the preview image - memcpy(trackDesign, loaded_design, 163); + memcpy(&trackDesign->track_td6, loaded_track, sizeof(rct_track_td6)); // Load in a new preview image, calculate cost variable, calculate var_06 RCT2_CALLPROC_X(0x006D1EF0, 0, 0, 0, 0, 0, (int)&trackDesign->preview, 0); - trackDesign->cost = RCT2_GLOBAL(0x00F4411D, money32); - trackDesign->var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7; + trackDesign->track_td6.cost = RCT2_GLOBAL(0x00F4411D, money32); + trackDesign->track_td6.var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7; } // Set preview to correct preview image based on rotation @@ -453,4 +680,4 @@ int track_rename(const char *text) int track_delete() { return (RCT2_CALLPROC_X(0x006D3761, 0, 0, 0, 0, 0, 0, 0) & 0x100) != 0; -} \ No newline at end of file +} diff --git a/src/ride/track.h b/src/ride/track.h index 10d66427e7..7f62f0547d 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -37,21 +37,29 @@ typedef struct { #define TRACK_PREVIEW_IMAGE_SIZE (370 * 217) +/* size: 0x2 */ +typedef struct{ + uint8 body_colour; + uint8 trim_colour; +} rct_track_vehicle_colour; + /** * Track design structure. * size: 0x4E72B */ typedef struct { uint8 type; // 0x00 - uint8 var_01; + uint8 vehicle_type; money32 cost; // 0x02 uint8 var_06; uint8 var_07; - uint8 pad_08[0x18]; - uint8 pad_20[40]; + rct_track_vehicle_colour vehicle_colours[32]; // 0x08 uint8 pad_48[2]; uint8 total_air_time; // 0x4A - uint8 pad_4B[0x05]; + uint8 pad_4B; + uint8 number_of_trains; // 0x4C + uint8 number_of_cars_per_train; // 0x4D + uint8 pad_4E[2]; uint8 var_50; uint8 max_speed; // 0x51 uint8 average_speed; // 0x52 @@ -69,17 +77,23 @@ typedef struct { uint8 intensity; // 0x5C uint8 nausea; // 0x5D uint8 pad_5E[2]; - uint8 pad_60[0xC]; + uint8 track_spine_colour[4]; // 0x60 + uint8 track_rail_colour[4]; // 0x64 + uint8 track_support_colour[4]; // 0x68 uint32 var_6C; rct_object_entry vehicle_object; // 0x70 uint8 space_required_x; // 0x80 uint8 space_required_y; // 0x81 - uint8 pad_82[0x1D]; - uint8 pad_9F[3]; + uint8 vehicle_additional_colour[32]; // 0x82 uint8 var_A2; +} rct_track_td6; + +typedef struct{ + rct_track_td6 track_td6; uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3 } rct_track_design; + enum { TRACK_NONE = 0, @@ -140,8 +154,9 @@ enum { void track_load_list(ride_list_item item); int sub_67726A(const char *path); rct_track_design *track_get_info(int index, uint8** preview); +rct_track_td6* load_track_design(const char *path); int track_rename(const char *text); int track_delete(); void reset_track_list_cache(); -#endif \ No newline at end of file +#endif diff --git a/src/util/util.c b/src/util/util.c index 8abdaca2ca..dffbb8a5ee 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -75,4 +75,14 @@ int bitscanforward(int source) return i; return -1; +} + +/* case insensitve compare */ +int strcicmp(char const *a, char const *b) +{ + for (;; a++, b++) { + int d = tolower(*a) - tolower(*b); + if (d != 0 || !*a) + return d; + } } \ No newline at end of file diff --git a/src/util/util.h b/src/util/util.h index 82098918be..ac62a3ad79 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -31,5 +31,6 @@ void path_set_extension(char *path, const char *extension); long fsize(FILE *fp); int bitscanforward(int source); +int strcicmp(char const *a, char const *b); #endif diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index b7f21646c2..a68c18d77e 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -23,6 +23,9 @@ #include "../interface/widget.h" #include "../interface/window.h" #include "../object.h" +#include "../audio/audio.h" +#include "../ride/track.h" +#include "error.h" #pragma region Widgets @@ -55,9 +58,11 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX { static void window_editor_object_selection_emptysub() { } static void window_editor_object_selection_mouseup(); +static void window_editor_object_selection_scroll_mousedown(); +static void window_editor_object_selection_close(); static void* window_editor_object_selection_events[] = { - (void*)0x006AB199, + window_editor_object_selection_close, (void*)window_editor_object_selection_mouseup, (void*)window_editor_object_selection_emptysub, (void*)window_editor_object_selection_emptysub, @@ -73,7 +78,7 @@ static void* window_editor_object_selection_events[] = { (void*)window_editor_object_selection_emptysub, (void*)window_editor_object_selection_emptysub, (void*)0x006AB031, - (void*)0x006AB0B6, + window_editor_object_selection_scroll_mousedown, (void*)window_editor_object_selection_emptysub, (void*)0x006AB079, (void*)window_editor_object_selection_emptysub, @@ -106,6 +111,10 @@ void window_editor_object_selection_open() RCT2_CALLPROC_EBPSAFE(0x006AB211); RCT2_CALLPROC_EBPSAFE(0x006AA770); + // HACK REMOVE WHEN ALL OBJECT_LOAD CALLS FINISHED + // Force Expansion Packs to always pass tests on object load + RCT2_GLOBAL(0x9AB4C0, uint16) = 0xFF; + window = window_create( RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300, max(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) / 2 - 200, 28), @@ -194,4 +203,161 @@ static void window_editor_object_set_page(rct_window *w, int page) w->scrolls[0].v_top = 0; RCT2_CALLPROC_EBPSAFE(0x006A982D); // object_free_scenario_text(); window_invalidate(w); +} + +/* rct2: 0x006AA703 + * Takes the y coordinate of the clicked on scroll list + * and converts this into an object selection. + * Returns the position in the list. + * Object_selection_flags, installed_entry also populated + */ +int get_object_from_object_selection(uint8 object_type, int y, uint8* object_selection_flags, rct_object_entry** installed_entry){ + *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); + int object_count = 0; + for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + if (((*installed_entry)->flags & 0xF) == object_type){ + if (!(*selection_flags & 0x20)){ + y -= 12; + *object_selection_flags = *selection_flags; + if (y < 0)return object_count; + object_count++; + } + } + + *installed_entry = object_get_next(*installed_entry); + selection_flags++; + } + return -1; +} + +/* rct2: 0x006D33E2 */ +void sub_6d33e2(){ + RCT2_GLOBAL(0x1357404, sint32) = -1; + RCT2_GLOBAL(0x1357408, sint32) = -1; + RCT2_GLOBAL(0x135740C, sint32) = -1; + RCT2_GLOBAL(0x1357410, sint32) = -1; + + for (int i = 0; i < 128; ++i){ + RCT2_ADDRESS(0x1357444, uint32)[i] = RCT2_ADDRESS(0x97C468, uint32)[i]; + RCT2_ADDRESS(0x1357644, uint32)[i] = RCT2_ADDRESS(0x97C5D4, uint32)[i]; + } + + for (int i = 0; i < 8; ++i){ + RCT2_ADDRESS(0x1357424, sint32)[i] = -1; + } + + RCT2_GLOBAL(0x141F570, uint8) = 7; + + int entry_index = 0; + for (; ((int)object_entry_groups[0].chunks[entry_index]) == -1; ++entry_index); + + //RCT2_GLOBAL(0xF44157, uint8) = entry_index; + + rct_ride_type* ride_entry = GET_RIDE_ENTRY(entry_index); + uint8* ride_type_array = &ride_entry->var_00C; + + int ride_type; + for (int i = 0; (ride_type = ride_type_array[i]) == 0xFF; i++); + //RCT2_GLOBAL(0xF44158, uint8) = ride_type; + + ride_list_item item = { ride_type, entry_index }; + track_load_list(item); + window_track_list_open(item); +} + +/* rct2: 0x006AB0B6 */ +static void window_editor_object_selection_scroll_mousedown(){ + short x, y, scrollIndex; + rct_window *w; + + window_scrollmouse_get_registers(w, scrollIndex, x, y); + + uint8 object_selection_flags; + rct_object_entry* installed_entry; + int selected_object = get_object_from_object_selection((w->selected_tab & 0xFF), y, &object_selection_flags, &installed_entry); + if (selected_object == -1) return; + + if (object_selection_flags & 0x20)return; + + window_invalidate(w); + + sound_play_panned(SOUND_CLICK_1, RCT2_GLOBAL(0x142406C,uint32), 0, 0, 0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER){ + if (RCT2_CALLPROC_X(0x6AB54F, 0, 1, 0, 0, 0, 0, (int)installed_entry) & 0x100)return; + + window_close(w); + + //This function calls window_track_list_open + sub_6d33e2(); + return; + } + + int ebx = 6; + // If already selected + if (!(object_selection_flags & 1)) + ebx = 7; + + RCT2_GLOBAL(0xF43411, uint8) = 0; + if (0x100 & RCT2_CALLPROC_X(0x6AB54F, 0, ebx, 0, 0, 0, 0, (int)installed_entry)){ + + rct_string_id error_title; + if (ebx & 1) + error_title = 3176; + else + error_title = 3177; + + window_error_open(error_title, RCT2_GLOBAL(0x141E9AC, uint16)); + return; + } + + if (!RCT2_GLOBAL(0xF43411, uint8) & 1)return; + + window_error_open(3374, 3375); +} + +/* rct2:0x006ABBBE */ +static void editor_load_selected_objects(){ + uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); + rct_object_entry* installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + + if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0)return; + + for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i != 0; --i, selection_flags++){ + + if (*selection_flags & 1){ + + uint8 entry_index, entry_type; + if (!find_object_in_entry_group(installed_entry, &entry_type, &entry_index)){ + int chunk_size; + if (!object_load(-1, installed_entry, &chunk_size)){ + log_error("Failed to load entry %.8s", installed_entry->name); + } + } + } + + installed_entry = object_get_next(installed_entry); + } +} + +/* rct2: 0x006AB199 */ +static void window_editor_object_selection_close(){ + rct_window* w; + window_get_register(w); + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & + (SCREEN_FLAGS_SCENARIO_EDITOR | + SCREEN_FLAGS_TRACK_MANAGER | + SCREEN_FLAGS_TRACK_MANAGER)) + )return; + + RCT2_CALLPROC_EBPSAFE(0x6ABB66); + editor_load_selected_objects(); + sub_6A9FC0(); + RCT2_CALLPROC_EBPSAFE(0x6A982D); + RCT2_CALLPROC_EBPSAFE(0x6AB316); + RCT2_CALLPROC_EBPSAFE(0x685675); + RCT2_CALLPROC_EBPSAFE(0x68585B); + window_new_ride_init_vars(); } \ No newline at end of file diff --git a/src/windows/track_list.c b/src/windows/track_list.c index c996df281b..bda822fcc4 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -126,7 +126,7 @@ void window_track_list_open(ride_list_item item) if (mem == NULL) return; - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, void*) = mem; + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*) = mem; reset_track_list_cache(); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { @@ -136,7 +136,7 @@ void window_track_list_open(ride_list_item item) x = 0; y = 29; } - w = window_create(0, 29, 600, 400, (uint32*)window_track_list_events, WC_TRACK_DESIGN_LIST, 0); + w = window_create(x, y, 600, 400, (uint32*)window_track_list_events, WC_TRACK_DESIGN_LIST, 0); w->widgets = window_track_list_widgets; w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY); window_init_scroll_widgets(w); @@ -144,7 +144,7 @@ void window_track_list_open(ride_list_item item) w->colours[1] = 26; w->colours[2] = 26; w->track_list.var_480 = 0xFFFF; - w->track_list.var_482 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 1 : 0; + w->track_list.var_482 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1; w->track_list.var_484 = 0; RCT2_GLOBAL(0x00F44152, uint8) = 0; window_push_others_right(w); @@ -157,7 +157,7 @@ void window_track_list_open(ride_list_item item) */ static void window_track_list_select(rct_window *w, int index) { - uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC; + uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); rct_track_design *trackDesign; w->track_list.var_480 = index; @@ -182,18 +182,19 @@ static void window_track_list_select(rct_window *w, int index) (char*)0x009BC313, trackDesignItem, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? - 0 : - FORMAT_WHITE - ); + 0 : + FORMAT_WHITE + ); - subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); + char track_path[MAX_PATH] = { 0 }; + subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { window_track_manage_open(); return; } - if (!RCT2_CALLPROC_X(0x0067726A, 0, 0, 0, 0, 0, 0, 0)) { + if (!load_track_design(track_path)) { w->track_list.var_480 = 0xFFFF; window_invalidate(w); return; @@ -201,7 +202,7 @@ static void window_track_list_select(rct_window *w, int index) trackDesign = track_get_info(index, NULL); if (trackDesign == NULL) return; - if (trackDesign->var_06 & 4) + if (trackDesign->track_td6.var_06 & 4) window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1); window_close(w); @@ -211,7 +212,7 @@ static void window_track_list_select(rct_window *w, int index) static int window_track_list_get_list_item_index_from_position(int x, int y) { int index; - uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC; + uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); index = 0; if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) { @@ -237,7 +238,7 @@ static int window_track_list_get_list_item_index_from_position(int x, int y) */ static void window_track_list_close() { - free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, void*)); + free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*)); } /** @@ -281,7 +282,7 @@ static void window_track_list_scrollgetsize() { rct_window *w; int width, height; - uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC; + uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); window_get_register(w); @@ -400,7 +401,7 @@ static void window_track_list_paint() rct_drawpixelinfo *dpi; rct_widget *widget; rct_track_design *trackDesign = NULL; - uint8 *image, *trackDesignList = (uint8*)0x00F441EC; + uint8 *image, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; int trackIndex, x, y, colour, gForces, airTime; @@ -429,6 +430,8 @@ static void window_track_list_paint() if (trackDesign == NULL) return; + rct_track_td6* track_td6 = &trackDesign->track_td6; + subsituteElement = &g1Elements[0]; tmpElement = *subsituteElement; subsituteElement->offset = image; @@ -445,13 +448,13 @@ static void window_track_list_paint() RCT2_GLOBAL(0x00F44153, uint8) = 0; // Warnings - if ((trackDesign->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) { + if ((track_td6->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) { // Vehicle design not available gfx_draw_string_centred_clipped(dpi, STR_VEHICLE_DESIGN_UNAVAILABLE, NULL, 0, x, y, 368); y -= 10; } - if (trackDesign->var_06 & 1) { + if (track_td6->var_06 & 1) { RCT2_GLOBAL(0x00F44153, uint8) = 1; if (RCT2_GLOBAL(0x00F44152, uint8) == 0) { // Scenery not available @@ -468,89 +471,89 @@ static void window_track_list_paint() x = w->x + widget->left + 1; y = w->y + widget->bottom + 2; - if (trackDesign->var_6C & 0x80000000) { + if (track_td6->var_6C & 0x80000000) { // Six flags logo gfx_draw_sprite(dpi, SPR_SIX_FLAGS, w->x + widget->right - 50, y + 4, 0); } // Stats - rating = trackDesign->excitement * 10; + rating = track_td6->excitement * 10; gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y); y += 10; - rating = trackDesign->intensity * 10; + rating = track_td6->intensity * 10; gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y); y += 10; - rating = trackDesign->nausea * 10; + rating = track_td6->nausea * 10; gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, 0, x, y); y += 14; - if (trackDesign->type != RIDE_TYPE_MAZE) { - if (trackDesign->type == RIDE_TYPE_MINI_GOLF) { + if (track_td6->type != RIDE_TYPE_MAZE) { + if (track_td6->type == RIDE_TYPE_MINI_GOLF) { // Holes - holes = trackDesign->holes & 0x1F; + holes = track_td6->holes & 0x1F; gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y); y += 10; } else { // Maximum speed - speed = ((trackDesign->max_speed << 16) * 9) >> 18; + speed = ((track_td6->max_speed << 16) * 9) >> 18; gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y); y += 10; // Average speed - speed = ((trackDesign->average_speed << 16) * 9) >> 18; + speed = ((track_td6->average_speed << 16) * 9) >> 18; gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, 0, x, y); y += 10; } // Ride length RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1345; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->ride_length; + RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->ride_length; gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 214); y += 10; } - if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x80) { + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x80) { // Maximum positive vertical Gs - gForces = trackDesign->max_positive_vertical_g * 32; + gForces = track_td6->max_positive_vertical_g * 32; gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y); y += 10; // Maximum negative verical Gs - gForces = trackDesign->max_negitive_vertical_g * 32; + gForces = track_td6->max_negitive_vertical_g * 32; gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, 0, x, y); y += 10; // Maximum lateral Gs - gForces = trackDesign->max_lateral_g * 32; + gForces = track_td6->max_lateral_g * 32; gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, 0, x, y); y += 10; - if (trackDesign->var_07 / 4 >= 2) { - if (trackDesign->total_air_time != 0) { + if (track_td6->var_07 / 4 >= 2) { + if (track_td6->total_air_time != 0) { // Total air time - airTime = trackDesign->total_air_time * 25; + airTime = track_td6->total_air_time * 25; gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, 0, x, y); y += 10; } } } - if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x400) { + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x400) { // Drops - drops = trackDesign->drops & 0x3F; + drops = track_td6->drops & 0x3F; gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y); y += 10; // Drop height is multiplied by 0.75 - dropHeight = (trackDesign->highest_drop_height + (trackDesign->highest_drop_height / 2)) / 2; + dropHeight = (track_td6->highest_drop_height + (track_td6->highest_drop_height / 2)) / 2; gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, 0, x, y); y += 10; } - if (trackDesign->type != RIDE_TYPE_MINI_GOLF) { - inversions = trackDesign->inversions & 0x1F; + if (track_td6->type != RIDE_TYPE_MINI_GOLF) { + inversions = track_td6->inversions & 0x1F; if (inversions != 0) { // Inversions gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y); @@ -559,16 +562,16 @@ static void window_track_list_paint() } y += 4; - if (trackDesign->space_required_x != 0xFF) { + if (track_td6->space_required_x != 0xFF) { // Space required - RCT2_GLOBAL(0x013CE952 + 0, uint16) = trackDesign->space_required_x; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->space_required_y; + RCT2_GLOBAL(0x013CE952 + 0, uint16) = track_td6->space_required_x; + RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->space_required_y; gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)0x013CE952, 0, x, y); y += 10; } - if (trackDesign->cost != 0) { - gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &trackDesign->cost, 0, x, y); + if (track_td6->cost != 0) { + gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &track_td6->cost, 0, x, y); y += 14; } } @@ -583,7 +586,7 @@ static void window_track_list_scrollpaint() rct_drawpixelinfo *dpi; rct_string_id stringId, stringId2; int i, x, y, colour; - uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC; + uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8); window_paint_get_registers(w, dpi); @@ -615,9 +618,9 @@ static void window_track_list_scrollpaint() stringId2 = STR_BUILD_CUSTOM_DESIGN; gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1); y += 10; + i++; } - i++; while (*trackDesignItem != 0) { if (y + 10 >= dpi->y && y < dpi->y + dpi->height) { if (i == w->track_list.var_482) { diff --git a/src/windows/track_place.c b/src/windows/track_place.c index 6f935f2b48..42bf35cc40 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -171,7 +171,7 @@ static void window_track_place_draw_mini_preview() originY -= ((maxY + minY) >> 6) << 5; } - if (design->type != RIDE_TYPE_MAZE) { + if (design->track_td6.type != RIDE_TYPE_MAZE) { #pragma region Track rotation = RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);