diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index f948462979..831470a580 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -88,6 +88,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index 181b6cd8bd..3b8344d289 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -257,6 +257,9 @@
Source Files
+
+ Windows
+
diff --git a/src/game.c b/src/game.c
index b83169e0d8..ea88c3a7c2 100644
--- a/src/game.c
+++ b/src/game.c
@@ -29,6 +29,7 @@
#include "peep.h"
#include "screenshot.h"
#include "strings.h"
+#include "title.h"
#include "tutorial.h"
#include "widget.h"
#include "window.h"
@@ -986,6 +987,8 @@ static int game_check_affordability(int cost)
return ebp;
}
+static uint32 game_do_command_table[58];
+
/**
*
* rct2: 0x006677F2
@@ -1004,9 +1007,6 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
original_edi = edi;
original_ebp = ebp;
- RCT2_CALLFUNC_X(0x006677F2, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- return ebx;
-
flags = ebx;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0xFFFF;
@@ -1016,7 +1016,7 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
ebx &= ~1;
// Primary command
- RCT2_CALLFUNC_X(RCT2_ADDRESS(0x0097B9A4, uint32)[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
cost = ebx;
if (cost != 0x80000000) {
@@ -1039,7 +1039,7 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
}
// Secondary command
- RCT2_CALLFUNC_X(RCT2_ADDRESS(0x0097B9A4, uint32)[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
edx = ebx;
if (edx != 0x80000000 && edx < cost)
@@ -1075,4 +1075,203 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16));
return 0x80000000;
-}
\ No newline at end of file
+}
+
+/**
+ *
+ * rct2: 0x0066DB5F
+ */
+static void game_load_or_quit()
+{
+ rct_window *w;
+ char input_bl, input_dl;
+ short input_di;
+
+ __asm mov input_bl, bl
+ __asm mov input_dl, dl
+ __asm mov input_di, di
+
+ if (!(input_bl & 1))
+ return 0;
+
+ switch (input_dl) {
+ case 0:
+ RCT2_GLOBAL(0x009A9802, uint16) = input_di;
+ window_save_prompt_open();
+ break;
+ case 1:
+ window_close_by_id(WC_SAVE_PROMPT, 0);
+ break;
+ default:
+ game_load_or_quit_no_save_prompt();
+ break;
+ }
+
+ __asm mov ebx, 0
+}
+
+/**
+ *
+ * rct2: 0x00674F40
+ */
+static int open_landscape_file_dialog()
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ RCT2_CALLFUNC_X(0x00674F40, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ return eax;
+}
+
+/**
+ *
+ * rct2: 0x00674EB6
+ */
+static int open_load_game_dialog()
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ RCT2_CALLFUNC_X(0x00674EB6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ return eax;
+}
+
+/**
+ *
+ * rct2: 0x0066DC0F
+ */
+static void load_landscape()
+{
+ if (open_landscape_file_dialog() == 0) {
+ gfx_invalidate_screen();
+ } else {
+ // string stuff
+
+ RCT2_CALLPROC_EBPSAFE(0x006758C0);
+ if (1) {
+ gfx_invalidate_screen();
+ // game_loop_iteration
+ } else {
+ RCT2_GLOBAL(0x009DEA66, uint16) = 0;
+ // game_loop_iteration
+ }
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066DBB7
+ */
+static void load_game()
+{
+ if (open_load_game_dialog() == 0) {
+ gfx_invalidate_screen();
+ } else {
+ // string stuff
+
+ RCT2_CALLPROC_EBPSAFE(0x00675E1B);
+ if (1) {
+ gfx_invalidate_screen();
+ // game_loop_iteration
+ } else {
+ RCT2_GLOBAL(0x009DEA66, uint16) = 0;
+ // game_loop_iteration
+ }
+ }
+}
+
+/**
+ *
+ * rct2: 0x006E3879
+ */
+static void rct2_exit()
+{
+ RCT2_CALLPROC_EBPSAFE(0x006E3879);
+}
+
+/**
+ *
+ * rct2: 0x0066DB79
+ */
+void game_load_or_quit_no_save_prompt()
+{
+ if (RCT2_GLOBAL(0x009A9802, uint16) < 1) {
+ game_do_command(0, 1, 0, 1, 5, 0, 0);
+ RCT2_CALLPROC_EBPSAFE(0x006EE281); // tool_cancel
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
+ load_landscape();
+ else
+ load_game();
+ } else if (RCT2_GLOBAL(0x009A9802, uint16) == 1) {
+ game_do_command(0, 1, 0, 1, 5, 0, 0);
+ if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
+ RCT2_CALLPROC_EBPSAFE(0x0040705E);
+ RCT2_GLOBAL(0x009DE518, uint32) &= ~(1 << 5);
+ }
+ title_load();
+ // game_loop_iteration
+ } else {
+ rct2_exit();
+ }
+}
+
+#pragma region Game command function table
+
+static uint32 game_do_command_table[58] = {
+ 0x006B2FC5,
+ 0x0066397F,
+ 0x00667C15,
+ 0x006C511D,
+ 0x006C5B69,
+ 0x0066DB5F, // game_load_or_quit,
+ 0x006B3F0F,
+ 0x006B49D9,
+ 0x006B4EA6,
+ 0x006B52D4,
+ 0x006B578B,
+ 0x006B5559,
+ 0x006660A8,
+ 0x0066640B,
+ 0x006E0E01,
+ 0x006E08F4,
+ 0x006E650F,
+ 0x006A61DE,
+ 0x006A68AE,
+ 0x006A67C0,
+ 0x00663CCD,
+ 0x006B53E9,
+ 0x00698D6C,
+ 0x0068C542,
+ 0x0068C6D1,
+ 0x0068BC01,
+ 0x006E66A0,
+ 0x006E6878,
+ 0x006C5AE9,
+ 0x006BEFA1,
+ 0x006C09D1,
+ 0x006C0B83,
+ 0x006C0BB5,
+ 0x00669C6D,
+ 0x00669D4A,
+ 0x006649BD,
+ 0x006666E7,
+ 0x00666A63,
+ 0x006CD8CE,
+ 0x00669E30,
+ 0x00669E55,
+ 0x006E519A,
+ 0x006E5597,
+ 0x006B893C,
+ 0x006B8E1B,
+ 0x0069DFB3,
+ 0x00684A7F,
+ 0x006D13FE,
+ 0x0069E73C,
+ 0x006CDEE4,
+ 0x006B9E6D,
+ 0x006BA058,
+ 0x006E0F26,
+ 0x006E56B5,
+ 0x006B909A,
+ 0x006BA16A,
+ 0x006648E3,
+ 0x0068DF91
+};
+
+#pragma endregion
\ No newline at end of file
diff --git a/src/game.h b/src/game.h
index cca9afb469..23aaff9a33 100644
--- a/src/game.h
+++ b/src/game.h
@@ -27,4 +27,6 @@ void game_logic_update();
int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
+void game_load_or_quit_no_save_prompt();
+
#endif
diff --git a/src/strings.h b/src/strings.h
index 583bc4738e..f088c56212 100644
--- a/src/strings.h
+++ b/src/strings.h
@@ -162,6 +162,8 @@ enum {
STR_CREDIT_SPARE_6 = 863,
STR_CREDIT_SPARE_7 = 864,
+ STR_QUIT_SCENARIO_EDITOR = 887,
+
STR_SCR_BMP = 890,
STR_SCREENSHOT = 891,
STR_SCREENSHOT_SAVED_AS = 892,
@@ -170,6 +172,19 @@ enum {
STR_VIEW_OPTIONS_TIP = 937,
STR_ADJUST_LAND_TIP = 938,
+ STR_SAVE_PROMPT_SAVE = 944,
+ STR_SAVE_PROMPT_DONT_SAVE = 945,
+ STR_SAVE_PROMPT_CANCEL = 946,
+
+ STR_SAVE_BEFORE_LOADING = 947,
+ STR_SAVE_BEFORE_QUITTING = 948,
+ STR_SAVE_BEFORE_QUITTING_2 = 949,
+
+ STR_LOAD_GAME = 950,
+ STR_QUIT_GAME = 951,
+ STR_QUIT_GAME_2 = 952,
+ STR_LOAD_LANDSCAPE = 953,
+
STR_CANCEL = 972,
STR_OK = 973,
diff --git a/src/window.h b/src/window.h
index d74e7e98d7..cc424965b8 100644
--- a/src/window.h
+++ b/src/window.h
@@ -250,6 +250,7 @@ enum {
WC_ERROR = 11,
WC_RIDE = 12,
WC_RIDE_CONSTRUCTION = 13,
+ WC_SAVE_PROMPT = 14,
WC_RIDE_LIST = 15,
WC_CONSTRUCT_RIDE = 16,
WC_SCENERY = 18,
@@ -324,6 +325,7 @@ void window_main_open();
void window_game_top_toolbar_open();
void window_game_bottom_toolbar_open();
void window_about_open();
+void window_save_prompt_open();
void window_title_menu_open();
void window_title_exit_open();
void window_title_logo_open();
diff --git a/src/window_save_prompt.c b/src/window_save_prompt.c
new file mode 100644
index 0000000000..35c95a7797
--- /dev/null
+++ b/src/window_save_prompt.c
@@ -0,0 +1,192 @@
+/*****************************************************************************
+ * 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 "game.h"
+#include "rct2.h"
+#include "strings.h"
+#include "sprites.h"
+#include "tutorial.h"
+#include "widget.h"
+#include "window.h"
+
+static enum WINDOW_SAVE_PROMPT_WIDGET_IDX {
+ WIDX_BACKGROUND,
+ WIDX_TITLE,
+ WIDX_CLOSE,
+ WIDX_3,
+ WIDX_SAVE,
+ WIDX_DONT_SAVE,
+ WIDX_CANCEL
+};
+
+static rct_widget window_save_prompt_widgets[] = {
+ { WWT_FRAME, 0, 0, 259, 0, 49, -1, STR_NONE }, // panel / background
+ { WWT_CAPTION, 0, 1, 258, 1, 14, 0, STR_WINDOW_TITLE_TIP }, // title bar
+ { WWT_CLOSEBOX, 0, 247, 257, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
+ { WWT_12, 0, 2, 257, 19, 30, 0, STR_NONE }, //
+ { WWT_DROPDOWN_BUTTON, 0, 8, 85, 35, 46, STR_SAVE_PROMPT_SAVE, STR_NONE }, // save
+ { WWT_DROPDOWN_BUTTON, 0, 91, 168, 35, 46, STR_SAVE_PROMPT_DONT_SAVE, STR_NONE }, // don't save
+ { WWT_DROPDOWN_BUTTON, 0, 174, 251, 35, 46, STR_SAVE_PROMPT_CANCEL, STR_NONE }, // cancel
+ { WIDGETS_END },
+};
+
+static void window_save_prompt_emptysub() { }
+static void window_save_prompt_close();
+static void window_save_prompt_mouseup();
+static void window_save_prompt_paint();
+
+static uint32 window_save_prompt_events[] = {
+ window_save_prompt_close,
+ window_save_prompt_mouseup,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_emptysub,
+ window_save_prompt_paint,
+ window_save_prompt_emptysub
+};
+
+/**
+ *
+ * rct2: 0x0066DCBE
+ */
+void window_save_prompt_open()
+{
+ int stringId;
+ rct_window* window;
+
+ // Check if window is already open
+ window = window_bring_to_front_by_id(WC_SAVE_PROMPT, 0);
+ if (window == NULL) {
+ window = window_create(
+ (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2) - 130,
+ max(28, (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) / 2) - 25),
+ 260,
+ 50,
+ window_save_prompt_events,
+ WC_SAVE_PROMPT,
+ 0
+ );
+
+ window->widgets = window_save_prompt_widgets;
+ window->enabled_widgets =
+ (1 << WIDX_CLOSE) |
+ (1 << WIDX_SAVE) |
+ (1 << WIDX_DONT_SAVE) |
+ (1 << WIDX_CANCEL);
+ window_init_scroll_widgets(window);
+ window->colours[0] = 154;
+ window->flags |= WF_TRANSPARENT;
+
+ // Pause the game
+ RCT2_GLOBAL(0x009DEA6E, uint8) |= 2;
+ RCT2_CALLPROC_EBPSAFE(0x006BABB4);
+ window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
+ }
+
+ stringId = RCT2_GLOBAL(0x009A9802, uint16) + STR_LOAD_GAME;
+ if (stringId == STR_LOAD_GAME && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
+ stringId = STR_LOAD_LANDSCAPE;
+ if (stringId == STR_QUIT_GAME && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
+ stringId = STR_QUIT_SCENARIO_EDITOR;
+ window_save_prompt_widgets[WIDX_TITLE].image = stringId;
+ window_save_prompt_widgets[WIDX_3].image = RCT2_GLOBAL(0x009A9802, uint16) + STR_SAVE_BEFORE_LOADING;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0D) {
+ game_load_or_quit_no_save_prompt();
+ return;
+ }
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) {
+ RCT2_CALLPROC_EBPSAFE(0x0066EE54);
+ game_load_or_quit_no_save_prompt();
+ return;
+ } else {
+ tutorial_stop();
+ game_load_or_quit_no_save_prompt();
+ return;
+ }
+ }
+
+ if (RCT2_GLOBAL(0x009DEA66, uint16) < 3840) {
+ game_load_or_quit_no_save_prompt();
+ return;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066DF17
+ */
+static void window_save_prompt_close()
+{
+ // Unpause the game
+ RCT2_GLOBAL(0x009DEA6E, uint8) &= ~2;
+ RCT2_CALLPROC_EBPSAFE(0x006BABD8);
+ window_invalidate_by_id(0x80 | WC_TOP_TOOLBAR, 0);
+}
+
+/**
+ *
+ * rct2: 0x0066DDF2
+ */
+static void window_save_prompt_mouseup()
+{
+ short widgetIndex;
+ rct_window *w;
+
+ __asm mov widgetIndex, dx
+ __asm mov w, esi
+
+ // TODO
+}
+
+static void window_save_prompt_paint()
+{
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+
+ __asm mov w, esi
+ __asm mov dpi, edi
+
+ window_draw_widgets(w, dpi);
+}
\ No newline at end of file