diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index ed5c5a5c55..a436c6a336 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -44,11 +44,13 @@
+
+
@@ -99,6 +101,7 @@
Level3
Disabled
true
+ 1Byte
true
@@ -113,6 +116,7 @@
true
true
MultiThreaded
+ 1Byte
true
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index 2d18f28aab..d76e652147 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -116,6 +116,12 @@
Windows
+
+ Source Files
+
+
+ Windows
+
diff --git a/src/addresses.h b/src/addresses.h
index 52ca4bc08b..9f9943aaee 100644
--- a/src/addresses.h
+++ b/src/addresses.h
@@ -108,4 +108,29 @@ static void RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx,
}
}
+static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp)
+{
+ __asm {
+ push ebp
+ push address
+ mov eax, [_eax]
+ mov ebx, [_ebx]
+ mov ecx, [_ecx]
+ mov edx, [_edx]
+ mov esi, [_esi]
+ mov edi, [_edi]
+ mov ebp, [_ebp]
+ call[esp]
+ add esp, 4
+ pop ebp
+ // mov[_ebp], ebp
+ mov[_edi], edi
+ mov[_esi], esi
+ mov[_edx], edx
+ mov[_ecx], ecx
+ mov[_ebx], ebx
+ mov [_eax], eax
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/intro.c b/src/intro.c
index fd91386b3f..3c18041ab5 100644
--- a/src/intro.c
+++ b/src/intro.c
@@ -24,6 +24,7 @@
#include "intro.h"
#include "rct2.h"
#include "osinterface.h"
+#include "sprites.h"
#include "strings.h"
static void screen_intro_process_mouse_input();
@@ -103,10 +104,10 @@ void intro_update()
129);
// Draw the logo
- gfx_draw_sprite(screenDPI, 0x5ABA, (screenWidth / 2) - 320 + 69, _tick_counter + 69);
- gfx_draw_sprite(screenDPI, 0x5ABB, (screenWidth / 2) - 320 + 319, _tick_counter + 69);
- gfx_draw_sprite(screenDPI, 0x5ABC, (screenWidth / 2) - 320 + 69, _tick_counter + 319);
- gfx_draw_sprite(screenDPI, 0x5ABD, (screenWidth / 2) - 320 + 319, _tick_counter + 319);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_INFOGRAMES_00, (screenWidth / 2) - 320 + 69, _tick_counter + 69);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_INFOGRAMES_10, (screenWidth / 2) - 320 + 319, _tick_counter + 69);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_INFOGRAMES_01, (screenWidth / 2) - 320 + 69, _tick_counter + 319);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_INFOGRAMES_11, (screenWidth / 2) - 320 + 319, _tick_counter + 319);
// Check if logo is off the screen .ish
if (_tick_counter > 520) {
@@ -144,8 +145,8 @@ void intro_update()
gfx_clear(screenDPI, 10);
// Draw Chris Sawyer logo
- gfx_draw_sprite(screenDPI, 0x5AAF, (screenWidth / 2) - 320 + 70, _tick_counter);
- gfx_draw_sprite(screenDPI, 0x5AB0, (screenWidth / 2) - 320 + 320, _tick_counter);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_CHRIS_SAWYER_00, (screenWidth / 2) - 320 + 70, _tick_counter);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_CHRIS_SAWYER_10, (screenWidth / 2) - 320 + 320, _tick_counter);
// Check if logo is at 259 pixels
if (_tick_counter == 259) {
@@ -170,12 +171,12 @@ void intro_update()
gfx_clear(screenDPI, 245);
// Draw RollerCoaster Tycoon 2 logo
- gfx_draw_sprite(screenDPI, 0x5AB2, (screenWidth / 2) - 320 + 0, 0);
- gfx_draw_sprite(screenDPI, 0x5AB3, (screenWidth / 2) - 320 + 220, 0);
- gfx_draw_sprite(screenDPI, 0x5AB4, (screenWidth / 2) - 320 + 440, 0);
- gfx_draw_sprite(screenDPI, 0x5AB5, (screenWidth / 2) - 320 + 0, 240);
- gfx_draw_sprite(screenDPI, 0x5AB6, (screenWidth / 2) - 320 + 220, 240);
- gfx_draw_sprite(screenDPI, 0x5AB7, (screenWidth / 2) - 320 + 440, 240);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_00, (screenWidth / 2) - 320 + 0, 0);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_10, (screenWidth / 2) - 320 + 220, 0);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_20, (screenWidth / 2) - 320 + 440, 0);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_01, (screenWidth / 2) - 320 + 0, 240);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_11, (screenWidth / 2) - 320 + 220, 240);
+ gfx_draw_sprite(screenDPI, SPR_INTRO_LOGO_21, (screenWidth / 2) - 320 + 440, 240);
// Set palette thing
gfx_transpose_palette(23224, 0);
diff --git a/src/widget.c b/src/widget.c
new file mode 100644
index 0000000000..09bae1fc11
--- /dev/null
+++ b/src/widget.c
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * 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 "widget.h"
+#include "window.h"
+
+/**
+ *
+ * rct2: 0x006EAF26
+ */
+void widget_scroll_update_thumbs(rct_window *w, int widget_index)
+{
+ rct_widget* widget;
+ rct_scroll* scroll;
+ int x, y, view_size;
+
+ widget = &w->widgets[widget_index];
+ scroll = &w->scrolls[window_get_scroll_data_index(w, widget_index)];
+
+ if (scroll->flags & HSCROLLBAR_VISIBLE) {
+ view_size = widget->right - widget->left - 21;
+ if (scroll->flags & VSCROLLBAR_VISIBLE)
+ view_size -= 11;
+ x = scroll->h_left * view_size;
+ if (scroll->h_right != 0)
+ x /= scroll->h_right;
+ scroll->h_thumb_left = x + 11;
+
+ x = widget->right - widget->left - 2;
+ if (scroll->flags & VSCROLLBAR_VISIBLE)
+ x -= 11;
+ x += scroll->h_left;
+ if (scroll->h_right != 0)
+ x = (x * view_size) / scroll->h_right;
+ x += 11;
+ view_size += 10;
+ scroll->h_thumb_right = min(x, view_size);
+ }
+
+ if (scroll->flags & VSCROLLBAR_VISIBLE) {
+ view_size = widget->bottom - widget->top - 21;
+ if (scroll->flags & HSCROLLBAR_VISIBLE)
+ view_size -= 11;
+ y = scroll->v_top * view_size;
+ if (scroll->v_bottom != 0)
+ y /= scroll->v_bottom;
+ scroll->v_thumb_top = y + 11;
+
+ y = widget->bottom - widget->top - 2;
+ if (scroll->flags & HSCROLLBAR_VISIBLE)
+ y -= 11;
+ y += scroll->v_top;
+ if (scroll->v_bottom != 0)
+ y = (y * view_size) / scroll->v_bottom;
+ y += 11;
+ view_size += 10;
+ scroll->v_thumb_bottom = min(y, view_size);
+ }
+}
\ No newline at end of file
diff --git a/src/widget.h b/src/widget.h
index a65ba755dd..face7f482c 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -21,6 +21,8 @@
#ifndef _WIDGET_H_
#define _WIDGET_H_
+#include "window.h"
+
typedef enum {
WWT_EMPTY = 0,
WWT_FRAME = 1,
@@ -42,4 +44,6 @@ typedef enum {
} WINDOW_WIDGET_TYPES;
#define WIDGETS_END WWT_LAST, 0, 0, 0, 0, 0, 0, 0
+void widget_scroll_update_thumbs(rct_window *w, int widget_index);
+
#endif
\ No newline at end of file
diff --git a/src/window.c b/src/window.c
index de0b938149..fd423e1bb5 100644
--- a/src/window.c
+++ b/src/window.c
@@ -21,6 +21,7 @@
#include "addresses.h"
#include "audio.h"
#include "rct2.h"
+#include "widget.h"
#include "window.h"
#define RCT2_FIRST_WINDOW (RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window))
@@ -206,5 +207,108 @@ void window_invalidate(rct_window *window)
*/
void window_init_scroll_widgets(rct_window *w)
{
- RCT2_CALLPROC_X(0x006EAEB8, 0, 0, 0, 0, w, 0, 0);
+ rct_widget* widget;
+ rct_scroll* scroll;
+ int widget_index, scroll_index;
+
+ widget_index = 0;
+ scroll_index = 0;
+ for (widget = w->widgets; widget->type != WWT_LAST; widget++) {
+ if (widget->type != WWT_SCROLL) {
+ widget_index++;
+ continue;
+ }
+
+ scroll = &w->scrolls[scroll_index];
+
+ {
+ int _eax = 0, _ebx = scroll_index * sizeof(rct_scroll), _ecx = 0, _edx = 0, _esi = w, _edi = widget_index * sizeof(rct_widget), _ebp = 0;
+ RCT2_CALLFUNC_X(w->event_handlers[WE_SCROLL_GETSIZE], & _eax, &_ebx, &_ecx, &_edx, &_esi, &_edi, &_ebp);
+
+ scroll->h_left = 0;
+ scroll->h_right = _ecx + 1;
+ scroll->v_top = 0;
+ scroll->v_bottom = _edx + 1;
+ }
+
+ if (widget->image & 0x01)
+ scroll->flags |= HSCROLLBAR_VISIBLE;
+ if (widget->image & 0x02)
+ scroll->flags |= VSCROLLBAR_VISIBLE;
+
+ widget_scroll_update_thumbs(w, widget_index);
+
+ widget_index++;
+ scroll_index++;
+ }
+}
+
+int window_get_scroll_data_index(rct_window *w, int widget_index)
+{
+ int i, result;
+
+ result = 0;
+ for (i = 0; i < widget_index; i++) {
+ if (w->widgets[i].type == WWT_SCROLL)
+ result++;
+ }
+ return result;
+}
+
+/**
+ *
+ * rct2: 0x006ED78A
+ * cls (cl)
+ * number (dx)
+ */
+rct_window *window_bring_to_front_by_id(rct_windowclass cls, rct_windownumber number)
+{
+ rct_window* w;
+
+ w = window_find_by_id(cls, number);
+ if (w != NULL) {
+ w->flags |= WF_WHITE_BORDER_MASK;
+ window_invalidate(w);
+ w = window_bring_to_front(w);
+ }
+
+ return w;
+}
+
+/**
+ *
+ * rct2: 0x006ECDA4
+ */
+rct_window *window_bring_to_front(rct_window *w)
+{
+ int i;
+ rct_window* v, t;
+
+ if (w->flags & 0x03)
+ return w;
+
+ for (v = RCT2_LAST_WINDOW; v >= RCT2_FIRST_WINDOW; v--)
+ if (!(v->flags & 2))
+ break;
+
+ if (v >= RCT2_FIRST_WINDOW && w != v) {
+ do {
+ t = *w;
+ *w = *(w + 1);
+ *(w + 1) = t;
+ w++;
+ } while (w != v);
+
+ window_invalidate(w);
+ }
+
+ if (w->x + w->width < 20) {
+ i = 20 - w->x;
+ w->x += i;
+ if (w->viewport != NULL)
+ w->viewport->x += i;
+ window_invalidate(w);
+ }
+
+ return w;
}
\ No newline at end of file
diff --git a/src/window.h b/src/window.h
index db2d55871f..f9409f03b9 100644
--- a/src/window.h
+++ b/src/window.h
@@ -272,5 +272,9 @@ void window_close(rct_window *window);
rct_window *window_find_by_id(rct_windowclass cls, rct_windownumber number);
void window_invalidate(rct_window *window);
void window_init_scroll_widgets(rct_window *w);
+int window_get_scroll_data_index(rct_window *w, int widget_index);
+
+rct_window *window_bring_to_front_by_id(rct_windowclass cls, rct_windownumber number);
+rct_window *window_bring_to_front(rct_window *w);
#endif
\ No newline at end of file
diff --git a/src/window_title_exit.c b/src/window_title_exit.c
index f663179b4c..2625da4a26 100644
--- a/src/window_title_exit.c
+++ b/src/window_title_exit.c
@@ -42,7 +42,7 @@ void window_title_exit_open()
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 64,
40, 64, 0x0097BEFC, WC_TITLE_EXIT, 0x02
);
- window->widgets = 0x009A9644;
+ window->widgets = window_title_exit_widgets;
window->enabled_widgets |= 1;
window_init_scroll_widgets(window);
window->flags |= 16;
diff --git a/src/window_title_logo.c b/src/window_title_logo.c
index 0939350ef8..3021d4513b 100644
--- a/src/window_title_logo.c
+++ b/src/window_title_logo.c
@@ -36,7 +36,7 @@ void window_title_logo_open()
{
int i, packs;
rct_window *window;
-
+
// Count number of expansion packs
packs = 0;
for (i = 0; i < 16; i++)
@@ -45,7 +45,7 @@ void window_title_logo_open()
// Create the window
window = window_create(0, 0, 200, 106 + (10 * packs), 0x0097BF6C, WC_TITLE_LOGO, 0x02);
- window->widgets = 0x009A9658;
+ window->widgets = 0x009A9658; // mouse move bug in original game, keep this address and no crash happens
window_init_scroll_widgets(window);
window->flags |= 16;
window->colours[0] = 129;
diff --git a/src/window_title_menu.c b/src/window_title_menu.c
index 5f257aa470..0cf43f498a 100644
--- a/src/window_title_menu.c
+++ b/src/window_title_menu.c
@@ -24,6 +24,8 @@
#include "widget.h"
#include "window.h"
+void window_levelselect_open();
+
enum {
WIDX_START_NEW_GAME,
WIDX_CONTINUE_SAVED_GAME,
@@ -39,6 +41,37 @@ static rct_widget window_title_menu_widgets[] = {
{ WIDGETS_END },
};
+static uint32 window_title_menu_events[] = {
+ 0x0066B834,
+ 0x0066B6EC,
+ 0x0066B834,
+ 0x0066B70E,
+ 0x0066B71F,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B730,
+ 0x0066B834,
+ 0x0066B834,
+ 0x0066B6E6,
+ 0x0066B834
+};
+
/**
* Creates the window containing the menu buttons on the title screen.
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
@@ -50,9 +83,9 @@ void window_title_menu_open()
window = window_create(
(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - 328) / 2,
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 142,
- 328, 82, 0x0097BE8C, WC_TITLE_MENU, 0x02
+ 328, 82, window_title_menu_events, WC_TITLE_MENU, 0x02
);
- window->widgets = 0x009A9600;
+ window->widgets = window_title_menu_widgets;
window->enabled_widgets |= (8 | 4 | 2 | 1);
window_init_scroll_widgets(window);
window->flags |= 16;
diff --git a/src/window_title_scenarioselect.c b/src/window_title_scenarioselect.c
new file mode 100644
index 0000000000..299c04a2ab
--- /dev/null
+++ b/src/window_title_scenarioselect.c
@@ -0,0 +1,73 @@
+/*****************************************************************************
+* 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 "strings.h"
+#include "sprites.h"
+#include "widget.h"
+#include "window.h"
+
+static rct_widget window_levelselect_widgets[] = {
+ { WWT_FRAME, 0, 0, 609, 0, 333, -1, STR_NONE }, // panel / background
+ { WWT_CAPTION, 0, 1, 608, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar
+ { WWT_CLOSEBOX, 0, 597, 607, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
+ { WWT_IMGBTN, 1, 0, 609, 50, 333, -1, STR_NONE }, // tab content panel
+ { WWT_TAB, 1, 3, 93, 17, 50, 0x200015BC, STR_NONE }, // tab 1
+ { WWT_TAB, 1, 94, 184, 17, 50, 0x200015BC, STR_NONE }, // tab 2
+ { WWT_TAB, 1, 185, 275, 17, 50, 0x200015BC, STR_NONE }, // tab 3
+ { WWT_TAB, 1, 276, 366, 17, 50, 0x200015BC, STR_NONE }, // tab 4
+ { WWT_TAB, 1, 367, 457, 17, 50, 0x200015BC, STR_NONE }, // tab 5
+ { WWT_SCROLL, 1, 3, 433, 54, 329, 2, STR_NONE }, // level list
+ { WIDGETS_END },
+};
+
+/**
+ *
+ * rct2: 0x006781B5
+ */
+void window_levelselect_open()
+{
+ rct_window* window;
+ int y;
+
+ if (window_bring_to_front_by_id(WC_LEVEL_SELECT, 0) != NULL)
+ return;
+
+ // Load scenario list
+ RCT2_CALLPROC_EBPSAFE(0x006775A8); // scenario_load_list();
+
+ y = (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) / 2) - 167;
+ if (y < 28)
+ y = 28;
+ window = window_create((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2) - 305, y, 610, 334, 0x0097FC4C, WC_LEVEL_SELECT, 0x0402);
+ window->widgets = window_levelselect_widgets;
+
+ window->enabled_widgets = 0x04 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100;
+ window_init_scroll_widgets(window);
+ window->colours[0] = 1;
+ window->colours[1] = 26;
+ window->colours[2] = 26;
+ window->var_480 = -1;
+ window->var_494 = -1;
+
+ RCT2_CALLPROC_EBPSAFE(0x00677C8A); // window_levelselect_init_tabs();
+
+ window->var_4AC = 0;
+}
\ No newline at end of file