mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #735 from duncanspumpkin/track_refactor_s
Track Refactor
This commit is contained in:
commit
01781bed6c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
134
src/rct1.h
134
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
|
||||
|
357
src/ride/track.c
357
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue