From 9f91798514093102fbd8f1eb9ba810ec6377546e Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 26 Apr 2014 01:16:32 +0100 Subject: [PATCH] implement keyboard shortcuts --- src/config.c | 50 ++++++++++++ src/config.h | 41 ++++++++++ src/game.c | 201 +++++++++++++++++++++++++++++++++++++++++++++- src/osinterface.c | 9 +-- src/osinterface.h | 2 +- src/rct2.c | 2 +- src/tutorial.c | 9 +++ src/tutorial.h | 1 + src/window.h | 1 + 9 files changed, 305 insertions(+), 11 deletions(-) diff --git a/src/config.c b/src/config.c index 4e6f9383c0..8a0fdbd6f6 100644 --- a/src/config.c +++ b/src/config.c @@ -18,13 +18,63 @@ * along with this program. If not, see . *****************************************************************************/ +#include #include #include "addresses.h" #include "config.h" #include "rct2.h" +// Current keyboard shortcuts +uint16 gShortcutKeys[SHORTCUT_COUNT]; + +// Magic number for original game cfg file static const int MagicNumber = 0x0003113A; +// Default keyboard shortcuts +static const uint16 _defaultShortcutKeys[SHORTCUT_COUNT] = { + SDL_SCANCODE_BACKSPACE, // SHORTCUT_CLOSE_TOP_MOST_WINDOW + 0x0100 | SDL_SCANCODE_BACKSPACE, // SHORTCUT_CLOSE_ALL_FLOATING_WINDOWS + SDL_SCANCODE_ESCAPE, // SHORTCUT_CANCEL_CONSTRUCTION_MODE + SDL_SCANCODE_PAUSE, // SHORTCUT_PAUSE_GAME + SDL_SCANCODE_PAGEUP, // SHORTCUT_ZOOM_VIEW_OUT + SDL_SCANCODE_PAGEDOWN, // SHORTCUT_ZOOM_VIEW_IN + SDL_SCANCODE_RETURN, // SHORTCUT_ROTATE_VIEW + SDL_SCANCODE_Z, // SHORTCUT_ROTATE_CONSTRUCTION_OBJECT + SDL_SCANCODE_1, // SHORTCUT_UNDERGROUND_VIEW_TOGGLE + SDL_SCANCODE_H, // SHORTCUT_REMOVE_BASE_LAND_TOGGLE + SDL_SCANCODE_V, // SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE + SDL_SCANCODE_3, // SHORTCUT_SEE_THROUGH_RIDES_TOGGLE + SDL_SCANCODE_4, // SHORTCUT_SEE_THROUGH_SCENERY_TOGGLE + SDL_SCANCODE_5, // SHORTCUT_INVISIBLE_SUPPORTS_TOGGLE + SDL_SCANCODE_6, // SHORTCUT_INVISIBLE_PEOPLE_TOGGLE + SDL_SCANCODE_8, // SHORTCUT_HEIGHT_MARKS_ON_LAND_TOGGLE + SDL_SCANCODE_9, // SHORTCUT_HEIGHT_MARKS_ON_RIDE_TRACKS_TOGGLE + SDL_SCANCODE_0, // SHORTCUT_HEIGHT_MARKS_ON_PATHS_TOGGLE + SDL_SCANCODE_F1, // SHORTCUT_ADJUST_LAND + SDL_SCANCODE_F2, // SHORTCUT_ADJUST_WATER + SDL_SCANCODE_F3, // SHORTCUT_BUILD_SCENERY + SDL_SCANCODE_F4, // SHORTCUT_BUILD_PATHS + SDL_SCANCODE_F5, // SHORTCUT_BUILD_NEW_RIDE + SDL_SCANCODE_F, // SHORTCUT_SHOW_FINANCIAL_INFORMATION + SDL_SCANCODE_D, // SHORTCUT_SHOW_RESEARCH_INFORMATION + SDL_SCANCODE_R, // SHORTCUT_SHOW_RIDES_LIST + SDL_SCANCODE_P, // SHORTCUT_SHOW_PARK_INFORMATION + SDL_SCANCODE_G, // SHORTCUT_SHOW_GUEST_LIST + SDL_SCANCODE_S, // SHORTCUT_SHOW_STAFF_LIST + SDL_SCANCODE_M, // SHORTCUT_SHOW_RECENT_MESSAGES + SDL_SCANCODE_TAB, // SHORTCUT_SHOW_MAP + 0x0200 | SDL_SCANCODE_S // SHORTCUT_SCREENSHOT +}; + +/** + * + * rct2: 0x006E3604 + */ +void config_reset_shortcut_keys() +{ + memcpy(gShortcutKeys, _defaultShortcutKeys, sizeof(gShortcutKeys)); +} + /** * * rct2: 0x006752D5 diff --git a/src/config.h b/src/config.h index 019c995232..efc5df03ba 100644 --- a/src/config.h +++ b/src/config.h @@ -21,12 +21,53 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ +#include "rct2.h" + enum { CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES = (1 << 0), CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS = (1 << 1), CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE = (1 << 2) }; +enum { + SHORTCUT_CLOSE_TOP_MOST_WINDOW, + SHORTCUT_CLOSE_ALL_FLOATING_WINDOWS, + SHORTCUT_CANCEL_CONSTRUCTION_MODE, + SHORTCUT_PAUSE_GAME, + SHORTCUT_ZOOM_VIEW_OUT, + SHORTCUT_ZOOM_VIEW_IN, + SHORTCUT_ROTATE_VIEW, + SHORTCUT_ROTATE_CONSTRUCTION_OBJECT, + SHORTCUT_UNDERGROUND_VIEW_TOGGLE, + SHORTCUT_REMOVE_BASE_LAND_TOGGLE, + SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE, + SHORTCUT_SEE_THROUGH_RIDES_TOGGLE, + SHORTCUT_SEE_THROUGH_SCENERY_TOGGLE, + SHORTCUT_INVISIBLE_SUPPORTS_TOGGLE, + SHORTCUT_INVISIBLE_PEOPLE_TOGGLE, + SHORTCUT_HEIGHT_MARKS_ON_LAND_TOGGLE, + SHORTCUT_HEIGHT_MARKS_ON_RIDE_TRACKS_TOGGLE, + SHORTCUT_HEIGHT_MARKS_ON_PATHS_TOGGLE, + SHORTCUT_ADJUST_LAND, + SHORTCUT_ADJUST_WATER, + SHORTCUT_BUILD_SCENERY, + SHORTCUT_BUILD_PATHS, + SHORTCUT_BUILD_NEW_RIDE, + SHORTCUT_SHOW_FINANCIAL_INFORMATION, + SHORTCUT_SHOW_RESEARCH_INFORMATION, + SHORTCUT_SHOW_RIDES_LIST, + SHORTCUT_SHOW_PARK_INFORMATION, + SHORTCUT_SHOW_GUEST_LIST, + SHORTCUT_SHOW_STAFF_LIST, + SHORTCUT_SHOW_RECENT_MESSAGES, + SHORTCUT_SHOW_MAP, + SHORTCUT_SCREENSHOT, + SHORTCUT_COUNT +}; + +extern uint16 gShortcutKeys[SHORTCUT_COUNT]; + +void config_reset_shortcut_keys(); void config_load(); void config_save(); diff --git a/src/game.c b/src/game.c index 43faabb0d7..7c94a2fb76 100644 --- a/src/game.c +++ b/src/game.c @@ -28,6 +28,7 @@ #include "peep.h" #include "screenshot.h" #include "strings.h" +#include "tutorial.h" #include "widget.h" #include "window.h" #include "window_error.h" @@ -761,7 +762,140 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex) } } +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->var_4B2 += scrollX * (12 << mainWindow->viewport->zoom); + RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7); + } + if (scrollY != 0) { + mainWindow->var_4B4 += scrollY * (12 << mainWindow->viewport->zoom); + RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7); + } +} + +#include + +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->var_4B2 += scrollX * (12 << mainWindow->viewport->zoom); + RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7); + } + if (scrollY != 0) { + mainWindow->var_4B4 += scrollY * (12 << mainWindow->viewport->zoom); + RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7); + } +} + +/** + * + * rct2: 0x00406CD2 + */ +int get_next_key() +{ + int i; + for (i = 0; i < 221; i++) { + if (gKeysState[i]) { + gKeysState[i] = 0; + return i; + } + } + + return 0; +} + +/** + * + * rct2: 0x006E3E68 + */ +void handle_shortcut(int key) +{ + int i; + for (i = 0; i < 32; i++) { + if (key == gShortcutKeys[i]) { + RCT2_CALLPROC_EBPSAFE(RCT2_ADDRESS(0x006E3FB4, uint32)[i]); + break; + } + } +} + +/** + * + * 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(); +} /** * @@ -769,5 +903,70 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex) */ void game_handle_keyboard_input() { - RCT2_CALLPROC_EBPSAFE(0x006E3B43); + rct_window *w; + int key, i; + + // Handle mouse scrolling + if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0) + if (RCT2_GLOBAL(0x009AACBA, uint8) != 0) + 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) { + if (key == 255 || key == 0x10 || key == 0x11) + 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) { + RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, w, RCT2_GLOBAL(0x009DEA72, uint16), 0); + RCT2_GLOBAL(0x009DEA72, uint16)++; + } + } + } else { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) { + window_tooltip_close(); + if ((w = window_get_main()) != NULL) { + RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, w, RCT2_GLOBAL(0x009DEA72, uint16), 0); + 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); + } } \ No newline at end of file diff --git a/src/osinterface.c b/src/osinterface.c index ac66460855..6c8418400d 100644 --- a/src/osinterface.c +++ b/src/osinterface.c @@ -30,7 +30,7 @@ typedef void(*update_palette_func)(char*, int, int); openrct2_cursor gCursorState; -const unsigned char* gKeysState; +unsigned char* gKeysState; unsigned int gLastKeyPressed; static void osinterface_create_window(); @@ -265,13 +265,6 @@ void osinterface_process_messages() // Updates the state of the keys int numKeys = 256; gKeysState = SDL_GetKeyboardState(&numKeys); - // memcpy(0x01425C00, gKeysState, 256); - - RCT2_GLOBAL(0x009DEA70, uint8) = 0; - if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT]) - RCT2_GLOBAL(0x009DEA70, uint8) |= 1; - if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL]) - RCT2_GLOBAL(0x009DEA70, uint8) |= 2; } static void osinterface_close_window() diff --git a/src/osinterface.h b/src/osinterface.h index 4c0fed94ba..ee7e83505f 100644 --- a/src/osinterface.h +++ b/src/osinterface.h @@ -37,7 +37,7 @@ typedef struct { } openrct2_cursor; extern openrct2_cursor gCursorState; -const extern unsigned char* gKeysState; +extern unsigned char* gKeysState; extern unsigned int gLastKeyPressed; void osinterface_init(); diff --git a/src/rct2.c b/src/rct2.c index 2f14daf7f9..b85514bfaa 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -107,7 +107,7 @@ void rct2_init() RCT2_GLOBAL(0x009DEA6B, short) = RCT2_GLOBAL(0x01424304, short); rct2_init_directories(); rct2_startup_checks(); - RCT2_CALLPROC_EBPSAFE(0x06E3604); // reset_keyboard_shortcuts() + config_reset_shortcut_keys(); RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; config_load(); // RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap diff --git a/src/tutorial.c b/src/tutorial.c index 17fd8dd196..a7c6639c9c 100644 --- a/src/tutorial.c +++ b/src/tutorial.c @@ -29,3 +29,12 @@ void tutorial_start(int type) { RCT2_CALLPROC_X(0x0066ECC1, type, 0, 0, 0, 0, 0, 0); } + +/** + * + * rct2: 0x0066EE25 + */ +void tutorial_stop() +{ + RCT2_CALLPROC_EBPSAFE(0x0066EE25); +} \ No newline at end of file diff --git a/src/tutorial.h b/src/tutorial.h index 916da5fa33..a9db5b71db 100644 --- a/src/tutorial.h +++ b/src/tutorial.h @@ -22,5 +22,6 @@ #define _TUTORIAL_H_ void tutorial_start(int type); +void tutorial_stop(); #endif diff --git a/src/window.h b/src/window.h index d6fe4e1928..f4b3d8de5c 100644 --- a/src/window.h +++ b/src/window.h @@ -188,6 +188,7 @@ typedef enum { WF_STICK_TO_BACK = (1 << 0), WF_STICK_TO_FRONT = (1 << 1), + WF_2 = (1 << 2), WF_TRANSPARENT = (1 << 4), WF_5 = (1 << 5), WF_RESIZABLE = (1 << 8),