mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 12:19:12 +00:00
merge
This commit is contained in:
parent
b3630a69b3
commit
76c08d3a22
119 changed files with 47784 additions and 40258 deletions
|
@ -672,7 +672,7 @@ dolphin_make_imported_target_if_missing(LibLZMA::LibLZMA LIBLZMA)
|
|||
|
||||
dolphin_find_optional_system_library_pkgconfig(ZSTD libzstd>=1.4.0 zstd::zstd Externals/zstd)
|
||||
|
||||
dolphin_find_optional_system_library_pkgconfig(ZLIB zlib-ng ZLIB::ZLIB Externals/zlib-ng)
|
||||
add_subdirectory(Externals/zlib-ng)
|
||||
|
||||
dolphin_find_optional_system_library_pkgconfig(MINIZIP
|
||||
"minizip>=4.0.4" minizip::minizip Externals/minizip-ng
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# GEDE01, GEDP01 - Eternal Darkness
|
||||
# GEDE01, GEDP01, GEDJ01, GEDW01 - Eternal Darkness
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
|
8
Data/Sys/GameSettings/GEDE01.ini
Normal file
8
Data/Sys/GameSettings/GEDE01.ini
Normal file
|
@ -0,0 +1,8 @@
|
|||
# GEDE01 - Eternal Darkness
|
||||
|
||||
[OnFrame]
|
||||
$Fix startup hang
|
||||
0x801EF444:dword:0x480371ED
|
||||
|
||||
[OnFrame_Enabled]
|
||||
$Fix startup hang
|
8
Data/Sys/GameSettings/GEDJ01.ini
Normal file
8
Data/Sys/GameSettings/GEDJ01.ini
Normal file
|
@ -0,0 +1,8 @@
|
|||
# GEDJ01 - Eternal Darkness
|
||||
|
||||
[OnFrame]
|
||||
$Fix startup hang
|
||||
0x801E4588:dword:0x48036E71
|
||||
|
||||
[OnFrame_Enabled]
|
||||
$Fix startup hang
|
8
Data/Sys/GameSettings/GEDP01.ini
Normal file
8
Data/Sys/GameSettings/GEDP01.ini
Normal file
|
@ -0,0 +1,8 @@
|
|||
# GEDP01 - Eternal Darkness
|
||||
|
||||
[OnFrame]
|
||||
$Fix startup hang
|
||||
0x801E3BC4:dword:0x48036F15
|
||||
|
||||
[OnFrame_Enabled]
|
||||
$Fix startup hang
|
8
Data/Sys/GameSettings/GEDW01.ini
Normal file
8
Data/Sys/GameSettings/GEDW01.ini
Normal file
|
@ -0,0 +1,8 @@
|
|||
# GEDW01 - Eternal Darkness
|
||||
|
||||
[OnFrame]
|
||||
$Fix startup hang
|
||||
0x801BE42C:dword:0x48036E65
|
||||
|
||||
[OnFrame_Enabled]
|
||||
$Fix startup hang
|
|
@ -9,8 +9,5 @@
|
|||
[ActionReplay]
|
||||
# Add action replay cheats here.
|
||||
|
||||
[Video_Settings]
|
||||
|
||||
[Video_Hacks]
|
||||
EFBAccessEnable = False
|
||||
ImmediateXFBEnable = False
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# GXBE69, GXBP69 - SSX3
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
||||
[OnFrame]
|
||||
# Add memory patches to be applied every frame here.
|
||||
|
||||
[ActionReplay]
|
||||
# Add action replay cheats here.
|
||||
|
||||
[Video_Hacks]
|
||||
EFBAccessEnable = False
|
||||
|
|
@ -16,6 +16,3 @@ $Disable blur
|
|||
|
||||
[Video_Settings]
|
||||
SafeTextureCacheColorSamples = 0
|
||||
|
||||
[Video_Hacks]
|
||||
EFBAccessEnable = False
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# SNCE8P, SNCJ8P, SNCP8P - SONIC COLOURS
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
||||
[OnFrame]
|
||||
# Add memory patches to be applied every frame here.
|
||||
|
||||
[ActionReplay]
|
||||
# Add action replay cheats here.
|
||||
|
||||
[Video_Hacks]
|
||||
EFBAccessEnable = False
|
||||
|
22
Flatpak/SDL2/SDL2.json
Normal file
22
Flatpak/SDL2/SDL2.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "SDL2",
|
||||
"buildsystem": "autotools",
|
||||
"config-opts": ["--disable-static"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "../../Externals/SDL/SDL"
|
||||
}
|
||||
],
|
||||
"cleanup": [ "/bin/sdl2-config",
|
||||
"/include",
|
||||
"/lib/libSDL2.la",
|
||||
"/lib/libSDL2main.a",
|
||||
"/lib/libSDL2main.la",
|
||||
"/lib/libSDL2_test.a",
|
||||
"/lib/libSDL2_test.la",
|
||||
"/lib/cmake",
|
||||
"/share/aclocal",
|
||||
"/lib/pkgconfig"]
|
||||
}
|
||||
|
8
Flatpak/fill_release_node.sh
Executable file
8
Flatpak/fill_release_node.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
DATE=$(git log -1 --pretty=%cd --date=iso8601 --date=format:'%Y-%m-%d')
|
||||
sed -i -e "s/@DATE_PLACEHOLDER/${DATE}/" org.DolphinEmu.dolphin-emu.metainfo.xml
|
||||
VERSION=$(git describe --tags | sed -E 's/^([0-9]+-[0-9]+).*/\1/')
|
||||
sed -i -e "s/@VERSION_PLACEHOLDER/${VERSION}/" org.DolphinEmu.dolphin-emu.metainfo.xml
|
||||
|
||||
|
49
Flatpak/org.DolphinEmu.dolphin-emu.metainfo.xml.in
Normal file
49
Flatpak/org.DolphinEmu.dolphin-emu.metainfo.xml.in
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2016 Jeremy Newton -->
|
||||
<component type="desktop-application">
|
||||
<id>org.DolphinEmu.dolphin-emu</id>
|
||||
<name>Dolphin Emulator</name>
|
||||
<developer id="org.dolphin-emu">
|
||||
<name>Dolphin Emulator Project</name>
|
||||
</developer>
|
||||
<summary>GameCube / Wii</summary>
|
||||
<metadata_license>CC-BY-SA-3.0</metadata_license>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<content_rating type="oars-1.0"/>
|
||||
<!-- Descriptions taken from Dolphin Homepage -->
|
||||
<description><p>Dolphin is an emulator for two recent Nintendo video game consoles: the GameCube and the Wii. It allows PC gamers to enjoy games for these two consoles in full HD (1080p) with several enhancements: compatibility with all PC controllers, turbo speed, networked multiplayer, and even more!</p></description>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Dolphin's main window</caption>
|
||||
<image type="source">http://dolphin-emu.org/m/user/flatpak/screenshot_1.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>In-game</caption>
|
||||
<image type="source">http://dolphin-emu.org/m/user/flatpak/screenshot_2.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Graphics configuration</caption>
|
||||
<image type="source">http://dolphin-emu.org/m/user/flatpak/screenshot_3.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Controller configuration</caption>
|
||||
<image type="source">http://dolphin-emu.org/m/user/flatpak/screenshot_4.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<launchable type="desktop-id">dolphin-emu.desktop</launchable>
|
||||
<provides>
|
||||
<binary>dolphin-emu</binary>
|
||||
<id>dolphin-emu.desktop</id>
|
||||
</provides>
|
||||
<releases>
|
||||
<release version="@VERSION_PLACEHOLDER" date="@DATE_PLACEHOLDER"/>
|
||||
</releases>
|
||||
<url type="homepage">https://dolphin-emu.org</url>
|
||||
<url type="bugtracker">https://bugs.dolphin-emu.org/projects/emulator/issues</url>
|
||||
<url type="faq">https://dolphin-emu.org/docs/faq/</url>
|
||||
<url type="help">https://dolphin-emu.org/docs/guides/</url>
|
||||
<url type="translate">https://www.transifex.com/projects/p/dolphin-emu</url>
|
||||
<url type="contact">https://dolphin-emu.org/docs/faq/#ive-got-idea-make-dolphin-better-how-should-i-tell</url>
|
||||
<url type="vcs-browser">https://github.com/dolphin-emu/dolphin</url>
|
||||
<url type="contribute">https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md</url>
|
||||
</component>
|
83
Flatpak/org.DolphinEmu.dolphin-emu.yml
Normal file
83
Flatpak/org.DolphinEmu.dolphin-emu.yml
Normal file
|
@ -0,0 +1,83 @@
|
|||
app-id: org.DolphinEmu.dolphin-emu
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: '6.7'
|
||||
sdk: org.kde.Sdk
|
||||
command: dolphin-emu-wrapper
|
||||
rename-desktop-file: dolphin-emu.desktop
|
||||
rename-icon: dolphin-emu
|
||||
finish-args:
|
||||
- --device=all
|
||||
- --socket=pulseaudio
|
||||
# dolphin doesn't work on wayland (only the ui does), if a user were to set
|
||||
# this env variable globally to wayland then games wouldn't work.
|
||||
# we overwrite the setting and force xcb to prevent this from happening.
|
||||
- --env=QT_QPA_PLATFORM=xcb
|
||||
- --socket=x11
|
||||
- --share=network
|
||||
- --share=ipc
|
||||
# required for the emulated bluetooth adapter feature to work.
|
||||
- --allow=bluetooth
|
||||
- --filesystem=xdg-run/app/com.discordapp.Discord:create
|
||||
- --talk-name=org.freedesktop.ScreenSaver
|
||||
# required for Gamescope on Steam Deck
|
||||
- --filesystem=xdg-run/gamescope-0:ro
|
||||
modules:
|
||||
# enables motion controls on non-wii controllers (switch, ps4, etc)
|
||||
# requires a udev rule enabling Motion Sensors access
|
||||
- name: libevdev
|
||||
buildsystem: meson
|
||||
config-opts:
|
||||
- -Dtests=disabled
|
||||
- -Ddocumentation=disabled
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://www.freedesktop.org/software/libevdev/libevdev-1.13.3.tar.xz
|
||||
sha256: abf1aace86208eebdd5d3550ffded4c8d73bb405b796d51c389c9d0604cbcfbf
|
||||
x-checker-data:
|
||||
type: anitya
|
||||
project-id: 20540
|
||||
stable-only: true
|
||||
url-template: https://www.freedesktop.org/software/libevdev/libevdev-$version.tar.xz
|
||||
|
||||
# needed for screensaver inhibition
|
||||
- name: xdg-screensaver-shim
|
||||
buildsystem: meson
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/Unrud/xdg-screensaver-shim/archive/0.0.2.tar.gz
|
||||
sha256: 0ed2a69fe6ee6cbffd2fe16f85116db737f17fb1e79bfb812d893cf15c728399
|
||||
|
||||
# build the vendored SDL2 from Externals until the runtime gets 2.30.6
|
||||
- SDL2/SDL2.json
|
||||
|
||||
- name: dolphin-emu
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DENABLE_ALSA=OFF
|
||||
- -DENABLE_SDL=ON
|
||||
- -DENABLE_EVDEV=ON
|
||||
- -DDISTRIBUTOR=dolphin-emu.org
|
||||
cleanup:
|
||||
- /share/man
|
||||
post-install:
|
||||
- install -D -t ${FLATPAK_DEST}/bin/ dolphin-emu-wrapper
|
||||
- "${FLATPAK_BUILDER_BUILDDIR}/Flatpak/fill_release_node.sh"
|
||||
- install -Dm644 -t ${FLATPAK_DEST}/share/metainfo/ org.DolphinEmu.dolphin-emu.metainfo.xml
|
||||
- desktop-file-edit --set-key=Exec --set-value='/app/bin/dolphin-emu-wrapper'
|
||||
/app/share/applications/dolphin-emu.desktop
|
||||
sources:
|
||||
- type: dir
|
||||
path: ..
|
||||
- type: file
|
||||
path: org.DolphinEmu.dolphin-emu.metainfo.xml.in
|
||||
dest-filename: org.DolphinEmu.dolphin-emu.metainfo.xml
|
||||
- type: script
|
||||
commands:
|
||||
- |
|
||||
for i in {0..9}; do
|
||||
test -S $XDG_RUNTIME_DIR/discord-ipc-$i ||
|
||||
ln -sf {app/com.discordapp.Discord,$XDG_RUNTIME_DIR}/discord-ipc-$i;
|
||||
done
|
||||
dolphin-emu "$@"
|
||||
dest-filename: dolphin-emu-wrapper
|
2829
Languages/po/ar.po
2829
Languages/po/ar.po
File diff suppressed because it is too large
Load diff
3483
Languages/po/ca.po
3483
Languages/po/ca.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/cs.po
2775
Languages/po/cs.po
File diff suppressed because it is too large
Load diff
2777
Languages/po/da.po
2777
Languages/po/da.po
File diff suppressed because it is too large
Load diff
2785
Languages/po/de.po
2785
Languages/po/de.po
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2775
Languages/po/el.po
2775
Languages/po/el.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/en.po
2775
Languages/po/en.po
File diff suppressed because it is too large
Load diff
2823
Languages/po/es.po
2823
Languages/po/es.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/fa.po
2775
Languages/po/fa.po
File diff suppressed because it is too large
Load diff
3056
Languages/po/fi.po
3056
Languages/po/fi.po
File diff suppressed because it is too large
Load diff
2849
Languages/po/fr.po
2849
Languages/po/fr.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/hr.po
2775
Languages/po/hr.po
File diff suppressed because it is too large
Load diff
2783
Languages/po/hu.po
2783
Languages/po/hu.po
File diff suppressed because it is too large
Load diff
2815
Languages/po/it.po
2815
Languages/po/it.po
File diff suppressed because it is too large
Load diff
2815
Languages/po/ja.po
2815
Languages/po/ja.po
File diff suppressed because it is too large
Load diff
2794
Languages/po/ko.po
2794
Languages/po/ko.po
File diff suppressed because it is too large
Load diff
2777
Languages/po/ms.po
2777
Languages/po/ms.po
File diff suppressed because it is too large
Load diff
2779
Languages/po/nb.po
2779
Languages/po/nb.po
File diff suppressed because it is too large
Load diff
2910
Languages/po/nl.po
2910
Languages/po/nl.po
File diff suppressed because it is too large
Load diff
2777
Languages/po/pl.po
2777
Languages/po/pl.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/pt.po
2775
Languages/po/pt.po
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2775
Languages/po/ro.po
2775
Languages/po/ro.po
File diff suppressed because it is too large
Load diff
2821
Languages/po/ru.po
2821
Languages/po/ru.po
File diff suppressed because it is too large
Load diff
2775
Languages/po/sr.po
2775
Languages/po/sr.po
File diff suppressed because it is too large
Load diff
2811
Languages/po/sv.po
2811
Languages/po/sv.po
File diff suppressed because it is too large
Load diff
2797
Languages/po/tr.po
2797
Languages/po/tr.po
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -302,7 +302,7 @@ public final class NativeLibrary
|
|||
|
||||
public static native int DefaultCPUCore();
|
||||
|
||||
public static native String GetDefaultGraphicsBackendName();
|
||||
public static native String GetDefaultGraphicsBackendConfigName();
|
||||
|
||||
public static native int GetMaxLogLevel();
|
||||
|
||||
|
|
|
@ -789,7 +789,7 @@ enum class BooleanSetting(
|
|||
Settings.FILE_GFX,
|
||||
Settings.SECTION_GFX_HACKS,
|
||||
"EFBAccessEnable",
|
||||
true
|
||||
false
|
||||
),
|
||||
GFX_HACK_EFB_DEFER_INVALIDATION(
|
||||
Settings.FILE_GFX,
|
||||
|
|
|
@ -45,7 +45,7 @@ enum class StringSetting(
|
|||
Settings.FILE_DOLPHIN,
|
||||
Settings.SECTION_INI_CORE,
|
||||
"GFXBackend",
|
||||
NativeLibrary.GetDefaultGraphicsBackendName()
|
||||
NativeLibrary.GetDefaultGraphicsBackendConfigName()
|
||||
),
|
||||
MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
|
||||
MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),
|
||||
|
|
|
@ -146,7 +146,7 @@ void Host_UpdateDisasmDialog()
|
|||
{
|
||||
}
|
||||
|
||||
void Host_JitCacheCleared()
|
||||
void Host_JitCacheInvalidation()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -408,9 +408,10 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_DefaultCPUCo
|
|||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDefaultGraphicsBackendName(JNIEnv* env, jclass)
|
||||
Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDefaultGraphicsBackendConfigName(JNIEnv* env,
|
||||
jclass)
|
||||
{
|
||||
return ToJString(env, VideoBackendBase::GetDefaultBackendName());
|
||||
return ToJString(env, VideoBackendBase::GetDefaultBackendConfigName());
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetMaxLogLevel(JNIEnv*, jclass)
|
||||
|
|
|
@ -47,7 +47,7 @@ private:
|
|||
std::array<uint32_t, 36 + sizeof...(ExtraMatches)> _conns;
|
||||
std::optional<V> _val;
|
||||
|
||||
TrieEntry() { std::fill(_conns.begin(), _conns.end(), INVALID_CONN); }
|
||||
TrieEntry() { _conns.fill(INVALID_CONN); }
|
||||
};
|
||||
|
||||
constexpr size_t IndexOf(char c) const
|
||||
|
|
|
@ -17,72 +17,72 @@
|
|||
|
||||
namespace Common
|
||||
{
|
||||
SettingsHandler::SettingsHandler() : m_buffer{}, m_position{0}, m_key{INITIAL_SEED}, decoded{""}
|
||||
namespace
|
||||
{
|
||||
// Key used to encrypt/decrypt setting.txt contents
|
||||
constexpr u32 INITIAL_SEED = 0x73B5DBFA;
|
||||
} // namespace
|
||||
|
||||
SettingsWriter::SettingsWriter() : m_buffer{}, m_position{0}, m_key{INITIAL_SEED}
|
||||
{
|
||||
}
|
||||
|
||||
SettingsHandler::SettingsHandler(const Buffer& buffer) : SettingsHandler()
|
||||
{
|
||||
m_buffer = buffer;
|
||||
Decrypt();
|
||||
}
|
||||
|
||||
const SettingsHandler::Buffer& SettingsHandler::GetBytes() const
|
||||
const SettingsBuffer& SettingsWriter::GetBytes() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
std::string SettingsHandler::GetValue(std::string_view key) const
|
||||
std::string SettingsReader::GetValue(std::string_view key) const
|
||||
{
|
||||
constexpr char delim[] = "\n";
|
||||
std::string toFind = std::string(delim).append(key).append("=");
|
||||
size_t found = decoded.find(toFind);
|
||||
size_t found = m_decoded.find(toFind);
|
||||
|
||||
if (found != std::string_view::npos)
|
||||
{
|
||||
size_t delimFound = decoded.find(delim, found + toFind.length());
|
||||
size_t delimFound = m_decoded.find(delim, found + toFind.length());
|
||||
if (delimFound == std::string_view::npos)
|
||||
delimFound = decoded.length() - 1;
|
||||
return decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
|
||||
delimFound = m_decoded.length() - 1;
|
||||
return m_decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
|
||||
}
|
||||
else
|
||||
{
|
||||
toFind = std::string(key).append("=");
|
||||
found = decoded.find(toFind);
|
||||
found = m_decoded.find(toFind);
|
||||
if (found == 0)
|
||||
{
|
||||
size_t delimFound = decoded.find(delim, found + toFind.length());
|
||||
size_t delimFound = m_decoded.find(delim, found + toFind.length());
|
||||
if (delimFound == std::string_view::npos)
|
||||
delimFound = decoded.length() - 1;
|
||||
return decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
|
||||
delimFound = m_decoded.length() - 1;
|
||||
return m_decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void SettingsHandler::Decrypt()
|
||||
SettingsReader::SettingsReader(const SettingsBuffer& buffer) : m_decoded{""}
|
||||
{
|
||||
while (m_position < m_buffer.size())
|
||||
u32 key = INITIAL_SEED;
|
||||
for (u32 position = 0; position < buffer.size(); ++position)
|
||||
{
|
||||
decoded.push_back((u8)(m_buffer[m_position] ^ m_key));
|
||||
m_position++;
|
||||
m_key = (m_key >> 31) | (m_key << 1);
|
||||
m_decoded.push_back((u8)(buffer[position] ^ key));
|
||||
key = (key >> 31) | (key << 1);
|
||||
}
|
||||
|
||||
// The decoded data normally uses CRLF line endings, but occasionally
|
||||
// (see the comment in WriteLine), lines can be separated by CRLFLF.
|
||||
// To handle this, we remove every CR and treat LF as the line ending.
|
||||
// (We ignore empty lines.)
|
||||
std::erase(decoded, '\x0d');
|
||||
std::erase(m_decoded, '\x0d');
|
||||
}
|
||||
|
||||
void SettingsHandler::AddSetting(std::string_view key, std::string_view value)
|
||||
void SettingsWriter::AddSetting(std::string_view key, std::string_view value)
|
||||
{
|
||||
WriteLine(fmt::format("{}={}\r\n", key, value));
|
||||
}
|
||||
|
||||
void SettingsHandler::WriteLine(std::string_view str)
|
||||
void SettingsWriter::WriteLine(std::string_view str)
|
||||
{
|
||||
const u32 old_position = m_position;
|
||||
const u32 old_key = m_key;
|
||||
|
@ -106,7 +106,7 @@ void SettingsHandler::WriteLine(std::string_view str)
|
|||
}
|
||||
}
|
||||
|
||||
void SettingsHandler::WriteByte(u8 b)
|
||||
void SettingsWriter::WriteByte(u8 b)
|
||||
{
|
||||
if (m_position >= m_buffer.size())
|
||||
return;
|
||||
|
@ -116,7 +116,7 @@ void SettingsHandler::WriteByte(u8 b)
|
|||
m_key = (m_key >> 31) | (m_key << 1);
|
||||
}
|
||||
|
||||
std::string SettingsHandler::GenerateSerialNumber()
|
||||
std::string SettingsWriter::GenerateSerialNumber()
|
||||
{
|
||||
const std::time_t t = std::time(nullptr);
|
||||
|
||||
|
|
|
@ -13,34 +13,35 @@
|
|||
|
||||
namespace Common
|
||||
{
|
||||
class SettingsHandler
|
||||
using SettingsBuffer = std::array<u8, 0x100>;
|
||||
|
||||
class SettingsWriter
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
SETTINGS_SIZE = 0x100,
|
||||
// Key used to encrypt/decrypt setting.txt contents
|
||||
INITIAL_SEED = 0x73B5DBFA
|
||||
};
|
||||
|
||||
using Buffer = std::array<u8, SETTINGS_SIZE>;
|
||||
SettingsHandler();
|
||||
explicit SettingsHandler(const Buffer& buffer);
|
||||
SettingsWriter();
|
||||
|
||||
void AddSetting(std::string_view key, std::string_view value);
|
||||
|
||||
const Buffer& GetBytes() const;
|
||||
std::string GetValue(std::string_view key) const;
|
||||
const SettingsBuffer& GetBytes() const;
|
||||
|
||||
static std::string GenerateSerialNumber();
|
||||
|
||||
private:
|
||||
void Decrypt();
|
||||
void WriteLine(std::string_view str);
|
||||
void WriteByte(u8 b);
|
||||
|
||||
std::array<u8, SETTINGS_SIZE> m_buffer;
|
||||
SettingsBuffer m_buffer;
|
||||
u32 m_position, m_key;
|
||||
std::string decoded;
|
||||
};
|
||||
|
||||
class SettingsReader
|
||||
{
|
||||
public:
|
||||
explicit SettingsReader(const SettingsBuffer& buffer);
|
||||
|
||||
std::string GetValue(std::string_view key) const;
|
||||
|
||||
private:
|
||||
std::string m_decoded;
|
||||
};
|
||||
} // namespace Common
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "Common/Version.h"
|
||||
#include "Common/WorkQueueThread.h"
|
||||
#include "Core/Config/AchievementSettings.h"
|
||||
#include "Core/Config/FreeLookSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
|
@ -62,7 +64,7 @@ void AchievementManager::Init()
|
|||
[](const char* message, const rc_client_t* client) {
|
||||
INFO_LOG_FMT(ACHIEVEMENTS, "{}", message);
|
||||
});
|
||||
rc_client_set_hardcore_enabled(m_client, Config::Get(Config::RA_HARDCORE_ENABLED));
|
||||
SetHardcoreMode();
|
||||
m_queue.Reset("AchievementManagerQueue", [](const std::function<void()>& func) { func(); });
|
||||
m_image_queue.Reset("AchievementManagerImageQueue",
|
||||
[](const std::function<void()>& func) { func(); });
|
||||
|
@ -361,6 +363,13 @@ std::recursive_mutex& AchievementManager::GetLock()
|
|||
void AchievementManager::SetHardcoreMode()
|
||||
{
|
||||
rc_client_set_hardcore_enabled(m_client, Config::Get(Config::RA_HARDCORE_ENABLED));
|
||||
if (Config::Get(Config::RA_HARDCORE_ENABLED))
|
||||
{
|
||||
if (Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f)
|
||||
Config::SetBaseOrCurrent(Config::MAIN_EMULATION_SPEED, 1.0f);
|
||||
Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, false);
|
||||
Config::SetBaseOrCurrent(Config::MAIN_ENABLE_CHEATS, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool AchievementManager::IsHardcoreModeActive() const
|
||||
|
|
|
@ -371,12 +371,12 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
|
|||
|
||||
const auto fs = system.GetIOS()->GetFS();
|
||||
{
|
||||
Common::SettingsHandler::Buffer data;
|
||||
Common::SettingsBuffer data;
|
||||
const auto file = fs->OpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, settings_file_path,
|
||||
IOS::HLE::FS::Mode::Read);
|
||||
if (file && file->Read(data.data(), data.size()))
|
||||
{
|
||||
Common::SettingsHandler settings_reader(data);
|
||||
const Common::SettingsReader settings_reader(data);
|
||||
serno = settings_reader.GetValue("SERNO");
|
||||
model = settings_reader.GetValue("MODEL");
|
||||
|
||||
|
@ -413,7 +413,7 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
|
|||
if (Core::WantsDeterminism())
|
||||
serno = "123456789";
|
||||
else
|
||||
serno = Common::SettingsHandler::GenerateSerialNumber();
|
||||
serno = Common::SettingsWriter::GenerateSerialNumber();
|
||||
INFO_LOG_FMT(BOOT, "No previous serial number found, generated one instead: {}", serno);
|
||||
}
|
||||
else
|
||||
|
@ -421,20 +421,21 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
|
|||
INFO_LOG_FMT(BOOT, "Using serial number: {}", serno);
|
||||
}
|
||||
|
||||
Common::SettingsHandler gen;
|
||||
gen.AddSetting("AREA", region_setting.area);
|
||||
gen.AddSetting("MODEL", model);
|
||||
gen.AddSetting("DVD", "0");
|
||||
gen.AddSetting("MPCH", "0x7FFE");
|
||||
gen.AddSetting("CODE", region_setting.code);
|
||||
gen.AddSetting("SERNO", serno);
|
||||
gen.AddSetting("VIDEO", region_setting.video);
|
||||
gen.AddSetting("GAME", region_setting.game);
|
||||
Common::SettingsWriter settings_writer;
|
||||
settings_writer.AddSetting("AREA", region_setting.area);
|
||||
settings_writer.AddSetting("MODEL", model);
|
||||
settings_writer.AddSetting("DVD", "0");
|
||||
settings_writer.AddSetting("MPCH", "0x7FFE");
|
||||
settings_writer.AddSetting("CODE", region_setting.code);
|
||||
settings_writer.AddSetting("SERNO", serno);
|
||||
settings_writer.AddSetting("VIDEO", region_setting.video);
|
||||
settings_writer.AddSetting("GAME", region_setting.game);
|
||||
|
||||
constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
const auto settings_file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID,
|
||||
settings_file_path, {rw_mode, rw_mode, rw_mode});
|
||||
if (!settings_file || !settings_file->Write(gen.GetBytes().data(), gen.GetBytes().size()))
|
||||
if (!settings_file ||
|
||||
!settings_file->Write(settings_writer.GetBytes().data(), settings_writer.GetBytes().size()))
|
||||
{
|
||||
PanicAlertFmtT("SetupWiiMemory: Can't create setting.txt file");
|
||||
return false;
|
||||
|
@ -443,7 +444,7 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
|
|||
auto& memory = system.GetMemory();
|
||||
|
||||
// Write the 256 byte setting.txt to memory.
|
||||
memory.CopyToEmu(0x3800, gen.GetBytes().data(), gen.GetBytes().size());
|
||||
memory.CopyToEmu(0x3800, settings_writer.GetBytes().data(), settings_writer.GetBytes().size());
|
||||
|
||||
INFO_LOG_FMT(BOOT, "Setup Wii Memory...");
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ const Info<int> GFX_STEREO_DEPTH_PERCENTAGE{{System::GFX, "Stereoscopy", "Stereo
|
|||
|
||||
// Graphics.Hacks
|
||||
|
||||
const Info<bool> GFX_HACK_EFB_ACCESS_ENABLE{{System::GFX, "Hacks", "EFBAccessEnable"}, true};
|
||||
const Info<bool> GFX_HACK_EFB_ACCESS_ENABLE{{System::GFX, "Hacks", "EFBAccessEnable"}, false};
|
||||
const Info<bool> GFX_HACK_EFB_DEFER_INVALIDATION{
|
||||
{System::GFX, "Hacks", "EFBAccessDeferInvalidation"}, false};
|
||||
const Info<int> GFX_HACK_EFB_ACCESS_TILE_SIZE{{System::GFX, "Hacks", "EFBAccessTileSize"}, 64};
|
||||
|
|
|
@ -212,7 +212,7 @@ const Info<bool> MAIN_RAM_OVERRIDE_ENABLE{{System::Main, "Core", "RAMOverrideEna
|
|||
const Info<u32> MAIN_MEM1_SIZE{{System::Main, "Core", "MEM1Size"}, Memory::MEM1_SIZE_RETAIL};
|
||||
const Info<u32> MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};
|
||||
const Info<std::string> MAIN_GFX_BACKEND{{System::Main, "Core", "GFXBackend"},
|
||||
VideoBackendBase::GetDefaultBackendName()};
|
||||
VideoBackendBase::GetDefaultBackendConfigName()};
|
||||
const Info<HSP::HSPDeviceType> MAIN_HSP_DEVICE{{System::Main, "Core", "HSPDevice"},
|
||||
HSP::HSPDeviceType::None};
|
||||
const Info<u32> MAIN_ARAM_EXPANSION_SIZE{{System::Main, "Core", "ARAMExpansionSize"}, 0x400000};
|
||||
|
|
|
@ -6,19 +6,14 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Core/Config/AchievementSettings.h"
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/UISettings.h"
|
||||
#include "Core/Config/WiimoteSettings.h"
|
||||
|
||||
namespace ConfigLoaders
|
||||
{
|
||||
bool IsSettingSaveable(const Config::Location& config_location)
|
||||
{
|
||||
static constexpr std::array<Config::System, 3> systems_not_saveable = {
|
||||
Config::System::GCPad, Config::System::WiiPad, Config::System::GCKeyboard};
|
||||
static constexpr std::array systems_not_saveable = {Config::System::GCPad, Config::System::WiiPad,
|
||||
Config::System::GCKeyboard};
|
||||
|
||||
if (std::find(begin(systems_not_saveable), end(systems_not_saveable), config_location.system) ==
|
||||
end(systems_not_saveable))
|
||||
|
|
|
@ -217,7 +217,7 @@ void SConfig::OnNewTitleLoad(const Core::CPUThreadGuard& guard)
|
|||
}
|
||||
CBoot::LoadMapFromFilename(guard, ppc_symbol_db);
|
||||
HLE::Reload(system);
|
||||
PatchEngine::Reload();
|
||||
PatchEngine::Reload(system);
|
||||
HiresTexture::Update();
|
||||
WC24PatchEngine::Reload();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/PowerPC/MMU.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "ConfigManager.h"
|
||||
|
@ -272,6 +273,7 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard)
|
|||
{
|
||||
ppc_state.iCache.Invalidate(INSTALLER_BASE_ADDRESS + j);
|
||||
}
|
||||
Host_JitCacheInvalidation();
|
||||
return Installation::Installed;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ void Host_PPCSymbolsChanged();
|
|||
void Host_RefreshDSPDebuggerWindow();
|
||||
void Host_RequestRenderWindowSize(int width, int height);
|
||||
void Host_UpdateDisasmDialog();
|
||||
void Host_JitCacheCleared();
|
||||
void Host_JitCacheInvalidation();
|
||||
void Host_JitProfileDataWiped();
|
||||
void Host_UpdateMainFrame();
|
||||
void Host_UpdateTitle(const std::string& title);
|
||||
|
|
|
@ -133,13 +133,13 @@ IPCReply GetRealProductCode(Core::System& system, const IOCtlVRequest& request)
|
|||
if (!file)
|
||||
return IPCReply(IPC_ENOENT);
|
||||
|
||||
Common::SettingsHandler::Buffer data;
|
||||
Common::SettingsBuffer data;
|
||||
|
||||
if (!file.ReadBytes(data.data(), data.size()))
|
||||
return IPCReply(IPC_ENOENT);
|
||||
|
||||
Common::SettingsHandler gen(data);
|
||||
const std::string code = gen.GetValue("CODE");
|
||||
const Common::SettingsReader settings_reader(data);
|
||||
const std::string code = settings_reader.GetValue("CODE");
|
||||
|
||||
const size_t length = std::min<size_t>(request.io_vectors[0].size, code.length());
|
||||
if (length == 0)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -575,7 +576,7 @@ SharedContentMap::GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const
|
|||
if (it == m_entries.end())
|
||||
return {};
|
||||
|
||||
const std::string id_string(it->id.begin(), it->id.end());
|
||||
const std::string_view id_string(reinterpret_cast<const char*>(it->id.data()), it->id.size());
|
||||
return fmt::format("/shared1/{}.app", id_string);
|
||||
}
|
||||
|
||||
|
@ -591,20 +592,22 @@ std::vector<std::array<u8, 20>> SharedContentMap::GetHashes() const
|
|||
|
||||
std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
|
||||
{
|
||||
auto filename = GetFilenameFromSHA1(sha1);
|
||||
if (filename)
|
||||
return *filename;
|
||||
if (auto filename = GetFilenameFromSHA1(sha1))
|
||||
return *std::move(filename);
|
||||
|
||||
const std::string id = fmt::format("{:08x}", m_last_id);
|
||||
Entry entry;
|
||||
std::copy(id.cbegin(), id.cend(), entry.id.begin());
|
||||
Entry& entry = m_entries.emplace_back();
|
||||
static_assert(sizeof(m_last_id) == 4,
|
||||
"'m_last_id' must be represented by 8 characters when formatted in hexadecimal.");
|
||||
static_assert(std::tuple_size_v<decltype(entry.id)> == sizeof(m_last_id) * 2,
|
||||
"'entry.id' must be a std::array capable of storing every nibble of 'm_last_id'.");
|
||||
fmt::format_to(entry.id.data(), "{:08x}", m_last_id);
|
||||
entry.sha1 = sha1;
|
||||
m_entries.push_back(entry);
|
||||
|
||||
WriteEntries();
|
||||
filename = fmt::format("/shared1/{}.app", id);
|
||||
m_last_id++;
|
||||
return *filename;
|
||||
|
||||
const std::string_view id_string(reinterpret_cast<const char*>(entry.id.data()), entry.id.size());
|
||||
return fmt::format("/shared1/{}.app", id_string);
|
||||
}
|
||||
|
||||
bool SharedContentMap::DeleteSharedContent(const std::array<u8, 20>& sha1)
|
||||
|
|
|
@ -923,7 +923,7 @@ IPCReply NetKDRequestDevice::HandleRequestRegisterUserId(const IOS::HLE::IOCtlRe
|
|||
return IPCReply{IPC_SUCCESS};
|
||||
}
|
||||
|
||||
Common::SettingsHandler::Buffer data;
|
||||
Common::SettingsBuffer data;
|
||||
if (!file->Read(data.data(), data.size()))
|
||||
{
|
||||
WriteReturnValue(memory, NWC24::WC24_ERR_FILE_READ, request.buffer_out);
|
||||
|
@ -931,8 +931,8 @@ IPCReply NetKDRequestDevice::HandleRequestRegisterUserId(const IOS::HLE::IOCtlRe
|
|||
return IPCReply{IPC_SUCCESS};
|
||||
}
|
||||
|
||||
const Common::SettingsHandler gen{data};
|
||||
const std::string serno = gen.GetValue("SERNO");
|
||||
const Common::SettingsReader settings_reader{data};
|
||||
const std::string serno = settings_reader.GetValue("SERNO");
|
||||
const std::string form_data =
|
||||
fmt::format("mlid=w{}&hdid={}&rgncd={}", m_config.Id(), m_ios.GetIOSC().GetDeviceId(), serno);
|
||||
const Common::HttpRequest::Response response = m_http.Post(m_config.GetAccountURL(), form_data);
|
||||
|
@ -1076,12 +1076,12 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
|
|||
const auto fs = m_ios.GetFS();
|
||||
if (const auto file = fs->OpenFile(PID_KD, PID_KD, settings_file_path, FS::Mode::Read))
|
||||
{
|
||||
Common::SettingsHandler::Buffer data;
|
||||
Common::SettingsBuffer data;
|
||||
if (file->Read(data.data(), data.size()))
|
||||
{
|
||||
const Common::SettingsHandler gen{data};
|
||||
area = gen.GetValue("AREA");
|
||||
model = gen.GetValue("MODEL");
|
||||
const Common::SettingsReader settings_reader{data};
|
||||
area = settings_reader.GetValue("AREA");
|
||||
model = settings_reader.GetValue("MODEL");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,6 +296,13 @@ void RemoveMemoryPatch(std::size_t index)
|
|||
std::erase(s_on_frame_memory, index);
|
||||
}
|
||||
|
||||
static void ApplyStartupPatches(Core::System& system)
|
||||
{
|
||||
ASSERT(Core::IsCPUThread());
|
||||
Core::CPUThreadGuard guard(system);
|
||||
ApplyPatches(guard, s_on_frame);
|
||||
}
|
||||
|
||||
bool ApplyFramePatches(Core::System& system)
|
||||
{
|
||||
const auto& ppc_state = system.GetPPCState();
|
||||
|
@ -335,10 +342,11 @@ void Shutdown()
|
|||
Gecko::Shutdown();
|
||||
}
|
||||
|
||||
void Reload()
|
||||
void Reload(Core::System& system)
|
||||
{
|
||||
Shutdown();
|
||||
LoadPatches();
|
||||
ApplyStartupPatches(system);
|
||||
}
|
||||
|
||||
} // namespace PatchEngine
|
||||
|
|
|
@ -61,7 +61,7 @@ void RemoveMemoryPatch(std::size_t index);
|
|||
|
||||
bool ApplyFramePatches(Core::System& system);
|
||||
void Shutdown();
|
||||
void Reload();
|
||||
void Reload(Core::System& system);
|
||||
|
||||
inline int GetPatchTypeCharLength(PatchType type)
|
||||
{
|
||||
|
|
|
@ -442,7 +442,7 @@ void CachedInterpreter::ClearCache()
|
|||
ClearCodeSpace();
|
||||
ResetFreeMemoryRanges();
|
||||
RefreshConfig();
|
||||
Host_JitCacheCleared();
|
||||
Host_JitCacheInvalidation();
|
||||
}
|
||||
|
||||
void CachedInterpreter::LogGeneratedCode() const
|
||||
|
|
|
@ -313,7 +313,7 @@ void Jit64::ClearCache()
|
|||
RefreshConfig();
|
||||
asm_routines.Regenerate();
|
||||
ResetFreeMemoryRanges();
|
||||
Host_JitCacheCleared();
|
||||
Host_JitCacheInvalidation();
|
||||
}
|
||||
|
||||
void Jit64::FreeRanges()
|
||||
|
|
|
@ -197,7 +197,7 @@ void JitArm64::GenerateAsmAndResetFreeMemoryRanges()
|
|||
ResetFreeMemoryRanges(routines_near_end - routines_near_start,
|
||||
routines_far_end - routines_far_start);
|
||||
|
||||
Host_JitCacheCleared();
|
||||
Host_JitCacheInvalidation();
|
||||
}
|
||||
|
||||
void JitArm64::FreeRanges()
|
||||
|
@ -262,12 +262,11 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
|||
if (js.op->canEndBlock)
|
||||
{
|
||||
// also flush the program counter
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, js.compilerPC);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(pc));
|
||||
ADD(WA, WA, 4);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
|
||||
|
@ -283,24 +282,23 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
|||
{
|
||||
if (js.isLastInstruction)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
|
||||
WriteExceptionExit(WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
else
|
||||
{
|
||||
// only exit if ppcstate.npc was changed
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
{
|
||||
auto WB = gpr.GetScopedReg();
|
||||
MOVI2R(WB, js.compilerPC + 4);
|
||||
CMP(WB, WA);
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
FixupBranch c = B(CC_EQ);
|
||||
WriteExceptionExit(WA);
|
||||
SetJumpTarget(c);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
else if (ShouldHandleFPExceptionForInstruction(js.op))
|
||||
|
@ -399,11 +397,12 @@ void JitArm64::IntializeSpeculativeConstants()
|
|||
SwitchToNearCode();
|
||||
}
|
||||
|
||||
ARM64Reg tmp = gpr.GetReg();
|
||||
{
|
||||
auto tmp = gpr.GetScopedReg();
|
||||
ARM64Reg value = gpr.R(i);
|
||||
MOVI2R(tmp, compile_time_value);
|
||||
CMP(value, tmp);
|
||||
gpr.Unlock(tmp);
|
||||
}
|
||||
|
||||
FixupBranch no_fail = B(CCFlags::CC_EQ);
|
||||
B(fail);
|
||||
|
@ -442,16 +441,15 @@ void JitArm64::MSRUpdated(u32 msr)
|
|||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, feature_flags);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
|
||||
void JitArm64::MSRUpdated(ARM64Reg msr)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
||||
// Update mem_ptr
|
||||
|
@ -472,8 +470,6 @@ void JitArm64::MSRUpdated(ARM64Reg msr)
|
|||
if (other_feature_flags != 0)
|
||||
ORR(WA, WA, LogicalImm(other_feature_flags, GPRSize::B32));
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return,
|
||||
|
@ -671,13 +667,16 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
|
|||
// function has been called!
|
||||
gpr.Lock(ARM64Reg::W30);
|
||||
}
|
||||
|
||||
const u8* host_address_after_return;
|
||||
{
|
||||
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
|
||||
ARM64Reg after_reg = ARM64Reg::INVALID_REG;
|
||||
Arm64RegCache::ScopedARM64Reg after_reg;
|
||||
ARM64Reg reg_to_push;
|
||||
const u64 feature_flags = m_ppc_state.feature_flags;
|
||||
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
|
||||
{
|
||||
after_reg = gpr.GetReg();
|
||||
after_reg = gpr.GetScopedReg();
|
||||
reg_to_push = EncodeRegTo64(after_reg);
|
||||
MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return);
|
||||
}
|
||||
|
@ -687,19 +686,18 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
|
|||
}
|
||||
else
|
||||
{
|
||||
after_reg = gpr.GetReg();
|
||||
after_reg = gpr.GetScopedReg();
|
||||
reg_to_push = EncodeRegTo64(after_reg);
|
||||
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
|
||||
reg_to_push);
|
||||
}
|
||||
ARM64Reg code_reg = gpr.GetReg();
|
||||
|
||||
auto code_reg = gpr.GetScopedReg();
|
||||
constexpr s32 adr_offset = sizeof(u32) * 3;
|
||||
const u8* host_address_after_return = GetCodePtr() + adr_offset;
|
||||
host_address_after_return = GetCodePtr() + adr_offset;
|
||||
ADR(EncodeRegTo64(code_reg), adr_offset);
|
||||
STP(IndexType::Pre, EncodeRegTo64(code_reg), reg_to_push, ARM64Reg::SP, -16);
|
||||
gpr.Unlock(code_reg);
|
||||
if (after_reg != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(after_reg);
|
||||
}
|
||||
|
||||
FixupBranch skip_exit = BL();
|
||||
DEBUG_ASSERT(GetCodePtr() == host_address_after_return || HasWriteFailed());
|
||||
|
@ -832,10 +830,9 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
|
|||
|
||||
void JitArm64::WriteConditionalExceptionExit(int exception, u64 increment_sp_on_exit)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
WriteConditionalExceptionExit(exception, WA, Arm64Gen::ARM64Reg::INVALID_REG,
|
||||
increment_sp_on_exit);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_gpr, ARM64Reg temp_fpr,
|
||||
|
@ -1227,7 +1224,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
// asynchronous.
|
||||
if (jo.optimizeGatherPipe && gatherPipeIntCheck)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
|
@ -1253,8 +1250,6 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
SwitchToNearCode();
|
||||
SetJumpTarget(no_ext_exception);
|
||||
SetJumpTarget(exit);
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1268,12 +1263,11 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
// The only thing that currently sets op.skip is the BLR following optimization.
|
||||
// If any non-branch instruction starts setting that too, this will need to be changed.
|
||||
ASSERT(op.inst.hex == 0x4e800020);
|
||||
const ARM64Reg bw_reg_a = gpr.GetReg(), bw_reg_b = gpr.GetReg();
|
||||
const auto bw_reg_a = gpr.GetScopedReg(), bw_reg_b = gpr.GetScopedReg();
|
||||
const BitSet32 gpr_caller_save =
|
||||
gpr.GetCallerSavedUsed() & ~BitSet32{DecodeReg(bw_reg_a), DecodeReg(bw_reg_b)};
|
||||
WriteBranchWatch<true>(op.address, op.branchTo, op.inst, bw_reg_a, bw_reg_b,
|
||||
gpr_caller_save, fpr.GetCallerSavedUsed());
|
||||
gpr.Unlock(bw_reg_a, bw_reg_b);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1311,10 +1305,12 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
|
||||
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
|
||||
{
|
||||
FixupBranch b1;
|
||||
// This instruction uses FPU - needs to add FP exception bailout
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr));
|
||||
FixupBranch b1 = TBNZ(WA, 13); // Test FP enabled bit
|
||||
b1 = TBNZ(WA, 13); // Test FP enabled bit
|
||||
|
||||
FixupBranch far_addr = B();
|
||||
SwitchToFarCode();
|
||||
|
@ -1326,8 +1322,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
ORR(WA, WA, LogicalImm(EXCEPTION_FPU_UNAVAILABLE, GPRSize::B32));
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
WriteExceptionExit(js.compilerPC, false, true);
|
||||
|
||||
|
|
|
@ -24,13 +24,12 @@ void JitArm64::sc(UGeckoInstruction inst)
|
|||
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
ORR(WA, WA, LogicalImm(EXCEPTION_SYSCALL, GPRSize::B32));
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
WriteExceptionExit(js.compilerPC + 4, false, true);
|
||||
}
|
||||
|
@ -51,9 +50,10 @@ void JitArm64::rfi(UGeckoInstruction inst)
|
|||
// R1 = MSR contents
|
||||
// R2 = Mask
|
||||
// R3 = Mask
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
ARM64Reg WC = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
{
|
||||
auto WB = gpr.GetScopedReg();
|
||||
auto WC = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WC, PPC_REG, PPCSTATE_OFF(msr));
|
||||
|
||||
|
@ -65,14 +65,13 @@ void JitArm64::rfi(UGeckoInstruction inst)
|
|||
ORR(WA, WA, WC); // rB = Masked MSR OR masked SRR1
|
||||
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr)); // STR rB in to rA
|
||||
gpr.Unlock(WB, WC);
|
||||
}
|
||||
|
||||
MSRUpdated(WA);
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_SRR0));
|
||||
|
||||
WriteExceptionExit(WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
template <bool condition>
|
||||
|
@ -144,10 +143,10 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
INSTRUCTION_START
|
||||
JITDISABLE(bJITBranchOff);
|
||||
|
||||
ARM64Reg WA = ARM64Reg::INVALID_REG;
|
||||
Arm64GPRCache::ScopedARM64Reg WA = ARM64Reg::INVALID_REG;
|
||||
if (inst.LK)
|
||||
{
|
||||
WA = gpr.GetReg();
|
||||
WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, js.compilerPC + 4);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_LR));
|
||||
}
|
||||
|
@ -156,13 +155,12 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
{
|
||||
if (IsDebuggingEnabled())
|
||||
{
|
||||
const ARM64Reg WB = gpr.GetReg(), WC = gpr.GetReg();
|
||||
const auto WB = gpr.GetScopedReg(), WC = gpr.GetScopedReg();
|
||||
BitSet32 gpr_caller_save = gpr.GetCallerSavedUsed() & ~BitSet32{DecodeReg(WB), DecodeReg(WC)};
|
||||
if (WA != ARM64Reg::INVALID_REG && js.op->skipLRStack)
|
||||
gpr_caller_save[DecodeReg(WA)] = false;
|
||||
WriteBranchWatch<true>(js.compilerPC, js.op->branchTo, inst, WB, WC, gpr_caller_save,
|
||||
fpr.GetCallerSavedUsed());
|
||||
gpr.Unlock(WB, WC);
|
||||
}
|
||||
if (inst.LK && !js.op->skipLRStack)
|
||||
{
|
||||
|
@ -172,9 +170,6 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
FakeLKExit(js.compilerPC + 4, WA);
|
||||
}
|
||||
|
||||
if (WA != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WA);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -184,13 +179,12 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
if (js.op->branchIsIdleLoop)
|
||||
{
|
||||
if (WA == ARM64Reg::INVALID_REG)
|
||||
WA = gpr.GetReg();
|
||||
WA = gpr.GetScopedReg();
|
||||
|
||||
if (IsDebuggingEnabled())
|
||||
{
|
||||
const ARM64Reg WB = gpr.GetReg();
|
||||
const auto WB = gpr.GetScopedReg();
|
||||
WriteBranchWatch<true>(js.compilerPC, js.op->branchTo, inst, WA, WB, {}, {});
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
// make idle loops go faster
|
||||
|
@ -198,7 +192,7 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
|
||||
MOVP2R(XA, &CoreTiming::GlobalIdle);
|
||||
BLR(XA);
|
||||
gpr.Unlock(WA);
|
||||
WA.Unlock();
|
||||
|
||||
WriteExceptionExit(js.op->branchTo);
|
||||
return;
|
||||
|
@ -206,16 +200,12 @@ void JitArm64::bx(UGeckoInstruction inst)
|
|||
|
||||
if (IsDebuggingEnabled())
|
||||
{
|
||||
const ARM64Reg WB = gpr.GetReg(), WC = gpr.GetReg();
|
||||
const auto WB = gpr.GetScopedReg(), WC = gpr.GetScopedReg();
|
||||
const BitSet32 gpr_caller_save =
|
||||
WA != ARM64Reg::INVALID_REG ? BitSet32{DecodeReg(WA)} & CALLER_SAVED_GPRS : BitSet32{};
|
||||
WriteBranchWatch<true>(js.compilerPC, js.op->branchTo, inst, WB, WC, gpr_caller_save, {});
|
||||
gpr.Unlock(WB, WC);
|
||||
}
|
||||
WriteExit(js.op->branchTo, inst.LK, js.compilerPC + 4, WA);
|
||||
|
||||
if (WA != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::bcx(UGeckoInstruction inst)
|
||||
|
@ -223,10 +213,14 @@ void JitArm64::bcx(UGeckoInstruction inst)
|
|||
INSTRUCTION_START
|
||||
JITDISABLE(bJITBranchOff);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = inst.LK || IsDebuggingEnabled() ? gpr.GetReg() : WA;
|
||||
ARM64Reg WC = IsDebuggingEnabled() && inst.LK && !js.op->branchIsIdleLoop ? gpr.GetReg() :
|
||||
ARM64Reg::INVALID_REG;
|
||||
auto WA = gpr.GetScopedReg();
|
||||
auto WB = inst.LK || IsDebuggingEnabled() ? gpr.GetScopedReg() :
|
||||
Arm64GPRCache::ScopedARM64Reg(WA.GetReg());
|
||||
|
||||
{
|
||||
auto WC = IsDebuggingEnabled() && inst.LK && !js.op->branchIsIdleLoop ?
|
||||
gpr.GetScopedReg() :
|
||||
Arm64GPRCache::ScopedARM64Reg(ARM64Reg::INVALID_REG);
|
||||
|
||||
FixupBranch pCTRDontBranch;
|
||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
||||
|
@ -290,9 +284,7 @@ void JitArm64::bcx(UGeckoInstruction inst)
|
|||
SetJumpTarget(pConditionDontBranch);
|
||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
|
||||
SetJumpTarget(pCTRDontBranch);
|
||||
|
||||
if (WC != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WC);
|
||||
}
|
||||
|
||||
if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
|
||||
{
|
||||
|
@ -311,10 +303,6 @@ void JitArm64::bcx(UGeckoInstruction inst)
|
|||
WriteBranchWatch<false>(js.compilerPC, js.compilerPC + 4, inst, WA, WB, gpr_caller_save,
|
||||
fpr.GetCallerSavedUsed());
|
||||
}
|
||||
|
||||
gpr.Unlock(WA);
|
||||
if (WB != WA)
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
void JitArm64::bcctrx(UGeckoInstruction inst)
|
||||
|
@ -337,34 +325,29 @@ void JitArm64::bcctrx(UGeckoInstruction inst)
|
|||
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
|
||||
ARM64Reg WB = ARM64Reg::INVALID_REG;
|
||||
Arm64GPRCache::ScopedARM64Reg WB = ARM64Reg::INVALID_REG;
|
||||
if (inst.LK_3)
|
||||
{
|
||||
WB = gpr.GetReg();
|
||||
WB = gpr.GetScopedReg();
|
||||
MOVI2R(WB, js.compilerPC + 4);
|
||||
STR(IndexType::Unsigned, WB, PPC_REG, PPCSTATE_OFF_SPR(SPR_LR));
|
||||
}
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_CTR));
|
||||
AND(WA, WA, LogicalImm(~0x3, GPRSize::B32));
|
||||
|
||||
if (IsDebuggingEnabled())
|
||||
{
|
||||
const ARM64Reg WC = gpr.GetReg(), WD = gpr.GetReg();
|
||||
const auto WC = gpr.GetScopedReg(), WD = gpr.GetScopedReg();
|
||||
BitSet32 gpr_caller_save = BitSet32{DecodeReg(WA)};
|
||||
if (WB != ARM64Reg::INVALID_REG)
|
||||
gpr_caller_save[DecodeReg(WB)] = true;
|
||||
gpr_caller_save &= CALLER_SAVED_GPRS;
|
||||
WriteBranchWatchDestInRegister(js.compilerPC, WA, inst, WC, WD, gpr_caller_save, {});
|
||||
gpr.Unlock(WC, WD);
|
||||
}
|
||||
WriteExit(WA, inst.LK_3, js.compilerPC + 4, WB);
|
||||
|
||||
if (WB != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WB);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::bclrx(UGeckoInstruction inst)
|
||||
|
@ -375,10 +358,19 @@ void JitArm64::bclrx(UGeckoInstruction inst)
|
|||
bool conditional =
|
||||
(inst.BO & BO_DONT_DECREMENT_FLAG) == 0 || (inst.BO & BO_DONT_CHECK_CONDITION) == 0;
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB =
|
||||
conditional || inst.LK || IsDebuggingEnabled() ? gpr.GetReg() : ARM64Reg::INVALID_REG;
|
||||
ARM64Reg WC = IsDebuggingEnabled() ? gpr.GetReg() : ARM64Reg::INVALID_REG;
|
||||
auto WA = gpr.GetScopedReg();
|
||||
Arm64GPRCache::ScopedARM64Reg WB;
|
||||
if (conditional || inst.LK || IsDebuggingEnabled())
|
||||
{
|
||||
WB = gpr.GetScopedReg();
|
||||
}
|
||||
|
||||
{
|
||||
Arm64GPRCache::ScopedARM64Reg WC;
|
||||
if (IsDebuggingEnabled())
|
||||
{
|
||||
WC = gpr.GetScopedReg();
|
||||
}
|
||||
|
||||
FixupBranch pCTRDontBranch;
|
||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
||||
|
@ -451,9 +443,7 @@ void JitArm64::bclrx(UGeckoInstruction inst)
|
|||
SetJumpTarget(pConditionDontBranch);
|
||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
|
||||
SetJumpTarget(pCTRDontBranch);
|
||||
|
||||
if (WC != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WC);
|
||||
}
|
||||
|
||||
if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
|
||||
{
|
||||
|
@ -472,8 +462,4 @@ void JitArm64::bclrx(UGeckoInstruction inst)
|
|||
WriteBranchWatch<false>(js.compilerPC, js.compilerPC + 4, inst, WA, WB, gpr_caller_save,
|
||||
fpr.GetCallerSavedUsed());
|
||||
}
|
||||
|
||||
gpr.Unlock(WA);
|
||||
if (WB != ARM64Reg::INVALID_REG)
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
|
|
@ -102,15 +102,16 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
|
|||
const ARM64Reg VC = use_c ? reg_encoder(fpr.R(c, type)) : ARM64Reg::INVALID_REG;
|
||||
const ARM64Reg VD = reg_encoder(fpr.RW(d, type_out));
|
||||
|
||||
ARM64Reg V0Q = ARM64Reg::INVALID_REG;
|
||||
ARM64Reg V1Q = ARM64Reg::INVALID_REG;
|
||||
{
|
||||
Arm64FPRCache::ScopedARM64Reg V0Q = ARM64Reg::INVALID_REG;
|
||||
Arm64FPRCache::ScopedARM64Reg V1Q = ARM64Reg::INVALID_REG;
|
||||
|
||||
ARM64Reg rounded_c_reg = VC;
|
||||
if (round_c)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, !inputs_are_singles, "Tried to apply 25-bit precision to single");
|
||||
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
rounded_c_reg = reg_encoder(V0Q);
|
||||
Force25BitPrecision(rounded_c_reg, VC);
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
|
|||
if (fma && inaccurate_fma && VD == VB)
|
||||
{
|
||||
if (V0Q == ARM64Reg::INVALID_REG)
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
inaccurate_fma_reg = reg_encoder(V0Q);
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,7 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
|
|||
m_accurate_nans && (VD == VA || (use_b && VD == VB) || (use_c && VD == VC));
|
||||
if (preserve_d)
|
||||
{
|
||||
V1Q = fpr.GetReg();
|
||||
V1Q = fpr.GetScopedReg();
|
||||
result_reg = reg_encoder(V1Q);
|
||||
}
|
||||
|
||||
|
@ -244,11 +245,7 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
|
|||
|
||||
for (FixupBranch fixup : nan_fixups)
|
||||
SetJumpTarget(fixup);
|
||||
|
||||
if (V0Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V0Q);
|
||||
if (V1Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V1Q);
|
||||
}
|
||||
|
||||
if (output_is_single)
|
||||
{
|
||||
|
@ -449,19 +446,20 @@ void JitArm64::FloatCompare(UGeckoInstruction inst, bool upper)
|
|||
gpr.BindCRToRegister(crf, false);
|
||||
const ARM64Reg XA = gpr.CR(crf);
|
||||
|
||||
ARM64Reg fpscr_reg = ARM64Reg::INVALID_REG;
|
||||
Arm64GPRCache::ScopedARM64Reg fpscr_reg = ARM64Reg::INVALID_REG;
|
||||
if (fprf)
|
||||
{
|
||||
fpscr_reg = gpr.GetReg();
|
||||
fpscr_reg = gpr.GetScopedReg();
|
||||
LDR(IndexType::Unsigned, fpscr_reg, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
AND(fpscr_reg, fpscr_reg, LogicalImm(~FPCC_MASK, GPRSize::B32));
|
||||
}
|
||||
|
||||
ARM64Reg V0Q = ARM64Reg::INVALID_REG;
|
||||
ARM64Reg V1Q = ARM64Reg::INVALID_REG;
|
||||
{
|
||||
Arm64FPRCache::ScopedARM64Reg V0Q;
|
||||
Arm64FPRCache::ScopedARM64Reg V1Q;
|
||||
if (upper_a)
|
||||
{
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
m_float_emit.DUP(singles ? 32 : 64, paired_reg_encoder(V0Q), paired_reg_encoder(VA), 1);
|
||||
VA = reg_encoder(V0Q);
|
||||
}
|
||||
|
@ -473,18 +471,14 @@ void JitArm64::FloatCompare(UGeckoInstruction inst, bool upper)
|
|||
}
|
||||
else
|
||||
{
|
||||
V1Q = fpr.GetReg();
|
||||
V1Q = fpr.GetScopedReg();
|
||||
m_float_emit.DUP(singles ? 32 : 64, paired_reg_encoder(V1Q), paired_reg_encoder(VB), 1);
|
||||
VB = reg_encoder(V1Q);
|
||||
}
|
||||
}
|
||||
|
||||
m_float_emit.FCMP(VA, VB);
|
||||
|
||||
if (V0Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V0Q);
|
||||
if (V1Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V1Q);
|
||||
}
|
||||
|
||||
FixupBranch pNaN, pLesser, pGreater;
|
||||
FixupBranch continue1, continue2, continue3;
|
||||
|
@ -538,7 +532,6 @@ void JitArm64::FloatCompare(UGeckoInstruction inst, bool upper)
|
|||
if (fprf)
|
||||
{
|
||||
STR(IndexType::Unsigned, fpscr_reg, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
gpr.Unlock(fpscr_reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,7 +565,7 @@ void JitArm64::fctiwx(UGeckoInstruction inst)
|
|||
|
||||
if (single)
|
||||
{
|
||||
const ARM64Reg V0 = fpr.GetReg();
|
||||
const auto V0 = fpr.GetScopedReg();
|
||||
|
||||
if (is_fctiwzx)
|
||||
{
|
||||
|
@ -589,12 +582,10 @@ void JitArm64::fctiwx(UGeckoInstruction inst)
|
|||
m_float_emit.BIC(16, EncodeRegToDouble(V0), 0x7);
|
||||
|
||||
m_float_emit.ORR(EncodeRegToDouble(VD), EncodeRegToDouble(VD), EncodeRegToDouble(V0));
|
||||
|
||||
fpr.Unlock(V0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ARM64Reg WA = gpr.GetReg();
|
||||
const auto WA = gpr.GetScopedReg();
|
||||
|
||||
if (is_fctiwzx)
|
||||
{
|
||||
|
@ -608,8 +599,6 @@ void JitArm64::fctiwx(UGeckoInstruction inst)
|
|||
|
||||
ORR(EncodeRegTo64(WA), EncodeRegTo64(WA), LogicalImm(0xFFF8'0000'0000'0000ULL, GPRSize::B64));
|
||||
m_float_emit.FMOV(EncodeRegToDouble(VD), EncodeRegTo64(WA));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, b == d || single == fpr.IsSingle(b, true),
|
||||
|
|
|
@ -86,10 +86,9 @@ void JitArm64::LoadCarry()
|
|||
{
|
||||
case CarryFlag::InPPCState:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
CMP(WA, 1);
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
|
@ -119,18 +118,16 @@ void JitArm64::FlushCarry()
|
|||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
CSET(WA, CC_CS);
|
||||
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::ConstantTrue:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, 1);
|
||||
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::ConstantFalse:
|
||||
|
@ -155,9 +152,10 @@ void JitArm64::reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32),
|
|||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
(this->*op)(gpr.R(d), gpr.R(a), value, WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (Rc)
|
||||
ComputeRC0(gpr.R(d));
|
||||
|
@ -245,9 +243,8 @@ void JitArm64::addix(UGeckoInstruction inst)
|
|||
{
|
||||
gpr.BindToRegister(d, d == a);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ADDI2R(gpr.R(d), gpr.R(a), imm, WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -544,9 +541,10 @@ void JitArm64::addx(UGeckoInstruction inst)
|
|||
int imm_value = gpr.GetImm(imm_reg);
|
||||
|
||||
gpr.BindToRegister(d, d == in_reg);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ADDI2R(gpr.R(d), gpr.R(in_reg), imm_value, WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
if (inst.Rc)
|
||||
ComputeRC0(gpr.R(d));
|
||||
}
|
||||
|
@ -722,9 +720,8 @@ void JitArm64::cmpi(UGeckoInstruction inst)
|
|||
|
||||
if (B != 0)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
SUBI2R(CR, CR, B, EncodeRegTo64(WA));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,10 +793,9 @@ void JitArm64::rlwinmx_internal(UGeckoInstruction inst, u32 sh)
|
|||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, mask);
|
||||
AND(gpr.R(a), WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, 32 - sh));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -829,11 +825,12 @@ void JitArm64::rlwnmx(UGeckoInstruction inst)
|
|||
const u32 mask = MakeRotationMask(inst.MB, inst.ME);
|
||||
|
||||
gpr.BindToRegister(a, a == s || a == b);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
NEG(WA, gpr.R(b));
|
||||
RORV(gpr.R(a), gpr.R(s), WA);
|
||||
ANDI2R(gpr.R(a), gpr.R(a), mask, WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC0(gpr.R(a));
|
||||
|
@ -878,8 +875,8 @@ void JitArm64::srawix(UGeckoInstruction inst)
|
|||
|
||||
if (js.op->wantsCA)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg dest = inplace_carry ? WA : ARM64Reg::WSP;
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg dest = inplace_carry ? ARM64Reg(WA) : ARM64Reg::WSP;
|
||||
if (a != s)
|
||||
{
|
||||
ASR(RA, RS, amount);
|
||||
|
@ -901,7 +898,6 @@ void JitArm64::srawix(UGeckoInstruction inst)
|
|||
CSINC(WA, ARM64Reg::WSP, ARM64Reg::WSP, CC_EQ);
|
||||
ComputeCarry(WA);
|
||||
}
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -936,9 +932,10 @@ void JitArm64::addic(UGeckoInstruction inst)
|
|||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
CARRY_IF_NEEDED(ADDI2R, ADDSI2R, gpr.R(d), gpr.R(a), simm, WA);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
ComputeCarry();
|
||||
if (rc)
|
||||
|
@ -1037,12 +1034,10 @@ void JitArm64::mulli(UGeckoInstruction inst)
|
|||
gpr.BindToRegister(d, allocate_reg);
|
||||
|
||||
// Reuse d to hold the immediate if possible, allocate a register otherwise.
|
||||
ARM64Reg WA = allocate_reg ? gpr.GetReg() : gpr.R(d);
|
||||
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
|
||||
|
||||
MOVI2R(WA, (u32)(s32)inst.SIMM_16);
|
||||
MUL(gpr.R(d), gpr.R(a), WA);
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,16 +1132,16 @@ void JitArm64::addzex(UGeckoInstruction inst)
|
|||
{
|
||||
case CarryFlag::InPPCState:
|
||||
{
|
||||
gpr.BindToRegister(d, d == a);
|
||||
ARM64Reg WA = d == a ? gpr.GetReg() : gpr.R(d);
|
||||
const bool allocate_reg = d == a;
|
||||
gpr.BindToRegister(d, allocate_reg);
|
||||
|
||||
{
|
||||
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
|
||||
}
|
||||
|
||||
ComputeCarry();
|
||||
|
||||
if (d == a)
|
||||
gpr.Unlock(WA);
|
||||
|
||||
break;
|
||||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
|
@ -1229,18 +1224,16 @@ void JitArm64::subfex(UGeckoInstruction inst)
|
|||
{
|
||||
case CarryFlag::InPPCState:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d));
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
MOVI2R(WA, ~i + j);
|
||||
ADC(gpr.R(d), WA, ARM64Reg::WZR);
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::ConstantTrue:
|
||||
|
@ -1274,9 +1267,17 @@ void JitArm64::subfex(UGeckoInstruction inst)
|
|||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
ARM64Reg RB = mex ? gpr.GetReg() : gpr.R(b);
|
||||
{
|
||||
Arm64GPRCache::ScopedARM64Reg RB;
|
||||
if (mex)
|
||||
{
|
||||
RB = gpr.GetScopedReg();
|
||||
MOVI2R(RB, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
RB = gpr.R(b);
|
||||
}
|
||||
|
||||
if (js.carryFlag == CarryFlag::ConstantTrue)
|
||||
{
|
||||
|
@ -1287,10 +1288,9 @@ void JitArm64::subfex(UGeckoInstruction inst)
|
|||
LoadCarry();
|
||||
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), RB, gpr.R(a));
|
||||
}
|
||||
}
|
||||
|
||||
ComputeCarry();
|
||||
if (mex)
|
||||
gpr.Unlock(RB);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -1343,12 +1343,13 @@ void JitArm64::subfzex(UGeckoInstruction inst)
|
|||
{
|
||||
case CarryFlag::InPPCState:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
MVN(gpr.R(d), gpr.R(a));
|
||||
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA);
|
||||
}
|
||||
ComputeCarry();
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
|
@ -1394,21 +1395,20 @@ void JitArm64::subfic(UGeckoInstruction inst)
|
|||
{
|
||||
const bool will_read = d == a;
|
||||
const bool is_zero = imm == 0;
|
||||
const bool allocate_reg = will_read && !is_zero;
|
||||
gpr.BindToRegister(d, will_read);
|
||||
|
||||
// d = imm - a
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
ARM64Reg WA = ARM64Reg::WZR;
|
||||
{
|
||||
Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
|
||||
if (!is_zero)
|
||||
{
|
||||
WA = will_read ? gpr.GetReg() : RD;
|
||||
WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
|
||||
MOVI2R(WA, imm);
|
||||
}
|
||||
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
|
||||
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WA);
|
||||
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
|
||||
}
|
||||
|
||||
ComputeCarry();
|
||||
}
|
||||
|
@ -1433,10 +1433,9 @@ void JitArm64::addex(UGeckoInstruction inst)
|
|||
{
|
||||
case CarryFlag::InPPCState:
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d));
|
||||
gpr.Unlock(WA);
|
||||
break;
|
||||
}
|
||||
case CarryFlag::InHostCarry:
|
||||
|
@ -1477,9 +1476,17 @@ void JitArm64::addex(UGeckoInstruction inst)
|
|||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
ARM64Reg RB = mex ? gpr.GetReg() : gpr.R(b);
|
||||
{
|
||||
Arm64GPRCache::ScopedARM64Reg RB;
|
||||
if (mex)
|
||||
{
|
||||
RB = gpr.GetScopedReg();
|
||||
MOVI2R(RB, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
RB = gpr.R(b);
|
||||
}
|
||||
|
||||
if (js.carryFlag == CarryFlag::ConstantFalse)
|
||||
{
|
||||
|
@ -1490,10 +1497,9 @@ void JitArm64::addex(UGeckoInstruction inst)
|
|||
LoadCarry();
|
||||
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), RB);
|
||||
}
|
||||
}
|
||||
|
||||
ComputeCarry();
|
||||
if (mex)
|
||||
gpr.Unlock(RB);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -1575,7 +1581,7 @@ void JitArm64::divwux(UGeckoInstruction inst)
|
|||
{
|
||||
UnsignedMagic m = UnsignedDivisionConstants(divisor);
|
||||
|
||||
ARM64Reg WI = allocate_reg ? gpr.GetReg() : RD;
|
||||
auto WI = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
|
||||
ARM64Reg XD = EncodeRegTo64(RD);
|
||||
|
||||
MOVI2R(WI, m.multiplier);
|
||||
|
@ -1590,9 +1596,6 @@ void JitArm64::divwux(UGeckoInstruction inst)
|
|||
}
|
||||
|
||||
LSR(XD, XD, 32 + m.shift);
|
||||
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WI);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -1719,7 +1722,7 @@ void JitArm64::divwx(UGeckoInstruction inst)
|
|||
ARM64Reg RA = gpr.R(a);
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
|
||||
ARM64Reg WA = allocate_reg ? gpr.GetReg() : RD;
|
||||
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
|
||||
|
||||
TST(RA, RA);
|
||||
ADDI2R(WA, RA, abs_val - 1, WA);
|
||||
|
@ -1729,9 +1732,6 @@ void JitArm64::divwx(UGeckoInstruction inst)
|
|||
NEG(RD, WA, ArithOption(WA, ShiftType::ASR, MathUtil::IntLog2(abs_val)));
|
||||
else
|
||||
ASR(RD, WA, MathUtil::IntLog2(abs_val));
|
||||
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1739,8 +1739,8 @@ void JitArm64::divwx(UGeckoInstruction inst)
|
|||
SignedMagic m = SignedDivisionConstants(divisor);
|
||||
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = allocate_reg ? gpr.GetReg() : RD;
|
||||
auto WA = gpr.GetScopedReg();
|
||||
auto WB = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
|
||||
|
||||
ARM64Reg XD = EncodeRegTo64(RD);
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
@ -1776,10 +1776,6 @@ void JitArm64::divwx(UGeckoInstruction inst)
|
|||
ASR(XD, XD, 32 + m.shift);
|
||||
ADD(RD, WA, RD);
|
||||
}
|
||||
|
||||
gpr.Unlock(WA);
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -1982,8 +1978,7 @@ void JitArm64::srawx(UGeckoInstruction inst)
|
|||
else
|
||||
{
|
||||
gpr.BindToRegister(a, a == s);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
if (a != s)
|
||||
{
|
||||
|
@ -2009,8 +2004,6 @@ void JitArm64::srawx(UGeckoInstruction inst)
|
|||
|
||||
CSET(WA, CC_NEQ);
|
||||
ComputeCarry(WA);
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2018,8 +2011,8 @@ void JitArm64::srawx(UGeckoInstruction inst)
|
|||
const bool will_read = a == b || a == s;
|
||||
gpr.BindToRegister(a, will_read);
|
||||
|
||||
const bool allocate_reg = will_read || js.op->wantsCA;
|
||||
ARM64Reg WA = allocate_reg ? gpr.GetReg() : gpr.R(a);
|
||||
auto WA =
|
||||
will_read || js.op->wantsCA ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(a));
|
||||
|
||||
LSL(EncodeRegTo64(WA), EncodeRegTo64(gpr.R(s)), 32);
|
||||
ASRV(EncodeRegTo64(WA), EncodeRegTo64(WA), EncodeRegTo64(gpr.R(b)));
|
||||
|
@ -2031,9 +2024,6 @@ void JitArm64::srawx(UGeckoInstruction inst)
|
|||
CSET(WA, CC_NEQ);
|
||||
ComputeCarry(WA);
|
||||
}
|
||||
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
@ -2088,10 +2078,9 @@ void JitArm64::rlwimix(UGeckoInstruction inst)
|
|||
// No rotation
|
||||
// No mask inversion
|
||||
gpr.BindToRegister(a, true);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
UBFX(WA, gpr.R(s), lsb, width);
|
||||
BFI(gpr.R(a), WA, lsb, width);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
else if (inst.SH && inst.MB <= inst.ME)
|
||||
{
|
||||
|
@ -2103,28 +2092,22 @@ void JitArm64::rlwimix(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ROR(WA, gpr.R(s), (rot_dist + lsb) % 32);
|
||||
BFI(gpr.R(a), WA, lsb, width);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(a, true);
|
||||
const bool allocate_reg = a == s;
|
||||
ARM64Reg RA = gpr.R(a);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = allocate_reg ? gpr.GetReg() : RA;
|
||||
auto WA = gpr.GetScopedReg();
|
||||
auto WB = a == s ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RA);
|
||||
|
||||
MOVI2R(WA, mask);
|
||||
BIC(WB, RA, WA);
|
||||
AND(WA, WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, rot_dist));
|
||||
ORR(RA, WB, WA);
|
||||
|
||||
gpr.Unlock(WA);
|
||||
if (allocate_reg)
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
|
|
|
@ -538,9 +538,12 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
|||
else
|
||||
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
|
||||
|
||||
ARM64Reg addr_base_reg = a_is_addr_base_reg ? ARM64Reg::INVALID_REG : gpr.GetReg();
|
||||
Arm64RegCache::ScopedARM64Reg addr_base_reg;
|
||||
if (!a_is_addr_base_reg)
|
||||
{
|
||||
addr_base_reg = gpr.GetScopedReg();
|
||||
MOV(addr_base_reg, addr_reg);
|
||||
}
|
||||
|
||||
BitSet32 gprs_to_discard{};
|
||||
if (!jo.memcheck)
|
||||
|
@ -628,8 +631,6 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
|||
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W30);
|
||||
if (jo.memcheck || !jo.fastmem)
|
||||
gpr.Unlock(ARM64Reg::W0);
|
||||
if (!a_is_addr_base_reg)
|
||||
gpr.Unlock(addr_base_reg);
|
||||
}
|
||||
|
||||
void JitArm64::stmw(UGeckoInstruction inst)
|
||||
|
@ -655,9 +656,12 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
|||
else
|
||||
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
|
||||
|
||||
ARM64Reg addr_base_reg = a_is_addr_base_reg ? ARM64Reg::INVALID_REG : gpr.GetReg();
|
||||
Arm64GPRCache::ScopedARM64Reg addr_base_reg;
|
||||
if (!a_is_addr_base_reg)
|
||||
{
|
||||
addr_base_reg = gpr.GetScopedReg();
|
||||
MOV(addr_base_reg, addr_reg);
|
||||
}
|
||||
|
||||
BitSet32 gprs_to_discard{};
|
||||
if (!jo.memcheck)
|
||||
|
@ -748,8 +752,6 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
|||
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W30);
|
||||
if (!jo.fastmem)
|
||||
gpr.Unlock(ARM64Reg::W0);
|
||||
if (!a_is_addr_base_reg)
|
||||
gpr.Unlock(addr_base_reg);
|
||||
}
|
||||
|
||||
void JitArm64::dcbx(UGeckoInstruction inst)
|
||||
|
@ -786,8 +788,8 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
|||
// bdnz afterwards! So if we invalidate a single cache line, we don't adjust the registers at
|
||||
// all, if we invalidate 2 cachelines we adjust the registers by one step, and so on.
|
||||
|
||||
const ARM64Reg reg_cycle_count = gpr.GetReg();
|
||||
const ARM64Reg reg_downcount = gpr.GetReg();
|
||||
const auto reg_cycle_count = gpr.GetScopedReg();
|
||||
const auto reg_downcount = gpr.GetScopedReg();
|
||||
|
||||
// Figure out how many loops we want to do.
|
||||
const u8 cycle_count_per_loop =
|
||||
|
@ -855,12 +857,9 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
|||
SetJumpTarget(branch_out);
|
||||
SetJumpTarget(branch_over);
|
||||
}
|
||||
|
||||
gpr.Unlock(reg_cycle_count, reg_downcount);
|
||||
}
|
||||
|
||||
constexpr ARM64Reg effective_addr = WB;
|
||||
const ARM64Reg physical_addr = gpr.GetReg();
|
||||
|
||||
if (a)
|
||||
ADD(effective_addr, gpr.R(a), gpr.R(b));
|
||||
|
@ -874,6 +873,8 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
|||
ADD(gpr.R(b), gpr.R(b), WA, ArithOption(WA, ShiftType::LSL, 5)); // Rb += (WA * 32)
|
||||
}
|
||||
|
||||
auto physical_addr = gpr.GetScopedReg();
|
||||
|
||||
// Translate effective address to physical address.
|
||||
const u8* loop_start = GetCodePtr();
|
||||
FixupBranch bat_lookup_failed;
|
||||
|
@ -939,7 +940,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
|||
SwitchToNearCode();
|
||||
SetJumpTarget(near_addr);
|
||||
|
||||
gpr.Unlock(WA, WB, physical_addr);
|
||||
gpr.Unlock(WA, WB);
|
||||
if (make_loop)
|
||||
gpr.Unlock(loop_counter);
|
||||
}
|
||||
|
|
|
@ -268,14 +268,14 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
|||
|
||||
const bool have_single = fpr.IsSingle(inst.FS, true);
|
||||
|
||||
ARM64Reg V0 =
|
||||
Arm64FPRCache::ScopedARM64Reg V0 =
|
||||
fpr.R(inst.FS, want_single && have_single ? RegType::LowerPairSingle : RegType::LowerPair);
|
||||
|
||||
if (want_single && !have_single)
|
||||
{
|
||||
const ARM64Reg single_reg = fpr.GetReg();
|
||||
auto single_reg = fpr.GetScopedReg();
|
||||
ConvertDoubleToSingleLower(inst.FS, single_reg, V0);
|
||||
V0 = single_reg;
|
||||
V0 = std::move(single_reg);
|
||||
}
|
||||
|
||||
gpr.Lock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W30);
|
||||
|
@ -425,9 +425,6 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
|||
MOV(gpr.R(a), addr_reg);
|
||||
}
|
||||
|
||||
if (want_single && !have_single)
|
||||
fpr.Unlock(V0);
|
||||
|
||||
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W30);
|
||||
fpr.Unlock(ARM64Reg::Q0);
|
||||
if (!jo.fastmem)
|
||||
|
|
|
@ -173,20 +173,21 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
|||
|
||||
const bool have_single = fpr.IsSingle(inst.RS);
|
||||
|
||||
ARM64Reg VS = fpr.R(inst.RS, have_single ? RegType::Single : RegType::Register);
|
||||
Arm64FPRCache::ScopedARM64Reg VS =
|
||||
fpr.R(inst.RS, have_single ? RegType::Single : RegType::Register);
|
||||
|
||||
if (js.assumeNoPairedQuantize)
|
||||
{
|
||||
if (!have_single)
|
||||
{
|
||||
const ARM64Reg single_reg = fpr.GetReg();
|
||||
auto single_reg = fpr.GetScopedReg();
|
||||
|
||||
if (w)
|
||||
m_float_emit.FCVT(32, 64, EncodeRegToDouble(single_reg), EncodeRegToDouble(VS));
|
||||
else
|
||||
m_float_emit.FCVTN(32, EncodeRegToDouble(single_reg), EncodeRegToDouble(VS));
|
||||
|
||||
VS = single_reg;
|
||||
VS = std::move(single_reg);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -279,9 +280,6 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
|||
MOV(gpr.R(inst.RA), addr_reg);
|
||||
}
|
||||
|
||||
if (js.assumeNoPairedQuantize && !have_single)
|
||||
fpr.Unlock(VS);
|
||||
|
||||
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W30);
|
||||
fpr.Unlock(ARM64Reg::Q0);
|
||||
if (!js.assumeNoPairedQuantize || !jo.fastmem)
|
||||
|
|
|
@ -108,16 +108,17 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
|
|||
const ARM64Reg VC = use_c ? reg_encoder(fpr.R(c, type)) : ARM64Reg::INVALID_REG;
|
||||
const ARM64Reg VD = reg_encoder(fpr.RW(d, type));
|
||||
|
||||
ARM64Reg V0Q = ARM64Reg::INVALID_REG;
|
||||
ARM64Reg V1Q = ARM64Reg::INVALID_REG;
|
||||
ARM64Reg V2Q = ARM64Reg::INVALID_REG;
|
||||
{
|
||||
Arm64FPRCache::ScopedARM64Reg V0Q = ARM64Reg::INVALID_REG;
|
||||
Arm64FPRCache::ScopedARM64Reg V1Q = ARM64Reg::INVALID_REG;
|
||||
Arm64FPRCache::ScopedARM64Reg V2Q = ARM64Reg::INVALID_REG;
|
||||
|
||||
ARM64Reg rounded_c_reg = VC;
|
||||
if (round_c)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, !singles, "Tried to apply 25-bit precision to single");
|
||||
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
rounded_c_reg = reg_encoder(V0Q);
|
||||
Force25BitPrecision(rounded_c_reg, VC);
|
||||
}
|
||||
|
@ -126,7 +127,7 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
|
|||
if (fma && inaccurate_fma && VD == VB)
|
||||
{
|
||||
if (V0Q == ARM64Reg::INVALID_REG)
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
inaccurate_fma_reg = reg_encoder(V0Q);
|
||||
}
|
||||
|
||||
|
@ -137,17 +138,17 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
|
|||
m_accurate_nans && (VD == VA || (use_b && VD == VB) || (use_c && VD == VC));
|
||||
if (need_accurate_fma_reg || preserve_d)
|
||||
{
|
||||
V1Q = fpr.GetReg();
|
||||
V1Q = fpr.GetScopedReg();
|
||||
result_reg = reg_encoder(V1Q);
|
||||
}
|
||||
|
||||
if (m_accurate_nans)
|
||||
{
|
||||
if (V0Q == ARM64Reg::INVALID_REG)
|
||||
V0Q = fpr.GetReg();
|
||||
V0Q = fpr.GetScopedReg();
|
||||
|
||||
if (duplicated_c || VD == result_reg)
|
||||
V2Q = fpr.GetReg();
|
||||
V2Q = fpr.GetScopedReg();
|
||||
}
|
||||
|
||||
switch (op5)
|
||||
|
@ -295,13 +296,7 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
|
|||
|
||||
if (m_accurate_nans)
|
||||
SetJumpTarget(nan_fixup);
|
||||
|
||||
if (V0Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V0Q);
|
||||
if (V1Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V1Q);
|
||||
if (V2Q != ARM64Reg::INVALID_REG)
|
||||
fpr.Unlock(V2Q);
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, singles == singles_func(),
|
||||
"Register allocation turned singles into doubles in the middle of ps_arith");
|
||||
|
@ -339,12 +334,11 @@ void JitArm64::ps_sel(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
const ARM64Reg V0Q = fpr.GetReg();
|
||||
const auto V0Q = fpr.GetScopedReg();
|
||||
const ARM64Reg V0 = reg_encoder(V0Q);
|
||||
m_float_emit.FCMGE(size, V0, VA);
|
||||
m_float_emit.BSL(V0, VC, VB);
|
||||
m_float_emit.MOV(VD, V0);
|
||||
fpr.Unlock(V0Q);
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)),
|
||||
|
@ -375,16 +369,21 @@ void JitArm64::ps_sumX(UGeckoInstruction inst)
|
|||
const ARM64Reg VB = fpr.R(b, type);
|
||||
const ARM64Reg VC = fpr.R(c, type);
|
||||
const ARM64Reg VD = fpr.RW(d, type);
|
||||
const ARM64Reg V0 = fpr.GetReg();
|
||||
|
||||
{
|
||||
const auto V0 = fpr.GetScopedReg();
|
||||
|
||||
m_float_emit.DUP(size, reg_encoder(V0), reg_encoder(VB), 1);
|
||||
|
||||
if (m_accurate_nans)
|
||||
{
|
||||
// If the first input is NaN, set the temp register for the second input to 0. This is because:
|
||||
// If the first input is NaN, set the temp register for the second input to 0. This is
|
||||
// because:
|
||||
//
|
||||
// - If the second input is also NaN, setting it to 0 ensures that the first NaN will be picked.
|
||||
// - If only the first input is NaN, setting the second input to 0 has no effect on the result.
|
||||
// - If the second input is also NaN, setting it to 0 ensures that the first NaN will be
|
||||
// picked.
|
||||
// - If only the first input is NaN, setting the second input to 0 has no effect on the
|
||||
// result.
|
||||
//
|
||||
// Either way, we can then do an FADD as usual, and the FADD will make the NaN quiet.
|
||||
m_float_emit.FCMP(scalar_reg_encoder(VA));
|
||||
|
@ -408,8 +407,7 @@ void JitArm64::ps_sumX(UGeckoInstruction inst)
|
|||
m_float_emit.FADD(scalar_reg_encoder(V0), scalar_reg_encoder(V0), scalar_reg_encoder(VA));
|
||||
m_float_emit.INS(size, VD, 0, V0, 0);
|
||||
}
|
||||
|
||||
fpr.Unlock(V0);
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)),
|
||||
"Register allocation turned singles into doubles in the middle of ps_sumX");
|
||||
|
|
|
@ -254,18 +254,26 @@ void Arm64GPRCache::FlushRegisters(BitSet32 regs, FlushMode mode, ARM64Reg tmp_r
|
|||
// We've got two guest registers in a row to store
|
||||
OpArg& reg1 = m_guest_registers[GUEST_GPR_OFFSET + i];
|
||||
OpArg& reg2 = m_guest_registers[GUEST_GPR_OFFSET + i + 1];
|
||||
if (reg1.IsDirty() && reg2.IsDirty() && reg1.GetType() == RegType::Register &&
|
||||
reg2.GetType() == RegType::Register)
|
||||
const bool reg1_imm = reg1.GetType() == RegType::Immediate;
|
||||
const bool reg2_imm = reg2.GetType() == RegType::Immediate;
|
||||
const bool reg1_zero = reg1_imm && reg1.GetImm() == 0;
|
||||
const bool reg2_zero = reg2_imm && reg2.GetImm() == 0;
|
||||
const bool flush_all = mode == FlushMode::All;
|
||||
if (reg1.IsDirty() && reg2.IsDirty() &&
|
||||
(reg1.GetType() == RegType::Register || (reg1_imm && (reg1_zero || flush_all))) &&
|
||||
(reg2.GetType() == RegType::Register || (reg2_imm && (reg2_zero || flush_all))))
|
||||
{
|
||||
const size_t ppc_offset = GetGuestByIndex(i).ppc_offset;
|
||||
if (ppc_offset <= 252)
|
||||
{
|
||||
ARM64Reg RX1 = R(GetGuestByIndex(i));
|
||||
ARM64Reg RX2 = R(GetGuestByIndex(i + 1));
|
||||
ARM64Reg RX1 = reg1_zero ? ARM64Reg::WZR : R(GetGuestByIndex(i));
|
||||
ARM64Reg RX2 = reg2_zero ? ARM64Reg::WZR : R(GetGuestByIndex(i + 1));
|
||||
m_emit->STP(IndexType::Signed, RX1, RX2, PPC_REG, u32(ppc_offset));
|
||||
if (mode == FlushMode::All)
|
||||
if (flush_all)
|
||||
{
|
||||
if (!reg1_zero)
|
||||
UnlockRegister(EncodeRegTo32(RX1));
|
||||
if (!reg2_zero)
|
||||
UnlockRegister(EncodeRegTo32(RX2));
|
||||
reg1.Flush();
|
||||
reg2.Flush();
|
||||
|
|
|
@ -177,6 +177,59 @@ public:
|
|||
// Requires unlocking after done
|
||||
Arm64Gen::ARM64Reg GetReg();
|
||||
|
||||
class ScopedARM64Reg
|
||||
{
|
||||
public:
|
||||
inline ScopedARM64Reg() = default;
|
||||
ScopedARM64Reg(const ScopedARM64Reg&) = delete;
|
||||
explicit inline ScopedARM64Reg(Arm64RegCache& cache) : m_reg(cache.GetReg()), m_gpr(&cache) {}
|
||||
inline ScopedARM64Reg(Arm64Gen::ARM64Reg reg) : m_reg(reg) {}
|
||||
inline ScopedARM64Reg(ScopedARM64Reg&& scoped_reg) { *this = std::move(scoped_reg); }
|
||||
inline ~ScopedARM64Reg() { Unlock(); }
|
||||
|
||||
inline ScopedARM64Reg& operator=(const ScopedARM64Reg&) = delete;
|
||||
inline ScopedARM64Reg& operator=(Arm64Gen::ARM64Reg reg)
|
||||
{
|
||||
Unlock();
|
||||
m_reg = reg;
|
||||
return *this;
|
||||
}
|
||||
inline ScopedARM64Reg& operator=(ScopedARM64Reg&& scoped_reg)
|
||||
{
|
||||
// Taking ownership of an existing scoped register, no need to release.
|
||||
m_reg = scoped_reg.m_reg;
|
||||
m_gpr = scoped_reg.m_gpr;
|
||||
scoped_reg.Invalidate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Arm64Gen::ARM64Reg GetReg() const { return m_reg; }
|
||||
inline operator Arm64Gen::ARM64Reg() const { return GetReg(); }
|
||||
inline void Unlock()
|
||||
{
|
||||
// Only unlock the register if GPR is set.
|
||||
if (m_gpr != nullptr)
|
||||
{
|
||||
m_gpr->Unlock(m_reg);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private:
|
||||
inline void Invalidate()
|
||||
{
|
||||
m_reg = Arm64Gen::ARM64Reg::INVALID_REG;
|
||||
m_gpr = nullptr;
|
||||
}
|
||||
|
||||
Arm64Gen::ARM64Reg m_reg = Arm64Gen::ARM64Reg::INVALID_REG;
|
||||
Arm64RegCache* m_gpr = nullptr;
|
||||
};
|
||||
|
||||
// Returns a temporary register
|
||||
// Unlocking is implicitly handled through RAII
|
||||
inline ScopedARM64Reg GetScopedReg() { return ScopedARM64Reg(*this); }
|
||||
|
||||
void UpdateLastUsed(BitSet32 regs_used);
|
||||
|
||||
// Get available host registers
|
||||
|
|
|
@ -48,17 +48,16 @@ void JitArm64::FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg)
|
|||
// if the internal representation either has bit 63 set or has all bits set to zero.
|
||||
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
|
||||
// doesn't accidentally become considered set. Gross but necessary; this can break actual games.
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
|
||||
CMP(reg, ARM64Reg::ZR);
|
||||
CSEL(reg, reg, XA, CC_NEQ);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
// fpscr.VX = (fpscr & FPSCR_VX_ANY) != 0
|
||||
MOVI2R(WA, FPSCR_VX_ANY);
|
||||
|
@ -71,8 +70,6 @@ void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
|
|||
TST(WA, fpscr, ArithOption(fpscr, ShiftType::LSR, 22));
|
||||
CSET(WA, CCFlags::CC_NEQ);
|
||||
BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_FEX), 1);
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::UpdateRoundingMode()
|
||||
|
@ -135,7 +132,7 @@ void JitArm64::mcrxr(UGeckoInstruction inst)
|
|||
JITDISABLE(bJITSystemRegistersOff);
|
||||
|
||||
gpr.BindCRToRegister(inst.CRFD, false);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
ARM64Reg XB = gpr.CR(inst.CRFD);
|
||||
ARM64Reg WB = EncodeRegTo32(XB);
|
||||
|
@ -155,8 +152,6 @@ void JitArm64::mcrxr(UGeckoInstruction inst)
|
|||
// Clear XER[0-3]
|
||||
static_assert(PPCSTATE_OFF(xer_ca) + 1 == PPCSTATE_OFF(xer_so_ov));
|
||||
STRH(IndexType::Unsigned, ARM64Reg::WZR, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::mfsr(UGeckoInstruction inst)
|
||||
|
@ -186,14 +181,12 @@ void JitArm64::mfsrin(UGeckoInstruction inst)
|
|||
|
||||
ARM64Reg RB = gpr.R(b);
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
ARM64Reg index = gpr.GetReg();
|
||||
auto index = gpr.GetScopedReg();
|
||||
ARM64Reg addr = EncodeRegTo64(RD);
|
||||
|
||||
UBFM(index, RB, 28, 31);
|
||||
ADDI2R(addr, PPC_REG, PPCSTATE_OFF_SR(0), addr);
|
||||
LDR(RD, addr, ArithOption(EncodeRegTo64(index), true));
|
||||
|
||||
gpr.Unlock(index);
|
||||
}
|
||||
|
||||
void JitArm64::mtsrin(UGeckoInstruction inst)
|
||||
|
@ -206,14 +199,12 @@ void JitArm64::mtsrin(UGeckoInstruction inst)
|
|||
|
||||
ARM64Reg RB = gpr.R(b);
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
ARM64Reg index = gpr.GetReg();
|
||||
ARM64Reg addr = gpr.GetReg();
|
||||
auto index = gpr.GetScopedReg();
|
||||
auto addr = gpr.GetScopedReg();
|
||||
|
||||
UBFM(index, RB, 28, 31);
|
||||
ADDI2R(EncodeRegTo64(addr), PPC_REG, PPCSTATE_OFF_SR(0), EncodeRegTo64(addr));
|
||||
STR(RD, EncodeRegTo64(addr), ArithOption(EncodeRegTo64(index), true));
|
||||
|
||||
gpr.Unlock(index, addr);
|
||||
}
|
||||
|
||||
void JitArm64::twx(UGeckoInstruction inst)
|
||||
|
@ -223,7 +214,7 @@ void JitArm64::twx(UGeckoInstruction inst)
|
|||
|
||||
s32 a = inst.RA;
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
if (inst.OPCD == 3) // twi
|
||||
{
|
||||
|
@ -278,8 +269,6 @@ void JitArm64::twx(UGeckoInstruction inst)
|
|||
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
WriteExit(js.compilerPC + 4);
|
||||
}
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::mfspr(UGeckoInstruction inst)
|
||||
|
@ -294,19 +283,19 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||
case SPR_TL:
|
||||
case SPR_TU:
|
||||
{
|
||||
ARM64Reg Wg = gpr.GetReg();
|
||||
auto Wg = gpr.GetScopedReg();
|
||||
ARM64Reg Xg = EncodeRegTo64(Wg);
|
||||
|
||||
ARM64Reg Wresult = gpr.GetReg();
|
||||
auto Wresult = gpr.GetScopedReg();
|
||||
ARM64Reg Xresult = EncodeRegTo64(Wresult);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
auto WB = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
ARM64Reg XB = EncodeRegTo64(WB);
|
||||
|
||||
ARM64Reg VC = fpr.GetReg();
|
||||
ARM64Reg VD = fpr.GetReg();
|
||||
auto VC = fpr.GetScopedReg();
|
||||
auto VD = fpr.GetScopedReg();
|
||||
ARM64Reg SC = EncodeRegToSingle(VC);
|
||||
ARM64Reg SD = EncodeRegToSingle(VD);
|
||||
|
||||
|
@ -371,8 +360,6 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||
else
|
||||
LSR(EncodeRegTo64(gpr.R(n)), Xresult, 32);
|
||||
|
||||
gpr.Unlock(Wg, Wresult, WA, WB);
|
||||
fpr.Unlock(VC, VD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -381,22 +368,18 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||
LSR(EncodeRegTo64(gpr.R(d)), Xresult, 32);
|
||||
else
|
||||
MOV(gpr.R(d), Wresult);
|
||||
|
||||
gpr.Unlock(Wg, Wresult, WA, WB);
|
||||
fpr.Unlock(VC, VD);
|
||||
}
|
||||
break;
|
||||
case SPR_XER:
|
||||
{
|
||||
gpr.BindToRegister(d, false);
|
||||
ARM64Reg RD = gpr.R(d);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
LDRH(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_stringctrl));
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_CA_SHIFT));
|
||||
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov));
|
||||
ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_OV_SHIFT));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
break;
|
||||
case SPR_WPAR:
|
||||
|
@ -462,14 +445,13 @@ void JitArm64::mtspr(UGeckoInstruction inst)
|
|||
case SPR_XER:
|
||||
{
|
||||
ARM64Reg RD = gpr.R(inst.RD);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
AND(WA, RD, LogicalImm(0xFFFFFF7F, GPRSize::B32));
|
||||
STRH(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_stringctrl));
|
||||
UBFM(WA, RD, XER_CA_SHIFT, XER_CA_SHIFT + 1);
|
||||
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
|
||||
UBFM(WA, RD, XER_OV_SHIFT, 31); // Same as WA = RD >> XER_OV_SHIFT
|
||||
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov));
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -553,9 +535,10 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||
return;
|
||||
}
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
{
|
||||
auto WB = gpr.GetScopedReg();
|
||||
ARM64Reg XB = EncodeRegTo64(WB);
|
||||
|
||||
// creqv or crnand or crnor
|
||||
|
@ -623,44 +606,41 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||
ORR(XA, XA, XB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Store result bit in CRBD
|
||||
int field = inst.CRBD >> 2;
|
||||
int bit = 3 - (inst.CRBD & 3);
|
||||
|
||||
gpr.Unlock(WB);
|
||||
WB = ARM64Reg::INVALID_REG;
|
||||
gpr.BindCRToRegister(field, true);
|
||||
XB = gpr.CR(field);
|
||||
ARM64Reg CR = gpr.CR(field);
|
||||
|
||||
if (bit != PowerPC::CR_GT_BIT)
|
||||
FixGTBeforeSettingCRFieldBit(XB);
|
||||
FixGTBeforeSettingCRFieldBit(CR);
|
||||
|
||||
switch (bit)
|
||||
{
|
||||
case PowerPC::CR_SO_BIT: // set bit 59 to input
|
||||
BFI(XB, XA, PowerPC::CR_EMU_SO_BIT, 1);
|
||||
BFI(CR, XA, PowerPC::CR_EMU_SO_BIT, 1);
|
||||
break;
|
||||
|
||||
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
|
||||
AND(XB, XB, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
|
||||
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
|
||||
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
|
||||
ORR(XB, XB, XA);
|
||||
ORR(CR, CR, XA);
|
||||
break;
|
||||
|
||||
case PowerPC::CR_GT_BIT: // set bit 63 to !input
|
||||
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
|
||||
BFI(XB, XA, 63, 1);
|
||||
BFI(CR, XA, 63, 1);
|
||||
break;
|
||||
|
||||
case PowerPC::CR_LT_BIT: // set bit 62 to input
|
||||
BFI(XB, XA, PowerPC::CR_EMU_LT_BIT, 1);
|
||||
BFI(CR, XA, PowerPC::CR_EMU_LT_BIT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
ORR(XB, XB, LogicalImm(1ULL << 32, GPRSize::B64));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
|
||||
}
|
||||
|
||||
void JitArm64::mfcr(UGeckoInstruction inst)
|
||||
|
@ -670,8 +650,8 @@ void JitArm64::mfcr(UGeckoInstruction inst)
|
|||
|
||||
gpr.BindToRegister(inst.RD, false);
|
||||
ARM64Reg WA = gpr.R(inst.RD);
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
ARM64Reg WC = gpr.GetReg();
|
||||
auto WB = gpr.GetScopedReg();
|
||||
auto WC = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
ARM64Reg XB = EncodeRegTo64(WB);
|
||||
ARM64Reg XC = EncodeRegTo64(WC);
|
||||
|
@ -716,8 +696,6 @@ void JitArm64::mfcr(UGeckoInstruction inst)
|
|||
else if (!js.op->crInUse[i])
|
||||
gpr.StoreCRRegisters(BitSet8{i}, WC);
|
||||
}
|
||||
|
||||
gpr.Unlock(WB, WC);
|
||||
}
|
||||
|
||||
void JitArm64::mtcrf(UGeckoInstruction inst)
|
||||
|
@ -729,7 +707,7 @@ void JitArm64::mtcrf(UGeckoInstruction inst)
|
|||
if (crm != 0)
|
||||
{
|
||||
ARM64Reg RS = gpr.R(inst.RS);
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
auto WB = gpr.GetScopedReg();
|
||||
ARM64Reg XB = EncodeRegTo64(WB);
|
||||
MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
|
@ -753,7 +731,6 @@ void JitArm64::mtcrf(UGeckoInstruction inst)
|
|||
LDR(CR, XB, ArithOption(CR, true));
|
||||
}
|
||||
}
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -771,7 +748,7 @@ void JitArm64::mcrfs(UGeckoInstruction inst)
|
|||
|
||||
gpr.BindCRToRegister(field, false);
|
||||
ARM64Reg CR = gpr.CR(field);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg WCR = EncodeRegTo32(CR);
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
||||
|
@ -789,8 +766,6 @@ void JitArm64::mcrfs(UGeckoInstruction inst)
|
|||
|
||||
MOVP2R(XA, PowerPC::ConditionRegister::s_crTable.data());
|
||||
LDR(CR, XA, ArithOption(CR, true));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::mffsx(UGeckoInstruction inst)
|
||||
|
@ -799,7 +774,7 @@ void JitArm64::mffsx(UGeckoInstruction inst)
|
|||
JITDISABLE(bJITSystemRegistersOff);
|
||||
FALLBACK_IF(inst.Rc);
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
@ -808,8 +783,6 @@ void JitArm64::mffsx(UGeckoInstruction inst)
|
|||
|
||||
ORR(XA, XA, LogicalImm(0xFFF8'0000'0000'0000, GPRSize::B64));
|
||||
m_float_emit.FMOV(EncodeRegToDouble(VD), XA);
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
void JitArm64::mtfsb0x(UGeckoInstruction inst)
|
||||
|
@ -824,7 +797,8 @@ void JitArm64::mtfsb0x(UGeckoInstruction inst)
|
|||
if (mask == FPSCR_FEX || mask == FPSCR_VX)
|
||||
return;
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
|
@ -833,8 +807,7 @@ void JitArm64::mtfsb0x(UGeckoInstruction inst)
|
|||
if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
|
||||
UpdateFPExceptionSummary(WA);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.CRBD >= 29)
|
||||
UpdateRoundingMode();
|
||||
|
@ -852,25 +825,24 @@ void JitArm64::mtfsb1x(UGeckoInstruction inst)
|
|||
if (mask == FPSCR_FEX || mask == FPSCR_VX)
|
||||
return;
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
if ((mask & FPSCR_ANY_X) != 0)
|
||||
{
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
auto WB = gpr.GetScopedReg();
|
||||
TST(WA, LogicalImm(mask, GPRSize::B32));
|
||||
ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32));
|
||||
CSEL(WA, WA, WB, CCFlags::CC_NEQ);
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
ORR(WA, WA, LogicalImm(mask, GPRSize::B32));
|
||||
|
||||
if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
|
||||
UpdateFPExceptionSummary(WA);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.CRBD >= 29)
|
||||
UpdateRoundingMode();
|
||||
|
@ -887,7 +859,8 @@ void JitArm64::mtfsfix(UGeckoInstruction inst)
|
|||
u8 shift = 28 - 4 * inst.CRFD;
|
||||
u32 mask = 0xF << shift;
|
||||
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
{
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
|
@ -902,17 +875,15 @@ void JitArm64::mtfsfix(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
auto WB = gpr.GetScopedReg();
|
||||
MOVZ(WB, imm);
|
||||
BFI(WA, WB, shift, 4);
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
|
||||
UpdateFPExceptionSummary(WA);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
// Field 7 contains NI and RN.
|
||||
if (inst.CRFD == 7)
|
||||
|
@ -936,20 +907,19 @@ void JitArm64::mtfsfx(UGeckoInstruction inst)
|
|||
if (mask == 0xFFFFFFFF)
|
||||
{
|
||||
ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
|
||||
m_float_emit.FMOV(WA, EncodeRegToSingle(VB));
|
||||
|
||||
UpdateFPExceptionSummary(WA);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
else if (mask != 0)
|
||||
{
|
||||
ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
ARM64Reg WB = gpr.GetReg();
|
||||
auto WA = gpr.GetScopedReg();
|
||||
{
|
||||
auto WB = gpr.GetScopedReg();
|
||||
|
||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
m_float_emit.FMOV(WB, EncodeRegToSingle(VB));
|
||||
|
@ -962,23 +932,18 @@ void JitArm64::mtfsfx(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WC = gpr.GetReg();
|
||||
auto WC = gpr.GetScopedReg();
|
||||
|
||||
MOVI2R(WC, mask);
|
||||
BIC(WA, WA, WC);
|
||||
AND(WB, WB, WC);
|
||||
|
||||
gpr.Unlock(WC);
|
||||
}
|
||||
ORR(WA, WA, WB);
|
||||
|
||||
gpr.Unlock(WB);
|
||||
}
|
||||
|
||||
if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
|
||||
UpdateFPExceptionSummary(WA);
|
||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
|
||||
if (inst.FM & 1)
|
||||
|
|
|
@ -86,7 +86,7 @@ void Host_UpdateDisasmDialog()
|
|||
{
|
||||
}
|
||||
|
||||
void Host_JitCacheCleared()
|
||||
void Host_JitCacheInvalidation()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
|
||||
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
|
||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
@ -36,7 +37,7 @@ AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent) : QWidget(
|
|||
|
||||
// If hardcore is enabled when the emulator starts, make sure it turns off what it needs to
|
||||
if (Config::Get(Config::RA_HARDCORE_ENABLED))
|
||||
ToggleHardcore();
|
||||
UpdateHardcoreMode();
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::UpdateData(int login_failed_code)
|
||||
|
@ -258,11 +259,7 @@ void AchievementSettingsWidget::ToggleRAIntegration()
|
|||
instance.Init();
|
||||
else
|
||||
instance.Shutdown();
|
||||
if (Config::Get(Config::RA_HARDCORE_ENABLED))
|
||||
{
|
||||
emit Settings::Instance().EmulationStateChanged(Core::GetState(Core::System::GetInstance()));
|
||||
emit Settings::Instance().HardcoreStateChanged();
|
||||
}
|
||||
UpdateHardcoreMode();
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::Login()
|
||||
|
@ -275,25 +272,32 @@ void AchievementSettingsWidget::Login()
|
|||
}
|
||||
|
||||
void AchievementSettingsWidget::Logout()
|
||||
{
|
||||
auto confirm = ModalMessageBox::question(
|
||||
this, tr("Confirm Logout"), tr("Are you sure you want to log out of RetroAchievements?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton, Qt::ApplicationModal);
|
||||
if (confirm == QMessageBox::Yes)
|
||||
{
|
||||
AchievementManager::GetInstance().Logout();
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::ToggleHardcore()
|
||||
{
|
||||
SaveSettings();
|
||||
AchievementManager::GetInstance().SetHardcoreMode();
|
||||
if (Config::Get(Config::RA_HARDCORE_ENABLED))
|
||||
{
|
||||
if (Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f)
|
||||
Config::SetBaseOrCurrent(Config::MAIN_EMULATION_SPEED, 1.0f);
|
||||
Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, false);
|
||||
Config::SetBaseOrCurrent(Config::MAIN_ENABLE_CHEATS, false);
|
||||
Settings::Instance().SetDebugModeEnabled(false);
|
||||
auto confirm = ModalMessageBox::question(
|
||||
this, tr("Confirm Hardcore Off"), tr("Are you sure you want to turn hardcore mode off?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton, Qt::ApplicationModal);
|
||||
if (confirm != QMessageBox::Yes)
|
||||
{
|
||||
SignalBlocking(m_common_hardcore_enabled_input)->setChecked(true);
|
||||
return;
|
||||
}
|
||||
emit Settings::Instance().EmulationStateChanged(Core::GetState(Core::System::GetInstance()));
|
||||
emit Settings::Instance().HardcoreStateChanged();
|
||||
}
|
||||
SaveSettings();
|
||||
UpdateHardcoreMode();
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::ToggleUnofficial()
|
||||
|
@ -323,4 +327,15 @@ void AchievementSettingsWidget::ToggleProgress()
|
|||
SaveSettings();
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::UpdateHardcoreMode()
|
||||
{
|
||||
AchievementManager::GetInstance().SetHardcoreMode();
|
||||
if (Config::Get(Config::RA_HARDCORE_ENABLED))
|
||||
{
|
||||
Settings::Instance().SetDebugModeEnabled(false);
|
||||
}
|
||||
emit Settings::Instance().EmulationStateChanged(Core::GetState(Core::System::GetInstance()));
|
||||
emit Settings::Instance().HardcoreStateChanged();
|
||||
}
|
||||
|
||||
#endif // USE_RETRO_ACHIEVEMENTS
|
||||
|
|
|
@ -39,6 +39,8 @@ private:
|
|||
void ToggleDiscordPresence();
|
||||
void ToggleProgress();
|
||||
|
||||
void UpdateHardcoreMode();
|
||||
|
||||
QGroupBox* m_common_box;
|
||||
QVBoxLayout* m_common_layout;
|
||||
ToolTipCheckBox* m_common_integration_enabled_input;
|
||||
|
|
|
@ -318,6 +318,8 @@ add_executable(dolphin-mpn
|
|||
QtUtils/ParallelProgressDialog.h
|
||||
QtUtils/PartiallyClosableTabWidget.cpp
|
||||
QtUtils/PartiallyClosableTabWidget.h
|
||||
QtUtils/QtUtils.cpp
|
||||
QtUtils/QtUtils.h
|
||||
QtUtils/SetWindowDecorations.cpp
|
||||
QtUtils/SetWindowDecorations.h
|
||||
QtUtils/SignalBlocking.h
|
||||
|
|
|
@ -140,20 +140,14 @@ void ARCodeWidget::SortAlphabetically()
|
|||
|
||||
void ARCodeWidget::SortEnabledCodesFirst()
|
||||
{
|
||||
std::stable_sort(m_ar_codes.begin(), m_ar_codes.end(), [](const auto& a, const auto& b) {
|
||||
return a.enabled && a.enabled != b.enabled;
|
||||
});
|
||||
|
||||
std::ranges::stable_partition(m_ar_codes, std::identity{}, &ActionReplay::ARCode::enabled);
|
||||
UpdateList();
|
||||
SaveCodes();
|
||||
}
|
||||
|
||||
void ARCodeWidget::SortDisabledCodesFirst()
|
||||
{
|
||||
std::stable_sort(m_ar_codes.begin(), m_ar_codes.end(), [](const auto& a, const auto& b) {
|
||||
return !a.enabled && a.enabled != b.enabled;
|
||||
});
|
||||
|
||||
std::ranges::stable_partition(m_ar_codes, std::logical_not{}, &ActionReplay::ARCode::enabled);
|
||||
UpdateList();
|
||||
SaveCodes();
|
||||
}
|
||||
|
|
|
@ -317,20 +317,14 @@ void GeckoCodeWidget::SortAlphabetically()
|
|||
|
||||
void GeckoCodeWidget::SortEnabledCodesFirst()
|
||||
{
|
||||
std::stable_sort(m_gecko_codes.begin(), m_gecko_codes.end(), [](const auto& a, const auto& b) {
|
||||
return a.enabled && a.enabled != b.enabled;
|
||||
});
|
||||
|
||||
std::ranges::stable_partition(m_gecko_codes, std::identity{}, &Gecko::GeckoCode::enabled);
|
||||
UpdateList();
|
||||
SaveCodes();
|
||||
}
|
||||
|
||||
void GeckoCodeWidget::SortDisabledCodesFirst()
|
||||
{
|
||||
std::stable_sort(m_gecko_codes.begin(), m_gecko_codes.end(), [](const auto& a, const auto& b) {
|
||||
return !a.enabled && a.enabled != b.enabled;
|
||||
});
|
||||
|
||||
std::ranges::stable_partition(m_gecko_codes, std::logical_not{}, &Gecko::GeckoCode::enabled);
|
||||
UpdateList();
|
||||
SaveCodes();
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ void GeneralWidget::AddDescriptions()
|
|||
"recommended. Different games and different GPUs will behave differently on each "
|
||||
"backend, so for the best emulation experience it is recommended to try each and "
|
||||
"select the backend that is least problematic.<br><br><dolphin_emphasis>If unsure, "
|
||||
"select OpenGL.</dolphin_emphasis>");
|
||||
"select %1.</dolphin_emphasis>");
|
||||
static const char TR_FULLSCREEN_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Uses the entire screen for rendering.<br><br>If disabled, a "
|
||||
"render window will be created instead.<br><br><dolphin_emphasis>If "
|
||||
|
@ -313,7 +313,9 @@ void GeneralWidget::AddDescriptions()
|
|||
"unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
|
||||
m_backend_combo->SetTitle(tr("Backend"));
|
||||
m_backend_combo->SetDescription(tr(TR_BACKEND_DESCRIPTION));
|
||||
m_backend_combo->SetDescription(
|
||||
tr(TR_BACKEND_DESCRIPTION)
|
||||
.arg(QString::fromStdString(VideoBackendBase::GetDefaultBackendDisplayName())));
|
||||
|
||||
m_adapter_combo->SetTitle(tr("Adapter"));
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ void HacksWidget::AddDescriptions()
|
|||
"Ignores any requests from the CPU to read from or write to the EFB. "
|
||||
"<br><br>Improves performance in some games, but will disable all EFB-based "
|
||||
"graphical effects or gameplay-related features.<br><br><dolphin_emphasis>If unsure, "
|
||||
"leave this unchecked.</dolphin_emphasis>");
|
||||
"leave this checked.</dolphin_emphasis>");
|
||||
static const char TR_IGNORE_FORMAT_CHANGE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Ignores any changes to the EFB format.<br><br>Improves performance in many games "
|
||||
"without "
|
||||
|
|
|
@ -313,7 +313,7 @@ void JITWidget::SaveQSettings() const
|
|||
void JITWidget::ConnectSlots()
|
||||
{
|
||||
auto* const host = Host::GetInstance();
|
||||
connect(host, &Host::JitCacheCleared, this, &JITWidget::OnJitCacheCleared);
|
||||
connect(host, &Host::JitCacheInvalidation, this, &JITWidget::OnJitCacheInvalidation);
|
||||
connect(host, &Host::UpdateDisasmDialog, this, &JITWidget::OnUpdateDisasmDialog);
|
||||
connect(host, &Host::PPCSymbolsChanged, this, &JITWidget::OnPPCSymbolsUpdated);
|
||||
connect(host, &Host::PPCBreakpointsChanged, this, &JITWidget::OnPPCBreakpointsChanged);
|
||||
|
@ -326,7 +326,7 @@ void JITWidget::ConnectSlots()
|
|||
void JITWidget::DisconnectSlots()
|
||||
{
|
||||
auto* const host = Host::GetInstance();
|
||||
disconnect(host, &Host::JitCacheCleared, this, &JITWidget::OnJitCacheCleared);
|
||||
disconnect(host, &Host::JitCacheInvalidation, this, &JITWidget::OnJitCacheInvalidation);
|
||||
disconnect(host, &Host::UpdateDisasmDialog, this, &JITWidget::OnUpdateDisasmDialog);
|
||||
disconnect(host, &Host::PPCSymbolsChanged, this, &JITWidget::OnPPCSymbolsUpdated);
|
||||
disconnect(host, &Host::PPCBreakpointsChanged, this, &JITWidget::OnPPCBreakpointsChanged);
|
||||
|
@ -340,7 +340,7 @@ void JITWidget::Show()
|
|||
{
|
||||
ConnectSlots();
|
||||
// Handle every slot that may have missed a signal while this widget was hidden.
|
||||
// OnJitCacheCleared() can be skipped.
|
||||
// OnJitCacheInvalidation() can be skipped.
|
||||
// OnUpdateDisasmDialog() can be skipped.
|
||||
// OnPPCSymbolsUpdated() can be skipped.
|
||||
// OnPPCBreakpointsChanged() can be skipped.
|
||||
|
@ -446,7 +446,7 @@ void JITWidget::OnStatusBarPressed()
|
|||
ShowFreeMemoryStatus();
|
||||
}
|
||||
|
||||
void JITWidget::OnJitCacheCleared()
|
||||
void JITWidget::OnJitCacheInvalidation()
|
||||
{
|
||||
if (Core::GetState(m_system) != Core::State::Paused)
|
||||
return;
|
||||
|
|
|
@ -102,7 +102,7 @@ private:
|
|||
void OnStatusBarPressed();
|
||||
|
||||
// Conditionally connected slots (external signals)
|
||||
void OnJitCacheCleared();
|
||||
void OnJitCacheInvalidation();
|
||||
void OnUpdateDisasmDialog();
|
||||
void OnPPCSymbolsUpdated();
|
||||
void OnPPCBreakpointsChanged();
|
||||
|
|
|
@ -112,7 +112,7 @@ void JitBlockTableModel::UpdateSymbols()
|
|||
void JitBlockTableModel::ConnectSlots()
|
||||
{
|
||||
auto* const host = Host::GetInstance();
|
||||
connect(host, &Host::JitCacheCleared, this, &JitBlockTableModel::OnJitCacheCleared);
|
||||
connect(host, &Host::JitCacheInvalidation, this, &JitBlockTableModel::OnJitCacheInvalidation);
|
||||
connect(host, &Host::JitProfileDataWiped, this, &JitBlockTableModel::OnJitProfileDataWiped);
|
||||
connect(host, &Host::UpdateDisasmDialog, this, &JitBlockTableModel::OnUpdateDisasmDialog);
|
||||
connect(host, &Host::PPCSymbolsChanged, this, &JitBlockTableModel::OnPPCSymbolsUpdated);
|
||||
|
@ -125,7 +125,7 @@ void JitBlockTableModel::ConnectSlots()
|
|||
void JitBlockTableModel::DisconnectSlots()
|
||||
{
|
||||
auto* const host = Host::GetInstance();
|
||||
disconnect(host, &Host::JitCacheCleared, this, &JitBlockTableModel::OnJitCacheCleared);
|
||||
disconnect(host, &Host::JitCacheInvalidation, this, &JitBlockTableModel::OnJitCacheInvalidation);
|
||||
disconnect(host, &Host::JitProfileDataWiped, this, &JitBlockTableModel::OnJitProfileDataWiped);
|
||||
disconnect(host, &Host::UpdateDisasmDialog, this, &JitBlockTableModel::OnUpdateDisasmDialog);
|
||||
disconnect(host, &Host::PPCSymbolsChanged, this, &JitBlockTableModel::OnPPCSymbolsUpdated);
|
||||
|
@ -169,7 +169,7 @@ void JitBlockTableModel::OnFilterSymbolTextChanged(const QString& string)
|
|||
m_filtering_by_symbols = !string.isEmpty();
|
||||
}
|
||||
|
||||
void JitBlockTableModel::OnJitCacheCleared()
|
||||
void JitBlockTableModel::OnJitCacheInvalidation()
|
||||
{
|
||||
Update(Core::GetState(m_system));
|
||||
}
|
||||
|
@ -187,7 +187,9 @@ void JitBlockTableModel::OnUpdateDisasmDialog()
|
|||
|
||||
void JitBlockTableModel::OnPPCSymbolsUpdated()
|
||||
{
|
||||
UpdateSymbols();
|
||||
// Previously, this was only a call to `UpdateSymbols`, but HLE patch engine code can
|
||||
// invalidate JIT blocks when specific symbols are loaded. What can be done about it?
|
||||
Update(Core::GetState(m_system));
|
||||
}
|
||||
|
||||
void JitBlockTableModel::OnPPCBreakpointsChanged()
|
||||
|
|
|
@ -106,7 +106,7 @@ private:
|
|||
void Hide();
|
||||
|
||||
// Conditionally connected slots (external signals)
|
||||
void OnJitCacheCleared();
|
||||
void OnJitCacheInvalidation();
|
||||
void OnJitProfileDataWiped();
|
||||
void OnUpdateDisasmDialog();
|
||||
void OnPPCSymbolsUpdated();
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
<ClCompile Include="QtUtils\ModalMessageBox.cpp" />
|
||||
<ClCompile Include="QtUtils\NonDefaultQPushButton.cpp" />
|
||||
<ClCompile Include="QtUtils\PartiallyClosableTabWidget.cpp" />
|
||||
<ClCompile Include="QtUtils\QtUtils.cpp" />
|
||||
<ClCompile Include="QtUtils\SetWindowDecorations.cpp" />
|
||||
<ClCompile Include="QtUtils\UTF8CodePointCountValidator.cpp" />
|
||||
<ClCompile Include="QtUtils\WindowActivationEventFilter.cpp" />
|
||||
|
@ -412,6 +413,7 @@
|
|||
<ClInclude Include="QtUtils\FromStdString.h" />
|
||||
<QtMoc Include="QtUtils\ParallelProgressDialog.h" />
|
||||
<QtMoc Include="QtUtils\PartiallyClosableTabWidget.h" />
|
||||
<ClInclude Include="QtUtils\QtUtils.h" />
|
||||
<ClInclude Include="QtUtils\SetWindowDecorations.h" />
|
||||
<QtMoc Include="QtUtils\UTF8CodePointCountValidator.h" />
|
||||
<QtMoc Include="QtUtils\WindowActivationEventFilter.h" />
|
||||
|
|
|
@ -256,9 +256,9 @@ void Host_UpdateDisasmDialog()
|
|||
QueueOnObject(QApplication::instance(), [] { emit Host::GetInstance()->UpdateDisasmDialog(); });
|
||||
}
|
||||
|
||||
void Host_JitCacheCleared()
|
||||
void Host_JitCacheInvalidation()
|
||||
{
|
||||
QueueOnObject(QApplication::instance(), [] { emit Host::GetInstance()->JitCacheCleared(); });
|
||||
QueueOnObject(QApplication::instance(), [] { emit Host::GetInstance()->JitCacheInvalidation(); });
|
||||
}
|
||||
|
||||
void Host_JitProfileDataWiped()
|
||||
|
|
|
@ -40,7 +40,7 @@ signals:
|
|||
void RequestStop();
|
||||
void RequestRenderSize(int w, int h);
|
||||
void UpdateDisasmDialog();
|
||||
void JitCacheCleared();
|
||||
void JitCacheInvalidation();
|
||||
void JitProfileDataWiped();
|
||||
void PPCSymbolsChanged();
|
||||
void PPCBreakpointsChanged();
|
||||
|
|
|
@ -257,7 +257,8 @@ int main(int argc, char* argv[])
|
|||
Settings::Instance().InitDefaultPalette();
|
||||
Settings::Instance().ApplyStyle();
|
||||
|
||||
MainWindow win{std::move(boot), static_cast<const char*>(options.get("movie"))};
|
||||
MainWindow win{Core::System::GetInstance(), std::move(boot),
|
||||
static_cast<const char*>(options.get("movie"))};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "Core/State.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/WiiUtils.h"
|
||||
|
||||
#include "DiscIO/DirectoryBlob.h"
|
||||
#include "DiscIO/NANDImporter.h"
|
||||
#include "DiscIO/RiivolutionPatcher.h"
|
||||
|
@ -80,7 +81,6 @@
|
|||
#include "DolphinQt/Config/LogConfigWidget.h"
|
||||
#include "DolphinQt/Config/LogWidget.h"
|
||||
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
||||
#include "DolphinQt/Config/PropertiesDialog.h"
|
||||
#include "DolphinQt/Config/SettingsWindow.h"
|
||||
#include "DolphinQt/Debugger/AssemblerWidget.h"
|
||||
#include "DolphinQt/Debugger/BreakpointWidget.h"
|
||||
|
@ -145,8 +145,6 @@
|
|||
#undef None
|
||||
#endif
|
||||
|
||||
#include <qprocess.h>
|
||||
|
||||
#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
|
||||
void MainWindow::OnSignal()
|
||||
{
|
||||
|
@ -219,9 +217,9 @@ static std::vector<std::string> StringListToStdVector(QStringList list)
|
|||
return result;
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
||||
MainWindow::MainWindow(Core::System& system, std::unique_ptr<BootParameters> boot_parameters,
|
||||
const std::string& movie_path)
|
||||
: QMainWindow(nullptr)
|
||||
: QMainWindow(nullptr), m_system(system)
|
||||
{
|
||||
setWindowTitle(QString::fromStdString(Common::GetScmRevStr()));
|
||||
setWindowIcon(Resources::GetAppIcon());
|
||||
|
@ -275,6 +273,8 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
|||
|
||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||
AchievementManager::GetInstance().Init();
|
||||
if (AchievementManager::GetInstance().IsHardcoreModeActive())
|
||||
Settings::Instance().SetDebugModeEnabled(false);
|
||||
#endif // USE_RETRO_ACHIEVEMENTS
|
||||
|
||||
#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
|
||||
|
@ -292,7 +292,7 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
|||
if (!movie_path.empty())
|
||||
{
|
||||
std::optional<std::string> savestate_path;
|
||||
if (Core::System::GetInstance().GetMovie().PlayInput(movie_path, &savestate_path))
|
||||
if (m_system.GetMovie().PlayInput(movie_path, &savestate_path))
|
||||
{
|
||||
m_pending_boot->boot_session_data.SetSavestateData(std::move(savestate_path),
|
||||
DeleteSavestateAfterBoot::No);
|
||||
|
@ -465,17 +465,17 @@ void MainWindow::CreateComponents()
|
|||
m_wii_tas_input_windows[i] = new WiiTASInputWindow(nullptr, i);
|
||||
}
|
||||
|
||||
m_jit_widget = new JITWidget(Core::System::GetInstance(), this);
|
||||
m_jit_widget = new JITWidget(m_system, this);
|
||||
m_log_widget = new LogWidget(this);
|
||||
m_log_config_widget = new LogConfigWidget(this);
|
||||
m_memory_widget = new MemoryWidget(Core::System::GetInstance(), this);
|
||||
m_memory_widget = new MemoryWidget(m_system, this);
|
||||
m_network_widget = new NetworkWidget(this);
|
||||
m_register_widget = new RegisterWidget(this);
|
||||
m_thread_widget = new ThreadWidget(this);
|
||||
m_watch_widget = new WatchWidget(this);
|
||||
m_breakpoint_widget = new BreakpointWidget(this);
|
||||
m_code_widget = new CodeWidget(this);
|
||||
m_cheats_manager = new CheatsManager(Core::System::GetInstance(), this);
|
||||
m_cheats_manager = new CheatsManager(m_system, this);
|
||||
m_assembler_widget = new AssemblerWidget(this);
|
||||
|
||||
const auto request_watch = [this](QString name, u32 addr) {
|
||||
|
@ -512,7 +512,7 @@ void MainWindow::CreateComponents()
|
|||
connect(m_memory_widget, &MemoryWidget::RequestWatch, request_watch);
|
||||
|
||||
connect(m_breakpoint_widget, &BreakpointWidget::ShowCode, [this](u32 address) {
|
||||
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
|
||||
if (Core::GetState(m_system) == Core::State::Paused)
|
||||
m_code_widget->SetAddress(address, CodeViewWidget::SetAddressUpdate::WithDetailedUpdate);
|
||||
});
|
||||
connect(m_breakpoint_widget, &BreakpointWidget::ShowMemory, m_memory_widget,
|
||||
|
@ -567,6 +567,8 @@ void MainWindow::ConnectMenuBar()
|
|||
connect(m_menu_bar, &MenuBar::ImportNANDBackup, this, &MainWindow::OnImportNANDBackup);
|
||||
connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate);
|
||||
connect(m_menu_bar, &MenuBar::BootWiiSystemMenu, this, &MainWindow::BootWiiSystemMenu);
|
||||
connect(m_menu_bar, &MenuBar::StartNetPlay, this, &MainWindow::ShowNetPlaySetupDialog);
|
||||
connect(m_menu_bar, &MenuBar::BrowseNetPlay, this, &MainWindow::ShowNetPlayBrowser);
|
||||
connect(m_menu_bar, &MenuBar::ShowFIFOPlayer, this, &MainWindow::ShowFIFOPlayer);
|
||||
connect(m_menu_bar, &MenuBar::ShowSkylanderPortal, this, &MainWindow::ShowSkylanderPortal);
|
||||
connect(m_menu_bar, &MenuBar::ShowInfinityBase, this, &MainWindow::ShowInfinityBase);
|
||||
|
@ -651,7 +653,7 @@ void MainWindow::ConnectHotkeys()
|
|||
connect(m_hotkey_scheduler, &HotkeyScheduler::ConnectWiiRemote, this,
|
||||
&MainWindow::OnConnectWiiRemote);
|
||||
connect(m_hotkey_scheduler, &HotkeyScheduler::ToggleReadOnlyMode, [this] {
|
||||
auto& movie = Core::System::GetInstance().GetMovie();
|
||||
auto& movie = m_system.GetMovie();
|
||||
bool read_only = !movie.IsReadOnly();
|
||||
movie.SetReadOnly(read_only);
|
||||
emit ReadOnlyModeChanged(read_only);
|
||||
|
@ -696,8 +698,6 @@ void MainWindow::ConnectToolBar()
|
|||
connect(m_tool_bar, &ToolBar::ControllersPressed, this, &MainWindow::ShowControllersWindow);
|
||||
connect(m_tool_bar, &ToolBar::GraphicsPressed, this, &MainWindow::ShowGraphicsWindow);
|
||||
|
||||
connect(m_tool_bar, &ToolBar::StartNetPlayPressed, this, &MainWindow::ShowNetPlaySetupDialog);
|
||||
connect(m_tool_bar, &ToolBar::ViewGeckoCodes, this, &MainWindow::ShowGeckoCodes);
|
||||
connect(m_tool_bar, &ToolBar::StepPressed, m_code_widget, &CodeWidget::Step);
|
||||
connect(m_tool_bar, &ToolBar::StepOverPressed, m_code_widget, &CodeWidget::StepOver);
|
||||
connect(m_tool_bar, &ToolBar::StepOutPressed, m_code_widget, &CodeWidget::StepOut);
|
||||
|
@ -808,14 +808,12 @@ void MainWindow::ChangeDisc()
|
|||
if (paths.empty())
|
||||
return;
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetDVDInterface().ChangeDisc(Core::CPUThreadGuard{system}, paths);
|
||||
m_system.GetDVDInterface().ChangeDisc(Core::CPUThreadGuard{m_system}, paths);
|
||||
}
|
||||
|
||||
void MainWindow::EjectDisc()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetDVDInterface().EjectDisc(Core::CPUThreadGuard{system}, DVD::EjectCause::User);
|
||||
m_system.GetDVDInterface().EjectDisc(Core::CPUThreadGuard{m_system}, DVD::EjectCause::User);
|
||||
}
|
||||
|
||||
void MainWindow::OpenUserFolder()
|
||||
|
@ -840,9 +838,9 @@ void MainWindow::Play(const std::optional<std::string>& savestate_path)
|
|||
// Otherwise, play the default game.
|
||||
// Otherwise, play the last played game, if there is one.
|
||||
// Otherwise, prompt for a new game.
|
||||
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
|
||||
if (Core::GetState(m_system) == Core::State::Paused)
|
||||
{
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Running);
|
||||
Core::SetState(m_system, Core::State::Running);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -870,12 +868,12 @@ void MainWindow::Play(const std::optional<std::string>& savestate_path)
|
|||
|
||||
void MainWindow::Pause()
|
||||
{
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Paused);
|
||||
Core::SetState(m_system, Core::State::Paused);
|
||||
}
|
||||
|
||||
void MainWindow::TogglePause()
|
||||
{
|
||||
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
|
||||
if (Core::GetState(m_system) == Core::State::Paused)
|
||||
{
|
||||
Play();
|
||||
}
|
||||
|
@ -918,7 +916,7 @@ void MainWindow::OnStopComplete()
|
|||
|
||||
bool MainWindow::RequestStop()
|
||||
{
|
||||
if (Core::IsUninitialized(Core::System::GetInstance()))
|
||||
if (Core::IsUninitialized(m_system))
|
||||
{
|
||||
Core::QueueHostJob([this](Core::System&) { OnStopComplete(); }, true);
|
||||
return true;
|
||||
|
@ -944,13 +942,13 @@ bool MainWindow::RequestStop()
|
|||
|
||||
Common::ScopeGuard confirm_lock([this] { m_stop_confirm_showing = false; });
|
||||
|
||||
const Core::State state = Core::GetState(Core::System::GetInstance());
|
||||
const Core::State state = Core::GetState(m_system);
|
||||
|
||||
// Only pause the game, if NetPlay is not running
|
||||
bool pause = !Settings::Instance().GetNetPlayClient();
|
||||
|
||||
if (pause)
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Paused);
|
||||
Core::SetState(m_system, Core::State::Paused);
|
||||
|
||||
if (rendered_widget_was_active)
|
||||
{
|
||||
|
@ -980,7 +978,7 @@ bool MainWindow::RequestStop()
|
|||
m_render_widget->SetWaitingForMessageBox(false);
|
||||
|
||||
if (pause)
|
||||
Core::SetState(Core::System::GetInstance(), state);
|
||||
Core::SetState(m_system, state);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1001,112 +999,8 @@ bool MainWindow::RequestStop()
|
|||
|
||||
// Unpause because gracefully shutting down needs the game to actually request a shutdown.
|
||||
// TODO: Do not unpause in debug mode to allow debugging until the complete shutdown.
|
||||
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Running);
|
||||
|
||||
// Tell NetPlay about the power event
|
||||
if (NetPlay::IsNetPlayRunning())
|
||||
NetPlay::SendPowerButtonEvent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ForceStop();
|
||||
#ifdef Q_OS_WIN
|
||||
// Allow windows to idle or turn off display again
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::RequestStopNetplay()
|
||||
{
|
||||
if (!Core::IsRunning(Core::System::GetInstance()))
|
||||
{
|
||||
Core::QueueHostJob([this](Core::System&) { OnStopComplete(); }, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool rendered_widget_was_active =
|
||||
m_render_widget->isActiveWindow() && !m_render_widget->isFullScreen();
|
||||
QWidget* confirm_parent = (!m_rendering_to_main && rendered_widget_was_active) ?
|
||||
m_render_widget :
|
||||
static_cast<QWidget*>(this);
|
||||
const bool was_cursor_locked = m_render_widget->IsCursorLocked();
|
||||
|
||||
if (!m_render_widget->isFullScreen())
|
||||
m_render_widget_geometry = m_render_widget->saveGeometry();
|
||||
else
|
||||
FullScreen();
|
||||
|
||||
if (Config::Get(Config::MAIN_CONFIRM_ON_STOP))
|
||||
{
|
||||
if (std::exchange(m_stop_confirm_showing, true))
|
||||
return true;
|
||||
|
||||
Common::ScopeGuard confirm_lock([this] { m_stop_confirm_showing = false; });
|
||||
|
||||
const Core::State state = Core::GetState(Core::System::GetInstance());
|
||||
|
||||
// Only pause the game, if NetPlay is not running
|
||||
bool pause = !Settings::Instance().GetNetPlayClient();
|
||||
|
||||
if (pause)
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Paused);
|
||||
|
||||
if (rendered_widget_was_active)
|
||||
{
|
||||
// We have to do this before creating the message box, otherwise we might receive the window
|
||||
// activation event before we know we need to lock the cursor again.
|
||||
m_render_widget->SetCursorLockedOnNextActivation(was_cursor_locked);
|
||||
}
|
||||
|
||||
// This is to avoid any "race conditions" between the "Window Activate" message and the
|
||||
// message box returning, which could break cursor locking depending on the order
|
||||
m_render_widget->SetWaitingForMessageBox(true);
|
||||
auto confirm = ModalMessageBox::question(
|
||||
confirm_parent, tr("Quitter!"),
|
||||
m_stop_requested ? tr("A user closed down their game from the netplay lobby. "
|
||||
"This means the Netplay session has ended! "
|
||||
"Do you want to stop the current emulation?") :
|
||||
tr("A user closed down their game from the netplay lobby. "
|
||||
"This means the Netplay session has ended! "
|
||||
"Do you want to stop the current emulation?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton, Qt::ApplicationModal);
|
||||
|
||||
// If a user confirmed stopping the emulation, we do not capture the cursor again,
|
||||
// even if the render widget will stay alive for a while.
|
||||
// If a used rejected stopping the emulation, we instead capture the cursor again,
|
||||
// and let them continue playing as if nothing had happened
|
||||
// (assuming cursor locking is on).
|
||||
if (confirm != QMessageBox::Yes)
|
||||
{
|
||||
m_render_widget->SetWaitingForMessageBox(false);
|
||||
|
||||
if (pause)
|
||||
Core::SetState(Core::System::GetInstance(), state);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_render_widget->SetCursorLockedOnNextActivation(false);
|
||||
// This needs to be after SetCursorLockedOnNextActivation(false) as it depends on it
|
||||
m_render_widget->SetWaitingForMessageBox(false);
|
||||
}
|
||||
}
|
||||
|
||||
OnStopRecording();
|
||||
// TODO: Add Debugger shutdown
|
||||
|
||||
if (!m_stop_requested && UICommon::TriggerSTMPowerEvent())
|
||||
{
|
||||
m_stop_requested = true;
|
||||
|
||||
// Unpause because gracefully shutting down needs the game to actually request a shutdown.
|
||||
// TODO: Do not unpause in debug mode to allow debugging until the complete shutdown.
|
||||
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
|
||||
Core::SetState(Core::System::GetInstance(), Core::State::Running);
|
||||
if (Core::GetState(m_system) == Core::State::Paused)
|
||||
Core::SetState(m_system, Core::State::Running);
|
||||
|
||||
// Tell NetPlay about the power event
|
||||
if (NetPlay::IsNetPlayRunning())
|
||||
|
@ -1125,21 +1019,20 @@ bool MainWindow::RequestStopNetplay()
|
|||
|
||||
void MainWindow::ForceStop()
|
||||
{
|
||||
Core::Stop(Core::System::GetInstance());
|
||||
Core::Stop(m_system);
|
||||
}
|
||||
|
||||
void MainWindow::Reset()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& movie = system.GetMovie();
|
||||
auto& movie = m_system.GetMovie();
|
||||
if (movie.IsRecordingInput())
|
||||
movie.SetReset(true);
|
||||
system.GetProcessorInterface().ResetButton_Tap_FromUser();
|
||||
m_system.GetProcessorInterface().ResetButton_Tap();
|
||||
}
|
||||
|
||||
void MainWindow::FrameAdvance()
|
||||
{
|
||||
Core::DoFrameStep(Core::System::GetInstance());
|
||||
Core::DoFrameStep(m_system);
|
||||
}
|
||||
|
||||
void MainWindow::FullScreen()
|
||||
|
@ -1230,7 +1123,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
|
|||
}
|
||||
|
||||
// If we're running, only start a new game once we've stopped the last.
|
||||
if (!Core::IsUninitialized(Core::System::GetInstance()))
|
||||
if (!Core::IsUninitialized(m_system))
|
||||
{
|
||||
if (!RequestStop())
|
||||
return;
|
||||
|
@ -1244,7 +1137,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
|
|||
ShowRenderWidget();
|
||||
|
||||
// Boot up, show an error if it fails to load the game.
|
||||
if (!BootManager::BootCore(Core::System::GetInstance(), std::move(parameters),
|
||||
if (!BootManager::BootCore(m_system, std::move(parameters),
|
||||
::GetWindowSystemInfo(m_render_widget->windowHandle())))
|
||||
{
|
||||
ModalMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
|
||||
|
@ -1400,7 +1293,7 @@ void MainWindow::ShowSettingsWindow()
|
|||
InstallHotkeyFilter(m_settings_window);
|
||||
}
|
||||
|
||||
//SetQWidgetWindowDecorations(m_settings_window);
|
||||
SetQWidgetWindowDecorations(m_settings_window);
|
||||
m_settings_window->show();
|
||||
m_settings_window->raise();
|
||||
m_settings_window->activateWindow();
|
||||
|
@ -1483,8 +1376,7 @@ void MainWindow::ShowFIFOPlayer()
|
|||
{
|
||||
if (!m_fifo_window)
|
||||
{
|
||||
m_fifo_window = new FIFOPlayerWindow(Core::System::GetInstance().GetFifoPlayer(),
|
||||
Core::System::GetInstance().GetFifoRecorder());
|
||||
m_fifo_window = new FIFOPlayerWindow(m_system.GetFifoPlayer(), m_system.GetFifoRecorder());
|
||||
connect(m_fifo_window, &FIFOPlayerWindow::LoadFIFORequested, this,
|
||||
[this](const QString& path) { StartGame(path, ScanForSecondDisc::No); });
|
||||
}
|
||||
|
@ -1530,7 +1422,7 @@ void MainWindow::StateLoad()
|
|||
this, tr("Select a File"), dialog_path, tr("All Save States (*.sav *.s##);; All Files (*)"));
|
||||
Config::SetBase(Config::MAIN_CURRENT_STATE_PATH, QFileInfo(path).dir().path().toStdString());
|
||||
if (!path.isEmpty())
|
||||
State::LoadAs(Core::System::GetInstance(), path.toStdString());
|
||||
State::LoadAs(m_system, path.toStdString());
|
||||
}
|
||||
|
||||
void MainWindow::StateSave()
|
||||
|
@ -1542,47 +1434,47 @@ void MainWindow::StateSave()
|
|||
this, tr("Select a File"), dialog_path, tr("All Save States (*.sav *.s##);; All Files (*)"));
|
||||
Config::SetBase(Config::MAIN_CURRENT_STATE_PATH, QFileInfo(path).dir().path().toStdString());
|
||||
if (!path.isEmpty())
|
||||
State::SaveAs(Core::System::GetInstance(), path.toStdString());
|
||||
State::SaveAs(m_system, path.toStdString());
|
||||
}
|
||||
|
||||
void MainWindow::StateLoadSlot()
|
||||
{
|
||||
State::Load(Core::System::GetInstance(), m_state_slot);
|
||||
State::Load(m_system, m_state_slot);
|
||||
}
|
||||
|
||||
void MainWindow::StateSaveSlot()
|
||||
{
|
||||
State::Save(Core::System::GetInstance(), m_state_slot);
|
||||
State::Save(m_system, m_state_slot);
|
||||
}
|
||||
|
||||
void MainWindow::StateLoadSlotAt(int slot)
|
||||
{
|
||||
State::Load(Core::System::GetInstance(), slot);
|
||||
State::Load(m_system, slot);
|
||||
}
|
||||
|
||||
void MainWindow::StateLoadLastSavedAt(int slot)
|
||||
{
|
||||
State::LoadLastSaved(Core::System::GetInstance(), slot);
|
||||
State::LoadLastSaved(m_system, slot);
|
||||
}
|
||||
|
||||
void MainWindow::StateSaveSlotAt(int slot)
|
||||
{
|
||||
State::Save(Core::System::GetInstance(), slot);
|
||||
State::Save(m_system, slot);
|
||||
}
|
||||
|
||||
void MainWindow::StateLoadUndo()
|
||||
{
|
||||
State::UndoLoadState(Core::System::GetInstance());
|
||||
State::UndoLoadState(m_system);
|
||||
}
|
||||
|
||||
void MainWindow::StateSaveUndo()
|
||||
{
|
||||
State::UndoSaveState(Core::System::GetInstance());
|
||||
State::UndoSaveState(m_system);
|
||||
}
|
||||
|
||||
void MainWindow::StateSaveOldest()
|
||||
{
|
||||
State::SaveFirstSaved(Core::System::GetInstance());
|
||||
State::SaveFirstSaved(m_system);
|
||||
}
|
||||
|
||||
void MainWindow::SetStateSlot(int slot)
|
||||
|
@ -1636,11 +1528,10 @@ void MainWindow::NetPlayInit()
|
|||
m_netplay_discord = new DiscordHandler(this);
|
||||
#endif
|
||||
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::RequestStopNetplay);
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::ForceStop);
|
||||
connect(m_netplay_dialog, &NetPlayDialog::rejected, this, &MainWindow::NetPlayQuit);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Join, this, &MainWindow::NetPlayJoin);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Host, this, &MainWindow::NetPlayHost);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::JoinBrowser, this, &MainWindow::NetPlayJoin);
|
||||
#ifdef USE_DISCORD_PRESENCE
|
||||
connect(m_netplay_discord, &DiscordHandler::Join, this, &MainWindow::NetPlayJoin);
|
||||
|
||||
|
@ -1655,7 +1546,7 @@ void MainWindow::NetPlayInit()
|
|||
|
||||
bool MainWindow::NetPlayJoin()
|
||||
{
|
||||
if (!Core::IsUninitialized(Core::System::GetInstance()))
|
||||
if (!Core::IsUninitialized(m_system))
|
||||
{
|
||||
ModalMessageBox::critical(nullptr, tr("Error"),
|
||||
tr("Can't start a NetPlay Session while a game is still running!"));
|
||||
|
@ -1722,7 +1613,7 @@ bool MainWindow::NetPlayJoin()
|
|||
|
||||
bool MainWindow::NetPlayHost(const UICommon::GameFile& game)
|
||||
{
|
||||
if (!Core::IsUninitialized(Core::System::GetInstance()))
|
||||
if (!Core::IsUninitialized(m_system))
|
||||
{
|
||||
ModalMessageBox::critical(nullptr, tr("Error"),
|
||||
tr("Can't start a NetPlay Session while a game is still running!"));
|
||||
|
@ -1784,7 +1675,7 @@ void MainWindow::NetPlayQuit()
|
|||
void MainWindow::UpdateScreenSaverInhibition()
|
||||
{
|
||||
const bool inhibit = Config::Get(Config::MAIN_DISABLE_SCREENSAVER) &&
|
||||
(Core::GetState(Core::System::GetInstance()) == Core::State::Running);
|
||||
(Core::GetState(m_system) == Core::State::Running);
|
||||
|
||||
if (inhibit == m_is_screensaver_inhibited)
|
||||
return;
|
||||
|
@ -1945,7 +1836,7 @@ void MainWindow::OnPlayRecording()
|
|||
if (dtm_file.isEmpty())
|
||||
return;
|
||||
|
||||
auto& movie = Core::System::GetInstance().GetMovie();
|
||||
auto& movie = m_system.GetMovie();
|
||||
if (!movie.IsReadOnly())
|
||||
{
|
||||
// let's make the read-only flag consistent at the start of a movie.
|
||||
|
@ -1964,10 +1855,9 @@ void MainWindow::OnPlayRecording()
|
|||
|
||||
void MainWindow::OnStartRecording()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& movie = system.GetMovie();
|
||||
if (Core::GetState(system) == Core::State::Starting ||
|
||||
Core::GetState(system) == Core::State::Stopping || movie.IsRecordingInput() ||
|
||||
auto& movie = m_system.GetMovie();
|
||||
if (Core::GetState(m_system) == Core::State::Starting ||
|
||||
Core::GetState(m_system) == Core::State::Stopping || movie.IsRecordingInput() ||
|
||||
movie.IsPlayingInput())
|
||||
{
|
||||
return;
|
||||
|
@ -1999,14 +1889,14 @@ void MainWindow::OnStartRecording()
|
|||
{
|
||||
emit RecordingStatusChanged(true);
|
||||
|
||||
if (Core::IsUninitialized(system))
|
||||
if (Core::IsUninitialized(m_system))
|
||||
Play();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnStopRecording()
|
||||
{
|
||||
auto& movie = Core::System::GetInstance().GetMovie();
|
||||
auto& movie = m_system.GetMovie();
|
||||
if (movie.IsRecordingInput())
|
||||
OnExportRecording();
|
||||
if (movie.IsMovieActive())
|
||||
|
@ -2016,13 +1906,12 @@ void MainWindow::OnStopRecording()
|
|||
|
||||
void MainWindow::OnExportRecording()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
const Core::CPUThreadGuard guard(system);
|
||||
const Core::CPUThreadGuard guard(m_system);
|
||||
|
||||
QString dtm_file = DolphinFileDialog::getSaveFileName(
|
||||
this, tr("Save Recording File As"), QString(), tr("Dolphin TAS Movies (*.dtm)"));
|
||||
if (!dtm_file.isEmpty())
|
||||
system.GetMovie().SaveRecording(dtm_file.toStdString());
|
||||
m_system.GetMovie().SaveRecording(dtm_file.toStdString());
|
||||
}
|
||||
|
||||
void MainWindow::OnActivateChat()
|
||||
|
@ -2060,11 +1949,10 @@ void MainWindow::ShowTASInput()
|
|||
}
|
||||
}
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
for (int i = 0; i < num_wii_controllers; i++)
|
||||
{
|
||||
if (Config::Get(Config::GetInfoForWiimoteSource(i)) == WiimoteSource::Emulated &&
|
||||
(!Core::IsRunning(system) || system.IsWii()))
|
||||
(!Core::IsRunning(m_system) || m_system.IsWii()))
|
||||
{
|
||||
SetQWidgetWindowDecorations(m_wii_tas_input_windows[i]);
|
||||
m_wii_tas_input_windows[i]->show();
|
||||
|
@ -2076,7 +1964,7 @@ void MainWindow::ShowTASInput()
|
|||
|
||||
void MainWindow::OnConnectWiiRemote(int id)
|
||||
{
|
||||
const Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
const Core::CPUThreadGuard guard(m_system);
|
||||
if (const auto bt = WiiUtils::GetBluetoothEmuDevice())
|
||||
{
|
||||
const auto wm = bt->AccessWiimoteByIndex(id);
|
||||
|
@ -2157,16 +2045,3 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
|
|||
AddRiivolutionPatches(boot_params.get(), std::move(w.GetPatches()));
|
||||
StartGame(std::move(boot_params));
|
||||
}
|
||||
|
||||
void MainWindow::ShowGeckoCodes()
|
||||
{
|
||||
if (!m_gecko_dialog)
|
||||
{
|
||||
m_gecko_dialog = new GeckoDialog(this);
|
||||
InstallHotkeyFilter(m_gecko_dialog);
|
||||
}
|
||||
|
||||
m_gecko_dialog->show();
|
||||
m_gecko_dialog->raise();
|
||||
m_gecko_dialog->activateWindow();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ class WatchWidget;
|
|||
class WiiTASInputWindow;
|
||||
struct WindowSystemInfo;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class Region;
|
||||
|
@ -75,7 +80,7 @@ class MainWindow final : public QMainWindow
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
||||
explicit MainWindow(Core::System& system, std::unique_ptr<BootParameters> boot_parameters,
|
||||
const std::string& movie_path);
|
||||
~MainWindow();
|
||||
|
||||
|
@ -216,6 +221,8 @@ private:
|
|||
QSize sizeHint() const override;
|
||||
void ShowGeckoCodes();
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
#ifdef HAVE_XRANDR
|
||||
std::unique_ptr<X11Utils::XRRConfiguration> m_xrr_config;
|
||||
#endif
|
||||
|
|
22
Source/Core/DolphinQt/QtUtils/QtUtils.cpp
Normal file
22
Source/Core/DolphinQt/QtUtils/QtUtils.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2024 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "DolphinQt/QtUtils/QtUtils.h"
|
||||
|
||||
#include <QDateTimeEdit>
|
||||
|
||||
namespace QtUtils
|
||||
{
|
||||
|
||||
void ShowFourDigitYear(QDateTimeEdit* widget)
|
||||
{
|
||||
if (!widget->displayFormat().contains(QStringLiteral("yyyy")))
|
||||
{
|
||||
// Always show the full year, no matter what the locale specifies. Otherwise, two-digit years
|
||||
// will always be interpreted as in the 21st century.
|
||||
widget->setDisplayFormat(
|
||||
widget->displayFormat().replace(QStringLiteral("yy"), QStringLiteral("yyyy")));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QtUtils
|
13
Source/Core/DolphinQt/QtUtils/QtUtils.h
Normal file
13
Source/Core/DolphinQt/QtUtils/QtUtils.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2024 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
class QDateTimeEdit;
|
||||
|
||||
namespace QtUtils
|
||||
{
|
||||
|
||||
void ShowFourDigitYear(QDateTimeEdit* widget);
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
#include "Core/System.h"
|
||||
|
||||
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
|
||||
#include "DolphinQt/QtUtils/QtUtils.h"
|
||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
|
@ -168,13 +169,7 @@ void AdvancedPane::CreateLayout()
|
|||
m_custom_rtc_datetime->setDisplayFormat(m_custom_rtc_datetime->displayFormat().replace(
|
||||
QStringLiteral("mm"), QStringLiteral("mm:ss")));
|
||||
|
||||
if (!m_custom_rtc_datetime->displayFormat().contains(QStringLiteral("yyyy")))
|
||||
{
|
||||
// Always show the full year, no matter what the locale specifies. Otherwise, two-digit years
|
||||
// will always be interpreted as in the 21st century.
|
||||
m_custom_rtc_datetime->setDisplayFormat(m_custom_rtc_datetime->displayFormat().replace(
|
||||
QStringLiteral("yy"), QStringLiteral("yyyy")));
|
||||
}
|
||||
QtUtils::ShowFourDigitYear(m_custom_rtc_datetime);
|
||||
m_custom_rtc_datetime->setDateTimeRange(QDateTime({2000, 1, 1}, {0, 0, 0}, Qt::UTC),
|
||||
QDateTime({2099, 12, 31}, {23, 59, 59}, Qt::UTC));
|
||||
m_custom_rtc_datetime->setTimeSpec(Qt::UTC);
|
||||
|
|
|
@ -163,7 +163,7 @@ void AudioPane::CreateWidgets()
|
|||
auto* misc_layout = new QGridLayout;
|
||||
misc_box->setLayout(misc_layout);
|
||||
|
||||
m_speed_up_mute_enable = new QCheckBox(tr("Mute When Disabling Speed Limit."));
|
||||
m_speed_up_mute_enable = new QCheckBox(tr("Mute When Disabling Speed Limit"));
|
||||
m_speed_up_mute_enable->setToolTip(
|
||||
tr("Mutes the audio when overriding the emulation speed limit (default hotkey: Tab)."));
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Core/IOS/USB/Emulated/Skylanders/Skylander.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#include "DolphinQt/QtUtils/QtUtils.h"
|
||||
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
|
||||
|
||||
SkylanderModifyDialog::SkylanderModifyDialog(QWidget* parent, u8 slot)
|
||||
|
@ -168,8 +169,9 @@ void SkylanderModifyDialog::PopulateSkylanderOptions(QVBoxLayout* layout)
|
|||
edit_nick->setValidator(
|
||||
new QRegularExpressionValidator(QRegularExpression(QStringLiteral("^\\p{L}{0,15}$")), this));
|
||||
edit_playtime->setValidator(new QIntValidator(0, INT_MAX, this));
|
||||
edit_last_reset->setDisplayFormat(QStringLiteral("dd/MM/yyyy hh:mm"));
|
||||
edit_last_placed->setDisplayFormat(QStringLiteral("dd/MM/yyyy hh:mm"));
|
||||
|
||||
QtUtils::ShowFourDigitYear(edit_last_reset);
|
||||
QtUtils::ShowFourDigitYear(edit_last_placed);
|
||||
|
||||
edit_toy_code->setToolTip(tr("The toy code for this figure. Only available for real figures."));
|
||||
edit_money->setToolTip(tr("The amount of money this Skylander has. Between 0 and 65000"));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue