diff --git a/config/ghidra_ns_to_obj.csv b/config/ghidra_ns_to_obj.csv index ba3f383d..6ae15f71 100644 --- a/config/ghidra_ns_to_obj.csv +++ b/config/ghidra_ns_to_obj.csv @@ -3,6 +3,7 @@ AsciiManager,th06::AsciiManager,th06::StageMenu BombData,th06::BombData BulletManager,th06::BulletManager Chain,th06::Chain,th06::ChainElem +Controller,th06::Controller EclManager,th06::EclManager EffectManager,th06::EffectManager Ending,th06::Ending @@ -29,7 +30,7 @@ Rng,th06::Rng ScreenEffect,th06::ScreenEffect SoundPlayer,th06::SoundPlayer Stage,th06::Stage,th06::AnmManager::ExecuteAnmIdx -Supervisor,th06::Supervisor,th06::Controller +Supervisor,th06::Supervisor TextHelper,th06::TextHelper utils,th06::utils ZunTimer,th06::ZunTimer diff --git a/objdiff.json b/objdiff.json index efc28c99..51f22bd4 100644 --- a/objdiff.json +++ b/objdiff.json @@ -58,6 +58,14 @@ "reverse_fn_order": false }, + { + "name": "Controller", + + "target_path": "build/objdiff/orig/Controller.obj", + "base_path": "build/objdiff/reimpl/Controller.obj", + + "reverse_fn_order": false + }, { "name": "EclManager", diff --git a/scripts/configure.py b/scripts/configure.py index 4fcd1a96..3269cc8e 100644 --- a/scripts/configure.py +++ b/scripts/configure.py @@ -104,7 +104,7 @@ def configure(build_type): "GuiImpl", "GameManager", "Chain", - # Controller + "Controller", "FileSystem", "GameErrorContext", "Rng", diff --git a/src/AsciiManager.cpp b/src/AsciiManager.cpp index 6c62e398..602cf2eb 100644 --- a/src/AsciiManager.cpp +++ b/src/AsciiManager.cpp @@ -3,6 +3,7 @@ #include "AnmManager.hpp" #include "ChainPriorities.hpp" +#include "Controller.hpp" #include "GameManager.hpp" #include "Gui.hpp" #include "Supervisor.hpp" diff --git a/src/Controller.cpp b/src/Controller.cpp new file mode 100644 index 00000000..d5a0b9c6 --- /dev/null +++ b/src/Controller.cpp @@ -0,0 +1,401 @@ +#include "Controller.hpp" + +#include "GameErrorContext.hpp" +#include "Supervisor.hpp" +#include "i18n.hpp" +#include "utils.hpp" + +namespace th06 +{ +DIFFABLE_STATIC(JOYCAPSA, g_JoystickCaps) +DIFFABLE_STATIC(u16, g_FocusButtonConflictState) + +u16 Controller::GetJoystickCaps(void) +{ + JOYINFOEX pji; + + pji.dwSize = sizeof(JOYINFOEX); + pji.dwFlags = JOY_RETURNALL; + + if (joyGetPosEx(0, &pji) != MMSYSERR_NOERROR) + { + GameErrorContext::Log(&g_GameErrorContext, TH_ERR_NO_PAD_FOUND); + return 1; + } + + joyGetDevCapsA(0, &g_JoystickCaps, sizeof(g_JoystickCaps)); + return 0; +} + +#define JOYSTICK_MIDPOINT(min, max) ((min + max) / 2) +#define JOYSTICK_BUTTON_PRESSED(button, x, y) (x > y ? button : 0) +#define JOYSTICK_BUTTON_PRESSED_INVERT(button, x, y) (x < y ? button : 0) +#define KEYBOARD_KEY_PRESSED(button, x) keyboardState[x] & 0x80 ? button : 0 + +u16 Controller::GetControllerInput(u16 buttons) +{ + // NOTE: Those names are like this to get perfect stack frame matching + // TODO: Give meaningfull names that still match. + JOYINFOEX aa; + u32 ab; + u32 ac; + DIJOYSTATE2 a0; + u32 a2; + HRESULT aaa; + + if (g_Supervisor.controller == NULL) + { + memset(&aa, 0, sizeof(aa)); + aa.dwSize = sizeof(JOYINFOEX); + aa.dwFlags = JOY_RETURNALL; + + if (joyGetPosEx(0, &aa) != MMSYSERR_NOERROR) + { + return buttons; + } + + ac = SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.shootButton, TH_BUTTON_SHOOT, + aa.dwButtons); + + if (g_ControllerMapping.shootButton != g_ControllerMapping.focusButton) + { + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.focusButton, TH_BUTTON_FOCUS, + aa.dwButtons); + } + else + { + if (ac != 0) + { + if (g_FocusButtonConflictState < 16) + { + g_FocusButtonConflictState++; + } + + if (g_FocusButtonConflictState >= 8) + { + buttons |= TH_BUTTON_FOCUS; + } + } + else + { + if (g_FocusButtonConflictState > 8) + { + g_FocusButtonConflictState -= 8; + } + else + { + g_FocusButtonConflictState = 0; + } + } + } + + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.bombButton, TH_BUTTON_BOMB, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.menuButton, TH_BUTTON_MENU, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.upButton, TH_BUTTON_UP, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.downButton, TH_BUTTON_DOWN, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.leftButton, TH_BUTTON_LEFT, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.rightButton, TH_BUTTON_RIGHT, + aa.dwButtons); + SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.skipButton, TH_BUTTON_SKIP, + aa.dwButtons); + + ab = ((g_JoystickCaps.wXmax - g_JoystickCaps.wXmin) / 2 / 2); + + buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_RIGHT, aa.dwXpos, + JOYSTICK_MIDPOINT(g_JoystickCaps.wXmin, g_JoystickCaps.wXmax) + ab); + buttons |= JOYSTICK_BUTTON_PRESSED( + TH_BUTTON_LEFT, JOYSTICK_MIDPOINT(g_JoystickCaps.wXmin, g_JoystickCaps.wXmax) - ab, aa.dwXpos); + + ab = ((g_JoystickCaps.wYmax - g_JoystickCaps.wYmin) / 2 / 2); + buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_DOWN, aa.dwYpos, + JOYSTICK_MIDPOINT(g_JoystickCaps.wYmin, g_JoystickCaps.wYmax) + ab); + buttons |= JOYSTICK_BUTTON_PRESSED( + TH_BUTTON_UP, JOYSTICK_MIDPOINT(g_JoystickCaps.wYmin, g_JoystickCaps.wYmax) - ab, aa.dwYpos); + + return buttons; + } + else + { + // FIXME: Next if not matching. + aaa = g_Supervisor.controller->Poll(); + if (FAILED(aaa)) + { + i32 retryCount = 0; + + utils::DebugPrint2("error : DIERR_INPUTLOST\n"); + aaa = g_Supervisor.controller->Acquire(); + + while (aaa == DIERR_INPUTLOST) + { + aaa = g_Supervisor.controller->Acquire(); + utils::DebugPrint2("error : DIERR_INPUTLOST %d\n", retryCount); + + retryCount++; + + if (retryCount >= 400) + { + return buttons; + } + } + + return buttons; + } + else + { + memset(&a0, 0, sizeof(a0)); + + aaa = g_Supervisor.controller->GetDeviceState(sizeof(a0), &a0); + + if (FAILED(aaa)) + { + return buttons; + } + + a2 = SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.shootButton, + TH_BUTTON_SHOOT, a0.rgbButtons); + + if (g_Supervisor.cfg.controllerMapping.shootButton != g_Supervisor.cfg.controllerMapping.focusButton) + { + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.focusButton, + TH_BUTTON_FOCUS, a0.rgbButtons); + } + else + { + if (a2 != 0) + { + if (g_FocusButtonConflictState < 16) + { + g_FocusButtonConflictState++; + } + + if (g_FocusButtonConflictState >= 8) + { + buttons |= TH_BUTTON_FOCUS; + } + } + else + { + if (g_FocusButtonConflictState > 8) + { + g_FocusButtonConflictState -= 8; + } + else + { + g_FocusButtonConflictState = 0; + } + } + } + + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.bombButton, TH_BUTTON_BOMB, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.menuButton, TH_BUTTON_MENU, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.upButton, TH_BUTTON_UP, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.downButton, TH_BUTTON_DOWN, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.leftButton, TH_BUTTON_LEFT, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.rightButton, TH_BUTTON_RIGHT, + a0.rgbButtons); + SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.skipButton, TH_BUTTON_SKIP, + a0.rgbButtons); + + buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_RIGHT, a0.lX, g_Supervisor.cfg.padXAxis); + buttons |= JOYSTICK_BUTTON_PRESSED_INVERT(TH_BUTTON_LEFT, a0.lX, -g_Supervisor.cfg.padXAxis); + buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_DOWN, a0.lY, g_Supervisor.cfg.padYAxis); + buttons |= JOYSTICK_BUTTON_PRESSED_INVERT(TH_BUTTON_UP, a0.lY, -g_Supervisor.cfg.padYAxis); + } + } + + return buttons; +} + +u32 Controller::SetButtonFromDirectInputJoystate(u16 *outButtons, i16 controllerButtonToTest, + enum TouhouButton touhouButton, u8 *inputButtons) +{ + if (controllerButtonToTest < 0) + { + return 0; + } + + *outButtons |= (inputButtons[controllerButtonToTest] & 0x80 ? touhouButton & 0xFFFF : 0); + + return inputButtons[controllerButtonToTest] & 0x80 ? touhouButton & 0xFFFF : 0; +} + +u32 Controller::SetButtonFromControllerInputs(u16 *outButtons, i16 controllerButtonToTest, + enum TouhouButton touhouButton, u32 inputButtons) +{ + DWORD mask; + + if (controllerButtonToTest < 0) + { + return 0; + } + + mask = 1 << controllerButtonToTest; + + *outButtons |= (inputButtons & mask ? touhouButton & 0xFFFF : 0); + + return inputButtons & mask ? touhouButton & 0xFFFF : 0; +} + +DIFFABLE_STATIC_ARRAY(u8, (32 * 4), g_ControllerData) + +#pragma optimize("", on) +#pragma var_order(joyinfoex, joyButtonBit, joyButtonIndex, dires, dijoystate2, diRetryCount) +// This is for rebinding keys +u8 *th06::Controller::GetControllerState() +{ + JOYINFOEX joyinfoex; + u32 joyButtonBit; + u32 joyButtonIndex; + + i32 dires; + DIJOYSTATE2 dijoystate2; + i32 diRetryCount; + + memset(&g_ControllerData, 0, sizeof(g_ControllerData)); + if (g_Supervisor.controller == NULL) + { + memset(&joyinfoex, 0, sizeof(JOYINFOEX)); + joyinfoex.dwSize = sizeof(JOYINFOEX); + joyinfoex.dwFlags = JOY_RETURNALL; + if (joyGetPosEx(0, &joyinfoex) != JOYERR_NOERROR) + { + return g_ControllerData; + } + for (joyButtonBit = joyinfoex.dwButtons, joyButtonIndex = 0; joyButtonIndex < 32; + joyButtonIndex += 1, joyButtonBit >>= 1) + { + if ((joyButtonBit & 1) != 0) + { + g_ControllerData[joyButtonIndex] = 0x80; + } + } + return g_ControllerData; + } + else + { + dires = g_Supervisor.controller->Poll(); + if (FAILED(dires)) + { + diRetryCount = 0; + utils::DebugPrint2("error : DIERR_INPUTLOST\n"); + dires = g_Supervisor.controller->Acquire(); + while (dires == DIERR_INPUTLOST) + { + dires = g_Supervisor.controller->Acquire(); + utils::DebugPrint2("error : DIERR_INPUTLOST %d\n", diRetryCount); + diRetryCount++; + if (diRetryCount >= 400) + { + return g_ControllerData; + } + } + return g_ControllerData; + } + /* dires = */ g_Supervisor.controller->GetDeviceState(sizeof(DIJOYSTATE2), &dijoystate2); + // TODO: seems ZUN forgot "dires =" above + if (FAILED(dires)) + { + return g_ControllerData; + } + memcpy(&g_ControllerData, dijoystate2.rgbButtons, sizeof(dijoystate2.rgbButtons)); + return g_ControllerData; + } +} +#pragma optimize("", on) + +u16 Controller::GetInput(void) +{ + u8 keyboardState[256]; + u16 buttons; + + buttons = 0; + + if (g_Supervisor.keyboard == NULL) + { + GetKeyboardState(keyboardState); + + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, VK_UP); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, VK_DOWN); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, VK_LEFT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, VK_RIGHT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, VK_NUMPAD8); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, VK_NUMPAD2); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, VK_NUMPAD4); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, VK_NUMPAD6); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_LEFT, VK_NUMPAD7); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_RIGHT, VK_NUMPAD9); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_LEFT, VK_NUMPAD1); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_RIGHT, VK_NUMPAD3); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_HOME, VK_HOME); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SHOOT, 'Z'); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_BOMB, 'X'); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, VK_SHIFT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_MENU, VK_ESCAPE); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, VK_CONTROL); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_Q, 'Q'); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_S, 'S'); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_ENTER, VK_RETURN); + } + else + { + HRESULT res = g_Supervisor.keyboard->GetDeviceState(sizeof(keyboardState), keyboardState); + + buttons = 0; + + if (res == DIERR_INPUTLOST) + { + g_Supervisor.keyboard->Acquire(); + + return Controller::GetControllerInput(buttons); + } + + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, DIK_UP); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, DIK_DOWN); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, DIK_LEFT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, DIK_RIGHT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, DIK_NUMPAD8); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, DIK_NUMPAD2); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, DIK_NUMPAD4); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, DIK_NUMPAD6); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_LEFT, DIK_NUMPAD7); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_RIGHT, DIK_NUMPAD9); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_LEFT, DIK_NUMPAD1); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_RIGHT, DIK_NUMPAD3); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_HOME, DIK_HOME); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SHOOT, DIK_Z); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_BOMB, DIK_X); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, DIK_LSHIFT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, DIK_RSHIFT); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_MENU, DIK_ESCAPE); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, DIK_LCONTROL); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, DIK_RCONTROL); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_Q, DIK_Q); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_S, DIK_S); + buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_ENTER, DIK_RETURN); + } + + return Controller::GetControllerInput(buttons); +} + +void Controller::ResetKeyboard(void) +{ + u8 key_states[256]; + + GetKeyboardState(key_states); + for (i32 idx = 0; idx < 256; idx++) + { + *(key_states + idx) &= 0x7f; + } + SetKeyboardState(key_states); +} +}; // namespace th06 diff --git a/src/Controller.hpp b/src/Controller.hpp new file mode 100644 index 00000000..0b0b89e5 --- /dev/null +++ b/src/Controller.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "inttypes.hpp" + +namespace th06 +{ +enum TouhouButton +{ + TH_BUTTON_SHOOT = 1 << 0, + TH_BUTTON_BOMB = 1 << 1, + TH_BUTTON_FOCUS = 1 << 2, + TH_BUTTON_MENU = 1 << 3, + TH_BUTTON_UP = 1 << 4, + TH_BUTTON_DOWN = 1 << 5, + TH_BUTTON_LEFT = 1 << 6, + TH_BUTTON_RIGHT = 1 << 7, + TH_BUTTON_SKIP = 1 << 8, + TH_BUTTON_Q = 1 << 9, + TH_BUTTON_S = 1 << 10, + TH_BUTTON_HOME = 1 << 11, + TH_BUTTON_ENTER = 1 << 12, + + TH_BUTTON_UP_LEFT = TH_BUTTON_UP | TH_BUTTON_LEFT, + TH_BUTTON_UP_RIGHT = TH_BUTTON_UP | TH_BUTTON_RIGHT, + TH_BUTTON_DOWN_LEFT = TH_BUTTON_DOWN | TH_BUTTON_LEFT, + TH_BUTTON_DOWN_RIGHT = TH_BUTTON_DOWN | TH_BUTTON_RIGHT, + TH_BUTTON_DIRECTION = TH_BUTTON_DOWN | TH_BUTTON_RIGHT | TH_BUTTON_UP | TH_BUTTON_LEFT, + + TH_BUTTON_SELECTMENU = TH_BUTTON_ENTER | TH_BUTTON_SHOOT, + TH_BUTTON_RETURNMENU = TH_BUTTON_MENU | TH_BUTTON_BOMB, + TH_BUTTON_WRONG_CHEATCODE = + TH_BUTTON_SHOOT | TH_BUTTON_BOMB | TH_BUTTON_MENU | TH_BUTTON_Q | TH_BUTTON_S | TH_BUTTON_ENTER, + TH_BUTTON_ANY = 0xFFFF, +}; + +namespace Controller +{ +u16 GetJoystickCaps(void); +u32 SetButtonFromControllerInputs(u16 *outButtons, i16 controllerButtonToTest, enum TouhouButton touhouButton, + u32 inputButtons); + +unsigned int SetButtonFromDirectInputJoystate(u16 *outButtons, i16 controllerButtonToTest, + enum TouhouButton touhouButton, u8 *inputButtons); + +u16 GetControllerInput(u16 buttons); +u8 *GetControllerState(); +u16 GetInput(void); +void ResetKeyboard(void); +}; // namespace Controller +}; // namespace th06 diff --git a/src/GuiImpl.cpp b/src/GuiImpl.cpp index f9d453a5..4afca904 100644 --- a/src/GuiImpl.cpp +++ b/src/GuiImpl.cpp @@ -1,6 +1,7 @@ #include "GuiImpl.hpp" #include "AnmManager.hpp" +#include "Controller.hpp" #include "Stage.hpp" #include "ZunColor.hpp" #include "utils.hpp" diff --git a/src/MusicRoom.cpp b/src/MusicRoom.cpp index 48fdf0d6..9c92c7f2 100644 --- a/src/MusicRoom.cpp +++ b/src/MusicRoom.cpp @@ -3,6 +3,7 @@ #include "AsciiManager.hpp" #include "Chain.hpp" #include "ChainPriorities.hpp" +#include "Controller.hpp" #include "FileSystem.hpp" #include "utils.hpp" #include diff --git a/src/ReplayManager.cpp b/src/ReplayManager.cpp index aa60e53a..3ef78400 100644 --- a/src/ReplayManager.cpp +++ b/src/ReplayManager.cpp @@ -2,6 +2,7 @@ #include #include +#include "Controller.hpp" #include "FileSystem.hpp" #include "GameManager.hpp" #include "Gui.hpp" diff --git a/src/ResultScreen.cpp b/src/ResultScreen.cpp index b1c4d7b6..d3232131 100644 --- a/src/ResultScreen.cpp +++ b/src/ResultScreen.cpp @@ -4,6 +4,7 @@ #include "BulletManager.hpp" #include "Chain.hpp" #include "ChainPriorities.hpp" +#include "Controller.hpp" #include "FileSystem.hpp" #include "GameManager.hpp" #include "Player.hpp" @@ -2245,4 +2246,4 @@ ZunResult ResultScreen::DeletedCallback(ResultScreen *resultScreen) } #pragma optimize("", on) -}; // namespace th06 \ No newline at end of file +}; // namespace th06 diff --git a/src/Supervisor.cpp b/src/Supervisor.cpp index 5acd6973..df72f176 100644 --- a/src/Supervisor.cpp +++ b/src/Supervisor.cpp @@ -26,13 +26,11 @@ namespace th06 { DIFFABLE_STATIC(Supervisor, g_Supervisor) DIFFABLE_STATIC(ControllerMapping, g_ControllerMapping) -DIFFABLE_STATIC(JOYCAPSA, g_JoystickCaps) DIFFABLE_STATIC(IDirect3DSurface8 *, g_TextBufferSurface) DIFFABLE_STATIC(u16, g_LastFrameInput); DIFFABLE_STATIC(u16, g_CurFrameInput); DIFFABLE_STATIC(u16, g_IsEigthFrameOfHeldInput); DIFFABLE_STATIC(u16, g_NumOfFramesInputsWereHeld); -DIFFABLE_STATIC(u16, g_FocusButtonConflictState) #pragma optimize("s", on) #pragma var_order(data, wavFile, wavFile2) @@ -735,316 +733,6 @@ void Supervisor::TickTimer(i32 *frames, f32 *subframes) } #pragma optimize("", on) -u16 Controller::GetJoystickCaps(void) -{ - JOYINFOEX pji; - - pji.dwSize = sizeof(JOYINFOEX); - pji.dwFlags = JOY_RETURNALL; - - if (joyGetPosEx(0, &pji) != MMSYSERR_NOERROR) - { - GameErrorContext::Log(&g_GameErrorContext, TH_ERR_NO_PAD_FOUND); - return 1; - } - - joyGetDevCapsA(0, &g_JoystickCaps, sizeof(g_JoystickCaps)); - return 0; -} - -u32 Controller::SetButtonFromControllerInputs(u16 *outButtons, i16 controllerButtonToTest, - enum TouhouButton touhouButton, u32 inputButtons) -{ - DWORD mask; - - if (controllerButtonToTest < 0) - { - return 0; - } - - mask = 1 << controllerButtonToTest; - - *outButtons |= (inputButtons & mask ? touhouButton & 0xFFFF : 0); - - return inputButtons & mask ? touhouButton & 0xFFFF : 0; -} - -#define JOYSTICK_MIDPOINT(min, max) ((min + max) / 2) -#define JOYSTICK_BUTTON_PRESSED(button, x, y) (x > y ? button : 0) -#define JOYSTICK_BUTTON_PRESSED_INVERT(button, x, y) (x < y ? button : 0) -#define KEYBOARD_KEY_PRESSED(button, x) keyboardState[x] & 0x80 ? button : 0 - -u32 Controller::SetButtonFromDirectInputJoystate(u16 *outButtons, i16 controllerButtonToTest, - enum TouhouButton touhouButton, u8 *inputButtons) -{ - if (controllerButtonToTest < 0) - { - return 0; - } - - *outButtons |= (inputButtons[controllerButtonToTest] & 0x80 ? touhouButton & 0xFFFF : 0); - - return inputButtons[controllerButtonToTest] & 0x80 ? touhouButton & 0xFFFF : 0; -} - -u16 Controller::GetControllerInput(u16 buttons) -{ - // NOTE: Those names are like this to get perfect stack frame matching - // TODO: Give meaningfull names that still match. - JOYINFOEX aa; - u32 ab; - u32 ac; - DIJOYSTATE2 a0; - u32 a2; - HRESULT aaa; - - if (g_Supervisor.controller == NULL) - { - memset(&aa, 0, sizeof(aa)); - aa.dwSize = sizeof(JOYINFOEX); - aa.dwFlags = JOY_RETURNALL; - - if (joyGetPosEx(0, &aa) != MMSYSERR_NOERROR) - { - return buttons; - } - - ac = SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.shootButton, TH_BUTTON_SHOOT, - aa.dwButtons); - - if (g_ControllerMapping.shootButton != g_ControllerMapping.focusButton) - { - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.focusButton, TH_BUTTON_FOCUS, - aa.dwButtons); - } - else - { - if (ac != 0) - { - if (g_FocusButtonConflictState < 16) - { - g_FocusButtonConflictState++; - } - - if (g_FocusButtonConflictState >= 8) - { - buttons |= TH_BUTTON_FOCUS; - } - } - else - { - if (g_FocusButtonConflictState > 8) - { - g_FocusButtonConflictState -= 8; - } - else - { - g_FocusButtonConflictState = 0; - } - } - } - - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.bombButton, TH_BUTTON_BOMB, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.menuButton, TH_BUTTON_MENU, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.upButton, TH_BUTTON_UP, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.downButton, TH_BUTTON_DOWN, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.leftButton, TH_BUTTON_LEFT, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.rightButton, TH_BUTTON_RIGHT, - aa.dwButtons); - SetButtonFromControllerInputs(&buttons, g_Supervisor.cfg.controllerMapping.skipButton, TH_BUTTON_SKIP, - aa.dwButtons); - - ab = ((g_JoystickCaps.wXmax - g_JoystickCaps.wXmin) / 2 / 2); - - buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_RIGHT, aa.dwXpos, - JOYSTICK_MIDPOINT(g_JoystickCaps.wXmin, g_JoystickCaps.wXmax) + ab); - buttons |= JOYSTICK_BUTTON_PRESSED( - TH_BUTTON_LEFT, JOYSTICK_MIDPOINT(g_JoystickCaps.wXmin, g_JoystickCaps.wXmax) - ab, aa.dwXpos); - - ab = ((g_JoystickCaps.wYmax - g_JoystickCaps.wYmin) / 2 / 2); - buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_DOWN, aa.dwYpos, - JOYSTICK_MIDPOINT(g_JoystickCaps.wYmin, g_JoystickCaps.wYmax) + ab); - buttons |= JOYSTICK_BUTTON_PRESSED( - TH_BUTTON_UP, JOYSTICK_MIDPOINT(g_JoystickCaps.wYmin, g_JoystickCaps.wYmax) - ab, aa.dwYpos); - - return buttons; - } - else - { - // FIXME: Next if not matching. - aaa = g_Supervisor.controller->Poll(); - if (FAILED(aaa)) - { - i32 retryCount = 0; - - utils::DebugPrint2("error : DIERR_INPUTLOST\n"); - aaa = g_Supervisor.controller->Acquire(); - - while (aaa == DIERR_INPUTLOST) - { - aaa = g_Supervisor.controller->Acquire(); - utils::DebugPrint2("error : DIERR_INPUTLOST %d\n", retryCount); - - retryCount++; - - if (retryCount >= 400) - { - return buttons; - } - } - - return buttons; - } - else - { - memset(&a0, 0, sizeof(a0)); - - aaa = g_Supervisor.controller->GetDeviceState(sizeof(a0), &a0); - - if (FAILED(aaa)) - { - return buttons; - } - - a2 = SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.shootButton, - TH_BUTTON_SHOOT, a0.rgbButtons); - - if (g_Supervisor.cfg.controllerMapping.shootButton != g_Supervisor.cfg.controllerMapping.focusButton) - { - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.focusButton, - TH_BUTTON_FOCUS, a0.rgbButtons); - } - else - { - if (a2 != 0) - { - if (g_FocusButtonConflictState < 16) - { - g_FocusButtonConflictState++; - } - - if (g_FocusButtonConflictState >= 8) - { - buttons |= TH_BUTTON_FOCUS; - } - } - else - { - if (g_FocusButtonConflictState > 8) - { - g_FocusButtonConflictState -= 8; - } - else - { - g_FocusButtonConflictState = 0; - } - } - } - - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.bombButton, TH_BUTTON_BOMB, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.menuButton, TH_BUTTON_MENU, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.upButton, TH_BUTTON_UP, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.downButton, TH_BUTTON_DOWN, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.leftButton, TH_BUTTON_LEFT, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.rightButton, TH_BUTTON_RIGHT, - a0.rgbButtons); - SetButtonFromDirectInputJoystate(&buttons, g_Supervisor.cfg.controllerMapping.skipButton, TH_BUTTON_SKIP, - a0.rgbButtons); - - buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_RIGHT, a0.lX, g_Supervisor.cfg.padXAxis); - buttons |= JOYSTICK_BUTTON_PRESSED_INVERT(TH_BUTTON_LEFT, a0.lX, -g_Supervisor.cfg.padXAxis); - buttons |= JOYSTICK_BUTTON_PRESSED(TH_BUTTON_DOWN, a0.lY, g_Supervisor.cfg.padYAxis); - buttons |= JOYSTICK_BUTTON_PRESSED_INVERT(TH_BUTTON_UP, a0.lY, -g_Supervisor.cfg.padYAxis); - } - } - - return buttons; -} - -u16 Controller::GetInput(void) -{ - u8 keyboardState[256]; - u16 buttons; - - buttons = 0; - - if (g_Supervisor.keyboard == NULL) - { - GetKeyboardState(keyboardState); - - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, VK_UP); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, VK_DOWN); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, VK_LEFT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, VK_RIGHT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, VK_NUMPAD8); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, VK_NUMPAD2); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, VK_NUMPAD4); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, VK_NUMPAD6); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_LEFT, VK_NUMPAD7); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_RIGHT, VK_NUMPAD9); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_LEFT, VK_NUMPAD1); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_RIGHT, VK_NUMPAD3); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_HOME, VK_HOME); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SHOOT, 'Z'); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_BOMB, 'X'); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, VK_SHIFT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_MENU, VK_ESCAPE); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, VK_CONTROL); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_Q, 'Q'); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_S, 'S'); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_ENTER, VK_RETURN); - } - else - { - HRESULT res = g_Supervisor.keyboard->GetDeviceState(sizeof(keyboardState), keyboardState); - - buttons = 0; - - if (res == DIERR_INPUTLOST) - { - g_Supervisor.keyboard->Acquire(); - - return Controller::GetControllerInput(buttons); - } - - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, DIK_UP); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, DIK_DOWN); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, DIK_LEFT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, DIK_RIGHT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP, DIK_NUMPAD8); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN, DIK_NUMPAD2); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_LEFT, DIK_NUMPAD4); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_RIGHT, DIK_NUMPAD6); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_LEFT, DIK_NUMPAD7); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_UP_RIGHT, DIK_NUMPAD9); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_LEFT, DIK_NUMPAD1); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_DOWN_RIGHT, DIK_NUMPAD3); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_HOME, DIK_HOME); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SHOOT, DIK_Z); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_BOMB, DIK_X); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, DIK_LSHIFT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_FOCUS, DIK_RSHIFT); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_MENU, DIK_ESCAPE); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, DIK_LCONTROL); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_SKIP, DIK_RCONTROL); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_Q, DIK_Q); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_S, DIK_S); - buttons |= KEYBOARD_KEY_PRESSED(TH_BUTTON_ENTER, DIK_RETURN); - } - - return Controller::GetControllerInput(buttons); -} - #pragma optimize("s", on) #pragma var_order(diprange, pvRefBackup) BOOL CALLBACK Supervisor::ControllerCallback(LPCDIDEVICEOBJECTINSTANCEA lpddoi, LPVOID pvRef) @@ -1088,18 +776,6 @@ BOOL CALLBACK Supervisor::EnumGameControllersCb(LPCDIDEVICEINSTANCEA pdidInstanc } #pragma optimize("", on) -void Controller::ResetKeyboard(void) -{ - u8 key_states[256]; - - GetKeyboardState(key_states); - for (i32 idx = 0; idx < 256; idx++) - { - *(key_states + idx) &= 0x7f; - } - SetKeyboardState(key_states); -} - #pragma optimize("s", on) ZunBool Supervisor::ReadMidiFile(u32 midiFileIdx, char *path) { @@ -1280,70 +956,4 @@ ZunResult Supervisor::FadeOutMusic(f32 fadeOutSeconds) } #pragma optimize("", on) -DIFFABLE_STATIC_ARRAY(u8, (32 * 4), g_ControllerData) - -#pragma optimize("", on) -#pragma var_order(joyinfoex, joyButtonBit, joyButtonIndex, dires, dijoystate2, diRetryCount) -// This is for rebinding keys -u8 *th06::Controller::GetControllerState() -{ - JOYINFOEX joyinfoex; - u32 joyButtonBit; - u32 joyButtonIndex; - - i32 dires; - DIJOYSTATE2 dijoystate2; - i32 diRetryCount; - - memset(&g_ControllerData, 0, sizeof(g_ControllerData)); - if (g_Supervisor.controller == NULL) - { - memset(&joyinfoex, 0, sizeof(JOYINFOEX)); - joyinfoex.dwSize = sizeof(JOYINFOEX); - joyinfoex.dwFlags = JOY_RETURNALL; - if (joyGetPosEx(0, &joyinfoex) != JOYERR_NOERROR) - { - return g_ControllerData; - } - for (joyButtonBit = joyinfoex.dwButtons, joyButtonIndex = 0; joyButtonIndex < 32; - joyButtonIndex += 1, joyButtonBit >>= 1) - { - if ((joyButtonBit & 1) != 0) - { - g_ControllerData[joyButtonIndex] = 0x80; - } - } - return g_ControllerData; - } - else - { - dires = g_Supervisor.controller->Poll(); - if (FAILED(dires)) - { - diRetryCount = 0; - utils::DebugPrint2("error : DIERR_INPUTLOST\n"); - dires = g_Supervisor.controller->Acquire(); - while (dires == DIERR_INPUTLOST) - { - dires = g_Supervisor.controller->Acquire(); - utils::DebugPrint2("error : DIERR_INPUTLOST %d\n", diRetryCount); - diRetryCount++; - if (diRetryCount >= 400) - { - return g_ControllerData; - } - } - return g_ControllerData; - } - /* dires = */ g_Supervisor.controller->GetDeviceState(sizeof(DIJOYSTATE2), &dijoystate2); - // TODO: seems ZUN forgot "dires =" above - if (FAILED(dires)) - { - return g_ControllerData; - } - memcpy(&g_ControllerData, dijoystate2.rgbButtons, sizeof(dijoystate2.rgbButtons)); - return g_ControllerData; - } -} -#pragma optimize("", on) }; // namespace th06 diff --git a/src/Supervisor.hpp b/src/Supervisor.hpp index 025340a3..e2c71a5b 100644 --- a/src/Supervisor.hpp +++ b/src/Supervisor.hpp @@ -5,6 +5,7 @@ #include #include "Chain.hpp" +#include "Controller.hpp" #include "MidiOutput.hpp" #include "ZunBool.hpp" #include "ZunResult.hpp" @@ -189,50 +190,6 @@ struct Supervisor }; C_ASSERT(sizeof(Supervisor) == 0x4d8); -enum TouhouButton -{ - TH_BUTTON_SHOOT = 1 << 0, - TH_BUTTON_BOMB = 1 << 1, - TH_BUTTON_FOCUS = 1 << 2, - TH_BUTTON_MENU = 1 << 3, - TH_BUTTON_UP = 1 << 4, - TH_BUTTON_DOWN = 1 << 5, - TH_BUTTON_LEFT = 1 << 6, - TH_BUTTON_RIGHT = 1 << 7, - TH_BUTTON_SKIP = 1 << 8, - TH_BUTTON_Q = 1 << 9, - TH_BUTTON_S = 1 << 10, - TH_BUTTON_HOME = 1 << 11, - TH_BUTTON_ENTER = 1 << 12, - - TH_BUTTON_UP_LEFT = TH_BUTTON_UP | TH_BUTTON_LEFT, - TH_BUTTON_UP_RIGHT = TH_BUTTON_UP | TH_BUTTON_RIGHT, - TH_BUTTON_DOWN_LEFT = TH_BUTTON_DOWN | TH_BUTTON_LEFT, - TH_BUTTON_DOWN_RIGHT = TH_BUTTON_DOWN | TH_BUTTON_RIGHT, - TH_BUTTON_DIRECTION = TH_BUTTON_DOWN | TH_BUTTON_RIGHT | TH_BUTTON_UP | TH_BUTTON_LEFT, - - TH_BUTTON_SELECTMENU = TH_BUTTON_ENTER | TH_BUTTON_SHOOT, - TH_BUTTON_RETURNMENU = TH_BUTTON_MENU | TH_BUTTON_BOMB, - TH_BUTTON_WRONG_CHEATCODE = - TH_BUTTON_SHOOT | TH_BUTTON_BOMB | TH_BUTTON_MENU | TH_BUTTON_Q | TH_BUTTON_S | TH_BUTTON_ENTER, - TH_BUTTON_ANY = 0xFFFF, -}; - -namespace Controller -{ -u16 GetJoystickCaps(void); -u32 SetButtonFromControllerInputs(u16 *outButtons, i16 controllerButtonToTest, enum TouhouButton touhouButton, - u32 inputButtons); - -unsigned int SetButtonFromDirectInputJoystate(u16 *outButtons, i16 controllerButtonToTest, - enum TouhouButton touhouButton, u8 *inputButtons); - -u16 GetControllerInput(u16 buttons); -u8 *GetControllerState(); -u16 GetInput(void); -void ResetKeyboard(void); -}; // namespace Controller - DIFFABLE_EXTERN(ControllerMapping, g_ControllerMapping) DIFFABLE_EXTERN(Supervisor, g_Supervisor) DIFFABLE_EXTERN(u16, g_LastFrameInput)