From 87d481d80b6287771c9cc3ead646ef94b67d36dc Mon Sep 17 00:00:00 2001 From: Helloyunho Date: Sat, 5 Jul 2025 16:38:05 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20untested=20but=20added=20ga?= =?UTF-8?q?mepad=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ISLE/isleapp.cpp | 95 ++++++++++++++++-- ISLE/isleapp.h | 6 +- .../lego/legoomni/include/legoinputmanager.h | 20 ++-- .../legoomni/src/entity/legonavcontroller.cpp | 2 +- .../legoomni/src/input/legoinputmanager.cpp | 96 +++++++------------ 5 files changed, 134 insertions(+), 85 deletions(-) diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 6cb0375c..aa13a56e 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -90,6 +90,11 @@ MxS32 g_targetDepth = 16; // GLOBAL: ISLE 0x410064 MxS32 g_reqEnableRMDevice = FALSE; +float g_lastJoystickMouseX = 0; +float g_lastJoystickMouseY = 0; +float g_lastMouseX = 0; +float g_lastMouseY = 0; + // STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO®" @@ -113,8 +118,8 @@ IsleApp::IsleApp() m_drawCursor = FALSE; m_use3dSound = TRUE; m_useMusic = TRUE; - m_useJoystick = TRUE; - m_joystickIndex = 0; + m_useGamepad = TRUE; + m_gamepadIndex = 0; m_wideViewAngle = TRUE; m_islandQuality = 2; m_islandTexture = 1; @@ -149,6 +154,7 @@ IsleApp::IsleApp() m_maxLod = RealtimeView::GetUserMaxLOD(); m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20; m_transitionType = MxTransitionManager::e_mosaic; + m_mouseSensitivity = 4; } // FUNCTION: ISLE 0x4011a0 @@ -379,6 +385,27 @@ SDL_AppResult SDL_AppIterate(void* appstate) if (g_mousemoved) { g_mousemoved = FALSE; } + + if (g_lastJoystickMouseX != 0 || g_lastJoystickMouseY != 0) { + g_mousemoved = TRUE; + + g_lastMouseX = SDL_clamp(g_lastMouseX + g_lastJoystickMouseX, 0, 640); + g_lastMouseY = SDL_clamp(g_lastMouseY + g_lastJoystickMouseY, 0, 480); + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationMouseMove, + g_mousedown ? LegoEventNotificationParam::c_lButtonState : 0, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + + if (g_isle->GetDrawCursor()) { + VideoManager()->MoveCursor(Min((MxS32) g_lastMouseX, 639), Min((MxS32) g_lastMouseY, 479)); + } + } } return SDL_APP_CONTINUE; @@ -457,6 +484,58 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) } break; } + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { + { + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_SOUTH) { + if (InputManager()) { + InputManager()->QueueEvent(c_notificationKeyPress, SDLK_SPACE, 0, 0, SDLK_SPACE); + } + } + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_START) { + if (InputManager()) { + InputManager()->QueueEvent(c_notificationKeyPress, SDLK_ESCAPE, 0, 0, SDLK_ESCAPE); + } + } + } + break; + } + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { + if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX) { + g_lastJoystickMouseX = ((float) event->gaxis.value) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetMouseSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTY) { + g_lastJoystickMouseY = ((float) event->gaxis.value) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetMouseSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { + if (event->gaxis.value != 0) { + g_mousedown = TRUE; + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationButtonDown, + LegoEventNotificationParam::c_lButtonState, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + } + else { + g_mousedown = FALSE; + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationButtonUp, + LegoEventNotificationParam::c_lButtonState, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + } + } + break; + } case SDL_EVENT_MOUSE_MOTION: #ifdef __EMSCRIPTEN__ if (detectedTouchEvents) { @@ -749,8 +828,8 @@ MxResult IsleApp::SetupWindow() RealtimeView::SetUserMaxLOD(m_maxLod); if (LegoOmni::GetInstance()) { if (LegoOmni::GetInstance()->GetInputManager()) { - LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick); - LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex); + LegoOmni::GetInstance()->GetInputManager()->SetUseGamepad(m_useGamepad); + LegoOmni::GetInstance()->GetInputManager()->SetGamepadIndex(m_gamepadIndex); } if (LegoOmni::GetInstance()->GetVideoManager() && g_isle->GetDrawCursor()) { LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap); @@ -839,8 +918,8 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:3DSound", m_use3dSound ? "true" : "false"); iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false"); - iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false"); - iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10)); + iniparser_set(dict, "isle:UseJoystick", m_useGamepad ? "true" : "false"); + iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_gamepadIndex, buf, 10)); iniparser_set(dict, "isle:Draw Cursor", m_drawCursor ? "true" : "false"); iniparser_set(dict, "isle:Back Buffers in Video RAM", "-1"); @@ -893,8 +972,8 @@ bool IsleApp::LoadConfig() m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle); m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound); m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic); - m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); - m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); + m_useGamepad = iniparser_getboolean(dict, "isle:UseJoystick", m_useGamepad); + m_gamepadIndex = iniparser_getint(dict, "isle:JoystickIndex", m_gamepadIndex); m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor); MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4064dc25..8264ef39 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -52,6 +52,7 @@ class IsleApp { SDL_Cursor* GetCursorNo() { return m_cursorNo; } MxS32 GetDrawCursor() { return m_drawCursor; } MxS32 GetGameStarted() { return m_gameStarted; } + MxFloat GetMouseSensitivity() { return m_mouseSensitivity; } void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; } void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } @@ -73,8 +74,8 @@ class IsleApp { MxS32 m_hasLightSupport; // 0x24 MxS32 m_use3dSound; // 0x28 MxS32 m_useMusic; // 0x2c - MxS32 m_useJoystick; // 0x30 - MxS32 m_joystickIndex; // 0x34 + MxS32 m_useGamepad; // 0x30 + MxS32 m_gamepadIndex; // 0x34 MxS32 m_wideViewAngle; // 0x38 MxS32 m_islandQuality; // 0x3c MxS32 m_islandTexture; // 0x40 @@ -93,6 +94,7 @@ class IsleApp { const CursorBitmap* m_cursorNoBitmap; const CursorBitmap* m_cursorCurrentBitmap; char* m_mediaPath; + MxFloat m_mouseSensitivity; char* m_iniPath; MxFloat m_maxLod; diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 7ccad404..86be3cd7 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -108,8 +108,8 @@ class LegoInputManager : public MxPresenter { MxResult Create(HWND p_hwnd); void Destroy() override; - MxResult GetJoystick(); - MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition); + MxResult GetGamepad(); + MxResult GetGamepadState(MxU32* p_gamepadX, MxU32* p_gamepadY, MxU32* p_povPosition); void StartAutoDragTimer(); void StopAutoDragTimer(); void EnableInputProcessing(); @@ -121,8 +121,8 @@ class LegoInputManager : public MxPresenter { void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; } void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } - void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; } - void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; } + void SetUseGamepad(MxBool p_useGamepad) { m_useGamepad = p_useGamepad; } + void SetGamepadIndex(MxS32 p_gamepadIndex) { m_gamepadIndex = p_gamepadIndex; } void DisableInputProcessing() { @@ -165,12 +165,12 @@ class LegoInputManager : public MxPresenter { MxBool m_unk0x88; // 0x88 const bool* m_keyboardState; MxBool m_unk0x195; // 0x195 - SDL_JoystickID* m_joyids; - SDL_Joystick* m_joystick; - MxS32 m_joystickIndex; // 0x19c - MxBool m_useJoystick; // 0x334 - MxBool m_unk0x335; // 0x335 - MxBool m_unk0x336; // 0x336 + SDL_JoystickID* m_gamepadids; + SDL_Gamepad* m_gamepad; + MxS32 m_gamepadIndex; // 0x19c + MxBool m_useGamepad; // 0x334 + MxBool m_unk0x335; // 0x335 + MxBool m_unk0x336; // 0x336 }; // TEMPLATE: LEGO1 0x10028850 diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 4308717a..0e41c9d6 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -533,7 +533,7 @@ MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und) MxS32 povPosition; if (instance->GetInputManager() - ->GetJoystickState((MxU32*) &joystickX, (MxU32*) &joystickY, (MxU32*) &povPosition) != FAILURE) { + ->GetGamepadState((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 3e9622c2..734554e2 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -40,10 +40,10 @@ LegoInputManager::LegoInputManager() m_unk0x81 = FALSE; m_unk0x88 = FALSE; m_unk0x195 = 0; - m_joyids = NULL; - m_joystickIndex = -1; - m_joystick = NULL; - m_useJoystick = FALSE; + m_gamepadids = NULL; + m_gamepadIndex = -1; + m_gamepad = NULL; + m_useGamepad = FALSE; m_unk0x335 = FALSE; m_unk0x336 = FALSE; m_unk0x74 = 0x19; @@ -71,7 +71,7 @@ MxResult LegoInputManager::Create(HWND p_hwnd) m_eventQueue = new LegoEventQueue; } - GetJoystick(); + GetGamepad(); if (!m_keyboardNotifyList || !m_eventQueue) { Destroy(); @@ -98,7 +98,7 @@ void LegoInputManager::Destroy() delete m_controlManager; } - SDL_free(m_joyids); + SDL_free(m_gamepadids); } // FUNCTION: LEGO1 0x1005c0f0 @@ -146,29 +146,31 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags) } // FUNCTION: LEGO1 0x1005c240 -MxResult LegoInputManager::GetJoystick() +MxResult LegoInputManager::GetGamepad() { - if (m_joystick != NULL && SDL_JoystickConnected(m_joystick) == TRUE) { + if (m_gamepad != NULL && SDL_GamepadConnected(m_gamepad) == TRUE) { return SUCCESS; } - MxS32 numJoysticks = 0; - if (m_joyids == NULL) { - m_joyids = SDL_GetJoysticks(&numJoysticks); + MxS32 numGamepads = 0; + if (m_gamepadids != NULL) { + SDL_free(m_gamepadids); + m_gamepadids = NULL; } + m_gamepadids = SDL_GetGamepads(&numGamepads); - if (m_useJoystick != FALSE && numJoysticks != 0) { - MxS32 joyid = m_joystickIndex; - if (joyid >= 0) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); - if (m_joystick != NULL) { + if (m_useGamepad != FALSE && numGamepads != 0) { + MxS32 gamepadid = m_gamepadIndex; + if (gamepadid >= 0) { + m_gamepad = SDL_OpenGamepad(m_gamepadids[gamepadid]); + if (m_gamepad != NULL) { return SUCCESS; } } - for (joyid = 0; joyid < numJoysticks; joyid++) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); - if (m_joystick != NULL) { + for (gamepadid = 0; gamepadid < numGamepads; gamepadid++) { + m_gamepad = SDL_OpenGamepad(m_gamepadids[gamepadid]); + if (m_gamepad != NULL) { return SUCCESS; } } @@ -178,59 +180,25 @@ MxResult LegoInputManager::GetJoystick() } // FUNCTION: LEGO1 0x1005c320 -MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition) +MxResult LegoInputManager::GetGamepadState(MxU32* p_gamepadX, MxU32* p_gamepadY, MxU32* p_povPosition) { - if (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; + if (m_useGamepad != FALSE) { + if (GetGamepad() == -1) { + if (m_gamepad != NULL) { + // GetGamepad() failed but handle to joystick is still open, close it + SDL_CloseGamepad(m_gamepad); + m_gamepad = NULL; } return FAILURE; } - MxS16 xPos = SDL_GetJoystickAxis(m_joystick, 0); - MxS16 yPos = SDL_GetJoystickAxis(m_joystick, 1); - MxU8 hatPos = SDL_GetJoystickHat(m_joystick, 0); + MxS16 xPos = SDL_GetGamepadAxis(m_gamepad, SDL_GAMEPAD_AXIS_LEFTX); + MxS16 yPos = SDL_GetGamepadAxis(m_gamepad, SDL_GAMEPAD_AXIS_LEFTY); // normalize values acquired from joystick axes - *p_joystickX = ((xPos + 32768) * 100) / 65535; - *p_joystickY = ((yPos + 32768) * 100) / 65535; - - 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; - } + *p_gamepadX = ((xPos + 32768) * 100) / 65535; + *p_gamepadY = ((yPos + 32768) * 100) / 65535; return SUCCESS; }