diff --git a/libultraship/libultraship/ControlDeck.cpp b/libultraship/libultraship/ControlDeck.cpp index 7c4708ab2..071d62956 100644 --- a/libultraship/libultraship/ControlDeck.cpp +++ b/libultraship/libultraship/ControlDeck.cpp @@ -80,6 +80,7 @@ namespace Ship { if (backend->GetGuid() == "Auto") { for (const auto& device : physicalDevices) { if(shouldBlockGameInput && device->GetGuid() != "Keyboard") { + device->Read(nullptr, i); continue; } device->Read(&pad[i], i); @@ -87,6 +88,7 @@ namespace Ship { continue; } if(shouldBlockGameInput && backend->GetGuid() != "Keyboard") { + backend->Read(nullptr, i); continue; } backend->Read(&pad[i], i); diff --git a/libultraship/libultraship/Controller.cpp b/libultraship/libultraship/Controller.cpp index ef2ebe943..ae9d863d1 100644 --- a/libultraship/libultraship/Controller.cpp +++ b/libultraship/libultraship/Controller.cpp @@ -1,6 +1,7 @@ #include "Controller.h" #include #include +#include "Cvar.h" #if __APPLE__ #include #else @@ -21,58 +22,67 @@ namespace Ship { void Controller::Read(OSContPad* pad, int32_t virtualSlot) { ReadFromSource(virtualSlot); + OSContPad padToBuffer = { 0 }; + #ifndef __WIIU__ SDL_PumpEvents(); #endif // Button Inputs - pad->button |= getPressedButtons(virtualSlot) & 0xFFFF; + padToBuffer.button |= getPressedButtons(virtualSlot) & 0xFFFF; // Stick Inputs if (getLeftStickX(virtualSlot) == 0) { if (getPressedButtons(virtualSlot) & BTN_STICKLEFT) { - pad->stick_x = -128; + padToBuffer.stick_x = -128; } else if (getPressedButtons(virtualSlot) & BTN_STICKRIGHT) { - pad->stick_x = 127; + padToBuffer.stick_x = 127; } } else { - pad->stick_x = getLeftStickX(virtualSlot); + padToBuffer.stick_x = getLeftStickX(virtualSlot); } if (getLeftStickY(virtualSlot) == 0) { if (getPressedButtons(virtualSlot) & BTN_STICKDOWN) { - pad->stick_y = -128; + padToBuffer.stick_y = -128; } else if (getPressedButtons(virtualSlot) & BTN_STICKUP) { - pad->stick_y = 127; + padToBuffer.stick_y = 127; } } else { - pad->stick_y = getLeftStickY(virtualSlot); + padToBuffer.stick_y = getLeftStickY(virtualSlot); } // Stick Inputs if (getRightStickX(virtualSlot) == 0) { if (getPressedButtons(virtualSlot) & BTN_VSTICKLEFT) { - pad->right_stick_x = -128; + padToBuffer.right_stick_x = -128; } else if (getPressedButtons(virtualSlot) & BTN_VSTICKRIGHT) { - pad->right_stick_x = 127; + padToBuffer.right_stick_x = 127; } } else { - pad->right_stick_x = getRightStickX(virtualSlot); + padToBuffer.right_stick_x = getRightStickX(virtualSlot); } if (getRightStickY(virtualSlot) == 0) { if (getPressedButtons(virtualSlot) & BTN_VSTICKDOWN) { - pad->right_stick_y = -128; + padToBuffer.right_stick_y = -128; } else if (getPressedButtons(virtualSlot) & BTN_VSTICKUP) { - pad->right_stick_y = 127; + padToBuffer.right_stick_y = 127; } } else { - pad->right_stick_y = getRightStickY(virtualSlot); + padToBuffer.right_stick_y = getRightStickY(virtualSlot); } // Gyro - pad->gyro_x = getGyroX(virtualSlot); - pad->gyro_y = getGyroY(virtualSlot); + padToBuffer.gyro_x = getGyroX(virtualSlot); + padToBuffer.gyro_y = getGyroY(virtualSlot); + + padBuffer.push_front(padToBuffer); + *pad = padBuffer[std::min(padBuffer.size(), (size_t)CVar_GetS32("gSimulatedInputLag", 0))]; + + while (padBuffer.size() > 6) { + padBuffer.pop_back(); + } } void Controller::SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t dwScancode) { diff --git a/libultraship/libultraship/Controller.h b/libultraship/libultraship/Controller.h index 5cd5b8654..3d03960ba 100644 --- a/libultraship/libultraship/Controller.h +++ b/libultraship/libultraship/Controller.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "UltraController.h" #include "ControllerAttachment.h" #include @@ -84,5 +85,6 @@ namespace Ship { std::unordered_map> profiles; std::unordered_map> ButtonData = {}; + std::deque padBuffer; }; } diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 9dc739527..0a84d3c41 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -504,6 +504,11 @@ namespace GameMenuBar { UIWidgets::EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); ImGui::PopItemWidth(); + UIWidgets::Spacer(0); + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 20.0f); + UIWidgets::EnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, false); + UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later"); + ImGui::PopItemWidth(); ImGui::EndMenu(); } diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index f4dcf56e8..2a0e5c733 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -483,10 +483,7 @@ static void RunFrame() Graph_StartFrame(); - // TODO: Workaround for rumble being too long. Implement os thread functions. - for (int i = 0; i < 3; i++) { - PadMgr_ThreadEntry(&gPadMgr); - } + PadMgr_ThreadEntry(&gPadMgr); Graph_Update(&runFrameContext.gfxCtx, runFrameContext.gameState); ticksB = GetPerfCounter(); diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index 9bd9d53e7..e2283c1e9 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -331,16 +331,20 @@ void PadMgr_HandleRetraceMsg(PadMgr* padMgr) { } padMgr->validCtrlrsMask = mask; - /* if (gFaultStruct.msgId) { - PadMgr_RumbleStop(padMgr); - } else */ if (padMgr->rumbleOffFrames > 0) { - --padMgr->rumbleOffFrames; - PadMgr_RumbleStop(padMgr); - } else if (padMgr->rumbleOnFrames == 0) { - PadMgr_RumbleStop(padMgr); - } else if (!padMgr->preNMIShutdown) { - PadMgr_RumbleControl(padMgr); - --padMgr->rumbleOnFrames; + // TODO: Workaround for rumble being too long. Implement os thread functions. + // Game logic runs at 20hz but input thread runs at 60 hertz, so we call this 3 times + for (i = 0; i < 3; i++) { + /* if (gFaultStruct.msgId) { + PadMgr_RumbleStop(padMgr); + } else */ if (padMgr->rumbleOffFrames > 0) { + --padMgr->rumbleOffFrames; + PadMgr_RumbleStop(padMgr); + } else if (padMgr->rumbleOnFrames == 0) { + PadMgr_RumbleStop(padMgr); + } else if (!padMgr->preNMIShutdown) { + PadMgr_RumbleControl(padMgr); + --padMgr->rumbleOnFrames; + } } }