diff --git a/openrct2.vcxproj b/openrct2.vcxproj
index db9aaeffe6..a3867bc4d0 100644
--- a/openrct2.vcxproj
+++ b/openrct2.vcxproj
@@ -325,8 +325,10 @@
+
+
@@ -342,7 +344,6 @@
-
@@ -574,8 +575,9 @@
+
-
+
diff --git a/src/OpenRCT2.cpp b/src/OpenRCT2.cpp
index fb496d3235..d078949b7e 100644
--- a/src/OpenRCT2.cpp
+++ b/src/OpenRCT2.cpp
@@ -39,7 +39,7 @@ extern "C"
#include "object_list.h"
#include "platform/platform.h"
#include "rct2/interop.h"
- #include "title.h"
+ #include "title/TitleScreen.h"
#include "version.h"
}
diff --git a/src/core/Zip.cpp b/src/core/Zip.cpp
index b2c48ca8c1..29d123f356 100644
--- a/src/core/Zip.cpp
+++ b/src/core/Zip.cpp
@@ -83,11 +83,11 @@ public:
zip_file_t * zipFile = zip_fopen(_zip, path, 0);
if (zipFile != nullptr)
{
- data = malloc(dataSize);
- size_t readBytes = zip_fread(zipFile, data, dataSize);
+ data = Memory::Allocate((size_t)dataSize);
+ uint64 readBytes = zip_fread(zipFile, data, dataSize);
if (readBytes != dataSize)
{
- free(data);
+ Memory::Free(data);
data = nullptr;
dataSize = 0;
}
@@ -95,7 +95,7 @@ public:
}
}
- if (outSize != nullptr) *outSize = dataSize;
+ if (outSize != nullptr) *outSize = (size_t)dataSize;
return data;
}
diff --git a/src/game.c b/src/game.c
index c5d75fd12c..1f6854dffb 100644
--- a/src/game.c
+++ b/src/game.c
@@ -17,15 +17,14 @@
#include "audio/audio.h"
#include "cheats.h"
#include "config.h"
-#include "game.h"
#include "editor.h"
-#include "world/footpath.h"
+#include "game.h"
#include "input.h"
-#include "localisation/localisation.h"
#include "interface/screenshot.h"
#include "interface/viewport.h"
#include "interface/widget.h"
#include "interface/window.h"
+#include "localisation/localisation.h"
#include "management/finance.h"
#include "management/marketing.h"
#include "management/news_item.h"
@@ -39,16 +38,17 @@
#include "rct1.h"
#include "ride/ride.h"
#include "ride/ride_ratings.h"
-#include "ride/vehicle.h"
#include "ride/track.h"
#include "ride/track_design.h"
+#include "ride/vehicle.h"
#include "scenario.h"
-#include "title.h"
+#include "title/TitleScreen.h"
#include "util/sawyercoding.h"
#include "util/util.h"
#include "windows/error.h"
#include "windows/tooltip.h"
#include "world/climate.h"
+#include "world/footpath.h"
#include "world/map_animation.h"
#include "world/park.h"
#include "world/scenery.h"
diff --git a/src/game.h b/src/game.h
index c02a67835c..f197c6cef3 100644
--- a/src/game.h
+++ b/src/game.h
@@ -170,7 +170,7 @@ void game_reduce_game_speed();
void game_load_or_quit_no_save_prompt();
bool game_load_sv6_path(const char * path);
-int game_load_sv6(SDL_RWops* rw);
+bool game_load_sv6(SDL_RWops* rw);
int game_load_network(SDL_RWops* rw);
bool game_load_save(const utf8 *path);
void game_load_init();
diff --git a/src/interface/keyboard_shortcut.c b/src/interface/keyboard_shortcut.c
index c7a9e6353b..a3cb9fb455 100644
--- a/src/interface/keyboard_shortcut.c
+++ b/src/interface/keyboard_shortcut.c
@@ -16,8 +16,8 @@
#include "../audio/audio.h"
#include "../config.h"
-#include "../game.h"
#include "../editor.h"
+#include "../game.h"
#include "../input.h"
#include "../interface/chat.h"
#include "../interface/screenshot.h"
@@ -25,7 +25,7 @@
#include "../network/network.h"
#include "../platform/platform.h"
#include "../ride/track_paint.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "keyboard_shortcut.h"
#include "viewport.h"
diff --git a/src/interface/title_sequences.c b/src/interface/title_sequences.c
index 65bed449e6..18bda544cb 100644
--- a/src/interface/title_sequences.c
+++ b/src/interface/title_sequences.c
@@ -74,7 +74,6 @@ void title_sequence_change_preset(int preset)
gConfigInterface.current_title_sequence_preset = _strdup(configId);
gCurrentPreviewTitleSequence = preset;
- title_refresh_sequence();
window_invalidate_all();
}
diff --git a/src/interface/title_sequences.h b/src/interface/title_sequences.h
index 54c209a117..76ef1c15ac 100644
--- a/src/interface/title_sequences.h
+++ b/src/interface/title_sequences.h
@@ -18,10 +18,10 @@
#define _TITLE_SEQUENCES_H_
#include "../common.h"
-#include "window.h"
#include "../config.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
+#include "window.h"
#define TITLE_SEQUENCE_DEFAULT_PRESETS 2
diff --git a/src/openrct2.c b/src/openrct2.c
new file mode 100644
index 0000000000..e9b800dd12
--- /dev/null
+++ b/src/openrct2.c
@@ -0,0 +1,361 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/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.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#include "audio/audio.h"
+#include "audio/mixer.h"
+#include "config.h"
+#include "editor.h"
+#include "game.h"
+#include "interface/chat.h"
+#include "interface/themes.h"
+#include "interface/window.h"
+#include "interface/viewport.h"
+#include "intro.h"
+#include "localisation/localisation.h"
+#include "network/http.h"
+#include "network/network.h"
+#include "object_list.h"
+#include "openrct2.h"
+#include "platform/crash.h"
+#include "platform/platform.h"
+#include "rct2/interop.h"
+#include "ride/ride.h"
+#include "title/TitleScreen.h"
+#include "title/TitleSequenceManager.h"
+#include "util/util.h"
+#include "version.h"
+#include "world/mapgen.h"
+
+#define UPDATE_TIME_MS 25 // (1000 / 40fps) = 25ms
+
+int gExitCode;
+
+int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE;
+utf8 gOpenRCT2StartupActionPath[512] = { 0 };
+utf8 gExePath[MAX_PATH];
+utf8 gCustomUserDataPath[MAX_PATH] = { 0 };
+utf8 gCustomOpenrctDataPath[MAX_PATH] = { 0 };
+utf8 gCustomRCT2DataPath[MAX_PATH] = { 0 };
+utf8 gCustomPassword[MAX_PATH] = { 0 };
+
+// This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT
+bool gOpenRCT2Headless = false;
+
+bool gOpenRCT2ShowChangelog;
+bool gOpenRCT2SilentBreakpad;
+
+#ifndef DISABLE_NETWORK
+// OpenSSL's message digest context used for calculating sprite checksums
+EVP_MD_CTX *gHashCTX = NULL;
+#endif // DISABLE_NETWORK
+
+/** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */
+int _finished;
+
+static void openrct2_loop();
+
+void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize)
+{
+ utf8 *ch = buffer;
+
+ // Name and version
+ safe_strcpy(ch, OPENRCT2_NAME ", v" OPENRCT2_VERSION, bufferSize - (ch - buffer));
+ ch = strchr(ch, '\0');
+
+ // Build information
+ if (!str_is_null_or_empty(gGitBranch)) {
+ snprintf(ch, bufferSize - (ch - buffer), "-%s", gGitBranch);
+ ch = strchr(ch, '\0');
+ }
+ if (!str_is_null_or_empty(gCommitSha1Short)) {
+ snprintf(ch, bufferSize - (ch - buffer), " build %s", gCommitSha1Short);
+ ch = strchr(ch, '\0');
+ }
+ if (!str_is_null_or_empty(gBuildServer)) {
+ snprintf(ch, bufferSize - (ch - buffer), " provided by %s", gBuildServer);
+ ch = strchr(ch, '\0');
+ }
+
+#if DEBUG
+ snprintf(ch, bufferSize - (ch - buffer), " (DEBUG)");
+#endif
+}
+
+static void openrct2_set_exe_path()
+{
+ platform_get_exe_path(gExePath, sizeof(gExePath));
+ log_verbose("Setting exe path to %s", gExePath);
+}
+
+bool openrct2_initialise()
+{
+ utf8 userPath[MAX_PATH];
+
+#ifndef DISABLE_NETWORK
+ gHashCTX = EVP_MD_CTX_create();
+ assert(gHashCTX != NULL);
+#endif // DISABLE_NETWORK
+
+ platform_resolve_openrct_data_path();
+ platform_resolve_user_data_path();
+ platform_get_user_directory(userPath, NULL, sizeof(userPath));
+ if (!platform_ensure_directory_exists(userPath)) {
+ log_fatal("Could not create user directory (do you have write access to your documents folder?)");
+ return false;
+ }
+
+ crash_init();
+
+ if (!rct2_interop_setup_segment()) {
+ log_fatal("Unable to load RCT2 data sector");
+ return false;
+ }
+
+ openrct2_set_exe_path();
+
+ config_set_defaults();
+ if (!config_open_default()) {
+ if (!config_find_or_browse_install_directory()) {
+ gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
+ config_save_default();
+ utf8 path[MAX_PATH];
+ config_get_default_path(path, sizeof(path));
+ log_fatal("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path);
+ return false;
+ }
+ }
+
+ gOpenRCT2ShowChangelog = true;
+ if (gConfigGeneral.last_run_version != NULL && (strcmp(gConfigGeneral.last_run_version, OPENRCT2_VERSION) == 0))
+ gOpenRCT2ShowChangelog = false;
+ gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
+ config_save_default();
+
+ // TODO add configuration option to allow multiple instances
+ // if (!gOpenRCT2Headless && !platform_lock_single_instance()) {
+ // log_fatal("OpenRCT2 is already running.");
+ // return false;
+ // }
+
+ if (!rct2_init_directories()) {
+ return false;
+ }
+ if (!rct2_startup_checks()) {
+ return false;
+ }
+
+ if (!gOpenRCT2Headless) {
+ audio_init();
+ audio_populate_devices();
+ }
+
+ if (!language_open(gConfigGeneral.language)) {
+ log_error("Failed to open configured language...");
+
+ if (!language_open(LANGUAGE_ENGLISH_UK)) {
+ log_fatal("Failed to open fallback language...");
+ return false;
+ }
+ }
+ http_init();
+
+ theme_manager_initialise();
+ title_sequence_manager_scan();
+
+ rct2_interop_setup_hooks();
+
+ if (!rct2_init())
+ return false;
+
+ chat_init();
+
+ rct2_copy_original_user_files_over();
+ return true;
+}
+
+/**
+ * Launches the game, after command line arguments have been parsed and processed.
+ */
+void openrct2_launch()
+{
+ if (openrct2_initialise()) {
+ gIntroState = INTRO_STATE_NONE;
+ if((gOpenRCT2StartupAction == STARTUP_ACTION_TITLE) && gConfigGeneral.play_intro)
+ gOpenRCT2StartupAction = STARTUP_ACTION_INTRO;
+
+ switch (gOpenRCT2StartupAction) {
+ case STARTUP_ACTION_INTRO:
+ gIntroState = INTRO_STATE_PUBLISHER_BEGIN;
+ title_load();
+ break;
+ case STARTUP_ACTION_TITLE:
+ title_load();
+ break;
+ case STARTUP_ACTION_OPEN:
+ assert(gOpenRCT2StartupActionPath != NULL);
+ if (!rct2_open_file(gOpenRCT2StartupActionPath)) {
+ fprintf(stderr, "Failed to load '%s'", gOpenRCT2StartupActionPath);
+ title_load();
+ break;
+ }
+
+ gScreenFlags = SCREEN_FLAGS_PLAYING;
+
+#ifndef DISABLE_NETWORK
+ if (gNetworkStart == NETWORK_MODE_SERVER) {
+ if (gNetworkStartPort == 0) {
+ gNetworkStartPort = gConfigNetwork.default_port;
+ }
+
+ if (str_is_null_or_empty(gCustomPassword)) {
+ network_set_password(gConfigNetwork.default_password);
+ }
+ else {
+ network_set_password(gCustomPassword);
+ }
+ network_begin_server(gNetworkStartPort);
+ }
+#endif // DISABLE_NETWORK
+ break;
+ case STARTUP_ACTION_EDIT:
+ if (strlen(gOpenRCT2StartupActionPath) == 0) {
+ editor_load();
+ } else {
+ if (!editor_load_landscape(gOpenRCT2StartupActionPath)) {
+ title_load();
+ }
+ }
+ break;
+ }
+
+#ifndef DISABLE_NETWORK
+ if (gNetworkStart == NETWORK_MODE_CLIENT) {
+ if (gNetworkStartPort == 0) {
+ gNetworkStartPort = gConfigNetwork.default_port;
+ }
+
+ network_begin_client(gNetworkStartHost, gNetworkStartPort);
+ }
+#endif // DISABLE_NETWORK
+
+ openrct2_loop();
+ }
+ openrct2_dispose();
+
+ // HACK Some threads are still running which causes the game to not terminate. Investigation required!
+ exit(gExitCode);
+}
+
+void openrct2_dispose()
+{
+ network_close();
+ http_dispose();
+ language_close_all();
+ rct2_dispose();
+ config_release();
+#ifndef DISABLE_NETWORK
+ EVP_MD_CTX_destroy(gHashCTX);
+#endif // DISABLE_NETWORK
+ rct2_interop_dispose();
+ platform_free();
+}
+
+/**
+ * Run the main game loop until the finished flag is set at 40fps (25ms interval).
+ */
+static void openrct2_loop()
+{
+ uint32 currentTick, ticksElapsed, lastTick = 0;
+ static uint32 uncapTick = 0;
+ static int fps = 0;
+ static uint32 secondTick = 0;
+
+ log_verbose("begin openrct2 loop");
+
+ _finished = 0;
+ do {
+ bool is_minimised = (SDL_GetWindowFlags(gWindow) & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_HIDDEN)) != 0;
+ if (gConfigGeneral.uncap_fps && gGameSpeed <= 4 && !gOpenRCT2Headless && !is_minimised) {
+ currentTick = SDL_GetTicks();
+ if (uncapTick == 0) {
+ // Reset sprite locations
+ uncapTick = SDL_GetTicks();
+ sprite_position_tween_reset();
+ }
+
+ // Limit number of updates per loop (any long pauses or debugging can make this update for a very long time)
+ if (currentTick - uncapTick > UPDATE_TIME_MS * 60) {
+ uncapTick = currentTick - UPDATE_TIME_MS - 1;
+ }
+
+ platform_process_messages();
+
+ while (uncapTick <= currentTick && currentTick - uncapTick > UPDATE_TIME_MS) {
+ // Get the original position of each sprite
+ sprite_position_tween_store_a();
+
+ // Update the game so the sprite positions update
+ rct2_update();
+
+ // Get the next position of each sprite
+ sprite_position_tween_store_b();
+
+ uncapTick += UPDATE_TIME_MS;
+ }
+
+ // Tween the position of each sprite from the last position to the new position based on the time between the last
+ // tick and the next tick.
+ float nudge = 1 - ((float)(currentTick - uncapTick) / UPDATE_TIME_MS);
+ sprite_position_tween_all(nudge);
+
+ platform_draw();
+
+ fps++;
+ if (SDL_GetTicks() - secondTick >= 1000) {
+ fps = 0;
+ secondTick = SDL_GetTicks();
+ }
+
+ sprite_position_tween_restore();
+ } else {
+ uncapTick = 0;
+ currentTick = SDL_GetTicks();
+ ticksElapsed = currentTick - lastTick;
+ if (ticksElapsed < UPDATE_TIME_MS) {
+ SDL_Delay(UPDATE_TIME_MS - ticksElapsed);
+ lastTick += UPDATE_TIME_MS;
+ } else {
+ lastTick = currentTick;
+ }
+
+ platform_process_messages();
+
+ rct2_update();
+
+ if (!is_minimised) {
+ platform_draw();
+ }
+ }
+ } while (!_finished);
+}
+
+/**
+ * Causes the OpenRCT2 game loop to finish.
+ */
+void openrct2_finish()
+{
+ _finished = 1;
+}
diff --git a/src/openrct2.h b/src/openrct2.h
new file mode 100644
index 0000000000..0b03fccf2e
--- /dev/null
+++ b/src/openrct2.h
@@ -0,0 +1,73 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/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.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#pragma once
+
+#include "common.h"
+#include "core/Guard.hpp"
+#include "platform/platform.h"
+
+#ifndef DISABLE_NETWORK
+ #include
+#endif // DISABLE_NETWORK
+
+enum STARTUP_ACTION
+{
+ STARTUP_ACTION_INTRO,
+ STARTUP_ACTION_TITLE,
+ STARTUP_ACTION_OPEN,
+ STARTUP_ACTION_EDIT
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /** The exit code for OpenRCT2 when it exits. */
+ extern int gExitCode;
+
+ extern int gOpenRCT2StartupAction;
+ extern utf8 gOpenRCT2StartupActionPath[512];
+ extern utf8 gExePath[MAX_PATH];
+ extern utf8 gCustomUserDataPath[MAX_PATH];
+ extern utf8 gCustomOpenrctDataPath[MAX_PATH];
+ extern utf8 gCustomRCT2DataPath[MAX_PATH];
+ extern utf8 gCustomPassword[MAX_PATH];
+ extern bool gOpenRCT2Headless;
+ extern bool gOpenRCT2ShowChangelog;
+
+#ifndef DISABLE_NETWORK
+ extern EVP_MD_CTX * gHashCTX;
+#endif // DISABLE_NETWORK
+
+#ifndef DISABLE_NETWORK
+ extern int gNetworkStart;
+ extern char gNetworkStartHost[128];
+ extern int gNetworkStartPort;
+#endif
+
+ void openrct2_write_full_version_info(utf8 * buffer, size_t bufferSize);
+ bool openrct2_initialise();
+ void openrct2_launch();
+ void openrct2_dispose();
+ void openrct2_finish();
+
+ int cmdline_run(const char * * argv, int argc);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/shared.c b/src/platform/shared.c
index 0f8404d368..065e05d32b 100644
--- a/src/platform/shared.c
+++ b/src/platform/shared.c
@@ -191,7 +191,6 @@ static void platform_resize(int width, int height)
window_relocate_windows(dst_w, dst_h);
}
- title_fix_location();
gfx_invalidate_screen();
// Check if the window has been resized in windowed mode and update the config file accordingly
diff --git a/src/rct2.c b/src/rct2.c
index 5426fb9309..7cbc612bd0 100644
--- a/src/rct2.c
+++ b/src/rct2.c
@@ -44,11 +44,11 @@
#include "ride/track_design.h"
#include "ride/TrackDesignRepository.h"
#include "ScenarioRepository.h"
-#include "title.h"
+#include "title/TitleScreen.h"
#include "util/util.h"
+#include "world/climate.h"
#include "world/map.h"
#include "world/park.h"
-#include "world/climate.h"
#include "world/scenery.h"
#include "world/sprite.h"
diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp
index 91b72db8d0..2561e1ae6a 100644
--- a/src/rct2/S6Importer.cpp
+++ b/src/rct2/S6Importer.cpp
@@ -366,7 +366,7 @@ extern "C"
*
* rct2: 0x00675E1B
*/
- int game_load_sv6(SDL_RWops * rw)
+ bool game_load_sv6(SDL_RWops * rw)
{
if (!sawyercoding_validate_checksum(rw))
{
diff --git a/src/scenario.c b/src/scenario.c
index db71779474..1292693cb8 100644
--- a/src/scenario.c
+++ b/src/scenario.c
@@ -18,15 +18,14 @@
#include "cheats.h"
#include "config.h"
#include "game.h"
-#include "world/climate.h"
#include "interface/viewport.h"
#include "localisation/date.h"
#include "localisation/localisation.h"
#include "management/award.h"
#include "management/finance.h"
#include "management/marketing.h"
-#include "management/research.h"
#include "management/news_item.h"
+#include "management/research.h"
#include "network/network.h"
#include "object.h"
#include "object_list.h"
@@ -37,9 +36,9 @@
#include "scenario.h"
#include "ScenarioRepository.h"
#include "ScenarioSources.h"
-#include "title.h"
#include "util/sawyercoding.h"
#include "util/util.h"
+#include "world/climate.h"
#include "world/map.h"
#include "world/park.h"
#include "world/scenery.h"
diff --git a/src/title/TitleScreen.cpp b/src/title/TitleScreen.cpp
new file mode 100644
index 0000000000..7a735813a7
--- /dev/null
+++ b/src/title/TitleScreen.cpp
@@ -0,0 +1,218 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/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.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#include "../network/network.h"
+#include "../openrct2.h"
+#include "TitleScreen.h"
+#include "TitleSequence.h"
+#include "TitleSequenceManager.h"
+#include "TitleSequencePlayer.h"
+
+extern "C"
+{
+ #include "../audio/audio.h"
+ #include "../drawing/drawing.h"
+ #include "../game.h"
+ #include "../input.h"
+ #include "../interface/screenshot.h"
+ #include "../interface/title_sequences.h"
+ #include "../interface/viewport.h"
+ #include "../interface/window.h"
+ #include "../localisation/localisation.h"
+ #include "../peep/staff.h"
+ #include "../world/climate.h"
+ #include "../world/scenery.h"
+}
+
+extern "C"
+{
+ bool gTitleHideVersionInfo = false;
+}
+
+static sint32 _sequenceAttemptId;
+static sint32 _loadedTitleSequenceId = -1;
+static ITitleSequencePlayer * _sequencePlayer = nullptr;
+
+static void TitleInitialise();
+static void TryLoadSequence();
+static void TryNextSequence();
+
+/**
+ *
+ * rct2: 0x00678680
+ */
+static void TitleInitialise()
+{
+ if (_sequencePlayer == nullptr)
+ {
+ _sequencePlayer = CreateTitleSequencePlayer();
+ }
+ size_t seqId = title_sequence_manager_get_index_for_config_id(gConfigInterface.current_title_sequence_preset);
+ if (seqId == SIZE_MAX)
+ {
+ seqId = title_sequence_manager_get_index_for_config_id("*OPENRCT2");
+ if (seqId == SIZE_MAX)
+ {
+ seqId = 0;
+ }
+ }
+ title_sequence_change_preset((int)seqId);
+ TryLoadSequence();
+}
+
+static void TryLoadSequence()
+{
+ if (_loadedTitleSequenceId != gCurrentPreviewTitleSequence)
+ {
+ if (_sequencePlayer->Begin(gCurrentPreviewTitleSequence))
+ {
+ _loadedTitleSequenceId = gCurrentPreviewTitleSequence;
+ gfx_invalidate_screen();
+ }
+ }
+}
+
+static void TryNextSequence()
+{
+ gCurrentPreviewTitleSequence = _sequenceAttemptId++;
+ if (_sequenceAttemptId >= (sint32)TitleSequenceManager::GetCount())
+ {
+ _sequenceAttemptId = 0;
+ }
+ TryLoadSequence();
+}
+
+extern "C"
+{
+ /**
+ *
+ * rct2: 0x0068E8DA
+ */
+ void title_load()
+ {
+ log_verbose("loading title");
+
+ if (gGamePaused & GAME_PAUSED_NORMAL)
+ pause_toggle();
+
+ gScreenFlags = SCREEN_FLAGS_TITLE_DEMO;
+
+#ifndef DISABLE_NETWORK
+ network_close();
+#endif
+ reset_park_entrances();
+ user_string_clear_all();
+ reset_sprite_list();
+ ride_init_all();
+ window_guest_list_init_vars_a();
+ staff_reset_modes();
+ map_init(150);
+ park_init();
+ date_reset();
+ climate_reset(CLIMATE_COOL_AND_WET);
+ scenery_set_default_placement_configuration();
+ window_new_ride_init_vars();
+ window_guest_list_init_vars_b();
+ window_staff_list_init_vars();
+ map_update_tile_pointers();
+ reset_sprite_spatial_index();
+ audio_stop_all_music_and_sounds();
+ viewport_init_all();
+ news_item_init_queue();
+ window_main_open();
+ title_create_windows();
+ TitleInitialise();
+ gfx_invalidate_screen();
+ audio_start_title_music();
+ gScreenAge = 0;
+
+ if (gOpenRCT2ShowChangelog) {
+ gOpenRCT2ShowChangelog = false;
+ window_changelog_open();
+ }
+
+ log_verbose("loading title finished");
+ }
+
+ /**
+ * Creates the windows shown on the title screen; New game, load game,
+ * tutorial, toolbox and exit.
+ * rct2: 0x0066B5C0 (part of 0x0066B3E8)
+ */
+ void title_create_windows()
+ {
+ window_title_menu_open();
+ window_title_exit_open();
+ window_title_options_open();
+ window_title_logo_open();
+ window_resize_gui(gScreenWidth, gScreenHeight);
+ gTitleHideVersionInfo = false;
+ }
+
+ void title_update()
+ {
+ screenshot_check();
+ title_handle_keyboard_input();
+
+ if (game_is_not_paused())
+ {
+ TryLoadSequence();
+ if (_sequencePlayer != nullptr && !_sequencePlayer->Update())
+ {
+ TryNextSequence();
+ }
+
+ sint32 numUpdates = 1;
+ if (gGameSpeed > 1) {
+ numUpdates = 1 << (gGameSpeed - 1);
+ }
+ for (sint32 i = 0; i < numUpdates; i++)
+ {
+ game_logic_update();
+ }
+ update_palette_effects();
+ // update_rain_animation();
+ }
+
+ gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
+
+ window_map_tooltip_update_visibility();
+ window_dispatch_update_all();
+
+ gSavedAge++;
+
+ game_handle_input();
+ }
+
+ void DrawOpenRCT2(rct_drawpixelinfo * dpi, int x, int y)
+ {
+ utf8 buffer[256];
+
+ // Write format codes
+ utf8 *ch = buffer;
+ ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT);
+ ch = utf8_write_codepoint(ch, FORMAT_OUTLINE);
+ ch = utf8_write_codepoint(ch, FORMAT_WHITE);
+
+ // Write name and version information
+ openrct2_write_full_version_info(ch, sizeof(buffer) - (ch - buffer));
+ gfx_draw_string(dpi, buffer, COLOUR_BLACK, x + 5, y + 5 - 13);
+
+ // Write platform information
+ snprintf(ch, 256 - (ch - buffer), "%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE);
+ gfx_draw_string(dpi, buffer, COLOUR_BLACK, x + 5, y + 5);
+ }
+}
diff --git a/src/title/TitleScreen.h b/src/title/TitleScreen.h
new file mode 100644
index 0000000000..b3fbda5410
--- /dev/null
+++ b/src/title/TitleScreen.h
@@ -0,0 +1,33 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/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.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#pragma once
+
+#include "../drawing/drawing.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ extern bool gTitleHideVersionInfo;
+
+ void title_load();
+ void title_create_windows();
+ void title_update();
+ void DrawOpenRCT2(rct_drawpixelinfo *dpi, int x, int y);
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/title/TitleSequencePlayer.cpp b/src/title/TitleSequencePlayer.cpp
new file mode 100644
index 0000000000..c8d8e1c18c
--- /dev/null
+++ b/src/title/TitleSequencePlayer.cpp
@@ -0,0 +1,402 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/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.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#include "../common.h"
+#include
+#include "../core/Console.hpp"
+#include "../core/Exception.hpp"
+#include "../core/Math.hpp"
+#include "../core/Path.hpp"
+#include "../core/String.hpp"
+#include "../ScenarioRepository.h"
+#include "../ScenarioSources.h"
+#include "TitleSequence.h"
+#include "TitleSequenceManager.h"
+#include "TitleSequencePlayer.h"
+
+extern "C"
+{
+ #include "../game.h"
+ #include "../interface/viewport.h"
+ #include "../interface/window.h"
+ #include "../world/scenery.h"
+}
+
+class TitleSequencePlayer : public ITitleSequencePlayer
+{
+private:
+ uint32 _sequenceId = 0;
+ TitleSequence * _sequence = nullptr;
+ sint32 _position = 0;
+ sint32 _waitCounter = 0;
+
+ sint32 _lastScreenWidth = 0;
+ sint32 _lastScreenHeight = 0;
+ rct_xy32 _viewCentreLocation = { 0 };
+
+public:
+ ~TitleSequencePlayer() override
+ {
+ FreeTitleSequence(_sequence);
+ }
+
+ sint32 GetCurrentPosition() const override
+ {
+ return _position;
+ }
+
+ bool Begin(uint32 titleSequenceId) override
+ {
+ size_t numSequences = TitleSequenceManager::GetCount();
+ if (titleSequenceId >= numSequences)
+ {
+ return false;
+ }
+
+ auto seqItem = TitleSequenceManager::GetItem(titleSequenceId);
+ auto sequence = LoadTitleSequence(seqItem->Path.c_str());
+ if (sequence == nullptr)
+ {
+ return false;
+ }
+
+ FreeTitleSequence(_sequence);
+ _sequence = sequence;
+ _sequenceId = titleSequenceId;
+
+ Reset();
+ return true;
+ }
+
+ bool Update() override
+ {
+ FixViewLocation();
+
+ sint32 entryPosition = _position;
+ if (_waitCounter <= 0)
+ {
+ do
+ {
+ if (_position > (sint32)_sequence->NumCommands)
+ {
+ _position = 0;
+ return false;
+ }
+
+ const TitleCommand * command = &_sequence->Commands[_position];
+ bool successful = ExecuteCommand(command);
+ IncrementPosition();
+ if (!successful)
+ {
+ bool isLoadCommand = false;
+ do
+ {
+ const TitleCommand * command = &_sequence->Commands[_position];
+ switch (command->Type) {
+ case TITLE_SCRIPT_LOADMM:
+ case TITLE_SCRIPT_LOAD:
+ case TITLE_SCRIPT_LOADRCT1:
+ isLoadCommand = true;
+ break;
+ default:
+ IncrementPosition();
+ if (_position == entryPosition)
+ {
+ // We have got back to where we started so we can't load any of these parks
+ return false;
+ }
+ break;
+ }
+ }
+ while (!isLoadCommand);
+ }
+ }
+ while (_waitCounter == 0);
+ }
+ _waitCounter--;
+ return true;
+ }
+
+ void Reset() override
+ {
+ _position = 0;
+ _waitCounter = 0;
+ Update();
+ }
+
+ void Seek(sint32 targetPosition) override
+ {
+ if (targetPosition < 0 || targetPosition >= (sint32)_sequence->NumCommands)
+ {
+ throw Exception("Invalid position.");
+ }
+ if (_position >= targetPosition)
+ {
+ Reset();
+ }
+
+ // Set position to the last LOAD command before target position
+ for (sint32 i = targetPosition; i >= 0; i--)
+ {
+ uint8 commandType = _sequence->Commands[i].Type;
+ if (commandType == TITLE_SCRIPT_LOADMM ||
+ commandType == TITLE_SCRIPT_LOAD ||
+ commandType == TITLE_SCRIPT_LOADRCT1)
+ {
+ _position = i;
+ }
+ }
+
+ // Keep updating until we reach target position
+ while (_position < targetPosition)
+ {
+ if (Update())
+ {
+ game_logic_update();
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+private:
+ void IncrementPosition()
+ {
+ _position++;
+ if (_position >= (sint32)_sequence->NumCommands)
+ {
+ _position = 0;
+ }
+ }
+
+ bool ExecuteCommand(const TitleCommand * command)
+ {
+ switch (command->Type) {
+ case TITLE_SCRIPT_END:
+ _waitCounter = 1;
+ break;
+ case TITLE_SCRIPT_WAIT:
+ _waitCounter = command->Seconds * 32;
+ break;
+ case TITLE_SCRIPT_LOADMM:
+ {
+ const utf8 * path = get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN);
+ if (!LoadParkFromFile(path))
+ {
+ Console::Error::WriteLine("Failed to load: \"%s\" for the title sequence.", path);
+ return false;
+ }
+ break;
+ }
+ case TITLE_SCRIPT_LOCATION:
+ {
+ sint32 x = command->X * 32 + 16;
+ sint32 y = command->Y * 32 + 16;
+ SetViewLocation(x, y);
+ break;
+ }
+ case TITLE_SCRIPT_ROTATE:
+ RotateView(command->Rotations);
+ break;
+ case TITLE_SCRIPT_ZOOM:
+ SetViewZoom(command->Zoom);
+ break;
+ case TITLE_SCRIPT_SPEED:
+ gGameSpeed = Math::Clamp(1, command->Speed, 4);
+ break;
+ case TITLE_SCRIPT_RESTART:
+ Reset();
+ break;
+ case TITLE_SCRIPT_LOAD:
+ {
+ bool loadSuccess = false;
+ uint8 saveIndex = command->SaveIndex;
+ TitleSequenceParkHandle * parkHandle = TitleSequenceGetParkHandle(_sequence, saveIndex);
+ if (parkHandle != nullptr)
+ {
+ loadSuccess = LoadParkFromRW(parkHandle->RWOps, parkHandle->IsScenario);
+ TitleSequenceCloseParkHandle(parkHandle);
+ }
+ if (!loadSuccess)
+ {
+ if (_sequence->NumSaves > saveIndex)
+ {
+ const utf8 * path = _sequence->Saves[saveIndex];
+ Console::Error::WriteLine("Failed to load: \"%s\" for the title sequence.", path);
+ }
+ return false;
+ }
+ break;
+ }
+ case TITLE_SCRIPT_LOADRCT1:
+ {
+ source_desc sourceDesc;
+ if (!ScenarioSources::TryGetById(command->SaveIndex, &sourceDesc) || sourceDesc.index == -1)
+ {
+ Console::Error::WriteLine("Invalid scenario id.");
+ return false;
+ }
+
+ const utf8 * path = nullptr;
+ IScenarioRepository * scenarioRepo = GetScenarioRepository();
+ size_t numScenarios = scenarioRepo->GetCount();
+ for (size_t i = 0; i < numScenarios; i++)
+ {
+ const scenario_index_entry * scenario = scenarioRepo->GetByIndex(i);
+ if (scenario->source_index == sourceDesc.index)
+ {
+ path = scenario->path;
+ break;
+ }
+ }
+ if (path == nullptr || !LoadParkFromFile(path))
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ void SetViewZoom(const uint32 &zoom)
+ {
+ rct_window * w = window_get_main();
+ if (w != nullptr && w->viewport != nullptr)
+ {
+ window_zoom_set(w, zoom);
+ }
+ }
+
+ void RotateView(uint32 count)
+ {
+ rct_window * w = window_get_main();
+ if (w != nullptr)
+ {
+ for (uint32 i = 0; i < count; i++)
+ {
+ window_rotate_camera(w, 1);
+ }
+ }
+ }
+
+ bool LoadParkFromFile(const utf8 * path)
+ {
+ bool success = false;
+ bool isScenario = String::Equals(Path::GetExtension(path), ".sc6", true);
+ SDL_RWops * rw = SDL_RWFromFile(path, "rb");
+ if (rw != nullptr)
+ {
+ success = LoadParkFromRW(rw, isScenario);
+ SDL_RWclose(rw);
+ }
+ return success;
+ }
+
+ bool LoadParkFromRW(SDL_RWops * rw, bool isScenario)
+ {
+ bool successfulLoad = isScenario ? scenario_load_rw(rw) :
+ game_load_sv6(rw);
+ if (!successfulLoad)
+ {
+ return false;
+ }
+
+ rct_window * w = window_get_main();
+ w->viewport_target_sprite = -1;
+ w->saved_view_x = gSavedViewX;
+ w->saved_view_y = gSavedViewY;
+
+ char zoomDifference = gSavedViewZoom - w->viewport->zoom;
+ w->viewport->zoom = gSavedViewZoom;
+ gCurrentRotation = gSavedViewRotation;
+ if (zoomDifference != 0)
+ {
+ if (zoomDifference < 0)
+ {
+ zoomDifference = -zoomDifference;
+ w->viewport->view_width >>= zoomDifference;
+ w->viewport->view_height >>= zoomDifference;
+ }
+ else
+ {
+ w->viewport->view_width <<= zoomDifference;
+ w->viewport->view_height <<= zoomDifference;
+ }
+ }
+ w->saved_view_x -= w->viewport->view_width >> 1;
+ w->saved_view_y -= w->viewport->view_height >> 1;
+
+ window_invalidate(w);
+ reset_sprite_spatial_index();
+ reset_all_sprite_quadrant_placements();
+ window_new_ride_init_vars();
+ if (!isScenario)
+ {
+ sub_684AC3();
+ }
+ scenery_set_default_placement_configuration();
+ news_item_init_queue();
+ load_palette();
+ gfx_invalidate_screen();
+ gScreenAge = 0;
+ gGameSpeed = 1;
+ return true;
+ }
+
+ /**
+ * Sets the map location to the given tile coordinates. Z is automatic.
+ * @param x X position in map tiles.
+ * @param y Y position in map tiles.
+ */
+ void SetViewLocation(sint32 x, sint32 y)
+ {
+ // Update viewport
+ rct_window * w = window_get_main();
+ if (w != nullptr)
+ {
+ sint32 z = map_element_height(x, y);
+ window_scroll_to_location(w, x, y, z);
+ w->flags &= ~WF_SCROLLING_TO_LOCATION;
+ viewport_update_position(w);
+ }
+
+ // Save known tile position in case of window resize
+ _lastScreenWidth = gScreenWidth;
+ _lastScreenHeight = gScreenHeight;
+ _viewCentreLocation.x = x;
+ _viewCentreLocation.y = y;
+ }
+
+ /**
+ * Fixes the view location for when the game window has changed size.
+ */
+ void FixViewLocation()
+ {
+ if (gScreenWidth != _lastScreenWidth ||
+ gScreenHeight != _lastScreenHeight)
+ {
+ SetViewLocation(_viewCentreLocation.x, _viewCentreLocation.y);
+ }
+ }
+};
+
+ITitleSequencePlayer * CreateTitleSequencePlayer()
+{
+ return new TitleSequencePlayer();
+}
diff --git a/src/title.h b/src/title/TitleSequencePlayer.h
similarity index 63%
rename from src/title.h
rename to src/title/TitleSequencePlayer.h
index cd8a8f1bbe..dcca351f2d 100644
--- a/src/title.h
+++ b/src/title/TitleSequencePlayer.h
@@ -14,26 +14,25 @@
*****************************************************************************/
#pragma endregion
-#ifndef _TITLE_H_
-#define _TITLE_H_
+#pragma once
#include
#include "drawing/drawing.h"
-extern bool gTitleHideVersionInfo;
+#ifdef __cplusplus
-extern sint32 gTitleScriptCommand;
-extern uint8 gTitleScriptSave;
-extern sint32 gTitleScriptSkipTo;
-extern sint32 gTitleScriptSkipLoad;
+interface ITitleSequencePlayer
+{
+ virtual ~ITitleSequencePlayer() = default;
-void title_load();
-void title_create_windows();
-void title_update();
-void title_skip_from_beginning();
-void title_script_get_line(SDL_RWops *file, char *parts);
-void title_refresh_sequence();
-void title_fix_location();
-void DrawOpenRCT2(rct_drawpixelinfo *dpi, int x, int y);
+ virtual sint32 GetCurrentPosition() const abstract;
+
+ virtual bool Begin(uint32 titleSequenceId) abstract;
+ virtual void Reset() abstract;
+ virtual bool Update() abstract;
+ virtual void Seek(sint32 position) abstract;
+};
+
+ITitleSequencePlayer * CreateTitleSequencePlayer();
#endif
diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c
index 3f61c1511d..2c7fdba5f8 100644
--- a/src/windows/editor_bottom_toolbar.c
+++ b/src/windows/editor_bottom_toolbar.c
@@ -28,7 +28,6 @@
#include "../interface/window.h"
#include "../platform/platform.h"
#include "../ride/track_data.h"
-#include "../title.h"
#include "../util/util.h"
#include "../world/footpath.h"
#include "../world/scenery.h"
diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c
index a8ff12ceb4..933eafdf96 100644
--- a/src/windows/loadsave.c
+++ b/src/windows/loadsave.c
@@ -25,7 +25,6 @@
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../scenario.h"
-#include "../title.h"
#include "../util/util.h"
#include "../windows/error.h"
diff --git a/src/windows/options.c b/src/windows/options.c
index 79f46a115f..c605141bfe 100644
--- a/src/windows/options.c
+++ b/src/windows/options.c
@@ -37,7 +37,6 @@
#include "../platform/platform.h"
#include "../rct2.h"
#include "../sprites.h"
-#include "../title.h"
#include "../title/TitleSequence.h"
#include "../title/TitleSequenceManager.h"
#include "dropdown.h"
diff --git a/src/windows/server_start.c b/src/windows/server_start.c
index ce6243d498..9e5ec91516 100644
--- a/src/windows/server_start.c
+++ b/src/windows/server_start.c
@@ -21,7 +21,7 @@
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../sprites.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "error.h"
diff --git a/src/windows/title_command_editor.c b/src/windows/title_command_editor.c
index 99e786a762..2b480dad79 100644
--- a/src/windows/title_command_editor.c
+++ b/src/windows/title_command_editor.c
@@ -14,20 +14,20 @@
*****************************************************************************/
#pragma endregion
+#include "../game.h"
#include "../input.h"
+#include "../interface/themes.h"
+#include "../interface/title_sequences.h"
+#include "../interface/viewport.h"
#include "../interface/widget.h"
#include "../interface/window.h"
-#include "../interface/viewport.h"
#include "../localisation/localisation.h"
#include "../rct2.h"
#include "../sprites.h"
-#include "../world/map.h"
-#include "../game.h"
-#include "../interface/themes.h"
-#include "../interface/title_sequences.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
#include "../util/util.h"
+#include "../world/map.h"
#include "dropdown.h"
#if 0
diff --git a/src/windows/title_editor.c b/src/windows/title_editor.c
index 6ac074af46..2a15b5fd38 100644
--- a/src/windows/title_editor.c
+++ b/src/windows/title_editor.c
@@ -29,7 +29,7 @@
#include "../scenario.h"
#include "../ScenarioSources.h"
#include "../sprites.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "../title/TitleSequence.h"
#include "../title/TitleSequenceManager.h"
#include "../util/util.h"
@@ -192,6 +192,11 @@ static rct_widget window_title_editor_widgets[] = {
static sint16 _window_title_editor_highlighted_index;
static TitleSequence * _loadedTitleSequence;
+int gTitleScriptCommand;
+int gTitleScriptSkipLoad;
+int gTitleScriptSkipTo;
+int gTitleScriptSave;
+
static int window_title_editor_tab_animation_loops[] = {
64,
1,
@@ -328,7 +333,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
title_sequence_remove_save(gCurrentTitleSequence, w->selected_list_item);
if (w->selected_list_item > 0)
w->selected_list_item--;
- else if (w->selected_list_item > _loadedTitleSequence->NumSaves)
+ else if (w->selected_list_item > (sint16)_loadedTitleSequence->NumSaves)
w->selected_list_item = (sint16)(_loadedTitleSequence->NumSaves - 1);
}
}
@@ -368,18 +373,18 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
case WIDX_TITLE_EDITOR_EDIT:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
- if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands)
+ if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands)
window_title_command_editor_open(w->selected_list_item, false);
}
break;
case WIDX_TITLE_EDITOR_DELETE:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
- if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands) {
+ if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands) {
title_sequence_delete_command(gCurrentTitleSequence, w->selected_list_item);
if (w->selected_list_item > 0)
w->selected_list_item--;
- else if (w->selected_list_item >= _loadedTitleSequence->NumCommands)
+ else if (w->selected_list_item >= (sint16)_loadedTitleSequence->NumCommands)
w->selected_list_item = (sint16)(_loadedTitleSequence->NumCommands - 1);
}
}
@@ -391,12 +396,12 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
}
break;*/
case WIDX_TITLE_EDITOR_SKIP_TO:
- if (playing && w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands) {
+ if (playing && w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands) {
if (gTitleScriptCommand > w->selected_list_item) {
gTitleScriptCommand = 0;
}
if (gTitleScriptCommand != w->selected_list_item) {
- for (i = gTitleScriptCommand + 1; i < _loadedTitleSequence->NumCommands; i++) {
+ for (i = gTitleScriptCommand + 1; i < (int)_loadedTitleSequence->NumCommands; i++) {
if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOAD ||
_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOADMM) {
gTitleScriptSkipLoad = i;
@@ -412,7 +417,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
case WIDX_TITLE_EDITOR_MOVE_DOWN:
defaultPreset *= 2; playing *= 2; commandEditorOpen *= 2;
if (!defaultPreset && !playing && !commandEditorOpen) {
- if (w->selected_list_item != -1 && w->selected_list_item < _loadedTitleSequence->NumCommands - 1) {
+ if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_loadedTitleSequence->NumCommands - 1) {
title_sequence_move_down_command(gCurrentTitleSequence, w->selected_list_item);
w->selected_list_item++;
}
@@ -428,25 +433,20 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
}
break;
case WIDX_TITLE_EDITOR_REPLAY:
- if (playing) {
- title_refresh_sequence();
- }
break;
case WIDX_TITLE_EDITOR_STOP:
if (playing) {
gCurrentPreviewTitleSequence = 0;
- title_refresh_sequence();
}
break;
case WIDX_TITLE_EDITOR_PLAY:
if (gCurrentTitleSequence != gCurrentPreviewTitleSequence && inTitle) {
gCurrentPreviewTitleSequence = gCurrentTitleSequence;
- title_refresh_sequence();
}
break;
case WIDX_TITLE_EDITOR_SKIP:
if (playing) {
- for (i = gTitleScriptCommand; i < _loadedTitleSequence->NumCommands; i++) {
+ for (i = gTitleScriptCommand; i < (int)_loadedTitleSequence->NumCommands; i++) {
if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOAD ||
_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_LOADMM
) {
@@ -459,7 +459,6 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
} else if (_loadedTitleSequence->Commands[i].Type == TITLE_SCRIPT_RESTART) {
gTitleScriptSkipLoad = -1;
gTitleScriptSkipTo = -1;
- title_refresh_sequence();
break;
}
}
@@ -633,13 +632,13 @@ static void window_title_editor_scrollmousedown(rct_window *w, int scrollIndex,
w->selected_list_item = -1;
switch (w->selected_tab) {
case WINDOW_TITLE_EDITOR_TAB_SAVES:
- if (index < _loadedTitleSequence->NumSaves) {
+ if (index < (int)_loadedTitleSequence->NumSaves) {
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
- if (index < _loadedTitleSequence->NumCommands) {
+ if (index < (int)_loadedTitleSequence->NumCommands) {
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
@@ -654,11 +653,11 @@ static void window_title_editor_scrollmouseover(rct_window *w, int scrollIndex,
index = y / ROW_HEIGHT;
switch (w->selected_tab) {
case WINDOW_TITLE_EDITOR_TAB_SAVES:
- if (index < _loadedTitleSequence->NumSaves)
+ if (index < (int)_loadedTitleSequence->NumSaves)
_window_title_editor_highlighted_index = (sint16)index;
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
- if (index < _loadedTitleSequence->NumCommands)
+ if (index < (int)_loadedTitleSequence->NumCommands)
_window_title_editor_highlighted_index = (sint16)index;
break;
}
@@ -877,7 +876,7 @@ static void window_title_editor_scrollpaint_saves(rct_window *w, rct_drawpixelin
int x = 0;
int y = 0;
bool inTitle = ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO);
- for (int i = 0; i < _loadedTitleSequence->NumSaves; i++, y += ROW_HEIGHT) {
+ for (int i = 0; i < (int)_loadedTitleSequence->NumSaves; i++, y += ROW_HEIGHT) {
bool selected = false;
bool hover = false;
if (i == w->selected_list_item) {
@@ -908,7 +907,7 @@ static void window_title_editor_scrollpaint_commands(rct_window *w, rct_drawpixe
int x = 0;
int y = 0;
bool inTitle = ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO);
- for (int i = 0; i < _loadedTitleSequence->NumCommands; i++, y += ROW_HEIGHT) {
+ for (int i = 0; i < (int)_loadedTitleSequence->NumCommands; i++, y += ROW_HEIGHT) {
TitleCommand * command = &_loadedTitleSequence->Commands[i];
bool selected = false;
bool hover = false;
diff --git a/src/windows/title_menu.c b/src/windows/title_menu.c
index 1989be02f8..a1dd008f24 100644
--- a/src/windows/title_menu.c
+++ b/src/windows/title_menu.c
@@ -23,7 +23,7 @@
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../sprites.h"
-#include "../title.h"
+#include "../title/TitleScreen.h"
#include "dropdown.h"
enum {
diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c
index 478a669692..ff72a3070c 100644
--- a/src/windows/title_scenarioselect.c
+++ b/src/windows/title_scenarioselect.c
@@ -24,7 +24,6 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../interface/themes.h"
-#include "../title.h"
#include "../util/util.h"
#define INITIAL_NUM_UNLOCKED_SCENARIOS 5
diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c
index 0cf120f475..f0f0491ebd 100644
--- a/src/windows/top_toolbar.c
+++ b/src/windows/top_toolbar.c
@@ -31,8 +31,8 @@
#include "../network/twitch.h"
#include "../peep/staff.h"
#include "../scenario.h"
-#include "../title.h"
#include "../sprites.h"
+#include "../title/TitleScreen.h"
#include "../util/util.h"
#include "../world/banner.h"
#include "../world/scenery.h"