diff --git a/CMakeLists.txt b/CMakeLists.txt index 4acc509a05..f2e2a7fa99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence, show the current gam option(ENABLE_ANALYTICS "Enables opt-in Analytics collection" OFF) # Enable Playback build for Slippi. TODO: turn off for normal builds -option(SLIPPI_PLAYBACK "Enable Playback changes" OFF) +option(SLIPPI_PLAYBACK "Enable Playback changes" ON) option(ENCODE_FRAMEDUMPS "Encode framedumps in AVI format" ON) diff --git a/Externals/open-vcdiff/src/vcdecoder.cc b/Externals/open-vcdiff/src/vcdecoder.cc index 34ecd0bbf3..3cc0517414 100644 --- a/Externals/open-vcdiff/src/vcdecoder.cc +++ b/Externals/open-vcdiff/src/vcdecoder.cc @@ -324,7 +324,7 @@ class VCDiffStreamingDecoderImpl { // The default maximum target file size (and target window size) if // SetMaximumTargetFileSize() is not called. - static const size_t kDefaultMaximumTargetFileSize = 134217728U; // 128 MB + static const size_t kDefaultMaximumTargetFileSize = 268435456U; // 128 MB // The largest value that can be passed to SetMaximumTargetWindowSize(). // Using a larger value will result in an error. diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index eb15c67604..1ffc7dbc78 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -157,6 +157,10 @@ void Host_PlaybackSeek() { } +void Host_Fullscreen() +{ +} + static bool MsgAlert(const char* caption, const char* text, bool yes_no, Common::MsgType /*style*/) { JNIEnv* env = IDCache::GetEnvForThread(); diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index b82198bf25..41a3622cb3 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -479,8 +479,8 @@ add_library(core Slippi/SlippiReplayComm.h Slippi/SlippiSavestate.cpp Slippi/SlippiSavestate.h - Slippi/SlippiTimer.cpp - Slippi/SlippiTimer.h + + Slippi/SlippiUser.cpp Slippi/SlippiUser.h ) diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index ea733afb8e..3b6ce0de90 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -47,3 +47,4 @@ void Host_TitleChanged(); void Host_LowerWindow(); void Host_Exit(); void Host_PlaybackSeek(); +void Host_Fullscreen(); diff --git a/Source/Core/Core/Slippi/SlippiPlayback.cpp b/Source/Core/Core/Slippi/SlippiPlayback.cpp index 68e4c2ea45..b7b8508cb0 100644 --- a/Source/Core/Core/Slippi/SlippiPlayback.cpp +++ b/Source/Core/Core/Slippi/SlippiPlayback.cpp @@ -7,7 +7,6 @@ #include "Common/Logging/Log.h" #include "Core/Core.h" -#include "Core/ConfigManager.h" #include "Core/HW/EXI/EXI_DeviceSlippi.h" #include "Core/NetPlayClient.h" #include "Core/State.h" @@ -74,7 +73,7 @@ void SlippiPlaybackStatus::startThreads() void SlippiPlaybackStatus::prepareSlippiPlayback(s32& frameIndex) { // block if there's too many diffs being processed - while (shouldRunThreads && numDiffsProcessing > 3) + while (shouldRunThreads && numDiffsProcessing > 2) { INFO_LOG(SLIPPI, "Processing too many diffs, blocking main process"); cv_processingDiff.wait(processingLock); @@ -205,7 +204,7 @@ void SlippiPlaybackStatus::seekToFrame() } else { - // If this diff has been processed, load it + // If this diff exists, load it if (futureDiffs.count(closestStateFrame) > 0) { loadState(closestStateFrame); @@ -241,7 +240,13 @@ void SlippiPlaybackStatus::seekToFrame() Core::SetState(Core::State::Paused); setHardFFW(false); } + else { + // In the case where we don't need to fastforward, we're already at the frame we want! + // Update currentPlaybackFrame accordingly + g_playbackStatus->currentPlaybackFrame = targetFrameNum; + } + // We've reached the frame we want. Reset targetFrameNum and release mutex so another seek can be performed targetFrameNum = INT_MAX; Core::SetState(prevState); seekMtx.unlock(); diff --git a/Source/Core/Core/Slippi/SlippiPlayback.h b/Source/Core/Core/Slippi/SlippiPlayback.h index 7a35b74d83..dfb6fc3d72 100644 --- a/Source/Core/Core/Slippi/SlippiPlayback.h +++ b/Source/Core/Core/Slippi/SlippiPlayback.h @@ -2,12 +2,14 @@ #include #include -#include -#include -#include #include #include +#include +#include +#include + +#include "Core/ConfigManager.h" #include "../../Common/CommonTypes.h" class SlippiPlaybackStatus @@ -22,8 +24,8 @@ public: volatile bool shouldRunThreads = false; bool isHardFFW = false; bool isSoftFFW = false; - bool origOCEnable; - float origOCFactor; + bool origOCEnable = SConfig::GetInstance().m_OCEnable; + float origOCFactor = SConfig::GetInstance().m_OCFactor; s32 lastFFWFrame = INT_MIN; s32 currentPlaybackFrame = INT_MIN; diff --git a/Source/Core/Core/Slippi/SlippiTimer.cpp b/Source/Core/Core/Slippi/SlippiTimer.cpp deleted file mode 100644 index 5e8ad51912..0000000000 --- a/Source/Core/Core/Slippi/SlippiTimer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// SLIPPITODO: refactor with qt - -/*#include "SlippiTimer.h" -#include "DolphinWX/Frame.h" -#include "SlippiPlayback.h" - -extern std::unique_ptr g_playbackStatus; - -void SlippiTimer::Notify() -{ - if (!m_slider || !m_text) - { - // If there is no slider, do nothing - return; - } - - int totalSeconds = (int)((g_playbackStatus->latestFrame - Slippi::GAME_FIRST_FRAME) / 60); - int totalMinutes = (int)(totalSeconds / 60); - int totalRemainder = (int)(totalSeconds % 60); - - int currSeconds = int((g_playbackStatus->currentPlaybackFrame - Slippi::GAME_FIRST_FRAME) / 60); - int currMinutes = (int)(currSeconds / 60); - int currRemainder = (int)(currSeconds % 60); - // Position string (i.e. MM:SS) - char endTime[6]; - sprintf(endTime, "%02d:%02d", totalMinutes, totalRemainder); - char currTime[6]; - sprintf(currTime, "%02d:%02d", currMinutes, currRemainder); - - std::string time = std::string(currTime) + " / " + std::string(endTime); - - // Setup the slider and gauge min/max values - int minValue = m_slider->GetMin(); - int maxValue = m_slider->GetMax(); - if (maxValue != (int)g_playbackStatus->latestFrame || minValue != Slippi::PLAYBACK_FIRST_SAVE) - { - m_slider->SetRange(Slippi::PLAYBACK_FIRST_SAVE, (int)(g_playbackStatus->latestFrame)); - } - - // Only update values while not actively seeking - if (g_playbackStatus->targetFrameNum == INT_MAX && m_slider->isDraggingSlider == false) - { - m_text->SetLabel(_(time)); - m_slider->SetValue(g_playbackStatus->currentPlaybackFrame); - } -}*/ diff --git a/Source/Core/Core/Slippi/SlippiTimer.h b/Source/Core/Core/Slippi/SlippiTimer.h deleted file mode 100644 index 67abbfca13..0000000000 --- a/Source/Core/Core/Slippi/SlippiTimer.h +++ /dev/null @@ -1,30 +0,0 @@ -// SLIPPITODO: refactor with qt - -/*#ifndef SLIPPI_TIMER_HEADER -#define SLIPPI_TIMER_HEADER - -#include -#include -#include - -class CFrame; - -class SlippiTimer : public wxTimer -{ -public: - SlippiTimer(CFrame* mainFrame, PlaybackSlider* slider, wxStaticText* text) { - m_frame = mainFrame; - m_slider = slider; - m_text = text; - } - - // Called each time the timer's timeout expires - void Notify() wxOVERRIDE; - - CFrame* m_frame; - PlaybackSlider* m_slider; - wxStaticText* m_text; -}; - -#endif -*/ diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 763fd2190a..be260aa6b7 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -110,6 +110,7 @@ void Host_TitleChanged() void Host_LowerWindow() {} void Host_Exit() {} void Host_PlaybackSeek() {} +void Host_Fullscreen() {} static std::unique_ptr GetPlatform(const optparse::Values& options) { diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index bdfc1ba328..4340b7bdbf 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -188,3 +188,8 @@ void Host_PlaybackSeek() { Host::GetInstance()->RequestSeek(); } + +void Host_Fullscreen() +{ + Host::GetInstance()->RequestFullscreen(); +} diff --git a/Source/Core/DolphinQt/Host.h b/Source/Core/DolphinQt/Host.h index faec27984d..390023f115 100644 --- a/Source/Core/DolphinQt/Host.h +++ b/Source/Core/DolphinQt/Host.h @@ -40,7 +40,8 @@ signals: void RequestLowerWindow(); void RequestExit(); void RequestSeek(); - + void RequestFullscreen(); + private: Host(); diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 1ecb875986..f17e1a91b1 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -632,6 +632,7 @@ void MainWindow::ConnectRenderWidget() void MainWindow::ConnectHost() { connect(Host::GetInstance(), &Host::RequestStop, this, &MainWindow::RequestStop); + connect(Host::GetInstance(), &Host::RequestFullscreen, this, &MainWindow::FullScreen); } void MainWindow::ConnectStack() diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp index ff4b7ccd7e..a0efbb8001 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp @@ -11,13 +11,9 @@ #include #include "Common/CommonTypes.h" - #include "Common/Timer.h" - #include "Core/ConfigManager.h" - #include "Core/Slippi/SlippiPlayback.h" - #include "VideoCommon/OnScreenDisplay.h" #ifdef IS_PLAYBACK @@ -25,6 +21,7 @@ #define IMGUI_DEFINE_MATH_OPERATORS #endif + #include #include "Core/Core.h" #include "Core/Host.h" @@ -158,6 +155,7 @@ static std::string GetTimeForFrame(s32 currFrame) { return std::string(currTime); } +bool showHelp = false; u32 idle_tick = Common::Timer::GetTimeMs(); ImVec2 prev_mouse(0, 0); @@ -462,10 +460,45 @@ void DrawSlippiPlaybackControls() if (ButtonCustom(ICON_FA_FAST_FORWARD, ImVec2(32.0f, 32.0f))) { INFO_LOG(SLIPPI, "fast_foward"); if (g_playbackStatus->targetFrameNum == INT_MAX) { - g_playbackStatus->targetFrameNum = g_playbackStatus->currentPlaybackFrame - 1200; + g_playbackStatus->targetFrameNum = g_playbackStatus->currentPlaybackFrame + 1200; Host_PlaybackSeek(); } } + ImGui::SameLine(ImGui::GetWindowWidth() - 64.0f); + if (ButtonCustom(ICON_FA_QUESTION_CIRCLE, ImVec2(32.0f, 32.0f))) { + showHelp = !showHelp; + } + ImGui::SameLine(ImGui::GetWindowWidth() - 32.0f); + if (ButtonCustom(ICON_FA_EXPAND, ImVec2(32.0f, 32.0f))) { + INFO_LOG(SLIPPI, "fullscreen"); + Host_Fullscreen(); + } + + if (g_playbackStatus->isHardFFW) { + INFO_LOG(SLIPPI, "Ffw"); + } + + if (showHelp) { + ImGui::GetWindowDrawList()->AddRectFilled( + ImVec2(ImGui::GetWindowWidth() - 300.0f, ImGui::GetWindowHeight() - 200.0f), + ImVec2(ImGui::GetWindowWidth() - 50.0f, ImGui::GetWindowHeight() - 40.0f), + ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.8f * alpha))); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 190.0f)); + ImGui::Text("Play/Pause: Spacebar"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 170.0f)); + ImGui::Text("Step Back (5s): Left Arrow"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 150.0f)); + ImGui::Text("Step Forward (5s): Right Arrow"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 130.0f)); + ImGui::Text("Jump Back (20s): Shift + Left Arrow"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 110.0f)); + ImGui::Text("Jump Forward (20s): Shift + Right Arrow"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 90.0f)); + ImGui::Text("Frame Advance: Period"); + ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 70.0f)); + ImGui::Text("Big jumps/seeks may take several seconds."); + } + ImGui::PopStyleVar(); ImGuiWindow* window = ImGui::GetCurrentWindow(); ImGui::SetCursorPos(ImVec2(135.0f, window->DC.CursorPosPrevLine.y + 6.0f)); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index bdd7cd5ec5..d1bee718e6 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -521,9 +521,10 @@ void Renderer::DrawDebugText() if (ImGui::Begin("FPS", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | - ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoFocusOnAppearing)) { ImGui::TextColored(ImVec4(0.0f, 1.0f, 1.0f, 1.0f), "FPS: %.2f", m_fps_counter.GetFPS()); } diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp index d623f48049..3086758a75 100644 --- a/Source/UnitTests/StubHost.cpp +++ b/Source/UnitTests/StubHost.cpp @@ -58,3 +58,6 @@ void Host_Exit() void Host_PlaybackSeek() { } +void Host_Fullscreen() +{ +}