Merge pull request #735 from duncanspumpkin/track_refactor_s

Track Refactor
This commit is contained in:
Ted John 2015-02-02 22:16:21 +00:00
commit 01781bed6c
11 changed files with 709 additions and 125 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
}
}

View File

@ -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
#endif

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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) {

View File

@ -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);