OpenRCT2/src/game.c

1797 lines
50 KiB
C
Raw Normal View History

/*****************************************************************************
2014-05-09 09:47:20 +02:00
* Copyright (c) 2014 Ted John, Peter Hill
* 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 <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "addresses.h"
#include "audio.h"
#include "climate.h"
2014-04-24 22:29:57 +02:00
#include "config.h"
#include "rct2.h"
#include "game.h"
2014-05-08 00:45:16 +02:00
#include "finance.h"
2014-04-08 01:05:05 +02:00
#include "news_item.h"
2014-05-04 17:21:15 +02:00
#include "object.h"
2014-04-18 04:04:46 +02:00
#include "osinterface.h"
2014-04-03 01:22:33 +02:00
#include "peep.h"
2014-05-04 17:21:15 +02:00
#include "sawyercoding.h"
#include "scenario.h"
#include "screenshot.h"
2014-06-21 14:31:28 +02:00
#include "sprite.h"
#include "string_ids.h"
2014-05-02 23:21:08 +02:00
#include "title.h"
2014-04-26 02:16:32 +02:00
#include "tutorial.h"
2014-05-25 19:40:11 +02:00
#include "vehicle.h"
2014-05-04 17:21:15 +02:00
#include "viewport.h"
2014-04-14 15:32:05 +02:00
#include "widget.h"
#include "window.h"
#include "window_error.h"
#include "window_tooltip.h"
2014-05-25 04:02:48 +02:00
int _gameSpeed = 1;
2014-04-14 04:09:51 +02:00
void game_handle_input();
void game_handle_keyboard_input();
2014-04-14 04:09:51 +02:00
2014-04-11 03:42:39 +02:00
/**
*
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
*/
void game_create_windows()
{
window_main_open();
2014-04-11 04:58:17 +02:00
window_game_top_toolbar_open();
window_game_bottom_toolbar_open();
2014-04-11 03:42:39 +02:00
RCT2_CALLPROC_EBPSAFE(0x0066B905);
}
2014-05-28 19:11:33 +02:00
/**
*
* rct2: 0x006838BD
*/
void update_water_animation()
{
RCT2_CALLPROC_EBPSAFE(0x006838BD);
}
/**
*
* rct2: 0x00684218
*/
void update_rain_animation()
{
if (RCT2_GLOBAL(0x009ABDF2, uint8) == 0)
return;
// Draw picked-up peep
if (RCT2_GLOBAL(0x009DE550, uint32) != 0xFFFFFFFF) {
gfx_draw_sprite(
(rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI,
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32),
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16),
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16)
);
}
// Get rain draw function and draw rain
uint32 eax = RCT2_ADDRESS(0x009AC058, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8)];
if (eax != 0xFFFFFFFF && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1))
RCT2_CALLPROC_X(0x00684266, eax, 0, 0, 0, 0, 0, 0);
}
void game_update()
{
int eax, tmp;
2014-05-28 19:11:33 +02:00
// Handles picked-up peep and rain redraw
RCT2_CALLPROC_EBPSAFE(0x006843DC);
// 0x006E3AEC // screen_game_process_mouse_input();
2014-04-18 04:04:46 +02:00
// RCT2_CALLPROC_EBPSAFE(0x006E3AEC); // screen_game_process_keyboard_input();
screenshot_check();
game_handle_keyboard_input();
// do game logic
eax = RCT2_GLOBAL(0x009DE588, uint16) / 31;
if (eax == 0)
eax = 1;
if (eax > 4)
eax = 4;
2014-05-25 04:02:48 +02:00
if (_gameSpeed > 1)
eax = 1 << (_gameSpeed - 1);
if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
for (; eax > 0; eax--) {
game_logic_update();
2014-04-18 17:26:45 +02:00
RCT2_CALLPROC_EBPSAFE(0x006BD0F8); // play title screen music
/*
if (rctmem->dword_009E2D74 == 1) {
rctmem->dword_009E2D74 = 0;
break;
} else {
if (rctmem->input_state != INPUT_STATE_WIDGET_RESET && rctmem->input_state != INPUT_STATE_WIDGET_NORMAL)
break;
tmp = rctmem->dword_009DE518 & 0x80;
rctmem->dword_009DE518 &= ~0x80;
if (tmp)
break;
}
*/
}
}
RCT2_GLOBAL(0x009DE518, uint32) &= ~0x80;
RCT2_GLOBAL(0x009AC861, uint16) &= ~0x8000;
RCT2_GLOBAL(0x009AC861, uint16) &= ~0x02;
tmp = RCT2_GLOBAL(0x009AC861, uint16) & 0x01;
RCT2_GLOBAL(0x009AC861, uint16) &= ~0x01;
if (!tmp)
RCT2_GLOBAL(0x009AC861, uint16) |= 0x02;
RCT2_GLOBAL(0x009AC861, uint16) &= ~0x08;
tmp = RCT2_GLOBAL(0x009AC861, uint16) & 0x04;
RCT2_GLOBAL(0x009AC861, uint16) &= ~0x04;
if (!tmp)
RCT2_GLOBAL(0x009AC861, uint16) |= 0x04;
RCT2_CALLPROC_EBPSAFE(0x006EE77A);
2014-04-08 18:52:39 +02:00
window_update_all();
RCT2_GLOBAL(0x01388698, uint16)++;
// Input
2014-04-13 23:23:56 +02:00
RCT2_GLOBAL(0x0141F568, uint8) = RCT2_GLOBAL(0x0013CA740, uint8);
2014-04-14 04:09:51 +02:00
game_handle_input();
2014-05-28 19:11:33 +02:00
update_water_animation();
update_rain_animation();
if (RCT2_GLOBAL(0x009AAC73, uint8) != 255) {
RCT2_GLOBAL(0x009AAC73, uint8)++;
2014-04-24 22:29:57 +02:00
if (RCT2_GLOBAL(0x009AAC73, uint8) == 255)
config_save();
}
}
2014-04-11 03:42:39 +02:00
void game_logic_update()
{
short stringId, _dx;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, sint32)++;
RCT2_GLOBAL(0x00F663AC, sint32)++;
RCT2_GLOBAL(0x009DEA66, sint16)++;
if (RCT2_GLOBAL(0x009DEA66, sint16) == 0)
RCT2_GLOBAL(0x009DEA66, sint16)--;
2014-05-04 19:51:36 +02:00
sub_68B089();
scenario_update();
2014-04-29 13:18:50 +02:00
climate_update();
RCT2_CALLPROC_EBPSAFE(0x006646E1);
RCT2_CALLPROC_EBPSAFE(0x006A876D);
2014-04-03 01:22:33 +02:00
peep_update_all();
2014-05-25 19:40:11 +02:00
vehicle_update_all();
2014-04-09 12:16:35 +02:00
RCT2_CALLPROC_EBPSAFE(0x00672AA4); // update text effects
RCT2_CALLPROC_EBPSAFE(0x006ABE4C); // update rides
2014-05-25 14:59:31 +02:00
park_update();
RCT2_CALLPROC_EBPSAFE(0x00684C7A);
RCT2_CALLPROC_EBPSAFE(0x006B5A2A);
2014-04-09 12:16:35 +02:00
RCT2_CALLPROC_EBPSAFE(0x006B6456); // update ride measurements
RCT2_CALLPROC_EBPSAFE(0x0068AFAD);
2014-05-25 04:02:48 +02:00
RCT2_CALLPROC_EBPSAFE(0x006BBC6B); // vehicle and scream sounds
2014-05-25 02:08:08 +02:00
peep_update_crowd_noise();
2014-05-28 23:53:28 +02:00
climate_update_sound();
2014-04-08 01:05:05 +02:00
news_item_update_current();
2014-05-25 04:02:48 +02:00
RCT2_CALLPROC_EBPSAFE(0x0067009A); // scenario editor opening of windows for a phase
// Update windows
2014-04-08 18:52:39 +02:00
window_dispatch_update_all();
if (RCT2_GLOBAL(0x009AC31B, uint8) != 0) {
stringId = STR_UNABLE_TO_LOAD_FILE;
_dx = RCT2_GLOBAL(0x009AC31C, uint16);
if (RCT2_GLOBAL(0x009AC31B, uint8) != 254) {
stringId = RCT2_GLOBAL(0x009AC31C, uint16);
_dx = 0xFFFF;
}
RCT2_GLOBAL(0x009AC31B, uint8) = 0;
window_error_open(stringId, _dx);
}
2014-04-14 04:09:51 +02:00
}
static void game_handle_input_mouse();
2014-04-14 15:32:05 +02:00
static void game_get_next_input(int *x, int *y, int *state);
2014-04-14 04:09:51 +02:00
/**
*
* rct2: 0x006EA627
*/
void game_handle_input()
{
rct_window *w;
if (RCT2_GLOBAL(0x009DEA64, uint16) & 2) {
RCT2_GLOBAL(0x009DEA64, uint16) &= ~2;
RCT2_CALLPROC_X(0x006677F2, 0, 1, 0, 0, 5, 2, 0);
}
if (RCT2_GLOBAL(0x009ABDF2, uint8) != 0) {
for (w = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_07], 0, 0, 0, 0, (int)w, 0, 0);
2014-04-14 04:09:51 +02:00
RCT2_CALLPROC_EBPSAFE(0x006EA73F);
RCT2_CALLPROC_EBPSAFE(0x006E8346); // update_cursor_position
{
2014-05-12 03:18:08 +02:00
// int eax, ebx, ecx, edx, esi, edi, ebp;
int eax, ebx, ecx;
2014-04-14 04:09:51 +02:00
for (;;) {
2014-04-14 15:32:05 +02:00
game_get_next_input(&eax, &ebx, &ecx);
2014-04-14 04:09:51 +02:00
if (ecx == 0)
break;
2014-04-14 15:32:05 +02:00
game_handle_input_mouse(eax, ebx, ecx & 0xFF);
// RCT2_CALLPROC_X(0x006E8655, eax, ebx, ecx, 0, 0, 0, 0); // window_process_mouse_input
2014-04-14 04:09:51 +02:00
}
if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
2014-04-14 15:32:05 +02:00
game_handle_input_mouse(eax, ebx, ecx);
// RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
2014-04-14 04:09:51 +02:00
} else if (eax != 0x80000000) {
eax = clamp(0, eax, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - 1);
ebx = clamp(0, ebx, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 1);
2014-04-14 15:32:05 +02:00
game_handle_input_mouse(eax, ebx, ecx);
// RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
2014-04-14 04:09:51 +02:00
RCT2_CALLPROC_X(0x006ED833, eax, ebx, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x006ED801);
}
}
}
for (w = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_08], 0, 0, 0, 0,(int) w, 0, 0);
2014-04-14 04:09:51 +02:00
}
2014-04-14 15:32:05 +02:00
/**
*
* rct2: 0x006E83C7
*/
static void game_get_next_input(int *x, int *y, int *state)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
2014-04-18 04:04:46 +02:00
RCT2_CALLFUNC_X(0x00407074, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (eax == 0) {
*x = gCursorState.x;
*y = gCursorState.y;
*state = 0;
return;
}
2014-04-14 15:32:05 +02:00
2014-04-18 04:04:46 +02:00
*x = RCT2_GLOBAL(eax + 0, sint32);
*y = RCT2_GLOBAL(eax + 4, sint32);
*state = RCT2_GLOBAL(eax + 8, sint32);
2014-04-14 15:32:05 +02:00
2014-04-18 04:04:46 +02:00
//int eax, ebx, ecx, edx, esi, edi, ebp;
//RCT2_CALLFUNC_X(0x006E83C7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
//*x = eax & 0xFFFF;
//*y = ebx & 0xFFFF;
//*state = ecx & 0xFF;
//return;
2014-04-14 15:32:05 +02:00
2014-04-18 04:04:46 +02:00
//int on_tutorial = RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8);
//if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
// if (on_tutorial == 1) {
// } else {
// RCT2_CALLPROC_EBPSAFE(0x00407074);
// }
// if (on_tutorial == 2) {
// }
//} else {
//}
2014-04-14 15:32:05 +02:00
}
#include <windows.h>
POINT _dragPosition;
static void input_mouseover(int x, int y, rct_window *w, int widgetIndex);
static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex);
static void input_mouseover_widget_flatbutton_invalidate();
static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex);
2014-04-14 04:09:51 +02:00
/**
*
* rct2: 0x006E8655
*/
static void game_handle_input_mouse(int x, int y, int state)
{
2014-05-12 02:45:45 +02:00
rct_window *w;
2014-04-14 15:32:05 +02:00
rct_widget *widget;
int widgetIndex;
2014-04-14 04:09:51 +02:00
2014-04-14 15:32:05 +02:00
// Get window and widget under cursor position
2014-04-14 04:09:51 +02:00
w = window_find_from_point(x, y);
2014-04-14 15:32:05 +02:00
widgetIndex = w == NULL ? -1 : window_find_widget_from_point(w, x, y);
widget = widgetIndex == -1 ? 0 : &w->widgets[widgetIndex];
2014-04-14 04:09:51 +02:00
switch (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8)) {
case INPUT_STATE_RESET:
window_tooltip_reset(x, y);
// fall-through
2014-04-14 04:09:51 +02:00
case INPUT_STATE_NORMAL:
2014-04-14 15:32:05 +02:00
switch (state) {
case 0:
input_mouseover(x, y, w, widgetIndex);
2014-04-14 15:32:05 +02:00
break;
case 1:
input_leftmousedown(x, y, w, widgetIndex);
2014-04-14 15:32:05 +02:00
break;
case 3:
// Close tooltip
window_close_by_id(5, 0);
if (w != NULL)
2014-04-28 03:35:23 +02:00
w = window_bring_to_front(w);
2014-04-14 15:32:05 +02:00
if (widgetIndex == -1)
break;
if (widget->type == WWT_VIEWPORT) {
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9)
break;
w->flags &= ~(1 << 3);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_DRAG;
2014-04-14 15:32:05 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = w->classification;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = w->number;
2014-04-14 15:32:05 +02:00
RCT2_GLOBAL(0x009DE540, sint16) = 0;
// hide cursor
// RCT2_CALLPROC_X(0x00407045, 0, 0, 0, 0, 0, 0, 0);
// RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 5);
GetCursorPos(&_dragPosition);
ShowCursor(FALSE);
} else if (widget->type == WWT_SCROLL) {
}
break;
}
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_WIDGET_PRESSED:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_DRAGGING:
2014-04-25 04:02:06 +02:00
// RCT2_CALLPROC_X(0x006E8C5C, x, y, state, widgetIndex, w, widget, 0);
w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
break;
}
if (state == 0) {
y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
window_move_position(
w,
x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
);
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
} else if (state == 2) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
2014-05-12 02:45:45 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
2014-04-25 04:02:06 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
window_move_position(
w,
x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
);
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_18], 0, 0, x, y, (int)w, 0, 0);
2014-04-25 04:02:06 +02:00
}
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_VIEWPORT_DRAG:
2014-04-14 15:32:05 +02:00
{
int dx, dy;
dx = x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16);
dy = y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16);
w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
2014-04-14 15:32:05 +02:00
if (state == 0) {
rct_viewport *viewport = w->viewport;
RCT2_GLOBAL(0x009DE540, sint16) += RCT2_GLOBAL(0x009DE588, sint16);
if (viewport == NULL) {
ShowCursor(TRUE);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
} else if (dx != 0 || dy != 0) {
if (!(w->flags & (1 << 2))) {
RCT2_GLOBAL(0x009DE540, sint16) = 1000;
dx <<= viewport->zoom + 1;
dy <<= viewport->zoom + 1;
w->saved_view_x += dx;
w->saved_view_y += dy;
2014-04-14 15:32:05 +02:00
}
}
} else if (state == 4) {
ShowCursor(TRUE);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
if (RCT2_GLOBAL(0x009DE540, sint16) < 500) {
// Right click
2014-04-14 21:26:29 +02:00
{
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16);
ebx = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16);
RCT2_CALLFUNC_X(0x006EDE88, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
switch (ebx & 0xFF) {
case 2:
if (*((uint8*)edx) == 0)
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006B4857, eax, 0, ecx, 0, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 3:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006CC056, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 5:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006E08D2, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 6:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006A614A, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 7:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006A61AB, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 8:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x00666C0E, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 9:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006E57A9, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 10:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006B88DC, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
case 12:
2014-04-20 04:31:54 +02:00
RCT2_CALLPROC_X(0x006BA233, eax, 0, ecx, edx, 0, 0, 0);
2014-04-14 21:26:29 +02:00
break;
default:
break;
}
}
2014-04-14 15:32:05 +02:00
}
}
2014-04-14 21:26:29 +02:00
//
//
2014-04-14 15:32:05 +02:00
SetCursorPos(_dragPosition.x, _dragPosition.y);
// RCT2_CALLPROC_X(0x006E89C6, x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16), y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16), state, widgetIndex, w, widget, 0);
2014-04-14 04:09:51 +02:00
break;
2014-04-14 15:32:05 +02:00
}
2014-04-14 04:09:51 +02:00
case INPUT_STATE_DROPDOWN_ACTIVE:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_VIEWPORT_LEFT:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E87B4, x, y, state, widgetIndex, (int)w, (int)widget, 0);
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_SCROLL_LEFT:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E8676, x, y, state, widgetIndex, (int)w, (int)widget, 0);
2014-04-14 04:09:51 +02:00
break;
case INPUT_STATE_RESIZING:
2014-04-25 04:02:06 +02:00
// RCT2_CALLPROC_X(0x006E8B46, x, y, state, widgetIndex, w, widget, 0);
w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
break;
}
if (state != 0 && state != 2)
break;
if (state == 2) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
2014-05-12 02:45:45 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
2014-04-25 04:02:06 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
}
if (y < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 2) {
window_resize(
w,
x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
);
}
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
2014-04-14 04:09:51 +02:00
break;
case 9:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E8ACB, x, y, state, widgetIndex, (int)w, (int)widget, 0);
2014-04-14 04:09:51 +02:00
break;
}
}
/**
*
* rct2: 0x006E9253
*/
static void input_mouseover(int x, int y, rct_window *w, int widgetIndex)
{
// RCT2_CALLPROC_X(0x006E9253, x, y, state, widgetIndex, w, widget, 0);
rct_windowclass windowClass = 255;
rct_windownumber windowNumber = 0;
rct_widget *widget;
if (w != NULL) {
windowClass = w->classification;
windowNumber = w->number;
widget = &w->widgets[widgetIndex];
}
input_mouseover_widget_check(windowClass, windowNumber, widgetIndex);
if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL)
{
int eax, ebx, ecx, edx;
widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
if (ecx < 0)
goto showTooltip;
if (ecx == 0) {
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEOVER], edx, 0, eax, ebx, (int)w, 0, 0);
goto showTooltip;
} else {
}
} else {
showTooltip:
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) == 255) {
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 ||
(RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y)
) {
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(0x009DE588, uint16);
int bp = 2000;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) <= 1000)
bp = 0;
if (bp > RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16))
return;
window_tooltip_open(w, widgetIndex, x, y);
// RCT2_CALLPROC_X(0x006EA10D, x, y, 0, widgetIndex, w, widget, 0); // window_tooltip_open();
}
} else {
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex
) {
window_tooltip_close();
}
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(0x009DE588, uint16);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) < 8000)
return;
window_close_by_id(WC_TOOLTIP, 0);
}
}
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) = y;
}
/**
*
* rct2: 0x006E9269
*/
static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex)
{
// Check if widget cursor was over has changed
if (windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) ||
windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) ||
widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)
) {
// Invalidate last widget cursor was on if widget is a flat button
input_mouseover_widget_flatbutton_invalidate();
// Set new cursor over widget
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) = windowClass;
2014-05-12 02:45:45 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) = windowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16) = widgetIndex;
// Invalidate new widget cursor is on if widget is a flat button
if (windowClass != 255)
input_mouseover_widget_flatbutton_invalidate();
}
}
static void input_mouseover_widget_flatbutton_invalidate()
{
rct_window *w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber));
if (w == NULL)
return;
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
if (w->widgets[RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)].type == WWT_FLATBTN)
widget_invalidate(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber));
}
2014-05-28 23:22:09 +02:00
static void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget )
{
#ifdef _MSC_VER
__asm {
push address
push widget
push w
push widgetIndex
mov edi, widget
mov edx, widgetIndex
mov esi, w
call[esp + 12]
add esp, 16
}
#else
__asm__("\
push %[address]\n\
2014-05-29 01:19:09 +02:00
mov edi, %[widget] \n\
2014-05-28 23:22:09 +02:00
mov eax, %[w] \n\
2014-05-29 01:19:09 +02:00
mov edx, %[widgetIndex] \n\
2014-05-28 23:22:09 +02:00
push edi \n\
2014-05-29 01:19:09 +02:00
push eax \n\
push edx \n\
2014-05-28 23:22:09 +02:00
mov esi, %[w] \n\
call [esp+12] \n\
add esp, 16 \n\
2014-05-29 01:19:09 +02:00
" :[address] "+m" (address), [w] "+m" (w), [widget] "+m" (widget), [widgetIndex] "+m" (widgetIndex): : "eax", "esi", "edx", "edi"
);
2014-05-28 23:22:09 +02:00
#endif
}
/**
*
* rct2: 0x006E95F9
*/
static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
{
// RCT2_CALLPROC_X(0x006E95F9, x, y, state, widgetIndex, w, widget, 0);
rct_windowclass windowClass = 255;
rct_windownumber windowNumber = 0;
rct_widget *widget;
if (w != NULL) {
windowClass = w->classification;
windowNumber = w->number;
}
window_close_by_id(WC_ERROR, 0);
window_close_by_id(WC_TOOLTIP, 0);
w = window_find_by_id(windowClass, windowNumber);
if (w == NULL)
return;
2014-04-28 03:35:23 +02:00
w = window_bring_to_front(w);
if (widgetIndex == -1)
return;
widget = &w->widgets[widgetIndex];
switch (widget->type) {
case WWT_FRAME:
case WWT_RESIZE:
if (!(w->flags & WF_RESIZABLE))
break;
if (w->min_width == w->max_width && w->min_height == w->max_height)
break;
if (x < w->x + w->width - 19 || y < w->y + w->height - 19)
break;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESIZING;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
break;
case WWT_VIEWPORT:
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_LEFT;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)))
break;
2014-04-25 04:02:06 +02:00
w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
if (w == NULL)
break;
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DOWN], x, y, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 4);
break;
case WWT_CAPTION:
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_DRAGGING;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
break;
case WWT_SCROLL:
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_LEFT;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
2014-04-28 03:35:23 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
int eax, ebx, ecx, edx;
widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
RCT2_GLOBAL(0x009DE548, uint16) = ecx;
RCT2_GLOBAL(0x009DE54C, uint32) = edx;
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_15], RCT2_GLOBAL(0x009DE54C, uint32), ebx, ecx, edx, (int)w, (int)widget, 0);
switch (ecx) {
case SCROLL_PART_VIEW:
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEDOWN], edx / sizeof(rct_scroll), ebx, eax, ebx, (int)w, (int)widget, 0);
break;
case SCROLL_PART_HSCROLLBAR_LEFT:
// 0x006E9A60
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9A60, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_HSCROLLBAR_RIGHT:
// 0x006E9ABF
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9ABF, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
// 0x006E9B47
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9B47, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
// 0x006E9BB7
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9BB7, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_VSCROLLBAR_TOP:
// 0x006E9C37
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9C37, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_VSCROLLBAR_BOTTOM:
// 0x006E9C96
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9C96, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
// 0x006E9D1E
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9D1E, 0, 0, 0, 0, (int)w, 0, 0);
break;
case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
// 0x006E9D8E
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006E9D8E, 0, 0, 0, 0, (int)w, 0, 0);
break;
}
break;
default:
// comment check as it disables the rotate station/building button in construction window
// if (!widget_is_enabled(w, widgetIndex))
// break;
if (widget_is_disabled(w, widgetIndex))
break;
2014-05-25 23:08:36 +02:00
sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2);
// Set new cursor down widget
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
2014-05-12 02:45:45 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 0);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_WIDGET_PRESSED;
RCT2_GLOBAL(0x009DE528, uint16) = 1;
widget_invalidate(windowClass, windowNumber, widgetIndex);
2014-05-28 23:22:09 +02:00
RCT2_CALLPROC_WE_MOUSE_DOWN(w->event_handlers[WE_MOUSE_DOWN], widgetIndex, w, widget);
break;
}
}
2014-04-26 02:16:32 +02:00
void game_handle_edge_scroll()
{
rct_window *mainWindow;
int scrollX, scrollY;
mainWindow = window_get_main();
if (mainWindow == NULL)
return;
if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
return;
if (mainWindow->viewport == NULL)
return;
scrollX = 0;
scrollY = 0;
// Scroll left / right
if (gCursorState.x == 0)
scrollX = -1;
else if (gCursorState.x == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 1)
scrollX = 1;
// Scroll up / down
if (gCursorState.y == 0)
scrollY = -1;
else if (gCursorState.y == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 1)
scrollY = 1;
// Scroll viewport
if (scrollX != 0) {
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
if (scrollY != 0) {
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
}
#include <SDL_keycode.h>
void game_handle_key_scroll()
{
rct_window *mainWindow;
int scrollX, scrollY;
mainWindow = window_get_main();
if (mainWindow == NULL)
return;
if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
return;
if (mainWindow->viewport == NULL)
return;
scrollX = 0;
scrollY = 0;
// Scroll left / right
if (gKeysState[SDL_SCANCODE_LEFT])
scrollX = -1;
else if (gKeysState[SDL_SCANCODE_RIGHT])
scrollX = 1;
// Scroll up / down
if (gKeysState[SDL_SCANCODE_UP])
scrollY = -1;
else if (gKeysState[SDL_SCANCODE_DOWN])
scrollY = 1;
// Scroll viewport
if (scrollX != 0) {
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
if (scrollY != 0) {
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
}
}
/**
*
* rct2: 0x00406CD2
*/
int get_next_key()
{
int i;
for (i = 0; i < 221; i++) {
if (gKeysPressed[i]) {
gKeysPressed[i] = 0;
2014-04-26 02:16:32 +02:00
return i;
}
}
return 0;
}
void handle_shortcut_command(int shortcutIndex)
{
rct_window *window;
2014-05-09 09:47:20 +02:00
switch (shortcutIndex) {
case SHORTCUT_CLOSE_TOP_MOST_WINDOW:
2014-05-09 09:47:20 +02:00
window_close_top();
break;
case SHORTCUT_CLOSE_ALL_FLOATING_WINDOWS:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2))
2014-05-09 09:47:20 +02:00
window_close_all();
2014-05-12 02:45:45 +02:00
else if (RCT2_GLOBAL(0x0141F570, uint8) == 1)
2014-05-09 09:47:20 +02:00
window_close_top();
break;
case SHORTCUT_CANCEL_CONSTRUCTION_MODE:
2014-05-09 09:47:20 +02:00
window = window_find_by_id(WC_ERROR, 0);
if (window != NULL)
2014-05-09 09:47:20 +02:00
window_close(window);
else if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3))
2014-05-09 09:47:20 +02:00
tool_cancel();
break;
case SHORTCUT_PAUSE_GAME:
2014-05-09 09:47:20 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 10)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 0, WE_MOUSE_UP);
}
}
break;
case SHORTCUT_ZOOM_VIEW_OUT:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 2, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_ZOOM_VIEW_IN:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 3, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_ROTATE_VIEW:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 4, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_ROTATE_CONSTRUCTION_OBJECT:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_EBPSAFE(0x006E4182);
break;
case SHORTCUT_UNDERGROUND_VIEW_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 0, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_REMOVE_BASE_LAND_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 1, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 2, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_SEE_THROUGH_RIDES_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 4, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_SEE_THROUGH_SCENERY_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 5, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_INVISIBLE_SUPPORTS_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 6, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_INVISIBLE_PEOPLE_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 7, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_HEIGHT_MARKS_ON_LAND_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 9, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_HEIGHT_MARKS_ON_RIDE_TRACKS_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 10, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_HEIGHT_MARKS_ON_PATHS_TOGGLE:
2014-05-09 09:47:20 +02:00
RCT2_CALLPROC_X(0x0066CF8A, 11, 0, 0, 0, 0, 0, 0);
break;
case SHORTCUT_ADJUST_LAND:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 7, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_ADJUST_WATER:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 8, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_BUILD_SCENERY:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 9, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_BUILD_PATHS:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 10, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_BUILD_NEW_RIDE:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 11, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_SHOW_FINANCIAL_INFORMATION:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C))
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800))
window_finances_open();
break;
case SHORTCUT_SHOW_RESEARCH_INFORMATION:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
// Open new ride window
RCT2_CALLPROC_EBPSAFE(0x006B3CFF);
window = window_find_by_id(WC_CONSTRUCT_RIDE, 0);
if (window != NULL)
2014-05-29 18:22:32 +02:00
RCT2_CALLPROC_WE_MOUSE_DOWN(window->event_handlers[WE_MOUSE_DOWN], 10, window, NULL);
2014-05-09 09:47:20 +02:00
}
break;
case SHORTCUT_SHOW_RIDES_LIST:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
2014-05-09 09:47:20 +02:00
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 12, WE_MOUSE_UP);
}
}
break;
case SHORTCUT_SHOW_PARK_INFORMATION:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
2014-05-09 09:47:20 +02:00
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 13, WE_MOUSE_UP);
}
}
break;
case SHORTCUT_SHOW_GUEST_LIST:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
2014-05-09 09:47:20 +02:00
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 15, WE_MOUSE_UP);
}
}
break;
case SHORTCUT_SHOW_STAFF_LIST:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
2014-05-09 09:47:20 +02:00
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 14, WE_MOUSE_UP);
}
}
break;
case SHORTCUT_SHOW_RECENT_MESSAGES:
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E))
window_news_open();
break;
case SHORTCUT_SHOW_MAP:
2014-05-12 02:45:45 +02:00
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
window = window_find_by_id(WC_TOP_TOOLBAR, 0);
if (window != NULL) {
window_invalidate(window);
window_event_helper(window, 6, WE_MOUSE_UP);
}
2014-05-09 09:47:20 +02:00
}
}
break;
case SHORTCUT_SCREENSHOT:
RCT2_CALLPROC_EBPSAFE(0x006E4034); // set screenshot countdown to 2
break;
2014-05-25 04:02:48 +02:00
// New
case SHORTCUT_REDUCE_GAME_SPEED:
_gameSpeed = max(1, _gameSpeed - 1);
break;
case SHORTCUT_INCREASE_GAME_SPEED:
_gameSpeed = min(8, _gameSpeed + 1);
break;
2014-04-26 02:16:32 +02:00
}
}
2014-05-09 09:47:20 +02:00
/**
*
* rct2: 0x006E3E68
*/
void handle_shortcut(int key)
{
int i;
for (i = 0; i < SHORTCUT_COUNT; i++) {
if (key == gShortcutKeys[i]) {
handle_shortcut_command(i);
break;
}
}
2014-04-26 02:16:32 +02:00
}
2014-04-26 02:16:32 +02:00
/**
*
* rct2: 0x006E3E91
*/
void set_shortcut(int key)
{
int i;
// Unmap shortcut that already uses this key
for (i = 0; i < 32; i++) {
if (key == gShortcutKeys[i]) {
gShortcutKeys[i] = 0xFFFF;
break;
}
}
// Map shortcut to this key
gShortcutKeys[RCT2_GLOBAL(0x009DE511, uint8)] = key;
window_close_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
window_invalidate_by_id(WC_KEYBOARD_SHORTCUT_LIST, 0);
config_save();
}
/**
*
* rct2: 0x006E3B43
*/
void game_handle_keyboard_input()
{
2014-04-26 02:16:32 +02:00
rct_window *w;
2014-05-12 02:45:45 +02:00
int key;
2014-04-26 02:16:32 +02:00
// Handle mouse scrolling
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0)
2014-04-26 02:16:32 +02:00
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 1)
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3))
game_handle_edge_scroll();
// Handle modifier keys and key scrolling
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0;
if (RCT2_GLOBAL(0x009E2B64, uint32) != 1) {
if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT])
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 1;
if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL])
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2;
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
game_handle_key_scroll();
}
// Handle key input
while ((key = get_next_key()) != 0) {
2014-05-04 15:10:32 +02:00
if (key == 255)
2014-04-26 02:16:32 +02:00
continue;
key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
w = window_find_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
if (w != NULL)
set_shortcut(key);
else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1)
tutorial_stop();
else
handle_shortcut(key);
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
return;
// Tutorial and the modifier key
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x0066EEB4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
eax &= 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = eax;
if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4) {
window_tooltip_close();
if ((w = window_get_main()) != NULL) {
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DEA72, uint16)++;
}
}
} else {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) {
window_tooltip_close();
if ((w = window_get_main()) != NULL) {
2014-05-12 02:45:45 +02:00
RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
2014-04-26 02:16:32 +02:00
RCT2_GLOBAL(0x009DEA72, uint16)++;
}
}
// Write tutorial input
RCT2_CALLPROC_X(0x0066EEE1, RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8), 0, 0, 0, 0, 0, 0);
}
2014-05-02 03:12:14 +02:00
}
/**
*
* rct2: 0x006677F2
*
* @param cost (ebp)
*/
static int game_check_affordability(int cost)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
ebp = cost;
RCT2_CALLFUNC_X(0x0069C62C, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return ebp;
}
2014-05-02 23:21:08 +02:00
static uint32 game_do_command_table[58];
2014-05-02 03:12:14 +02:00
/**
*
* rct2: 0x006677F2
*
* @param flags (ebx)
* @param command (esi)
*/
int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp)
{
2014-05-02 04:05:18 +02:00
int cost, flags, insufficientFunds;
2014-05-02 03:12:14 +02:00
int original_ebx, original_edx, original_esi, original_edi, original_ebp;
original_ebx = ebx;
original_edx = edx;
original_esi = esi;
original_edi = edi;
original_ebp = ebp;
flags = ebx;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0xFFFF;
// Increment nest count
RCT2_GLOBAL(0x009A8C28, uint8)++;
ebx &= ~1;
// Primary command
2014-05-02 23:21:08 +02:00
RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
2014-05-02 03:12:14 +02:00
cost = ebx;
if (cost != 0x80000000) {
2014-05-02 04:05:18 +02:00
// Check funds
insufficientFunds = 0;
if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & 4) && !(flags & 0x20) && cost != 0)
insufficientFunds = game_check_affordability(cost);
if (insufficientFunds != 0x80000000) {
2014-05-02 03:12:14 +02:00
ebx = original_ebx;
edx = original_edx;
esi = original_esi;
edi = original_edi;
ebp = original_ebp;
if (!(flags & 1)) {
// Decrement nest count
RCT2_GLOBAL(0x009A8C28, uint8)--;
return cost;
}
// Secondary command
2014-05-02 23:21:08 +02:00
RCT2_CALLFUNC_X(game_do_command_table[esi], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
2014-05-02 03:12:14 +02:00
edx = ebx;
2014-05-02 04:05:18 +02:00
if (edx != 0x80000000 && edx < cost)
2014-05-02 03:12:14 +02:00
cost = edx;
// Decrement nest count
RCT2_GLOBAL(0x009A8C28, uint8)--;
if (RCT2_GLOBAL(0x009A8C28, uint8) != 0)
return cost;
//
2014-05-02 04:05:18 +02:00
if (!(flags & 0x20)) {
2014-05-02 03:12:14 +02:00
// Update money balance
2014-05-08 00:45:16 +02:00
finance_payment(cost, RCT2_GLOBAL(0x0141F56C, uint8));
2014-05-02 03:12:14 +02:00
RCT2_CALLPROC_X(0x0069C674, 0, cost, 0, 0, 0, 0, 0);
if (RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8)) {
// Create a +/- money text effect
if (cost != 0)
RCT2_CALLPROC_X(0x0069C5D0, 0, cost, 0, 0, 0, 0, 0);
}
}
return cost;
}
}
// Error occured
// Decrement nest count
RCT2_GLOBAL(0x009A8C28, uint8)--;
// Show error window
2014-05-02 04:05:18 +02:00
if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & 1) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & 8))
2014-05-02 03:12:14 +02:00
window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16));
return 0x80000000;
2014-05-02 23:21:08 +02:00
}
2014-05-03 10:00:49 +02:00
/**
*
* rct2: 0x00667C15
*/
static void game_pause_toggle()
{
2014-05-12 02:45:45 +02:00
char input_bl;
2014-05-03 10:00:49 +02:00
2014-05-19 22:53:14 +02:00
#ifdef _MSC_VER
2014-05-03 10:00:49 +02:00
__asm mov input_bl, bl
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov %[input_bl], bl " : [input_bl] "+m" (input_bl) );
#endif
2014-05-03 10:00:49 +02:00
if (input_bl & 1) {
RCT2_GLOBAL(0x009DEA6E, uint32) ^= 1;
window_invalidate_by_id(WC_TOP_TOOLBAR, 0);
if (RCT2_GLOBAL(0x009DEA6E, uint32) & 1)
pause_sounds();
2014-05-03 10:00:49 +02:00
else
unpause_sounds();
2014-05-03 10:00:49 +02:00
}
2014-05-19 22:53:14 +02:00
#ifdef _MSC_VER
2014-05-03 10:00:49 +02:00
__asm mov ebx, 0
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov ebx, 0 " );
#endif
2014-05-03 10:00:49 +02:00
}
2014-05-02 23:21:08 +02:00
/**
*
* rct2: 0x0066DB5F
*/
static void game_load_or_quit()
{
char input_bl, input_dl;
short input_di;
2014-05-19 22:53:14 +02:00
#ifdef _MSC_VER
2014-05-02 23:21:08 +02:00
__asm mov input_bl, bl
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov %[input_bl], bl " : [input_bl] "+m" (input_bl) );
#endif
#ifdef _MSC_VER
2014-05-02 23:21:08 +02:00
__asm mov input_dl, dl
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov %[input_dl], dl " : [input_dl] "+m" (input_dl) );
#endif
#ifdef _MSC_VER
2014-05-02 23:21:08 +02:00
__asm mov input_di, di
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov %[input_di], di " : [input_di] "+m" (input_di) );
#endif
2014-05-02 23:21:08 +02:00
if (!(input_bl & 1))
2014-05-12 03:18:08 +02:00
return; // 0;
2014-05-23 11:30:19 +02:00
2014-05-02 23:21:08 +02:00
switch (input_dl) {
case 0:
2014-05-23 11:30:19 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) = input_di;
2014-05-02 23:21:08 +02:00
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;
}
2014-05-19 22:53:14 +02:00
#ifdef _MSC_VER
2014-05-02 23:21:08 +02:00
__asm mov ebx, 0
2014-05-19 22:53:14 +02:00
#else
__asm__ ( "mov ebx, 0 " );
#endif
2014-05-02 23:21:08 +02:00
}
/**
*
* rct2: 0x00674F40
*/
static int open_landscape_file_dialog()
{
2014-05-12 03:18:08 +02:00
int result;
2014-05-12 02:45:45 +02:00
format_string((char*)0x0141ED68, STR_LOAD_LANDSCAPE_DIALOG_TITLE, 0);
strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_LANDSCAPES_PATH);
format_string((char*)0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0);
pause_sounds();
2014-05-12 03:18:08 +02:00
result = osinterface_open_common_file_dialog(1, (char*)0x0141ED68, (char*)0x0141EF68, "*.SV6;*.SV4;*.SC6", (char*)0x0141EE68);
unpause_sounds();
2014-05-03 11:27:48 +02:00
// window_proc
2014-05-12 03:18:08 +02:00
return result;
2014-05-02 23:21:08 +02:00
}
/**
*
* rct2: 0x00674EB6
*/
static int open_load_game_dialog()
{
int result;
2014-05-12 02:45:45 +02:00
format_string((char*)0x0141ED68, STR_LOAD_GAME_DIALOG_TITLE, 0);
strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_SAVED_GAMES_PATH);
format_string((char*)0x0141EE68, STR_RCT2_SAVED_GAME, 0);
pause_sounds();
2014-05-12 02:45:45 +02:00
result = osinterface_open_common_file_dialog(1, (char*)0x0141ED68, (char*)0x0141EF68, "*.SV6", (char*)0x0141EE68);
unpause_sounds();
2014-05-03 11:27:48 +02:00
// window_proc
return result;
2014-05-02 23:21:08 +02:00
}
/**
*
* rct2: 0x0066DC0F
*/
static void load_landscape()
{
if (open_landscape_file_dialog() == 0) {
gfx_invalidate_screen();
} else {
// Set default filename
2014-05-12 02:45:45 +02:00
char *esi = (char*)0x0141EF67;
while (1) {
esi++;
if (*esi == '.')
break;
if (*esi != 0)
continue;
strcpy(esi, ".SC6");
break;
}
strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68);
2014-05-02 23:21:08 +02:00
RCT2_CALLPROC_EBPSAFE(0x006758C0); // landscape_load
2014-05-02 23:21:08 +02:00
if (1) {
gfx_invalidate_screen();
rct2_endupdate();
2014-05-02 23:21:08 +02:00
} else {
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
rct2_endupdate();
2014-05-02 23:21:08 +02:00
}
}
}
2014-05-04 17:21:15 +02:00
/**
*
* rct2: 0x00675E1B
*/
int game_load_save()
{
rct_window *mainWindow;
2014-05-24 23:14:42 +02:00
FILE *file;
2014-05-04 17:21:15 +02:00
char *path;
int i, j;
path = (char*)0x0141EF68;
2014-05-24 23:14:42 +02:00
file = fopen(path, "rb");
if (file == NULL) {
2014-05-04 17:21:15 +02:00
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
2014-05-24 23:14:42 +02:00
if (!sawyercoding_validate_checksum(file)) {
fclose(file);
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
return 0;
}
2014-05-04 17:21:15 +02:00
2014-05-12 02:45:45 +02:00
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
2014-05-04 17:21:15 +02:00
// Read first chunk
2014-05-24 23:14:42 +02:00
sawyercoding_read_chunk(file, (uint8*)s6Header);
2014-05-04 17:21:15 +02:00
if (s6Header->type == S6_TYPE_SAVEDGAME) {
// Read packed objects
if (s6Header->num_packed_objects > 0) {
j = 0;
for (i = 0; i < s6Header->num_packed_objects; i++)
j += object_load_packed();
if (j > 0)
2014-05-24 02:34:17 +02:00
object_list_load();
2014-05-04 17:21:15 +02:00
}
}
2014-05-24 23:14:42 +02:00
object_read_and_load_entries(file);
2014-05-04 17:21:15 +02:00
// Read flags (16 bytes)
2014-05-24 23:14:42 +02:00
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
2014-05-04 17:21:15 +02:00
// Read map elements
2014-05-12 02:45:45 +02:00
memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
2014-05-24 23:14:42 +02:00
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
2014-05-04 17:21:15 +02:00
// Read game data, including sprites
2014-05-24 23:14:42 +02:00
sawyercoding_read_chunk(file, (uint8*)0x010E63B8);
2014-05-04 17:21:15 +02:00
2014-05-24 23:14:42 +02:00
fclose(file);
2014-05-04 17:21:15 +02:00
// Check expansion pack
// RCT2_CALLPROC_EBPSAFE(0x006757E6);
// The rest is the same as in scenario load and play
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
map_update_tile_pointers();
2014-06-21 14:31:28 +02:00
reset_0x69EBE4();// RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
2014-05-04 17:21:15 +02:00
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING;
viewport_init_all();
game_create_windows();
mainWindow = window_get_main();
mainWindow->var_4B0 = -1;
mainWindow->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
mainWindow->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
uint8 _cl = (RCT2_GLOBAL(0x0138869E, sint16) & 0xFF) - mainWindow->viewport->zoom;
mainWindow->viewport->zoom = RCT2_GLOBAL(0x0138869E, sint16) & 0xFF;
*((char*)(&RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, sint32))) = RCT2_GLOBAL(0x0138869E, sint16) >> 8;
if (_cl != 0) {
if (_cl < 0) {
_cl = -_cl;
mainWindow->viewport->view_width >>= _cl;
mainWindow->viewport->view_height >>= _cl;
} else {
mainWindow->viewport->view_width <<= _cl;
mainWindow->viewport->view_height <<= _cl;
}
}
mainWindow->saved_view_x -= mainWindow->viewport->view_width >> 1;
mainWindow->saved_view_y -= mainWindow->viewport->view_height >> 1;
window_invalidate(mainWindow);
2014-06-21 16:50:13 +02:00
sub_0x0069E9A7();
2014-05-04 17:21:15 +02:00
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
2014-05-10 00:11:51 +02:00
window_new_ride_init_vars();
2014-05-04 17:21:15 +02:00
RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
if (RCT2_GLOBAL(0x0013587C4, uint32) == 0) // this check is not in scenario play
sub_69E869();
2014-05-04 17:21:15 +02:00
RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
gfx_invalidate_screen();
return 1;
}
2014-06-21 16:50:13 +02:00
/*
*
* rct2: 0x0069E9A7
*/
void sub_0x0069E9A7(){
//RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
//return;
2014-06-29 15:51:18 +02:00
for (rct_sprite* spr = g_sprite_list; spr < (rct_sprite*)RCT2_ADDRESS_SPRITES_NEXT_INDEX; ++spr){
2014-06-21 16:50:13 +02:00
if (spr->unknown.sprite_identifier != 0xFF){
RCT2_CALLPROC_X(0x0069E9D3, spr->unknown.x, 0, spr->unknown.y, spr->unknown.z, (int)spr, 0, 0);
}
}
}
2014-05-02 23:21:08 +02:00
/**
*
* rct2: 0x0066DBB7
*/
static void load_game()
{
if (open_load_game_dialog() == 0) {
gfx_invalidate_screen();
} else {
// Set default filename
2014-05-12 02:45:45 +02:00
char *esi = (char*)0x0141EF67;
while (1) {
esi++;
if (*esi == '.')
break;
if (*esi != 0)
continue;
strcpy(esi, ".SV6");
break;
}
strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68);
2014-05-02 23:21:08 +02:00
2014-05-04 17:21:15 +02:00
if (game_load_save()) {
2014-05-02 23:21:08 +02:00
gfx_invalidate_screen();
rct2_endupdate();
2014-05-02 23:21:08 +02:00
} else {
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
rct2_endupdate();
2014-05-02 23:21:08 +02:00
}
}
}
2014-05-27 23:33:16 +02:00
char save_game()
{
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (eax == 0) {
// user pressed "cancel"
gfx_invalidate_screen();
return 0;
}
char *src = (char*)0x0141EF67;
do {
src++;
} while (*src != '.' && *src != '\0');
strcpy(src, ".SV6");
strcpy((char*) RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*) 0x0141EF68);
eax = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 8)
eax |= 1;
RCT2_CALLPROC_X(0x006754F5, eax, 0, 0, 0, 0, 0, 0);
// check success?
game_do_command(0, 1047, 0, -1, 0, 0, 0);
gfx_invalidate_screen();
return 1;
}
2014-05-02 23:21:08 +02:00
/**
*
* rct2: 0x006E3879
*/
static void rct2_exit()
{
RCT2_CALLPROC_EBPSAFE(0x006E3879);
}
/**
*
* rct2: 0x0066DB79
*/
void game_load_or_quit_no_save_prompt()
{
2014-05-23 11:30:19 +02:00
if (RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) < 1) {
2014-05-02 23:21:08 +02:00
game_do_command(0, 1, 0, 1, 5, 0, 0);
2014-05-02 23:38:16 +02:00
tool_cancel();
2014-05-02 23:21:08 +02:00
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
load_landscape();
else
load_game();
2014-05-23 11:30:19 +02:00
} else if (RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) == 1) {
2014-05-02 23:21:08 +02:00
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();
rct2_endupdate();
2014-05-02 23:21:08 +02:00
} else {
rct2_exit();
}
}
#pragma region Game command function table
static uint32 game_do_command_table[58] = {
0x006B2FC5,
0x0066397F,
2014-05-12 02:45:45 +02:00
(uint32)game_pause_toggle,
2014-05-02 23:21:08 +02:00
0x006C511D,
0x006C5B69,
2014-05-12 02:45:45 +02:00
(uint32)game_load_or_quit,
2014-05-02 23:21:08 +02:00
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