Compare commits
20 Commits
v0.0.4-rc2
...
v0.0.4-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08f3639c80 | ||
|
|
e13c7ef3f8 | ||
|
|
89dd133a2f | ||
|
|
86e9c32800 | ||
|
|
f1cf30bc2a | ||
|
|
5af5214451 | ||
|
|
312c1cc0f6 | ||
|
|
576c4e5f77 | ||
|
|
84cf3e8c84 | ||
|
|
45a2008aa6 | ||
|
|
8f6e0aa2cb | ||
|
|
ca0bc65531 | ||
|
|
a1930d1063 | ||
|
|
48843306e2 | ||
|
|
159482a7a9 | ||
|
|
0510f0bdbc | ||
|
|
569dbfe8c0 | ||
|
|
8412e64bb0 | ||
|
|
1c4dae066b | ||
|
|
9406438d51 |
@@ -13,6 +13,8 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set(PLATFORM_OPENBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
|
||||
set(PLATFORM_NETBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "DragonFly")
|
||||
set(PLATFORM_DRAGONFLYBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Haiku")
|
||||
set(PLATFORM_HAIKU ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
@@ -189,9 +191,9 @@ if (CXX_CLANG_CL)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc> # thanks microsoft
|
||||
)
|
||||
|
||||
# REQUIRED CPU features IN Windows-amd64
|
||||
if (ARCHITECTURE_x86_64)
|
||||
add_compile_options(
|
||||
# Required CPU features for amd64
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-msse4.1>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>
|
||||
)
|
||||
@@ -209,9 +211,8 @@ if (MSVC AND NOT CXX_CLANG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-")
|
||||
endif()
|
||||
|
||||
if (PLATFORM_FREEBSD)
|
||||
if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib")
|
||||
|
||||
endif()
|
||||
|
||||
# Set bundled sdl2/qt as dependent options.
|
||||
@@ -585,7 +586,7 @@ else()
|
||||
find_package(zstd 1.5 REQUIRED MODULE)
|
||||
|
||||
# wow
|
||||
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber)
|
||||
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber filesystem)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR ANDROID)
|
||||
find_package(gamemode 1.7 MODULE)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"hash": "4fb7f6fde92762305aad8754d7643cd918dd1f3f67e104e9ab385b18c73178d72a17321354eb203b790b6702f2cf6d725a5d6e2dfbc63b1e35f9eb59fb42ece9",
|
||||
"git_version": "1.89.0",
|
||||
"version": "1.57",
|
||||
"find_args": "CONFIG",
|
||||
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
|
||||
"patches": [
|
||||
"0001-clang-cl.patch",
|
||||
"0002-use-marmasm.patch",
|
||||
|
||||
0
dist/dev.eden_emu.eden.desktop
vendored
Normal file → Executable file
107
dist/dev.eden_emu.eden.svg
vendored
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.2 KiB |
BIN
dist/eden.icns
vendored
BIN
dist/eden.ico
vendored
|
Before Width: | Height: | Size: 403 KiB After Width: | Height: | Size: 315 KiB |
83
dist/eden_named.svg
vendored
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 37 KiB |
BIN
dist/qt_themes/default/icons/256x256/eden.png
vendored
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 17 KiB |
BIN
dist/qt_themes/default/icons/256x256/eden_named.png
vendored
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 29 KiB |
25
dist/qt_themes/qdarkstyle/style.qss
vendored
@@ -821,31 +821,6 @@ QTabBar QToolButton::left-arrow:disabled {
|
||||
image: url(:/qss_icons/rc/left_arrow_disabled.png);
|
||||
}
|
||||
|
||||
QDockWidget {
|
||||
background: #31363b;
|
||||
border: 1px solid #403F3F;
|
||||
titlebar-close-icon: url(:/qss_icons/rc/close.png);
|
||||
titlebar-normal-icon: url(:/qss_icons/rc/undock.png);
|
||||
}
|
||||
|
||||
QDockWidget::close-button,
|
||||
QDockWidget::float-button {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QDockWidget::close-button:hover,
|
||||
QDockWidget::float-button:hover {
|
||||
background: rgba(255, 255, 255, 10);
|
||||
}
|
||||
|
||||
QDockWidget::close-button:pressed,
|
||||
QDockWidget::float-button:pressed {
|
||||
padding: 1px -1px -1px 1px;
|
||||
background: rgba(255, 255, 255, 10);
|
||||
}
|
||||
|
||||
QTreeView,
|
||||
QListView {
|
||||
border: 1px solid #54575B;
|
||||
|
||||
@@ -1685,54 +1685,6 @@ QTabBar QToolButton::right-arrow:disabled {
|
||||
image: url(":/qss_icons/rc/arrow_right_disabled.png");
|
||||
}
|
||||
|
||||
/* QDockWiget -------------------------------------------------------------
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QDockWidget {
|
||||
outline: 1px solid #32414B;
|
||||
background-color: #19232D;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
titlebar-close-icon: url(":/qss_icons/rc/window_close.png");
|
||||
titlebar-normal-icon: url(":/qss_icons/rc/window_undock.png");
|
||||
}
|
||||
|
||||
QDockWidget::title {
|
||||
/* Better size for title bar */
|
||||
padding: 6px;
|
||||
spacing: 4px;
|
||||
border: none;
|
||||
background-color: #32414B;
|
||||
}
|
||||
|
||||
QDockWidget::close-button {
|
||||
background-color: #32414B;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
QDockWidget::close-button:hover {
|
||||
image: url(":/qss_icons/rc/window_close_focus.png");
|
||||
}
|
||||
|
||||
QDockWidget::close-button:pressed {
|
||||
image: url(":/qss_icons/rc/window_close_pressed.png");
|
||||
}
|
||||
|
||||
QDockWidget::float-button {
|
||||
background-color: #32414B;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
QDockWidget::float-button:hover {
|
||||
image: url(":/qss_icons/rc/window_undock_focus.png");
|
||||
}
|
||||
|
||||
QDockWidget::float-button:pressed {
|
||||
image: url(":/qss_icons/rc/window_undock_pressed.png");
|
||||
}
|
||||
|
||||
/* QTreeView QListView QTableView -----------------------------------------
|
||||
|
||||
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview
|
||||
|
||||
BIN
dist/yuzu.bmp
vendored
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
BIN
dist/yuzu.icns
vendored
@@ -30,6 +30,13 @@ macOS is largely untested. Expect crashes, significant Vulkan issues, and other
|
||||
|
||||
## Solaris
|
||||
|
||||
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
|
||||
|
||||
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
|
||||
|
||||
- **gcc**: `sudo pkg install developer/gcc-14`.
|
||||
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
|
||||
|
||||
Qt Widgets appears to be broken. For now, add `-DENABLE_QT=OFF` to your configure command. In the meantime, a Qt Quick frontend is in the works--check back later!
|
||||
|
||||
This is needed for some dependencies that call cc directly (tz):
|
||||
@@ -74,7 +81,7 @@ Still will not run flawlessly until `mesa-24` is available. Modify CMakeCache.tx
|
||||
|
||||
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
|
||||
|
||||
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`.
|
||||
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`. Builds are currently not working due to lack of `std::jthread` and such, either compile libc++ manually or wait for ports to catch up.
|
||||
|
||||
If clang has errors, try using `g++-11`.
|
||||
|
||||
@@ -107,6 +114,21 @@ cmake --build build -- -j`nproc`
|
||||
cmake --install build
|
||||
```
|
||||
|
||||
# DragonFlyBSD
|
||||
|
||||
If `libstdc++.so.6` is not found (`GLIBCXX_3.4.30`) then attempt:
|
||||
```sh
|
||||
rm /usr/local/lib/gcc11/libstdc++.so.6
|
||||
ln -s /usr/local/lib/gcc14/libstdc++.so /usr/local/lib/gcc11/libstdc++.so.6
|
||||
```
|
||||
This may have unforeseen consequences of which we don't need to worry about for now.
|
||||
|
||||
Default `g++` (and the libstdc++) is too outdated - so install `gcc14` and redirect CMake to the new compiler toolchain `-DCMAKE_CXX_COMPILER=gcc14 -DCMAKE_C_COMPILER=g++14`.
|
||||
|
||||
There is also `llvm18` and use `-DCMAKE_CXX_COMPILER=clang++18 -DCMAKE_C_COMPILER=clang18` (note the `18` suffix at the end). NOTE: It doesn't have an updated libcxx so `<span>` will be missing, either build it manually or use gcc.
|
||||
|
||||
If build hangs, use `hammer2 bulkfree`.
|
||||
|
||||
## MSYS2
|
||||
|
||||
`qt6-static` isn't supported yet.
|
||||
@@ -169,3 +191,9 @@ find ./*/ -name "*.dll" | while read -r dll; do deps "$dll"; done
|
||||
DirectX 12 is not available - simply copy and paste a random DLL and name it `d3d12.dll`.
|
||||
|
||||
Install [Qt6 compatibility libraries](github.com/ANightly/qt6windows7) specifically Qt 6.9.5.
|
||||
|
||||
## RedoxOS
|
||||
|
||||
The package install may randomly hang at times, in which case it has to be restarted. ALWAYS do a `sudo pkg update` or the chances of it hanging will be close to 90%. If "multiple" installs fail at once, try installing 1 by 1 the packages.
|
||||
|
||||
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.
|
||||
|
||||
@@ -8,6 +8,8 @@ But for new developers you may find that following these guidelines will make ev
|
||||
|
||||
Simply put, types/classes are named as `PascalCase`, same for methods and functions like `AddElement`. Variables are named `like_this_snake_case` and constants are `IN_SCREAMING_CASE`.
|
||||
|
||||
Except for Qt MOC where `functionName` is preferred.
|
||||
|
||||
Template typenames prefer short names like `T`, `I`, `U`, if a longer name is required either `Iterator` or `perform_action` are fine as well.
|
||||
|
||||
Macros must always be in `SCREAMING_CASE`. Do not use short letter macros as systems like Solaris will conflict with them; a good rule of thumb is >5 characters per macro - i.e `THIS_MACRO_IS_GOOD`, `AND_ALSO_THIS_ONE`.
|
||||
|
||||
32
docs/Deps.md
@@ -196,7 +196,6 @@ apk add g++ git cmake make mbedtls-dev mbedtls-static mesa-dev qt6-qtbase-dev qt
|
||||
`mbedtls-static` has to be specified otherwise `libeverest.a` and `libp256m.a` will fail to be found.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Void Linux</summary>
|
||||
|
||||
@@ -236,7 +235,7 @@ brew install molten-vk vulkan-loader
|
||||
<details>
|
||||
<summary>FreeBSD</summary>
|
||||
|
||||
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/jwt-cpp devel/unordered-dense`
|
||||
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/jwt-cpp devel/unordered-dense mbedtls3 vulkan-headers quazip-qt6`
|
||||
|
||||
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||
|
||||
@@ -261,18 +260,23 @@ pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gm
|
||||
|
||||
[Caveats](./Caveats.md#openbsd).
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>DragonFlyBSD</summary>
|
||||
|
||||
```sh
|
||||
pkg install gcc14 git cmake unzip nasm autoconf bash pkgconf ffmpeg glslang gmake jq nlohmann-json enet spirv-tools sdl2 vulkan-utility-libraries vulkan-headers catch2 libfmt openssl liblz4 boost-libs cpp-httplib qt6-base quazip-qt6 unordered-dense libva-vdpau-driver libva-utils libva-intel-driver
|
||||
```
|
||||
|
||||
[Caveats](./Caveats.md#dragonflybsd).
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Solaris / OpenIndiana</summary>
|
||||
|
||||
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
|
||||
|
||||
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
|
||||
|
||||
- **gcc**: `sudo pkg install developer/gcc-14`.
|
||||
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
|
||||
|
||||
Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
|
||||
```sh
|
||||
sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt
|
||||
```
|
||||
|
||||
[Caveats](./Caveats.md#solaris).
|
||||
|
||||
@@ -316,16 +320,16 @@ pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel b
|
||||
[Caveats](./Caveats.md#haikuos).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>RedoxOS</summary>
|
||||
|
||||
TODO: Fix syscall crashes (heavy IO stalls and hangup due to net mutexes?)
|
||||
```sh
|
||||
sudo pkg update && sudo pkg install git cmake
|
||||
sudo pkg install ffmpeg6 sdl2 zlib llvm18
|
||||
sudo pkg update
|
||||
sudo pkg install git cmake ffmpeg6 sdl2 zlib llvm18
|
||||
```
|
||||
|
||||
[Caveats](./Caveats.md#redoxos).
|
||||
|
||||
</details>
|
||||
|
||||
## All Done
|
||||
|
||||
16
shell.nix
@@ -9,11 +9,15 @@ pkgs.mkShellNoCC {
|
||||
# libraries
|
||||
openssl boost fmt nlohmann_json lz4 zlib zstd
|
||||
enet libopus vulkan-headers vulkan-utility-libraries
|
||||
spirv-tools spirv-headers simpleini vulkan-memory-allocator
|
||||
vulkan-loader unzip mbedtls glslang python3 httplib
|
||||
cpp-jwt ffmpeg-headless libusb1 cubeb
|
||||
qt6.full # eden
|
||||
SDL2 # eden-cli
|
||||
discord-rpc gamemode # optional components
|
||||
spirv-tools spirv-headers vulkan-loader unzip mbedtls
|
||||
glslang python3 httplib cpp-jwt ffmpeg-headless
|
||||
libusb1 cubeb
|
||||
# eden
|
||||
qt6.qtbase qt6.qtmultimedia qt6.qtwayland qt6.qttools
|
||||
qt6.qtwebengine qt6.qt5compat
|
||||
# eden-cli
|
||||
SDL2
|
||||
# optional components
|
||||
discord-rpc gamemode
|
||||
];
|
||||
}
|
||||
@@ -178,8 +178,10 @@ else()
|
||||
|
||||
if (MINGW)
|
||||
add_compile_definitions(MINGW_HAS_SECURE_API)
|
||||
add_compile_options("-msse4.1")
|
||||
|
||||
# Only windows has this requirement, thanks windows
|
||||
if (WIN32)
|
||||
add_compile_options("-msse4.1")
|
||||
endif()
|
||||
if (MINGW_STATIC_BUILD)
|
||||
add_compile_definitions(QT_STATICPLUGIN)
|
||||
add_compile_options("-static")
|
||||
|
||||
@@ -29,7 +29,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
|
||||
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
|
||||
RENDERER_DEBUG("debug"),
|
||||
RENDERER_FORCE_UNSUPPORTED_EXTENSIONS("force_unsupported_extensions"),
|
||||
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
||||
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||
|
||||
@@ -139,13 +139,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.dynaStateValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FORCE_UNSUPPORTED_EXTENSIONS,
|
||||
titleId = R.string.force_unsupported_extensions,
|
||||
descriptionId = R.string.force_unsupported_extensions_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_PROVOKING_VERTEX,
|
||||
|
||||
@@ -453,7 +453,6 @@ class SettingsFragmentPresenter(
|
||||
sl.apply {
|
||||
add(HeaderSetting(R.string.veil_extensions))
|
||||
add(ByteSetting.RENDERER_DYNA_STATE.key)
|
||||
add(BooleanSetting.RENDERER_FORCE_UNSUPPORTED_EXTENSIONS.key)
|
||||
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
||||
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
||||
add(BooleanSetting.RENDERER_SAMPLE_SHADING.key)
|
||||
|
||||
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 65 KiB |
@@ -94,8 +94,6 @@
|
||||
<string name="dyna_state">Extended Dynamic State</string>
|
||||
<string name="dyna_state_description">Controls the number of features that can be used in Extended Dynamic State. Higher numbers allow for more features and can increase performance, but may cause issues with some drivers and vendors. The default value may vary depending on your system and hardware capabilities. This value can be changed until stability and a better visual quality are achieved.</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="force_unsupported_extensions">Force Unsupported Extensions</string>
|
||||
<string name="force_unsupported_extensions_description">Bypasses all driver workarounds and safety checks. May cause crashes, graphical glitches, or instability. Only enable for testing purposes.</string>
|
||||
<string name="provoking_vertex">Provoking Vertex</string>
|
||||
<string name="provoking_vertex_description">Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs.</string>
|
||||
<string name="descriptor_indexing">Descriptor Indexing</string>
|
||||
|
||||
@@ -84,6 +84,7 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
|
||||
const auto pow_10 = [](f32 val) -> f32 {
|
||||
return (val >= 0.0f) ? 1.0f : (val <= -5.3f) ? 0.0f : std::pow(10.0f, val);
|
||||
};
|
||||
|
||||
const auto cos = [](f32 degrees) -> f32 {
|
||||
return std::cos(degrees * std::numbers::pi_v<f32> / 180.0f);
|
||||
};
|
||||
@@ -91,26 +92,39 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
|
||||
static bool unk_initialized{false};
|
||||
static Common::FixedPoint<50, 14> unk_value{};
|
||||
|
||||
const auto sample_rate{Common::FixedPoint<50, 14>::from_base(params.sample_rate)};
|
||||
const auto pre_delay_time{Common::FixedPoint<50, 14>::from_base(params.pre_delay)};
|
||||
auto sample_rate = Common::FixedPoint<50, 14>::from_base(params.sample_rate);
|
||||
if (sample_rate.to_float() < 1.0f) sample_rate = Common::FixedPoint<50, 14>(1.0f);
|
||||
|
||||
auto pre_delay_time = Common::FixedPoint<50, 14>::from_base(params.pre_delay);
|
||||
if (pre_delay_time.to_float() < 0.0f) pre_delay_time = Common::FixedPoint<50, 14>(0.0f);
|
||||
|
||||
for (u32 i = 0; i < ReverbInfo::MaxDelayTaps; i++) {
|
||||
auto early_delay{
|
||||
((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int()};
|
||||
early_delay = (std::min)(early_delay, state.pre_delay_line.sample_count_max);
|
||||
state.early_delay_times[i] = early_delay + 1;
|
||||
state.early_gains[i] = Common::FixedPoint<50, 14>::from_base(params.early_gain) *
|
||||
EarlyDelayGains[params.early_mode][i];
|
||||
int target_delay = ((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int();
|
||||
if (target_delay < 0) target_delay = 0;
|
||||
if (target_delay > state.pre_delay_line.sample_count_max) target_delay = state.pre_delay_line.sample_count_max;
|
||||
|
||||
int old_delay = state.early_delay_times[i] - 1;
|
||||
int smooth_delay = old_delay + (target_delay - old_delay) / 4;
|
||||
state.early_delay_times[i] = smooth_delay + 1;
|
||||
|
||||
auto target_gain = Common::FixedPoint<50, 14>::from_base(params.early_gain) * EarlyDelayGains[params.early_mode][i];
|
||||
if (target_gain.to_float() < 0.0f) target_gain = Common::FixedPoint<50, 14>(0.0f);
|
||||
if (target_gain.to_float() > 1.0f) target_gain = Common::FixedPoint<50, 14>(1.0f);
|
||||
|
||||
state.early_gains[i] = state.early_gains[i] + (target_gain - state.early_gains[i]) / 4;
|
||||
}
|
||||
|
||||
if (params.channel_count == 2) {
|
||||
state.early_gains[4] * 0.5f;
|
||||
state.early_gains[5] * 0.5f;
|
||||
state.early_gains[4] *= Common::FixedPoint<50, 14>(0.5f);
|
||||
state.early_gains[5] *= Common::FixedPoint<50, 14>(0.5f);
|
||||
}
|
||||
|
||||
auto pre_time{
|
||||
((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int()};
|
||||
state.pre_delay_time = (std::min)(pre_time, state.pre_delay_line.sample_count_max);
|
||||
int target_pre_time = ((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int();
|
||||
if (target_pre_time < 0) target_pre_time = 0;
|
||||
if (target_pre_time > state.pre_delay_line.sample_count_max) target_pre_time = state.pre_delay_line.sample_count_max;
|
||||
|
||||
int old_pre_time = state.pre_delay_time;
|
||||
state.pre_delay_time = old_pre_time + (target_pre_time - old_pre_time) / 4;
|
||||
|
||||
if (!unk_initialized) {
|
||||
unk_value = cos((1280.0f / sample_rate).to_float());
|
||||
@@ -118,45 +132,64 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
|
||||
const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
||||
state.fdn_delay_lines[i].sample_count =
|
||||
(std::min)(fdn_delay, state.fdn_delay_lines[i].sample_count_max);
|
||||
state.fdn_delay_lines[i].buffer_end =
|
||||
&state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
|
||||
int target_fdn_delay = (FdnDelayTimes[params.late_mode][i] * sample_rate).to_int();
|
||||
if (target_fdn_delay < 0) target_fdn_delay = 0;
|
||||
if (target_fdn_delay > state.fdn_delay_lines[i].sample_count_max) target_fdn_delay = state.fdn_delay_lines[i].sample_count_max;
|
||||
|
||||
const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
||||
state.decay_delay_lines[i].sample_count =
|
||||
(std::min)(decay_delay, state.decay_delay_lines[i].sample_count_max);
|
||||
state.decay_delay_lines[i].buffer_end =
|
||||
&state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
|
||||
int old_fdn = state.fdn_delay_lines[i].sample_count;
|
||||
state.fdn_delay_lines[i].sample_count = old_fdn + (target_fdn_delay - old_fdn) / 4;
|
||||
state.fdn_delay_lines[i].buffer_end = &state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
|
||||
|
||||
state.decay_delay_lines[i].decay =
|
||||
0.5999755859375f * (1.0f - Common::FixedPoint<50, 14>::from_base(params.colouration));
|
||||
int target_decay_delay = (DecayDelayTimes[params.late_mode][i] * sample_rate).to_int();
|
||||
if (target_decay_delay < 0) target_decay_delay = 0;
|
||||
if (target_decay_delay > state.decay_delay_lines[i].sample_count_max) target_decay_delay = state.decay_delay_lines[i].sample_count_max;
|
||||
|
||||
auto a{(Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) +
|
||||
state.decay_delay_lines[i].sample_count_max) *
|
||||
-3};
|
||||
auto b{a / (Common::FixedPoint<50, 14>::from_base(params.decay_time) * sample_rate)};
|
||||
Common::FixedPoint<50, 14> c{0.0f};
|
||||
Common::FixedPoint<50, 14> d{0.0f};
|
||||
auto hf_decay_ratio{Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio)};
|
||||
int old_decay = state.decay_delay_lines[i].sample_count;
|
||||
state.decay_delay_lines[i].sample_count = old_decay + (target_decay_delay - old_decay) / 4;
|
||||
state.decay_delay_lines[i].buffer_end = &state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
|
||||
|
||||
if (hf_decay_ratio > 0.99493408203125f) {
|
||||
auto colouration = Common::FixedPoint<50, 14>::from_base(params.colouration);
|
||||
if (colouration.to_float() < 0.0f) colouration = Common::FixedPoint<50, 14>(0.0f);
|
||||
if (colouration.to_float() > 1.0f) colouration = Common::FixedPoint<50, 14>(1.0f);
|
||||
|
||||
state.decay_delay_lines[i].decay = state.decay_delay_lines[i].decay + (0.5999755859375f * (1.0f - colouration) - state.decay_delay_lines[i].decay) / 4;
|
||||
|
||||
auto decay_time_fp = Common::FixedPoint<50, 14>::from_base(params.decay_time);
|
||||
if (decay_time_fp.to_float() <= 0.0f) decay_time_fp = Common::FixedPoint<50, 14>(0.0001f);
|
||||
|
||||
auto a = (Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) + state.decay_delay_lines[i].sample_count_max) * -3;
|
||||
auto b = a / (decay_time_fp * sample_rate);
|
||||
|
||||
auto hf_decay_ratio = Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio);
|
||||
if (hf_decay_ratio.to_float() < 0.001f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.001f);
|
||||
if (hf_decay_ratio.to_float() > 0.999f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.999f);
|
||||
|
||||
Common::FixedPoint<50, 14> c{0.0f}, d{0.0f};
|
||||
if (hf_decay_ratio.to_float() > 0.9949f) {
|
||||
c = 0.0f;
|
||||
d = 1.0f;
|
||||
} else {
|
||||
const auto e{
|
||||
pow_10(((((1.0f / hf_decay_ratio) - 1.0f) * 2) / 100 * (b / 10)).to_float())};
|
||||
const auto f{1.0f - e};
|
||||
const auto g{2.0f - (unk_value * e * 2)};
|
||||
const auto h{std::sqrt(std::pow(g.to_float(), 2.0f) - (std::pow(f, 2.0f) * 4))};
|
||||
auto e = pow_10(((((1.0f / hf_decay_ratio.to_float()) - 1.0f) * 2) / 100 * (b / 10)).to_float());
|
||||
if (e < 0.0001f) e = 0.0001f;
|
||||
if (e > 1.0f) e = 1.0f;
|
||||
|
||||
auto f = 1.0f - e;
|
||||
if (f < 0.0001f) f = 0.0001f;
|
||||
|
||||
auto g = 2.0f - (unk_value.to_float() * e * 2);
|
||||
|
||||
auto h_sq = g * g - f * f * 4;
|
||||
if (h_sq < 0.0f) h_sq = 0.0f;
|
||||
|
||||
auto h = std::sqrt(h_sq);
|
||||
|
||||
c = (g - h) / (f * 2.0f);
|
||||
d = 1.0f - c;
|
||||
}
|
||||
|
||||
state.hf_decay_prev_gain[i] = c;
|
||||
state.hf_decay_gain[i] = pow_10((b / 1000).to_float()) * d * 0.70709228515625f;
|
||||
state.hf_decay_prev_gain[i] = state.hf_decay_prev_gain[i] + (c - state.hf_decay_prev_gain[i]) / 4;
|
||||
state.hf_decay_gain[i] = state.hf_decay_gain[i] + (pow_10((b / 1000).to_float()) * d * 0.70709228515625f - state.hf_decay_gain[i]) / 4;
|
||||
|
||||
state.prev_feedback_output[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -191,6 +224,8 @@ static void InitializeReverbEffect(const ReverbInfo::ParameterVersion2& params,
|
||||
const auto center_delay_time{(5 * delay).to_uint_floor()};
|
||||
state.center_delay_line.Initialize(center_delay_time, 1.0f);
|
||||
|
||||
UpdateReverbEffectParameter(params, state);
|
||||
|
||||
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
|
||||
std::ranges::fill(state.fdn_delay_lines[i].buffer, 0);
|
||||
std::ranges::fill(state.decay_delay_lines[i].buffer, 0);
|
||||
|
||||
@@ -252,11 +252,13 @@ if(CXX_CLANG)
|
||||
endif()
|
||||
|
||||
if (BOOST_NO_HEADERS)
|
||||
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool)
|
||||
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool Boost::filesystem)
|
||||
else()
|
||||
target_link_libraries(common PUBLIC Boost::headers)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::filesystem)
|
||||
|
||||
if (lz4_ADDED)
|
||||
target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib)
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -12,24 +15,4 @@ namespace Common {
|
||||
template <typename T>
|
||||
concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
|
||||
|
||||
// TODO: Replace with std::derived_from when the <concepts> header
|
||||
// is available on all supported platforms.
|
||||
template <typename Derived, typename Base>
|
||||
concept DerivedFrom = requires {
|
||||
std::is_base_of_v<Base, Derived>;
|
||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||
};
|
||||
|
||||
// TODO: Replace with std::convertible_to when libc++ implements it.
|
||||
template <typename From, typename To>
|
||||
concept ConvertibleTo = std::is_convertible_v<From, To>;
|
||||
|
||||
// No equivalents in the stdlib
|
||||
|
||||
template <typename T>
|
||||
concept IsArithmetic = std::is_arithmetic_v<T>;
|
||||
|
||||
template <typename T>
|
||||
concept IsIntegral = std::is_integral_v<T>;
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2015 Evan Teran
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -16,6 +19,10 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
// No equivalent for "std::arithmetic" in the stdlib
|
||||
template <typename T>
|
||||
concept IsArithmetic = std::is_arithmetic_v<T>;
|
||||
|
||||
template <size_t I, size_t F>
|
||||
class FixedPoint;
|
||||
|
||||
@@ -392,13 +399,13 @@ public: // binary math operators, effects underlying bit pattern since these
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <IsIntegral Integer>
|
||||
template <std::integral Integer>
|
||||
constexpr FixedPoint& operator>>=(Integer n) {
|
||||
data_ >>= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <IsIntegral Integer>
|
||||
template <std::integral Integer>
|
||||
constexpr FixedPoint& operator<<=(Integer n) {
|
||||
data_ <<= n;
|
||||
return *this;
|
||||
@@ -587,12 +594,12 @@ constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
|
||||
}
|
||||
|
||||
// shift operators
|
||||
template <size_t I, size_t F, IsIntegral Integer>
|
||||
template <size_t I, size_t F, std::integral Integer>
|
||||
constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) {
|
||||
lhs <<= rhs;
|
||||
return lhs;
|
||||
}
|
||||
template <size_t I, size_t F, IsIntegral Integer>
|
||||
template <size_t I, size_t F, std::integral Integer>
|
||||
constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) {
|
||||
lhs >>= rhs;
|
||||
return lhs;
|
||||
|
||||
@@ -14,16 +14,29 @@ namespace fs = std::filesystem;
|
||||
|
||||
fs::path GetKvdbPath()
|
||||
{
|
||||
return GetLegacyPath(EmuPath::RyujinxDir) / "bis" / "system" / "save" / "8000000000000000" / "0"
|
||||
return GetKvdbPath(GetLegacyPath(EmuPath::RyujinxDir));
|
||||
}
|
||||
|
||||
fs::path GetKvdbPath(const fs::path& path) {
|
||||
return path / "bis" / "system" / "save" / "8000000000000000" / "0"
|
||||
/ "imkvdb.arc";
|
||||
}
|
||||
|
||||
fs::path GetRyuPathFromSavePath(const fs::path& path) {
|
||||
// This is a horrible hack, but I cba to find something better
|
||||
return path.parent_path().parent_path().parent_path().parent_path().parent_path();
|
||||
}
|
||||
|
||||
fs::path GetRyuSavePath(const u64 &save_id)
|
||||
{
|
||||
return GetRyuSavePath(GetLegacyPath(EmuPath::RyujinxDir), save_id);
|
||||
}
|
||||
|
||||
std::filesystem::path GetRyuSavePath(const std::filesystem::path& path, const u64& save_id) {
|
||||
std::string hex = fmt::format("{:016x}", save_id);
|
||||
|
||||
// TODO: what's the difference between 0 and 1?
|
||||
return GetLegacyPath(EmuPath::RyujinxDir) / "bis" / "user" / "save" / hex / "0";
|
||||
// TODO: what's the difference between 0 and 1?
|
||||
return path / "bis" / "user" / "save" / hex / "0";
|
||||
}
|
||||
|
||||
IMENReadResult ReadKvdb(const fs::path &path, std::vector<IMEN> &imens)
|
||||
|
||||
@@ -7,16 +7,17 @@
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
constexpr const char IMEN_MAGIC[4] = {0x49, 0x4d, 0x45, 0x4e};
|
||||
constexpr const char IMKV_MAGIC[4] = {0x49, 0x4d, 0x4b, 0x56};
|
||||
constexpr const u8 IMEN_SIZE = 0x8c;
|
||||
|
||||
fs::path GetKvdbPath();
|
||||
fs::path GetRyuSavePath(const u64 &program_id);
|
||||
std::filesystem::path GetKvdbPath();
|
||||
std::filesystem::path GetKvdbPath(const std::filesystem::path &path);
|
||||
std::filesystem::path GetRyuPathFromSavePath(const std::filesystem::path &path);
|
||||
std::filesystem::path GetRyuSavePath(const u64 &save_id);
|
||||
std::filesystem::path GetRyuSavePath(const std::filesystem::path &path, const u64 &save_id);
|
||||
|
||||
enum class IMENReadResult {
|
||||
Nonexistent, // ryujinx not found
|
||||
@@ -35,6 +36,6 @@ struct IMEN
|
||||
|
||||
static_assert(sizeof(IMEN) == 0x10, "IMEN has incorrect size.");
|
||||
|
||||
IMENReadResult ReadKvdb(const fs::path &path, std::vector<IMEN> &imens);
|
||||
IMENReadResult ReadKvdb(const std::filesystem::path &path, std::vector<IMEN> &imens);
|
||||
|
||||
} // namespace Common::FS
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include "symlink.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <fmt/format.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// The sole purpose of this file is to treat symlinks like symlinks on POSIX,
|
||||
@@ -15,29 +17,40 @@ namespace fs = std::filesystem;
|
||||
// This is because, for some inexplicable reason, Microsoft has locked symbolic
|
||||
// links behind a "security policy", whereas directory junctions--functionally identical
|
||||
// for directories, by the way--are not. Why? I don't know.
|
||||
// And no, they do NOT provide a standard API for this (at least to my knowledge).
|
||||
// CreateSymbolicLink, even when EXPLICITLY TOLD to create a junction, still fails
|
||||
// because of their security policy.
|
||||
// I don't know what kind of drugs the Windows developers have been on since NT started.
|
||||
|
||||
// Microsoft still has not implemented any of this in their std::filesystem implemenation,
|
||||
// which ALSO means that it DOES NOT FOLLOW ANY DIRECTORY JUNCTIONS... AT ALL.
|
||||
// Nor does any of their command line utilities or APIs. So you're quite literally
|
||||
// on your own.
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
bool CreateSymlink(const fs::path &from, const fs::path &to)
|
||||
bool CreateSymlink(fs::path from, fs::path to)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const std::string command = fmt::format("mklink /J {} {}", to.string(), from.string());
|
||||
return system(command.c_str()) == 0;
|
||||
#else
|
||||
from.make_preferred();
|
||||
to.make_preferred();
|
||||
|
||||
std::error_code ec;
|
||||
fs::create_directory_symlink(from, to, ec);
|
||||
return !ec;
|
||||
#ifdef _WIN32
|
||||
if (ec) {
|
||||
const std::string command = fmt::format("mklink /J \"{}\" \"{}\"",
|
||||
to.string(),
|
||||
from.string());
|
||||
return system(command.c_str()) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return !ec;
|
||||
}
|
||||
|
||||
bool IsSymlink(const fs::path &path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
auto attributes = GetFileAttributesW(path.wstring().c_str());
|
||||
return attributes & FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
#else
|
||||
return fs::is_symlink(path);
|
||||
#endif
|
||||
return boost::filesystem::is_symlink(boost::filesystem::path{path});
|
||||
}
|
||||
|
||||
} // namespace Common::FS
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <filesystem>
|
||||
namespace Common::FS {
|
||||
|
||||
bool CreateSymlink(const std::filesystem::path &from, const std::filesystem::path &to);
|
||||
bool CreateSymlink(std::filesystem::path from, std::filesystem::path to);
|
||||
bool IsSymlink(const std::filesystem::path &path);
|
||||
|
||||
} // namespace Common::FS
|
||||
|
||||
@@ -521,14 +521,29 @@ public:
|
||||
#else
|
||||
fd = memfd_create("HostMemory", 0);
|
||||
#endif
|
||||
ASSERT_MSG(fd >= 0, "memfd_create failed: {}", strerror(errno));
|
||||
|
||||
// Defined to extend the file with zeros
|
||||
int ret = ftruncate(fd, backing_size);
|
||||
ASSERT_MSG(ret == 0, "ftruncate failed with {}, are you out-of-memory?", strerror(errno));
|
||||
|
||||
backing_base = static_cast<u8*>(
|
||||
mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
|
||||
bool use_anon = false;
|
||||
if (fd <= 0) {
|
||||
LOG_WARNING(Common_Memory, "memfd_create: {}", strerror(errno));
|
||||
use_anon = true;
|
||||
}
|
||||
if (!use_anon) {
|
||||
// Defined to extend the file with zeros
|
||||
int ret = ftruncate(fd, backing_size);
|
||||
if (ret != 0) {
|
||||
LOG_WARNING(Common_Memory, "ftruncate: {} (likely out-of-emory)", strerror(errno));
|
||||
use_anon = true;
|
||||
}
|
||||
}
|
||||
if (use_anon) {
|
||||
LOG_WARNING(Common_Memory, "Using private mappings instead of shared ones");
|
||||
backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
||||
if (fd > 0) {
|
||||
fd = -1;
|
||||
close(fd);
|
||||
}
|
||||
} else {
|
||||
backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
|
||||
}
|
||||
ASSERT_MSG(backing_base != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||
|
||||
// Virtual memory initialization
|
||||
@@ -552,22 +567,18 @@ public:
|
||||
free_manager.AllocateBlock(virtual_base + virtual_offset, length);
|
||||
|
||||
// Deduce mapping protection flags.
|
||||
int flags = PROT_NONE;
|
||||
if (True(perms & MemoryPermission::Read)) {
|
||||
flags |= PROT_READ;
|
||||
}
|
||||
if (True(perms & MemoryPermission::Write)) {
|
||||
flags |= PROT_WRITE;
|
||||
}
|
||||
int prot_flags = PROT_NONE;
|
||||
if (True(perms & MemoryPermission::Read))
|
||||
prot_flags |= PROT_READ;
|
||||
if (True(perms & MemoryPermission::Write))
|
||||
prot_flags |= PROT_WRITE;
|
||||
#ifdef ARCHITECTURE_arm64
|
||||
if (True(perms & MemoryPermission::Execute)) {
|
||||
flags |= PROT_EXEC;
|
||||
}
|
||||
if (True(perms & MemoryPermission::Execute))
|
||||
prot_flags |= PROT_EXEC;
|
||||
#endif
|
||||
|
||||
void* ret = mmap(virtual_base + virtual_offset, length, flags, MAP_SHARED | MAP_FIXED, fd,
|
||||
host_offset);
|
||||
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||
int flags = (fd > 0 ? MAP_SHARED : MAP_PRIVATE) | MAP_FIXED;
|
||||
void* ret = mmap(virtual_base + virtual_offset, length, prot_flags, flags, fd, host_offset);
|
||||
ASSERT_MSG(ret != MAP_FAILED, "mmap: {}", strerror(errno));
|
||||
}
|
||||
|
||||
void Unmap(size_t virtual_offset, size_t length) {
|
||||
|
||||
@@ -169,7 +169,7 @@ bool IsFastmemEnabled() {
|
||||
if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe) {
|
||||
return bool(values.cpuopt_unsafe_host_mmu);
|
||||
}
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
|
||||
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
|
||||
@@ -296,7 +296,7 @@ struct Values {
|
||||
Category::CpuDebug};
|
||||
|
||||
SwitchableSetting<bool> cpuopt_unsafe_host_mmu{linkage,
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
|
||||
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
|
||||
false,
|
||||
#else
|
||||
true,
|
||||
@@ -546,7 +546,6 @@ struct Values {
|
||||
Category::RendererExtensions,
|
||||
Specialization::Scalar};
|
||||
|
||||
SwitchableSetting<bool> force_unsupported_extensions{linkage, false, "force_unsupported_extensions", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> sample_shading{linkage, false, "sample_shading", Category::RendererExtensions, Specialization::Paired};
|
||||
|
||||
@@ -292,7 +292,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
|
||||
// Curated optimizations
|
||||
case Settings::CpuAccuracy::Auto:
|
||||
config.unsafe_optimizations = true;
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__)
|
||||
config.fastmem_pointer = std::nullopt;
|
||||
config.fastmem_exclusive_access = false;
|
||||
#endif
|
||||
|
||||
@@ -351,7 +351,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
|
||||
// Safe optimisations
|
||||
case Settings::CpuAccuracy::Auto:
|
||||
config.unsafe_optimizations = true;
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
|
||||
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
|
||||
config.fastmem_pointer = std::nullopt;
|
||||
config.fastmem_exclusive_access = false;
|
||||
#endif
|
||||
|
||||
@@ -388,14 +388,6 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) {
|
||||
const std::size_t CACHE_PAGE_SIZE = 4096;
|
||||
|
||||
void ArmNce::ClearInstructionCache() {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
void* start = (void*)((uintptr_t)__builtin_return_address(0) & ~(CACHE_PAGE_SIZE - 1));
|
||||
void* end =
|
||||
(void*)((uintptr_t)start + CACHE_PAGE_SIZE * 2); // Clear two pages for better coverage
|
||||
// Prefetch next likely pages
|
||||
__builtin_prefetch((void*)((uintptr_t)end), 1, 3);
|
||||
__builtin___clear_cache(static_cast<char*>(start), static_cast<char*>(end));
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
// Ensure all previous memory operations complete
|
||||
asm volatile("dmb ish" ::: "memory");
|
||||
@@ -405,20 +397,6 @@ void ArmNce::ClearInstructionCache() {
|
||||
}
|
||||
|
||||
void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
// Align the start address to cache line boundary for better performance
|
||||
const size_t CACHE_LINE_SIZE = 64;
|
||||
addr &= ~(CACHE_LINE_SIZE - 1);
|
||||
|
||||
// Round up size to nearest cache line
|
||||
size = (size + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
|
||||
|
||||
// Prefetch the range to be invalidated
|
||||
for (size_t offset = 0; offset < size; offset += CACHE_LINE_SIZE) {
|
||||
__builtin_prefetch((void*)(addr + offset), 1, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
this->ClearInstructionCache();
|
||||
}
|
||||
|
||||
|
||||
@@ -181,14 +181,6 @@ bool InterpreterVisitor::Ordered(size_t size, bool L, bool o0, Reg Rn, Reg Rt) {
|
||||
const size_t dbytes = datasize / 8;
|
||||
|
||||
u64 address = (Rn == Reg::SP) ? this->GetSp() : this->GetReg(Rn);
|
||||
|
||||
// Conservative prefetch for atomic ops
|
||||
if (memop == MemOp::Load) {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 1);
|
||||
} else {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address), 1, 1);
|
||||
}
|
||||
|
||||
switch (memop) {
|
||||
case MemOp::Store: {
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
@@ -435,21 +427,6 @@ bool InterpreterVisitor::RegisterImmediate(bool wback, bool postindex, size_t sc
|
||||
if (!postindex)
|
||||
address += offset;
|
||||
|
||||
// Optimized prefetch for loads
|
||||
if (memop == MemOp::Load) {
|
||||
const size_t access_size = datasize / 8;
|
||||
const bool is_aligned = (address % access_size) == 0;
|
||||
|
||||
if (is_aligned) {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 3);
|
||||
if (access_size >= 8 && access_size <= 32) {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address + PREFETCH_STRIDE), 0, 3);
|
||||
}
|
||||
} else {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (memop) {
|
||||
case MemOp::Store: {
|
||||
u64 data = this->GetReg(Rt);
|
||||
@@ -516,15 +493,6 @@ bool InterpreterVisitor::SIMDImmediate(bool wback, bool postindex, size_t scale,
|
||||
if (!postindex)
|
||||
address += offset;
|
||||
|
||||
// Aggressive prefetch for SIMD
|
||||
if (memop == MemOp::Load) {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 3);
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address + CACHE_LINE_SIZE), 0, 3);
|
||||
if (datasize >= SIMD_PREFETCH_THRESHOLD) {
|
||||
__builtin_prefetch(reinterpret_cast<const void*>(address + PREFETCH_STRIDE), 0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
switch (memop) {
|
||||
case MemOp::Store: {
|
||||
u128 data = VectorGetElement(this->GetVec(Vt), datasize);
|
||||
|
||||
@@ -63,12 +63,10 @@ constexpr bool IsInvalidCharacter(char c) {
|
||||
return impl::IsInvalidCharacterImpl<InvalidCharacters, std::size(InvalidCharacters)>(c);
|
||||
}
|
||||
constexpr bool IsInvalidCharacterForHostName(char c) {
|
||||
return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName,
|
||||
std::size(InvalidCharactersForHostName)>(c);
|
||||
return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName, std::size(InvalidCharactersForHostName)>(c);
|
||||
}
|
||||
constexpr bool IsInvalidCharacterForMountName(char c) {
|
||||
return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName,
|
||||
std::size(InvalidCharactersForMountName)>(c);
|
||||
return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName, std::size(InvalidCharactersForMountName)>(c);
|
||||
}
|
||||
|
||||
} // namespace StringTraits
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/concepts.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -24,7 +23,7 @@ class KThread;
|
||||
template <typename T>
|
||||
concept KPriorityQueueAffinityMask = !
|
||||
std::is_reference_v<T>&& requires(T& t) {
|
||||
{ t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
|
||||
{ t.GetAffinityMask() } -> std::convertible_to<u64>;
|
||||
{ t.SetAffinityMask(0) };
|
||||
|
||||
{ t.GetAffinity(0) } -> std::same_as<bool>;
|
||||
@@ -50,9 +49,9 @@ std::is_reference_v<T>&& requires(T& t) {
|
||||
std::remove_cvref_t<decltype(t.GetAffinityMask())>()
|
||||
} -> KPriorityQueueAffinityMask;
|
||||
|
||||
{ t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
|
||||
{ t.GetPriority() } -> Common::ConvertibleTo<s32>;
|
||||
{ t.IsDummyThread() } -> Common::ConvertibleTo<bool>;
|
||||
{ t.GetActiveCore() } -> std::convertible_to<s32>;
|
||||
{ t.GetPriority() } -> std::convertible_to<s32>;
|
||||
{ t.IsDummyThread() } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-License-Identifier: GPL-2.0-or-late
|
||||
|
||||
// This file is automatically generated using svc_generator.py.
|
||||
// DO NOT MODIFY IT MANUALLY
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -16,8 +19,6 @@ class System;
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Kernel::Svc {
|
||||
|
||||
// clang-format off
|
||||
Result SetHeapSize(Core::System& system, uint64_t* out_address, uint64_t size);
|
||||
Result SetMemoryPermission(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
|
||||
Result SetMemoryAttribute(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
|
||||
@@ -506,8 +507,6 @@ enum class SvcId : u32 {
|
||||
MapInsecureMemory = 0x90,
|
||||
UnmapInsecureMemory = 0x91,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Custom ABI.
|
||||
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
|
||||
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/find.hpp>
|
||||
@@ -18,11 +16,11 @@
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/fs_types.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/fs/symlink.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/file_sys/savedata_factory.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include <ranges>
|
||||
|
||||
namespace Service::Account {
|
||||
|
||||
@@ -492,6 +490,32 @@ void ProfileManager::ResetUserSaveFile()
|
||||
ParseUserSaveFile();
|
||||
}
|
||||
|
||||
std::vector<UUID> ProfileManager::FindExistingProfileUUIDs()
|
||||
{
|
||||
std::vector<UUID> uuids;
|
||||
for (const ProfileInfo& p : profiles) {
|
||||
auto uuid = p.user_uuid;
|
||||
if (!uuid.IsInvalid()) {
|
||||
uuids.emplace_back(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
return uuids;
|
||||
}
|
||||
|
||||
std::vector<std::string> ProfileManager::FindExistingProfileStrings()
|
||||
{
|
||||
std::vector<UUID> uuids = FindExistingProfileUUIDs();
|
||||
std::vector<std::string> uuid_strings;
|
||||
|
||||
for (const UUID &uuid : uuids) {
|
||||
auto user_id = uuid.AsU128();
|
||||
uuid_strings.emplace_back(fmt::format("{:016X}{:016X}", user_id[1], user_id[0]));
|
||||
}
|
||||
|
||||
return uuid_strings;
|
||||
}
|
||||
|
||||
std::vector<std::string> ProfileManager::FindGoodProfiles()
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
@@ -501,31 +525,17 @@ std::vector<std::string> ProfileManager::FindGoodProfiles()
|
||||
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
|
||||
/ "user/save/0000000000000000";
|
||||
|
||||
// some exceptions because certain games just LOVE TO CAUSE ISSUES
|
||||
static constexpr const std::array<const char* const, 2> EXCEPTION_UUIDS
|
||||
= {"5755CC2A545A87128500000000000000", "00000000000000000000000000000000"};
|
||||
// some exceptions, e.g. the "system" profile
|
||||
static constexpr const std::array<const char* const, 1> EXCEPTION_UUIDS
|
||||
= {"00000000000000000000000000000000"};
|
||||
|
||||
for (const char *const uuid : EXCEPTION_UUIDS) {
|
||||
if (fs::exists(path / uuid))
|
||||
good_uuids.emplace_back(uuid);
|
||||
}
|
||||
|
||||
for (const ProfileInfo& p : profiles) {
|
||||
std::string uuid_string = [p]() -> std::string {
|
||||
auto uuid = p.user_uuid;
|
||||
|
||||
// "ignore" invalid uuids
|
||||
if (uuid.IsInvalid()) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
auto user_id = uuid.AsU128();
|
||||
|
||||
return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]);
|
||||
}();
|
||||
|
||||
if (uuid_string != "0") good_uuids.emplace_back(uuid_string);
|
||||
}
|
||||
auto existing = FindExistingProfileStrings();
|
||||
good_uuids.insert(good_uuids.end(), existing.begin(), existing.end());
|
||||
|
||||
return good_uuids;
|
||||
}
|
||||
@@ -562,7 +572,8 @@ std::vector<std::string> ProfileManager::FindOrphanedProfiles()
|
||||
override = true;
|
||||
|
||||
// if there are any regular files (NOT directories) there, do NOT delete it :p
|
||||
if (file.is_regular_file())
|
||||
// Also: check for symlinks
|
||||
if (file.is_regular_file() || Common::FS::IsSymlink(file.path()))
|
||||
return false;
|
||||
}
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
|
||||
@@ -105,6 +105,8 @@ public:
|
||||
|
||||
void ResetUserSaveFile();
|
||||
|
||||
std::vector<Common::UUID> FindExistingProfileUUIDs();
|
||||
std::vector<std::string> FindExistingProfileStrings();
|
||||
std::vector<std::string> FindGoodProfiles();
|
||||
std::vector<std::string> FindOrphanedProfiles();
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,8 +11,8 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <concepts>
|
||||
|
||||
#include "common/concepts.h"
|
||||
#include "core/hle/kernel/k_port.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/result.h"
|
||||
@@ -63,7 +66,7 @@ public:
|
||||
Result UnregisterService(const std::string& name);
|
||||
Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name);
|
||||
|
||||
template <Common::DerivedFrom<SessionRequestHandler> T>
|
||||
template <std::derived_from<SessionRequestHandler> T>
|
||||
std::shared_ptr<T> GetService(const std::string& service_name, bool block = false) const {
|
||||
auto service = registered_services.find(service_name);
|
||||
if (service == registered_services.end() && !block) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <concepts>
|
||||
#include "common/concepts.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -27,7 +28,7 @@ namespace Loader {
|
||||
|
||||
namespace {
|
||||
|
||||
template <Common::DerivedFrom<AppLoader> T>
|
||||
template <std::derived_from<AppLoader> T>
|
||||
std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
|
||||
const auto file_type = T::IdentifyType(file);
|
||||
if (file_type != FileType::Error) {
|
||||
|
||||
@@ -125,6 +125,10 @@ struct Jit::Impl final {
|
||||
current_state.exclusive_state = false;
|
||||
}
|
||||
|
||||
std::string Disassemble() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
void PerformRequestedCacheInvalidation(HaltReason hr) {
|
||||
if (Has(hr, HaltReason::CacheInvalidation)) {
|
||||
@@ -231,4 +235,8 @@ void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
||||
@@ -152,7 +152,7 @@ struct Jit::Impl final {
|
||||
}
|
||||
|
||||
std::string Disassemble() const {
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -468,8 +468,9 @@ void EmitIR<IR::Opcode::FPRoundInt32>(oaknut::CodeGenerator& code, EmitContext&
|
||||
case FP::RoundingMode::ToNearest_TieAwayFromZero:
|
||||
code.FRINTA(Sresult, Soperand);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1668,8 +1668,9 @@ void EmitIR<IR::Opcode::VectorTableLookup64>(oaknut::CodeGenerator& code, EmitCo
|
||||
code.TBX(Dresult->B8(), oaknut::List{V0.B16(), V1.B16()}, Dindices->B8());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -1731,8 +1732,9 @@ void EmitIR<IR::Opcode::VectorTableLookup128>(oaknut::CodeGenerator& code, EmitC
|
||||
code.TBX(Qresult->B16(), oaknut::List{V0.B16(), V1.B16(), V2.B16(), V3.B16()}, Qindices->B16());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -645,8 +645,9 @@ void EmitIR<IR::Opcode::FPVectorRoundInt32>(oaknut::CodeGenerator& code, EmitCon
|
||||
case FP::RoundingMode::ToNearest_TieAwayFromZero:
|
||||
code.FRINTA(Qresult->S4(), Qoperand->S4());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -684,8 +685,9 @@ void EmitIR<IR::Opcode::FPVectorRoundInt64>(oaknut::CodeGenerator& code, EmitCon
|
||||
case FP::RoundingMode::ToNearest_TieAwayFromZero:
|
||||
code.FRINTA(Qresult->D2(), Qoperand->D2());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -371,8 +371,9 @@ void RAReg<T>::Realize() {
|
||||
case RWType::ReadWrite:
|
||||
reg = T{reg_alloc.RealizeReadWriteImpl<kind>(read_value, write_value)};
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::Arm64
|
||||
|
||||
@@ -188,15 +188,15 @@ private:
|
||||
ExceptionHandler::ExceptionHandler() = default;
|
||||
ExceptionHandler::~ExceptionHandler() = default;
|
||||
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
void ExceptionHandler::Register(X64::BlockOfCode& code) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(code.getCode()), code.GetTotalCodeSize());
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr()), size);
|
||||
}
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
|
||||
}
|
||||
|
||||
@@ -36,22 +36,8 @@
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
||||
@@ -36,22 +36,8 @@
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
||||
@@ -14,23 +14,8 @@
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (esize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (esize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
#define FCODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
# elif defined(__sun__)
|
||||
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||
# elif defined(__DragonFly__)
|
||||
# define CTX_RIP (mctx.mc_rip)
|
||||
# define CTX_RSP (mctx.mc_rsp)
|
||||
# else
|
||||
# error "Unknown platform"
|
||||
# endif
|
||||
|
||||
@@ -28,7 +28,7 @@ const QString GetOpenFileName(const QString &title,
|
||||
Options options)
|
||||
{
|
||||
#ifdef YUZU_QT_WIDGETS
|
||||
return QFileDialog::getOpenFileName((QWidget *) rootObject, title, dir, filter, selectedFilter, options);
|
||||
return QFileDialog::getOpenFileName(rootObject, title, dir, filter, selectedFilter, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -39,7 +39,14 @@ const QString GetSaveFileName(const QString &title,
|
||||
Options options)
|
||||
{
|
||||
#ifdef YUZU_QT_WIDGETS
|
||||
return QFileDialog::getSaveFileName((QWidget *) rootObject, title, dir, filter, selectedFilter, options);
|
||||
return QFileDialog::getSaveFileName(rootObject, title, dir, filter, selectedFilter, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
const QString GetExistingDirectory(const QString& caption, const QString& dir,
|
||||
Options options) {
|
||||
#ifdef YUZU_QT_WIDGETS
|
||||
return QFileDialog::getExistingDirectory(rootObject, caption, dir, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -135,5 +135,9 @@ const QString GetSaveFileName(const QString &title,
|
||||
QString *selectedFilter = nullptr,
|
||||
Options options = Options());
|
||||
|
||||
const QString GetExistingDirectory(const QString &caption = QString(),
|
||||
const QString &dir = QString(),
|
||||
Options options = Option::ShowDirsOnly);
|
||||
|
||||
} // namespace QtCommon::Frontend
|
||||
#endif // FRONTEND_H
|
||||
|
||||
@@ -294,6 +294,17 @@ void QtConfig::ReadUIGamelistValues() {
|
||||
}
|
||||
EndArray();
|
||||
|
||||
const int linked_size = BeginArray("ryujinx_linked");
|
||||
for (int i = 0; i < linked_size; ++i) {
|
||||
SetArrayIndex(i);
|
||||
|
||||
QDir ryu_dir = QString::fromStdString(ReadStringSetting("ryujinx_path"));
|
||||
u64 program_id = ReadUnsignedIntegerSetting("program_id");
|
||||
|
||||
UISettings::values.ryujinx_link_paths.insert(program_id, ryu_dir);
|
||||
}
|
||||
EndArray();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
@@ -499,6 +510,21 @@ void QtConfig::SaveUIGamelistValues() {
|
||||
}
|
||||
EndArray(); // favorites
|
||||
|
||||
BeginArray(std::string("ryujinx_linked"));
|
||||
int i = 0;
|
||||
QMapIterator iter(UISettings::values.ryujinx_link_paths);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
|
||||
SetArrayIndex(i);
|
||||
WriteIntegerSetting("program_id", iter.key());
|
||||
WriteStringSetting("ryujinx_path", iter.value().absolutePath().toStdString());
|
||||
++i;
|
||||
}
|
||||
|
||||
EndArray(); // ryujinx
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
|
||||
@@ -329,13 +329,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
||||
tr("Extended Dynamic State"),
|
||||
tr("Controls the number of features that can be used in Extended Dynamic State.\nHigher numbers allow for more features and can increase performance, but may cause issues.\nThe default value is per-system."));
|
||||
|
||||
INSERT(Settings,
|
||||
force_unsupported_extensions,
|
||||
tr("Force Unsupported Extensions"),
|
||||
tr("Bypasses all driver workarounds and safety checks.\n"
|
||||
"May cause crashes, graphical glitches, or instability.\n"
|
||||
"Only enable for testing purposes."));
|
||||
|
||||
INSERT(Settings,
|
||||
provoking_vertex,
|
||||
tr("Provoking Vertex"),
|
||||
|
||||
@@ -28,54 +28,54 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject *parent);
|
||||
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent);
|
||||
|
||||
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = {
|
||||
{Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
|
||||
{Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
|
||||
{Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
|
||||
{Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "None"))},
|
||||
{Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "FXAA"))},
|
||||
{Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "SMAA"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map = {
|
||||
{Settings::ScalingFilter::NearestNeighbor,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Nearest"))},
|
||||
{Settings::ScalingFilter::Bilinear,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
|
||||
{Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
|
||||
{Settings::ScalingFilter::ZeroTangent, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Zero-Tangent"))},
|
||||
{Settings::ScalingFilter::BSpline, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "B-Spline"))},
|
||||
{Settings::ScalingFilter::Mitchell, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Mitchell"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Bilinear"))},
|
||||
{Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Bicubic"))},
|
||||
{Settings::ScalingFilter::ZeroTangent, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Zero-Tangent"))},
|
||||
{Settings::ScalingFilter::BSpline, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "B-Spline"))},
|
||||
{Settings::ScalingFilter::Mitchell, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Mitchell"))},
|
||||
{Settings::ScalingFilter::Spline1,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Spline-1"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Spline-1"))},
|
||||
{Settings::ScalingFilter::Gaussian,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Gaussian"))},
|
||||
{Settings::ScalingFilter::Lanczos,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Lanczos"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Lanczos"))},
|
||||
{Settings::ScalingFilter::ScaleForce,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
|
||||
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
|
||||
{Settings::ScalingFilter::Area, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Area"))},
|
||||
{Settings::ScalingFilter::Mmpx, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "MMPX"))},
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "ScaleForce"))},
|
||||
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "FSR"))},
|
||||
{Settings::ScalingFilter::Area, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Area"))},
|
||||
{Settings::ScalingFilter::Mmpx, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "MMPX"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = {
|
||||
{Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
|
||||
{Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
|
||||
{Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Docked"))},
|
||||
{Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Handheld"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = {
|
||||
{Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
|
||||
{Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
|
||||
{Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
|
||||
{Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Normal"))},
|
||||
{Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "High"))},
|
||||
{Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Extreme"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = {
|
||||
{Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
|
||||
{Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
|
||||
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
|
||||
{Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Vulkan"))},
|
||||
{Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL"))},
|
||||
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Null"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map = {
|
||||
{Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
|
||||
{Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
|
||||
{Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
|
||||
{Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "GLSL"))},
|
||||
{Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "GLASM"))},
|
||||
{Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "SPIRV"))},
|
||||
};
|
||||
|
||||
} // namespace ConfigurationShared
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <qdir.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
@@ -201,6 +202,7 @@ struct Values {
|
||||
Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
|
||||
Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
|
||||
QVector<u64> favorited_ids;
|
||||
QMap<u64, QDir> ryujinx_link_paths;
|
||||
|
||||
// Compatibility List
|
||||
Setting<bool> show_compat{linkage, true, "show_compat", Category::UiGameList};
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
#include "frozen/map.h"
|
||||
#include "frozen/string.h"
|
||||
|
||||
/// Small helper to look up enums.
|
||||
/// res = the result code
|
||||
/// base = the base matching value in the StringKey table
|
||||
#define LOOKUP_ENUM(res, base) StringLookup::Lookup( \
|
||||
static_cast<StringLookup::StringKey>((int) res + (int) StringLookup::base))
|
||||
|
||||
namespace QtCommon::StringLookup {
|
||||
|
||||
Q_NAMESPACE
|
||||
|
||||
@@ -25,8 +25,7 @@ enum class FirmwareInstallResult {
|
||||
|
||||
inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result)
|
||||
{
|
||||
return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>(
|
||||
(int) result + (int) QtCommon::StringLookup::FwInstallSuccess));
|
||||
return LOOKUP_ENUM(result, FwInstallSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,9 +35,7 @@ inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result
|
||||
*/
|
||||
inline const QString GetKeyInstallResultString(FirmwareManager::KeyInstallResult result)
|
||||
{
|
||||
// this can probably be made into a common function of sorts
|
||||
return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>(
|
||||
(int) result + (int) QtCommon::StringLookup::KeyInstallSuccess));
|
||||
return LOOKUP_ENUM(result, KeyInstallSuccess);
|
||||
}
|
||||
|
||||
void InstallFirmware(const QString &location, bool recursive);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include "fs.h"
|
||||
#include "common/fs/ryujinx_compat.h"
|
||||
#include "common/fs/symlink.h"
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "fs.h"
|
||||
#include "qt_common/abstract/frontend.h"
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
|
||||
@@ -56,6 +56,9 @@ bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
|
||||
orig = eden_dir;
|
||||
}
|
||||
|
||||
linked.make_preferred();
|
||||
orig.make_preferred();
|
||||
|
||||
// first cleanup the symlink/junction,
|
||||
try {
|
||||
// NB: do NOT use remove_all, as Windows treats this as a remove_all to the target,
|
||||
@@ -84,47 +87,64 @@ bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 GetRyujinxSaveID(const u64 &program_id)
|
||||
const fs::path GetRyujinxSavePath(const fs::path &path_hint, const u64 &program_id)
|
||||
{
|
||||
auto path = Common::FS::GetKvdbPath();
|
||||
auto ryu_path = path_hint;
|
||||
|
||||
auto kvdb_path = Common::FS::GetKvdbPath(ryu_path);
|
||||
|
||||
if (!fs::exists(kvdb_path)) {
|
||||
using namespace QtCommon::Frontend;
|
||||
auto res = Warning(
|
||||
tr("Could not find Ryujinx installation"),
|
||||
tr("Could not find a valid Ryujinx installation. This may typically occur if you are "
|
||||
"using Ryujinx in portable mode.\n\nWould you like to manually select a portable "
|
||||
"folder to use?"), StandardButton::Yes | StandardButton::No);
|
||||
|
||||
if (res == StandardButton::Yes) {
|
||||
auto selected_path = GetExistingDirectory(tr("Ryujinx Portable Location"), QDir::homePath()).toStdString();
|
||||
if (selected_path.empty())
|
||||
return fs::path{};
|
||||
|
||||
ryu_path = selected_path;
|
||||
|
||||
// In case the user selects the actual ryujinx installation dir INSTEAD OF
|
||||
// the portable dir
|
||||
if (fs::exists(ryu_path / "portable")) {
|
||||
ryu_path = ryu_path / "portable";
|
||||
}
|
||||
|
||||
kvdb_path = Common::FS::GetKvdbPath(ryu_path);
|
||||
|
||||
if (!fs::exists(kvdb_path)) {
|
||||
QtCommon::Frontend::Critical(
|
||||
tr("Not a valid Ryujinx directory"),
|
||||
tr("The specified directory does not contain valid Ryujinx data."));
|
||||
return fs::path{};
|
||||
}
|
||||
} else {
|
||||
return fs::path{};
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Common::FS::IMEN> imens;
|
||||
Common::FS::IMENReadResult res = Common::FS::ReadKvdb(path, imens);
|
||||
Common::FS::IMENReadResult res = Common::FS::ReadKvdb(kvdb_path, imens);
|
||||
|
||||
if (res == Common::FS::IMENReadResult::Success) {
|
||||
// TODO: this can probably be done with std::find_if but I'm lazy
|
||||
for (const Common::FS::IMEN &imen : imens) {
|
||||
if (imen.title_id == program_id)
|
||||
return imen.save_id;
|
||||
return Common::FS::GetRyuSavePath(ryu_path, imen.save_id);
|
||||
}
|
||||
|
||||
QtCommon::Frontend::Critical(
|
||||
tr("Could not find Ryujinx save data"),
|
||||
StringLookup::Lookup(StringLookup::RyujinxNoSaveId).arg(program_id, 0, 16));
|
||||
} else {
|
||||
// TODO: make this long thing a function or something
|
||||
QString caption = StringLookup::Lookup(
|
||||
static_cast<StringLookup::StringKey>((int) res + (int) StringLookup::KvdbNonexistent));
|
||||
QString caption = LOOKUP_ENUM(res, KvdbNonexistent);
|
||||
QtCommon::Frontend::Critical(tr("Could not find Ryujinx save data"), caption);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::optional<std::pair<fs::path, fs::path> > GetEmuPaths(
|
||||
const u64 program_id, const u64 save_id, const std::string &user_id)
|
||||
{
|
||||
fs::path ryu_dir = Common::FS::GetRyuSavePath(save_id);
|
||||
|
||||
if (user_id.empty())
|
||||
return std::nullopt;
|
||||
|
||||
std::string hex_program = fmt::format("{:016X}", program_id);
|
||||
fs::path eden_dir
|
||||
= FrontendCommon::DataManager::GetDataDir(FrontendCommon::DataManager::DataDir::Saves,
|
||||
user_id)
|
||||
/ hex_program;
|
||||
|
||||
return std::make_pair(eden_dir, ryu_dir);
|
||||
return fs::path{};
|
||||
}
|
||||
|
||||
} // namespace QtCommon::FS
|
||||
|
||||
@@ -10,13 +10,10 @@
|
||||
namespace QtCommon::FS {
|
||||
|
||||
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to);
|
||||
u64 GetRyujinxSaveID(const u64 &program_id);
|
||||
|
||||
/// @brief {eden, ryu}
|
||||
std::optional<std::pair<std::filesystem::path, std::filesystem::path>> GetEmuPaths(
|
||||
const u64 program_id, const u64 save_id, const std::string &user_id);
|
||||
const std::filesystem::path GetRyujinxSavePath(const std::filesystem::path &path_hint, const u64 &program_id);
|
||||
|
||||
/// returns FALSE if the dirs are NOT linked
|
||||
bool CheckUnlink(const std::filesystem::path &eden_dir, const std::filesystem::path &ryu_dir);
|
||||
bool CheckUnlink(const std::filesystem::path& eden_dir,
|
||||
const std::filesystem::path& ryu_dir);
|
||||
|
||||
} // namespace QtCommon::FS
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "shader_recompiler/exception.h"
|
||||
#include "shader_recompiler/frontend/maxwell/decode.h"
|
||||
@@ -45,7 +46,8 @@ Opcode Decode(u64 insn) {
|
||||
return Opcode::name;
|
||||
#include "maxwell.inc"
|
||||
#undef INST
|
||||
throw NotImplementedException("Invalid insn 0x{:016x}", insn);
|
||||
ASSERT_MSG(false, "Invalid insn 0x{:016x}", insn);
|
||||
return Opcode::NOP;
|
||||
}
|
||||
|
||||
} // namespace Shader::Maxwell
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -29,7 +32,7 @@ void TranslatorVisitor::MEMBAR(u64 inst) {
|
||||
}
|
||||
}
|
||||
|
||||
void TranslatorVisitor::DEPBAR() {
|
||||
void TranslatorVisitor::DEPBAR(u64) {
|
||||
// DEPBAR is a no-op
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -32,7 +35,7 @@ void ExitFragment(TranslatorVisitor& v) {
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void TranslatorVisitor::EXIT() {
|
||||
void TranslatorVisitor::EXIT(u64) {
|
||||
switch (env.ShaderStage()) {
|
||||
case Stage::Fragment:
|
||||
ExitFragment(*this);
|
||||
|
||||
@@ -56,293 +56,14 @@ enum class FPCompareOp : u64 {
|
||||
T,
|
||||
};
|
||||
|
||||
class TranslatorVisitor {
|
||||
public:
|
||||
struct TranslatorVisitor {
|
||||
explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {}
|
||||
|
||||
Environment& env;
|
||||
IR::IREmitter ir;
|
||||
|
||||
void AL2P(u64 insn);
|
||||
void ALD(u64 insn);
|
||||
void AST(u64 insn);
|
||||
void ATOM_cas(u64 insn);
|
||||
void ATOM(u64 insn);
|
||||
void ATOMS_cas(u64 insn);
|
||||
void ATOMS(u64 insn);
|
||||
void B2R(u64 insn);
|
||||
void BAR(u64 insn);
|
||||
void BFE_reg(u64 insn);
|
||||
void BFE_cbuf(u64 insn);
|
||||
void BFE_imm(u64 insn);
|
||||
void BFI_reg(u64 insn);
|
||||
void BFI_rc(u64 insn);
|
||||
void BFI_cr(u64 insn);
|
||||
void BFI_imm(u64 insn);
|
||||
void BPT(u64 insn);
|
||||
void BRA(u64 insn);
|
||||
void BRK(u64 insn);
|
||||
void BRX(u64 insn);
|
||||
void CAL();
|
||||
void CCTL(u64 insn);
|
||||
void CCTLL(u64 insn);
|
||||
void CCTLT(u64 insn);
|
||||
void CONT(u64 insn);
|
||||
void CS2R(u64 insn);
|
||||
void CSET(u64 insn);
|
||||
void CSETP(u64 insn);
|
||||
void DADD_reg(u64 insn);
|
||||
void DADD_cbuf(u64 insn);
|
||||
void DADD_imm(u64 insn);
|
||||
void DEPBAR();
|
||||
void DFMA_reg(u64 insn);
|
||||
void DFMA_rc(u64 insn);
|
||||
void DFMA_cr(u64 insn);
|
||||
void DFMA_imm(u64 insn);
|
||||
void DMNMX_reg(u64 insn);
|
||||
void DMNMX_cbuf(u64 insn);
|
||||
void DMNMX_imm(u64 insn);
|
||||
void DMUL_reg(u64 insn);
|
||||
void DMUL_cbuf(u64 insn);
|
||||
void DMUL_imm(u64 insn);
|
||||
void DSET_reg(u64 insn);
|
||||
void DSET_cbuf(u64 insn);
|
||||
void DSET_imm(u64 insn);
|
||||
void DSETP_reg(u64 insn);
|
||||
void DSETP_cbuf(u64 insn);
|
||||
void DSETP_imm(u64 insn);
|
||||
void EXIT();
|
||||
void F2F_reg(u64 insn);
|
||||
void F2F_cbuf(u64 insn);
|
||||
void F2F_imm(u64 insn);
|
||||
void F2I_reg(u64 insn);
|
||||
void F2I_cbuf(u64 insn);
|
||||
void F2I_imm(u64 insn);
|
||||
void FADD_reg(u64 insn);
|
||||
void FADD_cbuf(u64 insn);
|
||||
void FADD_imm(u64 insn);
|
||||
void FADD32I(u64 insn);
|
||||
void FCHK_reg(u64 insn);
|
||||
void FCHK_cbuf(u64 insn);
|
||||
void FCHK_imm(u64 insn);
|
||||
void FCMP_reg(u64 insn);
|
||||
void FCMP_rc(u64 insn);
|
||||
void FCMP_cr(u64 insn);
|
||||
void FCMP_imm(u64 insn);
|
||||
void FFMA_reg(u64 insn);
|
||||
void FFMA_rc(u64 insn);
|
||||
void FFMA_cr(u64 insn);
|
||||
void FFMA_imm(u64 insn);
|
||||
void FFMA32I(u64 insn);
|
||||
void FLO_reg(u64 insn);
|
||||
void FLO_cbuf(u64 insn);
|
||||
void FLO_imm(u64 insn);
|
||||
void FMNMX_reg(u64 insn);
|
||||
void FMNMX_cbuf(u64 insn);
|
||||
void FMNMX_imm(u64 insn);
|
||||
void FMUL_reg(u64 insn);
|
||||
void FMUL_cbuf(u64 insn);
|
||||
void FMUL_imm(u64 insn);
|
||||
void FMUL32I(u64 insn);
|
||||
void FSET_reg(u64 insn);
|
||||
void FSET_cbuf(u64 insn);
|
||||
void FSET_imm(u64 insn);
|
||||
void FSETP_reg(u64 insn);
|
||||
void FSETP_cbuf(u64 insn);
|
||||
void FSETP_imm(u64 insn);
|
||||
void FSWZADD(u64 insn);
|
||||
void GETCRSPTR(u64 insn);
|
||||
void GETLMEMBASE(u64 insn);
|
||||
void HADD2_reg(u64 insn);
|
||||
void HADD2_cbuf(u64 insn);
|
||||
void HADD2_imm(u64 insn);
|
||||
void HADD2_32I(u64 insn);
|
||||
void HFMA2_reg(u64 insn);
|
||||
void HFMA2_rc(u64 insn);
|
||||
void HFMA2_cr(u64 insn);
|
||||
void HFMA2_imm(u64 insn);
|
||||
void HFMA2_32I(u64 insn);
|
||||
void HMUL2_reg(u64 insn);
|
||||
void HMUL2_cbuf(u64 insn);
|
||||
void HMUL2_imm(u64 insn);
|
||||
void HMUL2_32I(u64 insn);
|
||||
void HSET2_reg(u64 insn);
|
||||
void HSET2_cbuf(u64 insn);
|
||||
void HSET2_imm(u64 insn);
|
||||
void HSETP2_reg(u64 insn);
|
||||
void HSETP2_cbuf(u64 insn);
|
||||
void HSETP2_imm(u64 insn);
|
||||
void I2F_reg(u64 insn);
|
||||
void I2F_cbuf(u64 insn);
|
||||
void I2F_imm(u64 insn);
|
||||
void I2I_reg(u64 insn);
|
||||
void I2I_cbuf(u64 insn);
|
||||
void I2I_imm(u64 insn);
|
||||
void IADD_reg(u64 insn);
|
||||
void IADD_cbuf(u64 insn);
|
||||
void IADD_imm(u64 insn);
|
||||
void IADD3_reg(u64 insn);
|
||||
void IADD3_cbuf(u64 insn);
|
||||
void IADD3_imm(u64 insn);
|
||||
void IADD32I(u64 insn);
|
||||
void ICMP_reg(u64 insn);
|
||||
void ICMP_rc(u64 insn);
|
||||
void ICMP_cr(u64 insn);
|
||||
void ICMP_imm(u64 insn);
|
||||
void IDE(u64 insn);
|
||||
void IDP_reg(u64 insn);
|
||||
void IDP_imm(u64 insn);
|
||||
void IMAD_reg(u64 insn);
|
||||
void IMAD_rc(u64 insn);
|
||||
void IMAD_cr(u64 insn);
|
||||
void IMAD_imm(u64 insn);
|
||||
void IMAD32I(u64 insn);
|
||||
void IMADSP_reg(u64 insn);
|
||||
void IMADSP_rc(u64 insn);
|
||||
void IMADSP_cr(u64 insn);
|
||||
void IMADSP_imm(u64 insn);
|
||||
void IMNMX_reg(u64 insn);
|
||||
void IMNMX_cbuf(u64 insn);
|
||||
void IMNMX_imm(u64 insn);
|
||||
void IMUL_reg(u64 insn);
|
||||
void IMUL_cbuf(u64 insn);
|
||||
void IMUL_imm(u64 insn);
|
||||
void IMUL32I(u64 insn);
|
||||
void IPA(u64 insn);
|
||||
void ISBERD(u64 insn);
|
||||
void ISCADD_reg(u64 insn);
|
||||
void ISCADD_cbuf(u64 insn);
|
||||
void ISCADD_imm(u64 insn);
|
||||
void ISCADD32I(u64 insn);
|
||||
void ISET_reg(u64 insn);
|
||||
void ISET_cbuf(u64 insn);
|
||||
void ISET_imm(u64 insn);
|
||||
void ISETP_reg(u64 insn);
|
||||
void ISETP_cbuf(u64 insn);
|
||||
void ISETP_imm(u64 insn);
|
||||
void JCAL(u64 insn);
|
||||
void JMP(u64 insn);
|
||||
void JMX(u64 insn);
|
||||
void KIL();
|
||||
void LD(u64 insn);
|
||||
void LDC(u64 insn);
|
||||
void LDG(u64 insn);
|
||||
void LDL(u64 insn);
|
||||
void LDS(u64 insn);
|
||||
void LEA_hi_reg(u64 insn);
|
||||
void LEA_hi_cbuf(u64 insn);
|
||||
void LEA_lo_reg(u64 insn);
|
||||
void LEA_lo_cbuf(u64 insn);
|
||||
void LEA_lo_imm(u64 insn);
|
||||
void LEPC(u64 insn);
|
||||
void LONGJMP(u64 insn);
|
||||
void LOP_reg(u64 insn);
|
||||
void LOP_cbuf(u64 insn);
|
||||
void LOP_imm(u64 insn);
|
||||
void LOP3_reg(u64 insn);
|
||||
void LOP3_cbuf(u64 insn);
|
||||
void LOP3_imm(u64 insn);
|
||||
void LOP32I(u64 insn);
|
||||
void MEMBAR(u64 insn);
|
||||
void MOV_reg(u64 insn);
|
||||
void MOV_cbuf(u64 insn);
|
||||
void MOV_imm(u64 insn);
|
||||
void MOV32I(u64 insn);
|
||||
void MUFU(u64 insn);
|
||||
void NOP(u64 insn);
|
||||
void OUT_reg(u64 insn);
|
||||
void OUT_cbuf(u64 insn);
|
||||
void OUT_imm(u64 insn);
|
||||
void P2R_reg(u64 insn);
|
||||
void P2R_cbuf(u64 insn);
|
||||
void P2R_imm(u64 insn);
|
||||
void PBK();
|
||||
void PCNT();
|
||||
void PEXIT(u64 insn);
|
||||
void PIXLD(u64 insn);
|
||||
void PLONGJMP(u64 insn);
|
||||
void POPC_reg(u64 insn);
|
||||
void POPC_cbuf(u64 insn);
|
||||
void POPC_imm(u64 insn);
|
||||
void PRET(u64 insn);
|
||||
void PRMT_reg(u64 insn);
|
||||
void PRMT_rc(u64 insn);
|
||||
void PRMT_cr(u64 insn);
|
||||
void PRMT_imm(u64 insn);
|
||||
void PSET(u64 insn);
|
||||
void PSETP(u64 insn);
|
||||
void R2B(u64 insn);
|
||||
void R2P_reg(u64 insn);
|
||||
void R2P_cbuf(u64 insn);
|
||||
void R2P_imm(u64 insn);
|
||||
void RAM(u64 insn);
|
||||
void RED(u64 insn);
|
||||
void RET(u64 insn);
|
||||
void RRO_reg(u64 insn);
|
||||
void RRO_cbuf(u64 insn);
|
||||
void RRO_imm(u64 insn);
|
||||
void RTT(u64 insn);
|
||||
void S2R(u64 insn);
|
||||
void SAM(u64 insn);
|
||||
void SEL_reg(u64 insn);
|
||||
void SEL_cbuf(u64 insn);
|
||||
void SEL_imm(u64 insn);
|
||||
void SETCRSPTR(u64 insn);
|
||||
void SETLMEMBASE(u64 insn);
|
||||
void SHF_l_reg(u64 insn);
|
||||
void SHF_l_imm(u64 insn);
|
||||
void SHF_r_reg(u64 insn);
|
||||
void SHF_r_imm(u64 insn);
|
||||
void SHFL(u64 insn);
|
||||
void SHL_reg(u64 insn);
|
||||
void SHL_cbuf(u64 insn);
|
||||
void SHL_imm(u64 insn);
|
||||
void SHR_reg(u64 insn);
|
||||
void SHR_cbuf(u64 insn);
|
||||
void SHR_imm(u64 insn);
|
||||
void SSY();
|
||||
void ST(u64 insn);
|
||||
void STG(u64 insn);
|
||||
void STL(u64 insn);
|
||||
void STP(u64 insn);
|
||||
void STS(u64 insn);
|
||||
void SUATOM(u64 insn);
|
||||
void SUATOM_cas(u64 insn);
|
||||
void SULD(u64 insn);
|
||||
void SURED(u64 insn);
|
||||
void SUST(u64 insn);
|
||||
void SYNC(u64 insn);
|
||||
void TEX(u64 insn);
|
||||
void TEX_b(u64 insn);
|
||||
void TEXS(u64 insn);
|
||||
void TLD(u64 insn);
|
||||
void TLD_b(u64 insn);
|
||||
void TLD4(u64 insn);
|
||||
void TLD4_b(u64 insn);
|
||||
void TLD4S(u64 insn);
|
||||
void TLDS(u64 insn);
|
||||
void TMML(u64 insn);
|
||||
void TMML_b(u64 insn);
|
||||
void TXA(u64 insn);
|
||||
void TXD(u64 insn);
|
||||
void TXD_b(u64 insn);
|
||||
void TXQ(u64 insn);
|
||||
void TXQ_b(u64 insn);
|
||||
void VABSDIFF(u64 insn);
|
||||
void VABSDIFF4(u64 insn);
|
||||
void VADD(u64 insn);
|
||||
void VMAD(u64 insn);
|
||||
void VMNMX(u64 insn);
|
||||
void VOTE(u64 insn);
|
||||
void VOTE_vtg(u64 insn);
|
||||
void VSET(u64 insn);
|
||||
void VSETP(u64 insn);
|
||||
void VSHL(u64 insn);
|
||||
void VSHR(u64 insn);
|
||||
void XMAD_reg(u64 insn);
|
||||
void XMAD_rc(u64 insn);
|
||||
void XMAD_cr(u64 insn);
|
||||
void XMAD_imm(u64 insn);
|
||||
#define INST(name, cute, encode) void name(u64 insn);
|
||||
#include "shader_recompiler/frontend/maxwell/maxwell.inc"
|
||||
#undef INST
|
||||
|
||||
[[nodiscard]] IR::U32 X(IR::Reg reg);
|
||||
[[nodiscard]] IR::U64 L(IR::Reg reg);
|
||||
|
||||
@@ -39,7 +39,7 @@ void TranslatorVisitor::BRK(u64) {
|
||||
ThrowNotImplemented(Opcode::BRK);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::CAL() {
|
||||
void TranslatorVisitor::CAL(u64) {
|
||||
// CAL is a no-op
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ void TranslatorVisitor::JMP(u64) {
|
||||
ThrowNotImplemented(Opcode::JMP);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::KIL() {
|
||||
void TranslatorVisitor::KIL(u64) {
|
||||
// KIL is a no-op
|
||||
}
|
||||
|
||||
@@ -172,14 +172,14 @@ void TranslatorVisitor::LONGJMP(u64) {
|
||||
}
|
||||
|
||||
void TranslatorVisitor::NOP(u64) {
|
||||
// NOP is No-Op.
|
||||
// NOP is a no-op
|
||||
}
|
||||
|
||||
void TranslatorVisitor::PBK() {
|
||||
void TranslatorVisitor::PBK(u64) {
|
||||
// PBK is a no-op
|
||||
}
|
||||
|
||||
void TranslatorVisitor::PCNT() {
|
||||
void TranslatorVisitor::PCNT(u64) {
|
||||
// PCNT is a no-op
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ void TranslatorVisitor::SETLMEMBASE(u64) {
|
||||
ThrowNotImplemented(Opcode::SETLMEMBASE);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::SSY() {
|
||||
void TranslatorVisitor::SSY(u64) {
|
||||
// SSY is a no-op
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -10,40 +13,17 @@
|
||||
|
||||
namespace Shader::Maxwell {
|
||||
|
||||
template <auto method>
|
||||
static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) {
|
||||
using MethodType = decltype(method);
|
||||
if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, Location, u64>) {
|
||||
(visitor.*method)(pc, insn);
|
||||
} else if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, u64>) {
|
||||
(visitor.*method)(insn);
|
||||
} else {
|
||||
(visitor.*method)();
|
||||
}
|
||||
}
|
||||
|
||||
void Translate(Environment& env, IR::Block* block, u32 location_begin, u32 location_end) {
|
||||
if (location_begin == location_end) {
|
||||
return;
|
||||
}
|
||||
TranslatorVisitor visitor{env, *block};
|
||||
for (Location pc = location_begin; pc != location_end; ++pc) {
|
||||
const u64 insn{env.ReadInstruction(pc.Offset())};
|
||||
try {
|
||||
const Opcode opcode{Decode(insn)};
|
||||
if (location_begin != location_end) {
|
||||
TranslatorVisitor visitor{env, *block};
|
||||
for (Location pc = location_begin; pc != location_end; ++pc) {
|
||||
u64 const insn = env.ReadInstruction(pc.Offset());
|
||||
Opcode const opcode = Decode(insn);
|
||||
switch (opcode) {
|
||||
#define INST(name, cute, mask) \
|
||||
case Opcode::name: \
|
||||
Invoke<&TranslatorVisitor::name>(visitor, pc, insn); \
|
||||
break;
|
||||
#define INST(name, cute, mask) case Opcode::name: visitor.name(insn); break;
|
||||
#include "shader_recompiler/frontend/maxwell/maxwell.inc"
|
||||
#undef OPCODE
|
||||
default:
|
||||
throw LogicError("Invalid opcode {}", opcode);
|
||||
}
|
||||
} catch (Exception& exception) {
|
||||
exception.Prepend(fmt::format("Translate {}: ", Decode(insn)));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,10 +384,6 @@ if (ARCHITECTURE_x86_64)
|
||||
macro/macro_jit_x64.h
|
||||
)
|
||||
target_link_libraries(video_core PUBLIC xbyak::xbyak)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options(video_core PRIVATE -msse4.1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
|
||||
@@ -23,9 +23,7 @@ namespace VideoCommon::GPUThread {
|
||||
static void RunThread(std::stop_token stop_token, Core::System& system,
|
||||
VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
|
||||
Tegra::Control::Scheduler& scheduler, SynchState& state) {
|
||||
std::string name = "GPU";
|
||||
|
||||
Common::SetCurrentThreadName(name.c_str());
|
||||
Common::SetCurrentThreadName("GPU");
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
|
||||
system.RegisterHostThread();
|
||||
|
||||
|
||||
@@ -945,6 +945,7 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
|
||||
|
||||
void RasterizerVulkan::UpdateDynamicStates() {
|
||||
auto& regs = maxwell3d->regs;
|
||||
|
||||
UpdateViewportsState(regs);
|
||||
UpdateScissorsState(regs);
|
||||
UpdateDepthBias(regs);
|
||||
@@ -952,7 +953,19 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
UpdateDepthBounds(regs);
|
||||
UpdateStencilFaces(regs);
|
||||
UpdateLineWidth(regs);
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
|
||||
const u8 dynamic_state = Settings::values.dyna_state.GetValue();
|
||||
|
||||
auto features = DynamicFeatures{
|
||||
.has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0,
|
||||
.has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1,
|
||||
.has_extended_dynamic_state_2_extra = device.IsExtExtendedDynamicState2ExtrasSupported() && dynamic_state > 1,
|
||||
.has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2,
|
||||
.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2,
|
||||
.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),
|
||||
};
|
||||
|
||||
if (features.has_extended_dynamic_state) {
|
||||
UpdateCullMode(regs);
|
||||
UpdateDepthCompareOp(regs);
|
||||
UpdateFrontFace(regs);
|
||||
@@ -963,13 +976,14 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
UpdateDepthTestEnable(regs);
|
||||
UpdateDepthWriteEnable(regs);
|
||||
UpdateStencilTestEnable(regs);
|
||||
if (device.IsExtExtendedDynamicState2Supported()) {
|
||||
|
||||
if (features.has_extended_dynamic_state_2) {
|
||||
UpdatePrimitiveRestartEnable(regs);
|
||||
UpdateRasterizerDiscardEnable(regs);
|
||||
UpdateDepthBiasEnable(regs);
|
||||
}
|
||||
|
||||
if (device.IsExtExtendedDynamicState3Supported()) {
|
||||
if (features.has_extended_dynamic_state_3_enables) {
|
||||
using namespace Tegra::Engines;
|
||||
|
||||
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
||||
@@ -996,15 +1010,20 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
UpdateDepthClampEnable(regs);
|
||||
}
|
||||
}
|
||||
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
|
||||
if (features.has_extended_dynamic_state_2_extra) {
|
||||
UpdateLogicOp(regs);
|
||||
}
|
||||
if (device.IsExtExtendedDynamicState3Supported()) {
|
||||
if (features.has_extended_dynamic_state_3_enables) {
|
||||
UpdateBlending(regs);
|
||||
UpdateLineStippleEnable(regs);
|
||||
UpdateConservativeRasterizationMode(regs);
|
||||
}
|
||||
}
|
||||
if (device.IsExtVertexInputDynamicStateSupported()) {
|
||||
UpdateVertexInput(regs);
|
||||
if (features.has_dynamic_vertex_input) {
|
||||
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline();
|
||||
gp && gp->HasDynamicVertexInput()) {
|
||||
UpdateVertexInput(regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -10,7 +13,7 @@
|
||||
namespace VideoCommon {
|
||||
|
||||
constexpr size_t NUM_RT = 8;
|
||||
constexpr size_t MAX_MIP_LEVELS = 14;
|
||||
constexpr size_t MAX_MIP_LEVELS = 16;
|
||||
|
||||
constexpr Common::SlotId CORRUPT_ID{0xfffffffe};
|
||||
|
||||
|
||||
@@ -646,9 +646,10 @@ LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
|
||||
if (info.type == ImageType::Linear) {
|
||||
return {};
|
||||
}
|
||||
ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS));
|
||||
if (info.resources.levels > static_cast<s32>(MAX_MIP_LEVELS))
|
||||
if (info.resources.levels > static_cast<s32>(MAX_MIP_LEVELS)) {
|
||||
LOG_ERROR(HW_GPU, "Image has too many mip levels={}, maximum supported is={}", info.resources.levels, MAX_MIP_LEVELS);
|
||||
return {};
|
||||
}
|
||||
const LevelInfo level_info = MakeLevelInfo(info);
|
||||
LevelArray offsets{};
|
||||
u32 offset = 0;
|
||||
|
||||
@@ -494,25 +494,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
CollectPhysicalMemoryInfo();
|
||||
CollectToolingInfo();
|
||||
|
||||
const bool force_extensions = Settings::values.force_unsupported_extensions.GetValue();
|
||||
|
||||
if (force_extensions) {
|
||||
LOG_WARNING(Render_Vulkan, "Force Unsupported Extensions is enabled - bypassing ALL driver workarounds and safety checks!");
|
||||
}
|
||||
|
||||
if ((is_qualcomm || is_turnip) && !force_extensions) {
|
||||
if (is_qualcomm || is_turnip) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
|
||||
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
|
||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
//RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
|
||||
//VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (is_qualcomm) {
|
||||
if (!force_extensions) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
||||
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Disabling shader float controls and 64-bit integer features on Qualcomm proprietary drivers");
|
||||
@@ -553,9 +545,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math");
|
||||
features.shader_float16_int8.shaderFloat16 = false;
|
||||
} else if (arch <= NvidiaArchitecture::Arch_Volta) {
|
||||
if (nv_major_version < 527 && !force_extensions) {
|
||||
if (nv_major_version < 527) {
|
||||
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (nv_major_version >= 510) {
|
||||
@@ -566,67 +558,79 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (extensions.extended_dynamic_state && is_radv) {
|
||||
// Mask driver version variant
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0) && !force_extensions) {
|
||||
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state,
|
||||
features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
//RemoveExtensionFeature(extensions.extended_dynamic_state,
|
||||
//features.extended_dynamic_state,
|
||||
//VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state2 && is_radv) {
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1) && !force_extensions) {
|
||||
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
|
||||
LOG_WARNING(
|
||||
Render_Vulkan,
|
||||
"RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
// RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
// features.extended_dynamic_state2,
|
||||
// VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state2 && is_qualcomm) {
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version >= VK_MAKE_API_VERSION(0, 0, 676, 0) &&
|
||||
version < VK_MAKE_API_VERSION(0, 0, 680, 0) && !force_extensions) {
|
||||
version < VK_MAKE_API_VERSION(0, 0, 680, 0)) {
|
||||
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
//RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
//features.extended_dynamic_state2,
|
||||
//VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state3 && is_radv && !force_extensions) {
|
||||
if (extensions.extended_dynamic_state3 && is_radv) {
|
||||
LOG_WARNING(Render_Vulkan, "RADV has broken extendedDynamicState3ColorBlendEquation");
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = true;
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = true;
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_blending = true;
|
||||
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(0, 23, 1, 0) && !force_extensions) {
|
||||
if (version < VK_MAKE_API_VERSION(0, 23, 1, 0)) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"RADV versions older than 23.1.0 have broken depth clamp dynamic state");
|
||||
features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = true;
|
||||
dynamic_state3_enables = false;
|
||||
dynamic_state3_enables = true;
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state3 &&
|
||||
(is_amd_driver || driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY) && !force_extensions) {
|
||||
if (extensions.extended_dynamic_state3 && (is_amd_driver || driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY)) {
|
||||
// AMD and Samsung drivers have broken extendedDynamicState3ColorBlendEquation
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"AMD and Samsung drivers have broken extendedDynamicState3ColorBlendEquation");
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = true;
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = true;
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_blending = true;
|
||||
}
|
||||
if (extensions.vertex_input_dynamic_state && is_qualcomm && !force_extensions) {
|
||||
if (extensions.vertex_input_dynamic_state && is_radv) {
|
||||
// TODO(ameerj): Blacklist only offending driver versions
|
||||
// TODO(ameerj): Confirm if RDNA1 is affected
|
||||
const bool is_rdna2 =
|
||||
supported_extensions.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
|
||||
if (is_rdna2) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
|
||||
// RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
// features.vertex_input_dynamic_state,
|
||||
// VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
|
||||
// Qualcomm drivers do not properly support vertex_input_dynamic_state.
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm drivers have broken VK_EXT_vertex_input_dynamic_state");
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
// features.vertex_input_dynamic_state,
|
||||
// VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
sets_per_pool = 64;
|
||||
@@ -656,13 +660,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions.vertex_input_dynamic_state && is_intel_windows && !force_extensions) {
|
||||
if (extensions.vertex_input_dynamic_state && is_intel_windows) {
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
|
||||
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
//features.vertex_input_dynamic_state,
|
||||
//VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
|
||||
@@ -684,19 +688,19 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (extensions.push_descriptor && is_intel_anv) {
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version >= VK_MAKE_API_VERSION(0, 22, 3, 0) &&
|
||||
version < VK_MAKE_API_VERSION(0, 23, 2, 0) && !force_extensions) {
|
||||
version < VK_MAKE_API_VERSION(0, 23, 2, 0)) {
|
||||
// Disable VK_KHR_push_descriptor due to
|
||||
// mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
} else if (extensions.push_descriptor && is_nvidia) {
|
||||
const auto arch = GetNvidiaArch();
|
||||
if (arch <= NvidiaArchitecture::Arch_Pascal && !force_extensions) {
|
||||
if (arch <= NvidiaArchitecture::Arch_Pascal) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Pascal and older architectures have broken VK_KHR_push_descriptor");
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,13 +725,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (!extensions.extended_dynamic_state2 && extensions.extended_dynamic_state3 && !force_extensions) {
|
||||
if (!extensions.extended_dynamic_state2 && extensions.extended_dynamic_state3) {
|
||||
LOG_INFO(Render_Vulkan,
|
||||
"Removing extendedDynamicState3 due to missing extendedDynamicState2");
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_enables = false;
|
||||
dynamic_state3_blending = true;
|
||||
dynamic_state3_enables = true;
|
||||
}
|
||||
|
||||
// Mesa Intel drivers on UHD 620 have broken EDS causing extreme flickering - unknown if it affects other iGPUs
|
||||
@@ -739,6 +743,25 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
Settings::values.dyna_state.SetValue(0);
|
||||
}
|
||||
|
||||
if (Settings::values.dyna_state.GetValue() == 0) {
|
||||
must_emulate_scaled_formats = true;
|
||||
LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON");
|
||||
|
||||
// Disable dynamic state 1-3 and all extensions
|
||||
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_enables = false;
|
||||
|
||||
LOG_INFO(Render_Vulkan, "All dynamic state extensions and features have been disabled");
|
||||
} else {
|
||||
must_emulate_scaled_formats = false;
|
||||
LOG_INFO(Render_Vulkan, "Dynamic state is enabled (dyna_state = 1-3), disabling scaled format emulation");
|
||||
}
|
||||
|
||||
logical = vk::Device::Create(physical, queue_cis, ExtensionListForVulkan(loaded_extensions), first_next, dld);
|
||||
|
||||
graphics_queue = logical.GetQueue(graphics_family);
|
||||
@@ -1203,7 +1226,7 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
|
||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_extended_dynamic_state
|
||||
/* */ // VK_EXT_extended_dynamic_state
|
||||
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
|
||||
features.extended_dynamic_state,
|
||||
|
||||
@@ -12,6 +12,8 @@ if (YUZU_USE_BUNDLED_QT AND PLATFORM_LINUX)
|
||||
set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/bin/lib/")
|
||||
endif()
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets)
|
||||
|
||||
add_executable(yuzu
|
||||
Info.plist
|
||||
about_dialog.cpp
|
||||
@@ -156,8 +158,6 @@ add_executable(yuzu
|
||||
debugger/console.h
|
||||
debugger/controller.cpp
|
||||
debugger/controller.h
|
||||
debugger/wait_tree.cpp
|
||||
debugger/wait_tree.h
|
||||
|
||||
game_list.cpp
|
||||
game_list.h
|
||||
@@ -171,9 +171,9 @@ add_executable(yuzu
|
||||
loading_screen.cpp
|
||||
loading_screen.h
|
||||
loading_screen.ui
|
||||
|
||||
main.cpp
|
||||
main.h
|
||||
main.ui
|
||||
|
||||
multiplayer/chat_room.cpp
|
||||
multiplayer/chat_room.h
|
||||
multiplayer/chat_room.ui
|
||||
@@ -237,6 +237,7 @@ add_executable(yuzu
|
||||
data_dialog.h data_dialog.cpp data_dialog.ui
|
||||
data_widget.ui
|
||||
ryujinx_dialog.h ryujinx_dialog.cpp ryujinx_dialog.ui
|
||||
main_window.h main_window.cpp
|
||||
)
|
||||
|
||||
set_target_properties(yuzu PROPERTIES OUTPUT_NAME "eden")
|
||||
@@ -443,6 +444,7 @@ endif()
|
||||
|
||||
if (YUZU_ROOM)
|
||||
target_link_libraries(yuzu PRIVATE yuzu-room)
|
||||
target_link_libraries(yuzu PRIVATE Qt6::Widgets)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(yuzu)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -18,7 +21,7 @@
|
||||
#include "web_service/web_backend.h"
|
||||
#endif
|
||||
#include "yuzu/applets/qt_amiibo_settings.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
|
||||
QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,
|
||||
Core::Frontend::CabinetParameters parameters_,
|
||||
@@ -244,12 +247,12 @@ void QtAmiiboSettingsDialog::SetSettingsDescription() {
|
||||
}
|
||||
}
|
||||
|
||||
QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) {
|
||||
QtAmiiboSettings::QtAmiiboSettings(MainWindow& parent) {
|
||||
connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent,
|
||||
&GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection);
|
||||
&MainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection);
|
||||
connect(this, &QtAmiiboSettings::MainWindowRequestExit, &parent,
|
||||
&GMainWindow::AmiiboSettingsRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &GMainWindow::AmiiboSettingsFinished, this,
|
||||
&MainWindow::AmiiboSettingsRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &MainWindow::AmiiboSettingsFinished, this,
|
||||
&QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,7 +11,7 @@
|
||||
#include <QDialog>
|
||||
#include "core/frontend/applets/cabinet.h"
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDialogButtonBox;
|
||||
@@ -65,7 +68,7 @@ class QtAmiiboSettings final : public QObject, public Core::Frontend::CabinetApp
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtAmiiboSettings(GMainWindow& parent);
|
||||
explicit QtAmiiboSettings(MainWindow& parent);
|
||||
~QtAmiiboSettings() override;
|
||||
|
||||
void Close() const override;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "yuzu/configuration/configure_motion_touch.h"
|
||||
#include "yuzu/configuration/configure_vibration.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
|
||||
namespace {
|
||||
@@ -753,12 +753,12 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
|
||||
}
|
||||
}
|
||||
|
||||
QtControllerSelector::QtControllerSelector(GMainWindow& parent) {
|
||||
QtControllerSelector::QtControllerSelector(MainWindow& parent) {
|
||||
connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent,
|
||||
&GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection);
|
||||
&MainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection);
|
||||
connect(this, &QtControllerSelector::MainWindowRequestExit, &parent,
|
||||
&GMainWindow::ControllerSelectorRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this,
|
||||
&MainWindow::ControllerSelectorRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &MainWindow::ControllerSelectorReconfigureFinished, this,
|
||||
&QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,7 +11,7 @@
|
||||
#include <QDialog>
|
||||
#include "core/frontend/applets/controller.h"
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDialogButtonBox;
|
||||
@@ -163,7 +166,7 @@ class QtControllerSelector final : public QObject, public Core::Frontend::Contro
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtControllerSelector(GMainWindow& parent);
|
||||
explicit QtControllerSelector(MainWindow& parent);
|
||||
~QtControllerSelector() override;
|
||||
|
||||
void Close() const override;
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <QDateTime>
|
||||
#include "yuzu/applets/qt_error.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
|
||||
QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
|
||||
QtErrorDisplay::QtErrorDisplay(MainWindow& parent) {
|
||||
connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent,
|
||||
&GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection);
|
||||
&MainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection);
|
||||
connect(this, &QtErrorDisplay::MainWindowRequestExit, &parent,
|
||||
&GMainWindow::ErrorDisplayRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &GMainWindow::ErrorDisplayFinished, this,
|
||||
&MainWindow::ErrorDisplayRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &MainWindow::ErrorDisplayFinished, this,
|
||||
&QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -7,13 +10,13 @@
|
||||
|
||||
#include "core/frontend/applets/error.h"
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
|
||||
class QtErrorDisplay final : public QObject, public Core::Frontend::ErrorApplet {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtErrorDisplay(GMainWindow& parent);
|
||||
explicit QtErrorDisplay(MainWindow& parent);
|
||||
~QtErrorDisplay() override;
|
||||
|
||||
void Close() const override;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "yuzu/applets/qt_profile_select.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
|
||||
namespace {
|
||||
@@ -230,12 +230,12 @@ void QtProfileSelectionDialog::SetDialogPurpose(
|
||||
}
|
||||
}
|
||||
|
||||
QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
|
||||
QtProfileSelector::QtProfileSelector(MainWindow& parent) {
|
||||
connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent,
|
||||
&GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection);
|
||||
&MainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection);
|
||||
connect(this, &QtProfileSelector::MainWindowRequestExit, &parent,
|
||||
&GMainWindow::ProfileSelectorRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this,
|
||||
&MainWindow::ProfileSelectorRequestExit, Qt::QueuedConnection);
|
||||
connect(&parent, &MainWindow::ProfileSelectorFinishedSelection, this,
|
||||
&QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -9,7 +12,7 @@
|
||||
#include "core/frontend/applets/profile_select.h"
|
||||
|
||||
class ControllerNavigation;
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
class QDialogButtonBox;
|
||||
class QGraphicsScene;
|
||||
class QLabel;
|
||||
@@ -69,7 +72,7 @@ class QtProfileSelector final : public QObject, public Core::Frontend::ProfileSe
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtProfileSelector(GMainWindow& parent);
|
||||
explicit QtProfileSelector(MainWindow& parent);
|
||||
~QtProfileSelector() override;
|
||||
|
||||
void Close() const override;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -15,7 +18,7 @@
|
||||
#include "hid_core/hid_types.h"
|
||||
#include "ui_qt_software_keyboard.h"
|
||||
#include "yuzu/applets/qt_software_keyboard.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
#include "yuzu/util/overlay_dialog.h"
|
||||
|
||||
namespace {
|
||||
@@ -1541,24 +1544,24 @@ void QtSoftwareKeyboardDialog::InputThread() {
|
||||
}
|
||||
}
|
||||
|
||||
QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {
|
||||
QtSoftwareKeyboard::QtSoftwareKeyboard(MainWindow& main_window) {
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection);
|
||||
&MainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection);
|
||||
connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window,
|
||||
&GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection);
|
||||
connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this,
|
||||
&MainWindow::SoftwareKeyboardExit, Qt::QueuedConnection);
|
||||
connect(&main_window, &MainWindow::SoftwareKeyboardSubmitNormalText, this,
|
||||
&QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection);
|
||||
connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this,
|
||||
connect(&main_window, &MainWindow::SoftwareKeyboardSubmitInlineText, this,
|
||||
&QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -27,7 +30,7 @@ namespace Ui {
|
||||
class QtSoftwareKeyboardDialog;
|
||||
}
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
|
||||
class QtSoftwareKeyboardDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
@@ -230,7 +233,7 @@ class QtSoftwareKeyboard final : public QObject, public Core::Frontend::Software
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtSoftwareKeyboard(GMainWindow& parent);
|
||||
explicit QtSoftwareKeyboard(MainWindow& parent);
|
||||
~QtSoftwareKeyboard() override;
|
||||
|
||||
void Close() const override {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -18,7 +21,7 @@
|
||||
#endif
|
||||
|
||||
#include "yuzu/applets/qt_web_browser.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
|
||||
#ifdef YUZU_USE_QT_WEB_ENGINE
|
||||
|
||||
@@ -391,14 +394,14 @@ void QtNXWebEngineView::FocusFirstLinkElement() {
|
||||
|
||||
#endif
|
||||
|
||||
QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
|
||||
QtWebBrowser::QtWebBrowser(MainWindow& main_window) {
|
||||
connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window,
|
||||
&GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
|
||||
&MainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
|
||||
connect(this, &QtWebBrowser::MainWindowRequestExit, &main_window,
|
||||
&GMainWindow::WebBrowserRequestExit, Qt::QueuedConnection);
|
||||
connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
|
||||
&MainWindow::WebBrowserRequestExit, Qt::QueuedConnection);
|
||||
connect(&main_window, &MainWindow::WebBrowserExtractOfflineRomFS, this,
|
||||
&QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
|
||||
connect(&main_window, &GMainWindow::WebBrowserClosed, this,
|
||||
connect(&main_window, &MainWindow::WebBrowserClosed, this,
|
||||
&QtWebBrowser::MainWindowWebBrowserClosed, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -14,7 +17,7 @@
|
||||
|
||||
#include "core/frontend/applets/web_browser.h"
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
class InputInterpreter;
|
||||
class UrlRequestInterceptor;
|
||||
|
||||
@@ -193,7 +196,7 @@ class QtWebBrowser final : public QObject, public Core::Frontend::WebBrowserAppl
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtWebBrowser(GMainWindow& parent);
|
||||
explicit QtWebBrowser(MainWindow& parent);
|
||||
~QtWebBrowser() override;
|
||||
|
||||
void Close() const override;
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "yuzu/bootmanager.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
|
||||
class QObject;
|
||||
@@ -272,7 +272,7 @@ struct NullRenderWidget : public RenderWidget {
|
||||
explicit NullRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {}
|
||||
};
|
||||
|
||||
GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||
GRenderWindow::GRenderWindow(MainWindow* parent, EmuThread* emu_thread_,
|
||||
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
|
||||
Core::System& system_)
|
||||
: QWidget(parent),
|
||||
@@ -290,11 +290,11 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||
strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland") ||
|
||||
QGuiApplication::platformName() == QStringLiteral("wayland-egl");
|
||||
|
||||
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
|
||||
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
|
||||
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &MainWindow::OnLoadComplete);
|
||||
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &MainWindow::OnExecuteProgram,
|
||||
Qt::QueuedConnection);
|
||||
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
|
||||
connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged);
|
||||
connect(this, &GRenderWindow::ExitSignal, parent, &MainWindow::OnExit, Qt::QueuedConnection);
|
||||
connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &MainWindow::OnTasStateChanged);
|
||||
|
||||
mouse_constrain_timer.setInterval(default_mouse_constrain_timeout);
|
||||
connect(&mouse_constrain_timer, &QTimer::timeout, this, &GRenderWindow::ConstrainMouse);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -29,7 +32,7 @@
|
||||
#include "common/thread.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
|
||||
class GMainWindow;
|
||||
class MainWindow;
|
||||
class QCamera;
|
||||
class QCameraImageCapture;
|
||||
class QCloseEvent;
|
||||
@@ -146,7 +149,7 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||
explicit GRenderWindow(MainWindow* parent, EmuThread* emu_thread_,
|
||||
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
|
||||
Core::System& system_);
|
||||
~GRenderWindow() override;
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "data_dialog.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "qt_common/util/content.h"
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
#include "ui_data_dialog.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
@@ -26,17 +25,18 @@ DataDialog::DataDialog(QWidget *parent)
|
||||
ui->setupUi(this);
|
||||
|
||||
// TODO: Should we make this a single widget that pulls data from a model?
|
||||
#define WIDGET(name) \
|
||||
#define WIDGET(label, name) \
|
||||
ui->page->addWidget(new DataWidget(FrontendCommon::DataManager::DataDir::name, \
|
||||
QtCommon::StringLookup::name##Tooltip, \
|
||||
QStringLiteral(#name), \
|
||||
this));
|
||||
this)); \
|
||||
ui->labels->addItem(label);
|
||||
|
||||
WIDGET(Saves)
|
||||
WIDGET(Shaders)
|
||||
WIDGET(UserNand)
|
||||
WIDGET(SysNand)
|
||||
WIDGET(Mods)
|
||||
WIDGET(tr("Shaders"), Shaders)
|
||||
WIDGET(tr("UserNAND"), UserNand)
|
||||
WIDGET(tr("SysNAND"), SysNand)
|
||||
WIDGET(tr("Mods"), Mods)
|
||||
WIDGET(tr("Saves"), Saves)
|
||||
|
||||
#undef WIDGET
|
||||
|
||||
@@ -82,7 +82,7 @@ void DataWidget::clear()
|
||||
{
|
||||
std::string user_id{};
|
||||
if (m_dir == FrontendCommon::DataManager::DataDir::Saves) {
|
||||
user_id = selectProfile();
|
||||
user_id = GetProfileIDString();
|
||||
}
|
||||
QtCommon::Content::ClearDataDir(m_dir, user_id);
|
||||
scan();
|
||||
@@ -92,7 +92,7 @@ void DataWidget::open()
|
||||
{
|
||||
std::string user_id{};
|
||||
if (m_dir == FrontendCommon::DataManager::DataDir::Saves) {
|
||||
user_id = selectProfile();
|
||||
user_id = GetProfileIDString();
|
||||
}
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
||||
QString::fromStdString(FrontendCommon::DataManager::GetDataDirString(m_dir, user_id))));
|
||||
@@ -102,7 +102,7 @@ void DataWidget::upload()
|
||||
{
|
||||
std::string user_id{};
|
||||
if (m_dir == FrontendCommon::DataManager::DataDir::Saves) {
|
||||
user_id = selectProfile();
|
||||
user_id = GetProfileIDString();
|
||||
}
|
||||
QtCommon::Content::ExportDataDir(m_dir, user_id, m_exportName);
|
||||
}
|
||||
@@ -111,7 +111,7 @@ void DataWidget::download()
|
||||
{
|
||||
std::string user_id{};
|
||||
if (m_dir == FrontendCommon::DataManager::DataDir::Saves) {
|
||||
user_id = selectProfile();
|
||||
user_id = GetProfileIDString();
|
||||
}
|
||||
QtCommon::Content::ImportDataDir(m_dir, user_id, std::bind(&DataWidget::scan, this));
|
||||
}
|
||||
@@ -131,37 +131,3 @@ void DataWidget::scan() {
|
||||
watcher->setFuture(
|
||||
QtConcurrent::run([this]() { return FrontendCommon::DataManager::DataDirSize(m_dir); }));
|
||||
}
|
||||
|
||||
std::string DataWidget::selectProfile()
|
||||
{
|
||||
const auto select_profile = [this] {
|
||||
const Core::Frontend::ProfileSelectParameters parameters{
|
||||
.mode = Service::AM::Frontend::UiMode::UserSelector,
|
||||
.invalid_uid_list = {},
|
||||
.display_options = {},
|
||||
.purpose = Service::AM::Frontend::UserSelectionPurpose::General,
|
||||
};
|
||||
QtProfileSelectionDialog dialog(*QtCommon::system, this, parameters);
|
||||
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint
|
||||
| Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
|
||||
if (dialog.exec() == QDialog::Rejected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dialog.GetIndex();
|
||||
};
|
||||
|
||||
const auto index = select_profile();
|
||||
if (index == -1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const auto uuid = QtCommon::system->GetProfileManager().GetUser(static_cast<std::size_t>(index));
|
||||
ASSERT(uuid);
|
||||
|
||||
const auto user_id = uuid->AsU128();
|
||||
|
||||
return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]);
|
||||
}
|
||||
|
||||
@@ -36,31 +36,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Saves</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Shaders</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>UserNAND</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SysNAND</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mods</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -1,434 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include "yuzu/debugger/wait_tree.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
|
||||
#include "core/arm/debug.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_class_token.h"
|
||||
#include "core/hle/kernel/k_handle_table.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_synchronization_object.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/svc_common.h"
|
||||
#include "core/hle/kernel/svc_types.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
|
||||
{Qt::GlobalColor::darkGreen, Qt::GlobalColor::green},
|
||||
{Qt::GlobalColor::darkBlue, Qt::GlobalColor::cyan},
|
||||
{Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray},
|
||||
{Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray},
|
||||
{Qt::GlobalColor::darkRed, Qt::GlobalColor::red},
|
||||
{Qt::GlobalColor::darkYellow, Qt::GlobalColor::yellow},
|
||||
{Qt::GlobalColor::red, Qt::GlobalColor::red},
|
||||
{Qt::GlobalColor::darkCyan, Qt::GlobalColor::cyan},
|
||||
{Qt::GlobalColor::gray, Qt::GlobalColor::gray},
|
||||
}};
|
||||
|
||||
bool IsDarkTheme() {
|
||||
const auto& theme = UISettings::values.theme;
|
||||
return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
|
||||
theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WaitTreeItem::WaitTreeItem() = default;
|
||||
WaitTreeItem::~WaitTreeItem() = default;
|
||||
|
||||
QColor WaitTreeItem::GetColor() const {
|
||||
if (IsDarkTheme()) {
|
||||
return QColor(Qt::GlobalColor::white);
|
||||
} else {
|
||||
return QColor(Qt::GlobalColor::black);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void WaitTreeItem::Expand() {
|
||||
if (IsExpandable() && !expanded) {
|
||||
children = GetChildren();
|
||||
for (std::size_t i = 0; i < children.size(); ++i) {
|
||||
children[i]->parent = this;
|
||||
children[i]->row = i;
|
||||
}
|
||||
expanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
WaitTreeItem* WaitTreeItem::Parent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<WaitTreeItem>>& WaitTreeItem::Children() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
bool WaitTreeItem::IsExpandable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t WaitTreeItem::Row() const {
|
||||
return row;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList(
|
||||
Core::System& system) {
|
||||
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
||||
std::size_t row = 0;
|
||||
auto add_threads = [&](const std::vector<Kernel::KThread*>& threads) {
|
||||
for (std::size_t i = 0; i < threads.size(); ++i) {
|
||||
if (threads[i]->GetThreadType() == Kernel::ThreadType::User) {
|
||||
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i], system));
|
||||
item_list.back()->row = row;
|
||||
}
|
||||
++row;
|
||||
}
|
||||
};
|
||||
|
||||
add_threads(system.GlobalSchedulerContext().GetThreadList());
|
||||
|
||||
return item_list;
|
||||
}
|
||||
|
||||
WaitTreeText::WaitTreeText(QString t) : text(std::move(t)) {}
|
||||
WaitTreeText::~WaitTreeText() = default;
|
||||
|
||||
QString WaitTreeText::GetText() const {
|
||||
return text;
|
||||
}
|
||||
|
||||
WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_)
|
||||
: thread{thread_}, system{system_} {}
|
||||
WaitTreeCallstack::~WaitTreeCallstack() = default;
|
||||
|
||||
QString WaitTreeCallstack::GetText() const {
|
||||
return tr("Call stack");
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> list;
|
||||
|
||||
if (thread.GetThreadType() != Kernel::ThreadType::User) {
|
||||
return list;
|
||||
}
|
||||
|
||||
if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64Bit()) {
|
||||
return list;
|
||||
}
|
||||
|
||||
auto backtrace = Core::GetBacktraceFromContext(thread.GetOwnerProcess(), thread.GetContext());
|
||||
|
||||
for (auto& entry : backtrace) {
|
||||
std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
|
||||
entry.original_address, entry.offset, entry.name);
|
||||
list.push_back(std::make_unique<WaitTreeText>(QString::fromStdString(s)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
WaitTreeSynchronizationObject::WaitTreeSynchronizationObject(
|
||||
const Kernel::KSynchronizationObject& object_, Core::System& system_)
|
||||
: object{object_}, system{system_} {}
|
||||
WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default;
|
||||
|
||||
WaitTreeExpandableItem::WaitTreeExpandableItem() = default;
|
||||
WaitTreeExpandableItem::~WaitTreeExpandableItem() = default;
|
||||
|
||||
bool WaitTreeExpandableItem::IsExpandable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString WaitTreeSynchronizationObject::GetText() const {
|
||||
return tr("[%1] %2")
|
||||
.arg(object.GetId())
|
||||
.arg(QString::fromStdString(object.GetTypeObj().GetName()));
|
||||
}
|
||||
|
||||
std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make(
|
||||
const Kernel::KSynchronizationObject& object, Core::System& system) {
|
||||
const auto type =
|
||||
static_cast<Kernel::KClassTokenGenerator::ObjectType>(object.GetTypeObj().GetClassToken());
|
||||
switch (type) {
|
||||
case Kernel::KClassTokenGenerator::ObjectType::KReadableEvent:
|
||||
return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object),
|
||||
system);
|
||||
case Kernel::KClassTokenGenerator::ObjectType::KThread:
|
||||
return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object),
|
||||
system);
|
||||
default:
|
||||
return std::make_unique<WaitTreeSynchronizationObject>(object, system);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const {
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> list;
|
||||
|
||||
auto threads = object.GetWaitingThreadsForDebugging();
|
||||
if (threads.empty()) {
|
||||
list.push_back(std::make_unique<WaitTreeText>(tr("waited by no thread")));
|
||||
} else {
|
||||
list.push_back(std::make_unique<WaitTreeThreadList>(std::move(threads), system));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
WaitTreeThread::WaitTreeThread(const Kernel::KThread& thread, Core::System& system_)
|
||||
: WaitTreeSynchronizationObject(thread, system_), system{system_} {}
|
||||
WaitTreeThread::~WaitTreeThread() = default;
|
||||
|
||||
QString WaitTreeThread::GetText() const {
|
||||
const auto& thread = static_cast<const Kernel::KThread&>(object);
|
||||
QString status;
|
||||
switch (thread.GetState()) {
|
||||
case Kernel::ThreadState::Runnable:
|
||||
if (!thread.IsSuspended()) {
|
||||
status = tr("runnable");
|
||||
} else {
|
||||
status = tr("paused");
|
||||
}
|
||||
break;
|
||||
case Kernel::ThreadState::Waiting:
|
||||
switch (thread.GetWaitReasonForDebugging()) {
|
||||
case Kernel::ThreadWaitReasonForDebugging::Sleep:
|
||||
status = tr("sleeping");
|
||||
break;
|
||||
case Kernel::ThreadWaitReasonForDebugging::IPC:
|
||||
status = tr("waiting for IPC reply");
|
||||
break;
|
||||
case Kernel::ThreadWaitReasonForDebugging::Synchronization:
|
||||
status = tr("waiting for objects");
|
||||
break;
|
||||
case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
|
||||
status = tr("waiting for condition variable");
|
||||
break;
|
||||
case Kernel::ThreadWaitReasonForDebugging::Arbitration:
|
||||
status = tr("waiting for address arbiter");
|
||||
break;
|
||||
case Kernel::ThreadWaitReasonForDebugging::Suspended:
|
||||
status = tr("waiting for suspend resume");
|
||||
break;
|
||||
default:
|
||||
status = tr("waiting");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Kernel::ThreadState::Initialized:
|
||||
status = tr("initialized");
|
||||
break;
|
||||
case Kernel::ThreadState::Terminated:
|
||||
status = tr("terminated");
|
||||
break;
|
||||
default:
|
||||
status = tr("unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& context = thread.GetContext();
|
||||
const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
|
||||
.arg(context.pc, 8, 16, QLatin1Char{'0'})
|
||||
.arg(context.lr, 8, 16, QLatin1Char{'0'});
|
||||
return QStringLiteral("%1%2 (%3) ")
|
||||
.arg(WaitTreeSynchronizationObject::GetText(), pc_info, status);
|
||||
}
|
||||
|
||||
QColor WaitTreeThread::GetColor() const {
|
||||
const std::size_t color_index = IsDarkTheme() ? 1 : 0;
|
||||
|
||||
const auto& thread = static_cast<const Kernel::KThread&>(object);
|
||||
switch (thread.GetState()) {
|
||||
case Kernel::ThreadState::Runnable:
|
||||
if (!thread.IsSuspended()) {
|
||||
return QColor(WaitTreeColors[0][color_index]);
|
||||
} else {
|
||||
return QColor(WaitTreeColors[2][color_index]);
|
||||
}
|
||||
case Kernel::ThreadState::Waiting:
|
||||
switch (thread.GetWaitReasonForDebugging()) {
|
||||
case Kernel::ThreadWaitReasonForDebugging::IPC:
|
||||
return QColor(WaitTreeColors[4][color_index]);
|
||||
case Kernel::ThreadWaitReasonForDebugging::Sleep:
|
||||
return QColor(WaitTreeColors[5][color_index]);
|
||||
case Kernel::ThreadWaitReasonForDebugging::Synchronization:
|
||||
case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
|
||||
case Kernel::ThreadWaitReasonForDebugging::Arbitration:
|
||||
case Kernel::ThreadWaitReasonForDebugging::Suspended:
|
||||
return QColor(WaitTreeColors[6][color_index]);
|
||||
break;
|
||||
default:
|
||||
return QColor(WaitTreeColors[3][color_index]);
|
||||
}
|
||||
case Kernel::ThreadState::Initialized:
|
||||
return QColor(WaitTreeColors[7][color_index]);
|
||||
case Kernel::ThreadState::Terminated:
|
||||
return QColor(WaitTreeColors[8][color_index]);
|
||||
default:
|
||||
return WaitTreeItem::GetColor();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeSynchronizationObject::GetChildren());
|
||||
|
||||
const auto& thread = static_cast<const Kernel::KThread&>(object);
|
||||
|
||||
QString processor;
|
||||
switch (thread.GetActiveCore()) {
|
||||
case Kernel::Svc::IdealCoreUseProcessValue:
|
||||
processor = tr("ideal");
|
||||
break;
|
||||
default:
|
||||
processor = tr("core %1").arg(thread.GetActiveCore());
|
||||
break;
|
||||
}
|
||||
|
||||
list.push_back(std::make_unique<WaitTreeText>(tr("processor = %1").arg(processor)));
|
||||
list.push_back(std::make_unique<WaitTreeText>(
|
||||
tr("affinity mask = %1").arg(thread.GetAffinityMask().GetAffinityMask())));
|
||||
list.push_back(std::make_unique<WaitTreeText>(tr("thread id = %1").arg(thread.GetThreadId())));
|
||||
list.push_back(std::make_unique<WaitTreeText>(tr("priority = %1(current) / %2(normal)")
|
||||
.arg(thread.GetPriority())
|
||||
.arg(thread.GetBasePriority())));
|
||||
list.push_back(std::make_unique<WaitTreeText>(
|
||||
tr("last running ticks = %1").arg(thread.GetLastScheduledTick())));
|
||||
|
||||
list.push_back(std::make_unique<WaitTreeCallstack>(thread, system));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_)
|
||||
: WaitTreeSynchronizationObject(object_, system_) {}
|
||||
WaitTreeEvent::~WaitTreeEvent() = default;
|
||||
|
||||
WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_)
|
||||
: thread_list(std::move(list)), system{system_} {}
|
||||
WaitTreeThreadList::~WaitTreeThreadList() = default;
|
||||
|
||||
QString WaitTreeThreadList::GetText() const {
|
||||
return tr("waited by thread");
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThreadList::GetChildren() const {
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> list(thread_list.size());
|
||||
std::transform(thread_list.begin(), thread_list.end(), list.begin(),
|
||||
[this](const auto& t) { return std::make_unique<WaitTreeThread>(*t, system); });
|
||||
return list;
|
||||
}
|
||||
|
||||
WaitTreeModel::WaitTreeModel(Core::System& system_, QObject* parent)
|
||||
: QAbstractItemModel(parent), system{system_} {}
|
||||
WaitTreeModel::~WaitTreeModel() = default;
|
||||
|
||||
QModelIndex WaitTreeModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
if (!hasIndex(row, column, parent))
|
||||
return {};
|
||||
|
||||
if (parent.isValid()) {
|
||||
WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(parent.internalPointer());
|
||||
parent_item->Expand();
|
||||
return createIndex(row, column, parent_item->Children()[row].get());
|
||||
}
|
||||
|
||||
return createIndex(row, column, thread_items[row].get());
|
||||
}
|
||||
|
||||
QModelIndex WaitTreeModel::parent(const QModelIndex& index) const {
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(index.internalPointer())->Parent();
|
||||
if (!parent_item) {
|
||||
return QModelIndex();
|
||||
}
|
||||
return createIndex(static_cast<int>(parent_item->Row()), 0, parent_item);
|
||||
}
|
||||
|
||||
int WaitTreeModel::rowCount(const QModelIndex& parent) const {
|
||||
if (!parent.isValid())
|
||||
return static_cast<int>(thread_items.size());
|
||||
|
||||
WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(parent.internalPointer());
|
||||
parent_item->Expand();
|
||||
return static_cast<int>(parent_item->Children().size());
|
||||
}
|
||||
|
||||
int WaitTreeModel::columnCount(const QModelIndex&) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant WaitTreeModel::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return static_cast<WaitTreeItem*>(index.internalPointer())->GetText();
|
||||
case Qt::ForegroundRole:
|
||||
return static_cast<WaitTreeItem*>(index.internalPointer())->GetColor();
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void WaitTreeModel::ClearItems() {
|
||||
thread_items.clear();
|
||||
}
|
||||
|
||||
void WaitTreeModel::InitItems() {
|
||||
thread_items = WaitTreeItem::MakeThreadItemList(system);
|
||||
}
|
||||
|
||||
WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent)
|
||||
: QDockWidget(tr("&Wait Tree"), parent), system{system_} {
|
||||
setObjectName(QStringLiteral("WaitTreeWidget"));
|
||||
view = new QTreeView(this);
|
||||
view->setHeaderHidden(true);
|
||||
setWidget(view);
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
WaitTreeWidget::~WaitTreeWidget() = default;
|
||||
|
||||
void WaitTreeWidget::OnDebugModeEntered() {
|
||||
if (!system.IsPoweredOn())
|
||||
return;
|
||||
model->InitItems();
|
||||
view->setModel(model);
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
void WaitTreeWidget::OnDebugModeLeft() {
|
||||
setEnabled(false);
|
||||
view->setModel(nullptr);
|
||||
model->ClearItems();
|
||||
}
|
||||
|
||||
void WaitTreeWidget::OnEmulationStarting(EmuThread* emu_thread) {
|
||||
model = new WaitTreeModel(system, this);
|
||||
view->setModel(model);
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
void WaitTreeWidget::OnEmulationStopping() {
|
||||
view->setModel(nullptr);
|
||||
delete model;
|
||||
setEnabled(false);
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/svc_common.h"
|
||||
|
||||
class EmuThread;
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class KHandleTable;
|
||||
class KReadableEvent;
|
||||
class KSynchronizationObject;
|
||||
class KThread;
|
||||
} // namespace Kernel
|
||||
|
||||
class WaitTreeThread;
|
||||
|
||||
class WaitTreeItem : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
WaitTreeItem();
|
||||
~WaitTreeItem() override;
|
||||
|
||||
virtual bool IsExpandable() const;
|
||||
virtual std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const;
|
||||
virtual QString GetText() const = 0;
|
||||
virtual QColor GetColor() const;
|
||||
|
||||
void Expand();
|
||||
WaitTreeItem* Parent() const;
|
||||
const std::vector<std::unique_ptr<WaitTreeItem>>& Children() const;
|
||||
std::size_t Row() const;
|
||||
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList(Core::System& system);
|
||||
|
||||
private:
|
||||
std::size_t row;
|
||||
bool expanded = false;
|
||||
WaitTreeItem* parent = nullptr;
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> children;
|
||||
};
|
||||
|
||||
class WaitTreeText : public WaitTreeItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeText(QString text);
|
||||
~WaitTreeText() override;
|
||||
|
||||
QString GetText() const override;
|
||||
|
||||
private:
|
||||
QString text;
|
||||
};
|
||||
|
||||
class WaitTreeExpandableItem : public WaitTreeItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
WaitTreeExpandableItem();
|
||||
~WaitTreeExpandableItem() override;
|
||||
|
||||
bool IsExpandable() const override;
|
||||
};
|
||||
|
||||
class WaitTreeCallstack : public WaitTreeExpandableItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_);
|
||||
~WaitTreeCallstack() override;
|
||||
|
||||
QString GetText() const override;
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||
|
||||
private:
|
||||
const Kernel::KThread& thread;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
class WaitTreeSynchronizationObject : public WaitTreeExpandableItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object_,
|
||||
Core::System& system_);
|
||||
~WaitTreeSynchronizationObject() override;
|
||||
|
||||
static std::unique_ptr<WaitTreeSynchronizationObject> make(
|
||||
const Kernel::KSynchronizationObject& object, Core::System& system);
|
||||
QString GetText() const override;
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||
|
||||
protected:
|
||||
const Kernel::KSynchronizationObject& object;
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
class WaitTreeThread : public WaitTreeSynchronizationObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeThread(const Kernel::KThread& thread, Core::System& system_);
|
||||
~WaitTreeThread() override;
|
||||
|
||||
QString GetText() const override;
|
||||
QColor GetColor() const override;
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
class WaitTreeEvent : public WaitTreeSynchronizationObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_);
|
||||
~WaitTreeEvent() override;
|
||||
};
|
||||
|
||||
class WaitTreeThreadList : public WaitTreeExpandableItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_);
|
||||
~WaitTreeThreadList() override;
|
||||
|
||||
QString GetText() const override;
|
||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||
|
||||
private:
|
||||
std::vector<Kernel::KThread*> thread_list;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
class WaitTreeModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WaitTreeModel(Core::System& system_, QObject* parent = nullptr);
|
||||
~WaitTreeModel() override;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent) const override;
|
||||
QModelIndex parent(const QModelIndex& index) const override;
|
||||
int rowCount(const QModelIndex& parent) const override;
|
||||
int columnCount(const QModelIndex& parent) const override;
|
||||
|
||||
void ClearItems();
|
||||
void InitItems();
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
class WaitTreeWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WaitTreeWidget(Core::System& system_, QWidget* parent = nullptr);
|
||||
~WaitTreeWidget() override;
|
||||
|
||||
public slots:
|
||||
void OnDebugModeEntered();
|
||||
void OnDebugModeLeft();
|
||||
|
||||
void OnEmulationStarting(EmuThread* emu_thread);
|
||||
void OnEmulationStopping();
|
||||
|
||||
private:
|
||||
QTreeView* view;
|
||||
WaitTreeModel* model;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
@@ -18,7 +18,7 @@ DepsDialog::DepsDialog(QWidget* parent)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
constexpr size_t rows = Common::dep_hashes.size();
|
||||
constexpr int rows = (int) Common::dep_hashes.size();
|
||||
ui->tableDeps->setRowCount(rows);
|
||||
|
||||
QStringList labels;
|
||||
@@ -29,7 +29,7 @@ DepsDialog::DepsDialog(QWidget* parent)
|
||||
ui->tableDeps->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Fixed);
|
||||
ui->tableDeps->horizontalHeader()->setMinimumSectionSize(200);
|
||||
|
||||
for (size_t i = 0; i < rows; ++i) {
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
const std::string name = Common::dep_names.at(i);
|
||||
const std::string sha = Common::dep_hashes.at(i);
|
||||
const std::string url = Common::dep_urls.at(i);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "yuzu/compatibility_list.h"
|
||||
#include "yuzu/game_list_p.h"
|
||||
#include "yuzu/game_list_worker.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/main_window.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
#include <fmt/ranges.h>
|
||||
#include <regex>
|
||||
@@ -314,7 +314,7 @@ void GameList::OnFilterCloseClicked() {
|
||||
|
||||
GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvider* provider_,
|
||||
PlayTime::PlayTimeManager& play_time_manager_, Core::System& system_,
|
||||
GMainWindow* parent)
|
||||
MainWindow* parent)
|
||||
: QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_},
|
||||
play_time_manager{play_time_manager_}, system{system_} {
|
||||
watcher = new QFileSystemWatcher(this);
|
||||
@@ -347,7 +347,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
|
||||
tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
|
||||
item_model->setSortRole(GameListItemPath::SortRole);
|
||||
|
||||
connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons);
|
||||
connect(main_window, &MainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons);
|
||||
connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
|
||||
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
|
||||
connect(tree_view, &QTreeView::expanded, this, &GameList::OnItemExpanded);
|
||||
@@ -943,8 +943,8 @@ void GameList::RemoveFavorite(u64 program_id) {
|
||||
}
|
||||
}
|
||||
|
||||
GameListPlaceholder::GameListPlaceholder(GMainWindow* parent) : QWidget{parent} {
|
||||
connect(parent, &GMainWindow::UpdateThemedIcons, this,
|
||||
GameListPlaceholder::GameListPlaceholder(MainWindow* parent) : QWidget{parent} {
|
||||
connect(parent, &MainWindow::UpdateThemedIcons, this,
|
||||
&GameListPlaceholder::onUpdateThemedIcons);
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
|
||||