diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 6cb0375c..cd0a6849 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -90,6 +90,11 @@ MxS32 g_targetDepth = 16; // GLOBAL: ISLE 0x410064 MxS32 g_reqEnableRMDevice = FALSE; +MxFloat g_lastJoystickMouseX = 0; +MxFloat g_lastJoystickMouseY = 0; +MxFloat g_lastMouseX = 0; +MxFloat g_lastMouseY = 0; + // STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO®" @@ -149,6 +154,7 @@ IsleApp::IsleApp() m_maxLod = RealtimeView::GetUserMaxLOD(); m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20; m_transitionType = MxTransitionManager::e_mosaic; + m_cursorSensitivity = 4; } // FUNCTION: ISLE 0x4011a0 @@ -270,7 +276,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)) { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) { char buffer[256]; SDL_snprintf( buffer, @@ -379,6 +385,8 @@ SDL_AppResult SDL_AppIterate(void* appstate) if (g_mousemoved) { g_mousemoved = FALSE; } + + g_isle->MoveVirtualMouseViaJoystick(); } return SDL_APP_CONTINUE; @@ -457,6 +465,63 @@ 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: { + MxS16 axisValue = 0; + if (event->gaxis.value < -8000 || event->gaxis.value > 8000) { + // Ignore small axis values + axisValue = event->gaxis.value; + } + if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX) { + g_lastJoystickMouseX = ((MxFloat) axisValue) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetCursorSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTY) { + g_lastJoystickMouseY = ((MxFloat) axisValue) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetCursorSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { + if (axisValue != 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) { @@ -842,6 +907,8 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false"); iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10)); iniparser_set(dict, "isle:Draw Cursor", m_drawCursor ? "true" : "false"); + SDL_snprintf(buf, sizeof(buf), "%f", m_cursorSensitivity); + iniparser_set(dict, "isle:Cursor Sensitivity", buf); iniparser_set(dict, "isle:Back Buffers in Video RAM", "-1"); @@ -896,6 +963,7 @@ bool IsleApp::LoadConfig() m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor); + m_cursorSensitivity = iniparser_getdouble(dict, "isle:Cursor Sensitivity", m_cursorSensitivity); MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); if (backBuffersInVRAM != -1) { @@ -1207,3 +1275,27 @@ IDirect3DRMMiniwinDevice* GetD3DRMMiniwinDevice() } return d3drmMiniwinDev; } + +void IsleApp::MoveVirtualMouseViaJoystick() +{ + 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)); + } + } +} diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4064dc25..70445d05 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 GetCursorSensitivity() { return m_cursorSensitivity; } void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; } void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } @@ -59,6 +60,7 @@ class IsleApp { MxResult ParseArguments(int argc, char** argv); MxResult VerifyFilesystem(); void DetectGameVersion(); + void MoveVirtualMouseViaJoystick(); private: char* m_hdPath; // 0x00 @@ -93,6 +95,7 @@ class IsleApp { const CursorBitmap* m_cursorNoBitmap; const CursorBitmap* m_cursorCurrentBitmap; char* m_mediaPath; + MxFloat m_cursorSensitivity; char* m_iniPath; MxFloat m_maxLod; diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 7ccad404..ece1cbd1 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -166,7 +166,7 @@ class LegoInputManager : public MxPresenter { const bool* m_keyboardState; MxBool m_unk0x195; // 0x195 SDL_JoystickID* m_joyids; - SDL_Joystick* m_joystick; + SDL_Gamepad* m_joystick; MxS32 m_joystickIndex; // 0x19c MxBool m_useJoystick; // 0x334 MxBool m_unk0x335; // 0x335 diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 3e9622c2..eca8078b 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -148,26 +148,28 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags) // FUNCTION: LEGO1 0x1005c240 MxResult LegoInputManager::GetJoystick() { - if (m_joystick != NULL && SDL_JoystickConnected(m_joystick) == TRUE) { + if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) { return SUCCESS; } MxS32 numJoysticks = 0; - if (m_joyids == NULL) { - m_joyids = SDL_GetJoysticks(&numJoysticks); + if (m_joyids != NULL) { + SDL_free(m_joyids); + m_joyids = NULL; } + m_joyids = SDL_GetGamepads(&numJoysticks); if (m_useJoystick != FALSE && numJoysticks != 0) { MxS32 joyid = m_joystickIndex; if (joyid >= 0) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + m_joystick = SDL_OpenGamepad(m_joyids[joyid]); if (m_joystick != NULL) { return SUCCESS; } } for (joyid = 0; joyid < numJoysticks; joyid++) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + m_joystick = SDL_OpenGamepad(m_joyids[joyid]); if (m_joystick != NULL) { return SUCCESS; } @@ -184,54 +186,28 @@ MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystic if (GetJoystick() == -1) { if (m_joystick != NULL) { // GetJoystick() failed but handle to joystick is still open, close it - SDL_CloseJoystick(m_joystick); + SDL_CloseGamepad(m_joystick); m_joystick = 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_joystick, SDL_GAMEPAD_AXIS_LEFTX); + MxS16 yPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTY); + if (xPos > -8000 && xPos < 8000) { + // Ignore small axis values + xPos = 0; + } + if (yPos > -8000 && yPos < 8000) { + // Ignore small axis values + yPos = 0; + } // 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; - } - return SUCCESS; }