diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 0cb6c4e330..b480d80723 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -143,6 +143,9 @@
+
+
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index dde58e801f..5f0581eca7 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -168,6 +168,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -401,6 +407,24 @@
Windows
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Windows
+
+
+ Windows
+
+
+ Windows
+
diff --git a/src/rct2.c b/src/rct2.c
index 0af4c93dea..0ffe6585ca 100644
--- a/src/rct2.c
+++ b/src/rct2.c
@@ -161,7 +161,10 @@ void rct2_init()
// RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap
object_list_load();
scenario_load_list();
- track_load_list(253);
+
+ ride_list_item item = { 253, 0 };
+ track_load_list(item);
+
gfx_load_g1();
//RCT2_CALLPROC_EBPSAFE(0x006C19AC); //Load character widths
gfx_load_character_widths();
diff --git a/src/ride.c b/src/ride.c
index da87ccce29..f6bb8eb460 100644
--- a/src/ride.c
+++ b/src/ride.c
@@ -430,10 +430,10 @@ rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *ou
*
* rct2: 0x006B4800
*/
-void ride_construct_new(int list_item)
+void ride_construct_new(ride_list_item listItem)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
- edx = list_item;
+ edx = *((uint16*)&listItem);
eax = 0;
ecx = 0;
ebx = 1;
diff --git a/src/ride.h b/src/ride.h
index 1116903b04..3d323c6a34 100644
--- a/src/ride.h
+++ b/src/ride.h
@@ -39,6 +39,14 @@ typedef struct {
ride_rating nausea;
} rating_tuple;
+/**
+ * Couples a ride type and subtype together.
+ */
+typedef struct {
+ uint8 type;
+ uint8 entry_index;
+} ride_list_item;
+
/**
* Ride type structure.
* size: unknown
@@ -543,7 +551,7 @@ void ride_update_favourited_stat();
void ride_check_all_reachable();
rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY);
rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *outX, int *outY);
-void ride_construct_new(int list_item);
+void ride_construct_new(ride_list_item listItem);
int ride_try_construct(rct_map_element *trackMapElement);
void ride_get_status(int rideIndex, int *formatSecondary, int *argument);
rct_peep *ride_get_assigned_mechanic(rct_ride *ride);
diff --git a/src/scenario.c b/src/scenario.c
index 4851a038d6..8e58d09e78 100644
--- a/src/scenario.c
+++ b/src/scenario.c
@@ -183,7 +183,7 @@ void scenario_load_and_play(const rct_scenario_basic *scenario)
srand0 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32) ^ timeGetTime();
srand1 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) ^ timeGetTime();
- RCT2_CALLPROC_EBPSAFE(0x006CBCC3);
+ window_close_construction_windows();
subsitute_path(
RCT2_ADDRESS(0x0141EF68, char),
diff --git a/src/string_ids.h b/src/string_ids.h
index 9cf960b8f6..4d22b3eb56 100644
--- a/src/string_ids.h
+++ b/src/string_ids.h
@@ -471,6 +471,10 @@ enum {
STR_MEASUREMENTS_AND_TEST_DATA_TIP = 1398,
STR_GRAPHS_TIP = 1399,
+ STR_ROTATE_90_TIP = 1404,
+ STR_MIRROR_IMAGE_TIP = 1405,
+ STR_TOGGLE_SCENERY_TIP = 1406,
+
STR_BUILD_THIS = 1407,
STR_COST_LABEL = 1408,
@@ -823,6 +827,17 @@ enum {
STR_CHANGE_BASE_LAND_TIP = 2294,
STR_CHANGE_VERTICAL_LAND_TIP = 2295,
+ STR_SELECT_DESIGN = 2307,
+ STR_TRACK_DESIGNS = 2308,
+ STR_BUILD_CUSTOM_DESIGN = 2310,
+
+ STR_TRACK_LIST_EXCITEMENT_RATING = 2311,
+ STR_TRACK_LIST_INTENSITY_RATING = 2312,
+ STR_TRACK_LIST_NAUSEA_RATING = 2313,
+ STR_TRACK_LIST_RIDE_LENGTH = 2314,
+ STR_TRACK_LIST_COST_AROUND = 2315,
+ STR_TRACK_LIST_SPACE_REQUIRED = 2316,
+
STR_SOUND_QUALITY = 2317,
STR_SOUND_LOW = 2318,
STR_SOUND_MEDIUM = 2319,
@@ -1160,6 +1175,9 @@ enum {
STR_OPEN_RIDE = 3109,
STR_BLOCK_SECTIONS = 3110,
+ STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP = 3111,
+ STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT = 3112,
+
STR_SAVE_TRACK_DESIGN = 3115,
STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE = 3116,
@@ -1177,6 +1195,9 @@ enum {
STR_DESIGN_CANCEL = 3131,
STR_CLICK_ITEMS_OF_SCENERY_TO_SELECT = 3132,
+ STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE = 3134,
+ STR_VEHICLE_DESIGN_UNAVAILABLE = 3135,
+ STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE = 3136,
STR_SELECT_NEARBY_SCENERY = 3137,
STR_RESET_SELECTION = 3138,
@@ -1226,6 +1247,10 @@ enum {
STR_ROLLER_COASTER_DESIGNER = 3344,
STR_TRACK_DESIGNS_MANAGER = 3345,
+ STR_NO_TRACK_DESIGNS_OF_THIS_TYPE = 3359,
+ STR_WARNING = 3360,
+ STR_TOO_MANY_TRACK_DESIGNS_OF_THIS_TYPE = 3361,
+
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING = 3362,
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING_TIP = 3363,
diff --git a/src/track.c b/src/track.c
index 62b3adb912..341528d545 100644
--- a/src/track.c
+++ b/src/track.c
@@ -18,7 +18,11 @@
* along with this program. If not, see .
*****************************************************************************/
+#include
+#include
#include "addresses.h"
+#include "ride.h"
+#include "osinterface.h"
#include "track.h"
/**
@@ -220,7 +224,207 @@ const rct_trackdefinition gTrackDefinitions[] = {
*
* rct2: 0x006CED50
*/
-void track_load_list(int edx)
+void track_load_list(ride_list_item item)
{
- RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, edx, 0, 0, 0);
+ RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0);
}
+
+/**
+ *
+ * rct2: 0x00676EBA
+ */
+static uint8 sub_676EBA()
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ RCT2_CALLFUNC_X(0x00676EBA, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ return eax & 0xFF;
+}
+
+/**
+ *
+ * rct2: 0x00676EAF
+ */
+static void sub_676EAF(uint8 *esi, int ecx)
+{
+ do {
+ *esi++ = sub_676EBA();
+ } while (--ecx != 0);
+}
+
+/**
+ *
+ * rct2: 0x0067726A
+ * path: 0x0141EF68
+ */
+int sub_67726A(const char *path)
+{
+ HANDLE *hFile;
+ const char *ch;
+ char trackFilename[MAX_PATH], *dst;
+ int i;
+ uint8* edi;
+
+ RCT2_GLOBAL(0x009AAC54, uint8) = 1;
+
+ // Get filename
+ ch = strrchr(path, '\\');
+ ch = ch == NULL ? path : ch + 1;
+ dst = trackFilename;
+ while (*ch != 0 && *ch != '.') {
+ *dst++ = *ch++;
+ }
+ *dst = 0;
+
+ hFile = osinterface_file_open(path);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return 0;
+
+ RCT2_GLOBAL(0x009E382C, HANDLE) = hFile;
+ if (!RCT2_CALLPROC_X(0x006770C1, 0, 0, 0, 0, 0, 0, 0)) {
+ CloseHandle(hFile);
+ return 0;
+ }
+
+ RCT2_CALLPROC_EBPSAFE(0x00676E7A);
+ memset((void*)0x009D81D8, 0, 67);
+ sub_676EAF((void*)0x009D8178, 32);
+
+ uint8 al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
+ if (al >= 2)
+ sub_676EAF((void*)0x009D8198, 40);
+
+ sub_676EAF((void*)0x009D81C0, 24);
+ al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
+ if (al != 0)
+ sub_676EAF((void*)0x009D81D8, al == 1 ? 140 : 67);
+
+ sub_676EAF((void*)0x009D821B, 24572);
+ al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
+ if (al < 2) {
+ if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
+ edi = (uint8*)0x009D821B;
+ while (*edi != 0) {
+ edi += 4;
+ }
+ edi += 4;
+ memset(edi, 255, (uint8*)0x009DE217 - edi);
+ } else {
+ edi = (uint8*)0x009D821B;
+ while (*edi != 255) {
+ edi += 2;
+ }
+ edi++;
+ memset(edi, 255, (uint8*)0x009DE217 - edi);
+ }
+ }
+
+ CloseHandle(hFile);
+
+ al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
+ if (al > 2)
+ return 0;
+
+ if (al <= 1) {
+ edi = (uint8*)0x009D8180;
+ for (i = 0; i < 67; i++)
+ *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
+
+ edi = (uint8*)0x009D81D8;
+ for (i = 0; i < 12; i++)
+ *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
+
+ RCT2_GLOBAL(0x009D81D2, uint8) >>= 1;
+ if (!RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0))
+ RCT2_GLOBAL(0x009D8178, uint8) = 255;
+
+ if (RCT2_GLOBAL(0x009D8178, uint8) == 4)
+ RCT2_GLOBAL(0x009D8178, uint8) = 255;
+
+ if (RCT2_GLOBAL(0x009D8178, uint8) == 0)
+ RCT2_GLOBAL(0x009D8178, uint8) = 52;
+
+ if (RCT2_GLOBAL(0x009D8178, uint8) == 19) {
+ if (RCT2_GLOBAL(0x009D817E, uint8) == 3)
+ RCT2_GLOBAL(0x009D817E, uint8) = 35;
+ if (RCT2_GLOBAL(0x009D8179, uint8) == 79) {
+ if (RCT2_GLOBAL(0x009D817E, uint8) == 2)
+ RCT2_GLOBAL(0x009D817E, uint8) = 1;
+ }
+ }
+
+ int unk1 = RCT2_GLOBAL(0x009D8179, uint8);
+ if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
+ unk1 = 0x0097F66C;
+ } else {
+ if (unk1 == 3 && RCT2_GLOBAL(0x009D8178, uint8) == 3)
+ unk1 = 80;
+ unk1 = 0x0097F0DC + (unk1 * 16);
+ }
+
+ memcpy((void*)0x009D81E8, (void*)unk1, 16);
+ for (i = 0; i < 32; i++)
+ RCT2_ADDRESS(0x009D81FA, uint8)[i] = RCT2_ADDRESS(0x009D8181, uint8)[i * 2];
+
+ RCT2_GLOBAL(0x009D81F8, uint8) = 255;
+ RCT2_GLOBAL(0x009D81F9, uint8) = 255;
+ RCT2_GLOBAL(0x009D821A, uint8) = 5;
+ }
+
+ RCT2_GLOBAL(0x009D81C8, uint8) = min(
+ RCT2_GLOBAL(0x009D81C8, uint8),
+ RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (RCT2_GLOBAL(0x009D8178, uint8) * 8), uint8)
+ );
+
+ return 1;
+}
+
+/**
+ *
+ * I don't think preview is a necessary output argument. It can be obtained easily using the track design structure.
+ * rct2: 0x006D1DEC
+ */
+rct_track_design *track_get_info(int index, uint8** preview)
+{
+ rct_track_design *trackDesign;
+ uint8 *trackDesignList = (uint8*)0x00F441EC;
+ int i;
+
+ trackDesign = NULL;
+
+ // Check if track design has already been loaded
+ for (i = 0; i < 4; i++) {
+ if (index == RCT2_ADDRESS(0x00F44109, uint32)[i]) {
+ trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
+ break;
+ }
+ }
+
+ if (trackDesign == NULL) {
+ // Load track design
+ i = RCT2_GLOBAL(0x00F44119, uint32);
+ RCT2_GLOBAL(0x00F44119, uint32)++;
+ if (RCT2_GLOBAL(0x00F44119, uint32) >= 4)
+ RCT2_GLOBAL(0x00F44119, uint32) = 0;
+
+ RCT2_ADDRESS(0x00F44109, uint32)[i] = index;
+ subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128));
+ if (!sub_67726A((char*)0x0141EF68)) {
+ if (preview != NULL) *preview = NULL;
+ return NULL;
+ }
+
+ trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
+
+ memcpy(trackDesign, (void*)0x009D8178, 163);
+ RCT2_CALLPROC_EBPSAFE(0x006D1EF0);
+
+ trackDesign->cost = RCT2_GLOBAL(0x00F4411D, money32);
+ trackDesign->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)];
+
+ return trackDesign;
+}
\ No newline at end of file
diff --git a/src/track.h b/src/track.h
index 40f496e1f7..4c4fa6c203 100644
--- a/src/track.h
+++ b/src/track.h
@@ -33,6 +33,45 @@ typedef struct {
uint8 pad[2];
} rct_trackdefinition;
+#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
+
+/**
+ * Track design structure.
+ * size: 0x4E72B
+ */
+typedef struct {
+ uint8 type; // 0x00
+ uint8 pad_01;
+ money32 cost; // 0x02
+ uint8 var_06;
+ uint8 var_07;
+ uint8 pad_08[0x42];
+ uint8 total_air_time; // 0x4A
+ uint8 pad_4B[0x06];
+ uint8 max_speed; // 0x51
+ uint8 average_speed; // 0x52
+ uint16 ride_length; // 0x53
+ uint8 max_positive_vertical_g; // 0x55
+ uint8 max_negitive_vertical_g; // 0x56
+ uint8 max_lateral_g; // 0x57
+ union {
+ uint8 inversions; // 0x58
+ uint8 holes; // 0x58
+ };
+ uint8 drops; // 0x59
+ uint8 highest_drop_height; // 0x5A
+ uint8 excitement; // 0x5B
+ uint8 intensity; // 0x5C
+ uint8 nausea; // 0x5D
+ uint8 pad_5E[0x0E];
+ uint32 var_6C;
+ uint8 pad_70[0x10];
+ uint8 space_required_x; // 0x80
+ uint8 space_required_y; // 0x81
+ uint8 pad_82[0x21];
+ uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3
+} rct_track_design;
+
enum {
TRACK_NONE = 0,
@@ -90,6 +129,8 @@ enum {
TRACK_CORKSCREW_DOWN = 224
};
-void track_load_list(int edx);
+void track_load_list(ride_list_item item);
+int sub_67726A(const char *path);
+rct_track_design *track_get_info(int index, uint8** preview);
#endif
\ No newline at end of file
diff --git a/src/window.c b/src/window.c
index 41553254cc..f7afea7c85 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1688,3 +1688,14 @@ void window_align_tabs(rct_window *w, uint8 start_tab_id, uint8 end_tab_id)
}
}
+/**
+ *
+ * rct2: 0x006CBCC3
+ */
+void window_close_construction_windows()
+{
+ window_close_by_id(WC_RIDE_CONSTRUCTION, 0);
+ window_close_by_id(WC_FOOTPATH, 0);
+ window_close_by_id(WC_TRACK_DESIGN_LIST, 0);
+ window_close_by_id(WC_TRACK_DESIGN_PLACE, 0);
+}
\ No newline at end of file
diff --git a/src/window.h b/src/window.h
index cc07d23122..8f74ccef9b 100644
--- a/src/window.h
+++ b/src/window.h
@@ -25,6 +25,7 @@
#include "park.h"
#include "peep.h"
#include "rct2.h"
+#include "ride.h"
struct rct_window;
union rct_window_event;
@@ -168,6 +169,12 @@ typedef struct {
sint16 hover_counter;
} scenery_variables;
+typedef struct {
+ uint16 var_480;
+ uint16 var_482;
+ uint16 var_484;
+} track_list_variables;
+
/**
* Window structure
* size: 0x4C0
@@ -206,6 +213,7 @@ typedef struct rct_window {
map_variables map;
ride_variables ride;
scenery_variables scenery;
+ track_list_variables track_list;
};
sint16 page; // 0x48A
sint16 var_48C;
@@ -361,6 +369,7 @@ enum {
WC_RECENT_NEWS = 31,
WC_SCENARIO_SELECT = 32,
WC_TRACK_DESIGN_LIST = 33,
+ WC_TRACK_DESIGN_PLACE = 34,
WC_NEW_CAMPAIGN = 35,
WC_KEYBOARD_SHORTCUT_LIST = 36,
WC_CHANGE_KEYBOARD_SHORTCUT = 37,
@@ -371,6 +380,8 @@ enum {
WC_EDITOR_INVENTION_LIST = 43,
WC_EDITOR_SCENARIO_OPTIONS = 45,
WC_EDTIOR_OBJECTIVE_OPTIONS = 46,
+ WC_47,
+ WC_48,
WC_CLEAR_SCENERY = 50,
WC_MANAGE_TRACK_DESIGN = 89,
WC_CHEATS = 110,
@@ -433,6 +444,8 @@ void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth,
int tool_set(rct_window *w, int widgetIndex, int tool);
void tool_cancel();
+void window_close_construction_windows();
+
// Open window functions
void window_main_open();
void window_resize_gui(int width, int height);
@@ -447,6 +460,7 @@ void window_title_exit_open();
void window_title_logo_open();
void window_news_open();
void window_scenarioselect_open();
+void window_track_list_open(ride_list_item item);
void window_clear_scenery_open();
void window_land_open();
void window_water_open();
@@ -466,6 +480,7 @@ void window_finances_research_open();
void window_new_campaign_open(sint16 campaignType);
void window_ride_main_open(int rideIndex);
void window_ride_list_open();
+void window_track_place_open();
void window_new_ride_open();
void window_banner_open();
void window_cheats_open();
@@ -473,6 +488,7 @@ void window_research_open();
void window_scenery_open();
void window_music_credits_open();
void window_publisher_credits_open();
+void window_track_manage_open();
void window_guest_list_init_vars_a();
void window_guest_list_init_vars_b();
diff --git a/src/window_new_ride.c b/src/window_new_ride.c
index 6985a4878f..c920c6e004 100644
--- a/src/window_new_ride.c
+++ b/src/window_new_ride.c
@@ -32,11 +32,6 @@
#define _window_new_ride_current_tab RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB, uint8)
-typedef struct {
- uint8 type;
- uint8 entry_index;
-} ride_list_item;
-
#pragma region Ride type view order
/**
@@ -874,7 +869,7 @@ static ride_list_item window_new_ride_scroll_get_ride_list_item_at(rct_window *w
static int get_num_track_designs(ride_list_item item)
{
- track_load_list(*((uint16*)&item));
+ track_load_list(item);
uint8 *trackDesignList = (uint8*)0x00F441EC;
int count = 0;
@@ -964,17 +959,14 @@ static void window_new_ride_select(rct_window *w)
uint32 rideTypeFlags = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (item.type * 8), uint32);
if (rideTypeFlags & 0x10000000) {
- track_load_list(*((sint16*)&item));
+ track_load_list(item);
uint8 *trackDesignList = (uint8*)0x00F441EC;
if (*trackDesignList != 0) {
- // Show track design list
- RCT2_CALLPROC_X(0x006CF1A2, *((sint16*)&item), 0, 0, 0, 0, 0, 0);
+ window_track_list_open(item);
return;
}
}
- // Show ride construction window
- //RCT2_CALLPROC_X(0x006B4800, *((sint16*)&item), 0, 0, 0, 0, 0, 0);
- ride_construct_new(*((sint16*)&item));
+ ride_construct_new(item);
}
diff --git a/src/window_track_list.c b/src/window_track_list.c
new file mode 100644
index 0000000000..fb08c63d53
--- /dev/null
+++ b/src/window_track_list.c
@@ -0,0 +1,649 @@
+/*****************************************************************************
+ * 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
+#include "addresses.h"
+#include "audio.h"
+#include "editor.h"
+#include "ride.h"
+#include "sprites.h"
+#include "string_ids.h"
+#include "track.h"
+#include "widget.h"
+#include "window.h"
+#include "window_error.h"
+
+enum {
+ WIDX_BACKGROUND,
+ WIDX_TITLE,
+ WIDX_CLOSE,
+ WIDX_TRACK_LIST,
+ WIDX_TRACK_PREVIEW,
+ WIDX_ROTATE,
+ WIDX_TOGGLE_SCENERY
+};
+
+static rct_widget window_track_list_widgets[] = {
+ { WWT_FRAME, 0, 0, 599, 0, 399, 0xFFFFFFFF, STR_NONE },
+ { WWT_CAPTION, 0, 1, 598, 1, 14, STR_SELECT_DESIGN, STR_WINDOW_TITLE_TIP },
+ { WWT_CLOSEBOX, 0, 587, 597, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
+ { WWT_SCROLL, 0, 4, 221, 18, 395, 2, STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP },
+ { WWT_FLATBTN, 0, 224, 595, 18, 236, 0xFFFFFFFF, STR_NONE },
+ { WWT_FLATBTN, 0, 574, 597, 374, 397, 5169, STR_ROTATE_90_TIP },
+ { WWT_FLATBTN, 0, 574, 597, 350, 373, 5171, STR_TOGGLE_SCENERY_TIP },
+ { WIDGETS_END },
+};
+
+static void window_track_list_emptysub() { }
+static void window_track_list_close();
+static void window_track_list_mouseup();
+static void window_track_list_scrollgetsize();
+static void window_track_list_scrollmousedown();
+static void window_track_list_scrollmouseover();
+static void window_track_list_tooltip();
+static void window_track_list_invalidate();
+static void window_track_list_paint();
+static void window_track_list_scrollpaint();
+
+static void* window_track_list_events[] = {
+ (uint32*)window_track_list_close,
+ (uint32*)window_track_list_mouseup,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_scrollgetsize,
+ (uint32*)window_track_list_scrollmousedown,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_scrollmouseover,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_tooltip,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_emptysub,
+ (uint32*)window_track_list_invalidate,
+ (uint32*)window_track_list_paint,
+ (uint32*)window_track_list_scrollpaint
+};
+
+static ride_list_item _window_track_list_item;
+
+void window_track_list_format_name(char *dst, const char *src, char colour)
+{
+ if (colour != 0)
+ *dst++ = colour;
+ *dst++ = FORMAT_OPENQUOTES;
+ while (*src != '.' && *src != 0) {
+ *dst++ = *src++;
+ }
+ *dst++ = FORMAT_ENDQUOTES;
+ *dst = 0;
+}
+
+/**
+ *
+ * rct2: 0x006CF1A2
+ */
+void window_track_list_open(ride_list_item item)
+{
+ rct_window *w;
+ int x, y;
+ void *mem;
+
+ window_close_construction_windows();
+ _window_track_list_item = item;
+
+ if (RCT2_GLOBAL(0x00F635ED, uint8) & 1)
+ window_error_open(STR_WARNING, STR_TOO_MANY_TRACK_DESIGNS_OF_THIS_TYPE);
+
+ mem = malloc(1285292);
+ if (mem == NULL)
+ return;
+
+ RCT2_GLOBAL(0x00F44105, void*) = mem;
+ RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300;
+ y = max(28, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) / 2 - 200);
+ } else {
+ x = 0;
+ y = 29;
+ }
+ w = window_create(0, 29, 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);
+ w->colours[0] = 26;
+ 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_484 = 0;
+ RCT2_GLOBAL(0x00F44152, uint8) = 0;
+ window_push_others_right(w);
+ RCT2_GLOBAL(0x00F440AE, uint8) = 2;
+}
+
+/**
+ *
+ * rct2: 0x006CFB82
+ */
+static void window_track_list_select(rct_window *w, int index)
+{
+ uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+ rct_track_design *trackDesign;
+
+ w->track_list.var_480 = index;
+
+ sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8) && index == 0) {
+ window_close(w);
+ ride_construct_new(_window_track_list_item);
+ return;
+ }
+
+ if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
+ RCT2_GLOBAL(0x00F44152, uint8) = 1;
+
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8))
+ index--;
+
+ trackDesignItem = trackDesignList + (index * 128);;
+ RCT2_GLOBAL(0x00F4403C, uint8*) = trackDesignItem;
+
+ window_track_list_format_name(
+ (char*)0x009BC313,
+ trackDesignItem,
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8 ?
+ 0 :
+ FORMAT_WHITE
+ );
+
+ subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8) {
+ window_track_manage_open();
+ return;
+ }
+
+ if (!RCT2_CALLPROC_X(0x0067726A, 0, 0, 0, 0, 0, 0, 0)) {
+ w->track_list.var_480 = 0xFFFF;
+ window_invalidate(w);
+ return;
+ }
+
+ trackDesign = track_get_info(index, NULL);
+ if (trackDesign->var_06 & 4)
+ window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1);
+
+ window_close(w);
+ window_track_place_open();
+}
+
+static int window_track_list_get_list_item_index_from_position(int x, int y)
+{
+ int index;
+ uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+
+ index = 0;
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8)) {
+ y -= 10;
+ if (y < 0)
+ return index;
+ index++;
+ }
+
+ for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128) {
+ y -= 10;
+ if (y < 0)
+ return index;
+ index++;
+ }
+
+ return -1;
+}
+
+/**
+ *
+ * rct2: 0x006CFD76
+ */
+static void window_track_list_close()
+{
+ free(RCT2_GLOBAL(0x00F44105, void*));
+}
+
+/**
+ *
+ * rct2: 0x006CFA31
+ */
+static void window_track_list_mouseup()
+{
+ rct_window *w;
+ short widgetIndex;
+
+ window_widget_get_registers(w, widgetIndex);
+
+ switch (widgetIndex) {
+ case WIDX_CLOSE:
+ window_close(w);
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ window_close_by_id(WC_47, w->number);
+ window_close_by_id(WC_48, w->number);
+ trackmanager_load();
+ }
+ break;
+ case WIDX_ROTATE:
+ RCT2_GLOBAL(0x00F440AE, uint8)++;
+ RCT2_GLOBAL(0x00F440AE, uint8) %= 4;
+ window_invalidate(w);
+ break;
+ case WIDX_TOGGLE_SCENERY:
+ RCT2_GLOBAL(0x00F44152, uint8) ^= 1;
+ RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
+ window_invalidate(w);
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006CFAB0
+ */
+static void window_track_list_scrollgetsize()
+{
+ rct_window *w;
+ int height;
+ uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+
+ window_get_register(w);
+
+ height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8 ? 0 : 10;
+ for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128)
+ height += 10;
+
+ #ifdef _MSC_VER
+ __asm mov ecx, 0
+ #else
+ __asm__ ( "mov ecx, 0 " );
+ #endif
+
+ #ifdef _MSC_VER
+ __asm mov edx, height
+ #else
+ __asm__ ( "mov edx, %[height] " : [height] "+m" (height) );
+ #endif
+}
+
+/**
+ *
+ * rct2: 0x006CFB39
+ */
+static void window_track_list_scrollmousedown()
+{
+ rct_window *w;
+ short i, x, y;
+
+ window_scrollmouse_get_registers(w, x, y);
+
+ if (w->track_list.var_484 & 1)
+ return;
+ if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ return;
+
+ i = window_track_list_get_list_item_index_from_position(x, y);
+ if (i != -1)
+ window_track_list_select(w, i);
+}
+
+/**
+ *
+ * rct2: 0x006CFAD7
+ */
+static void window_track_list_scrollmouseover()
+{
+ rct_window *w;
+ short i, x, y;
+
+ window_scrollmouse_get_registers(w, x, y);
+
+ if (w->track_list.var_484 & 1)
+ return;
+ if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ return;
+
+ i = window_track_list_get_list_item_index_from_position(x, y);
+ if (i != -1 && w->track_list.var_482 != i) {
+ w->track_list.var_482 = i;
+ window_invalidate(w);
+ }
+}
+
+/**
+ *
+ * rct2: 0x006CFD6C
+ */
+static void window_track_list_tooltip()
+{
+ RCT2_GLOBAL(0x013CE952, uint16) = STR_LIST;
+}
+
+/**
+ *
+ * rct2: 0x006CF2D6
+ */
+static void window_track_list_invalidate()
+{
+ rct_window *w;
+ rct_ride_type *entry;
+ rct_string_id stringId;
+
+ window_get_register(w);
+
+ entry = GET_RIDE_ENTRY(_window_track_list_item.entry_index);
+
+ stringId = entry->name;
+ if (!(entry->var_008 & 0x1000))
+ stringId = _window_track_list_item.type + 2;
+
+ RCT2_GLOBAL(0x013CE952, uint16) = stringId;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ window_track_list_widgets[WIDX_TITLE].image = STR_TRACK_DESIGNS;
+ window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT;
+ } else {
+ window_track_list_widgets[WIDX_TITLE].image = STR_SELECT_DESIGN;
+ window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP;
+ }
+
+ if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) || w->track_list.var_482 != 0) {
+ w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
+ 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)
+ w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
+ else
+ w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
+ } else {
+ w->pressed_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
+ w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
+ window_track_list_widgets[WIDX_ROTATE].type = WWT_EMPTY;
+ window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_EMPTY;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006CF387
+ */
+static void window_track_list_paint()
+{
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+ rct_widget *widget;
+ rct_track_design *trackDesign;
+ uint8 *image, *trackDesignList = (uint8*)0x00F441EC;
+ uint16 holes, speed, drops, dropHeight, inversions;
+ fixed32_2dp rating;
+ int trackIndex, x, y, colour, gForces, airTime;
+ rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element);
+
+ window_paint_get_registers(w, dpi);
+
+ window_draw_widgets(w, dpi);
+
+ trackIndex = w->track_list.var_482;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ if (*trackDesignList == 0 || trackIndex == -1)
+ return;
+ } else if (trackIndex-- == 0) {
+ return;
+ }
+
+ // Track preview
+ widget = &window_track_list_widgets[WIDX_TRACK_PREVIEW];
+ x = w->x + widget->left + 1;
+ y = w->y + widget->top + 1;
+ colour = RCT2_GLOBAL(0x0141FC44 + (w->colours[0] * 8), uint8);
+ gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
+
+ trackDesign = track_get_info(trackIndex, &image);
+ if (trackDesign == NULL)
+ return;
+
+ subsituteElement = &g1Elements[0];
+ tmpElement = *subsituteElement;
+ subsituteElement->offset = image;
+ subsituteElement->width = 370;
+ subsituteElement->height = 217;
+ subsituteElement->x_offset = 0;
+ subsituteElement->y_offset = 0;
+ subsituteElement->flags = G1_FLAG_BMP;
+ gfx_draw_sprite(dpi, 0, x, y, 0);
+ *subsituteElement = tmpElement;
+
+ x = w->x + (widget->left + widget->right) / 2;
+ y = w->y + widget->bottom - 12;
+
+ // Warnings
+ if ((trackDesign->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
+ // Vehicle design not available
+ RCT2_GLOBAL(0x00F44153, uint8) = 0;
+ gfx_draw_string_centred_clipped(dpi, STR_VEHICLE_DESIGN_UNAVAILABLE, NULL, 0, x, y, 368);
+ y -= 10;
+ }
+
+ if (trackDesign->var_06 & 1) {
+ RCT2_GLOBAL(0x00F44153, uint8) = 1;
+ if (RCT2_GLOBAL(0x00F44152, 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;
+ }
+ }
+
+ // Track design name
+ window_track_list_format_name((char*)0x009BC677, trackDesignList + (trackIndex * 128), FORMAT_WINDOW_COLOUR_1);
+ gfx_draw_string_centred_clipped(dpi, 3165, NULL, 0, x, y, 368);
+
+ // Information
+ x = w->x + widget->left + 1;
+ y = w->y + widget->bottom + 2;
+
+ if (trackDesign->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;
+ gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y);
+ y += 10;
+
+ rating = trackDesign->intensity * 10;
+ gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y);
+ y += 10;
+
+ rating = trackDesign->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) {
+ // Holes
+ holes = trackDesign->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;
+ gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y);
+ y += 10;
+
+ // Average speed
+ speed = ((trackDesign->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;
+ 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) {
+ // Maximum positive vertical Gs
+ gForces = trackDesign->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;
+ 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;
+ 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) {
+ // Total air time
+ airTime = trackDesign->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) {
+ // Drops
+ drops = trackDesign->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;
+ 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 (inversions != 0) {
+ // Inversions
+ gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y);
+ y += 10;
+ }
+ }
+ y += 4;
+
+ if (trackDesign->space_required_x != 0xFF) {
+ // Space required
+ RCT2_GLOBAL(0x013CE952 + 0, uint16) = trackDesign->space_required_x;
+ RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->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);
+ y += 14;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006CF8CD
+ */
+static void window_track_list_scrollpaint()
+{
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+ rct_string_id stringId, stringId2;
+ int i, x, y, colour;
+ uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+
+ window_paint_get_registers(w, dpi);
+
+ colour = RCT2_GLOBAL(0x00141FC48 + (w->colours[0] * 8), uint8);
+ colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
+ gfx_clear(dpi, colour);
+
+ i = 0;
+ x = 0;
+ y = 0;
+
+ trackDesignItem = trackDesignList;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ if (*trackDesignItem == 0) {
+ // No track designs
+ gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, NULL, 0, x, y - 1);
+ return;
+ }
+ } else {
+ // Build custom track item
+ if (i == w->track_list.var_482) {
+ // Highlight
+ gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
+ stringId = 1193;
+ } else {
+ stringId = 1191;
+ }
+
+ stringId2 = STR_BUILD_CUSTOM_DESIGN;
+ gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
+ y += 10;
+ }
+
+ i++;
+ while (*trackDesignItem != 0) {
+ if (y + 10 >= dpi->y && y < dpi->y + dpi->height) {
+ if (i == w->track_list.var_482) {
+ // Highlight
+ gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
+ stringId = 1193;
+ } else {
+ stringId = 1191;
+ }
+
+ // Draw track name
+ window_track_list_format_name((char*)0x009BC678, trackDesignItem, 0);
+ stringId2 = 3165;
+ gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
+ }
+ y += 10;
+ i++;
+ trackDesignItem += 128;
+ }
+}
\ No newline at end of file
diff --git a/src/window_track_manage.c b/src/window_track_manage.c
new file mode 100644
index 0000000000..7741bdfe30
--- /dev/null
+++ b/src/window_track_manage.c
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * 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 "addresses.h"
+#include "window.h"
+
+/**
+ *
+ * rct2: 0x006D348F
+ */
+void window_track_manage_open()
+{
+ RCT2_CALLPROC_EBPSAFE(0x006D348F);
+}
\ No newline at end of file
diff --git a/src/window_track_place.c b/src/window_track_place.c
new file mode 100644
index 0000000000..678384c295
--- /dev/null
+++ b/src/window_track_place.c
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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 "addresses.h"
+#include "viewport.h"
+#include "window.h"
+
+/**
+ *
+ * rct2: 0x006CFCA0
+ */
+void window_track_place_open()
+{
+ rct_window *w;
+
+ window_close_construction_windows();
+ RCT2_GLOBAL(0x00F44168, void*) = rct2_malloc(13104);
+ RCT2_CALLPROC_EBPSAFE(0x006D182E);
+
+ w = window_create(0, 29, 200, 124, (uint32*)0x0099405C, WC_TRACK_DESIGN_PLACE, 0);
+ w->widgets = (rct_widget*)0x009D7F18;
+ w->enabled_widgets = 4 | 8 | 0x10 | 0x20;
+ window_init_scroll_widgets(w);
+ w->colours[0] = 24;
+ w->colours[1] = 24;
+ w->colours[2] = 24;
+ tool_set(w, 6, 12);
+ RCT2_GLOBAL(0x009DE518, uint32) |= 6;
+ window_push_others_right(w);
+ show_gridlines();
+ RCT2_GLOBAL(0x00F440D9, uint32) |= 0x80000000;
+ RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF;
+ RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
+ RCT2_CALLPROC_EBPSAFE(0x006D1845);
+}
\ No newline at end of file