From 413ba09ee059211cf85096011e7253fd40bb9a0f Mon Sep 17 00:00:00 2001 From: Stenzek <stenzek@gmail.com> Date: Sat, 6 Jan 2024 00:34:21 +1000 Subject: [PATCH] Config: Replace FpuNegDivHack with eeDivRoundMode --- bin/resources/GameIndex.yaml | 65 +++++++++----------- pcsx2-qt/Settings/AdvancedSettingsWidget.cpp | 8 ++- pcsx2-qt/Settings/AdvancedSettingsWidget.ui | 35 ++++++++++- pcsx2-qt/Settings/GameFixSettingsWidget.cpp | 2 - pcsx2-qt/Settings/GameFixSettingsWidget.ui | 7 --- pcsx2/Config.h | 4 +- pcsx2/Docs/gamedb-schema.json | 6 +- pcsx2/GameDatabase.cpp | 22 +++++++ pcsx2/GameDatabase.h | 1 + pcsx2/ImGui/FullscreenUI.cpp | 14 +++-- pcsx2/Pcsx2Config.cpp | 12 ++-- pcsx2/x86/iFPU.cpp | 37 +++-------- pcsx2/x86/iFPUd.cpp | 32 ++-------- 13 files changed, 124 insertions(+), 121 deletions(-) diff --git a/bin/resources/GameIndex.yaml b/bin/resources/GameIndex.yaml index 7840bde349..ac574a5ab3 100644 --- a/bin/resources/GameIndex.yaml +++ b/bin/resources/GameIndex.yaml @@ -14515,8 +14515,8 @@ SLES-50879: name: "Paris-Dakar 2" region: "PAL-M5" compat: 5 - gameFixes: - - FpuNegDivHack # Fixes sky being shown over the 3D. + roundModes: + eeDivRoundMode: 1 # Fixes sky being shown over the 3D. SLES-50880: name: "BMX XXX" region: "PAL-M4" @@ -16840,8 +16840,8 @@ SLES-51897: name-sort: "Simpsons, The - Hit & Run" region: "PAL-M4" compat: 5 - gameFixes: - - FpuNegDivHack # Lens flare appears even when behind objects. + roundModes: + eeDivRoundMode: 1 # Lens flare appears even when behind objects. gsHWFixes: autoFlush: 2 # Fixes missing lens flare. SLES-51903: @@ -22037,8 +22037,8 @@ SLES-53804: SLES-53805: name: "Cocoto Funfair" region: "PAL-M5" - gameFixes: - - FpuNegDivHack # Fixes the cursor not being visible. + roundModes: + eeDivRoundMode: 1 # Fixes the cursor not being visible. SLES-53809: name: "K-1 Premium Dynamite!!" region: "PAL-E" @@ -23998,8 +23998,8 @@ SLES-54549: name: "Crazy Frog Racer 2" region: "PAL-M5" compat: 5 - gameFixes: - - FpuNegDivHack # Fixes black fade effects and some overlays texts in the menus. + roundModes: + eeDivRoundMode: 1 # Fixes black fade effects and some overlays texts in the menus. gsHWFixes: mipmap: 2 # Mipmap + trilinear, improves road and grass textures to match sw renderer. trilinearFiltering: 1 @@ -25716,8 +25716,8 @@ SLES-55170: SLES-55172: name: "Code Lyoko - Quest for Infinity" region: "PAL-M4" - gameFixes: - - FpuNegDivHack # Fixes missing texts on in-game textboxes. + roundModes: + eeDivRoundMode: 1 # Fixes missing texts on in-game textboxes. gsHWFixes: deinterlace: 9 # Game requires adaptive bff de-interlacing instead of auto for the UI at native. halfPixelOffset: 1 # Reduces ghosting effects. @@ -27312,8 +27312,7 @@ SLKA-15018: region: "NTSC-K" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLKA-15019: name: "F1 Career Challenge" region: "NTSC-K" @@ -27957,8 +27956,7 @@ SLKA-25165: region: "NTSC-K" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLKA-25166: name: "Sengoku Musou" region: "NTSC-K" @@ -28565,8 +28563,7 @@ SLKA-25314: region: "NTSC-K" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLKA-25315: name: "NBA Live 06" region: "NTSC-K" @@ -51852,8 +51849,8 @@ SLPS-25430: name-sort: るぱんさんせい ころんぶすのいさんはしゅにそまる name-en: "Lupin III - Columbus no Isan wa Akenisomaru" region: "NTSC-J" - gameFixes: - - FpuNegDivHack # Fixes game softlock after prison level. + roundModes: + eeDivRoundMode: 1 # Fixes game softlock after prison level. SLPS-25431: name: "Bokujou Monogatari - Oh! Wonderful Life" region: "NTSC-J" @@ -52581,8 +52578,7 @@ SLPS-25569: region: "NTSC-J" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLPS-25570: name: キノの旅II name-sort: きののたびII @@ -53487,8 +53483,7 @@ SLPS-25718: compat: 5 roundModes: eeRoundMode: 1 # Fix camera issue. - gameFixes: - - FpuNegDivHack # Fix target loss issue. + eeDivRoundMode: 1 # Fix target loss issue. patches: F616C207: content: |- @@ -54500,8 +54495,8 @@ SLPS-25914: name-sort: きどうせんしがんだむ ぎれんのやぼう あくしずのきょういV name-en: "Kidou Senshi Gundam - Giren no Yabou - Axis no Kyoui V" region: "NTSC-J" - gameFixes: - - FpuNegDivHack + roundModes: + eeDivRoundMode: 1 SLPS-25915: name: ザ・キング・オブ・ファイターズ 2002 アンリミテッドマッチ name-sort: ざ・きんぐ・おぶ・ふぁいたーず 2002 あんりみてっどまっち @@ -54660,8 +54655,8 @@ SLPS-25959: name-sort: きどうせんしがんだむ ぎれんのやぼう あくしずのきょういV GUNDAM 30th ANNIVERSARY COLLECTION name-en: "Kidou Senshi Gundam - Giren no Yabou - Axis no Kyoui V" region: "NTSC-J" - gameFixes: - - FpuNegDivHack + roundModes: + eeDivRoundMode: 1 SLPS-25961: name: 機動戦士ガンダムSEED DESTINY 連合 vs. Z.A.F.T. II plus GUNDAM 30th ANNIVERSARY COLLECTION name-sort: きどうせんしがんだむSEED DESTINY れんごう vs. Z.A.F.T. II plus GUNDAM 30th ANNIVERSARY COLLECTION @@ -54669,8 +54664,7 @@ SLPS-25961: region: "NTSC-K" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLPS-25971: name: "NeoGeo Online Collection Vol. 2 - Bakumatsu Roman - Gekka no Kenshi 1, 2" region: "NTSC-J" @@ -55453,8 +55447,7 @@ SLPS-73269: region: "NTSC-K" roundModes: eeRoundMode: 1 # Fixes camera issue. - gameFixes: - - FpuNegDivHack # Fixes target loss issue. + eeDivRoundMode: 1 # Fixes target loss issue. SLPS-73270: name: "Super Robot Taisen Z [PS2 The Best]" region: "NTSC-J" @@ -58550,8 +58543,8 @@ SLUS-20624: name-sort: "Simpsons, The - Hit & Run" region: "NTSC-U" compat: 5 - gameFixes: - - FpuNegDivHack # Lens flare appears even when behind objects. + roundModes: + eeDivRoundMode: 1 # Lens flare appears even when behind objects. gsHWFixes: autoFlush: 2 # Fixes missing lens flare. SLUS-20625: @@ -64126,8 +64119,8 @@ SLUS-21634: name: "Crazy Frog Racer 2" region: "NTSC-U" compat: 5 - gameFixes: - - FpuNegDivHack # Fixes black fade effects and some overlays texts in the menus. + roundModes: + eeDivRoundMode: 1 # Fixes black fade effects and some overlays texts in the menus. gsHWFixes: mipmap: 2 # Mipmap + trilinear, improves road and grass textures to match sw renderer. trilinearFiltering: 1 @@ -64672,8 +64665,8 @@ SLUS-21743: name: "Code Lyoko - Quest for Infinity" region: "NTSC-U" compat: 5 - gameFixes: - - FpuNegDivHack # Fixes missing texts on in-game textboxes. + roundModes: + eeDivRoundMode: 1 # Fixes missing texts on in-game textboxes. gsHWFixes: deinterlace: 9 # Game requires adaptive bff de-interlacing instead of auto for the UI at native. halfPixelOffset: 1 # Reduces ghosting effects. diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp index 9af5e5cdc6..773ac2d04f 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp @@ -29,9 +29,10 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true); 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.vu0RoundingMode, "EmuCore/CPU", "VU0.Roundmode", 3); - SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu1RoundingMode, "EmuCore/CPU", "VU1.Roundmode", 3); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", static_cast<int>(FPRoundMode::ChopZero)); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeDivRoundingMode, "EmuCore/CPU", "FPUDiv.Roundmode", static_cast<int>(FPRoundMode::Nearest)); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu0RoundingMode, "EmuCore/CPU", "VU0.Roundmode", static_cast<int>(FPRoundMode::ChopZero)); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu1RoundingMode, "EmuCore/CPU", "VU1.Roundmode", static_cast<int>(FPRoundMode::ChopZero)); if (m_dialog->isPerGameSettings()) { m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(-1)))); @@ -58,6 +59,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp(m_ui.eeRoundingMode, tr("Rounding Mode"), tr("Chop/Zero (Default)"), tr("Changes how PCSX2 handles rounding while emulating the Emotion Engine's Floating Point Unit (EE FPU). " "Because the various FPUs in the PS2 are non-compliant with international standards, some games may need different modes to do math correctly. The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>")); + dialog->registerWidgetHelp(m_ui.eeDivRoundingMode, tr("Division Rounding Mode"), tr("Nearest (Default)"), tr("Determines how the results of floating-point division is rounded. Some games need specific settings; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>")); dialog->registerWidgetHelp(m_ui.eeClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("Changes how PCSX2 handles keeping floats in a standard x86 range. " "The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>")); diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui index e63d6abbf5..d2d859f7bd 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui @@ -95,13 +95,44 @@ </widget> </item> <item row="1" column="0"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string extracomment="Rounding refers here to the mathematical term.">Division Rounding Mode:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="eeDivRoundingMode"> + <item> + <property name="text"> + <string>Nearest (Default)</string> + </property> + </item> + <item> + <property name="text"> + <string>Negative</string> + </property> + </item> + <item> + <property name="text"> + <string>Positive</string> + </property> + </item> + <item> + <property name="text"> + <string>Chop/Zero</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0"> <widget class="QLabel" name="label_12"> <property name="text"> <string extracomment="Clamping: Forcing out of bounds things in bounds by changing them to the closest possible value. In this case, this refers to clamping large PS2 floating point values (which map to infinity or NaN in PCs' IEEE754 floats) to non-infinite ones.">Clamping Mode:</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="1"> <widget class="QComboBox" name="eeClampMode"> <item> <property name="text"> @@ -125,7 +156,7 @@ </item> </widget> </item> - <item row="2" column="0" colspan="2"> + <item row="3" column="0" colspan="2"> <layout class="QGridLayout" name="gridLayout_4"> <item row="1" column="0"> <widget class="QCheckBox" name="eeWaitLoopDetection"> diff --git a/pcsx2-qt/Settings/GameFixSettingsWidget.cpp b/pcsx2-qt/Settings/GameFixSettingsWidget.cpp index 9e30f1f42b..da1e4ded15 100644 --- a/pcsx2-qt/Settings/GameFixSettingsWidget.cpp +++ b/pcsx2-qt/Settings/GameFixSettingsWidget.cpp @@ -18,7 +18,6 @@ GameFixSettingsWidget::GameFixSettingsWidget(SettingsWindow* dialog, QWidget* pa m_ui.setupUi(this); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false); - SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false); @@ -38,7 +37,6 @@ GameFixSettingsWidget::GameFixSettingsWidget(SettingsWindow* dialog, QWidget* pa SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.BlitInternalFPSHack, "EmuCore/Gamefixes", "BlitInternalFPSHack", false); dialog->registerWidgetHelp(m_ui.FpuMulHack, tr("FPU Multiply Hack"), tr("Unchecked"), tr("For Tales of Destiny.")); - dialog->registerWidgetHelp(m_ui.FpuNegDivHack, tr("FPU Negative Divide Hack"), tr("Unchecked"), tr("For Gundam Games.")); dialog->registerWidgetHelp(m_ui.GoemonTlbHack, tr("Preload TLB Hack"), tr("Unchecked"), tr("To avoid TLB miss on Goemon.")); dialog->registerWidgetHelp(m_ui.SoftwareRendererFMVHack, tr("Use Software Renderer For FMVs"), tr("Unchecked"), tr("Needed for some games with complex FMV rendering.")); dialog->registerWidgetHelp(m_ui.SkipMPEGHack, tr("Skip MPEG Hack"), tr("Unchecked"), tr("Skips videos/FMVs in games to avoid game hanging/freezes.")); diff --git a/pcsx2-qt/Settings/GameFixSettingsWidget.ui b/pcsx2-qt/Settings/GameFixSettingsWidget.ui index 1439c3cd4d..224f737c52 100644 --- a/pcsx2-qt/Settings/GameFixSettingsWidget.ui +++ b/pcsx2-qt/Settings/GameFixSettingsWidget.ui @@ -56,13 +56,6 @@ <string>Game Fixes (NOT recommended to change globally)</string> </property> <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QCheckBox" name="FpuNegDivHack"> - <property name="text"> - <string extracomment="FPU = Floating Point Unit. A part of the PS2's CPU. Do not translate.\nNegative Divide: mathematical term.\nGundam: a multimedia franchise name. Leave as-is or use an official translation.">FPU Negative Divide Hack</string> - </property> - </widget> - </item> <item> <widget class="QCheckBox" name="FpuMulHack"> <property name="text"> diff --git a/pcsx2/Config.h b/pcsx2/Config.h index d7293f43c7..c9b47ed2f8 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -153,7 +153,6 @@ enum GamefixId GamefixId_FIRST = 0, Fix_FpuMultiply = GamefixId_FIRST, - Fix_FpuNegDiv, Fix_GoemonTlbMiss, Fix_SoftwareRendererFMV, Fix_SkipMpeg, @@ -539,6 +538,7 @@ struct Pcsx2Config RecompilerOptions Recompiler; FPControlRegister FPUFPCR; + FPControlRegister FPUDivFPCR; FPControlRegister VU0FPCR; FPControlRegister VU1FPCR; @@ -899,7 +899,6 @@ struct Pcsx2Config BITFIELD32() bool FpuMulHack : 1, // Tales of Destiny hangs. - FpuNegDivHack : 1, // Gundam games messed up camera-view. GoemonTlbHack : 1, // Gomeon tlb miss hack. The game need to access unmapped virtual address. Instead to handle it as exception, tlb are preloaded at startup SoftwareRendererFMVHack : 1, // Switches to software renderer for FMVs SkipMPEGHack : 1, // Skips MPEG videos (Katamari and other games need this) @@ -1264,7 +1263,6 @@ namespace EmuFolders //------------ SPECIAL GAME FIXES!!! --------------- #define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. #define CHECK_FPUMULHACK (EmuConfig.Gamefixes.FpuMulHack) // Special Fix for Tales of Destiny hangs. -#define CHECK_FPUNEGDIVHACK (EmuConfig.Gamefixes.FpuNegDivHack) // Special Fix for Gundam games messed up camera-view. #define CHECK_XGKICKHACK (EmuConfig.Gamefixes.XgKickHack) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics. #define CHECK_EETIMINGHACK (EmuConfig.Gamefixes.EETimingHack) // Fix all scheduled events to happen in 1 cycle. #define CHECK_INSTANTDMAHACK (EmuConfig.Gamefixes.InstantDMAHack) // Attempt to finish DMA's instantly, useful for games which rely on cache emulation. diff --git a/pcsx2/Docs/gamedb-schema.json b/pcsx2/Docs/gamedb-schema.json index 5223a21c51..9a41afbaa2 100644 --- a/pcsx2/Docs/gamedb-schema.json +++ b/pcsx2/Docs/gamedb-schema.json @@ -40,6 +40,11 @@ "minimum": 0, "maximum": 3 }, + "eeDivRoundMode": { + "type": "integer", + "minimum": 0, + "maximum": 3 + }, "vuRoundMode": { "type": "integer", "minimum": 0, @@ -97,7 +102,6 @@ "DMABusyHack", "EETimingHack", "FpuMulHack", - "FpuNegDivHack", "GIFFIFOHack", "GoemonTlbHack", "IbitHack", diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index 26cab1e021..46af1b52fc 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -120,6 +120,15 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml: else Console.Error(fmt::format("[GameDB] Invalid EE round mode '{}', specified for serial: '{}'.", eeVal, serial)); } + if (node["roundModes"].has_child("eeDivRoundMode")) + { + int eeVal = -1; + node["roundModes"]["eeDivRoundMode"] >> eeVal; + if (eeVal >= 0 && eeVal < static_cast<int>(FPRoundMode::MaxCount)) + gameEntry.eeDivRoundMode = static_cast<FPRoundMode>(eeVal); + else + Console.Error(fmt::format("[GameDB] Invalid EE division round mode '{}', specified for serial: '{}'.", eeVal, serial)); + } if (node["roundModes"].has_child("vuRoundMode")) { int vuVal = -1; @@ -447,6 +456,19 @@ void GameDatabaseSchema::GameEntry::applyGameFixes(Pcsx2Config& config, bool app } } + if (eeDivRoundMode < FPRoundMode::MaxCount) + { + if (applyAuto) + { + Console.WriteLn("(GameDB) Changing EE/FPU divison roundmode to %d [%s]", eeRoundMode, s_round_modes[static_cast<u8>(eeDivRoundMode)]); + config.Cpu.FPUDivFPCR.SetRoundMode(eeDivRoundMode); + } + else + { + Console.Warning("[GameDB] Skipping changing EE/FPU roundmode to %d [%s]", eeRoundMode, s_round_modes[static_cast<u8>(eeRoundMode)]); + } + } + if (vu0RoundMode < FPRoundMode::MaxCount) { if (applyAuto) diff --git a/pcsx2/GameDatabase.h b/pcsx2/GameDatabase.h index 8b24b20587..b9f73f213f 100644 --- a/pcsx2/GameDatabase.h +++ b/pcsx2/GameDatabase.h @@ -93,6 +93,7 @@ namespace GameDatabaseSchema std::string region; Compatibility compat = Compatibility::Unknown; FPRoundMode eeRoundMode = FPRoundMode::MaxCount; + FPRoundMode eeDivRoundMode = FPRoundMode::MaxCount; FPRoundMode vu0RoundMode = FPRoundMode::MaxCount; FPRoundMode vu1RoundMode = FPRoundMode::MaxCount; ClampMode eeClampMode = ClampMode::Undefined; diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index acdd258326..74fe09ad22 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -4450,7 +4450,12 @@ void FullscreenUI::DrawAdvancedSettingsPage() DrawIntListSetting(bsi, FSUI_CSTR("Rounding Mode"), FSUI_CSTR("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), true); + "EmuCore/CPU", "FPU.Roundmode", static_cast<int>(FPRoundMode::ChopZero), ee_rounding_mode_settings, + std::size(ee_rounding_mode_settings), true); + DrawIntListSetting(bsi, FSUI_CSTR("Division Rounding Mode"), + FSUI_CSTR("Determines how the results of floating-point division is rounded. Some games need specific settings."), + "EmuCore/CPU", "FPUDiv.Roundmode", static_cast<int>(FPRoundMode::Nearest), + ee_rounding_mode_settings, std::size(ee_rounding_mode_settings), true); DrawClampingModeSetting(bsi, FSUI_CSTR("Clamping Mode"), FSUI_CSTR("Determines how out-of-range floating point numbers are handled. Some games need specific settings."), -1); @@ -4470,12 +4475,14 @@ void FullscreenUI::DrawAdvancedSettingsPage() MenuHeading(FSUI_CSTR("Vector Units")); DrawIntListSetting(bsi, FSUI_CSTR("VU0 Rounding Mode"), FSUI_CSTR("Determines how the results of floating-point operations are rounded. Some games need specific settings."), - "EmuCore/CPU", "VU0.Roundmode", 3, ee_rounding_mode_settings, std::size(ee_rounding_mode_settings), true); + "EmuCore/CPU", "VU0.Roundmode", static_cast<int>(FPRoundMode::ChopZero), + ee_rounding_mode_settings, std::size(ee_rounding_mode_settings), true); DrawClampingModeSetting(bsi, FSUI_CSTR("VU0 Clamping Mode"), FSUI_CSTR("Determines how out-of-range floating point numbers are handled. Some games need specific settings."), 0); DrawIntListSetting(bsi, FSUI_CSTR("VU1 Rounding Mode"), FSUI_CSTR("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), true); + "EmuCore/CPU", "VU1.Roundmode", static_cast<int>(FPRoundMode::ChopZero), + ee_rounding_mode_settings, std::size(ee_rounding_mode_settings), true); DrawClampingModeSetting(bsi, FSUI_CSTR("VU1 Clamping Mode"), FSUI_CSTR("Determines how out-of-range floating point numbers are handled. Some games need specific settings."), 1); DrawToggleSetting(bsi, FSUI_CSTR("Enable VU0 Recompiler (Micro Mode)"), @@ -4595,7 +4602,6 @@ void FullscreenUI::DrawGameFixesSettingsPage() FSUI_CSTR("Game fixes should not be modified unless you are aware of what each option does and the implications of doing so."), false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); - DrawToggleSetting(bsi, FSUI_CSTR("FPU Negative Div Hack"), FSUI_CSTR("For Gundam games."), "EmuCore/Gamefixes", "FpuNegDivHack", false); DrawToggleSetting(bsi, FSUI_CSTR("FPU Multiply Hack"), FSUI_CSTR("For Tales of Destiny."), "EmuCore/Gamefixes", "FpuMulHack", false); DrawToggleSetting(bsi, FSUI_CSTR("Use Software Renderer For FMVs"), FSUI_CSTR("Needed for some games with complex FMV rendering."), "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index e05441565e..c25949fb76 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -501,12 +501,17 @@ bool Pcsx2Config::CpuOptions::operator!=(const CpuOptions& right) const bool Pcsx2Config::CpuOptions::operator==(const CpuOptions& right) const { - return OpEqu(FPUFPCR) && OpEqu(VU0FPCR) && OpEqu(VU1FPCR) && OpEqu(AffinityControlMode) && OpEqu(Recompiler); + return OpEqu(FPUFPCR) && OpEqu(FPUDivFPCR) && OpEqu(VU0FPCR) && OpEqu(VU1FPCR) && OpEqu(AffinityControlMode) && OpEqu(Recompiler); } Pcsx2Config::CpuOptions::CpuOptions() { FPUFPCR = DEFAULT_FPU_FP_CONTROL_REGISTER; + + // Rounding defaults to nearest to match old behavior. + // TODO: Make it default to the same as the rest of the FPU operations, at some point. + FPUDivFPCR = FPControlRegister(DEFAULT_FPU_FP_CONTROL_REGISTER).SetRoundMode(FPRoundMode::Nearest); + VU0FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; VU1FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; AffinityControlMode = 0; @@ -536,6 +541,7 @@ void Pcsx2Config::CpuOptions::LoadSave(SettingsWrapper& wrap) }; read_fpcr(FPUFPCR, "FPU"); + read_fpcr(FPUDivFPCR, "FPUDiv"); read_fpcr(VU0FPCR, "VU0"); read_fpcr(VU1FPCR, "VU1"); @@ -1284,7 +1290,6 @@ bool Pcsx2Config::DEV9Options::HostEntry::operator!=(const HostEntry& right) con static const char* const tbl_GamefixNames[] = { "FpuMul", - "FpuNegDiv", "GoemonTlb", "SoftwareRendererFMV", "SkipMPEG", @@ -1328,7 +1333,6 @@ void Pcsx2Config::GamefixOptions::Set(GamefixId id, bool enabled) // clang-format off case Fix_VuAddSub: VuAddSubHack = enabled; break; case Fix_FpuMultiply: FpuMulHack = enabled; break; - case Fix_FpuNegDiv: FpuNegDivHack = enabled; break; case Fix_XGKick: XgKickHack = enabled; break; case Fix_EETiming: EETimingHack = enabled; break; case Fix_InstantDMA: InstantDMAHack = enabled; break; @@ -1367,7 +1371,6 @@ bool Pcsx2Config::GamefixOptions::Get(GamefixId id) const // clang-format off case Fix_VuAddSub: return VuAddSubHack; case Fix_FpuMultiply: return FpuMulHack; - case Fix_FpuNegDiv: return FpuNegDivHack; case Fix_XGKick: return XgKickHack; case Fix_EETiming: return EETimingHack; case Fix_InstantDMA: return InstantDMAHack; @@ -1396,7 +1399,6 @@ void Pcsx2Config::GamefixOptions::LoadSave(SettingsWrapper& wrap) SettingsWrapBitBool(VuAddSubHack); SettingsWrapBitBool(FpuMulHack); - SettingsWrapBitBool(FpuNegDivHack); SettingsWrapBitBool(XgKickHack); SettingsWrapBitBool(EETimingHack); SettingsWrapBitBool(InstantDMAHack); diff --git a/pcsx2/x86/iFPU.cpp b/pcsx2/x86/iFPU.cpp index aacd034ab5..f4bf4de5e4 100644 --- a/pcsx2/x86/iFPU.cpp +++ b/pcsx2/x86/iFPU.cpp @@ -1102,32 +1102,8 @@ void recDIV_S_xmm(int info) int t0reg = _allocTempXMMreg(XMMT_FPS); //Console.WriteLn("DIV"); - if (CHECK_FPUNEGDIVHACK) - { - if (EmuConfig.Cpu.FPUFPCR.GetRoundMode() != FPRoundMode::NegativeInfinity) - { - // Set roundmode to nearest since it isn't already - //Console.WriteLn("div to negative inf"); - - roundmode_neg = EmuConfig.Cpu.FPUFPCR; - roundmode_neg.SetRoundMode(FPRoundMode::NegativeInfinity); - xLDMXCSR(ptr32[&roundmode_neg.bitmask]); - roundmodeFlag = true; - } - } - else - { - if (EmuConfig.Cpu.FPUFPCR.GetRoundMode() != FPRoundMode::Nearest) - { - // Set roundmode to nearest since it isn't already - //Console.WriteLn("div to nearest"); - - roundmode_nearest = EmuConfig.Cpu.FPUFPCR; - roundmode_nearest.SetRoundMode(FPRoundMode::Nearest); - xLDMXCSR(ptr32[&roundmode_nearest.bitmask]); - roundmodeFlag = true; - } - } + if (EmuConfig.Cpu.FPUFPCR.bitmask != EmuConfig.Cpu.FPUDivFPCR.bitmask) + xLDMXCSR(ptr32[&EmuConfig.Cpu.FPUDivFPCR.bitmask]); switch (info & (PROCESS_EE_S | PROCESS_EE_T)) { @@ -1190,8 +1166,10 @@ void recDIV_S_xmm(int info) recDIVhelper2(EEREC_D, t0reg); break; } - if (roundmodeFlag) + + if (EmuConfig.Cpu.FPUFPCR.bitmask != EmuConfig.Cpu.FPUDivFPCR.bitmask) xLDMXCSR(ptr32[&EmuConfig.Cpu.FPUFPCR.bitmask]); + _freeXMMreg(t0reg); } @@ -1890,10 +1868,9 @@ void recRSQRThelper2(int regd, int t0reg) // Preforms the RSQRT function when re void recRSQRT_S_xmm(int info) { EE::Profiler.EmitOp(eeOpcode::RSQRT_F); - // iFPUd (Full mode) sets roundmode to nearest for rSQRT. - // Should this do the same, or should Full mode leave roundmode alone? --air - int t0reg = _allocTempXMMreg(XMMT_FPS); + // RSQRT doesn't change the round mode, because RSQRTSS ignores the rounding mode in MXCSR. + const int t0reg = _allocTempXMMreg(XMMT_FPS); //Console.WriteLn("FPU: RSQRT"); switch (info & (PROCESS_EE_S | PROCESS_EE_T)) diff --git a/pcsx2/x86/iFPUd.cpp b/pcsx2/x86/iFPUd.cpp index 62f5510bad..84f8d41b5a 100644 --- a/pcsx2/x86/iFPUd.cpp +++ b/pcsx2/x86/iFPUd.cpp @@ -657,35 +657,10 @@ alignas(16) static FPControlRegister roundmode_nearest, roundmode_neg; void recDIV_S_xmm(int info) { EE::Profiler.EmitOp(eeOpcode::DIV_F); - bool roundmodeFlag = false; //Console.WriteLn("DIV"); - if (CHECK_FPUNEGDIVHACK) - { - if (EmuConfig.Cpu.FPUFPCR.GetRoundMode() != FPRoundMode::NegativeInfinity) - { - // Set roundmode to nearest since it isn't already - //Console.WriteLn("div to negative inf"); - - roundmode_neg = EmuConfig.Cpu.FPUFPCR; - roundmode_neg.SetRoundMode(FPRoundMode::NegativeInfinity); - xLDMXCSR(ptr32[&roundmode_neg.bitmask]); - roundmodeFlag = true; - } - } - else - { - if (EmuConfig.Cpu.FPUFPCR.GetRoundMode() != FPRoundMode::Nearest) - { - // Set roundmode to nearest since it isn't already - //Console.WriteLn("div to nearest"); - - roundmode_nearest = EmuConfig.Cpu.FPUFPCR; - roundmode_nearest.SetRoundMode(FPRoundMode::Nearest); - xLDMXCSR(ptr32[&roundmode_nearest.bitmask]); - roundmodeFlag = true; - } - } + if (EmuConfig.Cpu.FPUFPCR.bitmask != EmuConfig.Cpu.FPUDivFPCR.bitmask) + xLDMXCSR(ptr32[&EmuConfig.Cpu.FPUDivFPCR.bitmask]); int sreg, treg; @@ -698,8 +673,9 @@ void recDIV_S_xmm(int info) xMOVSS(xRegisterSSE(EEREC_D), xRegisterSSE(sreg)); - if (roundmodeFlag) + if (EmuConfig.Cpu.FPUFPCR.bitmask != EmuConfig.Cpu.FPUDivFPCR.bitmask) xLDMXCSR(ptr32[&EmuConfig.Cpu.FPUFPCR.bitmask]); + _freeXMMreg(sreg); _freeXMMreg(treg); }