From 4cd4b55ae759099c4f7e44b2b11bac01e0823a24 Mon Sep 17 00:00:00 2001 From: Ramen2X Date: Thu, 19 Dec 2024 19:25:49 -0500 Subject: [PATCH] replace directinput joystick APIs with SDL (#41) --- ISLE/isleapp.cpp | 2 +- .../lego/legoomni/include/legoinputmanager.h | 13 +- .../legoomni/src/entity/legonavcontroller.cpp | 4 +- .../legoomni/src/input/legoinputmanager.cpp | 119 +++++++++--------- README.md | 2 +- 5 files changed, 72 insertions(+), 68 deletions(-) diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 76c24cae..ed235783 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -236,7 +236,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) { *appstate = NULL; - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)) { SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "LEGO® Island Error", diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 160c4d28..b1739110 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -7,8 +7,9 @@ #include "mxpresenter.h" #include "mxqueue.h" +#include #include -#include +#include class LegoCameraController; class LegoControlManager; @@ -95,8 +96,8 @@ class LegoInputManager : public MxPresenter { MxResult Create(HWND p_hwnd); void Destroy() override; - MxResult GetJoystickId(); - MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, DWORD* p_buttonsState, MxU32* p_povPosition); + MxResult GetJoystick(); + MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition); void StartAutoDragTimer(); void StopAutoDragTimer(); void EnableInputProcessing(); @@ -150,10 +151,10 @@ class LegoInputManager : public MxPresenter { LegoControlManager* m_controlManager; // 0x84 MxBool m_unk0x88; // 0x88 const bool* m_keyboardState; - MxBool m_unk0x195; // 0x195 - MxS32 m_joyid; // 0x198 + MxBool m_unk0x195; // 0x195 + SDL_JoystickID* m_joyids; + SDL_Joystick* m_joystick; MxS32 m_joystickIndex; // 0x19c - JOYCAPS m_joyCaps; // 0x200 MxBool m_useJoystick; // 0x334 MxBool m_unk0x335; // 0x335 MxBool m_unk0x336; // 0x336 diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index d3474ced..5fd660f3 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -499,12 +499,10 @@ MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und) if (instance->GetInputManager()) { MxS32 joystickX; MxS32 joystickY; - DWORD buttonState; MxS32 povPosition; if (instance->GetInputManager() - ->GetJoystickState((MxU32*) &joystickX, (MxU32*) &joystickY, &buttonState, (MxU32*) &povPosition) != - FAILURE) { + ->GetJoystickState((MxU32*) &joystickX, (MxU32*) &joystickY, (MxU32*) &povPosition) != FAILURE) { MxU32 yVal = (joystickY * m_vMax) / 100; MxU32 xVal = (joystickX * m_hMax) / 100; diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 8c4dd24b..c18367f5 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -40,8 +40,9 @@ LegoInputManager::LegoInputManager() m_unk0x81 = FALSE; m_unk0x88 = FALSE; m_unk0x195 = 0; - m_joyid = -1; + m_joyids = NULL; m_joystickIndex = -1; + m_joystick = NULL; m_useJoystick = FALSE; m_unk0x335 = FALSE; m_unk0x336 = FALSE; @@ -77,7 +78,7 @@ MxResult LegoInputManager::Create(HWND p_hwnd) m_eventQueue = new LegoEventQueue; } - GetJoystickId(); + GetJoystick(); if (!m_keyboardNotifyList || !m_eventQueue) { Destroy(); @@ -148,29 +149,27 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags) } // FUNCTION: LEGO1 0x1005c240 -MxResult LegoInputManager::GetJoystickId() +MxResult LegoInputManager::GetJoystick() { - JOYINFOEX joyinfoex; + if (m_joystick != NULL && SDL_JoystickConnected(m_joystick) == TRUE) { + return SUCCESS; + } - if (m_useJoystick != FALSE) { + MxS32 numJoysticks = 0; + m_joyids = SDL_GetJoysticks(&numJoysticks); + + if (m_useJoystick != FALSE && numJoysticks != 0) { MxS32 joyid = m_joystickIndex; if (joyid >= 0) { - joyinfoex.dwSize = 0x34; - joyinfoex.dwFlags = 0xFF; - - if (joyGetPosEx(joyid, &joyinfoex) == JOYERR_NOERROR && - joyGetDevCaps(joyid, &m_joyCaps, 0x194) == JOYERR_NOERROR) { - m_joyid = joyid; + m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + if (m_joystick != NULL) { return SUCCESS; } } - for (joyid = JOYSTICKID1; joyid < 16; joyid++) { - joyinfoex.dwSize = 0x34; - joyinfoex.dwFlags = 0xFF; - if (joyGetPosEx(joyid, &joyinfoex) == JOYERR_NOERROR && - joyGetDevCaps(joyid, &m_joyCaps, 0x194) == JOYERR_NOERROR) { - m_joyid = joyid; + for (joyid = 0; joyid < numJoysticks; joyid++) { + m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + if (m_joystick != NULL) { return SUCCESS; } } @@ -180,55 +179,61 @@ MxResult LegoInputManager::GetJoystickId() } // FUNCTION: LEGO1 0x1005c320 -MxResult LegoInputManager::GetJoystickState( - MxU32* p_joystickX, - MxU32* p_joystickY, - DWORD* p_buttonsState, - MxU32* p_povPosition -) +MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition) { if (m_useJoystick != FALSE) { - if (m_joyid < 0 && GetJoystickId() == -1) { - m_useJoystick = FALSE; + if (GetJoystick() == -1) { + if (m_joystick != NULL) { + // GetJoystick() failed but handle to joystick is still open, close it + SDL_CloseJoystick(m_joystick); + m_joystick = NULL; + } + return FAILURE; } - JOYINFOEX joyinfoex; - joyinfoex.dwSize = 0x34; - joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNBUTTONS; - MxU32 capabilities = m_joyCaps.wCaps; + MxS16 xPos = SDL_GetJoystickAxis(m_joystick, 0); + MxS16 yPos = SDL_GetJoystickAxis(m_joystick, 1); + MxU8 hatPos = SDL_GetJoystickHat(m_joystick, 0); - if ((capabilities & JOYCAPS_HASPOV) != 0) { - joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS; + // normalize values acquired from joystick axes + *p_joystickX = ((xPos + 32768) * 100) / 65535; + *p_joystickY = ((yPos + 32768) * 100) / 65535; - if ((capabilities & JOYCAPS_POVCTS) != 0) { - joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS | JOY_RETURNPOVCTS; - } + switch (hatPos) { + case SDL_HAT_CENTERED: + *p_povPosition = (MxU32) -1; + break; + case SDL_HAT_UP: + *p_povPosition = (MxU32) 0; + break; + case SDL_HAT_RIGHT: + *p_povPosition = (MxU32) 9000 / 100; + break; + case SDL_HAT_DOWN: + *p_povPosition = (MxU32) 18000 / 100; + break; + case SDL_HAT_LEFT: + *p_povPosition = (MxU32) 27000 / 100; + break; + case SDL_HAT_RIGHTUP: + *p_povPosition = (MxU32) 4500 / 100; + break; + case SDL_HAT_RIGHTDOWN: + *p_povPosition = (MxU32) 13500 / 100; + break; + case SDL_HAT_LEFTUP: + *p_povPosition = (MxU32) 31500 / 100; + break; + case SDL_HAT_LEFTDOWN: + *p_povPosition = (MxU32) 22500 / 100; + break; + default: + *p_povPosition = (MxU32) -1; + break; } - MMRESULT mmresult = joyGetPosEx(m_joyid, &joyinfoex); - - if (mmresult == MMSYSERR_NOERROR) { - *p_buttonsState = joyinfoex.dwButtons; - MxU32 xmin = m_joyCaps.wXmin; - MxU32 ymax = m_joyCaps.wYmax; - MxU32 ymin = m_joyCaps.wYmin; - MxS32 ydiff = ymax - ymin; - *p_joystickX = ((joyinfoex.dwXpos - xmin) * 100) / (m_joyCaps.wXmax - xmin); - *p_joystickY = ((joyinfoex.dwYpos - m_joyCaps.wYmin) * 100) / ydiff; - if ((m_joyCaps.wCaps & (JOYCAPS_POV4DIR | JOYCAPS_POVCTS)) != 0) { - if (joyinfoex.dwPOV == JOY_POVCENTERED) { - *p_povPosition = (MxU32) -1; - return SUCCESS; - } - *p_povPosition = joyinfoex.dwPOV / 100; - return SUCCESS; - } - else { - *p_povPosition = (MxU32) -1; - return SUCCESS; - } - } + return SUCCESS; } return FAILURE; diff --git a/README.md b/README.md index 0293a4a3..0227601c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ To achieve our goal of platform independence, we need to replace any Windows-onl | Filesystem | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Afilesystem%5D%22&type=code) | | Threads, Mutexes (Synchronization) | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Asynchronization%5D%22&type=code) | | Keyboard/Mouse, DirectInput (Input) | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Ainput%5D%22&type=code) | -| Joystick/Gamepad, DirectInput (Input) | [SDL3](https://www.libsdl.org/) | ❌ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Ainput%5D%22&type=code) | +| Joystick/Gamepad, DirectInput (Input) | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Ainput%5D%22&type=code) | | WinMM, DirectSound (Audio) | [SDL3](https://www.libsdl.org/), [miniaudio](https://miniaud.io/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Aaudio%5D%22&type=code) | | DirectDraw (2D video) | [SDL3](https://www.libsdl.org/) | ❌ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3A2d%5D%22&type=code) | | [Smacker](https://github.com/isledecomp/isle/tree/master/3rdparty/smacker) | [libsmacker](https://github.com/foxtacles/libsmacker) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable%20%22%2F%2F%20%5Blibrary%3Alibsmacker%5D%22&type=code) |