diff --git a/common/SettingsWrapper.cpp b/common/SettingsWrapper.cpp index 6656715066..a2f5b08090 100644 --- a/common/SettingsWrapper.cpp +++ b/common/SettingsWrapper.cpp @@ -67,9 +67,9 @@ void SettingsLoadWrapper::Entry(const char* section, const char* var, bool& valu value = m_si.GetBoolValue(section, var, defvalue); } -void SettingsLoadWrapper::Entry(const char* section, const char* var, double& value, const double defvalue /*= 0.0*/) +void SettingsLoadWrapper::Entry(const char* section, const char* var, float& value, const float defvalue /*= 0.0*/) { - value = m_si.GetDoubleValue(section, var, defvalue); + value = m_si.GetFloatValue(section, var, defvalue); } void SettingsLoadWrapper::Entry(const char* section, const char* var, std::string& value, const std::string& default_value /*= std::string()*/) @@ -141,9 +141,9 @@ void SettingsSaveWrapper::Entry(const char* section, const char* var, bool& valu m_si.SetBoolValue(section, var, value); } -void SettingsSaveWrapper::Entry(const char* section, const char* var, double& value, const double defvalue /*= 0.0*/) +void SettingsSaveWrapper::Entry(const char* section, const char* var, float& value, const float defvalue /*= 0.0*/) { - m_si.SetDoubleValue(section, var, value); + m_si.SetFloatValue(section, var, value); } void SettingsSaveWrapper::Entry(const char* section, const char* var, std::string& value, const std::string& default_value /*= std::string()*/) diff --git a/common/SettingsWrapper.h b/common/SettingsWrapper.h index 60710b7525..4294c24c44 100644 --- a/common/SettingsWrapper.h +++ b/common/SettingsWrapper.h @@ -29,7 +29,7 @@ public: virtual void Entry(const char* section, const char* var, int& value, const int defvalue = 0) = 0; virtual void Entry(const char* section, const char* var, uint& value, const uint defvalue = 0) = 0; virtual void Entry(const char* section, const char* var, bool& value, const bool defvalue = false) = 0; - virtual void Entry(const char* section, const char* var, double& value, const double defvalue = 0.0) = 0; + virtual void Entry(const char* section, const char* var, float& value, const float defvalue = 0.0) = 0; virtual void Entry(const char* section, const char* var, std::string& value, const std::string& default_value = std::string()) = 0; // This special form of Entry is provided for bitfields, which cannot be passed by reference. @@ -65,7 +65,7 @@ public: void Entry(const char* section, const char* var, int& value, const int defvalue = 0) override; void Entry(const char* section, const char* var, uint& value, const uint defvalue = 0) override; void Entry(const char* section, const char* var, bool& value, const bool defvalue = false) override; - void Entry(const char* section, const char* var, double& value, const double defvalue = 0.0) override; + void Entry(const char* section, const char* var, float& value, const float defvalue = 0.0) override; void Entry(const char* section, const char* var, std::string& value, const std::string& default_value = std::string()) override; bool EntryBitBool(const char* section, const char* var, bool value, const bool defvalue = false) override; @@ -86,7 +86,7 @@ public: void Entry(const char* section, const char* var, int& value, const int defvalue = 0) override; void Entry(const char* section, const char* var, uint& value, const uint defvalue = 0) override; void Entry(const char* section, const char* var, bool& value, const bool defvalue = false) override; - void Entry(const char* section, const char* var, double& value, const double defvalue = 0.0) override; + void Entry(const char* section, const char* var, float& value, const float defvalue = 0.0) override; void Entry(const char* section, const char* var, std::string& value, const std::string& default_value = std::string()) override; bool EntryBitBool(const char* section, const char* var, bool value, const bool defvalue = false) override; diff --git a/common/emitter/simd.cpp b/common/emitter/simd.cpp index 23f2d091d1..f1679e1d8d 100644 --- a/common/emitter/simd.cpp +++ b/common/emitter/simd.cpp @@ -38,6 +38,18 @@ const char* EnumToString(SSE_RoundMode sse) } } +SSE_MXCSR SSE_MXCSR::GetCurrent() +{ + SSE_MXCSR ret; + ret.bitmask = _mm_getcsr(); + return ret; +} + +void SSE_MXCSR::SetCurrent(const SSE_MXCSR& value) +{ + _mm_setcsr(value.bitmask); +} + SSE_RoundMode SSE_MXCSR::GetRoundMode() const { return (SSE_RoundMode)RoundingControl; diff --git a/common/emitter/tools.h b/common/emitter/tools.h index b950d3807e..d251ee1e78 100644 --- a/common/emitter/tools.h +++ b/common/emitter/tools.h @@ -185,6 +185,9 @@ union SSE_MXCSR FlushToZero : 1; }; + static SSE_MXCSR GetCurrent(); + static void SetCurrent(const SSE_MXCSR& value); + SSE_RoundMode GetRoundMode() const; SSE_MXCSR& SetRoundMode(SSE_RoundMode mode); SSE_MXCSR& ClearExceptionFlags(); diff --git a/pcsx2/Config.h b/pcsx2/Config.h index c5ad9c2713..f5194c2aa6 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -212,6 +212,7 @@ ImplementEnumOperators(SpeedhackId); //------------ DEFAULT sseMXCSR VALUES --------------- #define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop" #define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop" +#define SYSTEM_sseMXCSR 0x1f80 // -------------------------------------------------------------------------------------- // TraceFiltersEE @@ -427,6 +428,9 @@ struct Pcsx2Config static const char* GetRendererName(GSRendererType type); + static constexpr float DEFAULT_FRAME_RATE_NTSC = 59.94f; + static constexpr float DEFAULT_FRAME_RATE_PAL = 50.00f; + union { u64 bitset; @@ -503,24 +507,24 @@ struct Pcsx2Config VsyncMode VsyncEnable{VsyncMode::Off}; - double LimitScalar{1.0}; - double FramerateNTSC{59.94}; - double FrameratePAL{50.00}; + float LimitScalar{1.0f}; + float FramerateNTSC{DEFAULT_FRAME_RATE_NTSC}; + float FrameratePAL{DEFAULT_FRAME_RATE_PAL}; AspectRatioType AspectRatio{AspectRatioType::RAuto4_3_3_2}; FMVAspectRatioSwitchType FMVAspectRatioSwitch{FMVAspectRatioSwitchType::Off}; GSInterlaceMode InterlaceMode{GSInterlaceMode::Automatic}; - double Zoom{100.0}; - double StretchY{100.0}; + float Zoom{100.0f}; + float StretchY{100.0f}; #ifndef PCSX2_CORE - double OffsetX{0.0}; - double OffsetY{0.0}; + float OffsetX{0.0f}; + float OffsetY{0.0f}; #else int Crop[4]{}; #endif - double OsdScale{100.0}; + float OsdScale{100.0}; GSRendererType Renderer{GSRendererType::Auto}; uint UpscaleMultiplier{1}; @@ -623,14 +627,14 @@ struct Pcsx2Config s32 SpeakerConfiguration{0}; s32 DplDecodingLevel{0}; - double VolumeAdjustC{ 0.0f }; - double VolumeAdjustFL{ 0.0f }; - double VolumeAdjustFR{ 0.0f }; - double VolumeAdjustBL{ 0.0f }; - double VolumeAdjustBR{ 0.0f }; - double VolumeAdjustSL{ 0.0f }; - double VolumeAdjustSR{ 0.0f }; - double VolumeAdjustLFE{ 0.0f }; + float VolumeAdjustC{ 0.0f }; + float VolumeAdjustFL{ 0.0f }; + float VolumeAdjustFR{ 0.0f }; + float VolumeAdjustBL{ 0.0f }; + float VolumeAdjustBR{ 0.0f }; + float VolumeAdjustSL{ 0.0f }; + float VolumeAdjustSR{ 0.0f }; + float VolumeAdjustLFE{ 0.0f }; std::string OutputModule; @@ -890,9 +894,9 @@ struct Pcsx2Config // ------------------------------------------------------------------------ struct FramerateOptions { - double NominalScalar{1.0}; - double TurboScalar{2.0}; - double SlomoScalar{0.5}; + float NominalScalar{1.0f}; + float TurboScalar{2.0f}; + float SlomoScalar{0.5f}; void LoadSave(SettingsWrapper& wrap); void SanityCheck(); diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index c7387a4180..b581a3fdec 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -353,7 +353,7 @@ double GetVerticalFrequency() static double AdjustToHostRefreshRate(double vertical_frequency, double frame_limit) { - if (!EmuConfig.GS.SyncToHostRefreshRate || EmuConfig.GS.LimitScalar != 1.0) + if (!EmuConfig.GS.SyncToHostRefreshRate || EmuConfig.GS.LimitScalar != 1.0f) { SPU2SetDeviceSampleRateMultiplier(1.0); s_use_vsync_for_timing = false; @@ -413,7 +413,7 @@ u32 UpdateVSyncRate() break; case GS_VideoMode::PAL: case GS_VideoMode::DVD_PAL: - custom = (EmuConfig.GS.FrameratePAL != 50.0); + custom = (EmuConfig.GS.FrameratePAL != Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL); if (gsIsInterlaced) total_scanlines = SCANLINES_TOTAL_PAL_I; else @@ -421,7 +421,7 @@ u32 UpdateVSyncRate() break; case GS_VideoMode::NTSC: case GS_VideoMode::DVD_NTSC: - custom = (EmuConfig.GS.FramerateNTSC != 59.94); + custom = (EmuConfig.GS.FramerateNTSC != Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_NTSC); if (gsIsInterlaced) total_scanlines = SCANLINES_TOTAL_NTSC_I; else @@ -564,7 +564,7 @@ static __fi void frameLimitUpdateCore() static __fi void frameLimit() { // Framelimiter off in settings? Framelimiter go brrr. - if (EmuConfig.GS.LimitScalar == 0.0 || s_use_vsync_for_timing) + if (EmuConfig.GS.LimitScalar == 0.0f || s_use_vsync_for_timing) { frameLimitUpdateCore(); return; diff --git a/pcsx2/Frontend/ImGuiManager.cpp b/pcsx2/Frontend/ImGuiManager.cpp index e8df826ad0..81bd4a9224 100644 --- a/pcsx2/Frontend/ImGuiManager.cpp +++ b/pcsx2/Frontend/ImGuiManager.cpp @@ -95,7 +95,7 @@ bool ImGuiManager::Initialize() return false; } - s_global_scale = std::max(1.0f, g_host_display->GetWindowScale() * static_cast(EmuConfig.GS.OsdScale / 100.0)); + s_global_scale = std::max(1.0f, g_host_display->GetWindowScale() * (EmuConfig.GS.OsdScale / 100.0f)); ImGui::CreateContext(); @@ -183,7 +183,7 @@ void ImGuiManager::WindowResized() void ImGuiManager::UpdateScale() { const float window_scale = g_host_display ? g_host_display->GetWindowScale() : 1.0f; - const float scale = std::max(window_scale * static_cast(EmuConfig.GS.OsdScale / 100.0), 1.0f); + const float scale = std::max(window_scale * (EmuConfig.GS.OsdScale / 100.0f), 1.0f); #ifdef PCSX2_CORE if (scale == s_global_scale && (!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale())) @@ -728,10 +728,10 @@ void ImGuiManager::DrawPerformanceOverlay() fmt::format_to(std::back_inserter(text), "{}{}%", first ? "" : " | ", static_cast(std::round(speed))); // We read the main config here, since MTGS doesn't get updated with speed toggles. - if (EmuConfig.GS.LimitScalar == 0.0) + if (EmuConfig.GS.LimitScalar == 0.0f) text += " (Max)"; else - fmt::format_to(std::back_inserter(text), " ({:.0f}%)", EmuConfig.GS.LimitScalar * 100.0); + fmt::format_to(std::back_inserter(text), " ({:.0f}%)", EmuConfig.GS.LimitScalar * 100.0f); } if (!text.empty()) { diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index ac980cfb69..9430602c83 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -63,7 +63,7 @@ void gsUpdateFrequency(Pcsx2Config& config) config.GS.LimitScalar = config.Framerate.TurboScalar; break; case LimiterModeType::Unlimited: - config.GS.LimitScalar = 0.0; + config.GS.LimitScalar = 0.0f; break; default: pxAssert("Unknown framelimiter mode!"); @@ -71,7 +71,7 @@ void gsUpdateFrequency(Pcsx2Config& config) } else { - config.GS.LimitScalar = 0.0; + config.GS.LimitScalar = 0.0f; } UpdateVSyncRate(); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 2011b25c6f..5394f6db92 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -511,7 +511,7 @@ void Pcsx2Config::GSOptions::ReloadIniSettings() #define GSSettingIntEx(var, name) var = theApp.GetConfigI(name) #define GSSettingBool(var) var = theApp.GetConfigB(#var) #define GSSettingBoolEx(var, name) var = theApp.GetConfigB(name) -#define GSSettingFloat(var) var = static_cast(theApp.GetConfigI(#var)) +#define GSSettingFloat(var) var = static_cast(theApp.GetConfigI(#var)) #define GSSettingIntEnumEx(var, name) var = static_cast(theApp.GetConfigI(name)) #define GSSettingString(var) var = theApp.GetConfigS(#var) #define GSSettingStringEx(var, name) var = theApp.GetConfigS(name) @@ -680,7 +680,7 @@ bool Pcsx2Config::GSOptions::UseHardwareRenderer() const VsyncMode Pcsx2Config::GetEffectiveVsyncMode() const { - if (GS.LimitScalar != 1.0) + if (GS.LimitScalar != 1.0f) { Console.WriteLn("Vsync is OFF"); return VsyncMode::Off; @@ -1002,9 +1002,9 @@ void Pcsx2Config::FramerateOptions::SanityCheck() { // Ensure Conformation of various options... - NominalScalar = std::clamp(NominalScalar, 0.05, 10.0); - TurboScalar = std::clamp(TurboScalar, 0.05, 10.0); - SlomoScalar = std::clamp(SlomoScalar, 0.05, 10.0); + NominalScalar = std::clamp(NominalScalar, 0.05f, 10.0f); + TurboScalar = std::clamp(TurboScalar, 0.05f, 10.0f); + SlomoScalar = std::clamp(SlomoScalar, 0.05f, 10.0f); } void Pcsx2Config::FramerateOptions::LoadSave(SettingsWrapper& wrap) @@ -1049,6 +1049,11 @@ Pcsx2Config::Pcsx2Config() void Pcsx2Config::LoadSave(SettingsWrapper& wrap) { + // Switch the rounding mode back to the system default for loading settings. + // That way, we'll get exactly the same values as what we loaded when we first started. + const SSE_MXCSR prev_mxcsr(SSE_MXCSR::GetCurrent()); + SSE_MXCSR::SetCurrent(SSE_MXCSR{SYSTEM_sseMXCSR}); + SettingsWrapSection("EmuCore"); SettingsWrapBitBool(CdvdVerboseReads); @@ -1114,6 +1119,8 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap) { CurrentAspectRatio = GS.AspectRatio; } + + SSE_MXCSR::SetCurrent(prev_mxcsr); } void Pcsx2Config::LoadSaveMemcards(SettingsWrapper& wrap) diff --git a/pcsx2/gui/IniInterface.cpp b/pcsx2/gui/IniInterface.cpp index 2ed8ffaec8..ef60907567 100644 --- a/pcsx2/gui/IniInterface.cpp +++ b/pcsx2/gui/IniInterface.cpp @@ -194,15 +194,17 @@ int IniLoader::EntryBitfield(const wxString& var, int value, const int defvalue) return result; } -void IniLoader::Entry(const wxString& var, double& value, const double defvalue) +void IniLoader::Entry(const wxString& var, float& value, const float defvalue) { - auto readval = wxString::FromCDouble(value); + auto readval = wxString::FromCDouble(static_cast(value)); if (m_Config) m_Config->Read(var, &readval); - if (!readval.ToCDouble(&value)) - value = 0.0; + double dvalue; + if (!readval.ToCDouble(&dvalue)) + dvalue = 0.0; + value = static_cast(dvalue); } void IniLoader::Entry(const wxString& var, wxPoint& value, const wxPoint defvalue) @@ -380,12 +382,12 @@ int IniSaver::EntryBitfield(const wxString& var, int value, const int defvalue) return value; } -void IniSaver::Entry(const wxString& var, double& value, const double defvalue) +void IniSaver::Entry(const wxString& var, float& value, const float defvalue) { if (!m_Config) return; - m_Config->Write(var, wxString::FromCDouble(value)); + m_Config->Write(var, wxString::FromCDouble(static_cast(value))); } void IniSaver::Entry(const wxString& var, wxPoint& value, const wxPoint defvalue) diff --git a/pcsx2/gui/IniInterface.h b/pcsx2/gui/IniInterface.h index 5c43208141..f1baa45e33 100644 --- a/pcsx2/gui/IniInterface.h +++ b/pcsx2/gui/IniInterface.h @@ -59,7 +59,7 @@ public: virtual void Entry(const wxString& var, int& value, const int defvalue = 0) = 0; virtual void Entry(const wxString& var, uint& value, const uint defvalue = 0) = 0; virtual void Entry(const wxString& var, bool& value, const bool defvalue = false) = 0; - virtual void Entry(const wxString& var, double& value, const double defvalue = 0.0) = 0; + virtual void Entry(const wxString& var, float& value, const float defvalue = 0.0) = 0; virtual void Entry(const wxString& var, std::string& value, const std::string& default_value = std::string()) = 0; // This special form of Entry is provided for bitfields, which cannot be passed by reference. @@ -124,7 +124,7 @@ public: void Entry(const wxString& var, int& value, const int defvalue = 0) override; void Entry(const wxString& var, uint& value, const uint defvalue = 0) override; void Entry(const wxString& var, bool& value, const bool defvalue = false) override; - void Entry(const wxString& var, double& value, const double defvalue = 0.0) override; + void Entry(const wxString& var, float& value, const float defvalue = 0.0) override; void Entry(const wxString& var, std::string& value, const std::string& default_value = std::string()) override; bool EntryBitBool(const wxString& var, bool value, const bool defvalue = false) override; @@ -164,7 +164,7 @@ public: void Entry(const wxString& var, int& value, const int defvalue = 0) override; void Entry(const wxString& var, uint& value, const uint defvalue = 0) override; void Entry(const wxString& var, bool& value, const bool defvalue = false) override; - void Entry(const wxString& var, double& value, const double defvalue = 0.0) override; + void Entry(const wxString& var, float& value, const float defvalue = 0.0) override; void Entry(const wxString& var, std::string& value, const std::string& default_value = std::string()) override; bool EntryBitBool(const wxString& var, bool value, const bool defvalue = false) override;