From ff82232e27b4c2f089e2c4f46a034714df1d944a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 28 Dec 2022 14:44:34 +1000 Subject: [PATCH] Config: Add separate VU0/VU1 round/clamp mode options --- pcsx2-qt/Settings/AdvancedSettingsWidget.cpp | 75 ++++++---- pcsx2-qt/Settings/AdvancedSettingsWidget.h | 6 +- pcsx2-qt/Settings/AdvancedSettingsWidget.ui | 144 +++++++++++++------ pcsx2/Config.h | 36 ++--- pcsx2/Docs/gamedb-schema.json | 22 +++ pcsx2/Frontend/FullscreenUI.cpp | 74 +++++----- pcsx2/Frontend/ImGuiOverlays.cpp | 2 +- pcsx2/GameDatabase.cpp | 85 +++++++++-- pcsx2/GameDatabase.h | 6 +- pcsx2/Pcsx2Config.cpp | 71 ++++++--- pcsx2/System.cpp | 8 +- pcsx2/System.h | 4 +- pcsx2/VMManager.cpp | 13 +- pcsx2/VU0microInterp.cpp | 2 +- pcsx2/VU1microInterp.cpp | 2 +- pcsx2/VUflags.cpp | 2 +- pcsx2/VUops.cpp | 2 +- pcsx2/x86/microVU_Clamp.inl | 6 +- pcsx2/x86/microVU_Compile.inl | 2 +- pcsx2/x86/microVU_Execute.inl | 4 +- pcsx2/x86/microVU_Lower.inl | 2 +- pcsx2/x86/microVU_Misc.h | 2 +- pcsx2/x86/microVU_Upper.inl | 2 +- 23 files changed, 386 insertions(+), 186 deletions(-) diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp index b035723862..4e511d1154 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp @@ -25,7 +25,8 @@ #include "SettingsDialog.h" AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* parent) - : QWidget(parent), m_dialog(dialog) + : QWidget(parent) + , m_dialog(dialog) { SettingsInterface* sif = dialog->getSettingsInterface(); @@ -42,16 +43,20 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3); - SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vuRoundingMode, "EmuCore/CPU", "VU.Roundmode", 3); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu0RoundingMode, "EmuCore/CPU", "VU0.Roundmode", 3); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu1RoundingMode, "EmuCore/CPU", "VU1.Roundmode", 3); if (m_dialog->isPerGameSettings()) { - m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(false)))); - m_ui.vuClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.vuClampMode->itemText(getGlobalClampingModeIndex(true)))); + m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(-1)))); + m_ui.vu0ClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.vu0ClampMode->itemText(getGlobalClampingModeIndex(0)))); + m_ui.vu1ClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.vu1ClampMode->itemText(getGlobalClampingModeIndex(1)))); } - m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(false)); - m_ui.vuClampMode->setCurrentIndex(getClampingModeIndex(true)); - connect(m_ui.eeClampMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(false, index); }); - connect(m_ui.vuClampMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(true, index); }); + m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(-1)); + m_ui.vu0ClampMode->setCurrentIndex(getClampingModeIndex(0)); + m_ui.vu1ClampMode->setCurrentIndex(getClampingModeIndex(1)); + connect(m_ui.eeClampMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(-1, index); }); + connect(m_ui.vu0ClampMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(0, index); }); + connect(m_ui.vu1ClampMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(1, index); }); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true); @@ -60,7 +65,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f); SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f); - + dialog->registerWidgetHelp(m_ui.eeRoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr("")); dialog->registerWidgetHelp(m_ui.eeClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("")); @@ -71,8 +76,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* dialog->registerWidgetHelp(m_ui.eeWaitLoopDetection, tr("Wait Loop Detection"), tr("Checked"), tr("Moderate speedup for some games, with no known side effects.")); - dialog->registerWidgetHelp(m_ui.eeCache, tr("Enable Cache (Slow)"), tr("Unchecked"), - tr("Interpreter only, provided for diagnostic.")); + dialog->registerWidgetHelp(m_ui.eeCache, tr("Enable Cache (Slow)"), tr("Unchecked"), tr("Interpreter only, provided for diagnostic.")); dialog->registerWidgetHelp(m_ui.eeINTCSpinDetection, tr("INTC Spin Detection"), tr("Checked"), tr("Huge speedup for some games, with almost no compatibility side effects.")); @@ -80,18 +84,18 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* dialog->registerWidgetHelp(m_ui.eeFastmem, tr("Enable Fast Memory Access"), tr("Checked"), tr("Uses backpatching to avoid register flushing on every memory access.")); - dialog->registerWidgetHelp(m_ui.vuRoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr("")); + dialog->registerWidgetHelp(m_ui.vu0RoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr("")); + dialog->registerWidgetHelp(m_ui.vu1RoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr("")); - dialog->registerWidgetHelp(m_ui.vuClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("")); + dialog->registerWidgetHelp(m_ui.vu0ClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("")); + dialog->registerWidgetHelp(m_ui.vu1ClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("")); - dialog->registerWidgetHelp(m_ui.vu0Recompiler, tr("Enable VU0 Recompiler (Micro Mode)"), tr("Checked"), - tr("Enables VU0 Recompiler.")); + dialog->registerWidgetHelp(m_ui.vu0Recompiler, tr("Enable VU0 Recompiler (Micro Mode)"), tr("Checked"), tr("Enables VU0 Recompiler.")); - dialog->registerWidgetHelp(m_ui.vu1Recompiler, tr("Enable VU1 Recompiler"), tr("Checked"), - tr("Enables VU1 Recompiler.")); + dialog->registerWidgetHelp(m_ui.vu1Recompiler, tr("Enable VU1 Recompiler"), tr("Checked"), tr("Enables VU1 Recompiler.")); - dialog->registerWidgetHelp(m_ui.vuFlagHack, tr("mVU Flag Hack"), tr("Checked"), - tr("Good speedup and high compatibility, may cause graphical errors.")); + dialog->registerWidgetHelp( + m_ui.vuFlagHack, tr("mVU Flag Hack"), tr("Checked"), tr("Good speedup and high compatibility, may cause graphical errors.")); dialog->registerWidgetHelp(m_ui.iopRecompiler, tr("Enable Recompiler"), tr("Checked"), tr("Performs just-in-time binary translation of 32-bit MIPS-I machine code to x86.")); @@ -105,30 +109,36 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget* AdvancedSettingsWidget::~AdvancedSettingsWidget() = default; -int AdvancedSettingsWidget::getGlobalClampingModeIndex(bool vu) const +int AdvancedSettingsWidget::getGlobalClampingModeIndex(int vunum) const { - if (Host::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", false)) + if (Host::GetBaseBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0SignOverflow" : "vu1SignOverflow") : "fpuFullMode"), false)) return 3; - if (Host::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", false)) + if (Host::GetBaseBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0ExtraOverflow" : "vu1ExtraOverflow") : "fpuExtraOverflow"), false)) return 2; - if (Host::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", true)) + if (Host::GetBaseBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0Overflow" : "vu1Overflow") : "fpuOverflow"), true)) return 1; return 0; } -int AdvancedSettingsWidget::getClampingModeIndex(bool vu) const +int AdvancedSettingsWidget::getClampingModeIndex(int vunum) const { // This is so messy... maybe we should just make the mode an int in the settings too... const bool base = m_dialog->isPerGameSettings() ? 1 : 0; std::optional default_false = m_dialog->isPerGameSettings() ? std::nullopt : std::optional(false); std::optional default_true = m_dialog->isPerGameSettings() ? std::nullopt : std::optional(true); - std::optional third = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", default_false); - std::optional second = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", default_false); - std::optional first = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", default_true); + std::optional third = m_dialog->getBoolValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0SignOverflow" : "vu1SignOverflow") : "fpuFullMode"), default_false); + std::optional second = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", + (vunum >= 0 ? ((vunum == 0) ? "vu0ExtraOverflow" : "vu1ExtraOverflow") : "fpuExtraOverflow"), default_false); + std::optional first = m_dialog->getBoolValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0Overflow" : "vu1Overflow") : "fpuOverflow"), default_true); if (third.has_value() && third.value()) return base + 3; @@ -142,7 +152,7 @@ int AdvancedSettingsWidget::getClampingModeIndex(bool vu) const return 0; // no per game override } -void AdvancedSettingsWidget::setClampingMode(bool vu, int index) +void AdvancedSettingsWidget::setClampingMode(int vunum, int index) { std::optional first, second, third; @@ -154,7 +164,10 @@ void AdvancedSettingsWidget::setClampingMode(bool vu, int index) first = (index >= (base + 1)); } - m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", third); - m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", second); - m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", first); + m_dialog->setBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0SignOverflow" : "vu1SignOverflow") : "fpuFullMode"), third); + m_dialog->setBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0ExtraOverflow" : "vu1ExtraOverflow") : "fpuExtraOverflow"), second); + m_dialog->setBoolSettingValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0Overflow" : "vu1Overflow") : "fpuOverflow"), first); } diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.h b/pcsx2-qt/Settings/AdvancedSettingsWidget.h index 40e1115d22..1677f12c88 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.h +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.h @@ -30,9 +30,9 @@ public: ~AdvancedSettingsWidget(); private: - int getGlobalClampingModeIndex(bool vu) const; - int getClampingModeIndex(bool vu) const; - void setClampingMode(bool vu, int index); + int getGlobalClampingModeIndex(int vunum) const; + int getClampingModeIndex(int vunum) const; + void setClampingMode(int vunum, int index); SettingsDialog* m_dialog; diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui index 78113ece47..08ea3001d8 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui @@ -6,8 +6,8 @@ 0 0 - 628 - 375 + 809 + 647 @@ -36,8 +36,8 @@ 0 0 - 609 - 569 + 807 + 645 @@ -176,47 +176,15 @@ Vector Units (VU) - - - - - - Enable VU0 Recompiler (Micro Mode) - - - - - - - Enable VU1 Recompiler - - - - - - - mVU Flag Hack - - - - - - - + + - Clamping Mode: - - - - - - - Rounding Mode: + VU1 Rounding Mode: - + Nearest @@ -239,8 +207,102 @@ + + + + + + mVU Flag Hack + + + + + + + Enable VU1 Recompiler + + + + + + + Enable VU0 Recompiler (Micro Mode) + + + + + - + + + + None + + + + + Normal (Default) + + + + + Extra + + + + + Extra + Preserve Sign + + + + + + + + VU0 Clamping Mode: + + + + + + + VU0 Rounding Mode: + + + + + + + VU1 Clamping Mode: + + + + + + + + Nearest + + + + + Negative + + + + + Positive + + + + + Chop / Zero (Default) + + + + + + None diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 8f00b7e39d..7ff1d17d27 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -510,10 +510,16 @@ struct Pcsx2Config EnableVU1 : 1; bool - vuOverflow : 1, - vuExtraOverflow : 1, - vuSignOverflow : 1, - vuUnderflow : 1; + vu0Overflow : 1, + vu0ExtraOverflow : 1, + vu0SignOverflow : 1, + vu0Underflow : 1; + + bool + vu1Overflow : 1, + vu1ExtraOverflow : 1, + vu1SignOverflow : 1, + vu1Underflow : 1; bool fpuOverflow : 1, @@ -555,14 +561,7 @@ struct Pcsx2Config u32 GetVUClampMode() const { - return vuSignOverflow ? 3 : (vuExtraOverflow ? 2 : (vuOverflow ? 1 : 0)); - } - - void SetVUClampMode(u32 value) - { - vuOverflow = (value >= 1); - vuExtraOverflow = (value >= 2); - vuSignOverflow = (value >= 3); + return vu0SignOverflow ? 3 : (vu0ExtraOverflow ? 2 : (vu0Overflow ? 1 : 0)); } }; @@ -572,7 +571,8 @@ struct Pcsx2Config RecompilerOptions Recompiler; SSE_MXCSR sseMXCSR; - SSE_MXCSR sseVUMXCSR; + SSE_MXCSR sseVU0MXCSR; + SSE_MXCSR sseVU1MXCSR; u32 AffinityControlMode; @@ -584,7 +584,7 @@ struct Pcsx2Config bool operator==(const CpuOptions& right) const { - return OpEqu(sseMXCSR) && OpEqu(sseVUMXCSR) && OpEqu(AffinityControlMode) && OpEqu(Recompiler); + return OpEqu(sseMXCSR) && OpEqu(sseVU0MXCSR) && OpEqu(sseVU1MXCSR) && OpEqu(AffinityControlMode) && OpEqu(Recompiler); } bool operator!=(const CpuOptions& right) const @@ -1327,10 +1327,10 @@ namespace EmuFolders #define CHECK_FULLVU0SYNCHACK (EmuConfig.Gamefixes.FullVU0SyncHack) //------------ Advanced Options!!! --------------- -#define CHECK_VU_OVERFLOW (EmuConfig.Cpu.Recompiler.vuOverflow) -#define CHECK_VU_EXTRA_OVERFLOW (EmuConfig.Cpu.Recompiler.vuExtraOverflow) // If enabled, Operands are clamped before being used in the VU recs -#define CHECK_VU_SIGN_OVERFLOW (EmuConfig.Cpu.Recompiler.vuSignOverflow) -#define CHECK_VU_UNDERFLOW (EmuConfig.Cpu.Recompiler.vuUnderflow) +#define CHECK_VU_OVERFLOW(vunum) (((vunum) == 0) ? EmuConfig.Cpu.Recompiler.vu0Overflow : EmuConfig.Cpu.Recompiler.vu1Overflow) +#define CHECK_VU_EXTRA_OVERFLOW(vunum) (((vunum) == 0) ? EmuConfig.Cpu.Recompiler.vu0ExtraOverflow : EmuConfig.Cpu.Recompiler.vu1ExtraOverflow) // If enabled, Operands are clamped before being used in the VU recs +#define CHECK_VU_SIGN_OVERFLOW(vunum) (((vunum) == 0) ? EmuConfig.Cpu.Recompiler.vu0SignOverflow : EmuConfig.Cpu.Recompiler.vu1SignOverflow) +#define CHECK_VU_UNDERFLOW(vunum) (((vunum) == 0) ? EmuConfig.Cpu.Recompiler.vu0Underflow : EmuConfig.Cpu.Recompiler.vu1Underflow) #define CHECK_FPU_OVERFLOW (EmuConfig.Cpu.Recompiler.fpuOverflow) #define CHECK_FPU_EXTRA_OVERFLOW (EmuConfig.Cpu.Recompiler.fpuExtraOverflow) // If enabled, Operands are checked for infinities before being used in the FPU recs diff --git a/pcsx2/Docs/gamedb-schema.json b/pcsx2/Docs/gamedb-schema.json index 92cadafdde..8637d4e157 100644 --- a/pcsx2/Docs/gamedb-schema.json +++ b/pcsx2/Docs/gamedb-schema.json @@ -36,6 +36,16 @@ "type": "integer", "minimum": 0, "maximum": 3 + }, + "vu0RoundMode": { + "type": "integer", + "minimum": 0, + "maximum": 3 + }, + "vu1RoundMode": { + "type": "integer", + "minimum": 0, + "maximum": 3 } }, "additionalProperties": false @@ -55,6 +65,18 @@ "description": "0 (Disables), 1 (Normally), 2 (Extra), 3 (Extra+Preserve Sign)", "minimum": 0, "maximum": 3 + }, + "vu0ClampMode": { + "type": "integer", + "description": "0 (Disables), 1 (Normally), 2 (Extra), 3 (Extra+Preserve Sign)", + "minimum": 0, + "maximum": 3 + }, + "vu1ClampMode": { + "type": "integer", + "description": "0 (Disables), 1 (Normally), 2 (Extra), 3 (Extra+Preserve Sign)", + "minimum": 0, + "maximum": 3 } }, "additionalProperties": false diff --git a/pcsx2/Frontend/FullscreenUI.cpp b/pcsx2/Frontend/FullscreenUI.cpp index 7399af0425..dd36499c9f 100644 --- a/pcsx2/Frontend/FullscreenUI.cpp +++ b/pcsx2/Frontend/FullscreenUI.cpp @@ -360,7 +360,7 @@ namespace FullscreenUI static void DrawPathSetting(SettingsInterface* bsi, const char* title, const char* section, const char* key, const char* default_value, bool enabled = true, float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font, ImFont* summary_font = g_medium_font); - static void DrawClampingModeSetting(SettingsInterface* bsi, const char* title, const char* summary, bool vu); + static void DrawClampingModeSetting(SettingsInterface* bsi, const char* title, const char* summary, int vunum); static void PopulateGraphicsAdapterList(); static void PopulateGameListDirectoryCache(SettingsInterface* si); static void BeginInputBinding(SettingsInterface* bsi, InputBindingInfo::Type type, const std::string_view& section, @@ -1177,7 +1177,7 @@ SettingsInterface* FullscreenUI::GetEditingSettingsInterface(bool game_settings) bool FullscreenUI::ShouldShowAdvancedSettings(SettingsInterface* bsi) { return IsEditingGameSettings(bsi) ? Host::GetBaseBoolSettingValue("UI", "ShowAdvancedSettings", false) : - bsi->GetBoolValue("UI", "ShowAdvancedSettings", false); + bsi->GetBoolValue("UI", "ShowAdvancedSettings", false); } void FullscreenUI::SetSettingsChanged(SettingsInterface* bsi) @@ -1446,7 +1446,7 @@ void FullscreenUI::DrawIntListSetting(SettingsInterface* bsi, const char* title, const int index = value.has_value() ? (value.value() - option_offset) : std::numeric_limits::min(); const char* value_text = (value.has_value()) ? ((index < 0 || static_cast(index) >= option_count) ? "Unknown" : options[index]) : - "Use Global Setting"; + "Use Global Setting"; if (MenuButtonWithValue(title, summary, value_text, enabled, height, font, summary_font)) { @@ -1907,8 +1907,8 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title, ImVec2 button_pos(ImGui::GetCursorPos()); // Align value text in middle. - ImGui::SetCursorPosY( - ImGui::GetCursorPosY() + ((LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY) + padding.y * 2.0f) - g_large_font->FontSize) * 0.5f); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + + ((LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY) + padding.y * 2.0f) - g_large_font->FontSize) * 0.5f); ImGui::TextUnformatted(labels[i]); ImGui::SameLine(midpoint); ImGui::SetNextItemWidth(end); @@ -2218,7 +2218,7 @@ void FullscreenUI::DrawPathSetting(SettingsInterface* bsi, const char* title, co if (value.has_value()) initial_path = Path::GetDirectory(value.value()); - OpenFileSelector(title, false, std::move(callback), { "*" }, std::move(initial_path)); + OpenFileSelector(title, false, std::move(callback), {"*"}, std::move(initial_path)); } } @@ -2259,7 +2259,7 @@ void FullscreenUI::StartAutomaticBinding(u32 port) // and the toast needs to happen on the UI thread. GetMTGS().RunOnGSThread([result, name = std::move(name)]() { ShowToast({}, result ? fmt::format("Automatic mapping completed for {}.", name) : - fmt::format("Automatic mapping failed for {}.", name)); + fmt::format("Automatic mapping failed for {}.", name)); }); }); CloseChoiceDialog(); @@ -2442,7 +2442,7 @@ void FullscreenUI::DrawSettingsWindow() const bool game_settings = IsEditingGameSettings(bsi); const u32 count = game_settings ? (ShouldShowAdvancedSettings(bsi) ? std::size(per_game_pages) : (std::size(per_game_pages) - 1)) : - std::size(global_pages); + std::size(global_pages); const char* const* icons = game_settings ? per_game_icons : global_icons; const SettingsPage* pages = game_settings ? per_game_pages : global_pages; u32 index = 0; @@ -2903,17 +2903,19 @@ void FullscreenUI::DrawEmulationSettingsPage() EndMenuButtons(); } -void FullscreenUI::DrawClampingModeSetting(SettingsInterface* bsi, const char* title, const char* summary, bool vu) +void FullscreenUI::DrawClampingModeSetting(SettingsInterface* bsi, const char* title, const char* summary, int vunum) { // This is so messy... maybe we should just make the mode an int in the settings too... const bool base = IsEditingGameSettings(bsi) ? 1 : 0; std::optional default_false = IsEditingGameSettings(bsi) ? std::nullopt : std::optional(false); std::optional default_true = IsEditingGameSettings(bsi) ? std::nullopt : std::optional(true); - std::optional third = bsi->GetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", default_false); - std::optional second = - bsi->GetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", default_false); - std::optional first = bsi->GetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", default_true); + std::optional third = bsi->GetOptionalBoolValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0SignOverflow" : "vu1SignOverflow") : "fpuFullMode"), default_false); + std::optional second = bsi->GetOptionalBoolValue("EmuCore/CPU/Recompiler", + (vunum >= 0 ? ((vunum == 0) ? "vu0ExtraOverflow" : "vu1ExtraOverflow") : "fpuExtraOverflow"), default_false); + std::optional first = bsi->GetOptionalBoolValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0Overflow" : "vu1Overflow") : "fpuOverflow"), default_true); int index; if (third.has_value() && third.value()) @@ -2931,7 +2933,7 @@ void FullscreenUI::DrawClampingModeSetting(SettingsInterface* bsi, const char* t "Use Global Setting", "None", "Normal (Default)", "Extra + Preserve Sign", "Full"}; static constexpr const char* vu_clamping_mode_settings[] = { "Use Global Setting", "None", "Normal (Default)", "Extra", "Extra + Preserve Sign"}; - const char* const* options = vu ? vu_clamping_mode_settings : ee_clamping_mode_settings; + const char* const* options = (vunum >= 0) ? vu_clamping_mode_settings : ee_clamping_mode_settings; const int setting_offset = IsEditingGameSettings(bsi) ? 0 : 1; if (MenuButtonWithValue(title, summary, options[index + setting_offset])) @@ -2941,7 +2943,7 @@ void FullscreenUI::DrawClampingModeSetting(SettingsInterface* bsi, const char* t for (int i = setting_offset; i < static_cast(std::size(ee_clamping_mode_settings)); i++) cd_options.emplace_back(options[i], (i == (index + setting_offset))); OpenChoiceDialog(title, false, std::move(cd_options), - [game_settings = IsEditingGameSettings(bsi), vu](s32 index, const std::string& title, bool checked) { + [game_settings = IsEditingGameSettings(bsi), vunum](s32 index, const std::string& title, bool checked) { if (index >= 0) { auto lock = Host::GetSettingsLock(); @@ -2957,9 +2959,12 @@ void FullscreenUI::DrawClampingModeSetting(SettingsInterface* bsi, const char* t } SettingsInterface* bsi = GetEditingSettingsInterface(game_settings); - bsi->SetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", third); - bsi->SetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", second); - bsi->SetOptionalBoolValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", first); + bsi->SetOptionalBoolValue("EmuCore/CPU/Recompiler", + (vunum >= 0 ? ((vunum == 0) ? "vu0SignOverflow" : "vu1SignOverflow") : "fpuFullMode"), third); + bsi->SetOptionalBoolValue("EmuCore/CPU/Recompiler", + (vunum >= 0 ? ((vunum == 0) ? "vu0ExtraOverflow" : "vu1ExtraOverflow") : "fpuExtraOverflow"), second); + bsi->SetOptionalBoolValue( + "EmuCore/CPU/Recompiler", (vunum >= 0 ? ((vunum == 0) ? "vu0Overflow" : "vu1Overflow") : "fpuOverflow"), first); SetSettingsChanged(bsi); } @@ -3754,7 +3759,7 @@ void FullscreenUI::DrawControllerSettingsPage() ImGui::PushID(global_slot); MenuHeading( (mtap_enabled[mtap_port] ? fmt::format(ICON_FA_PLUG " Controller Port {}{}", mtap_port + 1, mtap_slot_names[mtap_slot]) : - fmt::format(ICON_FA_PLUG " Controller Port {}", mtap_port + 1)) + fmt::format(ICON_FA_PLUG " Controller Port {}", mtap_port + 1)) .c_str()); const char* section = sections[global_slot]; @@ -3800,7 +3805,7 @@ void FullscreenUI::DrawControllerSettingsPage() MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_MICROCHIP " Controller Port {}{} Macros", mtap_port + 1, mtap_slot_names[mtap_slot]) : - fmt::format(ICON_FA_MICROCHIP " Controller Port {} Macros", mtap_port + 1)) + fmt::format(ICON_FA_MICROCHIP " Controller Port {} Macros", mtap_port + 1)) .c_str()); static bool macro_button_expanded[PAD::NUM_CONTROLLER_PORTS][PAD::NUM_MACRO_BUTTONS_PER_CONTROLLER] = {}; @@ -3881,7 +3886,7 @@ void FullscreenUI::DrawControllerSettingsPage() const std::string freq_key(fmt::format("Macro{}Frequency", macro_index + 1)); s32 frequency = bsi->GetIntValue(section, freq_key.c_str(), 0); const std::string freq_summary((frequency == 0) ? std::string("Macro will not auto-toggle.") : - fmt::format("Macro will toggle every {} frames.", frequency)); + fmt::format("Macro will toggle every {} frames.", frequency)); if (MenuButton(ICON_FA_LIGHTBULB " Frequency", freq_summary.c_str())) ImGui::OpenPopup(freq_key.c_str()); @@ -3923,7 +3928,7 @@ void FullscreenUI::DrawControllerSettingsPage() { MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_SLIDERS_H " Controller Port {}{} Settings", mtap_port + 1, mtap_slot_names[mtap_slot]) : - fmt::format(ICON_FA_SLIDERS_H " Controller Port {} Settings", mtap_port + 1)) + fmt::format(ICON_FA_SLIDERS_H " Controller Port {} Settings", mtap_port + 1)) .c_str()); for (u32 i = 0; i < ci->num_settings; i++) @@ -4128,7 +4133,7 @@ void FullscreenUI::DrawAdvancedSettingsPage() "Determines how the results of floating-point operations are rounded. Some games need specific settings.", "EmuCore/CPU", "FPU.Roundmode", 3, ee_rounding_mode_settings, std::size(ee_rounding_mode_settings)); DrawClampingModeSetting(bsi, "Clamping Mode##ee_clamping_mode", - "Determines how out-of-range floating point numbers are handled. Some games need specific settings.", false); + "Determines how out-of-range floating point numbers are handled. Some games need specific settings.", -1); DrawToggleSetting(bsi, "Enable EE Recompiler", "Performs just-in-time binary translation of 64-bit MIPS-IV machine code to native code.", "EmuCore/CPU/Recompiler", "EnableEE", @@ -4143,11 +4148,16 @@ void FullscreenUI::DrawAdvancedSettingsPage() "EmuCore/CPU/Recompiler", "EnableFastmem", true); MenuHeading("Vector Units"); - DrawIntListSetting(bsi, "Rounding Mode##vu_rounding_mode", + DrawIntListSetting(bsi, "VU0 Rounding Mode##vu_rounding_mode", "Determines how the results of floating-point operations are rounded. Some games need specific settings.", "EmuCore/CPU", - "VU.Roundmode", 3, ee_rounding_mode_settings, std::size(ee_rounding_mode_settings)); - DrawClampingModeSetting(bsi, "Clamping Mode##vu_clamping_mode", - "Determines how out-of-range floating point numbers are handled. Some games need specific settings.", true); + "VU0.Roundmode", 3, ee_rounding_mode_settings, std::size(ee_rounding_mode_settings)); + DrawClampingModeSetting(bsi, "VU0 Clamping Mode##vu_clamping_mode", + "Determines how out-of-range floating point numbers are handled. Some games need specific settings.", 0); + DrawIntListSetting(bsi, "VU1 Rounding Mode##vu_rounding_mode", + "Determines how the results of floating-point operations are rounded. Some games need specific settings.", "EmuCore/CPU", + "VU1.Roundmode", 3, ee_rounding_mode_settings, std::size(ee_rounding_mode_settings)); + DrawClampingModeSetting(bsi, "VU1 Clamping Mode##vu_clamping_mode", + "Determines how out-of-range floating point numbers are handled. Some games need specific settings.", 1); DrawToggleSetting(bsi, "Enable VU0 Recompiler (Micro Mode)", "New Vector Unit recompiler with much improved compatibility. Recommended.", "EmuCore/CPU/Recompiler", "EnableVU0", true); DrawToggleSetting(bsi, "Enable VU1 Recompiler", "New Vector Unit recompiler with much improved compatibility. Recommended.", @@ -4246,7 +4256,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type) g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits::max(), -1.0f, s_current_game_title.c_str())); const ImVec2 path_size(path_string.empty() ? ImVec2(0.0f, 0.0f) : - g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits::max(), -1.0f, + g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits::max(), -1.0f, path_string.data(), path_string.data() + path_string.length())); const ImVec2 subtitle_size(g_medium_font->CalcTextSizeA( g_medium_font->FontSize, std::numeric_limits::max(), -1.0f, s_current_game_subtitle.c_str())); @@ -4415,7 +4425,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type) } if (ActiveButton(GSConfig.UseHardwareRenderer() ? (ICON_FA_PAINT_BRUSH " Switch To Software Renderer") : - (ICON_FA_PAINT_BRUSH " Switch To Hardware Renderer"), + (ICON_FA_PAINT_BRUSH " Switch To Hardware Renderer"), false)) { ClosePauseMenu(); @@ -5061,7 +5071,7 @@ void FullscreenUI::PopulateGameListEntryList() if (lhs->total_played_time != rhs->total_played_time) { return reverse ? (lhs->total_played_time > rhs->total_played_time) : - (lhs->total_played_time < rhs->total_played_time); + (lhs->total_played_time < rhs->total_played_time); } } break; @@ -5258,7 +5268,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size) ImGui::SetCursorPos(LayoutScale(ImVec2(128.0f, 20.0f)) + image_rect.Min); ImGui::Image(selected_entry ? GetGameListCover(selected_entry)->GetHandle() : - GetTextureForGameListEntryType(GameList::EntryType::Count)->GetHandle(), + GetTextureForGameListEntryType(GameList::EntryType::Count)->GetHandle(), image_rect.GetSize()); } @@ -5566,7 +5576,7 @@ void FullscreenUI::DrawGameListSettingsPage(const ImVec2& heading_size) ImGuiFullscreen::ChoiceDialogOptions options = { {ICON_FA_FOLDER_OPEN " Open in File Browser", false}, {it.second ? (ICON_FA_FOLDER_MINUS " Disable Subdirectory Scanning") : - (ICON_FA_FOLDER_PLUS " Enable Subdirectory Scanning"), + (ICON_FA_FOLDER_PLUS " Enable Subdirectory Scanning"), false}, {ICON_FA_TIMES " Remove From List", false}, {ICON_FA_WINDOW_CLOSE " Close Menu", false}, diff --git a/pcsx2/Frontend/ImGuiOverlays.cpp b/pcsx2/Frontend/ImGuiOverlays.cpp index 06d566e2ae..a2c7a3f39c 100644 --- a/pcsx2/Frontend/ImGuiOverlays.cpp +++ b/pcsx2/Frontend/ImGuiOverlays.cpp @@ -345,7 +345,7 @@ void ImGuiManager::DrawSettingsOverlay() APPEND("MTVU "); APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast(EmuConfig.Cpu.sseMXCSR.GetRoundMode()), - EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast(EmuConfig.Cpu.sseVUMXCSR.GetRoundMode()), + EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast(EmuConfig.Cpu.sseVU0MXCSR.GetRoundMode()), EmuConfig.Cpu.Recompiler.GetVUClampMode(), EmuConfig.GS.VsyncQueueSize); if (EmuConfig.EnableCheats || EmuConfig.EnableWideScreenPatches || EmuConfig.EnableNoInterlacingPatches) diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index 36471a7752..b8907e24b7 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -127,7 +127,20 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml: { int vuVal = -1; node["roundModes"]["vuRoundMode"] >> vuVal; - gameEntry.vuRoundMode = static_cast(vuVal); + gameEntry.vu0RoundMode = static_cast(vuVal); + gameEntry.vu1RoundMode = static_cast(vuVal); + } + if (node["roundModes"].has_child("vu0RoundMode")) + { + int vuVal = -1; + node["roundModes"]["vu0RoundMode"] >> vuVal; + gameEntry.vu0RoundMode = static_cast(vuVal); + } + if (node["roundModes"].has_child("vu1RoundMode")) + { + int vuVal = -1; + node["roundModes"]["vu1RoundMode"] >> vuVal; + gameEntry.vu1RoundMode = static_cast(vuVal); } } if (node.has_child("clampModes")) @@ -142,7 +155,20 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml: { int vuVal = -1; node["clampModes"]["vuClampMode"] >> vuVal; - gameEntry.vuClampMode = static_cast(vuVal); + gameEntry.vu0ClampMode = static_cast(vuVal); + gameEntry.vu1ClampMode = static_cast(vuVal); + } + if (node["clampModes"].has_child("vu0ClampMode")) + { + int vuVal = -1; + node["clampModes"]["vu0ClampMode"] >> vuVal; + gameEntry.vu0ClampMode = static_cast(vuVal); + } + if (node["clampModes"].has_child("vu1ClampMode")) + { + int vuVal = -1; + node["clampModes"]["vu1ClampMode"] >> vuVal; + gameEntry.vu1ClampMode = static_cast(vuVal); } } @@ -378,19 +404,35 @@ u32 GameDatabaseSchema::GameEntry::applyGameFixes(Pcsx2Config& config, bool appl } } - if (vuRoundMode != GameDatabaseSchema::RoundMode::Undefined) + if (vu0RoundMode != GameDatabaseSchema::RoundMode::Undefined) { - const SSE_RoundMode vuRM = (SSE_RoundMode)enum_cast(vuRoundMode); + const SSE_RoundMode vuRM = (SSE_RoundMode)enum_cast(vu0RoundMode); if (EnumIsValid(vuRM)) { if (applyAuto) { - PatchesCon->WriteLn("(GameDB) Changing VU0/VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); - config.Cpu.sseVUMXCSR.SetRoundMode(vuRM); + PatchesCon->WriteLn("(GameDB) Changing VU0 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); + config.Cpu.sseVU0MXCSR.SetRoundMode(vuRM); num_applied_fixes++; } else - PatchesCon->Warning("[GameDB] Skipping changing VU0/VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); + PatchesCon->Warning("[GameDB] Skipping changing VU0 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); + } + } + + if (vu1RoundMode != GameDatabaseSchema::RoundMode::Undefined) + { + const SSE_RoundMode vuRM = (SSE_RoundMode)enum_cast(vu1RoundMode); + if (EnumIsValid(vuRM)) + { + if (applyAuto) + { + PatchesCon->WriteLn("(GameDB) Changing VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); + config.Cpu.sseVU1MXCSR.SetRoundMode(vuRM); + num_applied_fixes++; + } + else + PatchesCon->Warning("[GameDB] Skipping changing VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); } } @@ -409,19 +451,34 @@ u32 GameDatabaseSchema::GameEntry::applyGameFixes(Pcsx2Config& config, bool appl PatchesCon->Warning("[GameDB] Skipping changing EE/FPU clamp mode [mode=%d]", clampMode); } - if (vuClampMode != GameDatabaseSchema::ClampMode::Undefined) + if (vu0ClampMode != GameDatabaseSchema::ClampMode::Undefined) { - const int clampMode = enum_cast(vuClampMode); + const int clampMode = enum_cast(vu0ClampMode); if (applyAuto) { - PatchesCon->WriteLn("(GameDB) Changing VU0/VU1 clamp mode [mode=%d]", clampMode); - config.Cpu.Recompiler.vuOverflow = (clampMode >= 1); - config.Cpu.Recompiler.vuExtraOverflow = (clampMode >= 2); - config.Cpu.Recompiler.vuSignOverflow = (clampMode >= 3); + PatchesCon->WriteLn("(GameDB) Changing VU0 clamp mode [mode=%d]", clampMode); + config.Cpu.Recompiler.vu0Overflow = (clampMode >= 1); + config.Cpu.Recompiler.vu0ExtraOverflow = (clampMode >= 2); + config.Cpu.Recompiler.vu0SignOverflow = (clampMode >= 3); num_applied_fixes++; } else - PatchesCon->Warning("[GameDB] Skipping changing VU0/VU1 clamp mode [mode=%d]", clampMode); + PatchesCon->Warning("[GameDB] Skipping changing VU0 clamp mode [mode=%d]", clampMode); + } + + if (vu1ClampMode != GameDatabaseSchema::ClampMode::Undefined) + { + const int clampMode = enum_cast(vu1ClampMode); + if (applyAuto) + { + PatchesCon->WriteLn("(GameDB) Changing VU1 clamp mode [mode=%d]", clampMode); + config.Cpu.Recompiler.vu1Overflow = (clampMode >= 1); + config.Cpu.Recompiler.vu1ExtraOverflow = (clampMode >= 2); + config.Cpu.Recompiler.vu1SignOverflow = (clampMode >= 3); + num_applied_fixes++; + } + else + PatchesCon->Warning("[GameDB] Skipping changing VU1 clamp mode [mode=%d]", clampMode); } // TODO - config - this could be simplified with maps instead of bitfields and enums diff --git a/pcsx2/GameDatabase.h b/pcsx2/GameDatabase.h index 18f787046a..a53269399e 100644 --- a/pcsx2/GameDatabase.h +++ b/pcsx2/GameDatabase.h @@ -95,9 +95,11 @@ namespace GameDatabaseSchema std::string region; Compatibility compat = Compatibility::Unknown; RoundMode eeRoundMode = RoundMode::Undefined; - RoundMode vuRoundMode = RoundMode::Undefined; + RoundMode vu0RoundMode = RoundMode::Undefined; + RoundMode vu1RoundMode = RoundMode::Undefined; ClampMode eeClampMode = ClampMode::Undefined; - ClampMode vuClampMode = ClampMode::Undefined; + ClampMode vu0ClampMode = ClampMode::Undefined; + ClampMode vu1ClampMode = ClampMode::Undefined; std::vector gameFixes; std::vector> speedHacks; std::vector> gsHWFixes; diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index e5aeffd228..db797cc25b 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -210,10 +210,14 @@ Pcsx2Config::RecompilerOptions::RecompilerOptions() EnableFastmem = true; // vu and fpu clamping default to standard overflow. - vuOverflow = true; - //vuExtraOverflow = false; - //vuSignOverflow = false; - //vuUnderflow = false; + vu0Overflow = true; + //vu0ExtraOverflow = false; + //vu0SignOverflow = false; + //vu0Underflow = false; + vu1Overflow = true; + //vu1ExtraOverflow = false; + //vu1SignOverflow = false; + //vu1Underflow = false; fpuOverflow = true; //fpuExtraOverflow = false; @@ -240,18 +244,34 @@ void Pcsx2Config::RecompilerOptions::ApplySanityCheck() bool vuIsOk = true; - if (vuExtraOverflow) - vuIsOk = vuIsOk && vuOverflow; - if (vuSignOverflow) - vuIsOk = vuIsOk && vuExtraOverflow; + if (vu0ExtraOverflow) + vuIsOk = vuIsOk && vu0Overflow; + if (vu0SignOverflow) + vuIsOk = vuIsOk && vu0ExtraOverflow; if (!vuIsOk) { // Values are wonky; assume the defaults. - vuOverflow = RecompilerOptions().vuOverflow; - vuExtraOverflow = RecompilerOptions().vuExtraOverflow; - vuSignOverflow = RecompilerOptions().vuSignOverflow; - vuUnderflow = RecompilerOptions().vuUnderflow; + vu0Overflow = RecompilerOptions().vu0Overflow; + vu0ExtraOverflow = RecompilerOptions().vu0ExtraOverflow; + vu0SignOverflow = RecompilerOptions().vu0SignOverflow; + vu0Underflow = RecompilerOptions().vu0Underflow; + } + + vuIsOk = true; + + if (vu1ExtraOverflow) + vuIsOk = vuIsOk && vu1Overflow; + if (vu1SignOverflow) + vuIsOk = vuIsOk && vu1ExtraOverflow; + + if (!vuIsOk) + { + // Values are wonky; assume the defaults. + vu1Overflow = RecompilerOptions().vu1Overflow; + vu1ExtraOverflow = RecompilerOptions().vu1ExtraOverflow; + vu1SignOverflow = RecompilerOptions().vu1SignOverflow; + vu1Underflow = RecompilerOptions().vu1Underflow; } } @@ -266,10 +286,14 @@ void Pcsx2Config::RecompilerOptions::LoadSave(SettingsWrapper& wrap) SettingsWrapBitBool(EnableVU1); SettingsWrapBitBool(EnableFastmem); - SettingsWrapBitBool(vuOverflow); - SettingsWrapBitBool(vuExtraOverflow); - SettingsWrapBitBool(vuSignOverflow); - SettingsWrapBitBool(vuUnderflow); + SettingsWrapBitBool(vu0Overflow); + SettingsWrapBitBool(vu0ExtraOverflow); + SettingsWrapBitBool(vu0SignOverflow); + SettingsWrapBitBool(vu0Underflow); + SettingsWrapBitBool(vu1Overflow); + SettingsWrapBitBool(vu1ExtraOverflow); + SettingsWrapBitBool(vu1SignOverflow); + SettingsWrapBitBool(vu1Underflow); SettingsWrapBitBool(fpuOverflow); SettingsWrapBitBool(fpuExtraOverflow); @@ -287,14 +311,16 @@ bool Pcsx2Config::CpuOptions::CpusChanged(const CpuOptions& right) const Pcsx2Config::CpuOptions::CpuOptions() { sseMXCSR.bitmask = DEFAULT_sseMXCSR; - sseVUMXCSR.bitmask = DEFAULT_sseVUMXCSR; + sseVU0MXCSR.bitmask = DEFAULT_sseVUMXCSR; + sseVU1MXCSR.bitmask = DEFAULT_sseVUMXCSR; AffinityControlMode = 0; } void Pcsx2Config::CpuOptions::ApplySanityCheck() { sseMXCSR.ClearExceptionFlags().DisableExceptions(); - sseVUMXCSR.ClearExceptionFlags().DisableExceptions(); + sseVU0MXCSR.ClearExceptionFlags().DisableExceptions(); + sseVU1MXCSR.ClearExceptionFlags().DisableExceptions(); AffinityControlMode = std::min(AffinityControlMode, 6); Recompiler.ApplySanityCheck(); @@ -309,9 +335,12 @@ void Pcsx2Config::CpuOptions::LoadSave(SettingsWrapper& wrap) SettingsWrapBitfieldEx(sseMXCSR.RoundingControl, "FPU.Roundmode"); SettingsWrapEntry(AffinityControlMode); - SettingsWrapBitBoolEx(sseVUMXCSR.DenormalsAreZero, "VU.DenormalsAreZero"); - SettingsWrapBitBoolEx(sseVUMXCSR.FlushToZero, "VU.FlushToZero"); - SettingsWrapBitfieldEx(sseVUMXCSR.RoundingControl, "VU.Roundmode"); + SettingsWrapBitBoolEx(sseVU0MXCSR.DenormalsAreZero, "VU0.DenormalsAreZero"); + SettingsWrapBitBoolEx(sseVU0MXCSR.FlushToZero, "VU0.FlushToZero"); + SettingsWrapBitfieldEx(sseVU0MXCSR.RoundingControl, "VU0.Roundmode"); + SettingsWrapBitBoolEx(sseVU1MXCSR.DenormalsAreZero, "VU1.DenormalsAreZero"); + SettingsWrapBitBoolEx(sseVU1MXCSR.FlushToZero, "VU1.FlushToZero"); + SettingsWrapBitfieldEx(sseVU1MXCSR.RoundingControl, "VU1.Roundmode"); Recompiler.LoadSave(wrap); } diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 19ce509c61..7113b00977 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -37,16 +37,18 @@ extern R5900cpu GSDumpReplayerCpu; SSE_MXCSR g_sseMXCSR = {DEFAULT_sseMXCSR}; -SSE_MXCSR g_sseVUMXCSR = {DEFAULT_sseVUMXCSR}; +SSE_MXCSR g_sseVU0MXCSR = {DEFAULT_sseVUMXCSR}; +SSE_MXCSR g_sseVU1MXCSR = {DEFAULT_sseVUMXCSR}; // SetCPUState -- for assignment of SSE roundmodes and clampmodes. // -void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVUMXCSR) +void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVU0MXCSR, SSE_MXCSR sseVU1MXCSR) { //Msgbox::Alert("SetCPUState: Config.sseMXCSR = %x; Config.sseVUMXCSR = %x \n", Config.sseMXCSR, Config.sseVUMXCSR); g_sseMXCSR = sseMXCSR.ApplyReserveMask(); - g_sseVUMXCSR = sseVUMXCSR.ApplyReserveMask(); + g_sseVU0MXCSR = sseVU0MXCSR.ApplyReserveMask(); + g_sseVU1MXCSR = sseVU1MXCSR.ApplyReserveMask(); _mm_setcsr(g_sseMXCSR.bitmask); } diff --git a/pcsx2/System.h b/pcsx2/System.h index 8c35e881b3..424b6dc074 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -146,5 +146,5 @@ extern std::string SysGetDiscID(); extern SysMainMemory& GetVmMemory(); -extern void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVUMXCSR); -extern SSE_MXCSR g_sseVUMXCSR, g_sseMXCSR; +extern void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVU0MXCSR, SSE_MXCSR sseVU1MXCSR); +extern SSE_MXCSR g_sseVU0MXCSR, g_sseVU1MXCSR, g_sseMXCSR; diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 48d23353be..b58d3d63c4 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -1039,7 +1039,7 @@ bool VMManager::Initialize(VMBootParameters boot_params) s_cpu_implementation_changed = false; s_cpu_provider_pack->ApplyConfig(); - SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR); + SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVU0MXCSR, EmuConfig.Cpu.sseVU1MXCSR); SysClearExecutionCache(); memBindConditionalHandlers(); @@ -1638,7 +1638,7 @@ void VMManager::CheckForCPUConfigChanges(const Pcsx2Config& old_config) } Console.WriteLn("Updating CPU configuration..."); - SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR); + SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVU0MXCSR, EmuConfig.Cpu.sseVU1MXCSR); SysClearExecutionCache(); memBindConditionalHandlers(); @@ -1953,14 +1953,17 @@ void VMManager::WarnAboutUnsafeSettings() messages += ICON_FA_FIRST_AID " CRC Fix Level is not set to default, this may break effects in some games.\n"; if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled) messages += ICON_FA_DOWNLOAD " Hardware Download Mode is not set to Accurate, this may break rendering in some games.\n"; - if (EmuConfig.Cpu.sseMXCSR.GetRoundMode() != SSEround_Chop || EmuConfig.Cpu.sseVUMXCSR.GetRoundMode() != SSEround_Chop) + if (EmuConfig.Cpu.sseMXCSR.GetRoundMode() != SSEround_Chop) messages += ICON_FA_MICROCHIP " EE FPU Round Mode is not set to default, this may break some games.\n"; if (!EmuConfig.Cpu.Recompiler.fpuOverflow || EmuConfig.Cpu.Recompiler.fpuExtraOverflow || EmuConfig.Cpu.Recompiler.fpuFullMode) messages += ICON_FA_MICROCHIP " EE FPU Clamp Mode is not set to default, this may break some games.\n"; - if (EmuConfig.Cpu.sseVUMXCSR.GetRoundMode() != SSEround_Chop) + if (EmuConfig.Cpu.sseVU0MXCSR.GetRoundMode() != SSEround_Chop || EmuConfig.Cpu.sseVU1MXCSR.GetRoundMode() != SSEround_Chop) messages += ICON_FA_MICROCHIP " VU Round Mode is not set to default, this may break some games.\n"; - if (!EmuConfig.Cpu.Recompiler.vuOverflow || EmuConfig.Cpu.Recompiler.vuExtraOverflow || EmuConfig.Cpu.Recompiler.vuSignOverflow) + if (!EmuConfig.Cpu.Recompiler.vu0Overflow || EmuConfig.Cpu.Recompiler.vu0ExtraOverflow || EmuConfig.Cpu.Recompiler.vu0SignOverflow || + !EmuConfig.Cpu.Recompiler.vu1Overflow || EmuConfig.Cpu.Recompiler.vu1ExtraOverflow || EmuConfig.Cpu.Recompiler.vu1SignOverflow) + { messages += ICON_FA_MICROCHIP " VU Clamp Mode is not set to default, this may break some games.\n"; + } if (!EmuConfig.EnableGameFixes) messages += ICON_FA_GAMEPAD " Game Fixes are not enabled. Compatibility with some games may be affected.\n"; if (!EmuConfig.EnablePatches) diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index 7d9d4aa720..e8aab32afd 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -268,7 +268,7 @@ void InterpVU0::Step() void InterpVU0::Execute(u32 cycles) { const int originalRounding = fegetround(); - fesetround(g_sseVUMXCSR.RoundingControl << 8); + fesetround(g_sseVU0MXCSR.RoundingControl << 8); VU0.VI[REG_TPC].UL <<= 3; VU0.flags &= ~VUFLAG_MFLAGSET; diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index 23ff27a1b3..2d700a7295 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -273,7 +273,7 @@ void InterpVU1::Step() void InterpVU1::Execute(u32 cycles) { const int originalRounding = fegetround(); - fesetround(g_sseVUMXCSR.RoundingControl << 8); + fesetround(g_sseVU1MXCSR.RoundingControl << 8); VU1.VI[REG_TPC].UL <<= 3; u32 startcycles = VU1.cycle; diff --git a/pcsx2/VUflags.cpp b/pcsx2/VUflags.cpp index 245e452fd8..61bc5c262b 100644 --- a/pcsx2/VUflags.cpp +++ b/pcsx2/VUflags.cpp @@ -49,7 +49,7 @@ static __ri u32 VU_MAC_UPDATE( int shift, VURegs * VU, float f ) return s; case 255: VU->macflag = (VU->macflag&~(0x0101<checkVFClamp(reg.Id)) + if (((!clampE && CHECK_VU_OVERFLOW(mVU.index)) || (clampE && bClampE)) && mVU.regAlloc->checkVFClamp(reg.Id)) { switch (xyzw) { @@ -59,7 +59,7 @@ void mVUclamp1(microVU& mVU, const xmm& reg, const xmm& regT1, int xyzw, bool bC // so we just use a temporary mem location for our backup for now... (non-sse4 version only) void mVUclamp2(microVU& mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool bClampE = 0) { - if (((!clampE && CHECK_VU_SIGN_OVERFLOW) || (clampE && bClampE && CHECK_VU_SIGN_OVERFLOW)) && mVU.regAlloc->checkVFClamp(reg.Id)) + if (((!clampE && CHECK_VU_SIGN_OVERFLOW(mVU.index)) || (clampE && bClampE && CHECK_VU_SIGN_OVERFLOW(mVU.index))) && mVU.regAlloc->checkVFClamp(reg.Id)) { int i = (xyzw == 1 || xyzw == 2 || xyzw == 4 || xyzw == 8) ? 0 : 1; xPMIN.SD(reg, ptr128[&sse4_maxvals[i][0]]); @@ -85,6 +85,6 @@ void mVUclamp3(microVU& mVU, const xmm& reg, const xmm& regT1, int xyzw) // but this clamp is just a precaution just-in-case. void mVUclamp4(microVU& mVU, const xmm& reg, const xmm& regT1, int xyzw) { - if (clampE && !CHECK_VU_SIGN_OVERFLOW && mVU.regAlloc->checkVFClamp(reg.Id)) + if (clampE && !CHECK_VU_SIGN_OVERFLOW(mVU.index) && mVU.regAlloc->checkVFClamp(reg.Id)) mVUclamp1(mVU, reg, regT1, xyzw, 1); } diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index d9544fcb1a..4998b8c8d3 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -156,7 +156,7 @@ void doIbit(mV) else { u32 tempI; - if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) + if (CHECK_VU_OVERFLOW(mVU.index) && ((curI & 0x7fffffff) >= 0x7f800000)) { DevCon.WriteLn(Color_Green, "microVU%d: Clamping I Reg", mVU.index); tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl index a3f528f2fa..309539e526 100644 --- a/pcsx2/x86/microVU_Execute.inl +++ b/pcsx2/x86/microVU_Execute.inl @@ -32,7 +32,7 @@ void mVUdispatcherAB(mV) else xFastCall((void*)mVUexecuteVU1, arg1reg, arg2reg); // Load VU's MXCSR state - xLDMXCSR(g_sseVUMXCSR); + xLDMXCSR(isVU0 ? g_sseVU0MXCSR : g_sseVU1MXCSR); // Load Regs xMOVAPS (xmmT1, ptr128[&mVU.regs().VI[REG_P].UL]); @@ -94,7 +94,7 @@ void mVUdispatcherCD(mV) xScopedStackFrame frame(false, true); // Load VU's MXCSR state - xLDMXCSR(g_sseVUMXCSR); + xLDMXCSR(isVU0 ? g_sseVU0MXCSR : g_sseVU1MXCSR); mVUrestoreRegs(mVU); xMOV(gprF0, ptr32[&mVU.regs().micro_statusflags[0]]); diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 3e0ca1fa1b..a46ec59dd9 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -101,7 +101,7 @@ mVUop(mVU_SQRT) xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags testNeg(mVU, Ft, gprT1); // Check for negative sqrt - if (CHECK_VU_OVERFLOW) // Clamp infinities (only need to do positive clamp since xmmFt is positive) + if (CHECK_VU_OVERFLOW(mVU.index)) // Clamp infinities (only need to do positive clamp since xmmFt is positive) xMIN.SS(Ft, ptr32[mVUglob.maxvals]); xSQRT.SS(Ft, Ft); writeQreg(Ft, mVUinfo.writeQ); diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 7db1615ca6..1149216300 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -239,7 +239,7 @@ typedef u32 (*mVUCall)(void*, void*); #define Rmem &mVU.regs().VI[REG_R].UL #define aWrap(x, m) ((x > m) ? 0 : x) #define shuffleSS(x) ((x == 1) ? (0x27) : ((x == 2) ? (0xc6) : ((x == 4) ? (0xe1) : (0xe4)))) -#define clampE CHECK_VU_EXTRA_OVERFLOW +#define clampE CHECK_VU_EXTRA_OVERFLOW(mVU.index) #define varPrint(x) DevCon.WriteLn(#x " = %d", (int)x) #define islowerOP ((iPC & 1) == 0) diff --git a/pcsx2/x86/microVU_Upper.inl b/pcsx2/x86/microVU_Upper.inl index 7572d30d7b..eb675513e6 100644 --- a/pcsx2/x86/microVU_Upper.inl +++ b/pcsx2/x86/microVU_Upper.inl @@ -205,7 +205,7 @@ static void setupFtReg(microVU& mVU, xmm& Ft, xmm& tempFt, int opCase, int clamp opCase1 { // Based on mVUclamp2 -> mVUclamp1 below. - const bool willClamp = (clampE || ((clampType & cFt) && !clampE && (CHECK_VU_OVERFLOW || CHECK_VU_SIGN_OVERFLOW))); + const bool willClamp = (clampE || ((clampType & cFt) && !clampE && (CHECK_VU_OVERFLOW(mVU.index) || CHECK_VU_SIGN_OVERFLOW(mVU.index)))); if (_XYZW_SS2) { Ft = mVU.regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W); tempFt = Ft; } else if (willClamp) { Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0xf); tempFt = Ft; }