diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 57c8cdac84..459c5bbc01 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -89,6 +89,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index f6db243fe2..c5dcc45474 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -260,6 +260,9 @@
Windows
+
+ Windows
+
diff --git a/readme.md b/readme.md
index 4671196629..266984bbaf 100644
--- a/readme.md
+++ b/readme.md
@@ -49,7 +49,7 @@ The aim is to decompile RollerCoaster Tycoon 2 fully into C so that it can remai
1. Checkout the repository. This can be done using [GitHub Windows](https://windows.github.com/) or [other tools](https://help.github.com/articles/which-remote-url-should-i-use).
2. Download [SDL2 development library for Visual C++]((http://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip)) and copy it to a new directory called "sdl" in the repository. This directory should contain "include". The path should be something like ```\GitHub\OpenRCT2\sdl\include\```.
3. Open the solution in the projects directory (**openrct2.vcxproj**) with Visual C++.
-4. In *rct2.c*, ```GAME_PATH``` can be edited to reflect your RollerCoaster Tycoon 2 installation. Each slash needs to be marked twice, like this: ```C:\\Program Files (x86)\\GOGcom\\RollerCoaster Tycoon 2\\RollerCoaster Tycoon 2 Triple Thrill Pack```. Existing registry keys and the original RCT2 executable are not required.
+4. In *rct2.c*, ```GAME_PATH``` **must** be edited to reflect your RollerCoaster Tycoon 2 installation. Each slash needs to be marked twice, like this: ```C:\\Program Files (x86)\\GOGcom\\RollerCoaster Tycoon 2\\RollerCoaster Tycoon 2 Triple Thrill Pack```. Existing registry keys and the original RCT2 executable are not required.
5. [Select the 'Release' configuration](http://msdn.microsoft.com/en-us/library/wx0123s5.aspx) and click Build -> Rebuild Solution. The dropdown menu to enable the 'release' configuration is towards the top of the VS Express window, near the "TEST" menu.
6. Start debugging. Press the "Local Windows Debugger" button with a green "play" icon next to it. If warned about *openrct2.exe* not having debug information, just continue.
7. If the game crashes, you may need to press the red, square button along the top of VS Express (for "stop") to stop the program.
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/peep.h b/src/peep.h
index f78b5d1f43..6bd275f025 100644
--- a/src/peep.h
+++ b/src/peep.h
@@ -45,6 +45,32 @@ enum PEEP_THOUGHT_TYPE {
PEEP_THOUGHT_TYPE_NONE = 255
};
+enum PEEP_STATE {
+
+ PEEP_STATE_QUEUING_FRONT = 2,
+ PEEP_STATE_ON_RIDE = 3,
+ PEEP_STATE_LEAVING_RIDE = 4,
+ PEEP_STATE_WALKING = 5,
+ PEEP_STATE_QUEUING = 6,
+ PEEP_STATE_ENTERING_RIDE = 7,
+ PEEP_STATE_SITTING = 8,
+ PEEP_STATE_PICKED = 9,
+ PEEP_STATE_PATROLLING = 10, // Not sure
+ PEEP_STATE_MOPING = 11,
+ PEEP_STATE_SWEEPING = 12,
+ PEEP_STATE_ENTERING_PARK = 13,
+ PEEP_STATE_LEAVING_PARK = 14,
+ PEEP_STATE_ANSWERING = 15,
+ PEEP_STATE_FIXING = 16,
+ PEEP_STATE_BUYING = 17,
+ PEEP_STATE_WATCHING = 18,
+ PEEP_STATE_EMPTYING_BIN = 19,
+
+ PEEP_STATE_WATERING = 21,
+ PEEP_STATE_HEADING_TO_INSPECTION = 22,
+ PEEP_STATE_INSPECTING = 23
+};
+
typedef struct {
uint8 type;
uint8 item;
@@ -87,24 +113,38 @@ typedef struct {
uint8 var_03D;
uint8 hunger; // 0x3E
uint8 thirst; // 0x3F
- uint8 pad_040[0x28];
+ uint8 bathroom; // 0x40
+ uint8 pad_041[0x27];
uint8 current_ride; // 0x68
uint8 pad_6A; // 0x6A Part of current_ride?
uint8 current_train; // 0x6B
uint8 current_car; // 0x6C
uint8 current_seat; // 0x6D
- uint8 pad_6E[0x2E];
+ uint8 pad_6E[0x0E];
+ uint8 rides_been_on[32]; // 0x7C
uint32 id; // 0x9C
- uint8 pad_A0[0x10];
+ sint32 cash_in_pocket; // 0xA0
+ sint32 cash_spent; // 0xA4
+ uint8 pad_A8[8];
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
uint16 pad_C4;
uint8 var_C6;
uint8 pad_C7;
- uint32 var_C8;
- uint8 pad_CC[0x2A];
+ uint32 var_C8; // Bit 11 tracking, Bit 8 leaving the park
+ uint8 var_CC; // Bit 0 mad, bit 1 Ice Cream
+ uint8 pad_CD[0x18];
+ uint16 paid_to_enter; // 0xE5
+ uint16 paid_on_rides; // 0xE7
+ uint16 paid_on_food; // 0xE9
+ uint16 paid_on_souvenirs; // 0xEB
+ uint8 no_of_food; // 0xEC
+ uint8 no_of_drinks; // 0xED
+ uint8 no_of_souvenirs; // 0xEE
+ uint8 pad_EF[0x07];
uint8 balloon_colour; // 0xF6
uint8 umbrella_colour; // 0xF7
uint8 hat_colour; // 0xF8
+ uint8 favourite_ride; // 0xF9
} rct_peep;
int peep_get_staff_count();
diff --git a/src/rct2.c b/src/rct2.c
index df687dca0c..e8f5ef2e92 100644
--- a/src/rct2.c
+++ b/src/rct2.c
@@ -191,6 +191,53 @@ void rct2_update()
rct2_update_2();
}
+void check_cmdline_arg()
+{
+ if(RCT2_GLOBAL(0x009AC310, uint32) == 0xFFFFFFFF)
+ return;
+
+ char *arg = RCT2_GLOBAL(0x009AC310, char *);
+ char processed_arg[255];
+ int len, i, j;
+ int quote = 0;
+ int last_period = 0;
+
+ RCT2_GLOBAL(0x009AC310, uint32) = 0xFFFFFFFF;
+ len = strlen(arg);
+
+ for(i = 0, j = 0; i < len; i ++)
+ {
+ if(arg[i] == '\"')
+ {
+ if(quote)
+ quote = 0;
+ else
+ quote = 1;
+ continue;
+ }
+ if(arg[i] == ' ' && !quote)
+ break;
+ if(arg[i] == '.')
+ last_period = i;
+ processed_arg[j ++] = arg[i];
+ }
+ processed_arg[j ++] = 0;
+
+ if(!stricmp(processed_arg + last_period, "sv6"))
+ {
+ strcpy(0x00141EF68, processed_arg);
+ RCT2_CALLPROC_EBPSAFE(0x00675E1B); //load_saved_game
+ }
+ else if(!stricmp(processed_arg + last_period, "sc6"))
+ {
+ //TODO: scenario install
+ }
+ else if(!stricmp(processed_arg + last_period, "td6") || !stricmp(processed_arg + last_period, "td4"))
+ {
+ //TODO: track design install
+ }
+}
+
void rct2_update_2()
{
int tick, tick2;
@@ -213,6 +260,7 @@ void rct2_update_2()
// TODO: screenshot countdown process
+ check_cmdline_arg();
// Screens
if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0)
intro_update();
diff --git a/src/strings.h b/src/strings.h
index f2093860d8..a24ae919d1 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 5ca4a91f92..8d1104e48c 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,
@@ -328,6 +329,7 @@ void window_game_top_toolbar_open();
void window_game_bottom_toolbar_open();
void window_about_open();
void window_footpath_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_cheats.c b/src/window_cheats.c
index 8e09e207cc..ae02e6e2ac 100644
--- a/src/window_cheats.c
+++ b/src/window_cheats.c
@@ -21,13 +21,17 @@
#include
#include "addresses.h"
#include "park.h"
+#include "peep.h"
#include "strings.h"
+#include "sprite.h"
#include "sprites.h"
#include "widget.h"
#include "window.h"
+
#define WW 200
#define WH 128
+#define CHEATS_MONEY_INCREMENT 10000
enum {
WINDOW_CHEATS_PAGE_MONEY,
@@ -41,10 +45,11 @@ static enum WINDOW_CHEATS_WIDGET_IDX {
WIDX_PAGE_BACKGROUND,
WIDX_TAB_1,
WIDX_TAB_2,
- WIDX_HIGH_MONEY
+ WIDX_HIGH_MONEY,
+ WIDX_HAPPY_GUESTS = 6 //Same as HIGH_MONEY as it is also the 6th widget but on a different page
};
-static rct_widget window_cheats_widgets[] = {
+static rct_widget window_cheats_money_widgets[] = {
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, 65535}, // panel / background
{ WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP}, // title bar
{ WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP}, // close x button
@@ -55,15 +60,33 @@ static rct_widget window_cheats_widgets[] = {
{ WIDGETS_END },
};
+static rct_widget window_cheats_guests_widgets[] = {
+ { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, 65535 }, // panel / background
+ { WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP }, // title bar
+ { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP }, // close x button
+ { WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel
+ { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1
+ { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2
+ { WWT_CLOSEBOX, 1, 4, 74, 47, 63, 2376, 2376 }, // happy guests
+ { WIDGETS_END },
+};
+
+static rct_widget *window_cheats_page_widgets[] = {
+ window_cheats_money_widgets,
+ window_cheats_guests_widgets
+};
+
static void window_cheats_emptysub() { }
-static void window_cheats_mouseup();
+static void window_cheats_money_mouseup();
+static void window_cheats_guests_mouseup();
static void window_cheats_update();
static void window_cheats_invalidate();
static void window_cheats_paint();
+static void window_cheats_set_page(rct_window *w, int page);
-static uint32 window_cheats_events[] = {
+static uint32 window_cheats_money_events[] = {
window_cheats_emptysub,
- window_cheats_mouseup,
+ window_cheats_money_mouseup,
window_cheats_emptysub,
window_cheats_emptysub,
window_cheats_emptysub,
@@ -92,6 +115,47 @@ static uint32 window_cheats_events[] = {
window_cheats_emptysub
};
+static uint32 window_cheats_guests_events[] = {
+ window_cheats_emptysub,
+ window_cheats_guests_mouseup,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_update,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_emptysub,
+ window_cheats_invalidate,
+ window_cheats_paint,
+ window_cheats_emptysub
+};
+
+static uint32 *window_cheats_page_events[] = {
+ window_cheats_money_events,
+ window_cheats_guests_events,
+};
+
+static uint32 window_cheats_page_enabled_widgets[] = {
+ (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_HIGH_MONEY),
+ (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_HAPPY_GUESTS)
+};
+
static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w);
void window_cheats_open()
@@ -103,18 +167,17 @@ void window_cheats_open()
if (window != NULL)
return;
- window = window_create(32, 32, WW, WH, window_cheats_events, WC_CHEATS, 0);
- window->widgets = window_cheats_widgets;
- window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_HIGH_MONEY);
+ window = window_create(32, 32, WW, WH, window_cheats_money_events, WC_CHEATS, 0);
+ window->widgets = window_cheats_money_widgets;
+ window->enabled_widgets = window_cheats_page_enabled_widgets[0];
window_init_scroll_widgets(window);
-
window->page = WINDOW_CHEATS_PAGE_MONEY;
window->colours[0] = 1;
window->colours[1] = 19;
window->colours[2] = 19;
}
-static void window_cheats_mouseup()
+static void window_cheats_money_mouseup()
{
int i;
short widgetIndex;
@@ -127,11 +190,53 @@ static void window_cheats_mouseup()
case WIDX_CLOSE:
window_close(w);
break;
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ window_cheats_set_page(w, widgetIndex - WIDX_TAB_1);
+ break;
case WIDX_HIGH_MONEY:
i = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32));
- i += 100000;
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(i);
+ if (i < INT_MAX - CHEATS_MONEY_INCREMENT) {
+ i += CHEATS_MONEY_INCREMENT;
+ }
+ else {
+ i = INT_MAX;
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(i);
+ window_invalidate_by_id(0x40 | WC_BOTTOM_TOOLBAR, 0);
+ break;
+ }
+}
+
+static void window_cheats_guests_mouseup()
+{
+ int i;
+ short widgetIndex;
+ rct_window *w;
+
+ __asm mov widgetIndex, dx
+ __asm mov w, esi
+ rct_peep* peep;
+ uint16 sprite_idx;
+
+ switch (widgetIndex) {
+ case WIDX_CLOSE:
+ window_close(w);
+ break;
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ window_cheats_set_page(w, widgetIndex - WIDX_TAB_1);
+ break;
+ case WIDX_HAPPY_GUESTS:
+ for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
+ peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
+ if (peep->type != PEEP_TYPE_GUEST)
+ continue;
+ if (peep->var_2A != 0)
+ continue;
+ peep->happiness = 255;
+ }
window_invalidate_by_id(0x40 | WC_BOTTOM_TOOLBAR, 0);
break;
}
@@ -144,7 +249,7 @@ static void window_cheats_update()
__asm mov w, esi
w->var_48E++;
- widget_invalidate(w->classification, w->number, WIDX_TAB_1);
+ widget_invalidate(w->classification, w->number, WIDX_TAB_1+w->page);
}
static void window_cheats_invalidate()
@@ -153,9 +258,14 @@ static void window_cheats_invalidate()
rct_window *w;
__asm mov w, esi
-
strcpy((char*)0x009BC677, "Cheats");
+ rct_widget **widgets = window_cheats_page_widgets[w->page];
+ if (w->widgets != widgets) {
+ w->widgets = widgets;
+ window_init_scroll_widgets(w);
+ }
+
// Set correct active tab
for (i = 0; i < 7; i++)
w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i));
@@ -190,7 +300,19 @@ static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
if (!(w->disabled_widgets & (1 << WIDX_TAB_2))) {
sprite_idx = 5568;
if (w->page == WINDOW_CHEATS_PAGE_GUESTS)
- sprite_idx += w->var_48E / 4;
+ sprite_idx += (w->var_48E / 2) % 8;
gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_2].left, w->y + w->widgets[WIDX_TAB_2].top);
}
}
+
+static void window_cheats_set_page(rct_window *w, int page)
+{
+ w->page = page;
+
+ w->enabled_widgets = window_cheats_page_enabled_widgets[page];
+
+ w->event_handlers = window_cheats_page_events[page];
+ w->widgets = window_cheats_page_widgets[page];
+
+ window_invalidate(w);
+}
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