From 698915a291318a7fb8a6eb60c75f8f58fe66ac83 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Mon, 28 Oct 2024 00:09:49 +0100 Subject: [PATCH] input: merge tr1 and tr2 inputs code --- data/tr2/ship/cfg/TR2X_gameflow.json5 | 4 + docs/tr2/CHANGELOG.md | 23 + docs/tr2/progress.svg | 56 +- docs/tr2/progress.txt | 54 +- .../game/input/backends/controller.c | 7 +- .../game/input/backends/internal.c | 0 .../game/input/backends/keyboard.c | 10 +- src/libtrx/game/input/common.c | 165 ++++++ .../include/libtrx/game/game_string.def | 4 + src/libtrx/include/libtrx/game/input.h | 3 +- .../libtrx}/game/input/backends/base.h | 2 +- .../libtrx}/game/input/backends/controller.h | 2 +- .../game/input/backends/controller_tr1.def | 0 .../game/input/backends/controller_tr2.def | 15 + .../libtrx}/game/input/backends/internal.h | 8 +- .../libtrx}/game/input/backends/keyboard.h | 2 +- .../game/input/backends/keyboard_tr1.def | 33 +- .../game/input/backends/keyboard_tr2.def | 45 ++ .../include/libtrx}/game/input/common.h | 10 +- src/libtrx/include/libtrx/game/input/role.h | 99 ++++ .../include/libtrx}/game/input/state.h | 41 +- src/libtrx/meson.build | 4 + src/tr1/game/game_string.def | 4 - src/tr1/game/{input/common.c => input.c} | 156 +----- src/tr1/game/input.h | 2 +- src/tr1/game/input/role.h | 55 -- src/tr1/game/ui/common.c | 18 +- src/tr1/meson.build | 5 +- src/tr1/specific/s_shell.c | 1 - src/tr2/config.c | 94 ++++ src/tr2/config.h | 5 + src/tr2/config_map.c | 1 + src/tr2/config_map.def | 2 + src/tr2/decomp/decomp.c | 73 +-- src/tr2/decomp/fmv.c | 13 +- src/tr2/decomp/fmv.h | 1 + src/tr2/decomp/stats.c | 9 + src/tr2/game/demo.c | 56 +- src/tr2/game/game.c | 43 ++ src/tr2/game/game.h | 1 + src/tr2/game/gun/gun.c | 4 +- src/tr2/game/input.c | 229 ++++---- src/tr2/game/input.h | 82 +-- src/tr2/game/inventory/common.c | 6 + src/tr2/game/option/option_controls.c | 75 ++- src/tr2/game/shell.h | 8 +- src/tr2/game/{shell.c => shell/common.c} | 59 +- src/tr2/game/shell/common.h | 10 + src/tr2/game/shell/input.c | 305 ++++++++++ src/tr2/game/shell/input.h | 3 + src/tr2/game/ui/common.c | 20 +- src/tr2/game/ui/controllers/controls.c | 136 +++-- src/tr2/game/ui/controllers/controls.h | 15 +- src/tr2/game/ui/widgets/controls_dialog.c | 1 - .../game/ui/widgets/controls_input_selector.c | 25 +- src/tr2/global/funcs.h | 11 - src/tr2/global/vars_decomp.h | 1 - src/tr2/inject_exec.c | 8 - src/tr2/meson.build | 4 +- src/tr2/specific/s_input.c | 523 ------------------ src/tr2/specific/s_input.h | 6 - 61 files changed, 1402 insertions(+), 1255 deletions(-) rename src/{tr1 => libtrx}/game/input/backends/controller.c (99%) rename src/{tr1 => libtrx}/game/input/backends/internal.c (100%) rename src/{tr1 => libtrx}/game/input/backends/keyboard.c (98%) create mode 100644 src/libtrx/game/input/common.c rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/base.h (96%) rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/controller.h (55%) rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/controller_tr1.def (100%) create mode 100644 src/libtrx/include/libtrx/game/input/backends/controller_tr2.def rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/internal.h (63%) rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/keyboard.h (54%) rename src/{tr1 => libtrx/include/libtrx}/game/input/backends/keyboard_tr1.def (99%) create mode 100644 src/libtrx/include/libtrx/game/input/backends/keyboard_tr2.def rename src/{tr1 => libtrx/include/libtrx}/game/input/common.h (95%) create mode 100644 src/libtrx/include/libtrx/game/input/role.h rename src/{tr1 => libtrx/include/libtrx}/game/input/state.h (71%) rename src/tr1/game/{input/common.c => input.c} (63%) delete mode 100644 src/tr1/game/input/role.h rename src/tr2/game/{shell.c => shell/common.c} (75%) create mode 100644 src/tr2/game/shell/common.h create mode 100644 src/tr2/game/shell/input.c create mode 100644 src/tr2/game/shell/input.h delete mode 100644 src/tr2/specific/s_input.c delete mode 100644 src/tr2/specific/s_input.h diff --git a/data/tr2/ship/cfg/TR2X_gameflow.json5 b/data/tr2/ship/cfg/TR2X_gameflow.json5 index e7488071d..e9fed2628 100644 --- a/data/tr2/ship/cfg/TR2X_gameflow.json5 +++ b/data/tr2/ship/cfg/TR2X_gameflow.json5 @@ -351,6 +351,10 @@ }, "game_strings": { + "CONTROL_CUSTOM_1": "Custom Scheme 1", + "CONTROL_CUSTOM_2": "Custom Scheme 2", + "CONTROL_CUSTOM_3": "Custom Scheme 3", + "CONTROL_DEFAULT_KEYS": "Default Keys", "MISC_OFF": "Off", "MISC_ON": "On", "OSD_AMBIGUOUS_INPUT_2": "Ambiguous input: %s and %s", diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index daf4291b0..49ec2cf19 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -1,4 +1,27 @@ ## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-0.5...develop) - ××××-××-×× +- changed the inputs backend from DirectX to SDL (#1695) + - improved controller support to match TR1X + - changed the number of custom layouts to 3 + - changed default key bindings according to the following table: + | Key | Old binding | New binding | Reason + | ----------------------------- | ----------- | ------------ | ----- + | Flare | Comma (,) | Period (.) | To maintain forward compatibility with TR3 + | Screenshot | S | Print Screen | To maintain compatibility with TR1X + | Toggle bilinear filter | F8 | F3 | To maintain compatibility with TR1X + | Toggle perspective filter | Shift+F8 | F4 | To maintain compatibility with TR1X + | Toggle z-buffer | F7 | F7 | Likely to be permanently enabled in the future + | Toggle triple buffering | Shift+F7 | **Removed** | Obscure setting, will be either removed or available via the ingame UI at some point + | Toggle dither | F11 | **Removed** | Obscure setting, will be either removed or available via the ingame UI at some point + | Toggle fullscreen | F12 | Alt-Enter | To maintain compatibility with TR1X + | Toggle rendering mode | Shift+F12 | F12 | No more conflict to require Shift + | Decrease resolution | F1 | Shift+F1 | F3 and F4 are already taken + | Increase resolution | F2 | F1 | F3 and F4 are already taken + | Decrease internal screen size | F3 | Shift+F2 | F3 and F4 are already taken + | Increase internal screen size | F4 | F2 | F3 and F4 are already taken + - removed "falling through" to the default layout, with the exception of keyboard arrows (matching TR1X behavior) + - removed hardcoded Shift+F7 key binding for toggling triple buffering + - removed hardcoded `0` key binding for flares + - removed hardcoded cooldown of 15 frames for medipacks - improved FMV mode appearance - removed black scanlines (#1729) - improved FMV mode behavior - stopped switching screen resolutions (#1729) - improved screenshots: now saved in the screenshots/ directory with level titles and timestamps as JPG or PNG, similar to TR1X (#1773) diff --git a/docs/tr2/progress.svg b/docs/tr2/progress.svg index 0964cc55c..d82f99d42 100644 --- a/docs/tr2/progress.svg +++ b/docs/tr2/progress.svg @@ -69,10 +69,10 @@ Tomb2.exe progress according to the physical function order: -70.02% (871) · 27.57% (343) · 0% (0) · 2.41% (30) +70.90% (882) · 26.69% (332) · 0% (0) · 2.41% (30) - - + + @@ -961,19 +961,19 @@ bool __cdecl DInputCreate(void); void __cdecl DInputRelease(void); void __cdecl WinInReadKeyboard(LPVOID lpInputData); -DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); +DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); sub_4473A0 -bool __cdecl WinInputInit(void); -bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); -BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); +bool __cdecl WinInputInit(void); +bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); +BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); void __thiscall S_FlaggedString_Create(STRING_FLAGGED *string, int32_t size); -JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); -void __cdecl DInputKeyboardCreate(void); -void __cdecl DInputKeyboardRelease(void); -bool __cdecl DInputJoystickCreate(void); -void __cdecl WinInStart(void); -void __cdecl WinInFinish(void); -void __cdecl WinInRunControlPanel(HWND hWnd); +JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); +void __cdecl DInputKeyboardCreate(void); +void __cdecl DInputKeyboardRelease(void); +bool __cdecl DInputJoystickCreate(void); +void __cdecl WinInStart(void); +void __cdecl WinInFinish(void); +void __cdecl WinInRunControlPanel(HWND hWnd); void __cdecl IncreaseScreenSize(void); void __cdecl DecreaseScreenSize(void); void __cdecl setup_screen_size(void); @@ -1324,10 +1324,10 @@ Tomb2.exe progress according to the function sizes: -74.33% · 25.34% · 0% · 0.33% +74.70% · 24.97% · 0% · 0.33% - - + + @@ -1708,7 +1708,7 @@ void __cdecl Output_InsertPolygons(const int16_t *obj_ptr, int32_t clip); void __cdecl ControlBubble1(int16_t fx_num); void __cdecl Lara_SurfaceCollision(ITEM *item, COLL_INFO *coll); -DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); +DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); int32_t __cdecl Box_StalkBox(const ITEM *item, const ITEM *enemy, int16_t box_num); void __cdecl Gun_Rifle_FireShotgun(void); void __cdecl SphereOfDoom(int16_t item_num); @@ -1718,14 +1718,14 @@ void __cdecl Lara_State_SurfTread(ITEM *item, COLL_INFO *coll); void __cdecl Output_InsertRoom(const int16_t *obj_ptr, int32_t is_outside); void __cdecl Output_CalculateObjectLighting(const ITEM *item, const FRAME_INFO *frame); -BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); +BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); void __cdecl CalculateWibbleTable(void); void __cdecl Camera_RefreshFromTrigger(int16_t type, const int16_t *data); int32_t __cdecl Lara_TestWaterStepOut(ITEM *item, COLL_INFO *coll); int32_t __cdecl S_Audio_Sample_Play(int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan, int32_t flags); void __cdecl Lara_TouchLava(ITEM *item); void __cdecl RenderFinish(bool need_to_clear_textures); -bool __cdecl DInputJoystickCreate(void); +bool __cdecl DInputJoystickCreate(void); void __cdecl S_InitialisePolyList(BOOL clear_back_buffer); void __cdecl Effect_Kill(int16_t fx_num); void __cdecl BigBowlControl(int16_t item_num); @@ -1770,7 +1770,7 @@ void __cdecl Output_InsertFlatRect(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t z, uint8_t color_idx); int32_t __cdecl Item_TestBoundsCollide(const ITEM *src_item, const ITEM *dst_item, int32_t radius); void __cdecl Lara_State_Wade(ITEM *item, COLL_INFO *coll); -void __cdecl DInputKeyboardCreate(void); +void __cdecl DInputKeyboardCreate(void); void __cdecl Room_GetNearbyRooms(int32_t x, int32_t y, int32_t z, int32_t r, int32_t h, int16_t room_num); void __cdecl Door_Control(int16_t item_num); BYTE __cdecl FindNearestPaletteEntry(RGB_888 *palette, int32_t red, int32_t green, int32_t blue, bool ignore_sys_palette); @@ -1961,7 +1961,7 @@ void __cdecl ControlExplosion1(int16_t fx_num); int32_t __cdecl Lara_DeflectEdge(ITEM *item, COLL_INFO *coll); void __cdecl SkidooDriver_Initialise(int16_t item_num); -bool __cdecl WinInputInit(void); +bool __cdecl WinInputInit(void); void __cdecl Random_Seed(void); void __cdecl Option_DoInventory(INVENTORY_ITEM *item); void __cdecl BellControl(int16_t item_num); @@ -2130,7 +2130,7 @@ void __cdecl Gun_Pistols_DrawMeshes(LARA_GUN_TYPE weapon_type); int32_t __cdecl MovableBlock_TestDestination(ITEM *item, int32_t block_height); void __cdecl ControlGunShot(int16_t fx_num); -JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); +JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); bool __cdecl OpenGameRegistryKey(LPCTSTR key); double __cdecl UT_Microseconds(void); void __cdecl Lara_State_Extra_StartAnim(ITEM *item, COLL_INFO *coll); @@ -2330,7 +2330,7 @@ void __cdecl S_DrawScreenFBox(int32_t sx, int32_t sy, int32_t z, int32_t width, int32_t height, BYTE color_idx, const GOURAUD_FILL *gour, uint16_t flags); void __cdecl Demo_GetInput(void); BOOL __cdecl Overlay_FlashCounter(void); -void __cdecl WinInStart(void); +void __cdecl WinInStart(void); void __cdecl ChandelierFX(ITEM *item); void __cdecl Overlay_DrawModeInfo(void); void __cdecl Inv_Ring_CalcAdders(RING_INFO *ring, int16_t rotation_duration); @@ -2354,7 +2354,7 @@ int32_t __cdecl S_Audio_Sample_CalculateSampleVolume(int32_t volume); LONG __cdecl SetRegistryBoolValue(LPCTSTR lpValueName, bool value); void __cdecl Text_AddOutline(TEXTSTRING *string, int16_t enable, int16_t color, uint16_t *gour_ptr, uint16_t flags); -void __cdecl DInputKeyboardRelease(void); +void __cdecl DInputKeyboardRelease(void); void __cdecl HWR_ResetTexSource(void); void __cdecl Overlay_MakeAmmoString(char *string); int32_t __cdecl CalculateWindowHeight(int32_t width, int32_t height); @@ -2379,7 +2379,7 @@ void __cdecl Inv_RemoveInventoryText(void); void __cdecl Sound_Shutdown(void); int16_t __cdecl Text_GetTextLength(const char *text); -bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); +bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); void __cdecl HWR_TexSource(HWR_TEXTURE_HANDLE tex_source); void __cdecl RubbleFX(ITEM *item); void __cdecl ExplosionFX(ITEM *item); @@ -2459,7 +2459,7 @@ int32_t __cdecl UT_MessageBox(LPCTSTR lpText, HWND hWnd); void __cdecl AssaultReset(ITEM *item); void __cdecl Text_SetScale(TEXTSTRING *string, int32_t scale_h, int32_t scale_v); -void __cdecl WinInRunControlPanel(HWND hWnd); +void __cdecl WinInRunControlPanel(HWND hWnd); sub_44E860 void __cdecl SE_GraphicsAdapterSet(HWND hwndDlg, DISPLAY_ADAPTER_NODE *adapter); void __cdecl S_Audio_Sample_OutCloseTrack(int32_t track_id); @@ -2500,7 +2500,7 @@ void __cdecl Text_RemoveOutline(TEXTSTRING *string); sub_44E880 void __cdecl ScreenPartialDump(void); -void __cdecl WinInFinish(void); +void __cdecl WinInFinish(void); void __cdecl S_FinishInventory(void); bool __cdecl IsNewRegistryKeyCreated(void); bool __cdecl S_PlayFMV(const char *file_name); diff --git a/docs/tr2/progress.txt b/docs/tr2/progress.txt index c1c3fde5c..665f2eb29 100644 --- a/docs/tr2/progress.txt +++ b/docs/tr2/progress.txt @@ -379,20 +379,20 @@ typedef struct __unaligned { } VERTEX_INFO; typedef enum { // decompiled - INPUT_ROLE_FORWARD = 0, - INPUT_ROLE_BACK = 1, - INPUT_ROLE_LEFT = 2, - INPUT_ROLE_RIGHT = 3, - INPUT_ROLE_STEP_LEFT = 4, - INPUT_ROLE_STEP_RIGHT = 5, - INPUT_ROLE_SLOW = 6, - INPUT_ROLE_JUMP = 7, - INPUT_ROLE_ACTION = 8, - INPUT_ROLE_DRAW_WEAPON = 9, - INPUT_ROLE_FLARE = 10, - INPUT_ROLE_LOOK = 11, - INPUT_ROLE_ROLL = 12, - INPUT_ROLE_OPTION = 13, + INPUT_ROLE_FORWARD = 0, + INPUT_ROLE_BACK = 1, + INPUT_ROLE_LEFT = 2, + INPUT_ROLE_RIGHT = 3, + INPUT_ROLE_STEP_L = 4, + INPUT_ROLE_STEP_R = 5, + INPUT_ROLE_SLOW = 6, + INPUT_ROLE_JUMP = 7, + INPUT_ROLE_ACTION = 8, + INPUT_ROLE_DRAW = 9, + INPUT_ROLE_USE_FLARE = 10, + INPUT_ROLE_LOOK = 11, + INPUT_ROLE_ROLL = 12, + INPUT_ROLE_OPTION = 13, } INPUT_ROLE; typedef struct __unaligned { @@ -3865,19 +3865,19 @@ typedef enum { 0x004471F0 0x0022 +R bool __cdecl DInputCreate(void); 0x00447220 0x001A +R void __cdecl DInputRelease(void); 0x00447240 0x005A +R void __cdecl WinInReadKeyboard(LPVOID lpInputData); -0x004472A0 0x00F3 -R DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); +0x004472A0 0x00F3 +R DWORD __cdecl WinInReadJoystick(int32_t *x, int32_t *y); 0x004473A0 0x0005 x sub_4473A0 -0x004473B0 0x007F -R bool __cdecl WinInputInit(void); -0x00447430 0x0024 -R bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); -0x00447460 0x00E8 -R BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); +0x004473B0 0x007F +R bool __cdecl WinInputInit(void); +0x00447430 0x0024 +R bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); +0x00447460 0x00E8 +R BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); 0x00447550 0x001F + void __thiscall S_FlaggedString_Create(STRING_FLAGGED *string, int32_t size); -0x00447570 0x004E -R JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); -0x004475C0 0x00C9 -R void __cdecl DInputKeyboardCreate(void); -0x00447690 0x0029 -R void __cdecl DInputKeyboardRelease(void); -0x004476C0 0x00E4 -R bool __cdecl DInputJoystickCreate(void); -0x004477B0 0x002D -R void __cdecl WinInStart(void); -0x004477E0 0x000F -R void __cdecl WinInFinish(void); -0x004477F0 0x0017 -R void __cdecl WinInRunControlPanel(HWND hWnd); +0x00447570 0x004E +R JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); +0x004475C0 0x00C9 +R void __cdecl DInputKeyboardCreate(void); +0x00447690 0x0029 +R void __cdecl DInputKeyboardRelease(void); +0x004476C0 0x00E4 +R bool __cdecl DInputJoystickCreate(void); +0x004477B0 0x002D +R void __cdecl WinInStart(void); +0x004477E0 0x000F +R void __cdecl WinInFinish(void); +0x004477F0 0x0017 +R void __cdecl WinInRunControlPanel(HWND hWnd); 0x00447810 0x0062 *R void __cdecl IncreaseScreenSize(void); 0x00447880 0x0062 *R void __cdecl DecreaseScreenSize(void); 0x004478F0 0x009F *R void __cdecl setup_screen_size(void); @@ -4455,7 +4455,7 @@ typedef enum { 0x0051A108 - uint8_t g_DIKeys[256]; 0x0051A208 + int32_t g_Input; 0x0051A20C - int8_t g_IsVidModeLock; -0x0051A210 - int32_t g_JoyKeys; +0x0051A210 + int32_t g_JoyKeys; 0x0051A214 + int32_t g_JoyXPos; 0x0051A218 + int32_t g_JoyYPos; 0x0051A220 + int32_t g_MediPackCooldown; @@ -4511,7 +4511,7 @@ typedef enum { 0x00526314 - int16_t g_CineFrameIdx; 0x00526320 - CAMERA_INFO g_Camera; 0x005263CC - BOX_INFO *g_Boxes; -0x004D855C - LPDIRECTINPUT g_DInput; +0x004D855C + LPDIRECTINPUT g_DInput; 0x004D8560 - LPDIRECTINPUTDEVICE IDID_SysKeyboard; 0x0051BDA0 - BOOL g_IsTitleLoaded; 0x004D7980 - int32_t g_Inv_ExtraData[8]; diff --git a/src/tr1/game/input/backends/controller.c b/src/libtrx/game/input/backends/controller.c similarity index 99% rename from src/tr1/game/input/backends/controller.c rename to src/libtrx/game/input/backends/controller.c index 3231f99d6..f51dce0a5 100644 --- a/src/tr1/game/input/backends/controller.c +++ b/src/libtrx/game/input/backends/controller.c @@ -1,8 +1,7 @@ #include "game/input/backends/controller.h" #include "game/input/backends/internal.h" - -#include +#include "log.h" #include #include @@ -31,6 +30,8 @@ static BUILTIN_CONTROLLER_LAYOUT m_BuiltinLayout[] = { { role, { button_type, { bind }, axis_dir } }, #if TR_VERSION == 1 #include "game/input/backends/controller_tr1.def" +#elif TR_VERSION == 2 + #include "game/input/backends/controller_tr2.def" #endif // guard { -1, { 0, { 0 }, 0 } }, @@ -383,7 +384,7 @@ static bool M_CustomUpdate(INPUT_STATE *const result, const INPUT_LAYOUT layout) if (m_Controller == NULL) { return false; } -#if TR_VERSION == 1 +#if TR_VERSION == 1 || TR_VERSION == 2 result->menu_back |= M_JoyBtn(SDL_CONTROLLER_BUTTON_Y); #endif return true; diff --git a/src/tr1/game/input/backends/internal.c b/src/libtrx/game/input/backends/internal.c similarity index 100% rename from src/tr1/game/input/backends/internal.c rename to src/libtrx/game/input/backends/internal.c diff --git a/src/tr1/game/input/backends/keyboard.c b/src/libtrx/game/input/backends/keyboard.c similarity index 98% rename from src/tr1/game/input/backends/keyboard.c rename to src/libtrx/game/input/backends/keyboard.c index 12bfe6063..c40e261a4 100644 --- a/src/tr1/game/input/backends/keyboard.c +++ b/src/libtrx/game/input/backends/keyboard.c @@ -11,14 +11,16 @@ typedef struct { SDL_Scancode scancode; } BUILTIN_KEYBOARD_LAYOUT; -const Uint8 *m_KeyboardState; +const Uint8 *m_KeyboardState = NULL; static bool m_Conflicts[INPUT_LAYOUT_NUMBER_OF][INPUT_ROLE_NUMBER_OF] = { 0 }; static BUILTIN_KEYBOARD_LAYOUT m_BuiltinLayout[] = { // clang-format off #define INPUT_KEYBOARD_ASSIGN(role, key) { role, key }, #if TR_VERSION == 1 -#include "keyboard_tr1.def" +#include "game/input/backends/keyboard_tr1.def" +#elif TR_VERSION == 2 +#include "game/input/backends/keyboard_tr2.def" #endif { -1, SDL_SCANCODE_UNKNOWN }, // clang-format on @@ -381,6 +383,10 @@ static bool M_CustomUpdate(INPUT_STATE *const result, const INPUT_LAYOUT layout) // we only do this for keyboard input #if TR_VERSION == 1 result->menu_confirm |= result->action; +#elif TR_VERSION == 2 + result->menu_confirm |= result->action; + result->toggle_fullscreen = + KEY_DOWN(SDL_SCANCODE_RETURN) && KEY_DOWN(SDL_SCANCODE_LALT); #endif return true; } diff --git a/src/libtrx/game/input/common.c b/src/libtrx/game/input/common.c new file mode 100644 index 000000000..99caec1ce --- /dev/null +++ b/src/libtrx/game/input/common.c @@ -0,0 +1,165 @@ +#include "game/input/common.h" + +#include "game/clock.h" +#include "game/game_string.h" +#include "game/input/backends/controller.h" +#include "game/input/backends/keyboard.h" + +#include + +INPUT_STATE g_Input = { 0 }; +INPUT_STATE g_InputDB = { 0 }; +INPUT_STATE g_OldInputDB = { 0 }; + +static bool m_ListenMode = false; + +static bool m_IsRoleHardcoded[INPUT_ROLE_NUMBER_OF] = { + 0, +#if TR_VERSION == 1 + [INPUT_ROLE_UNBIND_KEY] = 1, + [INPUT_ROLE_RESET_BINDINGS] = 1, + [INPUT_ROLE_PERSPECTIVE] = 1, +#endif + [INPUT_ROLE_MENU_CONFIRM] = 1, + [INPUT_ROLE_MENU_BACK] = 1, + [INPUT_ROLE_MENU_LEFT] = 1, + [INPUT_ROLE_MENU_RIGHT] = 1, + [INPUT_ROLE_MENU_UP] = 1, + [INPUT_ROLE_MENU_DOWN] = 1, +}; + +static const GAME_STRING_ID m_LayoutMap[INPUT_LAYOUT_NUMBER_OF] = { + [INPUT_LAYOUT_DEFAULT] = GS_ID(CONTROL_DEFAULT_KEYS), + [INPUT_LAYOUT_CUSTOM_1] = GS_ID(CONTROL_CUSTOM_1), + [INPUT_LAYOUT_CUSTOM_2] = GS_ID(CONTROL_CUSTOM_2), + [INPUT_LAYOUT_CUSTOM_3] = GS_ID(CONTROL_CUSTOM_3), +}; + +static INPUT_BACKEND_IMPL *M_GetBackend(INPUT_BACKEND backend); + +static INPUT_BACKEND_IMPL *M_GetBackend(const INPUT_BACKEND backend) +{ + switch (backend) { + case INPUT_BACKEND_KEYBOARD: + return &g_Input_Keyboard; + case INPUT_BACKEND_CONTROLLER: + return &g_Input_Controller; + } + return NULL; +} + +void Input_Init(void) +{ + if (g_Input_Keyboard.init != NULL) { + g_Input_Keyboard.init(); + } + if (g_Input_Controller.init != NULL) { + g_Input_Controller.init(); + } +} + +void Input_Shutdown(void) +{ + if (g_Input_Keyboard.shutdown != NULL) { + g_Input_Keyboard.shutdown(); + } + if (g_Input_Controller.shutdown != NULL) { + g_Input_Controller.shutdown(); + } +} + +void Input_InitController(void) +{ + if (g_Input_Controller.init != NULL) { + g_Input_Controller.init(); + } +} + +void Input_ShutdownController(void) +{ + if (g_Input_Controller.shutdown != NULL) { + g_Input_Controller.shutdown(); + } +} + +bool Input_IsRoleRebindable(const INPUT_ROLE role) +{ + return !m_IsRoleHardcoded[role]; +} + +bool Input_IsPressed( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + const INPUT_ROLE role) +{ + return M_GetBackend(backend)->is_pressed(layout, role); +} + +bool Input_IsKeyConflicted( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + const INPUT_ROLE role) +{ + return M_GetBackend(backend)->is_role_conflicted(layout, role); +} + +bool Input_ReadAndAssignRole( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + const INPUT_ROLE role) +{ + return M_GetBackend(backend)->read_and_assign(layout, role); +} + +void Input_UnassignRole( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + const INPUT_ROLE role) +{ + M_GetBackend(backend)->unassign_role(layout, role); +} + +const char *Input_GetKeyName( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + const INPUT_ROLE role) +{ + return M_GetBackend(backend)->get_name(layout, role); +} + +void Input_ResetLayout(const INPUT_BACKEND backend, const INPUT_LAYOUT layout) +{ + return M_GetBackend(backend)->reset_layout(layout); +} + +void Input_EnterListenMode(void) +{ + m_ListenMode = true; +} + +void Input_ExitListenMode(void) +{ + m_ListenMode = false; + Input_Update(); + g_OldInputDB.any = g_Input.any; + g_InputDB.any = g_Input.any; +} + +bool Input_IsInListenMode(void) +{ + return m_ListenMode; +} + +bool Input_AssignFromJSONObject( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + JSON_OBJECT *const bind_obj) +{ + return M_GetBackend(backend)->assign_from_json_object(layout, bind_obj); +} + +bool Input_AssignToJSONObject( + const INPUT_BACKEND backend, const INPUT_LAYOUT layout, + JSON_OBJECT *const bind_obj, const INPUT_ROLE role) +{ + return M_GetBackend(backend)->assign_to_json_object(layout, bind_obj, role); +} + +const char *Input_GetLayoutName(const INPUT_LAYOUT layout) +{ + return GameString_Get(m_LayoutMap[layout]); +} diff --git a/src/libtrx/include/libtrx/game/game_string.def b/src/libtrx/include/libtrx/game/game_string.def index 4877870d2..0b0c9c723 100644 --- a/src/libtrx/include/libtrx/game/game_string.def +++ b/src/libtrx/include/libtrx/game/game_string.def @@ -45,3 +45,7 @@ GS_DEFINE(OSD_AMBIGUOUS_INPUT_2, "Ambiguous input: %s and %s") GS_DEFINE(OSD_AMBIGUOUS_INPUT_3, "Ambiguous input: %s, %s, ...") GS_DEFINE(OSD_UI_ON, "UI enabled") GS_DEFINE(OSD_UI_OFF, "UI disabled") +GS_DEFINE(CONTROL_DEFAULT_KEYS, "Default Keys") +GS_DEFINE(CONTROL_CUSTOM_1, "Custom Scheme 1") +GS_DEFINE(CONTROL_CUSTOM_2, "Custom Scheme 2") +GS_DEFINE(CONTROL_CUSTOM_3, "Custom Scheme 3") diff --git a/src/libtrx/include/libtrx/game/input.h b/src/libtrx/include/libtrx/game/input.h index 4f5d68ef0..6982f1d16 100644 --- a/src/libtrx/include/libtrx/game/input.h +++ b/src/libtrx/include/libtrx/game/input.h @@ -1,4 +1,3 @@ #pragma once -extern void Input_EnterListenMode(void); -extern void Input_ExitListenMode(void); +#include "input/common.h" diff --git a/src/tr1/game/input/backends/base.h b/src/libtrx/include/libtrx/game/input/backends/base.h similarity index 96% rename from src/tr1/game/input/backends/base.h rename to src/libtrx/include/libtrx/game/input/backends/base.h index da73ebbed..8c379eeaf 100644 --- a/src/tr1/game/input/backends/base.h +++ b/src/libtrx/include/libtrx/game/input/backends/base.h @@ -1,6 +1,6 @@ #pragma once -#include "game/input/common.h" +#include "../common.h" #include diff --git a/src/tr1/game/input/backends/controller.h b/src/libtrx/include/libtrx/game/input/backends/controller.h similarity index 55% rename from src/tr1/game/input/backends/controller.h rename to src/libtrx/include/libtrx/game/input/backends/controller.h index 39b0574e4..1ac9b0814 100644 --- a/src/tr1/game/input/backends/controller.h +++ b/src/libtrx/include/libtrx/game/input/backends/controller.h @@ -1,3 +1,3 @@ -#include "game/input/backends/base.h" +#include "base.h" extern INPUT_BACKEND_IMPL g_Input_Controller; diff --git a/src/tr1/game/input/backends/controller_tr1.def b/src/libtrx/include/libtrx/game/input/backends/controller_tr1.def similarity index 100% rename from src/tr1/game/input/backends/controller_tr1.def rename to src/libtrx/include/libtrx/game/input/backends/controller_tr1.def diff --git a/src/libtrx/include/libtrx/game/input/backends/controller_tr2.def b/src/libtrx/include/libtrx/game/input/backends/controller_tr2.def new file mode 100644 index 000000000..eccd85490 --- /dev/null +++ b/src/libtrx/include/libtrx/game/input/backends/controller_tr2.def @@ -0,0 +1,15 @@ +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_UP, BT_BUTTON, SDL_CONTROLLER_BUTTON_DPAD_UP, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_DOWN, BT_BUTTON, SDL_CONTROLLER_BUTTON_DPAD_DOWN, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_LEFT, BT_BUTTON, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_RIGHT, BT_BUTTON, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_STEP_L, BT_AXIS, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 1) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_STEP_R, BT_AXIS, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 1) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_SLOW, BT_BUTTON, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_JUMP, BT_BUTTON, SDL_CONTROLLER_BUTTON_X, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_ACTION, BT_BUTTON, SDL_CONTROLLER_BUTTON_A, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_DRAW, BT_BUTTON, SDL_CONTROLLER_BUTTON_Y, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_LOOK, BT_BUTTON, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_ROLL, BT_BUTTON, SDL_CONTROLLER_BUTTON_B, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_OPTION, BT_BUTTON, SDL_CONTROLLER_BUTTON_BACK, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_MENU_CONFIRM, BT_BUTTON, SDL_CONTROLLER_BUTTON_A, 0) +INPUT_CONTROLLER_ASSIGN(INPUT_ROLE_MENU_BACK, BT_BUTTON, SDL_CONTROLLER_BUTTON_B, 0) diff --git a/src/tr1/game/input/backends/internal.h b/src/libtrx/include/libtrx/game/input/backends/internal.h similarity index 63% rename from src/tr1/game/input/backends/internal.h rename to src/libtrx/include/libtrx/game/input/backends/internal.h index acb033610..9c9519a0c 100644 --- a/src/tr1/game/input/backends/internal.h +++ b/src/libtrx/include/libtrx/game/input/backends/internal.h @@ -1,11 +1,11 @@ #pragma once -#include "game/input/backends/base.h" -#include "game/input/common.h" +#include "../common.h" +#include "base.h" void Input_UpdateFromBackend( - INPUT_STATE *const result, INPUT_LAYOUT layout, - const INPUT_BACKEND_IMPL *const backend); + INPUT_STATE *result, INPUT_LAYOUT layout, + const INPUT_BACKEND_IMPL *backend); void Input_ConflictHelper( INPUT_LAYOUT layout, diff --git a/src/tr1/game/input/backends/keyboard.h b/src/libtrx/include/libtrx/game/input/backends/keyboard.h similarity index 54% rename from src/tr1/game/input/backends/keyboard.h rename to src/libtrx/include/libtrx/game/input/backends/keyboard.h index 8a18e61f3..e1b99b49e 100644 --- a/src/tr1/game/input/backends/keyboard.h +++ b/src/libtrx/include/libtrx/game/input/backends/keyboard.h @@ -1,3 +1,3 @@ -#include "game/input/backends/base.h" +#include "base.h" extern INPUT_BACKEND_IMPL g_Input_Keyboard; diff --git a/src/tr1/game/input/backends/keyboard_tr1.def b/src/libtrx/include/libtrx/game/input/backends/keyboard_tr1.def similarity index 99% rename from src/tr1/game/input/backends/keyboard_tr1.def rename to src/libtrx/include/libtrx/game/input/backends/keyboard_tr1.def index c7361be04..639c6738b 100644 --- a/src/tr1/game/input/backends/keyboard_tr1.def +++ b/src/libtrx/include/libtrx/game/input/backends/keyboard_tr1.def @@ -2,46 +2,51 @@ INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_UP, SDL_SCANCODE_UP) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_DOWN, SDL_SCANCODE_DOWN) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LEFT, SDL_SCANCODE_LEFT) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_RIGHT, SDL_SCANCODE_RIGHT) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_L, SDL_SCANCODE_DELETE) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_R, SDL_SCANCODE_PAGEDOWN) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SLOW, SDL_SCANCODE_RSHIFT) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_JUMP, SDL_SCANCODE_RALT) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ACTION, SDL_SCANCODE_RCTRL) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_DRAW, SDL_SCANCODE_SPACE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ACTION, SDL_SCANCODE_RCTRL) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SLOW, SDL_SCANCODE_RSHIFT) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LOOK, SDL_SCANCODE_KP_0) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_L, SDL_SCANCODE_DELETE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_R, SDL_SCANCODE_PAGEDOWN) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ROLL, SDL_SCANCODE_END) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_OPTION, SDL_SCANCODE_ESCAPE) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_PAUSE, SDL_SCANCODE_P) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ENTER_CONSOLE, SDL_SCANCODE_SLASH) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SAVE, SDL_SCANCODE_F5) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LOAD, SDL_SCANCODE_F6) + INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_FLY_CHEAT, SDL_SCANCODE_O) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ITEM_CHEAT, SDL_SCANCODE_I) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LEVEL_SKIP_CHEAT, SDL_SCANCODE_L) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TURBO_CHEAT, SDL_SCANCODE_TAB) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_PAUSE, SDL_SCANCODE_P) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_UP, SDL_SCANCODE_Q) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_DOWN, SDL_SCANCODE_E) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_FORWARD, SDL_SCANCODE_W) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_BACK, SDL_SCANCODE_S) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_LEFT, SDL_SCANCODE_A) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_RIGHT, SDL_SCANCODE_D) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CHANGE_TARGET, SDL_SCANCODE_Z) + INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_PISTOLS, SDL_SCANCODE_1) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_SHOTGUN, SDL_SCANCODE_2) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_MAGNUMS, SDL_SCANCODE_3) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_UZIS, SDL_SCANCODE_4) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_USE_SMALL_MEDI, SDL_SCANCODE_8) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_USE_BIG_MEDI, SDL_SCANCODE_9) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SAVE, SDL_SCANCODE_F5) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LOAD, SDL_SCANCODE_F6) + INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_FPS, SDL_SCANCODE_F2) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_BILINEAR, SDL_SCANCODE_F3) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ENTER_CONSOLE, SDL_SCANCODE_SLASH) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CHANGE_TARGET, SDL_SCANCODE_Z) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_UI, SDL_SCANCODE_H) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_UP, SDL_SCANCODE_Q) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CAMERA_DOWN, SDL_SCANCODE_E) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_PHOTO_MODE, SDL_SCANCODE_F1) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_UNBIND_KEY, SDL_SCANCODE_BACKSPACE) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_RESET_BINDINGS, SDL_SCANCODE_R) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_PERSPECTIVE, SDL_SCANCODE_F4) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_OPTION, SDL_SCANCODE_ESCAPE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_BACK, SDL_SCANCODE_ESCAPE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_CONFIRM, SDL_SCANCODE_RETURN) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_UP, SDL_SCANCODE_UP) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_DOWN, SDL_SCANCODE_DOWN) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_LEFT, SDL_SCANCODE_LEFT) INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_RIGHT, SDL_SCANCODE_RIGHT) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_CONFIRM, SDL_SCANCODE_RETURN) -INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_BACK, SDL_SCANCODE_ESCAPE) diff --git a/src/libtrx/include/libtrx/game/input/backends/keyboard_tr2.def b/src/libtrx/include/libtrx/game/input/backends/keyboard_tr2.def new file mode 100644 index 000000000..070c361e9 --- /dev/null +++ b/src/libtrx/include/libtrx/game/input/backends/keyboard_tr2.def @@ -0,0 +1,45 @@ +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_UP, SDL_SCANCODE_UP) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_DOWN, SDL_SCANCODE_DOWN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LEFT, SDL_SCANCODE_LEFT) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_RIGHT, SDL_SCANCODE_RIGHT) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_JUMP, SDL_SCANCODE_RALT) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_DRAW, SDL_SCANCODE_SPACE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ACTION, SDL_SCANCODE_RCTRL) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SLOW, SDL_SCANCODE_RSHIFT) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LOOK, SDL_SCANCODE_KP_0) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_L, SDL_SCANCODE_DELETE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_STEP_R, SDL_SCANCODE_PAGEDOWN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ROLL, SDL_SCANCODE_END) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_ENTER_CONSOLE, SDL_SCANCODE_SLASH) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SAVE, SDL_SCANCODE_F5) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_LOAD, SDL_SCANCODE_F6) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_PISTOLS, SDL_SCANCODE_1) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_SHOTGUN, SDL_SCANCODE_2) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_MAGNUMS, SDL_SCANCODE_3) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_UZIS, SDL_SCANCODE_4) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_HARPOON, SDL_SCANCODE_5) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_M16, SDL_SCANCODE_6) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_EQUIP_GRENADE_LAUNCHER, SDL_SCANCODE_7) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_USE_SMALL_MEDI, SDL_SCANCODE_8) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_USE_BIG_MEDI, SDL_SCANCODE_9) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_USE_FLARE, SDL_SCANCODE_COMMA) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SCREENSHOT, SDL_SCANCODE_PRINTSCREEN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SWITCH_RESOLUTION, SDL_SCANCODE_F1) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SWITCH_INTERNAL_SCREEN_SIZE, SDL_SCANCODE_F2) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_BILINEAR_FILTER, SDL_SCANCODE_F3) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER, SDL_SCANCODE_F4) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_Z_BUFFER, SDL_SCANCODE_F7) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_DITHER, SDL_SCANCODE_UNKNOWN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_FULLSCREEN, SDL_SCANCODE_UNKNOWN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_RENDERING_MODE, SDL_SCANCODE_F12) + +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_OPTION, SDL_SCANCODE_ESCAPE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_BACK, SDL_SCANCODE_ESCAPE) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_CONFIRM, SDL_SCANCODE_RETURN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_UP, SDL_SCANCODE_UP) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_DOWN, SDL_SCANCODE_DOWN) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_LEFT, SDL_SCANCODE_LEFT) +INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_MENU_RIGHT, SDL_SCANCODE_RIGHT) diff --git a/src/tr1/game/input/common.h b/src/libtrx/include/libtrx/game/input/common.h similarity index 95% rename from src/tr1/game/input/common.h rename to src/libtrx/include/libtrx/game/input/common.h index 3899c6439..ec5e1f583 100644 --- a/src/tr1/game/input/common.h +++ b/src/libtrx/include/libtrx/game/input/common.h @@ -1,9 +1,8 @@ #pragma once -#include "game/input/role.h" -#include "game/input/state.h" - -#include +#include "../../json.h" +#include "role.h" +#include "state.h" #include #include @@ -74,6 +73,9 @@ void Input_EnterListenMode(void); // Enables updating g_Input. void Input_ExitListenMode(void); +// Checks whether updates are disabled. +bool Input_IsInListenMode(void); + // Restores the user configuration by converting the JSON object back into the // original input layout. bool Input_AssignFromJSONObject( diff --git a/src/libtrx/include/libtrx/game/input/role.h b/src/libtrx/include/libtrx/game/input/role.h new file mode 100644 index 000000000..bcbf94807 --- /dev/null +++ b/src/libtrx/include/libtrx/game/input/role.h @@ -0,0 +1,99 @@ +#pragma once + +typedef enum { +// clang-format off +#if TR_VERSION == 1 + INPUT_ROLE_UP = 0, + INPUT_ROLE_DOWN = 1, + INPUT_ROLE_LEFT = 2, + INPUT_ROLE_RIGHT = 3, + INPUT_ROLE_STEP_L = 4, + INPUT_ROLE_STEP_R = 5, + INPUT_ROLE_SLOW = 6, + INPUT_ROLE_JUMP = 7, + INPUT_ROLE_ACTION = 8, + INPUT_ROLE_DRAW = 9, + INPUT_ROLE_LOOK = 10, + INPUT_ROLE_ROLL = 11, + INPUT_ROLE_OPTION = 12, + INPUT_ROLE_FLY_CHEAT = 13, + INPUT_ROLE_ITEM_CHEAT = 14, + INPUT_ROLE_LEVEL_SKIP_CHEAT = 15, + INPUT_ROLE_TURBO_CHEAT = 16, + INPUT_ROLE_PAUSE = 17, + INPUT_ROLE_CAMERA_FORWARD = 18, + INPUT_ROLE_CAMERA_BACK = 19, + INPUT_ROLE_CAMERA_LEFT = 20, + INPUT_ROLE_CAMERA_RIGHT = 21, + INPUT_ROLE_CAMERA_RESET = 22, + INPUT_ROLE_EQUIP_PISTOLS = 23, + INPUT_ROLE_EQUIP_SHOTGUN = 24, + INPUT_ROLE_EQUIP_MAGNUMS = 25, + INPUT_ROLE_EQUIP_UZIS = 26, + INPUT_ROLE_USE_SMALL_MEDI = 27, + INPUT_ROLE_USE_BIG_MEDI = 28, + INPUT_ROLE_SAVE = 29, + INPUT_ROLE_LOAD = 30, + INPUT_ROLE_FPS = 31, + INPUT_ROLE_BILINEAR = 32, + INPUT_ROLE_ENTER_CONSOLE = 33, + INPUT_ROLE_CHANGE_TARGET = 34, + INPUT_ROLE_TOGGLE_UI = 35, + INPUT_ROLE_CAMERA_UP = 36, + INPUT_ROLE_CAMERA_DOWN = 37, + INPUT_ROLE_TOGGLE_PHOTO_MODE = 38, + INPUT_ROLE_UNBIND_KEY = 39, + INPUT_ROLE_RESET_BINDINGS = 40, + INPUT_ROLE_PERSPECTIVE = 42, + INPUT_ROLE_MENU_CONFIRM = 43, + INPUT_ROLE_MENU_BACK = 44, + INPUT_ROLE_MENU_LEFT = 45, + INPUT_ROLE_MENU_UP = 46, + INPUT_ROLE_MENU_DOWN = 47, + INPUT_ROLE_MENU_RIGHT = 48, +#elif TR_VERSION == 2 + INPUT_ROLE_UP = 0, + INPUT_ROLE_DOWN = 1, + INPUT_ROLE_LEFT = 2, + INPUT_ROLE_RIGHT = 3, + INPUT_ROLE_STEP_L = 4, + INPUT_ROLE_STEP_R = 5, + INPUT_ROLE_SLOW = 6, + INPUT_ROLE_JUMP = 7, + INPUT_ROLE_ACTION = 8, + INPUT_ROLE_DRAW = 9, + INPUT_ROLE_USE_FLARE = 10, + INPUT_ROLE_LOOK = 11, + INPUT_ROLE_ROLL = 12, + INPUT_ROLE_OPTION = 13, + INPUT_ROLE_ENTER_CONSOLE = 14, + INPUT_ROLE_MENU_CONFIRM = 15, + INPUT_ROLE_MENU_BACK = 16, + INPUT_ROLE_MENU_LEFT = 17, + INPUT_ROLE_MENU_UP = 18, + INPUT_ROLE_MENU_DOWN = 19, + INPUT_ROLE_MENU_RIGHT = 20, + INPUT_ROLE_SCREENSHOT = 21, + INPUT_ROLE_EQUIP_PISTOLS = 22, + INPUT_ROLE_EQUIP_SHOTGUN = 23, + INPUT_ROLE_EQUIP_MAGNUMS = 24, + INPUT_ROLE_EQUIP_UZIS = 25, + INPUT_ROLE_EQUIP_HARPOON = 26, + INPUT_ROLE_EQUIP_M16 = 27, + INPUT_ROLE_EQUIP_GRENADE_LAUNCHER = 28, + INPUT_ROLE_USE_SMALL_MEDI = 29, + INPUT_ROLE_USE_BIG_MEDI = 30, + INPUT_ROLE_SAVE = 31, + INPUT_ROLE_LOAD = 32, + INPUT_ROLE_SWITCH_RESOLUTION = 33, + INPUT_ROLE_SWITCH_INTERNAL_SCREEN_SIZE = 34, + INPUT_ROLE_TOGGLE_BILINEAR_FILTER = 35, + INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER = 36, + INPUT_ROLE_TOGGLE_Z_BUFFER = 37, + INPUT_ROLE_TOGGLE_DITHER = 38, + INPUT_ROLE_TOGGLE_FULLSCREEN = 39, + INPUT_ROLE_TOGGLE_RENDERING_MODE = 40, +#endif + INPUT_ROLE_NUMBER_OF, + // clang-format on +} INPUT_ROLE; diff --git a/src/tr1/game/input/state.h b/src/libtrx/include/libtrx/game/input/state.h similarity index 71% rename from src/tr1/game/input/state.h rename to src/libtrx/include/libtrx/game/input/state.h index 8d2e4f2cf..2ecc70fde 100644 --- a/src/tr1/game/input/state.h +++ b/src/libtrx/include/libtrx/game/input/state.h @@ -13,14 +13,17 @@ typedef union INPUT_STATE { uint64_t draw : 1; uint64_t action : 1; uint64_t slow : 1; - uint64_t option : 1; uint64_t look : 1; uint64_t step_left : 1; uint64_t step_right : 1; uint64_t roll : 1; + uint64_t pause : 1; + uint64_t enter_console : 1; uint64_t save : 1; uint64_t load : 1; + +#if TR_VERSION == 1 uint64_t fly_cheat : 1; uint64_t item_cheat : 1; uint64_t level_skip_cheat : 1; @@ -32,24 +35,48 @@ typedef union INPUT_STATE { uint64_t camera_left : 1; uint64_t camera_right : 1; uint64_t camera_reset : 1; + uint64_t change_target : 1; +#endif + uint64_t equip_pistols : 1; uint64_t equip_shotgun : 1; uint64_t equip_magnums : 1; uint64_t equip_uzis : 1; +#if TR_VERSION == 2 + uint64_t equip_harpoon : 1; + uint64_t equip_m16 : 1; + uint64_t equip_grenade_launcher : 1; +#endif uint64_t use_small_medi : 1; uint64_t use_big_medi : 1; +#if TR_VERSION == 2 + uint64_t use_flare : 1; +#endif + +#if TR_VERSION == 1 uint64_t toggle_bilinear_filter : 1; uint64_t toggle_perspective_filter : 1; uint64_t toggle_fps_counter : 1; + uint64_t toggle_ui : 1; + uint64_t toggle_photo_mode : 1; +#elif TR_VERSION == 2 + uint64_t screenshot : 1; + uint64_t switch_resolution : 1; + uint64_t switch_internal_screen_size : 1; + uint64_t toggle_bilinear_filter : 1; + uint64_t toggle_perspective_filter : 1; + uint64_t toggle_z_buffer : 1; + uint64_t toggle_dither : 1; + uint64_t toggle_fullscreen : 1; + uint64_t toggle_rendering_mode : 1; +#endif + + uint64_t option : 1; + uint64_t menu_back : 1; + uint64_t menu_confirm : 1; uint64_t menu_up : 1; uint64_t menu_down : 1; uint64_t menu_left : 1; uint64_t menu_right : 1; - uint64_t menu_confirm : 1; - uint64_t menu_back : 1; - uint64_t enter_console : 1; - uint64_t change_target : 1; - uint64_t toggle_ui : 1; - uint64_t toggle_photo_mode : 1; }; } INPUT_STATE; diff --git a/src/libtrx/meson.build b/src/libtrx/meson.build index 31939a157..fa7180ad3 100644 --- a/src/libtrx/meson.build +++ b/src/libtrx/meson.build @@ -90,6 +90,10 @@ sources = [ 'game/console/common.c', 'game/console/history.c', 'game/game_string.c', + 'game/input/backends/controller.c', + 'game/input/backends/internal.c', + 'game/input/backends/keyboard.c', + 'game/input/common.c', 'game/items.c', 'game/objects/common.c', 'game/objects/names.c', diff --git a/src/tr1/game/game_string.def b/src/tr1/game/game_string.def index 5e92519b3..612801103 100644 --- a/src/tr1/game/game_string.def +++ b/src/tr1/game/game_string.def @@ -44,10 +44,6 @@ GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes") GS_DEFINE(CONTROL_CUSTOMIZE, "Customize Controls") GS_DEFINE(CONTROL_KEYBOARD, "Keyboard") GS_DEFINE(CONTROL_CONTROLLER, "Controller") -GS_DEFINE(CONTROL_DEFAULT_KEYS, "Default Keys") -GS_DEFINE(CONTROL_CUSTOM_1, "Custom Scheme 1") -GS_DEFINE(CONTROL_CUSTOM_2, "Custom Scheme 2") -GS_DEFINE(CONTROL_CUSTOM_3, "Custom Scheme 3") GS_DEFINE(CONTROL_RESET_DEFAULTS, "Reset All: Hold %s") GS_DEFINE(CONTROL_UNBIND, "Unbind: Hold %s") GS_DEFINE(KEYMAP_RUN, "Run") diff --git a/src/tr1/game/input/common.c b/src/tr1/game/input.c similarity index 63% rename from src/tr1/game/input/common.c rename to src/tr1/game/input.c index 2dd53101e..1bcf0b4e1 100644 --- a/src/tr1/game/input/common.c +++ b/src/tr1/game/input.c @@ -1,33 +1,20 @@ -#include "game/input/common.h" +#include "game/input.h" #include "config.h" #include "game/clock.h" -#include "game/game_string.h" -#include "game/input/backends/controller.h" -#include "game/input/backends/keyboard.h" #include "global/vars.h" -#include +#include +#include +#include #define DELAY_FRAMES 12 #define HOLD_FRAMES 3 -INPUT_STATE g_Input = { 0 }; -INPUT_STATE g_InputDB = { 0 }; -INPUT_STATE g_OldInputDB = { 0 }; - static int32_t m_HoldBack = 0; static int32_t m_HoldForward = 0; -static bool m_ListenMode = false; -static const GAME_STRING_ID m_LayoutMap[INPUT_LAYOUT_NUMBER_OF] = { - [INPUT_LAYOUT_DEFAULT] = GS_ID(CONTROL_DEFAULT_KEYS), - [INPUT_LAYOUT_CUSTOM_1] = GS_ID(CONTROL_CUSTOM_1), - [INPUT_LAYOUT_CUSTOM_2] = GS_ID(CONTROL_CUSTOM_2), - [INPUT_LAYOUT_CUSTOM_3] = GS_ID(CONTROL_CUSTOM_3), -}; static INPUT_STATE M_GetDebounced(INPUT_STATE input); -static INPUT_BACKEND_IMPL *M_GetBackend(INPUT_BACKEND backend); static void M_UpdateFromBackend( INPUT_STATE *s, const INPUT_BACKEND_IMPL *backend, int32_t layout); @@ -63,17 +50,6 @@ static INPUT_STATE M_GetDebounced(const INPUT_STATE input) return result; } -static INPUT_BACKEND_IMPL *M_GetBackend(const INPUT_BACKEND backend) -{ - switch (backend) { - case INPUT_BACKEND_KEYBOARD: - return &g_Input_Keyboard; - case INPUT_BACKEND_CONTROLLER: - return &g_Input_Controller; - } - return NULL; -} - static void M_UpdateFromBackend( INPUT_STATE *const s, const INPUT_BACKEND_IMPL *const backend, const int32_t layout) @@ -91,7 +67,7 @@ static void M_UpdateFromBackend( s->draw |= backend->is_pressed(layout, INPUT_ROLE_DRAW); s->look |= backend->is_pressed(layout, INPUT_ROLE_LOOK); s->roll |= backend->is_pressed(layout, INPUT_ROLE_ROLL); - s->option |= backend->is_pressed(layout, INPUT_ROLE_OPTION); + s->pause |= backend->is_pressed(layout, INPUT_ROLE_PAUSE); s->toggle_photo_mode |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_PHOTO_MODE); s->camera_up |= backend->is_pressed(layout, INPUT_ROLE_CAMERA_UP); @@ -115,6 +91,7 @@ static void M_UpdateFromBackend( s->use_small_medi |= backend->is_pressed(layout, INPUT_ROLE_USE_SMALL_MEDI); s->use_big_medi |= backend->is_pressed(layout, INPUT_ROLE_USE_BIG_MEDI); + s->option |= backend->is_pressed(layout, INPUT_ROLE_OPTION); s->menu_up |= backend->is_pressed(layout, INPUT_ROLE_MENU_UP); s->menu_down |= backend->is_pressed(layout, INPUT_ROLE_MENU_DOWN); s->menu_left |= backend->is_pressed(layout, INPUT_ROLE_MENU_LEFT); @@ -134,49 +111,6 @@ static void M_UpdateFromBackend( backend->custom_update(s, layout); } -void Input_Init(void) -{ - if (g_Input_Keyboard.init != NULL) { - g_Input_Keyboard.init(); - } - if (g_Input_Controller.init != NULL) { - g_Input_Controller.init(); - } -} - -void Input_Shutdown(void) -{ - if (g_Input_Keyboard.shutdown != NULL) { - g_Input_Keyboard.shutdown(); - } - if (g_Input_Controller.shutdown != NULL) { - g_Input_Controller.shutdown(); - } -} - -void Input_InitController(void) -{ - if (g_Input_Controller.init != NULL) { - g_Input_Controller.init(); - } -} - -void Input_ShutdownController(void) -{ - if (g_Input_Controller.shutdown != NULL) { - g_Input_Controller.shutdown(); - } -} - -bool Input_IsRoleRebindable(const INPUT_ROLE role) -{ - return role != INPUT_ROLE_UNBIND_KEY && role != INPUT_ROLE_RESET_BINDINGS - && role != INPUT_ROLE_PERSPECTIVE && role != INPUT_ROLE_MENU_CONFIRM - && role != INPUT_ROLE_MENU_BACK && role != INPUT_ROLE_MENU_LEFT - && role != INPUT_ROLE_MENU_RIGHT && role != INPUT_ROLE_MENU_UP - && role != INPUT_ROLE_MENU_DOWN; -} - void Input_Update(void) { g_Input.any = 0; @@ -224,80 +158,8 @@ void Input_Update(void) g_InputDB = M_GetDebounced(g_Input); - if (m_ListenMode) { - g_Input = (INPUT_STATE) { 0 }; - g_InputDB = (INPUT_STATE) { 0 }; + if (Input_IsInListenMode()) { + g_Input.any = 0; + g_InputDB.any = 0; } } - -bool Input_IsPressed( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - const INPUT_ROLE role) -{ - return M_GetBackend(backend)->is_pressed(layout, role); -} - -bool Input_IsKeyConflicted( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - const INPUT_ROLE role) -{ - return M_GetBackend(backend)->is_role_conflicted(layout, role); -} - -bool Input_ReadAndAssignRole( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - const INPUT_ROLE role) -{ - return M_GetBackend(backend)->read_and_assign(layout, role); -} - -void Input_UnassignRole( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - const INPUT_ROLE role) -{ - M_GetBackend(backend)->unassign_role(layout, role); -} - -const char *Input_GetLayoutName(const INPUT_LAYOUT layout) -{ - return GameString_Get(m_LayoutMap[layout]); -} - -const char *Input_GetKeyName( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - const INPUT_ROLE role) -{ - return M_GetBackend(backend)->get_name(layout, role); -} - -void Input_ResetLayout(const INPUT_BACKEND backend, const INPUT_LAYOUT layout) -{ - return M_GetBackend(backend)->reset_layout(layout); -} - -void Input_EnterListenMode(void) -{ - m_ListenMode = true; -} - -void Input_ExitListenMode(void) -{ - m_ListenMode = false; - Input_Update(); - g_OldInputDB.any = g_Input.any; - g_InputDB.any = g_Input.any; -} - -bool Input_AssignFromJSONObject( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - JSON_OBJECT *const bind_obj) -{ - return M_GetBackend(backend)->assign_from_json_object(layout, bind_obj); -} - -bool Input_AssignToJSONObject( - const INPUT_BACKEND backend, const INPUT_LAYOUT layout, - JSON_OBJECT *const bind_obj, const INPUT_ROLE role) -{ - return M_GetBackend(backend)->assign_to_json_object(layout, bind_obj, role); -} diff --git a/src/tr1/game/input.h b/src/tr1/game/input.h index 0a971adf3..6f2d02c9b 100644 --- a/src/tr1/game/input.h +++ b/src/tr1/game/input.h @@ -1,3 +1,3 @@ #pragma once -#include "game/input/common.h" +#include diff --git a/src/tr1/game/input/role.h b/src/tr1/game/input/role.h deleted file mode 100644 index 6454f07fc..000000000 --- a/src/tr1/game/input/role.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -typedef enum { - // clang-format off - INPUT_ROLE_UP = 0, - INPUT_ROLE_DOWN = 1, - INPUT_ROLE_LEFT = 2, - INPUT_ROLE_RIGHT = 3, - INPUT_ROLE_STEP_L = 4, - INPUT_ROLE_STEP_R = 5, - INPUT_ROLE_SLOW = 6, - INPUT_ROLE_JUMP = 7, - INPUT_ROLE_ACTION = 8, - INPUT_ROLE_DRAW = 9, - INPUT_ROLE_LOOK = 10, - INPUT_ROLE_ROLL = 11, - INPUT_ROLE_OPTION = 12, - INPUT_ROLE_FLY_CHEAT = 13, - INPUT_ROLE_ITEM_CHEAT = 14, - INPUT_ROLE_LEVEL_SKIP_CHEAT = 15, - INPUT_ROLE_TURBO_CHEAT = 16, - INPUT_ROLE_PAUSE = 17, - INPUT_ROLE_CAMERA_FORWARD = 18, - INPUT_ROLE_CAMERA_BACK = 19, - INPUT_ROLE_CAMERA_LEFT = 20, - INPUT_ROLE_CAMERA_RIGHT = 21, - INPUT_ROLE_CAMERA_RESET = 22, - INPUT_ROLE_EQUIP_PISTOLS = 23, - INPUT_ROLE_EQUIP_SHOTGUN = 24, - INPUT_ROLE_EQUIP_MAGNUMS = 25, - INPUT_ROLE_EQUIP_UZIS = 26, - INPUT_ROLE_USE_SMALL_MEDI = 27, - INPUT_ROLE_USE_BIG_MEDI = 28, - INPUT_ROLE_SAVE = 29, - INPUT_ROLE_LOAD = 30, - INPUT_ROLE_FPS = 31, - INPUT_ROLE_BILINEAR = 32, - INPUT_ROLE_ENTER_CONSOLE = 33, - INPUT_ROLE_CHANGE_TARGET = 34, - INPUT_ROLE_TOGGLE_UI = 35, - INPUT_ROLE_CAMERA_UP = 36, - INPUT_ROLE_CAMERA_DOWN = 37, - INPUT_ROLE_TOGGLE_PHOTO_MODE = 38, - INPUT_ROLE_UNBIND_KEY = 39, - INPUT_ROLE_RESET_BINDINGS = 40, - INPUT_ROLE_PERSPECTIVE = 42, - INPUT_ROLE_MENU_CONFIRM = 43, - INPUT_ROLE_MENU_BACK = 44, - INPUT_ROLE_MENU_LEFT = 45, - INPUT_ROLE_MENU_UP = 46, - INPUT_ROLE_MENU_DOWN = 47, - INPUT_ROLE_MENU_RIGHT = 48, - INPUT_ROLE_NUMBER_OF, - // clang-format on -} INPUT_ROLE; diff --git a/src/tr1/game/ui/common.c b/src/tr1/game/ui/common.c index 8cdc15cbc..c3401ebda 100644 --- a/src/tr1/game/ui/common.c +++ b/src/tr1/game/ui/common.c @@ -18,15 +18,15 @@ UI_INPUT UI_TranslateInput(uint32_t system_keycode) { // clang-format off switch (system_keycode) { - case SDLK_UP: return UI_KEY_UP; - case SDLK_DOWN: return UI_KEY_DOWN; - case SDLK_LEFT: return UI_KEY_LEFT; - case SDLK_RIGHT: return UI_KEY_RIGHT; - case SDLK_HOME: return UI_KEY_HOME; - case SDLK_END: return UI_KEY_END; - case SDLK_BACKSPACE: return UI_KEY_BACK; - case SDLK_RETURN: return UI_KEY_RETURN; - case SDLK_ESCAPE: return UI_KEY_ESCAPE; + case SDLK_UP: return UI_KEY_UP; + case SDLK_DOWN: return UI_KEY_DOWN; + case SDLK_LEFT: return UI_KEY_LEFT; + case SDLK_RIGHT: return UI_KEY_RIGHT; + case SDLK_HOME: return UI_KEY_HOME; + case SDLK_END: return UI_KEY_END; + case SDLK_BACKSPACE: return UI_KEY_BACK; + case SDLK_RETURN: return UI_KEY_RETURN; + case SDLK_ESCAPE: return UI_KEY_ESCAPE; } // clang-format on return -1; diff --git a/src/tr1/meson.build b/src/tr1/meson.build index 5497e2d4f..fc15c295e 100644 --- a/src/tr1/meson.build +++ b/src/tr1/meson.build @@ -139,10 +139,7 @@ sources = [ 'game/gun/gun_pistols.c', 'game/gun/gun_rifle.c', 'game/inject.c', - 'game/input/backends/controller.c', - 'game/input/backends/internal.c', - 'game/input/backends/keyboard.c', - 'game/input/common.c', + 'game/input.c', 'game/interpolation.c', 'game/inventory/inventory.c', 'game/inventory/inventory_func.c', diff --git a/src/tr1/specific/s_shell.c b/src/tr1/specific/s_shell.c index 0a7bc1f03..afefb520c 100644 --- a/src/tr1/specific/s_shell.c +++ b/src/tr1/specific/s_shell.c @@ -202,7 +202,6 @@ void S_Shell_SpinMessageLoop(void) S_Shell_ToggleFullscreen(); break; } - break; case SDL_WINDOWEVENT: diff --git a/src/tr2/config.c b/src/tr2/config.c index f24bf7326..4e6d24830 100644 --- a/src/tr2/config.c +++ b/src/tr2/config.c @@ -1,13 +1,105 @@ #include "config.h" #include "config_map.h" +#include "game/input.h" #include +#include +#include + CONFIG g_Config = { 0 }; static const char *m_ConfigPath = "cfg/TR2X.json5"; +static void M_LoadInputConfig(JSON_OBJECT *root_obj); +static void M_LoadInputLayout( + JSON_OBJECT *parent_obj, INPUT_BACKEND backend, INPUT_LAYOUT layout); +static void M_DumpInputConfig(JSON_OBJECT *root_obj); +static void M_DumpInputLayout( + JSON_OBJECT *parent_obj, INPUT_BACKEND backend, INPUT_LAYOUT layout); + +static void M_LoadInputConfig(JSON_OBJECT *const root_obj) +{ + JSON_OBJECT *const input_obj = JSON_ObjectGetObject(root_obj, "input"); + if (input_obj == NULL) { + return; + } + + JSON_OBJECT *const keyboard_obj = + JSON_ObjectGetObject(input_obj, "keyboard"); + JSON_OBJECT *const controller_obj = + JSON_ObjectGetObject(input_obj, "controller"); + for (INPUT_LAYOUT layout = INPUT_LAYOUT_CUSTOM_1; + layout < INPUT_LAYOUT_NUMBER_OF; layout++) { + if (keyboard_obj != NULL) { + M_LoadInputLayout(keyboard_obj, INPUT_BACKEND_KEYBOARD, layout); + } + if (controller_obj != NULL) { + M_LoadInputLayout(controller_obj, INPUT_BACKEND_CONTROLLER, layout); + } + } +} + +static void M_LoadInputLayout( + JSON_OBJECT *const parent_obj, const INPUT_BACKEND backend, + const INPUT_LAYOUT layout) +{ + char layout_name[20]; + sprintf(layout_name, "layout_%d", layout); + JSON_ARRAY *const arr = JSON_ObjectGetArray(parent_obj, layout_name); + if (arr == NULL) { + return; + } + + for (size_t i = 0; i < arr->length; i++) { + JSON_OBJECT *const bind_obj = JSON_ArrayGetObject(arr, i); + assert(bind_obj != NULL); + Input_AssignFromJSONObject(backend, layout, bind_obj); + } +} + +static void M_DumpInputConfig(JSON_OBJECT *const root_obj) +{ + JSON_OBJECT *const input_obj = JSON_ObjectNew(); + JSON_OBJECT *const keyboard_obj = JSON_ObjectNew(); + JSON_OBJECT *const controller_obj = JSON_ObjectNew(); + JSON_ObjectAppendObject(root_obj, "input", input_obj); + JSON_ObjectAppendObject(input_obj, "keyboard", keyboard_obj); + JSON_ObjectAppendObject(input_obj, "controller", controller_obj); + for (INPUT_LAYOUT layout = INPUT_LAYOUT_CUSTOM_1; + layout < INPUT_LAYOUT_NUMBER_OF; layout++) { + M_DumpInputLayout(keyboard_obj, INPUT_BACKEND_KEYBOARD, layout); + M_DumpInputLayout(controller_obj, INPUT_BACKEND_CONTROLLER, layout); + } +} + +static void M_DumpInputLayout( + JSON_OBJECT *const parent_obj, const INPUT_BACKEND backend, + const INPUT_LAYOUT layout) +{ + JSON_ARRAY *const arr = JSON_ArrayNew(); + + bool has_elements = false; + for (INPUT_ROLE role = 0; role < INPUT_ROLE_NUMBER_OF; role++) { + JSON_OBJECT *const bind_obj = JSON_ObjectNew(); + if (Input_AssignToJSONObject(backend, layout, bind_obj, role)) { + has_elements = true; + JSON_ArrayAppendObject(arr, bind_obj); + } else { + JSON_ObjectFree(bind_obj); + } + } + + if (has_elements) { + char layout_name[20]; + sprintf(layout_name, "layout_%d", layout); + JSON_ObjectAppendArray(parent_obj, layout_name, arr); + } else { + JSON_ArrayFree(arr); + } +} + const char *Config_GetPath(void) { return m_ConfigPath; @@ -16,11 +108,13 @@ const char *Config_GetPath(void) void Config_LoadFromJSON(JSON_OBJECT *root_obj) { ConfigFile_LoadOptions(root_obj, g_ConfigOptionMap); + M_LoadInputConfig(root_obj); } void Config_DumpToJSON(JSON_OBJECT *root_obj) { ConfigFile_DumpOptions(root_obj, g_ConfigOptionMap); + M_DumpInputConfig(root_obj); } void Config_Sanitize(void) diff --git a/src/tr2/config.h b/src/tr2/config.h index b8b244920..c3302c164 100644 --- a/src/tr2/config.h +++ b/src/tr2/config.h @@ -8,6 +8,11 @@ typedef struct { bool loaded; + struct { + int32_t keyboard_layout; + int32_t controller_layout; + } input; + struct { bool fix_m16_accuracy; } gameplay; diff --git a/src/tr2/config_map.c b/src/tr2/config_map.c index 82a3299d2..954102af9 100644 --- a/src/tr2/config_map.c +++ b/src/tr2/config_map.c @@ -6,6 +6,7 @@ #include // import order guard +#include "game/input.h" #include "global/types.h" const CONFIG_OPTION g_ConfigOptionMap[] = { diff --git a/src/tr2/config_map.def b/src/tr2/config_map.def index addba8f0f..270ded597 100644 --- a/src/tr2/config_map.def +++ b/src/tr2/config_map.def @@ -1,2 +1,4 @@ CFG_BOOL(g_Config, gameplay.fix_m16_accuracy, true) CFG_ENUM(g_Config, rendering.screenshot_format, SCREENSHOT_FORMAT_JPEG, SCREENSHOT_FORMAT) +CFG_INT32(g_Config, input.keyboard_layout, INPUT_LAYOUT_DEFAULT) +CFG_INT32(g_Config, input.controller_layout, INPUT_LAYOUT_DEFAULT) diff --git a/src/tr2/decomp/decomp.c b/src/tr2/decomp/decomp.c index bfdea072d..d3ec31fc0 100644 --- a/src/tr2/decomp/decomp.c +++ b/src/tr2/decomp/decomp.c @@ -29,7 +29,6 @@ #include "global/funcs.h" #include "global/vars.h" #include "lib/ddraw.h" -#include "lib/dinput.h" #include "specific/s_flagged_string.h" #include @@ -39,8 +38,8 @@ #include #include +#include #include -#include #include #define IDI_MAINICON 100 @@ -193,12 +192,10 @@ int32_t __cdecl GameInit(void) Music_Shutdown(); UT_InitAccurateTimer(); // clang-format off - Sound_Init(); return WinVidInit() && Direct3DInit() && RenderInit() && InitTextures() - && WinInputInit() && TIME_Init() && HWR_Init() && BGND_Init(); @@ -280,31 +277,15 @@ int32_t __cdecl RenderErrorBox(int32_t error_code) bool __cdecl DInputCreate(void) { - return SUCCEEDED(DirectInputCreate(g_GameModule, 1280, &g_DInput, NULL)); + return true; } void __cdecl DInputRelease(void) { - if (g_DInput) { - IDirectInput_Release(g_DInput); - g_DInput = NULL; - } } void __cdecl WinInReadKeyboard(uint8_t *input_data) { - if (SUCCEEDED(IDirectInputDevice_GetDeviceState( - IDID_SysKeyboard, 256, input_data))) { - return; - } - - if (SUCCEEDED(IDirectInputDevice_Acquire(IDID_SysKeyboard)) - && SUCCEEDED(IDirectInputDevice_GetDeviceState( - IDID_SysKeyboard, 256, input_data))) { - return; - } - - memset(input_data, 0, 256); } int32_t __cdecl WinGameStart(void) @@ -312,7 +293,6 @@ int32_t __cdecl WinGameStart(void) // try { WinVidStart(); RenderStart(true); - WinInStart(); // } catch (int32_t error) { // return error; // } @@ -503,16 +483,6 @@ bool __cdecl WinVidSpinMessageLoop(bool need_wait) g_StopInventory = true; g_MessageLoopCounter--; return 0; - } else if (msg.message == WM_KEYDOWN) { - UI_HandleKeyDown(msg.wParam); - return 0; - } else if (msg.message == WM_KEYUP) { - UI_HandleKeyUp(msg.wParam); - return 0; - } else if (msg.message == WM_CHAR) { - char insert_string[2] = { msg.wParam, '\0' }; - UI_HandleTextEdit(insert_string); - return 0; } } } while (!g_IsGameWindowActive || g_IsGameWindowMinimized); @@ -963,15 +933,15 @@ int32_t __cdecl Game_Cutscene_Control(const int32_t nframes) return 4; } - if (Input_Update()) { - return 3; - } + Shell_ProcessEvents(); + Input_Update(); if (g_InputDB.action) { return 1; } if (g_InputDB.option) { return 2; } + Shell_ProcessInput(); g_DynamicLightCount = 0; @@ -2043,8 +2013,11 @@ bool __cdecl DDrawCreate(LPGUID lpGUID) return false; } - g_DDraw->lpVtbl->SetCooperativeLevel( - g_DDraw, g_GameWindowHandle, DDSCL_NORMAL); + if (FAILED(g_DDraw->lpVtbl->SetCooperativeLevel( + g_DDraw, g_GameWindowHandle, DDSCL_NORMAL))) { + return false; + } + return true; } @@ -2617,6 +2590,19 @@ bool __cdecl WinVidCreateGameWindow(void) return false; } + int32_t result = SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO); + if (result < 0) { + Shell_ExitSystemFmt( + "Error while calling SDL_Init: 0x%lx, %s", result, SDL_GetError()); + return false; + } + + SDL_Window *sdl_window = SDL_CreateWindowFrom(g_GameWindowHandle); + if (sdl_window == NULL) { + Shell_ExitSystemFmt("Failed to create SDL window: %s", SDL_GetError()); + return false; + } + RECT rect; GetWindowRect(g_GameWindowHandle, &rect); g_GameWindowX = rect.left; @@ -2772,14 +2758,8 @@ void __cdecl S_LoadSettings(void) } GetRegistryFloatValue("Sizer", &g_GameSizerCopy, 1.0); - GetRegistryBinaryValue( - "Layout", (uint8_t *)&g_Layout[1], - sizeof(uint16_t) * INPUT_ROLE_NUMBER_OF, 0); - CloseGameRegistryKey(); - Input_CheckConflictsWithDefaults(); - Sound_SetMasterVolume(6 * g_OptionSoundVolume + 4); if (g_OptionMusicVolume) { @@ -2796,9 +2776,6 @@ void __cdecl S_SaveSettings(void) SetRegistryDwordValue("SoundFxVolume", g_OptionSoundVolume); SetRegistryDwordValue("DetailLevel", g_DetailLevel); SetRegistryFloatValue("Sizer", g_GameSizerCopy); - SetRegistryBinaryValue( - "Layout", (uint8_t *)&g_Layout[1], - sizeof(uint16_t) * INPUT_ROLE_NUMBER_OF); CloseGameRegistryKey(); } @@ -2809,7 +2786,9 @@ void __cdecl S_Wait(int32_t frames, const BOOL input_check) if (g_Input.any) { break; } + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); int32_t passed; do { @@ -2824,7 +2803,9 @@ void __cdecl S_Wait(int32_t frames, const BOOL input_check) } while (frames > 0) { + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); if (input_check && g_Input.any) { break; } diff --git a/src/tr2/decomp/fmv.c b/src/tr2/decomp/fmv.c index 02bb1e485..3a72933ab 100644 --- a/src/tr2/decomp/fmv.c +++ b/src/tr2/decomp/fmv.c @@ -359,13 +359,11 @@ void __cdecl WinPlayFMV(const char *const file_name, const bool is_playback) Video_SetSurfaceSize(video, g_PhdWinWidth, g_PhdWinHeight); Video_PumpEvents(video); - + Shell_ProcessEvents(); WinVidSpinMessageLoop(false); - if (Input_Update()) { - Video_Stop(video); - break; - } + Input_Update(); + Shell_ProcessInput(); if (g_InputDB.option) { Video_Stop(video); break; @@ -388,3 +386,8 @@ bool __cdecl S_IntroFMV( { return IntroFMV(file_name_1, file_name_2); } + +bool FMV_IsPlaying(void) +{ + return g_IsFMVPlaying; +} diff --git a/src/tr2/decomp/fmv.h b/src/tr2/decomp/fmv.h index e15873142..a74c30015 100644 --- a/src/tr2/decomp/fmv.h +++ b/src/tr2/decomp/fmv.h @@ -8,3 +8,4 @@ void __cdecl WinPlayFMV(const char *file_name, bool is_playback); void __cdecl WinStopFMV(bool is_playback); bool __cdecl S_PlayFMV(const char *file_name); bool __cdecl S_IntroFMV(const char *file_name_1, const char *file_name_2); +bool FMV_IsPlaying(void); diff --git a/src/tr2/decomp/stats.c b/src/tr2/decomp/stats.c index 668498169..a56c54be3 100644 --- a/src/tr2/decomp/stats.c +++ b/src/tr2/decomp/stats.c @@ -4,6 +4,7 @@ #include "game/music.h" #include "game/overlay.h" #include "game/requester.h" +#include "game/shell.h" #include "game/text.h" #include "global/funcs.h" #include "global/types.h" @@ -314,14 +315,18 @@ int32_t __cdecl LevelStats(const int32_t level_num) S_CopyScreenToBuffer(); while (g_Input.menu_confirm) { + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); } while (true) { S_InitialisePolyList(0); S_CopyBufferToScreen(); + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); if (g_IsGameToExit) { break; @@ -364,14 +369,18 @@ int32_t __cdecl GameStats(const int32_t level_num) Overlay_HideGameInfo(); while (g_Input.menu_confirm) { + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); } while (true) { S_InitialisePolyList(0); S_CopyBufferToScreen(); + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); if (g_IsGameToExit) { break; diff --git a/src/tr2/game/demo.c b/src/tr2/game/demo.c index 7a16ef2a3..143df1918 100644 --- a/src/tr2/game/demo.c +++ b/src/tr2/game/demo.c @@ -149,15 +149,63 @@ bool __cdecl Demo_GetInput(void) { if (g_DemoCount >= MAX_DEMO_SIZE) { return false; - ; } - const int32_t input = g_DemoPtr[g_DemoCount]; - if (input == -1) { + union { + uint32_t any; + struct { + // clang-format off + uint32_t forward: 1; + uint32_t back: 1; + uint32_t left: 1; + uint32_t right: 1; + uint32_t jump: 1; + uint32_t draw: 1; + uint32_t action: 1; + uint32_t slow: 1; + uint32_t option: 1; + uint32_t look: 1; + uint32_t step_left: 1; + uint32_t step_right: 1; + uint32_t roll: 1; + uint32_t _pad: 6; + uint32_t use_flare: 1; + uint32_t menu_confirm: 1; + uint32_t menu_back: 1; + uint32_t save: 1; + uint32_t load: 1; + // clang-format on + }; + } demo_input = { .any = g_DemoPtr[g_DemoCount] }; + + if ((int32_t)demo_input.any == -1) { return false; } - g_Input.any = input; + g_Input = (INPUT_STATE) { + 0, + // clang-format off + .forward = demo_input.forward, + .back = demo_input.back, + .left = demo_input.left, + .right = demo_input.right, + .jump = demo_input.jump, + .draw = demo_input.draw, + .action = demo_input.action, + .slow = demo_input.slow, + .option = demo_input.option, + .look = demo_input.look, + .step_left = demo_input.step_left, + .step_right = demo_input.step_right, + .roll = demo_input.roll, + .use_flare = demo_input.use_flare, + .menu_confirm = demo_input.menu_confirm, + .menu_back = demo_input.menu_back, + .save = demo_input.save, + .load = demo_input.load, + // clang-format on + }; + g_InputDB.any = g_Input.any & ~m_OldDemoInputDB.any; m_OldDemoInputDB = g_Input; g_DemoCount++; diff --git a/src/tr2/game/game.c b/src/tr2/game/game.c index 00bd394bf..9def68359 100644 --- a/src/tr2/game/game.c +++ b/src/tr2/game/game.c @@ -5,11 +5,13 @@ #include "game/demo.h" #include "game/gameflow/gameflow_new.h" #include "game/input.h" +#include "game/inventory/backpack.h" #include "game/inventory/common.h" #include "game/lara/control.h" #include "game/music.h" #include "game/overlay.h" #include "game/room_draw.h" +#include "game/shell.h" #include "game/sound.h" #include "game/text.h" #include "global/funcs.h" @@ -42,7 +44,10 @@ int32_t __cdecl Game_Control(int32_t nframes, const bool demo_mode) return GFD_START_GAME | LV_FIRST; } + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); + Game_ProcessInput(); if (demo_mode) { if (g_InputDB.any) { @@ -178,6 +183,7 @@ int32_t __cdecl Game_Draw(void) Overlay_DrawGameInfo(true); S_OutputPolyList(); g_Camera.num_frames = S_DumpScreen(); + Shell_ProcessEvents(); S_AnimateTextures(g_Camera.num_frames); return g_Camera.num_frames; } @@ -189,6 +195,7 @@ int32_t __cdecl Game_DrawCinematic(void) Text_Draw(); S_OutputPolyList(); g_Camera.num_frames = S_DumpScreen(); + Shell_ProcessEvents(); S_AnimateTextures(g_Camera.num_frames); return g_Camera.num_frames; } @@ -316,3 +323,39 @@ bool Game_IsPlayable(void) return true; } + +void Game_ProcessInput(void) +{ + if (g_GameInfo.current_level.type == GFL_DEMO) { + return; + } + + if (g_InputDB.equip_pistols && Inv_RequestItem(O_PISTOL_OPTION)) { + g_Lara.request_gun_type = LGT_PISTOLS; + } else if (g_InputDB.equip_shotgun && Inv_RequestItem(O_SHOTGUN_OPTION)) { + g_Lara.request_gun_type = LGT_SHOTGUN; + } else if (g_InputDB.equip_magnums && Inv_RequestItem(O_MAGNUM_OPTION)) { + g_Lara.request_gun_type = LGT_MAGNUMS; + } else if (g_InputDB.equip_uzis && Inv_RequestItem(O_UZI_OPTION)) { + g_Lara.request_gun_type = LGT_UZIS; + } else if (g_InputDB.equip_harpoon && Inv_RequestItem(O_HARPOON_OPTION)) { + g_Lara.request_gun_type = LGT_HARPOON; + } else if (g_InputDB.equip_m16 && Inv_RequestItem(O_M16_OPTION)) { + g_Lara.request_gun_type = LGT_M16; + } else if ( + g_InputDB.equip_grenade_launcher && Inv_RequestItem(O_GRENADE_OPTION)) { + g_Lara.request_gun_type = LGT_GRENADE; + } + + if (g_InputDB.use_small_medi && Inv_RequestItem(O_SMALL_MEDIPACK_OPTION)) { + Lara_UseItem(O_SMALL_MEDIPACK_OPTION); + } + if (g_InputDB.use_big_medi && Inv_RequestItem(O_LARGE_MEDIPACK_OPTION)) { + Lara_UseItem(O_LARGE_MEDIPACK_OPTION); + } + + if (g_GameFlow.load_save_disabled) { + g_Input.save = 0; + g_Input.load = 0; + } +} diff --git a/src/tr2/game/game.h b/src/tr2/game/game.h index 660899baa..4a7ff9a74 100644 --- a/src/tr2/game/game.h +++ b/src/tr2/game/game.h @@ -8,3 +8,4 @@ int32_t __cdecl Game_DrawCinematic(void); int16_t __cdecl Game_Start(int32_t level_num, GAMEFLOW_LEVEL_TYPE level_type); int32_t __cdecl Game_Loop(bool demo_mode); bool Game_IsPlayable(void); +void Game_ProcessInput(void); diff --git a/src/tr2/game/gun/gun.c b/src/tr2/game/gun/gun.c index e18c8f197..2f3e33146 100644 --- a/src/tr2/game/gun/gun.c +++ b/src/tr2/game/gun/gun.c @@ -42,7 +42,7 @@ void __cdecl Gun_Control(void) } else if (g_Lara.gun_status == LGS_ARMLESS) { if (g_Input.draw) { g_Lara.request_gun_type = g_Lara.last_gun_type; - } else if (g_InputDB.flare) { + } else if (g_InputDB.use_flare) { if (g_Lara.gun_type == LGT_FLARE) { g_Lara.gun_status = LGS_UNDRAW; } else if (Inv_RequestItem(O_FLARES_ITEM)) { @@ -78,7 +78,7 @@ void __cdecl Gun_Control(void) } } } else if (g_Lara.gun_status == LGS_READY) { - if ((g_InputDB.flare) && Inv_RequestItem(O_FLARES_ITEM)) { + if (g_InputDB.use_flare && Inv_RequestItem(O_FLARES_ITEM)) { g_Lara.request_gun_type = LGT_FLARE; } diff --git a/src/tr2/game/input.c b/src/tr2/game/input.c index c8795d211..c3dae3490 100644 --- a/src/tr2/game/input.c +++ b/src/tr2/game/input.c @@ -1,57 +1,20 @@ #include "game/input.h" +#include "config.h" #include "game/console/common.h" +#include "game/shell.h" #include "global/funcs.h" #include "global/vars.h" -#include "specific/s_input.h" - -static const char *m_KeyNames[] = { - NULL, "ESC", "1", "2", "3", "4", "5", "6", - "7", "8", "9", "0", "-", "+", "BKSP", "TAB", - "Q", "W", "E", "R", "T", "Y", "U", "I", - "O", "P", "<", ">", "RET", "CTRL", "A", "S", - "D", "F", "G", "H", "J", "K", "L", ";", - "'", "`", "SHIFT", "#", "Z", "X", "C", "V", - "B", "N", "M", ",", ".", "/", "SHIFT", "PADx", - "ALT", "SPACE", "CAPS", NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, "NMLK", NULL, "PAD7", - "PAD8", "PAD9", "PAD-", "PAD4", "PAD5", "PAD6", "PAD+", "PAD1", - "PAD2", "PAD3", "PAD0", "PAD.", NULL, NULL, "\\", NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, "ENTER", "CTRL", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, "SHIFT", NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, "PAD/", NULL, NULL, - "ALT", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, "HOME", - "UP", "PGUP", NULL, "LEFT", NULL, "RIGHT", NULL, "END", - "DOWN", "PGDN", "INS", "DEL", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - "JOY1", "JOY2", "JOY3", "JOY4", "JOY5", "JOY6", "JOY7", "JOY8", - "JOY9", "JOY10", "JOY11", "JOY12", "JOY13", "JOY14", "JOY15", "JOY16", -}; - -INPUT_STATE g_Input = { 0 }; -INPUT_STATE g_InputDB = { 0 }; -INPUT_STATE g_OldInputDB = { 0 }; -bool g_ConflictLayout[INPUT_ROLE_NUMBER_OF] = { false }; - -static bool m_ListenMode = false; - -static INPUT_STATE __cdecl M_GetDebounced(INPUT_STATE input); - -static INPUT_STATE __cdecl M_GetDebounced(const INPUT_STATE input) + +#include +#include +#include + +static INPUT_STATE M_GetDebounced(INPUT_STATE input); +static void M_UpdateFromBackend( + INPUT_STATE *s, const INPUT_BACKEND_IMPL *backend, INPUT_LAYOUT layout); + +static INPUT_STATE M_GetDebounced(const INPUT_STATE input) { INPUT_STATE result; result.any = input.any & ~g_OldInputDB.any; @@ -60,102 +23,106 @@ static INPUT_STATE __cdecl M_GetDebounced(const INPUT_STATE input) return result; } -bool Input_Update(void) +static void M_UpdateFromBackend( + INPUT_STATE *const s, const INPUT_BACKEND_IMPL *const backend, + const INPUT_LAYOUT layout) { - bool result = S_Input_Update(); - - g_InputDB = M_GetDebounced(g_Input); - - if (m_ListenMode) { - g_Input = (INPUT_STATE) { 0 }; - g_InputDB = (INPUT_STATE) { 0 }; - return result; - } - - if (!g_IsFMVPlaying && g_InputDB.console) { - Console_Open(); - g_Input = (INPUT_STATE) { 0 }; - g_InputDB = (INPUT_STATE) { 0 }; - } + // clang-format off + s->forward |= backend->is_pressed(layout, INPUT_ROLE_UP); + s->back |= backend->is_pressed(layout, INPUT_ROLE_DOWN); + s->left |= backend->is_pressed(layout, INPUT_ROLE_LEFT); + s->right |= backend->is_pressed(layout, INPUT_ROLE_RIGHT); + s->step_left |= backend->is_pressed(layout, INPUT_ROLE_STEP_L); + s->step_right |= backend->is_pressed(layout, INPUT_ROLE_STEP_R); + s->slow |= backend->is_pressed(layout, INPUT_ROLE_SLOW); + s->jump |= backend->is_pressed(layout, INPUT_ROLE_JUMP); + s->action |= backend->is_pressed(layout, INPUT_ROLE_ACTION); + s->draw |= backend->is_pressed(layout, INPUT_ROLE_DRAW); + s->look |= backend->is_pressed(layout, INPUT_ROLE_LOOK); + s->roll |= backend->is_pressed(layout, INPUT_ROLE_ROLL); + + s->enter_console |= backend->is_pressed(layout, INPUT_ROLE_ENTER_CONSOLE); + s->save |= backend->is_pressed(layout, INPUT_ROLE_SAVE); + s->load |= backend->is_pressed(layout, INPUT_ROLE_LOAD); + + s->equip_pistols |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_PISTOLS); + s->equip_shotgun |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_SHOTGUN); + s->equip_magnums |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_MAGNUMS); + s->equip_uzis |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_UZIS); + s->equip_harpoon |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_HARPOON); + s->equip_m16 |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_M16); + s->equip_grenade_launcher |= backend->is_pressed(layout, INPUT_ROLE_EQUIP_GRENADE_LAUNCHER); + s->use_flare |= backend->is_pressed(layout, INPUT_ROLE_USE_FLARE); + s->use_small_medi |= backend->is_pressed(layout, INPUT_ROLE_USE_SMALL_MEDI); + s->use_big_medi |= backend->is_pressed(layout, INPUT_ROLE_USE_BIG_MEDI); + + s->option |= backend->is_pressed(layout, INPUT_ROLE_OPTION); + s->menu_up |= backend->is_pressed(layout, INPUT_ROLE_MENU_UP); + s->menu_down |= backend->is_pressed(layout, INPUT_ROLE_MENU_DOWN); + s->menu_left |= backend->is_pressed(layout, INPUT_ROLE_MENU_LEFT); + s->menu_right |= backend->is_pressed(layout, INPUT_ROLE_MENU_RIGHT); + s->menu_confirm |= backend->is_pressed(layout, INPUT_ROLE_MENU_CONFIRM); + s->menu_back |= backend->is_pressed(layout, INPUT_ROLE_MENU_BACK); + + s->screenshot |= backend->is_pressed(layout, INPUT_ROLE_SCREENSHOT); + s->switch_resolution |= backend->is_pressed(layout, INPUT_ROLE_SWITCH_RESOLUTION); + s->switch_internal_screen_size |= backend->is_pressed(layout, INPUT_ROLE_SWITCH_INTERNAL_SCREEN_SIZE); + s->toggle_bilinear_filter |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_BILINEAR_FILTER); + s->toggle_perspective_filter |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER); + s->toggle_z_buffer |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_Z_BUFFER); + s->toggle_dither |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_DITHER); + s->toggle_fullscreen |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_FULLSCREEN); + s->toggle_rendering_mode |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_RENDERING_MODE); + // clang-format on - return result; + backend->custom_update(s, layout); } -uint16_t Input_GetAssignedKey(const int32_t layout, const INPUT_ROLE role) +void Input_Update(void) { - return g_Layout[layout].key[role]; -} + g_Input.any = 0; + + M_UpdateFromBackend( + &g_Input, &g_Input_Keyboard, g_Config.input.keyboard_layout); + M_UpdateFromBackend( + &g_Input, &g_Input_Controller, g_Config.input.controller_layout); + + g_Input.option &= g_Camera.type != CAM_CINEMATIC; + g_Input.roll |= g_Input.forward && g_Input.back; + g_Input.menu_back |= g_Input.option; + if (g_Input.left && g_Input.right) { + g_Input.left = 0; + g_Input.right = 0; + } -void Input_AssignKey( - const int32_t layout, const INPUT_ROLE role, const uint16_t key) -{ - g_Layout[layout].key[role] = key; -} + g_InputDB = M_GetDebounced(g_Input); -const char *Input_GetLayoutName(const int32_t layout) -{ - // clang-format off - switch (layout) { - case 0: return g_GF_PCStrings[GF_S_PC_DEFAULT_KEYS]; - case 1: return g_GF_PCStrings[GF_S_PC_USER_KEYS]; - default: return ""; + if (Input_IsInListenMode()) { + g_Input = (INPUT_STATE) { 0 }; + g_InputDB = (INPUT_STATE) { 0 }; } - // clang-format on } const char *Input_GetRoleName(const INPUT_ROLE role) { // clang-format off switch (role) { - case INPUT_ROLE_UP: return g_GF_GameStrings[GF_S_GAME_KEYMAP_RUN]; - case INPUT_ROLE_DOWN: return g_GF_GameStrings[GF_S_GAME_KEYMAP_BACK]; - case INPUT_ROLE_LEFT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_LEFT]; - case INPUT_ROLE_RIGHT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_RIGHT]; - case INPUT_ROLE_STEP_LEFT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_STEP_LEFT]; - case INPUT_ROLE_STEP_RIGHT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_STEP_RIGHT]; - case INPUT_ROLE_SLOW: return g_GF_GameStrings[GF_S_GAME_KEYMAP_WALK]; - case INPUT_ROLE_JUMP: return g_GF_GameStrings[GF_S_GAME_KEYMAP_JUMP]; - case INPUT_ROLE_ACTION: return g_GF_GameStrings[GF_S_GAME_KEYMAP_ACTION]; - case INPUT_ROLE_DRAW_WEAPON: return g_GF_GameStrings[GF_S_GAME_KEYMAP_DRAW_WEAPON]; - case INPUT_ROLE_FLARE: return g_GF_GameStrings[GF_S_GAME_KEYMAP_FLARE]; - case INPUT_ROLE_LOOK: return g_GF_GameStrings[GF_S_GAME_KEYMAP_LOOK]; - case INPUT_ROLE_ROLL: return g_GF_GameStrings[GF_S_GAME_KEYMAP_ROLL]; - case INPUT_ROLE_OPTION: return g_GF_GameStrings[GF_S_GAME_KEYMAP_INVENTORY]; - case INPUT_ROLE_CONSOLE: return "Console"; - default: return ""; + case INPUT_ROLE_UP: return g_GF_GameStrings[GF_S_GAME_KEYMAP_RUN]; + case INPUT_ROLE_DOWN: return g_GF_GameStrings[GF_S_GAME_KEYMAP_BACK]; + case INPUT_ROLE_LEFT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_LEFT]; + case INPUT_ROLE_RIGHT: return g_GF_GameStrings[GF_S_GAME_KEYMAP_RIGHT]; + case INPUT_ROLE_STEP_L: return g_GF_GameStrings[GF_S_GAME_KEYMAP_STEP_LEFT]; + case INPUT_ROLE_STEP_R: return g_GF_GameStrings[GF_S_GAME_KEYMAP_STEP_RIGHT]; + case INPUT_ROLE_SLOW: return g_GF_GameStrings[GF_S_GAME_KEYMAP_WALK]; + case INPUT_ROLE_JUMP: return g_GF_GameStrings[GF_S_GAME_KEYMAP_JUMP]; + case INPUT_ROLE_ACTION: return g_GF_GameStrings[GF_S_GAME_KEYMAP_ACTION]; + case INPUT_ROLE_DRAW: return g_GF_GameStrings[GF_S_GAME_KEYMAP_DRAW_WEAPON]; + case INPUT_ROLE_USE_FLARE: return g_GF_GameStrings[GF_S_GAME_KEYMAP_FLARE]; + case INPUT_ROLE_LOOK: return g_GF_GameStrings[GF_S_GAME_KEYMAP_LOOK]; + case INPUT_ROLE_ROLL: return g_GF_GameStrings[GF_S_GAME_KEYMAP_ROLL]; + case INPUT_ROLE_OPTION: return g_GF_GameStrings[GF_S_GAME_KEYMAP_INVENTORY]; + case INPUT_ROLE_ENTER_CONSOLE: return "Console"; + default: return ""; } // clang-format on } - -const char *Input_GetKeyName(const uint16_t key) -{ - return m_KeyNames[key]; -} - -void __cdecl Input_CheckConflictsWithDefaults(void) -{ - for (int32_t i = 0; i < INPUT_ROLE_NUMBER_OF; i++) { - g_ConflictLayout[i] = false; - for (int32_t j = 0; j < INPUT_ROLE_NUMBER_OF; j++) { - const uint16_t key1 = Input_GetAssignedKey(0, i); - const uint16_t key2 = Input_GetAssignedKey(1, j); - if (key1 == key2) { - g_ConflictLayout[i] = true; - break; - } - } - } -} - -void Input_EnterListenMode(void) -{ - m_ListenMode = true; -} - -void Input_ExitListenMode(void) -{ - m_ListenMode = false; - S_Input_Update(); - g_OldInputDB = g_Input; - g_InputDB = M_GetDebounced(g_Input); -} diff --git a/src/tr2/game/input.h b/src/tr2/game/input.h index 8732b04b5..e4e59f254 100644 --- a/src/tr2/game/input.h +++ b/src/tr2/game/input.h @@ -1,85 +1,5 @@ #pragma once -#include "global/types.h" +#include -#define INPUT_MAX_LAYOUT 2 - -typedef enum { - // clang-format off - INPUT_ROLE_UP = 0, - INPUT_ROLE_FORWARD = INPUT_ROLE_UP, - INPUT_ROLE_DOWN = 1, - INPUT_ROLE_BACK = INPUT_ROLE_DOWN, - INPUT_ROLE_LEFT = 2, - INPUT_ROLE_RIGHT = 3, - INPUT_ROLE_STEP_LEFT = 4, - INPUT_ROLE_STEP_RIGHT = 5, - INPUT_ROLE_SLOW = 6, - INPUT_ROLE_JUMP = 7, - INPUT_ROLE_ACTION = 8, - INPUT_ROLE_DRAW_WEAPON = 9, - INPUT_ROLE_FLARE = 10, - INPUT_ROLE_LOOK = 11, - INPUT_ROLE_ROLL = 12, - INPUT_ROLE_OPTION = 13, - INPUT_ROLE_CONSOLE = 14, - INPUT_ROLE_NUMBER_OF = 15, - // clang-format on -} INPUT_ROLE; - -typedef union { - uint64_t any; - struct { - // clang-format off - uint64_t forward: 1; - uint64_t back: 1; - uint64_t left: 1; - uint64_t right: 1; - uint64_t jump: 1; - uint64_t draw: 1; - uint64_t action: 1; - uint64_t slow: 1; - uint64_t option: 1; - uint64_t look: 1; - uint64_t step_left: 1; - uint64_t step_right: 1; - uint64_t roll: 1; - uint64_t pause: 1; - uint64_t reserved1: 1; - uint64_t reserved2: 1; - uint64_t dozy_cheat: 1; - uint64_t stuff_cheat: 1; - uint64_t debug_info: 1; - uint64_t flare: 1; - uint64_t menu_confirm: 1; - uint64_t menu_back: 1; - uint64_t save: 1; - uint64_t load: 1; - uint64_t console: 1; - // clang-format on - }; -} INPUT_STATE; - -typedef struct { - uint16_t key[INPUT_ROLE_NUMBER_OF]; -} INPUT_LAYOUT; - -extern INPUT_STATE g_Input; -extern INPUT_STATE g_InputDB; -extern INPUT_STATE g_OldInputDB; -extern INPUT_LAYOUT g_Layout[2]; -extern bool g_ConflictLayout[INPUT_ROLE_NUMBER_OF]; - -bool Input_Update(void); - -void Input_EnterListenMode(void); -void Input_ExitListenMode(void); -bool Input_IsAnythingPressed(void); -void Input_AssignKey(int32_t layout, INPUT_ROLE role, uint16_t key); -uint16_t Input_GetAssignedKey(int32_t layout, INPUT_ROLE role); - -const char *Input_GetLayoutName(int32_t layout); const char *Input_GetRoleName(INPUT_ROLE role); -const char *Input_GetKeyName(uint16_t key); - -void __cdecl Input_CheckConflictsWithDefaults(void); diff --git a/src/tr2/game/inventory/common.c b/src/tr2/game/inventory/common.c index e94b523d2..6598f6d7d 100644 --- a/src/tr2/game/inventory/common.c +++ b/src/tr2/game/inventory/common.c @@ -1,6 +1,7 @@ #include "game/inventory/common.h" #include "game/demo.h" +#include "game/game.h" #include "game/input.h" #include "game/inventory/backpack.h" #include "game/inventory/ring.h" @@ -14,6 +15,7 @@ #include "game/option/option.h" #include "game/output.h" #include "game/overlay.h" +#include "game/shell.h" #include "game/sound.h" #include "game/text.h" #include "global/const.h" @@ -248,7 +250,10 @@ int32_t __cdecl Inv_Display(int32_t inventory_mode) } Inv_Ring_CalcAdders(&ring, 24); + Shell_ProcessEvents(); Input_Update(); + Shell_ProcessInput(); + Game_ProcessInput(); if (g_Inv_DemoMode) { if (g_InputDB.any) { @@ -401,6 +406,7 @@ int32_t __cdecl Inv_Display(int32_t inventory_mode) Sound_EndScene(); const int32_t frames = S_DumpScreen(); + Shell_ProcessEvents(); g_Inv_NFrames = frames; g_Camera.num_frames = frames; if (g_CurrentLevel) { diff --git a/src/tr2/game/option/option_controls.c b/src/tr2/game/option/option_controls.c index aad606c59..d42594c3f 100644 --- a/src/tr2/game/option/option_controls.c +++ b/src/tr2/game/option/option_controls.c @@ -1,28 +1,79 @@ +#include "config.h" #include "game/option/option.h" #include "game/ui/widgets/controls_dialog.h" #include "global/vars.h" -static UI_WIDGET *m_ControlsDialog; -static UI_CONTROLS_CONTROLLER m_ControlsDialogController; +#include -void Option_Controls_Shutdown(void) +static UI_WIDGET *m_Dialog; +static UI_CONTROLS_CONTROLLER m_Controller; +static int32_t m_Listener1; +static int32_t m_Listener2; + +static void M_Init(void); +static void M_Shutdown(void); +static void M_HandleLayoutChange(const EVENT *event, void *user_data); +static void M_HandleKeyChange(const EVENT *event, void *user_data); + +static void M_Init(void) +{ + UI_ControlsController_Init(&m_Controller); + m_Controller.active_layout = g_Config.input.keyboard_layout; + + m_Dialog = UI_ControlsDialog_Create(&m_Controller); + m_Listener1 = EventManager_Subscribe( + m_Controller.events, "layout_change", NULL, M_HandleLayoutChange, NULL); + m_Listener2 = EventManager_Subscribe( + m_Controller.events, "key_change", NULL, M_HandleKeyChange, NULL); +} + +static void M_Shutdown(void) +{ + if (m_Dialog == NULL) { + return; + } + + m_Dialog->free(m_Dialog); + m_Dialog = NULL; + + EventManager_Unsubscribe(m_Controller.events, m_Listener1); + EventManager_Unsubscribe(m_Controller.events, m_Listener2); + + UI_ControlsController_Shutdown(&m_Controller); +} + +static void M_HandleLayoutChange(const EVENT *event, void *user_data) { - if (m_ControlsDialog != NULL) { - m_ControlsDialog->free(m_ControlsDialog); - m_ControlsDialog = NULL; + switch (m_Controller.backend) { + case INPUT_BACKEND_KEYBOARD: + g_Config.input.keyboard_layout = m_Controller.active_layout; + break; + case INPUT_BACKEND_CONTROLLER: + g_Config.input.controller_layout = m_Controller.active_layout; + break; } - Input_CheckConflictsWithDefaults(); + + Config_Write(); +} + +static void M_HandleKeyChange(const EVENT *event, void *user_data) +{ + Config_Write(); +} + +void Option_Controls_Shutdown(void) +{ + M_Shutdown(); } void __cdecl Option_Controls(INVENTORY_ITEM *const item) { - if (m_ControlsDialog == NULL) { - m_ControlsDialog = - UI_ControlsDialog_Create(&m_ControlsDialogController); + if (m_Dialog == NULL) { + M_Init(); } - m_ControlsDialog->control(m_ControlsDialog); - if (m_ControlsDialogController.state == UI_CONTROLS_STATE_EXIT) { + m_Dialog->control(m_Dialog); + if (m_Controller.state == UI_CONTROLS_STATE_EXIT) { Option_Controls_Shutdown(); } else { g_Input = (INPUT_STATE) { 0 }; diff --git a/src/tr2/game/shell.h b/src/tr2/game/shell.h index c5df56a71..003b6f91e 100644 --- a/src/tr2/game/shell.h +++ b/src/tr2/game/shell.h @@ -1,8 +1,4 @@ #pragma once -#include "global/types.h" - -void __cdecl Shell_Main(void); -void __cdecl Shell_Shutdown(void); -void __cdecl Shell_ExitSystem(const char *message); -void __cdecl Shell_ExitSystemFmt(const char *fmt, ...); +#include "game/shell/common.h" +#include "game/shell/input.h" diff --git a/src/tr2/game/shell.c b/src/tr2/game/shell/common.c similarity index 75% rename from src/tr2/game/shell.c rename to src/tr2/game/shell/common.c index 7e201efff..2ab943fa6 100644 --- a/src/tr2/game/shell.c +++ b/src/tr2/game/shell/common.c @@ -1,7 +1,8 @@ -#include "game/shell.h" +#include "game/shell/common.h" #include "config.h" #include "decomp/decomp.h" +#include "decomp/fmv.h" #include "game/background.h" #include "game/console/common.h" #include "game/demo.h" @@ -20,6 +21,7 @@ #include #include +#include #include #include @@ -39,7 +41,10 @@ void __cdecl Shell_Main(void) Text_Init(); UI_Init(); Console_Init(); + + Sound_Init(); Music_Init(); + Input_Init(); Config_Read(); if (!S_InitialiseSystem()) { @@ -65,7 +70,6 @@ void __cdecl Shell_Main(void) g_HiRes = 0; TempVideoAdjust(1, 1.0); - Input_Update(); g_IsVidModeLock = 1; S_DisplayPicture("data\\legal.pcx", 0); @@ -73,6 +77,7 @@ void __cdecl Shell_Main(void) S_CopyBufferToScreen(); S_OutputPolyList(); S_DumpScreen(); + Shell_ProcessEvents(); FadeToPal(30, g_GamePalette8); S_Wait(180, 1); S_FadeToBlack(); @@ -169,7 +174,6 @@ void __cdecl Shell_Shutdown(void) { GameString_Shutdown(); Console_Shutdown(); - WinInFinish(); BGND_Free(); RenderFinish(false); WinVidFinish(); @@ -203,3 +207,52 @@ void __cdecl Shell_ExitSystemFmt(const char *fmt, ...) Memory_FreePointer(&message); } + +// TODO: try to call this function in a single place after introducing phasers. +void Shell_ProcessEvents(void) +{ + SDL_Event event; + while (SDL_PollEvent(&event) != 0) { + switch (event.type) { + case SDL_QUIT: + g_IsMessageLoopClosed = true; + g_IsGameWindowMinimized = true; + g_StopInventory = true; + break; + + case SDL_KEYDOWN: { + // NOTE: This normally would get handled by Input_Update, + // but by the time Input_Update gets ran, we may already have lost + // some keypresses if the player types really fast, so we need to + // react sooner. + if (!FMV_IsPlaying() && !Console_IsOpened() + && Input_IsPressed( + INPUT_BACKEND_KEYBOARD, g_Config.input.keyboard_layout, + INPUT_ROLE_ENTER_CONSOLE)) { + Console_Open(); + } else { + UI_HandleKeyDown(event.key.keysym.sym); + } + break; + } + + case SDL_TEXTEDITING: + UI_HandleTextEdit(event.text.text); + break; + + case SDL_TEXTINPUT: + UI_HandleTextEdit(event.text.text); + break; + + case SDL_CONTROLLERDEVICEADDED: + case SDL_JOYDEVICEADDED: + Input_InitController(); + break; + + case SDL_CONTROLLERDEVICEREMOVED: + case SDL_JOYDEVICEREMOVED: + Input_ShutdownController(); + break; + } + } +} diff --git a/src/tr2/game/shell/common.h b/src/tr2/game/shell/common.h new file mode 100644 index 000000000..94101a6e5 --- /dev/null +++ b/src/tr2/game/shell/common.h @@ -0,0 +1,10 @@ +#pragma once + +#include "global/types.h" + +void __cdecl Shell_Main(void); +void __cdecl Shell_Shutdown(void); +void __cdecl Shell_ExitSystem(const char *message); +void __cdecl Shell_ExitSystemFmt(const char *fmt, ...); + +void Shell_ProcessEvents(void); diff --git a/src/tr2/game/shell/input.c b/src/tr2/game/shell/input.c new file mode 100644 index 000000000..963c426fd --- /dev/null +++ b/src/tr2/game/shell/input.c @@ -0,0 +1,305 @@ +#include "game/shell/input.h" + +#include "config.h" +#include "decomp/decomp.h" +#include "game/console/common.h" +#include "game/gameflow/gameflow_new.h" +#include "game/input.h" +#include "game/inventory/backpack.h" +#include "game/lara/control.h" +#include "global/const.h" +#include "global/funcs.h" +#include "global/vars.h" + +#include +#include + +static void M_ToggleBilinearFiltering(void); +static void M_TogglePerspectiveCorrection(void); +static void M_ToggleZBuffer(void); +static void M_ToggleTripleBuffering(void); +static void M_ToggleDither(void); +static void M_ToggleFullscreen(void); +static void M_ToggleRenderingMode(void); +static void M_DecreaseResolutionOrBPP(void); +static void M_IncreaseResolutionOrBPP(void); +static void M_DecreaseInternalScreenSize(void); +static void M_IncreaseInternalScreenSize(void); + +static void M_ToggleBilinearFiltering(void) +{ + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.bilinear_filtering = !new_settings.bilinear_filtering; + GameApplySettings(&new_settings); +} + +static void M_TogglePerspectiveCorrection(void) +{ + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.perspective_correct = !new_settings.perspective_correct; + g_PerspectiveDistance = g_SavedAppSettings.perspective_correct + ? SW_DETAIL_HIGH + : SW_DETAIL_MEDIUM; + GameApplySettings(&new_settings); +} + +static void M_ToggleZBuffer(void) +{ + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.zbuffer = !new_settings.zbuffer; + GameApplySettings(&new_settings); +} + +static void M_ToggleTripleBuffering(void) +{ + if (g_SavedAppSettings.fullscreen) { + return; + } + + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.triple_buffering = !new_settings.triple_buffering; + GameApplySettings(&new_settings); +} + +static void M_ToggleDither(void) +{ + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.dither = !new_settings.dither; + GameApplySettings(&new_settings); +} + +static void M_ToggleFullscreen(void) +{ + if (g_IsVidModeLock) { + return; + } + + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.fullscreen = !new_settings.fullscreen; + if (g_SavedAppSettings.fullscreen) { + const int32_t win_width = MAX(g_PhdWinWidth, 320); + const int32_t win_height = MAX(g_PhdWinHeight, 240); + new_settings.window_height = win_height; + new_settings.window_width = CalculateWindowWidth(win_width, win_height); + new_settings.triple_buffering = 0; + GameApplySettings(&new_settings); + + g_GameSizer = 1.0; + g_GameSizerCopy = 1.0; + setup_screen_size(); + } else { + const DISPLAY_MODE_LIST *const mode_list = + new_settings.render_mode == RM_HARDWARE + ? &g_CurrentDisplayAdapter.hw_disp_mode_list + : &g_CurrentDisplayAdapter.sw_disp_mode_list; + + if (mode_list->count > 0) { + const DISPLAY_MODE target_mode = { + .width = g_GameVid_Width, + .height = g_GameVid_Height, + .bpp = g_GameVid_BPP, + .vga = VGA_NO_VGA, + }; + + const DISPLAY_MODE_NODE *mode = NULL; + for (mode = mode_list->head; mode != NULL; mode = mode->next) { + if (!CompareVideoModes(&mode->body, &target_mode)) { + break; + } + } + + if (mode == NULL) { + mode = mode_list->tail; + } + + new_settings.video_mode = mode; + GameApplySettings(&new_settings); + } + } +} + +static void M_ToggleRenderingMode(void) +{ + if (g_IsVidModeLock || g_Inv_IsActive) { + return; + } + + APP_SETTINGS new_settings = g_SavedAppSettings; + new_settings.render_mode = + new_settings.render_mode == RM_HARDWARE ? RM_SOFTWARE : RM_HARDWARE; + + const DISPLAY_MODE_LIST *const mode_list = + new_settings.render_mode == RM_HARDWARE + ? &g_CurrentDisplayAdapter.hw_disp_mode_list + : &g_CurrentDisplayAdapter.sw_disp_mode_list; + + if (mode_list->count == 0) { + return; + } + + const DISPLAY_MODE target_mode = { + .width = g_GameVid_Width, + .height = g_GameVid_Height, + .bpp = new_settings.render_mode == RM_HARDWARE ? 16 : 8, + .vga = VGA_NO_VGA, + }; + + const DISPLAY_MODE_NODE *mode = NULL; + for (mode = mode_list->head; mode != NULL; mode = mode->next) { + if (!CompareVideoModes(&mode->body, &target_mode)) { + break; + } + } + + if (mode == NULL) { + mode = mode_list->tail; + } + + new_settings.video_mode = mode; + new_settings.fullscreen = 1; + GameApplySettings(&new_settings); +} + +static void M_DecreaseResolutionOrBPP(void) +{ + if (g_IsVidSizeLock || g_Camera.type == CAM_CINEMATIC + || g_GameFlow.screen_sizing_disabled + || !g_SavedAppSettings.fullscreen) { + return; + } + + APP_SETTINGS new_settings = g_SavedAppSettings; + const DISPLAY_MODE_NODE *const current_mode = new_settings.video_mode; + const DISPLAY_MODE_NODE *mode = current_mode; + if (mode != NULL) { + mode = mode->previous; + } + + if (new_settings.render_mode == RM_HARDWARE) { + for (; mode != NULL; mode = mode->previous) { + if (g_Input.slow) { + if (mode->body.width == current_mode->body.width + && mode->body.height == current_mode->body.height + && mode->body.vga == current_mode->body.vga + && mode->body.bpp < current_mode->body.bpp) { + break; + } + } else if ( + mode->body.vga == current_mode->body.vga + && mode->body.bpp == current_mode->body.bpp) { + break; + } + } + } + + if (mode != NULL) { + new_settings.video_mode = mode; + GameApplySettings(&new_settings); + } +} + +static void M_IncreaseResolutionOrBPP(void) +{ + if (g_IsVidSizeLock || g_Camera.type == CAM_CINEMATIC + || g_GameFlow.screen_sizing_disabled + || !g_SavedAppSettings.fullscreen) { + return; + } + + APP_SETTINGS new_settings = g_SavedAppSettings; + const DISPLAY_MODE_NODE *const current_mode = new_settings.video_mode; + const DISPLAY_MODE_NODE *mode = current_mode; + if (mode != NULL) { + mode = mode->next; + } + + if (new_settings.render_mode == RM_HARDWARE) { + for (; mode != NULL; mode = mode->next) { + if (g_Input.slow) { + if (mode->body.width == current_mode->body.width + && mode->body.height == current_mode->body.height + && mode->body.vga == current_mode->body.vga + && mode->body.bpp > current_mode->body.bpp) { + break; + } + } else if ( + mode->body.vga == current_mode->body.vga + && mode->body.bpp == current_mode->body.bpp) { + break; + } + } + } + if (mode != NULL) { + new_settings.video_mode = mode; + GameApplySettings(&new_settings); + } +} + +static void M_DecreaseInternalScreenSize(void) +{ + if (g_IsVidSizeLock || g_Camera.type == CAM_CINEMATIC + || g_GameFlow.screen_sizing_disabled + || !g_SavedAppSettings.fullscreen) { + return; + } + + DecreaseScreenSize(); +} + +static void M_IncreaseInternalScreenSize(void) +{ + if (g_IsVidSizeLock || g_Camera.type == CAM_CINEMATIC + || g_GameFlow.screen_sizing_disabled + || !g_SavedAppSettings.fullscreen) { + return; + } + + IncreaseScreenSize(); +} + +void Shell_ProcessInput(void) +{ + if (g_InputDB.screenshot) { + Screenshot_Make(g_Config.rendering.screenshot_format); + } + + if (g_InputDB.switch_resolution) { + if (g_Input.slow) { + M_DecreaseResolutionOrBPP(); + } else { + M_IncreaseResolutionOrBPP(); + } + } + + if (g_InputDB.switch_internal_screen_size) { + if (g_Input.slow) { + M_DecreaseInternalScreenSize(); + } else { + M_IncreaseInternalScreenSize(); + } + } + + if (g_InputDB.toggle_bilinear_filter) { + M_ToggleBilinearFiltering(); + } + + if (g_InputDB.toggle_perspective_filter) { + M_TogglePerspectiveCorrection(); + } + + if (g_InputDB.toggle_z_buffer) { + M_ToggleZBuffer(); + } + + if (g_InputDB.toggle_dither) { + M_ToggleDither(); + } + + if (g_InputDB.toggle_fullscreen) { + M_ToggleFullscreen(); + } + + if (g_InputDB.toggle_rendering_mode) { + M_ToggleRenderingMode(); + } +} diff --git a/src/tr2/game/shell/input.h b/src/tr2/game/shell/input.h new file mode 100644 index 000000000..d246a7cd3 --- /dev/null +++ b/src/tr2/game/shell/input.h @@ -0,0 +1,3 @@ +#pragma once + +void Shell_ProcessInput(void); diff --git a/src/tr2/game/ui/common.c b/src/tr2/game/ui/common.c index f9cf6c892..aad47d9f8 100644 --- a/src/tr2/game/ui/common.c +++ b/src/tr2/game/ui/common.c @@ -1,6 +1,6 @@ #include -#include +#include int32_t UI_GetCanvasWidth(void) { @@ -16,15 +16,15 @@ UI_INPUT UI_TranslateInput(uint32_t system_keycode) { // clang-format off switch (system_keycode) { - case VK_UP: return UI_KEY_UP; - case VK_DOWN: return UI_KEY_DOWN; - case VK_LEFT: return UI_KEY_LEFT; - case VK_RIGHT: return UI_KEY_RIGHT; - case VK_HOME: return UI_KEY_HOME; - case VK_END: return UI_KEY_END; - case VK_BACK: return UI_KEY_BACK; - case VK_RETURN: return UI_KEY_RETURN; - case VK_ESCAPE: return UI_KEY_ESCAPE; + case SDLK_UP: return UI_KEY_UP; + case SDLK_DOWN: return UI_KEY_DOWN; + case SDLK_LEFT: return UI_KEY_LEFT; + case SDLK_RIGHT: return UI_KEY_RIGHT; + case SDLK_HOME: return UI_KEY_HOME; + case SDLK_END: return UI_KEY_END; + case SDLK_BACKSPACE: return UI_KEY_BACK; + case SDLK_RETURN: return UI_KEY_RETURN; + case SDLK_ESCAPE: return UI_KEY_ESCAPE; } // clang-format on return -1; diff --git a/src/tr2/game/ui/controllers/controls.c b/src/tr2/game/ui/controllers/controls.c index db339db53..aaa34d8af 100644 --- a/src/tr2/game/ui/controllers/controls.c +++ b/src/tr2/game/ui/controllers/controls.c @@ -1,49 +1,61 @@ #include "game/ui/controllers/controls.h" #include "game/input.h" +#include "game/shell.h" #include "global/vars.h" +#include #include -#include +#include static const INPUT_ROLE m_LeftRoles[] = { - INPUT_ROLE_UP, INPUT_ROLE_DOWN, INPUT_ROLE_LEFT, - INPUT_ROLE_RIGHT, INPUT_ROLE_STEP_LEFT, INPUT_ROLE_STEP_RIGHT, - INPUT_ROLE_SLOW, (INPUT_ROLE)-1, + INPUT_ROLE_UP, INPUT_ROLE_DOWN, INPUT_ROLE_LEFT, INPUT_ROLE_RIGHT, + INPUT_ROLE_STEP_L, INPUT_ROLE_STEP_R, INPUT_ROLE_SLOW, (INPUT_ROLE)-1, }; static const INPUT_ROLE m_RightRoles[] = { - INPUT_ROLE_JUMP, INPUT_ROLE_ACTION, INPUT_ROLE_DRAW_WEAPON, - INPUT_ROLE_FLARE, INPUT_ROLE_LOOK, INPUT_ROLE_ROLL, - INPUT_ROLE_OPTION, INPUT_ROLE_CONSOLE, (INPUT_ROLE)-1, + INPUT_ROLE_JUMP, INPUT_ROLE_ACTION, INPUT_ROLE_DRAW, + INPUT_ROLE_USE_FLARE, INPUT_ROLE_LOOK, INPUT_ROLE_ROLL, + INPUT_ROLE_OPTION, INPUT_ROLE_ENTER_CONSOLE, (INPUT_ROLE)-1, }; static const INPUT_ROLE *M_GetInputRoles(int32_t col); +static void M_CycleLayout(UI_CONTROLS_CONTROLLER *controller, int32_t dir); static bool M_NavigateLayout(UI_CONTROLS_CONTROLLER *controller); static bool M_NavigateInputs(UI_CONTROLS_CONTROLLER *controller); -static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *controller); -static bool M_Listen(UI_CONTROLS_CONTROLLER *controller); static bool M_NavigateInputsDebounce(UI_CONTROLS_CONTROLLER *controller); +static bool M_Listen(UI_CONTROLS_CONTROLLER *controller); +static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *controller); static const INPUT_ROLE *M_GetInputRoles(const int32_t col) { return col == 0 ? m_LeftRoles : m_RightRoles; } +static void M_CycleLayout( + UI_CONTROLS_CONTROLLER *const controller, const int32_t dir) +{ + controller->active_layout += dir; + controller->active_layout += INPUT_LAYOUT_NUMBER_OF; + controller->active_layout %= INPUT_LAYOUT_NUMBER_OF; + + const EVENT event = { + .name = "layout_change", + .sender = NULL, + .data = NULL, + }; + EventManager_Fire(controller->events, &event); +} + static bool M_NavigateLayout(UI_CONTROLS_CONTROLLER *const controller) { if (g_InputDB.menu_confirm || g_InputDB.menu_back) { controller->state = UI_CONTROLS_STATE_EXIT; - } else if (g_InputDB.right) { - controller->active_layout++; - controller->active_layout %= INPUT_MAX_LAYOUT; } else if (g_InputDB.left) { - if (controller->active_layout == 0) { - controller->active_layout = INPUT_MAX_LAYOUT - 1; - } else { - controller->active_layout--; - } + M_CycleLayout(controller, -1); + } else if (g_InputDB.right) { + M_CycleLayout(controller, 1); } else if (g_InputDB.back && controller->active_layout != 0) { controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS; controller->active_col = 0; @@ -93,7 +105,7 @@ static bool M_NavigateInputs(UI_CONTROLS_CONTROLLER *const controller) } } } else if (g_InputDB.menu_confirm) { - controller->state = UI_CONTROLS_STATE_LISTEN_DEBOUNCE; + controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE; } else { return false; } @@ -102,9 +114,11 @@ static bool M_NavigateInputs(UI_CONTROLS_CONTROLLER *const controller) return true; } -static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *const controller) +static bool M_NavigateInputsDebounce(UI_CONTROLS_CONTROLLER *const controller) { - if (Input_IsAnythingPressed()) { + Shell_ProcessEvents(); + Input_Update(); + if (g_Input.any) { return false; } Input_EnterListenMode(); @@ -114,66 +128,50 @@ static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *const controller) static bool M_Listen(UI_CONTROLS_CONTROLLER *const controller) { - int32_t pressed = 0; - - if (g_JoyKeys != 0) { - for (int32_t i = 0; i < 32; i++) { - if (g_JoyKeys & (1 << i)) { - pressed = i; - break; - } - } - if (!pressed) { - return false; - } - pressed += 0x100; - } else { - for (int32_t i = 0; i < 256; i++) { - if (g_DIKeys[i] & 0x80) { - pressed = i; - break; - } - } - if (!pressed) { - return false; - } - } - - if (!pressed - // clang-format off - || Input_GetKeyName(pressed) == NULL - || pressed == DIK_RETURN - || pressed == DIK_LEFT - || pressed == DIK_RIGHT - || pressed == DIK_UP - || pressed == DIK_DOWN - // clang-format on - ) { - g_Input = (INPUT_STATE) { 0 }; - g_InputDB = (INPUT_STATE) { 0 }; + if (!Input_ReadAndAssignRole( + controller->backend, controller->active_layout, + controller->active_role)) { return false; } - if (pressed != DIK_ESCAPE) { - Input_AssignKey( - controller->active_layout, controller->active_role, pressed); - } + Input_ExitListenMode(); + + const EVENT event = { + .name = "key_change", + .sender = NULL, + .data = NULL, + }; + EventManager_Fire(controller->events, &event); - controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE; + controller->state = UI_CONTROLS_STATE_LISTEN_DEBOUNCE; return true; } -static bool M_NavigateInputsDebounce(UI_CONTROLS_CONTROLLER *const controller) +static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *const controller) { - if (Input_IsAnythingPressed()) { + if (g_Input.any) { return false; } - Input_ExitListenMode(); controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS; return true; } +void UI_ControlsController_Init(UI_CONTROLS_CONTROLLER *const controller) +{ + assert(controller->events == NULL); + controller->backend = INPUT_BACKEND_KEYBOARD; + controller->state = UI_CONTROLS_STATE_NAVIGATE_LAYOUT; + + controller->events = EventManager_Create(); +} + +void UI_ControlsController_Shutdown(UI_CONTROLS_CONTROLLER *const controller) +{ + EventManager_Free(controller->events); + controller->events = NULL; +} + bool UI_ControlsController_Control(UI_CONTROLS_CONTROLLER *const controller) { switch (controller->state) { @@ -181,12 +179,12 @@ bool UI_ControlsController_Control(UI_CONTROLS_CONTROLLER *const controller) return M_NavigateLayout(controller); case UI_CONTROLS_STATE_NAVIGATE_INPUTS: return M_NavigateInputs(controller); - case UI_CONTROLS_STATE_LISTEN_DEBOUNCE: - return M_ListenDebounce(controller); - case UI_CONTROLS_STATE_LISTEN: - return M_Listen(controller); case UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE: return M_NavigateInputsDebounce(controller); + case UI_CONTROLS_STATE_LISTEN: + return M_Listen(controller); + case UI_CONTROLS_STATE_LISTEN_DEBOUNCE: + return M_ListenDebounce(controller); default: return false; } diff --git a/src/tr2/game/ui/controllers/controls.h b/src/tr2/game/ui/controllers/controls.h index c0dfe293c..ea222bdb5 100644 --- a/src/tr2/game/ui/controllers/controls.h +++ b/src/tr2/game/ui/controllers/controls.h @@ -2,23 +2,30 @@ #include "game/input.h" +#include + typedef enum { UI_CONTROLS_STATE_NAVIGATE_LAYOUT, UI_CONTROLS_STATE_NAVIGATE_INPUTS, - UI_CONTROLS_STATE_LISTEN_DEBOUNCE, - UI_CONTROLS_STATE_LISTEN, UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE, + UI_CONTROLS_STATE_LISTEN, + UI_CONTROLS_STATE_LISTEN_DEBOUNCE, UI_CONTROLS_STATE_EXIT, } UI_CONTROLS_STATE; typedef struct { + INPUT_BACKEND backend; + UI_CONTROLS_STATE state; int32_t active_layout; + INPUT_ROLE active_role; int32_t active_col; int32_t active_row; - INPUT_ROLE active_role; - UI_CONTROLS_STATE state; + + EVENT_MANAGER *events; } UI_CONTROLS_CONTROLLER; +void UI_ControlsController_Init(UI_CONTROLS_CONTROLLER *controller); +void UI_ControlsController_Shutdown(UI_CONTROLS_CONTROLLER *controller); bool UI_ControlsController_Control(UI_CONTROLS_CONTROLLER *controller); INPUT_ROLE UI_ControlsController_GetInputRole(int32_t col, int32_t row); diff --git a/src/tr2/game/ui/widgets/controls_dialog.c b/src/tr2/game/ui/widgets/controls_dialog.c index 5aa5223af..4ad0d6f9e 100644 --- a/src/tr2/game/ui/widgets/controls_dialog.c +++ b/src/tr2/game/ui/widgets/controls_dialog.c @@ -93,7 +93,6 @@ UI_WIDGET *UI_ControlsDialog_Create(UI_CONTROLS_CONTROLLER *const controller) }; self->controller = controller; - self->controller->state = UI_CONTROLS_STATE_NAVIGATE_LAYOUT; self->layout_selector = UI_ControlsLayoutSelector_Create(self->controller); self->left_column = UI_ControlsColumn_Create(0, self->controller); diff --git a/src/tr2/game/ui/widgets/controls_input_selector.c b/src/tr2/game/ui/widgets/controls_input_selector.c index a08356c37..097253c14 100644 --- a/src/tr2/game/ui/widgets/controls_input_selector.c +++ b/src/tr2/game/ui/widgets/controls_input_selector.c @@ -24,12 +24,13 @@ static void M_Free(UI_CONTROLS_INPUT_SELECTOR *self); static void M_UpdateText(UI_CONTROLS_INPUT_SELECTOR *const self) { - const uint16_t key = - Input_GetAssignedKey(self->controller->active_layout, self->input_role); - if (Input_GetKeyName(key) == NULL) { + const char *const key_name = Input_GetKeyName( + self->controller->backend, self->controller->active_layout, + self->input_role); + if (key_name == NULL) { UI_Label_ChangeText(self->choice, "BAD"); } else { - UI_Label_ChangeText(self->choice, Input_GetKeyName(key)); + UI_Label_ChangeText(self->choice, key_name); } UI_Label_ChangeText(self->label, Input_GetRoleName(self->input_role)); } @@ -67,9 +68,7 @@ static void M_Control(UI_CONTROLS_INPUT_SELECTOR *const self) || self->controller->state == UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE) { UI_Label_AddFrame(self->label); - } else if ( - self->controller->state == UI_CONTROLS_STATE_LISTEN - || self->controller->state == UI_CONTROLS_STATE_LISTEN_DEBOUNCE) { + } else if (self->controller->state == UI_CONTROLS_STATE_LISTEN) { UI_Label_AddFrame(self->choice); } } @@ -78,14 +77,10 @@ static void M_Control(UI_CONTROLS_INPUT_SELECTOR *const self) // Flash conflicts UI_Label_Flash(self->choice, false, 0); - const uint16_t key1 = - Input_GetAssignedKey(self->controller->active_layout, self->input_role); - for (INPUT_ROLE role = 0; role < INPUT_ROLE_NUMBER_OF; role++) { - const uint16_t key2 = - Input_GetAssignedKey(self->controller->active_layout, role); - if (role != self->input_role && key1 == key2) { - UI_Label_Flash(self->choice, true, 20); - } + if (Input_IsKeyConflicted( + self->controller->backend, self->controller->active_layout, + self->input_role)) { + UI_Label_Flash(self->choice, true, 20); } } diff --git a/src/tr2/global/funcs.h b/src/tr2/global/funcs.h index 65c8efb78..e8e5e0417 100644 --- a/src/tr2/global/funcs.h +++ b/src/tr2/global/funcs.h @@ -182,17 +182,6 @@ #define DartEffectControl ((void __cdecl (*)(int16_t fx_num))0x00442AE0) #define GiantYeti_Control ((void __cdecl (*)(int16_t item_num))0x00443050) #define Yeti_Control ((void __cdecl (*)(int16_t item_num))0x00443350) -#define WinInReadJoystick ((DWORD __cdecl (*)(int32_t *x, int32_t *y))0x004472A0) -#define WinInputInit ((bool __cdecl (*)(void))0x004473B0) -#define DInputEnumDevices ((bool __cdecl (*)(JOYSTICK_LIST *joystickList))0x00447430) -#define DInputEnumDevicesCallback ((BOOL __stdcall (*)(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef))0x00447460) -#define GetJoystick ((JOYSTICK_NODE *__cdecl (*)(GUID *lpGuid))0x00447570) -#define DInputKeyboardCreate ((void __cdecl (*)(void))0x004475C0) -#define DInputKeyboardRelease ((void __cdecl (*)(void))0x00447690) -#define DInputJoystickCreate ((bool __cdecl (*)(void))0x004476C0) -#define WinInStart ((void __cdecl (*)(void))0x004477B0) -#define WinInFinish ((void __cdecl (*)(void))0x004477E0) -#define WinInRunControlPanel ((void __cdecl (*)(HWND hWnd))0x004477F0) #define IncreaseScreenSize ((void __cdecl (*)(void))0x00447810) #define DecreaseScreenSize ((void __cdecl (*)(void))0x00447880) #define setup_screen_size ((void __cdecl (*)(void))0x004478F0) diff --git a/src/tr2/global/vars_decomp.h b/src/tr2/global/vars_decomp.h index cb2b98f92..371540da6 100644 --- a/src/tr2/global/vars_decomp.h +++ b/src/tr2/global/vars_decomp.h @@ -298,7 +298,6 @@ #define g_MinWindowHeight (*(int32_t*)0x004D838C) #define g_IsGameWindowActive (*(bool*)0x004D8390) #define g_MessageLoopCounter (*(int32_t*)0x004D8394) -#define g_DInput (*(LPDIRECTINPUT*)0x004D855C) #define IDID_SysKeyboard (*(LPDIRECTINPUTDEVICE*)0x004D8560) #define g_ScreenSizer (*(int32_t*)0x004D8568) #define g_IsVidSizeLock (*(int32_t*)0x004D856C) diff --git a/src/tr2/inject_exec.c b/src/tr2/inject_exec.c index 5ba10275a..90549aa20 100644 --- a/src/tr2/inject_exec.c +++ b/src/tr2/inject_exec.c @@ -86,7 +86,6 @@ #include "inject_util.h" #include "specific/s_audio_sample.h" #include "specific/s_flagged_string.h" -#include "specific/s_input.h" static void M_DecompGeneral(const bool enable); static void M_DecompFMV(const bool enable); @@ -133,7 +132,6 @@ static void M_Lot(bool enable); static void M_Objects(bool enable); static void M_S_Audio_Sample(bool enable); -static void M_S_Input(bool enable); static void M_S_FlaggedString(bool enable); static void M_DecompGeneral(const bool enable) @@ -1110,11 +1108,6 @@ static void M_S_Audio_Sample(const bool enable) INJECT(enable, 0x004553C0, S_Audio_Sample_OutIsTrackPlaying); } -static void M_S_Input(const bool enable) -{ - INJECT(enable, 0x0044D8F0, S_Input_Key); -} - static void M_S_FlaggedString(const bool enable) { INJECT(enable, 0x00445F00, S_FlaggedString_Delete); @@ -1174,6 +1167,5 @@ void Inject_Exec(void) M_Objects(true); M_S_Audio_Sample(true); - M_S_Input(true); M_S_FlaggedString(true); } diff --git a/src/tr2/meson.build b/src/tr2/meson.build index a952a7b81..6a4c86938 100644 --- a/src/tr2/meson.build +++ b/src/tr2/meson.build @@ -195,7 +195,8 @@ dll_sources = [ 'game/room.c', 'game/room_draw.c', 'game/savegame/common.c', - 'game/shell.c', + 'game/shell/common.c', + 'game/shell/input.c', 'game/sound.c', 'game/text.c', 'game/ui/common.c', @@ -215,7 +216,6 @@ dll_sources = [ 'main_dll.c', 'specific/s_audio_sample.c', 'specific/s_flagged_string.c', - 'specific/s_input.c', dll_resources, ] diff --git a/src/tr2/specific/s_input.c b/src/tr2/specific/s_input.c deleted file mode 100644 index f95888a39..000000000 --- a/src/tr2/specific/s_input.c +++ /dev/null @@ -1,523 +0,0 @@ -#include "specific/s_input.h" - -#include "config.h" -#include "decomp/decomp.h" -#include "game/console/common.h" -#include "game/gameflow/gameflow_new.h" -#include "game/input.h" -#include "game/inventory/backpack.h" -#include "game/lara/control.h" -#include "global/const.h" -#include "global/funcs.h" -#include "global/vars.h" - -#include -#include - -#include - -#define KEY_DOWN(key) ((g_DIKeys[(key)] & 0x80)) - -INPUT_LAYOUT g_Layout[2] = { - { .key = { - DIK_UP, - DIK_DOWN, - DIK_LEFT, - DIK_RIGHT, - DIK_DELETE, - DIK_NEXT, - DIK_RSHIFT, - DIK_RMENU, - DIK_RCONTROL, - DIK_SPACE, - DIK_PERIOD, - DIK_NUMPAD0, - DIK_END, - DIK_ESCAPE, - DIK_SLASH, - } }, - { .key = { - DIK_NUMPAD8, - DIK_NUMPAD2, - DIK_NUMPAD4, - DIK_NUMPAD6, - DIK_NUMPAD7, - DIK_NUMPAD9, - DIK_NUMPAD1, - DIK_ADD, - DIK_NUMPADENTER, - DIK_NUMPAD3, - DIK_SUBTRACT, - DIK_NUMPAD0, - DIK_NUMPAD5, - DIK_DECIMAL, - DIK_SLASH, - } } -}; - -static bool m_IsScreenshotPressed = false; -static bool m_IsF3Pressed = false; -static bool m_IsF4Pressed = false; -static bool m_IsF7Pressed = false; -static bool m_IsF8Pressed = false; -static bool m_IsF11Pressed = false; -static int32_t m_MediPackCooldown = 0; - -static bool M_KbdKey(int32_t layout_num, INPUT_ROLE role); -static bool M_JoyKey(int32_t layout_num, INPUT_ROLE role); - -static bool M_KbdKey(const int32_t layout_num, const INPUT_ROLE role) -{ - uint16_t key = Input_GetAssignedKey(layout_num, role); - if (key >= 0x100) { - return false; - } - - if (KEY_DOWN(key)) { - return true; - } - switch (key) { - case DIK_RCONTROL: - return KEY_DOWN(DIK_LCONTROL); - case DIK_LCONTROL: - return KEY_DOWN(DIK_RCONTROL); - case DIK_RSHIFT: - return KEY_DOWN(DIK_LSHIFT); - case DIK_LSHIFT: - return KEY_DOWN(DIK_RSHIFT); - case DIK_RMENU: - return KEY_DOWN(DIK_LMENU); - case DIK_LMENU: - return KEY_DOWN(DIK_RMENU); - } - return false; -} - -static bool M_JoyKey(const int32_t layout_num, const INPUT_ROLE role) -{ - uint16_t key = Input_GetAssignedKey(layout_num, role); - if (key < 0x100) { - return false; - } - return (g_JoyKeys & (1 << key)) != 0; -} - -bool __cdecl S_Input_Key(const INPUT_ROLE role) -{ - return M_KbdKey(1, role) || M_JoyKey(1, role) - || (!g_ConflictLayout[role] && M_KbdKey(0, role)); -} - -// TODO: refactor me!!! -bool __cdecl S_Input_Update(void) -{ - WinVidSpinMessageLoop(0); - WinInReadKeyboard(g_DIKeys); - - int32_t joy_xpos = 0; - int32_t joy_ypos = 0; - g_JoyKeys = WinInReadJoystick(&joy_xpos, &joy_ypos); - - INPUT_STATE input = { 0 }; - if (joy_xpos < -8) { - input.left = 1; - } else if (joy_xpos > 8) { - input.right = 1; - } - - if (joy_ypos > 8) { - input.back = 1; - } else if (joy_ypos < -8) { - input.forward = 1; - } - - if (S_Input_Key(INPUT_ROLE_UP)) { - input.forward = 1; - } - if (S_Input_Key(INPUT_ROLE_DOWN)) { - input.back = 1; - } - if (S_Input_Key(INPUT_ROLE_LEFT)) { - input.left = 1; - } - if (S_Input_Key(INPUT_ROLE_RIGHT)) { - input.right = 1; - } - if (S_Input_Key(INPUT_ROLE_STEP_LEFT)) { - input.step_left = 1; - } - if (S_Input_Key(INPUT_ROLE_STEP_RIGHT)) { - input.step_right = 1; - } - if (S_Input_Key(INPUT_ROLE_SLOW)) { - input.slow = 1; - } - if (S_Input_Key(INPUT_ROLE_JUMP)) { - input.jump = 1; - } - - if (S_Input_Key(INPUT_ROLE_ACTION)) { - input.action = 1; - } - if (S_Input_Key(INPUT_ROLE_DRAW_WEAPON)) { - input.draw = 1; - } - if (S_Input_Key(INPUT_ROLE_FLARE)) { - input.flare = 1; - } - if (S_Input_Key(INPUT_ROLE_LOOK)) { - input.look = 1; - } - if (S_Input_Key(INPUT_ROLE_ROLL)) { - input.roll = 1; - } - - if (S_Input_Key(INPUT_ROLE_CONSOLE)) { - input.console = 1; - } - - if (S_Input_Key(INPUT_ROLE_OPTION) && g_Camera.type != CAM_CINEMATIC) { - input.option = 1; - } - if (input.forward && input.back) { - input.roll = 1; - } - - if (KEY_DOWN(DIK_RETURN) || input.action) { - input.menu_confirm = 1; - } - if (KEY_DOWN(DIK_ESCAPE)) { - input.menu_back = 1; - } - - if (input.left && input.right) { - input.left = 0; - input.right = 0; - } - - if (g_IsFMVPlaying || Console_IsOpened()) { - g_Input = input; - return g_IsGameToExit; - } - - if (g_GameInfo.current_level.type != GFL_DEMO) { - if (KEY_DOWN(DIK_1) && Inv_RequestItem(O_PISTOL_OPTION)) { - g_Lara.request_gun_type = LGT_PISTOLS; - } else if (KEY_DOWN(DIK_2) && Inv_RequestItem(O_SHOTGUN_OPTION)) { - g_Lara.request_gun_type = LGT_SHOTGUN; - } else if (KEY_DOWN(DIK_3) && Inv_RequestItem(O_MAGNUM_OPTION)) { - g_Lara.request_gun_type = LGT_MAGNUMS; - } else if (KEY_DOWN(DIK_4) && Inv_RequestItem(O_UZI_OPTION)) { - g_Lara.request_gun_type = LGT_UZIS; - } else if (KEY_DOWN(DIK_5) && Inv_RequestItem(O_HARPOON_OPTION)) { - g_Lara.request_gun_type = LGT_HARPOON; - } else if (KEY_DOWN(DIK_6) && Inv_RequestItem(O_M16_OPTION)) { - g_Lara.request_gun_type = LGT_M16; - } else if (KEY_DOWN(DIK_7) && Inv_RequestItem(O_GRENADE_OPTION)) { - g_Lara.request_gun_type = LGT_GRENADE; - } else if (KEY_DOWN(DIK_0) && Inv_RequestItem(O_FLARES_OPTION)) { - g_Lara.request_gun_type = LGT_FLARE; - } - - if (KEY_DOWN(DIK_8) && Inv_RequestItem(O_SMALL_MEDIPACK_OPTION)) { - if (m_MediPackCooldown == 0) { - Lara_UseItem(O_SMALL_MEDIPACK_OPTION); - } - m_MediPackCooldown = 15; - } - if (KEY_DOWN(DIK_9) && Inv_RequestItem(O_LARGE_MEDIPACK_OPTION)) { - if (m_MediPackCooldown == 0) { - Lara_UseItem(O_LARGE_MEDIPACK_OPTION); - } - m_MediPackCooldown = 15; - } - - if (m_MediPackCooldown > 0) { - m_MediPackCooldown--; - } - } - - if (KEY_DOWN(DIK_S)) { - if (!m_IsScreenshotPressed) { - m_IsScreenshotPressed = true; - Screenshot_Make(g_Config.rendering.screenshot_format); - } - } else { - m_IsScreenshotPressed = false; - } - - const bool is_shift_pressed = KEY_DOWN(DIK_LSHIFT) || KEY_DOWN(DIK_RSHIFT); - - // software renderer keys… - if (g_SavedAppSettings.render_mode == RM_SOFTWARE) { - // toggle triple buffering (F7) or perspective correction (Shift+F7) - if (KEY_DOWN(DIK_F7)) { - if (!m_IsF7Pressed) { - m_IsF7Pressed = true; - APP_SETTINGS new_settings = g_SavedAppSettings; - if (!is_shift_pressed) { - new_settings.perspective_correct = - !new_settings.perspective_correct; - g_PerspectiveDistance = - g_SavedAppSettings.perspective_correct - ? SW_DETAIL_HIGH - : SW_DETAIL_MEDIUM; - } else if (g_SavedAppSettings.fullscreen) { - new_settings.triple_buffering = - !new_settings.triple_buffering; - } - GameApplySettings(&new_settings); - } - } else { - m_IsF7Pressed = false; - } - } - - // hardware renderer keys… - if (g_SavedAppSettings.render_mode == RM_HARDWARE) { - // toggle triple buffering (Shift+F7) or zbuffer (F7) - if (KEY_DOWN(DIK_F7)) { - if (!m_IsF7Pressed) { - m_IsF7Pressed = true; - APP_SETTINGS new_settings = g_SavedAppSettings; - if (!is_shift_pressed) { - new_settings.zbuffer = !new_settings.zbuffer; - } else if (g_SavedAppSettings.fullscreen) { - new_settings.triple_buffering = - !new_settings.triple_buffering; - } - GameApplySettings(&new_settings); - } - } else { - m_IsF7Pressed = false; - } - - // toggle perspective correction (Shift+F8) or bilinear filter (F8) - if (KEY_DOWN(DIK_F8)) { - if (!m_IsF8Pressed) { - m_IsF8Pressed = true; - APP_SETTINGS new_settings = g_SavedAppSettings; - if (!is_shift_pressed) { - new_settings.bilinear_filtering = - !new_settings.bilinear_filtering; - } else { - new_settings.perspective_correct = - !new_settings.perspective_correct; - } - GameApplySettings(&new_settings); - } - } else { - m_IsF8Pressed = false; - } - - // toggle dither (F11) - if (KEY_DOWN(DIK_F11)) { - if (!m_IsF11Pressed) { - m_IsF11Pressed = true; - APP_SETTINGS new_settings = g_SavedAppSettings; - new_settings.dither = !new_settings.dither; - GameApplySettings(&new_settings); - } - } else { - m_IsF11Pressed = false; - } - } - - if (!g_IsVidModeLock && KEY_DOWN(DIK_F12)) { - APP_SETTINGS new_settings = g_SavedAppSettings; - // toggle fullscreen (F12) - if (!is_shift_pressed) { - new_settings.fullscreen = !new_settings.fullscreen; - if (g_SavedAppSettings.fullscreen) { - const int32_t win_width = MAX(g_PhdWinWidth, 320); - const int32_t win_height = MAX(g_PhdWinHeight, 240); - new_settings.window_height = win_height; - new_settings.window_width = - CalculateWindowWidth(win_width, win_height); - new_settings.triple_buffering = 0; - GameApplySettings(&new_settings); - - g_GameSizer = 1.0; - g_GameSizerCopy = 1.0; - setup_screen_size(); - } else { - const DISPLAY_MODE_LIST *const mode_list = - new_settings.render_mode == RM_HARDWARE - ? &g_CurrentDisplayAdapter.hw_disp_mode_list - : &g_CurrentDisplayAdapter.sw_disp_mode_list; - - if (mode_list->count > 0) { - const DISPLAY_MODE target_mode = { - .width = g_GameVid_Width, - .height = g_GameVid_Height, - .bpp = g_GameVid_BPP, - .vga = VGA_NO_VGA, - }; - - const DISPLAY_MODE_NODE *mode = NULL; - for (mode = mode_list->head; mode != NULL; - mode = mode->next) { - if (!CompareVideoModes(&mode->body, &target_mode)) { - break; - } - } - - if (mode == NULL) { - mode = mode_list->tail; - } - - new_settings.video_mode = mode; - GameApplySettings(&new_settings); - } - } - // toggle renderer mode (Shift+F12) - } else if (!g_Inv_IsActive) { - new_settings.render_mode = new_settings.render_mode == RM_HARDWARE - ? RM_SOFTWARE - : RM_HARDWARE; - - const DISPLAY_MODE_LIST *const mode_list = - new_settings.render_mode == RM_HARDWARE - ? &g_CurrentDisplayAdapter.hw_disp_mode_list - : &g_CurrentDisplayAdapter.sw_disp_mode_list; - - if (mode_list->count > 0) { - const DISPLAY_MODE target_mode = { - .width = g_GameVid_Width, - .height = g_GameVid_Height, - .bpp = new_settings.render_mode == RM_HARDWARE ? 16 : 8, - .vga = VGA_NO_VGA, - }; - - const DISPLAY_MODE_NODE *mode = NULL; - for (mode = mode_list->head; mode != NULL; mode = mode->next) { - if (!CompareVideoModes(&mode->body, &target_mode)) { - break; - } - } - - if (mode == NULL) { - mode = mode_list->tail; - } - - new_settings.video_mode = mode; - new_settings.fullscreen = 1; - GameApplySettings(&new_settings); - } - } - } - - if (!g_IsVidSizeLock && g_Camera.type != CAM_CINEMATIC - && !(g_GameFlow.screen_sizing_disabled)) { - APP_SETTINGS new_settings = g_SavedAppSettings; - - // decrease resolution or BPP (F1) - if (KEY_DOWN(DIK_F1) && new_settings.fullscreen) { - const DISPLAY_MODE_NODE *const current_mode = - new_settings.video_mode; - const DISPLAY_MODE_NODE *mode = current_mode; - if (mode != NULL) { - mode = mode->previous; - } - - if (new_settings.render_mode == RM_HARDWARE) { - for (; mode != NULL; mode = mode->previous) { - if (is_shift_pressed) { - if (mode->body.width == current_mode->body.width - && mode->body.height == current_mode->body.height - && mode->body.vga == current_mode->body.vga - && mode->body.bpp < current_mode->body.bpp) { - break; - } - } else if ( - mode->body.vga == current_mode->body.vga - && mode->body.bpp == current_mode->body.bpp) { - break; - } - } - } - - if (mode != NULL) { - new_settings.video_mode = mode; - GameApplySettings(&new_settings); - } - } - - // increase resolution (F2) - if (KEY_DOWN(DIK_F2) && new_settings.fullscreen) { - const DISPLAY_MODE_NODE *const current_mode = - new_settings.video_mode; - const DISPLAY_MODE_NODE *mode = current_mode; - if (mode != NULL) { - mode = mode->next; - } - - if (new_settings.render_mode == RM_HARDWARE) { - for (; mode != NULL; mode = mode->next) { - if (is_shift_pressed) { - if (mode->body.width == current_mode->body.width - && mode->body.height == current_mode->body.height - && mode->body.vga == current_mode->body.vga - && mode->body.bpp > current_mode->body.bpp) { - break; - } - } else if ( - mode->body.vga == current_mode->body.vga - && mode->body.bpp == current_mode->body.bpp) { - break; - } - } - } - if (mode != NULL) { - new_settings.video_mode = mode; - GameApplySettings(&new_settings); - } - } - - // decrease inner screen size (F3) - if (KEY_DOWN(DIK_F3)) { - if (!m_IsF3Pressed) { - m_IsF3Pressed = true; - if (g_SavedAppSettings.fullscreen) { - DecreaseScreenSize(); - } - } - } else { - m_IsF3Pressed = false; - } - - // increase inner screen size (F4) - if (KEY_DOWN(DIK_F4)) { - if (!m_IsF4Pressed) { - m_IsF4Pressed = true; - if (g_SavedAppSettings.fullscreen) { - IncreaseScreenSize(); - } - } - } else { - m_IsF4Pressed = false; - } - } - - if (!g_GameFlow.load_save_disabled) { - if (KEY_DOWN(DIK_F5)) { - input.save = 1; - } else if (KEY_DOWN(DIK_F6)) { - input.load = 1; - } - } - - g_Input = input; - return g_IsGameToExit; -} - -bool Input_IsAnythingPressed(void) -{ - WinInReadKeyboard(g_DIKeys); - for (int32_t i = 0; i < 256; i++) { - if (KEY_DOWN(i)) { - return true; - } - } - return false; -} diff --git a/src/tr2/specific/s_input.h b/src/tr2/specific/s_input.h deleted file mode 100644 index 14d316d80..000000000 --- a/src/tr2/specific/s_input.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "game/input.h" - -bool __cdecl S_Input_Key(INPUT_ROLE role); -bool __cdecl S_Input_Update(void);