diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 6c3f33f482..328636c259 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -68,6 +68,7 @@
+
@@ -183,6 +184,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index cbb78b897f..6020eafffc 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -332,7 +332,6 @@
-
Source
@@ -344,7 +343,7 @@
Source\World
-
+
Source\World
@@ -423,6 +422,9 @@
Source\Windows
+
+ Source\Ride
+
@@ -614,5 +616,8 @@
Source
+
+ Source\Ride
+
\ No newline at end of file
diff --git a/src/addresses.h b/src/addresses.h
index 32f9e70edd..60fab7f688 100644
--- a/src/addresses.h
+++ b/src/addresses.h
@@ -261,10 +261,22 @@
#define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908
+#define RCT2_ADDRESS_TRACK_PREVIEW_ROTATION 0x00F440AE
+
+#define RCT2_ADDRESS_TRACK_PREVIEW_X_MIN 0x00F440F9
+#define RCT2_ADDRESS_TRACK_PREVIEW_X_MAX 0x00F440FB
+#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN 0x00F440FD
+#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX 0x00F440FF
+#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN 0x00F44101
+#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX 0x00F44103
#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_DESIGN_COST 0x00F4411D
+
+#define RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE 0x00F44152
+
#define RCT2_ADDRESS_TRACK_LIST 0x00F441EC
#define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8
diff --git a/src/interface/viewport.c b/src/interface/viewport.c
index 039f314461..ffbdeb12f5 100644
--- a/src/interface/viewport.c
+++ b/src/interface/viewport.c
@@ -527,8 +527,6 @@ void viewport_update_position(rct_window *window)
//RCT2_CALLPROC_X(0x6E7DE1, x, y, 0, 0, (int)window, (int)viewport, 0);
}
-void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom);
-
/**
*
* rct2: 0x00685C02
diff --git a/src/interface/viewport.h b/src/interface/viewport.h
index 10dc86f7b5..27eae985d7 100644
--- a/src/interface/viewport.h
+++ b/src/interface/viewport.h
@@ -80,6 +80,7 @@ void viewport_create(rct_window *w, int x, int y, int width, int height, int zoo
void viewport_update_pointers();
void viewport_update_position(rct_window *window);
void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, int left, int top, int right, int bottom);
+void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom);
void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation);
diff --git a/src/ride/ride.c b/src/ride/ride.c
index 47fb99c8b5..b00bf4c977 100644
--- a/src/ride/ride.c
+++ b/src/ride/ride.c
@@ -728,7 +728,7 @@ void sub_6C9627()
&x,
&y,
RCT2_GLOBAL(0x00F440AC, uint16),
- RCT2_GLOBAL(0x00F440AE, uint8) & 3,
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) & 3,
RCT2_GLOBAL(0x00F440AF, uint8),
0,
0,
@@ -910,7 +910,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -930,7 +930,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -942,7 +942,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -993,7 +993,7 @@ int sub_6CC3FB(int rideIndex)
RCT2_GLOBAL(0x00F440B6, uint8) = 0;
RCT2_GLOBAL(0x00F440B7, uint8) = 0;
- RCT2_GLOBAL(0x00F440AE, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
RCT2_GLOBAL(0x00F440A6, uint8) = 4;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
diff --git a/src/ride/track.c b/src/ride/track.c
index 44a079cf13..401a4f09b6 100644
--- a/src/ride/track.c
+++ b/src/ride/track.c
@@ -26,6 +26,10 @@
#include "ride.h"
#include "track.h"
#include "../platform/platform.h"
+#include "../game.h"
+#include "../localisation/localisation.h"
+#include "../world/park.h"
+#include "../interface/viewport.h"
/**
*
@@ -466,6 +470,14 @@ rct_track_td6* load_track_design(const char *path)
if (fp == NULL)
return 0;
+ char* track_name_pointer = (char*)path;
+ while (*track_name_pointer++ != '\0');
+ while (*--track_name_pointer != '\\');
+ char* default_name = RCT2_ADDRESS(0x009E3504, char);
+ // Copy the track name for use as the default name of this ride
+ while (*++track_name_pointer != '.')*default_name++ = *track_name_pointer;
+ *default_name++ = '\0';
+
// Read whole file into a buffer
fpLength = fsize(fp);
fpBuffer = malloc(fpLength);
@@ -604,6 +616,372 @@ void reset_track_list_cache(){
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0;
}
+/* rct2: 0x006D1C68 */
+int backup_map(){
+ RCT2_GLOBAL(0xF440ED, uint8*) = malloc(0xED600);
+ if (RCT2_GLOBAL(0xF440ED, uint32) == 0) return 0;
+
+ RCT2_GLOBAL(0xF440F1, uint8*) = malloc(0x40000);
+ if (RCT2_GLOBAL(0xF440F1, uint32) == 0){
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ return 0;
+ }
+
+ RCT2_GLOBAL(0xF440F5, uint8*) = malloc(14);
+ if (RCT2_GLOBAL(0xF440F5, uint32) == 0){
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ free(RCT2_GLOBAL(0xF440F1, uint8*));
+ return 0;
+ }
+
+ uint32* map_elements = RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, uint32);
+ memcpy(RCT2_GLOBAL(0xF440ED, uint32*), map_elements, 0xED600);
+
+ uint32* tile_map_pointers = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32);
+ memcpy(RCT2_GLOBAL(0xF440F1, uint32*), tile_map_pointers, 0x40000);
+
+ uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*);
+ *(uint32*)backup_info = RCT2_GLOBAL(0x0140E9A4, uint32);
+ *(uint16*)(backup_info + 4) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16);
+ *(uint16*)(backup_info + 6) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16);
+ *(uint16*)(backup_info + 8) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) = 0x100;
+ *(uint32*)(backup_info + 10) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
+ return 1;
+}
+
+/* rct2: 0x006D2378 */
+void reload_map_backup(){
+ uint32* map_elements = RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, uint32);
+ memcpy(map_elements, RCT2_GLOBAL(0xF440ED, uint32*), 0xED600);
+
+ uint32* tile_map_pointers = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32);
+ memcpy(tile_map_pointers, RCT2_GLOBAL(0xF440F1, uint32*), 0x40000);
+
+ uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*);
+ RCT2_GLOBAL(0x0140E9A4, uint32) = *(uint32*)backup_info;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = *(uint16*)(backup_info + 4);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16) = *(uint16*)(backup_info + 6);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) = *(uint16*)(backup_info + 8);
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = *(uint32*)(backup_info + 10);
+
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ free(RCT2_GLOBAL(0xF440F1, uint8*));
+ free(RCT2_GLOBAL(0xF440F5, uint8*));
+}
+
+/* rct2: 0x006D1D9A */
+void blank_map(){
+ rct_map_element* map_element;
+ for (int i = 0; i < MAX_TILE_MAP_ELEMENT_POINTERS; i++) {
+ map_element = GET_MAP_ELEMENT(i);
+ map_element->type = MAP_ELEMENT_TYPE_SURFACE;
+ map_element->flags = MAP_ELEMENT_FLAG_LAST_TILE;
+ map_element->base_height = 2;
+ map_element->clearance_height = 0;
+ map_element->properties.surface.slope = 0;
+ map_element->properties.surface.terrain = 0;
+ map_element->properties.surface.grass_length = 1;
+ map_element->properties.surface.ownership = OWNERSHIP_OWNED;
+ }
+ map_update_tile_pointers();
+}
+
+/* rct2: 0x006ABDB0 */
+void load_track_scenery_objects(){
+ uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8);
+ rct_object_entry_extended* object_entry = &object_entry_groups[0].entries[entry_index];
+
+ rct_object_entry* copied_entry = RCT2_ADDRESS(0xF43414, rct_object_entry);
+ memcpy(copied_entry, object_entry, sizeof(rct_object_entry));
+
+ object_unload_all();
+ object_load(-1, copied_entry, 0);
+ uint8 entry_type;
+ find_object_in_entry_group(copied_entry, &entry_type, &entry_index);
+ RCT2_GLOBAL(0xF44157, uint8) = entry_index;
+
+ rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8* track_elements = RCT2_ADDRESS(0x9D821B, uint8);
+
+ if (track_design->type == RIDE_TYPE_MAZE){
+ // Skip all of the maze track elements
+ while (*(uint32*)track_elements != 0)track_elements += 4;
+ track_elements += 4;
+ }
+ else{
+ // Skip track_elements
+ while (*track_elements != 255) track_elements += 2;
+ track_elements++;
+
+ // Skip entrance exit elements
+ while (*track_elements != 255) track_elements += 6;
+ track_elements++;
+ }
+
+ while (*track_elements != 255){
+ if (!find_object_in_entry_group((rct_object_entry*)track_elements, &entry_type, &entry_index)){
+ object_load(-1, (rct_object_entry*)track_elements, 0);
+ }
+ // Skip object and location/direction/colour
+ track_elements += sizeof(rct_object_entry) + 6;
+ }
+
+ sub_6A9FC0();
+}
+
+/**
+* Places a virtual track. This can involve highlighting the surface tiles and showing the track layout. It is also used by
+* the track preview window to place the whole track.
+* Depending on the value of bl it modifies the function.
+* bl == 0, Draw outlines on the ground
+* bl == 3, Returns the z value of a succesful placement
+* bl == 5, Returns cost to create the track. Places the track. (used by the preview)
+* bl == 6, Clear white outlined track.
+* rct2: 0x006D01B3
+*/
+int sub_6D01B3(int bl, int x, int y, int z)
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ eax = x;
+ ebx = bl;
+ ecx = y;
+ edx = z;
+ esi = 0;
+ edi = 0;
+ ebp = 0;
+ RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ return *((short*)&ebx);
+}
+
+/* rct2: 0x006D2189
+ * ebx = ride_id
+ * cost = edi
+ */
+int sub_6D2189(int* cost, uint8* ride_id){
+ RCT2_GLOBAL(0xF44151, uint8) = 0;
+ rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8 entry_type, entry_index;
+
+ if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index))
+ entry_index = 0xFF;
+
+ int eax = 0, ebx, ecx = 0, edx, esi, edi = 0, ebp = 0;
+ ebx = 41;
+ edx = track_design->type | (entry_index << 8);
+ esi = GAME_COMMAND_6;
+
+ if (0x80000000 == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
+
+ // bh
+ *ride_id = edi & 0xFF;
+
+ rct_ride* ride = GET_RIDE(*ride_id);
+
+ uint8* ride_name = RCT2_ADDRESS(0x9E3504, uint8);
+ rct_string_id new_ride_name = user_string_allocate(132, ride_name);
+
+ if (new_ride_name){
+ rct_string_id old_name = ride->name;
+ ride->name = new_ride_name;
+ user_string_free(old_name);
+ }
+
+ uint8 version = track_design->var_07 >> 2;
+
+ if (version == 2){
+ ride->entrance_style = track_design->entrance_style;
+ }
+
+ if (version != 0){
+ memcpy(&ride->track_colour_main, &track_design->track_spine_colour, 4);
+ memcpy(&ride->track_colour_additional, &track_design->track_rail_colour, 4);
+ memcpy(&ride->track_colour_supports, &track_design->track_support_colour, 4);
+ }
+ else{
+ memset(&ride->track_colour_main, track_design->track_spine_colour_rct1, 4);
+ memset(&ride->track_colour_additional, track_design->track_rail_colour_rct1, 4);
+ memset(&ride->track_colour_supports, track_design->track_support_colour_rct1, 4);
+ }
+
+ RCT2_GLOBAL(0x009D8150, uint8) |= 1;
+ uint8 backup_rotation = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8);
+ uint32 backup_park_flags = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32);
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_FORBID_HIGH_CONSTRUCTION;
+ int map_size = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) << 4;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
+ int z = sub_6D01B3(3, map_size, map_size, 16);
+
+ if (RCT2_GLOBAL(0xF4414E, uint8) & 4){
+ RCT2_GLOBAL(0xF44151, uint8) |= 2;
+ }
+ //dx
+ z += 16 - RCT2_GLOBAL(0xF44129, uint16);
+
+ int bl = 5;
+ if (RCT2_GLOBAL(0xF4414E, uint8) & 2){
+ bl |= 0x80;
+ RCT2_GLOBAL(0xF44151, uint8) |= 1;
+ }
+ edi = sub_6D01B3((*ride_id << 8) | bl, map_size, map_size, z);
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = backup_park_flags;
+
+ if (edi != 0x80000000){
+
+ if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index)){
+ RCT2_GLOBAL(0xF44151, uint8) |= 4;
+ }
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = backup_rotation;
+ RCT2_GLOBAL(0x009D8150, uint8) &= ~1;
+ *cost = edi;
+ return 1;
+ }
+ else{
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = backup_rotation;
+ user_string_free(ride->name);
+ ride->type = RIDE_TYPE_NULL;
+ RCT2_GLOBAL(0x009D8150, uint8) &= ~1;
+ return 0;
+ }
+}
+
+/* rct2: 0x006D235B */
+void sub_6D235B(uint8 ride_id){
+ rct_ride* ride = GET_RIDE(ride_id);
+ user_string_free(ride->name);
+ ride->type = RIDE_TYPE_NULL;
+}
+
+/* rct2: 0x006D1EF0 */
+void draw_track_preview(uint8** preview){
+ // Make a copy of the map
+ if (!backup_map())return;
+
+ blank_map();
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER){
+ load_track_scenery_objects();
+ }
+
+ int cost;
+ uint8 ride_id;
+
+ if (!sub_6D2189(&cost, &ride_id)){
+ memset(preview, 0, TRACK_PREVIEW_IMAGE_SIZE * 4);
+ reload_map_backup();
+ return;
+ }
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_COST, money32) = cost;
+
+ rct_viewport* view = RCT2_ADDRESS(0x9D8161, rct_viewport);
+ rct_drawpixelinfo* dpi = RCT2_ADDRESS(0x9D8151, rct_drawpixelinfo);
+ int left, top, right, bottom;
+
+ int center_x = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MAX, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MIN, sint16)) / 2 + 16;
+ int center_y = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN, sint16)) / 2 + 16;
+ int center_z = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX, sint16)) / 2;
+
+ int width = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MAX, sint16) - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MIN, sint16);
+ int height = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX, sint16) - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN, sint16);
+
+ if (width < height)
+ width = height;
+
+ int zoom_level = 1;
+
+ if (width > 1120)
+ zoom_level = 2;
+
+ if (width > 2240)
+ zoom_level = 3;
+
+ width = 370 << zoom_level;
+ height = 217 << zoom_level;
+
+ int x = center_y - center_x - width / 2;
+ int y = (center_y + center_x) / 2 - center_z - height / 2;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 0;
+
+ view->width = 370;
+ view->height = 217;
+ view->view_width = width;
+ view->view_height = height;
+ view->x = 0;
+ view->y = 0;
+ view->view_x = x;
+ view->view_y = y;
+ view->zoom = zoom_level;
+ view->flags = VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_INVISIBLE_SPRITES;
+
+ dpi->zoom_level = zoom_level;
+ dpi->x = 0;
+ dpi->y = 0;
+ dpi->width = 370;
+ dpi->height = 217;
+ dpi->pitch = 0;
+ dpi->bits = (char*)preview;
+
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 1;
+ x = -center_y - center_x - width / 2;
+ y = (center_y - center_x) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 2;
+ x = center_x - center_y - width / 2;
+ y = (-center_y - center_x) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 3;
+ x = center_x + center_y - width / 2;
+ y = (center_x - center_y) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ sub_6D235B(ride_id);
+ reload_map_backup();
+}
+
/**
*
* I don't think preview is a necessary output argument. It can be obtained easily using the track design structure.
@@ -651,15 +1029,16 @@ rct_track_design *track_get_info(int index, uint8** preview)
// Copy the track design apart from the preview image
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);
+ draw_track_preview((uint8**)trackDesign->preview);
+ //RCT2_CALLPROC_X(0x006D1EF0, 0, 0, 0, 0, 0, (int)&trackDesign->preview, 0);
- trackDesign->track_td6.cost = RCT2_GLOBAL(0x00F4411D, money32);
+ trackDesign->track_td6.cost = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_COST, money32);
trackDesign->track_td6.var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7;
}
// Set preview to correct preview image based on rotation
if (preview != NULL)
- *preview = trackDesign->preview[RCT2_GLOBAL(0x00F440AE, uint8)];
+ *preview = trackDesign->preview[RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8)];
return trackDesign;
}
diff --git a/src/ride/track.h b/src/ride/track.h
index 7f62f0547d..2ab8bc6a84 100644
--- a/src/ride/track.h
+++ b/src/ride/track.h
@@ -35,6 +35,49 @@ typedef struct {
uint8 pad[2];
} rct_trackdefinition;
+/**
+* Size: 0x0A
+*/
+typedef struct {
+ uint8 var_00;
+ sint16 x;
+ sint16 y;
+ uint8 pad_05[3];
+ uint8 var_08;
+ uint8 unk_09;
+} rct_preview_track;
+
+/**
+* Size: 0x04
+*/
+typedef struct {
+ union {
+ uint32 all;
+ struct {
+ sint8 x;
+ sint8 y;
+ uint8 unk_2;
+ uint8 type;
+ };
+ };
+} rct_maze_element;
+
+/* Size: 0x02 */
+typedef struct{
+ uint8 type;
+ uint8 flags;
+}rct_track_element;
+
+enum{
+ TRACK_ELEMENT_FLAG_CHAIN_LIFT = (1<<7),
+ TRACK_ELEMENT_FLAG_INVERTED = (1<<6),
+ TRACK_ELEMENT_FLAG_TERMINAL_STATION = (1<<3),
+};
+
+#define TRACK_ELEMENT_FLAG_MAGNITUDE_MASK 0x0F
+#define TRACK_ELEMENT_FLAG_COLOUR_MASK 0x30
+#define TRACK_ELEMENT_FLAG_STATION_NO_MASK 0x02
+
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
/* size: 0x2 */
@@ -54,8 +97,18 @@ typedef struct {
uint8 var_06;
uint8 var_07;
rct_track_vehicle_colour vehicle_colours[32]; // 0x08
- uint8 pad_48[2];
- uint8 total_air_time; // 0x4A
+ union{
+ uint8 pad_48;
+ uint8 track_spine_colour_rct1; // 0x48
+ };
+ union{
+ uint8 entrance_style; // 0x49
+ uint8 track_rail_colour_rct1; // 0x49
+ };
+ union{
+ uint8 total_air_time; // 0x4A
+ uint8 track_support_colour_rct1; // 0x4A
+ };
uint8 pad_4B;
uint8 number_of_trains; // 0x4C
uint8 number_of_cars_per_train; // 0x4D
@@ -158,5 +211,6 @@ rct_track_td6* load_track_design(const char *path);
int track_rename(const char *text);
int track_delete();
void reset_track_list_cache();
+int sub_6D01B3(int bl, int x, int y, int z);
#endif
diff --git a/src/ride/track_data.c b/src/ride/track_data.c
new file mode 100644
index 0000000000..636cb95522
--- /dev/null
+++ b/src/ride/track_data.c
@@ -0,0 +1,280 @@
+/*****************************************************************************
+* Copyright (c) 2014 Ted John
+* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+*
+* This file is part of OpenRCT2.
+*
+* OpenRCT2 is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*****************************************************************************/
+
+#include "track_data.h"
+
+const rct_track_coordinates TrackCoordinates[256] = {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 64, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 64, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 64, -64, -64 },
+ { 0, 1, 0, 64, -64, 64 },
+ { 0, 3, 64, 0, -64, -64 },
+ { 0, 1, 64, 0, -64, 64 },
+ { 0, 0, 0, 0, -64, -32 },
+ { 0, 0, 0, 0, -64, 32 },
+ { 0, 0, 0, 0, -32, -32 },
+ { 0, 0, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 32, -32, -32 },
+ { 0, 1, 0, 32, -32, 32 },
+ { 0, 3, 32, 0, -32, -32 },
+ { 0, 1, 32, 0, -32, 32 },
+ { 0, 3, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 2, 0, 152, -32, 0 },
+ { 0, 2, 0, -152, 32, 0 },
+ { 0, 3, 0, 80, -32, -32 },
+ { 0, 1, 0, 80, -32, 32 },
+ { 0, 3, 0, -80, -32, -32 },
+ { 0, 1, 0, -80, -32, 32 },
+ { 0, 0, 0, 24, 0, 0 },
+ { 0, 0, 0, 24, 0, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 0, 0, 96, 32, 0 },
+ { 0, 0, 0, 32, 32, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 64, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 64, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 0, -64, -32 },
+ { 0, 0, 0, 0, -64, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 2, 0, 16, 0, -96 },
+ { 0, 2, 0, 16, 0, 96 },
+ { 0, 2, 16, 0, 0, -96 },
+ { 0, 2, 16, 0, 0, 96 },
+ { 0, 2, 0, 16, 0, -160 },
+ { 0, 2, 0, 16, 0, 160 },
+ { 0, 2, 16, 0, 0, -160 },
+ { 0, 2, 16, 0, 0, 160 },
+ { 0, 3, 0, 64, 0, 0 },
+ { 0, 1, 0, 64, 0, 0 },
+ { 0, 3, 64, 0, 0, 0 },
+ { 0, 1, 64, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 16, -64, -64 },
+ { 0, 1, 0, 16, -64, 64 },
+ { 0, 3, 16, 0, -64, -64 },
+ { 0, 1, 16, 0, -64, 64 },
+ { 0, 3, 0, 16, -64, -64 },
+ { 0, 1, 0, 16, -64, 64 },
+ { 0, 3, 16, 0, -64, -64 },
+ { 0, 1, 16, 0, -64, 64 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 16, -128, 0 },
+ { 0, 0, 0, 88, -96, 0 },
+ { 0, 0, 0, 88, -96, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 88, 0, -96, 0 },
+ { 0, 0, 88, 0, -96, 0 },
+ { 0, 0, 0, -96, -96, 0 },
+ { 0, 0, 0, 240, -160, 0 },
+ { 0, 0, 0, 80, 32, 0 },
+ { 0, 0, 0, 32, 32, 0 },
+ { 0, 0, 32, 0, 32, 0 },
+ { 0, 0, 0, 56, 32, 0 },
+ { 0, 0, 56, 0, 0, 0 },
+ { 0, 0, 0, 56, 0, 0 },
+ { 0, 0, 56, 0, 32, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 7, 0, 0, -64, -32 },
+ { 0, 4, 0, 0, -64, 32 },
+ { 4, 0, 0, 0, -64, 32 },
+ { 4, 1, 0, 0, -32, 64 },
+ { 0, 7, 0, 0, -64, -32 },
+ { 0, 4, 0, 0, -64, 32 },
+ { 4, 0, 0, 0, -64, 32 },
+ { 4, 1, 0, 0, -32, 64 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 16, -32, 32 },
+ { 4, 4, 0, 64, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 32, -32, 32 },
+ { 4, 4, 0, 32, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 16, 0, -32, 32 },
+ { 4, 4, 64, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 32, 0, -32, 32 },
+ { 4, 4, 32, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 0, 24, -32, 32 },
+ { 4, 4, 0, 24, -32, 32 },
+ { 4, 4, 24, 0, -32, 32 },
+ { 4, 4, 24, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 32, -64, 0 },
+ { 0, 0, 0, 32, -64, 0 },
+ { 0, 0, 0, -32, -64, 0 },
+ { 0, 0, 0, -32, -64, 0 },
+ { 0, 3, 0, 24, -32, -32 },
+ { 0, 1, 0, 24, -32, 32 },
+ { 0, 3, 24, 0, -32, -32 },
+ { 0, 1, 24, 0, -32, 32 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 2, 0, 280, -64, -32 },
+ { 0, 2, 0, 280, -64, 32 },
+ { 0, 2, 0, -280, 64, -32 },
+ { 0, 2, 0, -280, 64, 32 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 2, 0, 120, -32, 0 },
+ { 0, 2, 0, -120, 32, 0 },
+ { 0, 3, 0, 48, -32, -32 },
+ { 0, 1, 0, 48, -32, 32 },
+ { 0, 3, 0, -48, -32, -32 },
+ { 0, 1, 0, -48, -32, 32 },
+ { 0, 2, 0, 32, 0, 0 },
+ { 0, 2, 0, -32, 0, 0 },
+ { 0, 0, 0, 0, -160, 0 },
+ { 0, 0, 0, 0, -160, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 2, 0, -96, -96, 0 },
+ { 0, 2, 0, 128, 64, 0 },
+ { 0, 2, 0, -128, -96, 0 },
+ { 0, 3, 0, 16, -32, -32 },
+ { 0, 1, 0, 16, -32, 32 },
+ { 0, 0, 0, 0, -64, 0 },
+ { 0, 0, 0, 0, -64, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 80, 0, 32, 0 },
+ { 0, 0, 240, 0, -160, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 32, -32, -32 },
+ { 0, 1, 0, 32, -32, 32 },
+ { 0, 3, 32, 0, -32, -32 },
+ { 0, 1, 32, 0, -32, 32 },
+ { 0, 3, 0, 64, -64, -64 },
+ { 0, 1, 0, 64, -64, 64 },
+ { 0, 3, 64, 0, -64, -64 },
+ { 0, 1, 64, 0, -64, 64 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 96, 0, 32 },
+ { 0, 1, 0, 96, 0, -32 },
+ { 0, 3, 96, 0, 0, 32 },
+ { 0, 1, 96, 0, 0, -32 },
+ { 0, 2, 0, 96, 64, 0 },
+ { 0, 2, 0, -128, -96, 0 },
+ { 0, 2, 0, 128, 64, 0 }
+};
\ No newline at end of file
diff --git a/src/ride/track_data.h b/src/ride/track_data.h
new file mode 100644
index 0000000000..c10ad9bd3d
--- /dev/null
+++ b/src/ride/track_data.h
@@ -0,0 +1,33 @@
+/*****************************************************************************
+* Copyright (c) 2014 Ted John
+* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+*
+* This file is part of OpenRCT2.
+*
+* OpenRCT2 is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*****************************************************************************/
+#include "../common.h"
+
+/* size 0x0A */
+typedef struct{
+ sint8 rotation_negative; // 0x00
+ sint8 rotation_positive; // 0x01
+ sint16 z_negative; // 0x02
+ sint16 z_positive; // 0x04
+ sint16 x; // 0x06
+ sint16 y; // 0x08
+}rct_track_coordinates;
+
+// 0x009968BB, 0x009968BC, 0x009968BD, 0x009968BF, 0x009968C1, 0x009968C3
+extern const rct_track_coordinates TrackCoordinates[256];
\ No newline at end of file
diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c
index 22b0c0e5e9..366ab00d24 100644
--- a/src/windows/editor_object_selection.c
+++ b/src/windows/editor_object_selection.c
@@ -111,10 +111,6 @@ 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),
@@ -252,14 +248,14 @@ void sub_6d33e2(){
int entry_index = 0;
for (; ((int)object_entry_groups[0].chunks[entry_index]) == -1; ++entry_index);
- //RCT2_GLOBAL(0xF44157, uint8) = 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;
+ RCT2_GLOBAL(0xF44158, uint8) = ride_type;
ride_list_item item = { ride_type, entry_index };
track_load_list(item);
diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c
index be37ef61c9..aa8eb48f76 100644
--- a/src/windows/ride_construction.c
+++ b/src/windows/ride_construction.c
@@ -189,7 +189,7 @@ rct_window *window_construction_open()
RCT2_GLOBAL(0x00F440B6, uint8) = 0;
RCT2_GLOBAL(0x00F440B7, uint8) = 0;
- RCT2_GLOBAL(0x00F440AE, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
RCT2_GLOBAL(0x00F440A6, uint8) = 4;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -314,11 +314,11 @@ void window_construction_mouseup_demolish(rct_window* w){
if (RCT2_GLOBAL(0xF440A6, uint8) != 2){
//6c9cc4
int eax = RCT2_GLOBAL(0xF440A8, uint16),
- ebx = RCT2_GLOBAL(0xF440AF, uint8) || (RCT2_GLOBAL(0xF440AE, uint8) << 8),
+ ebx = RCT2_GLOBAL(0xF440AF, uint8) || (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) << 8),
ecx = RCT2_GLOBAL(0xF440AA, uint16),
edx = RCT2_GLOBAL(0xF440AC, uint16);
- sub_6C683D(&eax, &ecx, edx, RCT2_GLOBAL(0xF440AE, uint8), RCT2_GLOBAL(0xF440AF, uint8) & 0x3FF, 0, 0, 0);
+ sub_6C683D(&eax, &ecx, edx, RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8), RCT2_GLOBAL(0xF440AF, uint8) & 0x3FF, 0, 0, 0);
}
int ride_id = RCT2_GLOBAL(0xF440A7, uint8);
diff --git a/src/windows/track_list.c b/src/windows/track_list.c
index c29a799dca..26f7ac428a 100644
--- a/src/windows/track_list.c
+++ b/src/windows/track_list.c
@@ -152,9 +152,9 @@ void window_track_list_open(ride_list_item item)
w->track_list.var_480 = 0xFFFF;
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;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 0;
window_push_others_right(w);
- RCT2_GLOBAL(0x00F440AE, uint8) = 2;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 2;
}
/**
@@ -176,7 +176,7 @@ static void window_track_list_select(rct_window *w, int index)
}
if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
- RCT2_GLOBAL(0x00F44152, uint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 1;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER))
index--;
@@ -195,9 +195,6 @@ static void window_track_list_select(rct_window *w, int index)
char track_path[MAX_PATH] = { 0 };
subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
- // Copy the track name for use as the default name of this ride
- window_track_list_format_name((char*)0x009E3504, trackDesignItem, 0, 0);
-
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
window_track_manage_open();
return;
@@ -271,13 +268,13 @@ static void window_track_list_mouseup()
}
break;
case WIDX_ROTATE:
- RCT2_GLOBAL(0x00F440AE, uint8)++;
- RCT2_GLOBAL(0x00F440AE, uint8) %= 4;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8)++;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) %= 4;
window_invalidate(w);
break;
case WIDX_TOGGLE_SCENERY:
- RCT2_GLOBAL(0x00F44152, uint8) ^= 1;
- RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) ^= 1;
+ reset_track_list_cache();
window_invalidate(w);
break;
}
@@ -388,7 +385,7 @@ static void window_track_list_invalidate()
w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
- if (RCT2_GLOBAL(0x00F44152, uint8) == 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0)
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
else
w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
@@ -465,7 +462,7 @@ static void window_track_list_paint()
if (track_td6->var_06 & 1) {
RCT2_GLOBAL(0x00F44153, uint8) = 1;
- if (RCT2_GLOBAL(0x00F44152, uint8) == 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0) {
// Scenery not available
gfx_draw_string_centred_clipped(dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, NULL, 0, x, y, 368);
y -= 10;
diff --git a/src/windows/track_place.c b/src/windows/track_place.c
index 73c40c24d7..785cc66364 100644
--- a/src/windows/track_place.c
+++ b/src/windows/track_place.c
@@ -28,6 +28,7 @@
#include "../localisation/localisation.h"
#include "../sprites.h"
#include "../ride/track.h"
+#include "../ride/track_data.h"
#define TRACK_MINI_PREVIEW_WIDTH 168
#define TRACK_MINI_PREVIEW_HEIGHT 78
@@ -114,33 +115,6 @@ static void window_track_place_clear_mini_preview()
memset(_window_track_place_mini_preview, 220, TRACK_MINI_PREVIEW_SIZE);
}
-/**
- * Size: 0x0A
- */
-typedef struct {
- uint8 var_00;
- sint16 x;
- sint16 y;
- uint8 pad_05[3];
- uint8 var_08;
- uint8 unk_09;
-} rct_preview_track;
-
-/**
- * Size: 0x04
- */
-typedef struct {
- union {
- uint32 all;
- struct {
- sint8 x;
- sint8 y;
- uint8 unk_2;
- uint8 type;
- };
- };
-} rct_preview_maze;
-
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
/**
@@ -149,10 +123,11 @@ typedef struct {
*/
static void window_track_place_draw_mini_preview()
{
- rct_track_design *design = (rct_track_design*)0x009D8178;
- uint8 *pixel, colour, *trackPtr, bits;
+ rct_track_td6 *track = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8 *pixel, colour, bits;
int i, rotation, pass, x, y, pixelX, pixelY, originX, originY, minX, minY, maxX, maxY;
- rct_preview_maze *mazeBlock;
+ rct_maze_element *mazeElement;
+ rct_track_element *trackElement;
rct_preview_track *trackBlock;
window_track_place_clear_mini_preview();
@@ -171,14 +146,14 @@ static void window_track_place_draw_mini_preview()
originY -= ((maxY + minY) >> 6) << 5;
}
- if (design->track_td6.type != RIDE_TYPE_MAZE) {
+ if (track->type != RIDE_TYPE_MAZE) {
#pragma region Track
- rotation = RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
- trackPtr = design->preview[0];
+ rotation = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
+ trackElement = RCT2_ADDRESS(0x009D821B, rct_track_element);
- while (*trackPtr != 255) {
- int trackType = *trackPtr;
+ while (trackElement->type != 255) {
+ int trackType = trackElement->type;
if (trackType == 101)
trackType = 255;
@@ -237,45 +212,47 @@ static void window_track_place_draw_mini_preview()
// Change rotation and next position based on track curvature
rotation &= 3;
+ const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
+
trackType *= 10;
switch (rotation) {
case 0:
- originX += RCT2_GLOBAL(0x009968C1 + trackType, sint16);
- originY += RCT2_GLOBAL(0x009968C3 + trackType, sint16);
+ originX += track_coordinate->x;
+ originY += track_coordinate->y;
break;
case 1:
- originX += RCT2_GLOBAL(0x009968C3 + trackType, sint16);
- originY -= RCT2_GLOBAL(0x009968C1 + trackType, sint16);
+ originX += track_coordinate->y;
+ originY -= track_coordinate->x;
break;
case 2:
- originX -= RCT2_GLOBAL(0x009968C1 + trackType, sint16);
- originY -= RCT2_GLOBAL(0x009968C3 + trackType, sint16);
+ originX -= track_coordinate->x;
+ originY -= track_coordinate->y;
break;
case 3:
- originX -= RCT2_GLOBAL(0x009968C3 + trackType, sint16);
- originY += RCT2_GLOBAL(0x009968C1 + trackType, sint16);
+ originX -= track_coordinate->y;
+ originY += track_coordinate->x;
break;
}
- rotation += RCT2_ADDRESS(0x009968BC, uint8)[trackType] - RCT2_ADDRESS(0x009968BB, uint8)[trackType];
+ rotation += track_coordinate->rotation_positive - track_coordinate->rotation_negative;
rotation &= 3;
- if (RCT2_ADDRESS(0x009968BC, uint8)[trackType] & 4)
+ if (track_coordinate->rotation_positive & 4)
rotation |= 4;
if (!(rotation & 4)) {
originX += RCT2_GLOBAL(0x00993CCC + (rotation * 4), sint16);
originY += RCT2_GLOBAL(0x00993CCE + (rotation * 4), sint16);
}
- trackPtr += 2;
+ trackElement++;
}
#pragma endregion
} else {
#pragma region Maze
- rotation = (RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3;
- mazeBlock = (rct_preview_maze*)design->preview[0];
- while (mazeBlock->all != 0) {
- x = mazeBlock->x * 32;
- y = mazeBlock->y * 32;
+ rotation = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3;
+ mazeElement = RCT2_ADDRESS(0x009D821B, rct_maze_element);
+ while (mazeElement->all != 0) {
+ x = mazeElement->x * 32;
+ y = mazeElement->y * 32;
switch (rotation) {
case 1:
x = -x;
@@ -294,7 +271,7 @@ static void window_track_place_draw_mini_preview()
y += originY;
// Entrance or exit is a lighter colour
- colour = mazeBlock->type == 8 || mazeBlock->type == 128 ? 222 : 218;
+ colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
if (pass == 0) {
minX = min(minX, x);
@@ -315,7 +292,7 @@ static void window_track_place_draw_mini_preview()
}
}
}
- mazeBlock++;
+ mazeElement++;
}
#pragma endregion
@@ -337,24 +314,6 @@ static void sub_68A15E(int x, int y, short *ax, short *bx)
*bx = *((short*)&ebx);
}
-/**
- * Seems to highlight the surface tiles to match the track layout at the given position but also returns some Z value.
- * rct2: 0x006D01B3
- */
-static int sub_6D01B3(int bl, int x, int y, int z)
-{
- int eax, ebx, ecx, edx, esi, edi, ebp;
- eax = x;
- ebx = bl;
- ecx = y;
- edx = z;
- esi = 0;
- edi = 0;
- ebp = 0;
- RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- return *((short*)&ebx);
-}
-
/**
*
* rct2: 0x006D017F
@@ -441,7 +400,7 @@ void window_track_place_open()
show_gridlines();
_window_track_place_last_cost = MONEY32_UNDEFINED;
_window_track_place_last_x = 0xFFFF;
- RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
window_track_place_draw_mini_preview();
}
@@ -476,14 +435,14 @@ static void window_track_place_mouseup()
break;
case WIDX_ROTATE:
window_track_place_clear_provisional();
- RCT2_GLOBAL(0x00F440AE, uint16) = (RCT2_GLOBAL(0x00F440AE, uint16) + 1) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) + 1) & 3;
window_invalidate(w);
_window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview();
break;
case WIDX_MIRROR:
RCT2_CALLPROC_EBPSAFE(0x006D2436);
- RCT2_GLOBAL(0x00F440AE, uint16) = (-RCT2_GLOBAL(0x00F440AE, uint16)) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) = (-RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16)) & 3;
window_invalidate(w);
_window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview();