diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index f7f3d149c3..522e330b05 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -511,14 +511,18 @@ void __DisplaySetWasPaused() { wasPaused = true; } +static int FrameTimingLimit() { + if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) + return g_Config.iFpsLimit1; + if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) + return g_Config.iFpsLimit2; + if (PSP_CoreParameter().fastForward) + return 0; + return 60; +} + static bool FrameTimingThrottled() { - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 == 0) { - return false; - } - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 == 0) { - return false; - } - return !PSP_CoreParameter().fastForward; + return FrameTimingLimit() != 0; } static void DoFrameDropLogging(float scaledTimestep) { @@ -546,10 +550,7 @@ static int CalculateFrameSkip() { // Let's collect all the throttling and frameskipping logic here. static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { PROFILE_THIS_SCOPE("timing"); - FPSLimit fpsLimiter = PSP_CoreParameter().fpsLimit; - int fpsLimit = 60; - if (fpsLimiter != FPSLimit::NORMAL) - fpsLimit = fpsLimiter == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2; + int fpsLimit = FrameTimingLimit(); throttle = FrameTimingThrottled(); skipFrame = false; @@ -558,16 +559,7 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { bool doFrameSkip = g_Config.iFrameSkip != 0; bool fastForwardNeedsSkip = g_Config.iFastForwardMode == (int)FastForwardMode::SKIP_DRAW; - if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) { - // Vulkan doesn't support the interval setting, so we force frameskip. - fastForwardNeedsSkip = true; - // If it's not a clean multiple of 60, we may need frameskip to achieve it. - if (fpsLimit == 0 || (fpsLimit >= 0 && fpsLimit != 15 && fpsLimit != 30 && fpsLimit != 60)) { - doFrameSkip = true; - } - } if (!throttle && fastForwardNeedsSkip) { - doFrameSkip = true; skipFrame = true; if (numSkippedFrames >= 7) { skipFrame = false; @@ -657,11 +649,10 @@ static void DoFrameIdleTiming() { } float scaledVblank = timePerVblank; - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 > 0) { + int fpsLimit = FrameTimingLimit(); + if (fpsLimit != 0 && fpsLimit != 60) { // 0 is handled in FrameTimingThrottled(). - scaledVblank *= 60.0f / g_Config.iFpsLimit1; - } else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 > 0) { - scaledVblank *= 60.0f / g_Config.iFpsLimit2; + scaledVblank *= 60.0f / fpsLimit; } // If we have over at least a vblank of spare time, maintain at least 30fps in delay. @@ -751,9 +742,10 @@ void __DisplayFlip(int cyclesLate) { bool duplicateFrames = g_Config.bRenderDuplicateFrames && g_Config.iFrameSkip == 0; bool fastForwardNeedsSkip = g_Config.iFastForwardMode != (int)FastForwardMode::CONTINUOUS; + bool fastForwardSkipFlip = g_Config.iFastForwardMode == (int)FastForwardMode::SKIP_FLIP; if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) { - // Vulkan doesn't support the interval setting, so we force frameskip. - fastForwardNeedsSkip = true; + // Vulkan doesn't support the interval setting, so we force skipping the flip. + fastForwardSkipFlip = true; } // postEffectRequiresFlip is not compatible with frameskip fast-forward, see #12325. @@ -786,12 +778,13 @@ void __DisplayFlip(int cyclesLate) { } bool forceNoFlip = false; + float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); // Alternative to frameskip fast-forward, where we draw everything. // Useful if skipping a frame breaks graphics or for checking drawing speed. - if (g_Config.iFastForwardMode == (int)FastForwardMode::SKIP_FLIP && !FrameTimingThrottled()) { + if (fastForwardSkipFlip && (!FrameTimingThrottled() || FrameTimingLimit() > refreshRate)) { static double lastFlip = 0; double now = time_now_d(); - if ((now - lastFlip) < 1.0f / System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE)) { + if ((now - lastFlip) < 1.0f / refreshRate) { forceNoFlip = true; } else { lastFlip = now; @@ -884,11 +877,10 @@ void hleLagSync(u64 userdata, int cyclesLate) { } float scale = 1.0f; - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 > 0) { + int fpsLimit = FrameTimingLimit(); + if (fpsLimit != 0 && fpsLimit != 60) { // 0 is handled in FrameTimingThrottled(). - scale = 60.0f / g_Config.iFpsLimit1; - } else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 > 0) { - scale = 60.0f / g_Config.iFpsLimit2; + scale = 60.0f / fpsLimit; } const double goal = lastLagSync + (scale / 1000.0f); diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 8b766110db..f2dd0410b4 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -657,7 +657,10 @@ void MainWindow::createMenus() gameSettingsMenu->add(new MenuAction(this, SLOT(cheatsAct()), QT_TR_NOOP("Enable &cheats"), Qt::CTRL + Qt::Key_T)) ->addEventChecked(&g_Config.bEnableCheats); gameSettingsMenu->addSeparator(); - gameSettingsMenu->add(new MenuAction(this, SLOT(chatAct()), QT_TR_NOOP("Enable chat"), Qt::CTRL + Qt::Key_C)); + gameSettingsMenu->add(new MenuAction(this, SLOT(chatAct()), QT_TR_NOOP("Open chat"), Qt::CTRL + Qt::Key_C)) + ->SetEnabledFunc([=]() { + return g_Config.bEnableNetworkChat && GetUIState() == UISTATE_INGAME; + }); // Help MenuTree* helpMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Help")); diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 2a9660d744..26ad5b521c 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -185,9 +185,9 @@ private slots: // Chat void chatAct() { - g_Config.bEnableNetworkChat = true; - updateMenus(); - NativeMessageReceived("chat screen", ""); + if (GetUIState() == UISTATE_INGAME) { + NativeMessageReceived("chat screen", ""); + } } void fullscrAct(); @@ -244,7 +244,7 @@ class MenuAction : public QAction public: // Add to QMenu MenuAction(QWidget* parent, const char *callback, const char *text, QKeySequence key = 0) : - QAction(parent), _text(text), _eventCheck(0), _eventUncheck(0), _stateEnable(-1), _stateDisable(-1), _enableStepping(false) + QAction(parent), _text(text) { if (key != (QKeySequence)0) { this->setShortcut(key); @@ -256,7 +256,7 @@ public: } // Add to QActionGroup MenuAction(QWidget* parent, QActionGroup* group, QVariant data, QString text, QKeySequence key = 0) : - QAction(parent), _eventCheck(0), _eventUncheck(0), _stateEnable(-1), _stateDisable(-1), _enableStepping(false) + QAction(parent) { this->setCheckable(true); this->setData(data); @@ -284,14 +284,19 @@ public: } // UI State which causes it to be enabled void addEnableState(int state) { + _enabledFunc = nullptr; _stateEnable = state; + _stateDisable = -1; } void addDisableState(int state) { + _enabledFunc = nullptr; + _stateEnable = -1; _stateDisable = state; } - MenuAction* addEnableStepping() { - _enableStepping = true; - return this; + void SetEnabledFunc(std::function func) { + _enabledFunc = func; + _stateEnable = -1; + _stateDisable = -1; } public slots: void retranslate() { @@ -306,15 +311,16 @@ public slots: setEnabled(GetUIState() == _stateEnable); if (_stateDisable >= 0) setEnabled(GetUIState() != _stateDisable); - if (_enableStepping && Core_IsStepping()) - setEnabled(true); + if (_enabledFunc) + setEnabled(_enabledFunc()); } private: const char *_text; - bool *_eventCheck; - bool *_eventUncheck; - int _stateEnable, _stateDisable; - bool _enableStepping; + bool *_eventCheck = nullptr; + bool *_eventUncheck = nullptr; + int _stateEnable = -1; + int _stateDisable = -1; + std::function _enabledFunc; }; class MenuActionGroup : public QActionGroup diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp index 41eef866ae..df311ad305 100644 --- a/UI/ChatScreen.cpp +++ b/UI/ChatScreen.cpp @@ -19,7 +19,7 @@ void ChatMenu::CreateContents(UI::ViewGroup *parent) { using namespace UI; auto n = GetI18NCategory("Networking"); LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT,400)); - scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0))); + scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0))); LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(SDL) chatEdit_ = bottom->Add(new TextEdit("", n->T("Chat message"), n->T("Chat Here"), new LinearLayoutParams(1.0))); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7e69ec28ed..78695e8efd 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -488,23 +488,23 @@ void EmuScreen::sendMessage(const char *message, const char *value) { gstate_c.skipDrawReason &= ~SKIPDRAW_WINDOW_MINIMIZED; } } else if (!strcmp(message, "chat screen")) { + if (g_Config.bEnableNetworkChat) { + if (!chatButton_) + RecreateViews(); #if defined(USING_WIN_UI) - //temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable - if (g_Config.bBypassOSKWithKeyboard) { - osm.Show("Disable windows native keyboard options to use ctrl + c hotkey", 2.0f); - } else { - if (g_Config.bEnableNetworkChat) { + //temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable + if (g_Config.bBypassOSKWithKeyboard) { + osm.Show("Disable windows native keyboard options to use ctrl + c hotkey", 2.0f); + } else { UI::EventParams e{}; OnChatMenu.Trigger(e); } - } #else - if (g_Config.bEnableNetworkChat) { UI::EventParams e{}; OnChatMenu.Trigger(e); - } #endif + } } else if (!strcmp(message, "app_resumed") && screenManager()->topScreen() == this) { if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) { if (!KeyMap::IsKeyMapped(DEVICE_ID_PAD_0, VIRTKEY_PAUSE) || !KeyMap::IsKeyMapped(DEVICE_ID_PAD_1, VIRTKEY_PAUSE)) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2305795bc7..37d5102c55 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1972,12 +1972,8 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) { parent->Add(ipRows_); listIP.clear(); listIP.shrink_to_fit(); - errorView_ = parent->Add(new TextView(n->T("Invalid IP or hostname"), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0)))); - errorView_->SetTextColor(0xFF3030FF); - errorView_->SetVisibility(V_GONE); - progressView_ = parent->Add(new TextView(n->T("Validating address..."), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0)))); - progressView_->SetVisibility(V_GONE); + progressView_->SetVisibility(V_INVISIBLE); } void HostnameSelectScreen::SendEditKey(int keyCode, int flags) { @@ -2064,6 +2060,8 @@ void HostnameSelectScreen::ResolverThread() { } bool HostnameSelectScreen::CanComplete(DialogResult result) { + auto n = GetI18NCategory("Networking"); + if (result != DR_OK) return true; @@ -2095,12 +2093,12 @@ bool HostnameSelectScreen::CanComplete(DialogResult result) { lastResolvedResult_ = toResolveResult_; if (lastResolvedResult_) { - errorView_->SetVisibility(UI::V_GONE); + progressView_->SetVisibility(UI::V_INVISIBLE); } else { - errorView_->SetVisibility(UI::V_VISIBLE); + progressView_->SetText(n->T("Invalid IP or hostname")); + progressView_->SetTextColor(0xFF3030FF); + progressView_->SetVisibility(UI::V_VISIBLE); } - progressView_->SetVisibility(UI::V_GONE); - return true; } @@ -2112,8 +2110,9 @@ bool HostnameSelectScreen::CanComplete(DialogResult result) { toResolve_ = value; resolverCond_.notify_one(); + progressView_->SetText(n->T("Validating address...")); + progressView_->SetTextColor(0xFFFFFFFF); progressView_->SetVisibility(UI::V_VISIBLE); - errorView_->SetVisibility(UI::V_GONE); return false; } diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 4fee9a5603..743c8e562c 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -227,7 +227,6 @@ private: std::string *value_; UI::TextEdit *addrView_ = nullptr; - UI::TextView *errorView_ = nullptr; UI::TextView *progressView_ = nullptr; UI::LinearLayout *ipRows_ = nullptr; diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index d3a8b7fe7b..0ddec3aff7 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -80,6 +80,7 @@ namespace MainWindow { EnableMenuItem(menu, ID_EMULATION_STOP, menuEnable); EnableMenuItem(menu, ID_EMULATION_RESET, menuEnable); EnableMenuItem(menu, ID_EMULATION_SWITCH_UMD, umdSwitchEnable); + EnableMenuItem(menu, ID_EMULATION_CHAT, g_Config.bEnableNetworkChat ? menuInGameEnable : MF_GRAYED); EnableMenuItem(menu, ID_TOGGLE_BREAK, menuEnable); EnableMenuItem(menu, ID_DEBUG_LOADMAPFILE, menuEnable); EnableMenuItem(menu, ID_DEBUG_SAVEMAPFILE, menuEnable); @@ -651,10 +652,6 @@ namespace MainWindow { osm.ShowOnOff(gr->T("Cheats"), g_Config.bEnableCheats); break; case ID_EMULATION_CHAT: - if (!g_Config.bEnableNetworkChat) { - g_Config.bEnableNetworkChat = true; - UpdateCommands(); - } if (GetUIState() == UISTATE_INGAME) { NativeMessageReceived("chat screen", ""); } @@ -1391,7 +1388,7 @@ namespace MainWindow { static CoreState lastCoreState = CORE_BOOT_ERROR; HMENU menu = GetMenu(GetHWND()); - EnableMenuItem(menu, ID_DEBUG_LOG, !g_Config.bEnableLogging); + EnableMenuItem(menu, ID_DEBUG_LOG, g_Config.bEnableLogging ? MF_ENABLED : MF_GRAYED); SetIngameMenuItemStates(menu, GetUIState()); if (lastGlobalUIState == GetUIState() && lastCoreState == coreState) @@ -1402,7 +1399,6 @@ namespace MainWindow { bool isPaused = Core_IsStepping() && GetUIState() == UISTATE_INGAME; TranslateMenuItem(menu, ID_TOGGLE_BREAK, L"\tF8", isPaused ? "Run" : "Break"); - TranslateMenuItem(menu, ID_EMULATION_CHAT, L"\tCtrl+C", g_Config.bEnableNetworkChat ? "Open Chat" : "Enable Chat"); } void UpdateSwitchUMD() { diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 0069ae70d6..efa65b894c 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -661,7 +661,7 @@ BEGIN MENUITEM "", 0, MFT_SEPARATOR MENUITEM "Enable Cheats", ID_EMULATION_CHEATS MENUITEM "", 0, MFT_SEPARATOR - MENUITEM "Enable Chat", ID_EMULATION_CHAT + MENUITEM "Open Chat", ID_EMULATION_CHAT END POPUP "Help", ID_HELP_MENU