feat: untested but added gamepad support

This commit is contained in:
Helloyunho 2025-07-05 16:38:05 +09:00
parent 761dc31ac0
commit 87d481d80b
No known key found for this signature in database
GPG Key ID: 6AFA210B0150BE47
5 changed files with 134 additions and 85 deletions

View File

@ -90,6 +90,11 @@ MxS32 g_targetDepth = 16;
// GLOBAL: ISLE 0x410064 // GLOBAL: ISLE 0x410064
MxS32 g_reqEnableRMDevice = FALSE; MxS32 g_reqEnableRMDevice = FALSE;
float g_lastJoystickMouseX = 0;
float g_lastJoystickMouseY = 0;
float g_lastMouseX = 0;
float g_lastMouseY = 0;
// STRING: ISLE 0x4101dc // STRING: ISLE 0x4101dc
#define WINDOW_TITLE "LEGO®" #define WINDOW_TITLE "LEGO®"
@ -113,8 +118,8 @@ IsleApp::IsleApp()
m_drawCursor = FALSE; m_drawCursor = FALSE;
m_use3dSound = TRUE; m_use3dSound = TRUE;
m_useMusic = TRUE; m_useMusic = TRUE;
m_useJoystick = TRUE; m_useGamepad = TRUE;
m_joystickIndex = 0; m_gamepadIndex = 0;
m_wideViewAngle = TRUE; m_wideViewAngle = TRUE;
m_islandQuality = 2; m_islandQuality = 2;
m_islandTexture = 1; m_islandTexture = 1;
@ -149,6 +154,7 @@ IsleApp::IsleApp()
m_maxLod = RealtimeView::GetUserMaxLOD(); m_maxLod = RealtimeView::GetUserMaxLOD();
m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20; m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20;
m_transitionType = MxTransitionManager::e_mosaic; m_transitionType = MxTransitionManager::e_mosaic;
m_mouseSensitivity = 4;
} }
// FUNCTION: ISLE 0x4011a0 // FUNCTION: ISLE 0x4011a0
@ -379,6 +385,27 @@ SDL_AppResult SDL_AppIterate(void* appstate)
if (g_mousemoved) { if (g_mousemoved) {
g_mousemoved = FALSE; 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; return SDL_APP_CONTINUE;
@ -457,6 +484,58 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
} }
break; 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: case SDL_EVENT_MOUSE_MOTION:
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
if (detectedTouchEvents) { if (detectedTouchEvents) {
@ -749,8 +828,8 @@ MxResult IsleApp::SetupWindow()
RealtimeView::SetUserMaxLOD(m_maxLod); RealtimeView::SetUserMaxLOD(m_maxLod);
if (LegoOmni::GetInstance()) { if (LegoOmni::GetInstance()) {
if (LegoOmni::GetInstance()->GetInputManager()) { if (LegoOmni::GetInstance()->GetInputManager()) {
LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick); LegoOmni::GetInstance()->GetInputManager()->SetUseGamepad(m_useGamepad);
LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex); LegoOmni::GetInstance()->GetInputManager()->SetGamepadIndex(m_gamepadIndex);
} }
if (LegoOmni::GetInstance()->GetVideoManager() && g_isle->GetDrawCursor()) { if (LegoOmni::GetInstance()->GetVideoManager() && g_isle->GetDrawCursor()) {
LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap); 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:3DSound", m_use3dSound ? "true" : "false");
iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false"); iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false");
iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false"); iniparser_set(dict, "isle:UseJoystick", m_useGamepad ? "true" : "false");
iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10)); 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:Draw Cursor", m_drawCursor ? "true" : "false");
iniparser_set(dict, "isle:Back Buffers in Video RAM", "-1"); 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_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle);
m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound); m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound);
m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic); m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic);
m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); m_useGamepad = iniparser_getboolean(dict, "isle:UseJoystick", m_useGamepad);
m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); m_gamepadIndex = iniparser_getint(dict, "isle:JoystickIndex", m_gamepadIndex);
m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor); m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor);
MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1);

View File

