diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 816811d4cb..0df5c4426a 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -173,6 +173,13 @@ void DisplayMessage(const std::string& message, int time_in_ms) if (!IsRunning()) return; + // Actually displaying non-ASCII could cause things to go pear-shaped + for (const char& c : message) + { + if (!std::isprint(c)) + return; + } + OSD::AddMessage(message, time_in_ms); Host_UpdateTitle(message); } diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 2253297bb6..6394714a3d 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1444,16 +1444,14 @@ void CFrame::ParseHotkeys() if (IsHotkey(HK_INCREASE_IR)) { + OSDChoice = 1; ++g_Config.iEFBScale; - OSDPrintInternalResolution(); } if (IsHotkey(HK_DECREASE_IR)) { + OSDChoice = 1; if (--g_Config.iEFBScale < SCALE_AUTO) - { g_Config.iEFBScale = SCALE_AUTO; - } - OSDPrintInternalResolution(); } if (IsHotkey(HK_TOGGLE_CROP)) { @@ -1461,26 +1459,28 @@ void CFrame::ParseHotkeys() } if (IsHotkey(HK_TOGGLE_AR)) { + OSDChoice = 2; // Toggle aspect ratio g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; - OSDPrintAspectRatio(); } if (IsHotkey(HK_TOGGLE_EFBCOPIES)) { + OSDChoice = 3; // Toggle EFB copies between EFB2RAM and EFB2Texture g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam; - OSDPrintEFB(); } if (IsHotkey(HK_TOGGLE_FOG)) { + OSDChoice = 4; g_Config.bDisableFog = !g_Config.bDisableFog; - OSDPrintFog(); } if (IsHotkey(HK_TOGGLE_TEXTURES)) g_Config.bHiresTextures = !g_Config.bHiresTextures; Core::SetIsThrottlerTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true)); if (IsHotkey(HK_DECREASE_EMULATION_SPEED)) { + OSDChoice = 5; + if (SConfig::GetInstance().m_EmulationSpeed <= 0.0f) SConfig::GetInstance().m_EmulationSpeed = 1.0f; else if (SConfig::GetInstance().m_EmulationSpeed >= 0.2f) @@ -1491,19 +1491,17 @@ void CFrame::ParseHotkeys() if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f && SConfig::GetInstance().m_EmulationSpeed <= 1.05f) SConfig::GetInstance().m_EmulationSpeed = 1.0f; - - OSDPrintEmulationSpeed(); } if (IsHotkey(HK_INCREASE_EMULATION_SPEED)) { + OSDChoice = 5; + if (SConfig::GetInstance().m_EmulationSpeed > 0.0f) SConfig::GetInstance().m_EmulationSpeed += 0.1f; if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f && SConfig::GetInstance().m_EmulationSpeed <= 1.05f) SConfig::GetInstance().m_EmulationSpeed = 1.0f; - - OSDPrintEmulationSpeed(); } if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED)) { @@ -1718,79 +1716,3 @@ void CFrame::HandleSignal(wxTimerEvent& event) return; Close(); } - -void CFrame::OSDPrintInternalResolution() -{ - std::string text; - switch (g_Config.iEFBScale) - { - case SCALE_AUTO: - text = "Auto (fractional)"; - break; - case SCALE_AUTO_INTEGRAL: - text = "Auto (integral)"; - break; - case SCALE_1X: - text = "Native"; - break; - case SCALE_1_5X: - text = "1.5x"; - break; - case SCALE_2X: - text = "2x"; - break; - case SCALE_2_5X: - text = "2.5x"; - break; - default: - text = StringFromFormat("%dx", g_Config.iEFBScale - 3); - break; - } - - OSD::AddMessage("Internal Resolution: " + text); -} - -void CFrame::OSDPrintAspectRatio() -{ - std::string text; - switch (g_Config.iAspectRatio) - { - case ASPECT_AUTO: - text = "Auto"; - break; - case ASPECT_STRETCH: - text = "Stretch"; - break; - case ASPECT_ANALOG: - text = "Force 4:3"; - break; - case ASPECT_ANALOG_WIDE: - text = "Force 16:9"; - break; - } - - OSD::AddMessage("Aspect Ratio: " + text + (g_Config.bCrop ? " (crop)" : "")); -} - -void CFrame::OSDPrintEFB() -{ - OSD::AddMessage(std::string("Copy EFB: ") + - (g_Config.bSkipEFBCopyToRam ? "to Texture" : "to RAM")); -} - -void CFrame::OSDPrintFog() -{ - OSD::AddMessage(std::string("Fog: ") + (g_Config.bDisableFog ? "Disabled" : "Enabled")); -} - -void CFrame::OSDPrintEmulationSpeed() -{ - std::string text = "Speed Limit: "; - - if (SConfig::GetInstance().m_EmulationSpeed <= 0) - text += "Unlimited"; - else - text += StringFromFormat("%li%%", std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)); - - OSD::AddMessage(text); -} diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 3e03ea0373..6a24e3768f 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -347,13 +347,6 @@ private: bool InitControllers(); - // OSD - void OSDPrintInternalResolution(); - void OSDPrintAspectRatio(); - void OSDPrintEFB(); - void OSDPrintFog(); - void OSDPrintEmulationSpeed(); - // Event table DECLARE_EVENT_TABLE(); }; diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp index d0f6f24825..62997cd150 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp @@ -21,24 +21,18 @@ static std::multimap s_callbacks; static std::multimap s_messages; static std::mutex s_messages_mutex; -static std::string CleanMessage(std::string message) -{ - std::replace_if(message.begin(), message.end(), [](char c) { return !std::isprint(c); }, '?'); - return message; -} - void AddTypedMessage(MessageType type, const std::string& message, u32 ms, u32 rgba) { std::lock_guard lock(s_messages_mutex); s_messages.erase(type); - s_messages.emplace(type, Message(CleanMessage(message), Common::Timer::GetTimeMs() + ms, rgba)); + s_messages.emplace(type, Message(message, Common::Timer::GetTimeMs() + ms, rgba)); } void AddMessage(const std::string& message, u32 ms, u32 rgba) { std::lock_guard lock(s_messages_mutex); s_messages.emplace(MessageType::Typeless, - Message(CleanMessage(message), Common::Timer::GetTimeMs() + ms, rgba)); + Message(message, Common::Timer::GetTimeMs() + ms, rgba)); } void DrawMessage(const Message& msg, int top, int left, int time_left) @@ -58,7 +52,7 @@ void DrawMessages() std::lock_guard lock(s_messages_mutex); u32 now = Common::Timer::GetTimeMs(); - int left = 20, top = 20; + int left = 20, top = 35; auto it = s_messages.begin(); while (it != s_messages.end()) diff --git a/Source/Core/VideoCommon/OnScreenDisplay.h b/Source/Core/VideoCommon/OnScreenDisplay.h index cf8d66db72..a05f4058ef 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.h +++ b/Source/Core/VideoCommon/OnScreenDisplay.h @@ -22,14 +22,6 @@ struct Message enum class MessageType { - FPS, - FrameCount, - RTC, - - MovieInputCount, - MovieLag, - MovieInput, - NetPlayPing, NetPlayBuffer, diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 519e4fcbc6..92817805e3 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -34,7 +34,6 @@ #include "Core/Host.h" #include "Core/Movie.h" -#include "OnScreenDisplay.h" #include "VideoCommon/AVIDump.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/CPMemory.h" @@ -43,6 +42,7 @@ #include "VideoCommon/FPSCounter.h" #include "VideoCommon/FramebufferManagerBase.h" #include "VideoCommon/ImageWrite.h" +#include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/PostProcessing.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" @@ -52,6 +52,8 @@ // TODO: Move these out of here. int frameCount; +int OSDChoice; +static int OSDTime; std::unique_ptr g_renderer; @@ -104,6 +106,9 @@ Renderer::Renderer() { UpdateActiveConfig(); TextureCacheBase::OnConfigChanged(g_ActiveConfig); + + OSDChoice = 0; + OSDTime = 0; } Renderer::~Renderer() @@ -305,46 +310,146 @@ void Renderer::SetScreenshot(const std::string& filename) s_bScreenshot = true; } +// Create On-Screen-Messages void Renderer::DrawDebugText() { - auto draw_text = [](OSD::MessageType type, const std::string& message) { - OSD::AddTypedMessage(type, message, OSD::Duration::SHORT, OSD::Color::CYAN); - }; + std::string final_yellow, final_cyan; - if (g_ActiveConfig.bShowFPS) + if (g_ActiveConfig.bShowFPS || SConfig::GetInstance().m_ShowFrameCount) { - draw_text(OSD::MessageType::FPS, - StringFromFormat("FPS: %u", g_renderer->m_fps_counter.GetFPS())); - } + if (g_ActiveConfig.bShowFPS) + final_cyan += StringFromFormat("FPS: %u", g_renderer->m_fps_counter.GetFPS()); - if (SConfig::GetInstance().m_ShowFrameCount) - { - draw_text(OSD::MessageType::FrameCount, - StringFromFormat("Frame: %" PRIx64, Movie::GetCurrentFrame())); - - if (Movie::IsPlayingInput()) + if (g_ActiveConfig.bShowFPS && SConfig::GetInstance().m_ShowFrameCount) + final_cyan += " - "; + if (SConfig::GetInstance().m_ShowFrameCount) { - draw_text(OSD::MessageType::MovieInputCount, - StringFromFormat("Input: %" PRIx64 " / %" PRIx64, Movie::GetCurrentInputCount(), - Movie::GetTotalInputCount())); + final_cyan += StringFromFormat("Frame: %llu", (unsigned long long)Movie::GetCurrentFrame()); + if (Movie::IsPlayingInput()) + final_cyan += StringFromFormat("\nInput: %llu / %llu", + (unsigned long long)Movie::GetCurrentInputCount(), + (unsigned long long)Movie::GetTotalInputCount()); } + + final_cyan += "\n"; + final_yellow += "\n"; } if (SConfig::GetInstance().m_ShowLag) { - draw_text(OSD::MessageType::MovieLag, - StringFromFormat("Lag: %" PRIu64, Movie::GetCurrentLagCount())); + final_cyan += StringFromFormat("Lag: %" PRIu64 "\n", Movie::GetCurrentLagCount()); + final_yellow += "\n"; } if (SConfig::GetInstance().m_ShowInputDisplay) { - draw_text(OSD::MessageType::MovieInput, Movie::GetInputDisplay()); + final_cyan += Movie::GetInputDisplay(); + final_yellow += "\n"; } if (SConfig::GetInstance().m_ShowRTC) { - draw_text(OSD::MessageType::RTC, Movie::GetRTCDisplay()); + final_cyan += Movie::GetRTCDisplay(); + final_yellow += "\n"; } + + // OSD Menu messages + if (OSDChoice > 0) + { + OSDTime = Common::Timer::GetTimeMs() + 3000; + OSDChoice = -OSDChoice; + } + + if ((u32)OSDTime > Common::Timer::GetTimeMs()) + { + std::string res_text; + switch (g_ActiveConfig.iEFBScale) + { + case SCALE_AUTO: + res_text = "Auto (fractional)"; + break; + case SCALE_AUTO_INTEGRAL: + res_text = "Auto (integral)"; + break; + case SCALE_1X: + res_text = "Native"; + break; + case SCALE_1_5X: + res_text = "1.5x"; + break; + case SCALE_2X: + res_text = "2x"; + break; + case SCALE_2_5X: + res_text = "2.5x"; + break; + default: + res_text = StringFromFormat("%dx", g_ActiveConfig.iEFBScale - 3); + break; + } + const char* ar_text = ""; + switch (g_ActiveConfig.iAspectRatio) + { + case ASPECT_AUTO: + ar_text = "Auto"; + break; + case ASPECT_STRETCH: + ar_text = "Stretch"; + break; + case ASPECT_ANALOG: + ar_text = "Force 4:3"; + break; + case ASPECT_ANALOG_WIDE: + ar_text = "Force 16:9"; + } + + const char* const efbcopy_text = g_ActiveConfig.bSkipEFBCopyToRam ? "to Texture" : "to RAM"; + + // The rows + const std::string lines[] = { + std::string("Internal Resolution: ") + res_text, + std::string("Aspect Ratio: ") + ar_text + (g_ActiveConfig.bCrop ? " (crop)" : ""), + std::string("Copy EFB: ") + efbcopy_text, + std::string("Fog: ") + (g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled"), + SConfig::GetInstance().m_EmulationSpeed <= 0 ? + "Speed Limit: Unlimited" : + StringFromFormat("Speed Limit: %li%%", + std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)), + }; + + enum + { + lines_count = sizeof(lines) / sizeof(*lines) + }; + + // The latest changed setting in yellow + for (int i = 0; i != lines_count; ++i) + { + if (OSDChoice == -i - 1) + final_yellow += lines[i]; + final_yellow += '\n'; + } + + // The other settings in cyan + for (int i = 0; i != lines_count; ++i) + { + if (OSDChoice != -i - 1) + final_cyan += lines[i]; + final_cyan += '\n'; + } + } + + final_cyan += Common::Profiler::ToString(); + + if (g_ActiveConfig.bOverlayStats) + final_cyan += Statistics::ToString(); + + if (g_ActiveConfig.bOverlayProjStats) + final_cyan += Statistics::ToStringProj(); + + // and then the text + g_renderer->RenderText(final_cyan, 20, 20, 0xFF00FFFF); + g_renderer->RenderText(final_yellow, 20, 20, 0xFFFFFF00); } void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height) diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 5c6a98dd21..8b3495b82e 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -39,6 +39,7 @@ struct EfbPokeData // TODO: Move these out of here. extern int frameCount; +extern int OSDChoice; // Renderer really isn't a very good name for this class - it's more like "Misc". // The long term goal is to get rid of this class and replace it with others that make