@ -52,6 +52,7 @@ class IsleApp {
SDL_Cursor* GetCursorNo() { return m_cursorNo; } SDL_Cursor* GetCursorNo() { return m_cursorNo; }
MxS32 GetDrawCursor() { return m_drawCursor; } MxS32 GetDrawCursor() { return m_drawCursor; }
MxS32 GetGameStarted() { return m_gameStarted; } MxS32 GetGameStarted() { return m_gameStarted; }
MxFloat GetMouseSensitivity() { return m_mouseSensitivity; }
void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; } void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; }
void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; }
@ -73,8 +74,8 @@ class IsleApp {
MxS32 m_hasLightSupport; // 0x24 MxS32 m_hasLightSupport; // 0x24
MxS32 m_use3dSound; // 0x28 MxS32 m_use3dSound; // 0x28
MxS32 m_useMusic; // 0x2c MxS32 m_useMusic; // 0x2c
MxS32 m_useJoystick; // 0x30 MxS32 m_useGamepad; // 0x30
MxS32 m_joystickIndex; // 0x34 MxS32 m_gamepadIndex; // 0x34
MxS32 m_wideViewAngle; // 0x38 MxS32 m_wideViewAngle; // 0x38
MxS32 m_islandQuality; // 0x3c MxS32 m_islandQuality; // 0x3c
MxS32 m_islandTexture; // 0x40 MxS32 m_islandTexture; // 0x40
@ -93,6 +94,7 @@ class IsleApp {
const CursorBitmap* m_cursorNoBitmap; const CursorBitmap* m_cursorNoBitmap;
const CursorBitmap* m_cursorCurrentBitmap; const CursorBitmap* m_cursorCurrentBitmap;
char* m_mediaPath; char* m_mediaPath;
MxFloat m_mouseSensitivity;
char* m_iniPath; char* m_iniPath;
MxFloat m_maxLod; MxFloat m_maxLod;

View File

@ -108,8 +108,8 @@ class LegoInputManager : public MxPresenter {
MxResult Create(HWND p_hwnd); MxResult Create(HWND p_hwnd);
void Destroy() override; void Destroy() override;
MxResult GetJoystick(); MxResult GetGamepad();
MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition); MxResult GetGamepadState(MxU32* p_gamepadX, MxU32* p_gamepadY, MxU32* p_povPosition);
void StartAutoDragTimer(); void StartAutoDragTimer();
void StopAutoDragTimer(); void StopAutoDragTimer();
void EnableInputProcessing(); void EnableInputProcessing();
@ -121,8 +121,8 @@ class LegoInputManager : public MxPresenter {
void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; }
void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; } void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; }
void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; }
void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; } void SetUseGamepad(MxBool p_useGamepad) { m_useGamepad = p_useGamepad; }
void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; } void SetGamepadIndex(MxS32 p_gamepadIndex) { m_gamepadIndex = p_gamepadIndex; }
void DisableInputProcessing() void DisableInputProcessing()
{ {
@ -165,12 +165,12 @@ class LegoInputManager : public MxPresenter {
MxBool m_unk0x88; // 0x88 MxBool m_unk0x88; // 0x88
const bool* m_keyboardState; const bool* m_keyboardState;
MxBool m_unk0x195; // 0x195 MxBool m_unk0x195; // 0x195
SDL_JoystickID* m_joyids; SDL_JoystickID* m_gamepadids;
SDL_Joystick* m_joystick; SDL_Gamepad* m_gamepad;
MxS32 m_joystickIndex; // 0x19c MxS32 m_gamepadIndex; // 0x19c
MxBool m_useJoystick; // 0x334 MxBool m_useGamepad; // 0x334
MxBool m_unk0x335; // 0x335 MxBool m_unk0x335; // 0x335
MxBool m_unk0x336; // 0x336 MxBool m_unk0x336; // 0x336
}; };
// TEMPLATE: LEGO1 0x10028850 // TEMPLATE: LEGO1 0x10028850

View File

@ -533,7 +533,7 @@ MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und)
MxS32 povPosition; MxS32 povPosition;
if (instance->GetInputManager() 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 yVal = (joystickY * m_vMax) / 100;
MxU32 xVal = (joystickX * m_hMax) / 100; MxU32 xVal = (joystickX * m_hMax) / 100;

View File

@ -40,10 +40,10 @@ LegoInputManager::LegoInputManager()
m_unk0x81 = FALSE; m_unk0x81 = FALSE;
m_unk0x88 = FALSE; m_unk0x88 = FALSE;
m_unk0x195 = 0; m_unk0x195 = 0;
m_joyids = NULL; m_gamepadids = NULL;
m_joystickIndex = -1; m_gamepadIndex = -1;
m_joystick = NULL; m_gamepad = NULL;
m_useJoystick = FALSE; m_useGamepad = FALSE;
m_unk0x335 = FALSE; m_unk0x335 = FALSE;
m_unk0x336 = FALSE; m_unk0x336 = FALSE;
m_unk0x74 = 0x19; m_unk0x74 = 0x19;
@ -71,7 +71,7 @@ MxResult LegoInputManager::Create(HWND p_hwnd)
m_eventQueue = new LegoEventQueue; m_eventQueue = new LegoEventQueue;
} }
GetJoystick(); GetGamepad();
if (!m_keyboardNotifyList || !m_eventQueue) { if (!m_keyboardNotifyList || !m_eventQueue) {
Destroy(); Destroy();
@ -98,7 +98,7 @@ void LegoInputManager::Destroy()
delete m_controlManager; delete m_controlManager;
} }
SDL_free(m_joyids); SDL_free(m_gamepadids);
} }
// FUNCTION: LEGO1 0x1005c0f0 // FUNCTION: LEGO1 0x1005c0f0
@ -146,29 +146,31 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags)
} }
// FUNCTION: LEGO1 0x1005c240 // 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; return SUCCESS;
} }
MxS32 numJoysticks = 0; MxS32 numGamepads = 0;
if (m_joyids == NULL) { if (m_gamepadids != NULL) {
m_joyids = SDL_GetJoysticks(&numJoysticks); SDL_free(m_gamepadids);
m_gamepadids = NULL;
} }
m_gamepadids = SDL_GetGamepads(&numGamepads);
if (m_useJoystick != FALSE && numJoysticks != 0) { if (m_useGamepad != FALSE && numGamepads != 0) {
MxS32 joyid = m_joystickIndex; MxS32 gamepadid = m_gamepadIndex;
if (joyid >= 0) { if (gamepadid >= 0) {
m_joystick = SDL_OpenJoystick(m_joyids[joyid]); m_gamepad = SDL_OpenGamepad(m_gamepadids[gamepadid]);
if (m_joystick != NULL) { if (m_gamepad != NULL) {
return SUCCESS; return SUCCESS;
} }
} }
for (joyid = 0; joyid < numJoysticks; joyid++) { for (gamepadid = 0; gamepadid < numGamepads; gamepadid++) {
m_joystick = SDL_OpenJoystick(m_joyids[joyid]); m_gamepad = SDL_OpenGamepad(m_gamepadids[gamepadid]);
if (m_joystick != NULL) { if (m_gamepad != NULL) {
return SUCCESS; return SUCCESS;
} }
} }
@ -178,59 +180,25 @@ MxResult LegoInputManager::GetJoystick()
} }
// FUNCTION: LEGO1 0x1005c320 // 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 (m_useGamepad != FALSE) {
if (GetJoystick() == -1) { if (GetGamepad() == -1) {
if (m_joystick != NULL) { if (m_gamepad != NULL) {
// GetJoystick() failed but handle to joystick is still open, close it // GetGamepad() failed but handle to joystick is still open, close it
SDL_CloseJoystick(m_joystick); SDL_CloseGamepad(m_gamepad);
m_joystick = NULL; m_gamepad = NULL;
} }
return FAILURE; return FAILURE;
} }
MxS16 xPos = SDL_GetJoystickAxis(m_joystick, 0); MxS16 xPos = SDL_GetGamepadAxis(m_gamepad, SDL_GAMEPAD_AXIS_LEFTX);
MxS16 yPos = SDL_GetJoystickAxis(m_joystick, 1); MxS16 yPos = SDL_GetGamepadAxis(m_gamepad, SDL_GAMEPAD_AXIS_LEFTY);
MxU8 hatPos = SDL_GetJoystickHat(m_joystick, 0);
// normalize values acquired from joystick axes // normalize values acquired from joystick axes
*p_joystickX = ((xPos + 32768) * 100) / 65535; *p_gamepadX = ((xPos + 32768) * 100) / 65535;
*p_joystickY = ((yPos + 32768) * 100) / 65535; *p_gamepadY = ((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; return SUCCESS;
} }