Compare commits
38 commits
Author | SHA1 | Date | |
---|---|---|---|
fa102f7e83 | |||
6f9216c20d | |||
2d81cf5b26 | |||
3d84b15330 | |||
a5877ca08b | |||
ca2fa770f7 | |||
aa880d3ca9 | |||
4462da9f06 | |||
74d387afb3 | |||
ba565f9d6a | |||
83c06fc037 | |||
59d1c09eb3 | |||
3ac6116910 | |||
8785de9b7e | |||
c6abde7af4 | |||
c5d78081d7 | |||
e6923b09c3 | |||
d9b7944963 | |||
4abf13ae93 | |||
57da00940d | |||
55d8911daa | |||
d744cc6a41 | |||
fd39eb780a | |||
002feb9d89 | |||
05e31d1e76 | |||
ebefd13e5c | |||
fd0cde2a8d | |||
89b70d14bd | |||
1e31a48957 | |||
2112c4a3aa | |||
57c4859da4 | |||
e18c7ba41d | |||
78c138d35f | |||
b6a5462faf | |||
257a8465fa | |||
2453fd4c78 | |||
772352f047 | |||
8cd0d78269 |
327 changed files with 5411 additions and 4448 deletions
|
@ -3,7 +3,6 @@
|
||||||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
export ARCH="$(uname -m)"
|
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
amd64|"")
|
amd64|"")
|
||||||
|
@ -11,15 +10,15 @@ case "$1" in
|
||||||
ARCH="amd64_v3"
|
ARCH="amd64_v3"
|
||||||
ARCH_FLAGS="-march=x86-64-v3"
|
ARCH_FLAGS="-march=x86-64-v3"
|
||||||
;;
|
;;
|
||||||
steamdeck)
|
steamdeck|zen2)
|
||||||
echo "Making Steam Deck (Zen 2) optimized build of Eden"
|
echo "Making Steam Deck (Zen 2) optimized build of Eden"
|
||||||
ARCH="steamdeck"
|
ARCH="steamdeck"
|
||||||
ARCH_FLAGS="-march=znver2 -mtune=znver2"
|
ARCH_FLAGS="-march=znver2 -mtune=znver2"
|
||||||
;;
|
;;
|
||||||
rog-ally|allyx)
|
rog-ally|allyx|zen4)
|
||||||
echo "Making ROG Ally X (Zen 4) optimized build of Eden"
|
echo "Making ROG Ally X (Zen 4) optimized build of Eden"
|
||||||
ARCH="rog-ally-x"
|
ARCH="rog-ally-x"
|
||||||
ARCH_FLAGS="-march=znver3 -mtune=znver4" # GH actions runner is a Zen 3 CPU, so a small workaround
|
ARCH_FLAGS="-march=znver4 -mtune=znver4"
|
||||||
;;
|
;;
|
||||||
legacy)
|
legacy)
|
||||||
echo "Making amd64 generic build of Eden"
|
echo "Making amd64 generic build of Eden"
|
||||||
|
@ -36,8 +35,13 @@ case "$1" in
|
||||||
ARCH=armv9
|
ARCH=armv9
|
||||||
ARCH_FLAGS="-march=armv9-a -mtune=generic -w"
|
ARCH_FLAGS="-march=armv9-a -mtune=generic -w"
|
||||||
;;
|
;;
|
||||||
|
native)
|
||||||
|
echo "Making native build of Eden"
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
ARCH_FLAGS="-march=native -mtune=native"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid target $1 specified, must be one of amd64, steamdeck, allyx, rog-ally, legacy, aarch64, armv9"
|
echo "Invalid target $1 specified, must be one of native, amd64, steamdeck, zen2, allyx, rog-ally, zen4, legacy, aarch64, armv9"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -16,11 +16,11 @@ case "$1" in
|
||||||
echo "Packaging amd64-v3 optimized build of Eden"
|
echo "Packaging amd64-v3 optimized build of Eden"
|
||||||
ARCH="amd64_v3"
|
ARCH="amd64_v3"
|
||||||
;;
|
;;
|
||||||
steamdeck)
|
steamdeck|zen2)
|
||||||
echo "Packaging Steam Deck (Zen 2) optimized build of Eden"
|
echo "Packaging Steam Deck (Zen 2) optimized build of Eden"
|
||||||
ARCH="steamdeck"
|
ARCH="steamdeck"
|
||||||
;;
|
;;
|
||||||
rog-ally|allyx)
|
rog-ally|allyx|zen4)
|
||||||
echo "Packaging ROG Ally X (Zen 4) optimized build of Eden"
|
echo "Packaging ROG Ally X (Zen 4) optimized build of Eden"
|
||||||
ARCH="rog-ally-x"
|
ARCH="rog-ally-x"
|
||||||
;;
|
;;
|
||||||
|
@ -36,6 +36,11 @@ case "$1" in
|
||||||
echo "Packaging armv9-a build of Eden"
|
echo "Packaging armv9-a build of Eden"
|
||||||
ARCH=armv9
|
ARCH=armv9
|
||||||
;;
|
;;
|
||||||
|
native)
|
||||||
|
echo "Packaging native build of Eden"
|
||||||
|
ARCH="$BASE_ARCH"
|
||||||
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
export BUILDDIR="$2"
|
export BUILDDIR="$2"
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
diff --git a/quazip/quazipdir.cpp b/quazip/quazipdir.cpp
|
|
||||||
index d43f1c1..eb24bf1 100644
|
|
||||||
--- a/quazip/quazipdir.cpp
|
|
||||||
+++ b/quazip/quazipdir.cpp
|
|
||||||
@@ -293,8 +293,8 @@ bool QuaZipDirComparator::operator()(const QuaZipFileInfo64 &info1,
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TFileInfoList>
|
|
||||||
-bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
|
|
||||||
- QDir::Filters filter, QDir::SortFlags sort, TFileInfoList &result) const
|
|
||||||
+bool QuaZipDirPrivate::entryInfoList(QStringList _nameFilters,
|
|
||||||
+ QDir::Filters _filter, QDir::SortFlags sort, TFileInfoList &result) const
|
|
||||||
{
|
|
||||||
QString basePath = simplePath();
|
|
||||||
if (!basePath.isEmpty())
|
|
||||||
@@ -305,12 +305,12 @@ bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
|
|
||||||
if (!zip->goToFirstFile()) {
|
|
||||||
return zip->getZipError() == UNZ_OK;
|
|
||||||
}
|
|
||||||
- QDir::Filters fltr = filter;
|
|
||||||
+ QDir::Filters fltr = _filter;
|
|
||||||
if (fltr == QDir::NoFilter)
|
|
||||||
fltr = this->filter;
|
|
||||||
if (fltr == QDir::NoFilter)
|
|
||||||
fltr = QDir::AllEntries;
|
|
||||||
- QStringList nmfltr = nameFilters;
|
|
||||||
+ QStringList nmfltr = _nameFilters;
|
|
||||||
if (nmfltr.isEmpty())
|
|
||||||
nmfltr = this->nameFilters;
|
|
||||||
QSet<QString> dirsFound;
|
|
||||||
diff --git a/quazip/quazipfile.cpp b/quazip/quazipfile.cpp
|
|
||||||
index 4a5f2f9..f7865f5 100644
|
|
||||||
--- a/quazip/quazipfile.cpp
|
|
||||||
+++ b/quazip/quazipfile.cpp
|
|
||||||
@@ -241,14 +241,14 @@ void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs
|
|
||||||
p->caseSensitivity=cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void QuaZipFilePrivate::setZipError(int zipError) const
|
|
||||||
+void QuaZipFilePrivate::setZipError(int _zipError) const
|
|
||||||
{
|
|
||||||
QuaZipFilePrivate *fakeThis = const_cast<QuaZipFilePrivate*>(this); // non-const
|
|
||||||
- fakeThis->zipError=zipError;
|
|
||||||
- if(zipError==UNZ_OK)
|
|
||||||
+ fakeThis->zipError = _zipError;
|
|
||||||
+ if(_zipError == UNZ_OK)
|
|
||||||
q->setErrorString(QString());
|
|
||||||
else
|
|
||||||
- q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError));
|
|
||||||
+ q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(_zipError));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QuaZipFile::open(OpenMode mode)
|
|
||||||
diff --git a/quazip/unzip.c b/quazip/unzip.c
|
|
||||||
index a39365d..ee7b487 100644
|
|
||||||
--- a/quazip/unzip.c
|
|
||||||
+++ b/quazip/unzip.c
|
|
||||||
@@ -1054,7 +1054,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
|
|
||||||
/* ZIP64 extra fields */
|
|
||||||
if (headerId == 0x0001)
|
|
||||||
{
|
|
||||||
- uLong uL;
|
|
||||||
+ uLong _uL;
|
|
||||||
|
|
||||||
if(file_info.uncompressed_size == (ZPOS64_T)0xFFFFFFFFu)
|
|
||||||
{
|
|
||||||
@@ -1078,7 +1078,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
|
|
||||||
if(file_info.disk_num_start == 0xFFFFFFFFu)
|
|
||||||
{
|
|
||||||
/* Disk Start Number */
|
|
||||||
- if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
|
|
||||||
+ if (unz64local_getLong(&s->z_filefunc, s->filestream, &_uL) != UNZ_OK)
|
|
||||||
err=UNZ_ERRNO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2151,3 +2151,4 @@ int ZEXPORT unzClearFlags(unzFile file, unsigned flags)
|
|
||||||
s->flags &= ~flags;
|
|
||||||
return UNZ_OK;
|
|
||||||
}
|
|
||||||
+
|
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/cmake/clone-repo.cmake b/cmake/clone-repo.cmake
|
|
||||||
index 2ffb4b2..77974dc 100644
|
|
||||||
--- a/cmake/clone-repo.cmake
|
|
||||||
+++ b/cmake/clone-repo.cmake
|
|
||||||
@@ -26,7 +26,7 @@ macro(clone_repo name url)
|
|
||||||
FetchContent_GetProperties(${name} POPULATED ${name_lower}_POPULATED)
|
|
||||||
|
|
||||||
if(NOT ${name_lower}_POPULATED)
|
|
||||||
- FetchContent_Populate(${name})
|
|
||||||
+ FetchContent_MakeAvailable(${name})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${name_upper}_SOURCE_DIR ${${name_lower}_SOURCE_DIR})
|
|
|
@ -1,19 +0,0 @@
|
||||||
echo off
|
|
||||||
|
|
||||||
call C:\tools\cygwin\cygwinsetup.exe -q -P autoconf,automake,libtool,make,pkg-config
|
|
||||||
|
|
||||||
REM Create wrapper batch files for Cygwin tools in a directory that will be in PATH
|
|
||||||
REM uncomment this for first-run only
|
|
||||||
REM call mkdir C:\cygwin-wrappers
|
|
||||||
|
|
||||||
REM Create autoconf.bat wrapper
|
|
||||||
call echo @echo off > C:\cygwin-wrappers\autoconf.bat
|
|
||||||
call echo C:\tools\cygwin\bin\bash.exe -l -c "autoconf %%*" >> C:\cygwin-wrappers\autoconf.bat
|
|
||||||
|
|
||||||
REM Add other wrappers if needed for other Cygwin tools
|
|
||||||
call echo @echo off > C:\cygwin-wrappers\automake.bat
|
|
||||||
call echo C:\tools\cygwin\bin\bash.exe -l -c "automake %%*" >> C:\cygwin-wrappers\automake.bat
|
|
||||||
|
|
||||||
REM Add the wrappers directory to PATH
|
|
||||||
call echo C:\cygwin-wrappers>>"%GITHUB_PATH%"
|
|
||||||
call echo C:\tools\cygwin\bin>>"%GITHUB_PATH%"
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$VulkanSDKVer = "1.3.250.1"
|
$VulkanSDKVer = "1.4.321.1"
|
||||||
$ExeFile = "VulkanSDK-$VulkanSDKVer-Installer.exe"
|
$ExeFile = "VulkanSDK-$VulkanSDKVer-Installer.exe"
|
||||||
$Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/windows/$ExeFile"
|
$Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/windows/$ExeFile"
|
||||||
$Destination = "./$ExeFile"
|
$Destination = "./$ExeFile"
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
# This is specific to the CI runner and is unlikely to work on your machine.
|
|
||||||
QTDIR="/c/Qt/6.9.0/msvc2022_64"
|
|
||||||
|
|
||||||
export QT_ROOT_DIR="$QTDIR"
|
|
||||||
export QT_PLUGIN_PATH="$QTDIR/plugins"
|
|
||||||
export QML2_IMPORT_PATH="$QTDIR/qml"
|
|
||||||
export PATH="${PATH};$QTDIR/bin"
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# Build directory
|
# Build directory
|
||||||
[Bb]uild*/
|
/[Bb]uild*/
|
||||||
doc-build/
|
doc-build/
|
||||||
AppDir/
|
AppDir/
|
||||||
uruntime
|
uruntime
|
||||||
|
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -12,7 +12,7 @@
|
||||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||||
[submodule "xbyak"]
|
[submodule "xbyak"]
|
||||||
path = externals/xbyak
|
path = externals/xbyak
|
||||||
url = https://github.com/herumi/xbyak.git
|
url = https://github.com/Lizzie841/xbyak.git
|
||||||
[submodule "opus"]
|
[submodule "opus"]
|
||||||
path = externals/opus
|
path = externals/opus
|
||||||
url = https://github.com/xiph/opus.git
|
url = https://github.com/xiph/opus.git
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
url = https://github.com/Lizzie841/unordered_dense.git
|
url = https://github.com/Lizzie841/unordered_dense.git
|
||||||
[submodule "externals/dynarmic/externals/xbyak"]
|
[submodule "externals/dynarmic/externals/xbyak"]
|
||||||
path = externals/dynarmic/externals/xbyak
|
path = externals/dynarmic/externals/xbyak
|
||||||
url = https://github.com/herumi/xbyak.git
|
url = https://github.com/Lizzie841/xbyak.git
|
||||||
[submodule "externals/dynarmic/externals/zycore-c"]
|
[submodule "externals/dynarmic/externals/zycore-c"]
|
||||||
path = externals/dynarmic/externals/zycore-c
|
path = externals/dynarmic/externals/zycore-c
|
||||||
url = https://github.com/zyantific/zycore-c.git
|
url = https://github.com/zyantific/zycore-c.git
|
||||||
|
|
|
@ -50,6 +50,7 @@ option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF)
|
||||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
||||||
|
|
||||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||||
|
option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF)
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" OFF)
|
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" OFF)
|
||||||
|
@ -60,7 +61,7 @@ endif()
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" OFF)
|
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" OFF)
|
||||||
else()
|
else()
|
||||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
|
@ -120,7 +121,7 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available
|
||||||
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
|
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
|
||||||
|
|
||||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
set(DEFAULT_ENABLE_OPENSSL ON)
|
||||||
if (ANDROID OR WIN32 OR APPLE)
|
if (ANDROID OR WIN32 OR APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
|
||||||
set(DEFAULT_ENABLE_OPENSSL OFF)
|
set(DEFAULT_ENABLE_OPENSSL OFF)
|
||||||
endif()
|
endif()
|
||||||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||||
|
@ -416,6 +417,10 @@ if (UNIX AND NOT APPLE)
|
||||||
find_package(gamemode 1.7 MODULE)
|
find_package(gamemode 1.7 MODULE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_QT)
|
||||||
|
find_package(libzip CONFIG REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package
|
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package
|
||||||
if (ENABLE_SDL2)
|
if (ENABLE_SDL2)
|
||||||
if (YUZU_USE_BUNDLED_SDL2)
|
if (YUZU_USE_BUNDLED_SDL2)
|
||||||
|
@ -458,19 +463,22 @@ if (ENABLE_QT)
|
||||||
if (YUZU_USE_BUNDLED_QT)
|
if (YUZU_USE_BUNDLED_QT)
|
||||||
download_qt(6.8.3)
|
download_qt(6.8.3)
|
||||||
else()
|
else()
|
||||||
message(STATUS "Using system Qt")
|
|
||||||
if (NOT Qt6_DIR)
|
if (NOT Qt6_DIR)
|
||||||
set(Qt6_DIR "" CACHE PATH "Additional path to search for Qt6 libraries like C:/Qt/6.8.3/msvc2022_64/lib/cmake/Qt6")
|
set(Qt6_DIR "" CACHE PATH "Additional path to search for Qt6 libraries like C:/Qt/6.8.3/msvc2022_64/lib/cmake/Qt6")
|
||||||
endif()
|
endif()
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${Qt6_DIR}")
|
list(APPEND CMAKE_PREFIX_PATH "${Qt6_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent)
|
||||||
|
|
||||||
|
if (Qt6_FOUND)
|
||||||
|
message(STATUS "Found Qt6: ${Qt6_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# QT6 Multimedia pulls in unneeded audio systems (ALSA, Pulseaudio) for FreeBSD
|
# QT6 Multimedia pulls in unneeded audio systems (ALSA, Pulseaudio) for FreeBSD
|
||||||
# ALSA is the default sound system on Linux, but FreeBSD uses OSS which works well enough
|
# ALSA is the default sound system on Linux, but FreeBSD uses OSS which works well enough
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if (YUZU_USE_QT_MULTIMEDIA)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent)
|
find_package(Qt6 REQUIRED COMPONENTS Multimedia)
|
||||||
else()
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
|
|
|
@ -91,11 +91,11 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out
|
||||||
set(type "desktop")
|
set(type "desktop")
|
||||||
set(arch "clang_64")
|
set(arch "clang_64")
|
||||||
set(arch_path "macos")
|
set(arch_path "macos")
|
||||||
else()
|
elseif (LINUX)
|
||||||
set(host "linux")
|
set(host "linux")
|
||||||
set(type "desktop")
|
set(type "desktop")
|
||||||
set(arch "gcc_64")
|
set(arch "linux_gcc_64")
|
||||||
set(arch_path "linux")
|
set(arch_path "gcc_64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${host_out} "${host}" PARENT_SCOPE)
|
set(${host_out} "${host}" PARENT_SCOPE)
|
||||||
|
@ -129,16 +129,29 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
|
||||||
|
|
||||||
set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini")
|
set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini")
|
||||||
if (tool)
|
if (tool)
|
||||||
set(prefix "${base_path}/Tools")
|
set(prefix "${base_path}/tools")
|
||||||
set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target})
|
set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target})
|
||||||
else()
|
else()
|
||||||
set(prefix "${base_path}/${target}/${arch_path}")
|
set(prefix "${base_path}/${target}/${arch_path}")
|
||||||
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt3d qt5compat qtactiveqt qtcharts qtconnectivity qtdatavis3d qtgraphs qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwebchannel qtwebengine qtwebsockets qtwebview)
|
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt_base)
|
||||||
|
|
||||||
|
if (YUZU_USE_QT_MULTIMEDIA)
|
||||||
|
set(install_args ${install_args} qtmultimedia)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (YUZU_USE_QT_WEB_ENGINE)
|
||||||
|
set(install_args ${install_args} qtpositioning qtwebchannel qtwebengine)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT ${YUZU_QT_MIRROR} STREQUAL "")
|
||||||
|
message(STATUS "Using Qt mirror ${YUZU_QT_MIRROR}")
|
||||||
|
set(install_args ${install_args} -b ${YUZU_QT_MIRROR})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT EXISTS "${prefix}")
|
if (NOT EXISTS "${prefix}")
|
||||||
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
|
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
|
||||||
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.2.1")
|
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0")
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(aqt_path "${base_path}/aqt.exe")
|
set(aqt_path "${base_path}/aqt.exe")
|
||||||
if (NOT EXISTS "${aqt_path}")
|
if (NOT EXISTS "${aqt_path}")
|
||||||
|
@ -158,14 +171,28 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
|
||||||
execute_process(COMMAND chmod +x ${aqt_path})
|
execute_process(COMMAND chmod +x ${aqt_path})
|
||||||
execute_process(COMMAND ${aqt_path} ${install_args}
|
execute_process(COMMAND ${aqt_path} ${install_args}
|
||||||
WORKING_DIRECTORY ${base_path})
|
WORKING_DIRECTORY ${base_path})
|
||||||
else()
|
elseif (LINUX)
|
||||||
set(aqt_install_path "${base_path}/aqt")
|
set(aqt_install_path "${base_path}/aqt")
|
||||||
file(MAKE_DIRECTORY "${aqt_install_path}")
|
file(MAKE_DIRECTORY "${aqt_install_path}")
|
||||||
|
|
||||||
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
WORKING_DIRECTORY ${base_path})
|
execute_process(
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args}
|
COMMAND ${Python3_EXECUTABLE} -m venv .venv
|
||||||
WORKING_DIRECTORY ${base_path})
|
WORKING_DIRECTORY ${base_path}
|
||||||
|
)
|
||||||
|
set(ENV{VIRTUAL_ENV} "${base_path}/.venv")
|
||||||
|
set(Python3_FIND_VIRTUALENV FIRST)
|
||||||
|
unset(Python3_EXECUTABLE)
|
||||||
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -m pip install aqtinstall
|
||||||
|
WORKING_DIRECTORY ${base_path}
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -m aqt ${install_args}
|
||||||
|
WORKING_DIRECTORY ${base_path}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}")
|
message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}")
|
||||||
|
|
32
CMakePresets.json
Normal file
32
CMakePresets.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "linux-amd64",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/build",
|
||||||
|
"environment": {
|
||||||
|
"CMAKE_C_COMPILER_LAUNCHER": "$env{CCACHE}",
|
||||||
|
"CMAKE_CXX_COMPILER_LAUNCHER": "$env{CCACHE}"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||||
|
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
||||||
|
"YUZU_USE_BUNDLED_VCPKG": "OFF",
|
||||||
|
"YUZU_USE_BUNDLED_QT": "ON",
|
||||||
|
"YUZU_TESTS": "OFF",
|
||||||
|
"YUZU_CHECK_SUBMODULES": "OFF",
|
||||||
|
"YUZU_USE_FASTER_LD": "ON",
|
||||||
|
"YUZU_ENABLE_LTO": "ON",
|
||||||
|
"ENABLE_QT_TRANSLATION": "ON",
|
||||||
|
"USE_DISCORD_PRESENCE": "OFF",
|
||||||
|
"YUZU_CMD": "OFF",
|
||||||
|
"YUZU_ROOM_STANDALONE": "OFF",
|
||||||
|
"CMAKE_POLICY_VERSION_MINIMUM": "3.5",
|
||||||
|
"CMAKE_INSTALL_PREFIX": "/usr",
|
||||||
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||||
|
"CMAKE_EXE_LINKER_FLAGS": "-Wl,--as-needed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
README.md
14
README.md
|
@ -9,13 +9,13 @@
|
||||||
|
|
||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<br>
|
<br>
|
||||||
<a href="https://git.eden-emu.dev/eden-emu/eden"><img src="https://git.eden-emu.dev/eden-emu/eden/raw/branch/master/dist/qt_themes/default/icons/256x256/eden_named.png" alt="Eden" width="200"></a>
|
<a href="https://git.eden-emu.dev/eden-emu/eden"><img src="./dist/qt_themes/default/icons/256x256/eden_named.png" alt="Eden" width="200"></a>
|
||||||
<br>
|
<br>
|
||||||
<b>Eden</b>
|
<b>Eden</b>
|
||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<h4 align="center"><b>Eden</b> is the world's most popular open-source Nintendo Switch emulator, forked from the Yuzu emulator — started by former Citron developer Camille LaVey and the Eden team.
|
<h4 align="center"><b>Eden</b> is a open-source Nintendo Switch emulator, forked from the Yuzu emulator — started by former Citron developer Camille LaVey and the Eden team.
|
||||||
<br>
|
<br>
|
||||||
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.
|
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.
|
||||||
</h4>
|
</h4>
|
||||||
|
@ -54,13 +54,15 @@ You can also contact any of the developers on Discord to learn more about the cu
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
* **Windows**: [Windows Building Guide](https://git.eden-emu.dev/eden-emu/eden/wiki/Building-for-Windows.-)
|
* **Windows**: [Windows Building Guide](./docs/build/Windows.md)
|
||||||
* **Linux**: [Linux Building Guide](https://git.eden-emu.dev/eden-emu/eden/wiki/Building-for-Linux.-)
|
* **Linux**: [Linux Building Guide](./docs/build/Linux.md)
|
||||||
* **Android**: [Android Building Guide](https://git.eden-emu.dev/eden-emu/eden/wiki/Building-for-Android.-)
|
* **Android**: [Android Building Guide](./docs/build/Android.md)
|
||||||
|
* **FreeBSD**: [FreeBSD Building Guide](./docs/build/FreeBSD.md)
|
||||||
|
* **macOS**: [macOS Building Guide](./docs/build/macOS.md)
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
You will be able to download the latest releases from [here](https://github.com/eden-emulator/Releases/releases).
|
You can download the latest releases from [here](https://github.com/eden-emulator/Releases/releases).
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|
174
docs/Development.md
Normal file
174
docs/Development.md
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
# Development
|
||||||
|
|
||||||
|
* **Windows**: [Windows Building Guide](./docs/build/Windows.md)
|
||||||
|
* **Linux**: [Linux Building Guide](./docs/build/Linux.md)
|
||||||
|
* **Android**: [Android Building Guide](./docs/build/Android.md)
|
||||||
|
* **Solaris**: [Solaris Building Guide](./docs/build/Solaris.md)
|
||||||
|
* **FreeBSD**: [FreeBSD Building Guide](./docs/build/FreeBSD.md)
|
||||||
|
* **macOS**: [macOS Building Guide](./docs/build/macOS.md)
|
||||||
|
|
||||||
|
# Building speedup
|
||||||
|
|
||||||
|
If you have an HDD, use ramdisk (build in RAM):
|
||||||
|
```sh
|
||||||
|
sudo mkdir /tmp/ramdisk
|
||||||
|
sudo chmod 777 /tmp/ramdisk
|
||||||
|
# about 10GB needed
|
||||||
|
sudo mount -t tmpfs -o size=10G myramdisk /tmp/ramdisk
|
||||||
|
cmake -B /tmp/ramdisk
|
||||||
|
cmake --build /tmp/ramdisk -- -j32
|
||||||
|
sudo umount /tmp/ramdisk
|
||||||
|
```
|
||||||
|
|
||||||
|
# How to test JIT
|
||||||
|
|
||||||
|
## gdb
|
||||||
|
|
||||||
|
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run eden normally to see where it is)> -d -g <path to game>`
|
||||||
|
|
||||||
|
Then hook up an aarch64-gdb (use `yay aarch64-gdb` or `sudo pkg in arch64-gdb` to install)
|
||||||
|
Then type `target remote localhost:1234` and type `c` (for continue) - and then if it crashes just do a `bt` (backtrace) and `layout asm`.
|
||||||
|
|
||||||
|
### gdb cheatsheet
|
||||||
|
|
||||||
|
- `mo <cmd>`: Monitor commands, `get info`, `get fastmem` and `get mappings` are available.
|
||||||
|
- `detach`: Detach from remote (i.e restarting the emulator).
|
||||||
|
- `c`: Continue
|
||||||
|
- `p <expr>`: Print variable, `p/x <expr>` for hexadecimal.
|
||||||
|
- `r`: Run
|
||||||
|
- `bt`: Print backtrace
|
||||||
|
- `info threads`: Print all active threads
|
||||||
|
- `thread <number>`: Switch to the given thread (see `info threads`)
|
||||||
|
- `layout asm`: Display in assembly mode (TUI)
|
||||||
|
- `si`: Step assembly instruction
|
||||||
|
- `s` or `step`: Step over LINE OF CODE (not assembly)
|
||||||
|
- `display <expr>`: Display variable each step.
|
||||||
|
- `n`: Next (skips over call frame of a function)
|
||||||
|
- `frame <number>`: Switches to the given frame (from `bt`)
|
||||||
|
- `br <expr>`: Set breakpoint at `<expr>`.
|
||||||
|
- `delete`: Deletes all breakpoints.
|
||||||
|
- `catch throw`: Breakpoint at throw. Can also use `br __cxa_throw`
|
||||||
|
|
||||||
|
Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference of a pointer) or `*(1 + var)` (computed expression).
|
||||||
|
|
||||||
|
For more information type `info gdb` and read [the man page](https://man7.org/linux/man-pages/man1/gdb.1.html).
|
||||||
|
|
||||||
|
## Bisecting older commits
|
||||||
|
|
||||||
|
Since going into the past can be tricky (especially due to the dependencies from the project being lost thru time). This should "restore" the URLs for the respective submodules.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
cat > .gitmodules <<EOF
|
||||||
|
[submodule "enet"]
|
||||||
|
path = externals/enet
|
||||||
|
url = https://github.com/lsalzman/enet.git
|
||||||
|
[submodule "cubeb"]
|
||||||
|
path = externals/cubeb
|
||||||
|
url = https://github.com/mozilla/cubeb.git
|
||||||
|
[submodule "dynarmic"]
|
||||||
|
path = externals/dynarmic
|
||||||
|
url = https://github.com/lioncash/dynarmic.git
|
||||||
|
[submodule "libusb"]
|
||||||
|
path = externals/libusb/libusb
|
||||||
|
url = https://github.com/libusb/libusb.git
|
||||||
|
[submodule "discord-rpc"]
|
||||||
|
path = externals/discord-rpc
|
||||||
|
url = https://github.com/yuzu-emu-mirror/discord-rpc.git
|
||||||
|
[submodule "Vulkan-Headers"]
|
||||||
|
path = externals/Vulkan-Headers
|
||||||
|
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||||
|
[submodule "sirit"]
|
||||||
|
path = externals/sirit
|
||||||
|
url = https://github.com/yuzu-emu-mirror/sirit.git
|
||||||
|
[submodule "mbedtls"]
|
||||||
|
path = externals/mbedtls
|
||||||
|
url = https://github.com/yuzu-emu-mirror/mbedtls.git
|
||||||
|
[submodule "xbyak"]
|
||||||
|
path = externals/xbyak
|
||||||
|
url = https://github.com/herumi/xbyak.git
|
||||||
|
[submodule "opus"]
|
||||||
|
path = externals/opus
|
||||||
|
url = https://github.com/xiph/opus.git
|
||||||
|
[submodule "SDL"]
|
||||||
|
path = externals/SDL
|
||||||
|
url = https://github.com/libsdl-org/SDL.git
|
||||||
|
[submodule "cpp-httplib"]
|
||||||
|
path = externals/cpp-httplib
|
||||||
|
url = https://github.com/yhirose/cpp-httplib.git
|
||||||
|
[submodule "ffmpeg"]
|
||||||
|
path = externals/ffmpeg/ffmpeg
|
||||||
|
url = https://github.com/FFmpeg/FFmpeg.git
|
||||||
|
[submodule "vcpkg"]
|
||||||
|
path = externals/vcpkg
|
||||||
|
url = https://github.com/microsoft/vcpkg.git
|
||||||
|
[submodule "cpp-jwt"]
|
||||||
|
path = externals/cpp-jwt
|
||||||
|
url = https://github.com/arun11299/cpp-jwt.git
|
||||||
|
[submodule "libadrenotools"]
|
||||||
|
path = externals/libadrenotools
|
||||||
|
url = https://github.com/bylaws/libadrenotools.git
|
||||||
|
[submodule "tzdb_to_nx"]
|
||||||
|
path = externals/nx_tzdb/tzdb_to_nx
|
||||||
|
url = https://github.com/lat9nq/tzdb_to_nx.git
|
||||||
|
[submodule "VulkanMemoryAllocator"]
|
||||||
|
path = externals/VulkanMemoryAllocator
|
||||||
|
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||||
|
[submodule "breakpad"]
|
||||||
|
path = externals/breakpad
|
||||||
|
url = https://github.com/yuzu-emu-mirror/breakpad.git
|
||||||
|
[submodule "simpleini"]
|
||||||
|
path = externals/simpleini
|
||||||
|
url = https://github.com/brofield/simpleini.git
|
||||||
|
[submodule "oaknut"]
|
||||||
|
path = externals/oaknut
|
||||||
|
url = https://github.com/merryhime/oaknut.git
|
||||||
|
[submodule "Vulkan-Utility-Libraries"]
|
||||||
|
path = externals/Vulkan-Utility-Libraries
|
||||||
|
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
|
||||||
|
[submodule "oboe"]
|
||||||
|
path = externals/oboe
|
||||||
|
url = https://github.com/google/oboe.git
|
||||||
|
[submodule "externals/boost-headers"]
|
||||||
|
path = externals/boost-headers
|
||||||
|
url = https://github.com/boostorg/headers.git
|
||||||
|
EOF
|
||||||
|
git submodule sync
|
||||||
|
update_or_checkout () {
|
||||||
|
if [ $0 = 'externals/sirit' ] \
|
||||||
|
|| [ $0 = 'externals/dynarmic' ] \
|
||||||
|
|| [ $0 = 'externals/breakpad' ] \
|
||||||
|
|| [ $0 = 'externals/discord-rpc' ] \
|
||||||
|
|| [ $0 = 'externals/mbedtls' ]; then
|
||||||
|
[ -f $0/CMakeLists.txt ] || git submodule update --force --remote --init -- $0
|
||||||
|
echo $0 ':remote' && git submodule update --remote $0
|
||||||
|
exit
|
||||||
|
elif [ $0 = 'externals/nx_tzdb/tzdb_to_nx' ]; then
|
||||||
|
[ -f $0/CMakeLists.txt ] || git submodule update --force --remote --init -- $0
|
||||||
|
echo $0 ':remote' && git submodule update --remote $0
|
||||||
|
else
|
||||||
|
echo $0 ':update' && git submodule update --init $0 && exit
|
||||||
|
echo $0 ':remote' && git submodule update --remote $0 && exit
|
||||||
|
echo $0 ':failure'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
export -f update_or_checkout
|
||||||
|
grep path .gitmodules | sed 's/.*= //' | xargs -n 1 -I {} bash -c 'update_or_checkout "$@"' {}
|
||||||
|
# Fix for LLVM builds
|
||||||
|
sed -i 's/src\/yuzu\/main.cpp/${CMAKE_SOURCE_DIR}\/src\/yuzu\/main.cpp/g' CMakeModules/FindLLVM.cmake
|
||||||
|
# Only after cloning and everything - fixes issues with Zydis
|
||||||
|
cat > externals/dynarmic/src/dynarmic/common/x64_disassemble.cpp <<EOF
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
namespace Dynarmic::Common {
|
||||||
|
void DumpDisassembledX64(const void* ptr, size_t size) {}
|
||||||
|
std::vector<std::string> DisassembleX64(const void* ptr, size_t size) { return {}; }
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
If having issues with older artifacts, then run `rm -r externals/dynarmic/build externals/dynarmic/externals externals/nx_tzdb/tzdb_to_nx/externals externals/sirit/externals`.
|
||||||
|
|
||||||
|
Configuring CMake with `-DSIRIT_USE_SYSTEM_SPIRV_HEADERS=1 -DCMAKE_CXX_FLAGS="-Wno-error" -DCMAKE_C_FLAGS="-Wno-error -Wno-array-parameter -Wno-stringop-overflow"` is also recommended.
|
||||||
|
|
94
docs/Solaris.md
Normal file
94
docs/Solaris.md
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Building for Solaris
|
||||||
|
|
||||||
|
## Dependencies.
|
||||||
|
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 libraies: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm`.
|
||||||
|
|
||||||
|
fmtlib is not available on repositories and has to be manually built:
|
||||||
|
```sh
|
||||||
|
git clone --recurisve --depth=1 https://github.com/fmtlib/fmt.git
|
||||||
|
cd fmt
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
```
|
||||||
|
|
||||||
|
pkg lz4 doesn't provide a proper CMakeFile to find the library, has to also be manually built:
|
||||||
|
```sh
|
||||||
|
git clone --depth=1 https://github.com/lz4/lz4.git
|
||||||
|
cd lz4
|
||||||
|
gmake
|
||||||
|
sudo gmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
Same goes for zstd:
|
||||||
|
```sh
|
||||||
|
git clone --depth=1 https://github.com/facebook/zstd.git
|
||||||
|
cd zstd
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -B build0 -S build/cmake
|
||||||
|
cmake --build build0
|
||||||
|
cd build0
|
||||||
|
sudo gmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
pkg SDL2 is also not nice to work with on CMake, save yourself some pain and compile it yourself:
|
||||||
|
```sh
|
||||||
|
git clone --depth=1 --branch=release-2.32.8 https://github.com/libsdl-org/SDL
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
```
|
||||||
|
|
||||||
|
Audio is broken in OpenIndiana [see this issue](https://github.com/libsdl-org/SDL/issues/13405), go into `SDL/CMakeLists.txt` and comment out lines 1468:
|
||||||
|
```diff
|
||||||
|
+# set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
|
||||||
|
+# file(GLOB SUN_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/sun/*.c)
|
||||||
|
+# list(APPEND SOURCE_FILES ${SUN_AUDIO_SOURCES})
|
||||||
|
+# set(HAVE_SDL_AUDIO TRUE)
|
||||||
|
```
|
||||||
|
For Solaris this issue does not exist - however PulseAudio crashes on Solaris - so use a different backend.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Build preparations:
|
||||||
|
Run the following command to clone eden with git:
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
```
|
||||||
|
You usually want to add the `--recursive` parameter as it also takes care of the external dependencies for you.
|
||||||
|
|
||||||
|
Now change into the eden directory and create a build directory there:
|
||||||
|
```sh
|
||||||
|
cd eden
|
||||||
|
mkdir build
|
||||||
|
```
|
||||||
|
|
||||||
|
Change into that build directory: `cd build`
|
||||||
|
|
||||||
|
Now choose one option either 1 or 2, but not both as one option overwrites the other.
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Needed for some dependencies that call cc directly (tz)
|
||||||
|
echo '#!/bin/sh' >cc
|
||||||
|
echo 'gcc $@' >>cc
|
||||||
|
chmod +x cc
|
||||||
|
export PATH="$PATH:$PWD"
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Configure**: `cmake -B build -DYUZU_TESTS=OFF -DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF -DYUZU_USE_LLVM_DEMANGLE=OFF -DYUZU_USE_QT_MULTIMEDIA=OFF -DYUZU_USE_QT_WEB_ENGINE=OFF -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_USE_BUNDLED_QT=OFF -DENABLE_QT=OFF -DSDL_AUDIO=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_QT_UPDATE_CHECKER=OFF`.
|
||||||
|
- **Build**: `cmake --build build`.
|
||||||
|
- **Installing**: `sudo cmake --install build`.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`).
|
||||||
|
- If using OpenIndiana, due to a bug in SDL2 cmake configuration; Audio driver defaults to SunOS `<sys/audioio.h>`, which does not exist on OpenIndiana.
|
||||||
|
- Enabling OpenSSL requires compiling OpenSSL manually instead of using the provided one from repositores.
|
42
docs/build/Android.md
vendored
Normal file
42
docs/build/Android.md
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Note: These build instructions are a work-in-progress.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
* [Android Studio](https://developer.android.com/studio)
|
||||||
|
* [NDK 25.2.9519653 and CMake 3.22.1](https://developer.android.com/studio/projects/install-ndk#default-version)
|
||||||
|
* [Git](https://git-scm.com/download)
|
||||||
|
|
||||||
|
### WINDOWS ONLY - Additional Dependencies
|
||||||
|
* **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - **Make sure to select "Desktop development with C++" support in the installer. Make sure to update to the latest version if already installed.**
|
||||||
|
* **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - **Make sure to select Latest SDK.**
|
||||||
|
- A convenience script to install the latest SDK is provided in `.ci\windows\install-vulkan-sdk.ps1`.
|
||||||
|
|
||||||
|
## Cloning Eden with Git
|
||||||
|
```
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden.git
|
||||||
|
```
|
||||||
|
Eden by default will be cloned into -
|
||||||
|
* `C:\Users\<user-name>\eden` on Windows
|
||||||
|
* `~/eden` on Linux
|
||||||
|
* And wherever on macOS
|
||||||
|
|
||||||
|
## Building
|
||||||
|
1. Start Android Studio, on the startup dialog select `Open`.
|
||||||
|
2. Navigate to the `eden/src/android` directory and click on `OK`.
|
||||||
|
3. In `Build > Select Build Variant`, select `release` or `relWithDebInfo` as the "Active build variant".
|
||||||
|
4. Build the project with `Build > Make Project` or run it on an Android device with `Run > Run 'app'`.
|
||||||
|
|
||||||
|
## Building with Terminal
|
||||||
|
1. Download the SDK and NDK from Android Studio.
|
||||||
|
2. Navigate to SDK and NDK paths.
|
||||||
|
3. Then set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT in terminal via
|
||||||
|
`export ANDROID_SDK_ROOT=path/to/sdk`
|
||||||
|
`export ANDROID_NDK_ROOT=path/to/ndk`.
|
||||||
|
4. Navigate to `eden/src/android`.
|
||||||
|
5. Then Build with `./gradlew assemblerelWithDebInfo`.
|
||||||
|
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
|
||||||
|
|
||||||
|
### Script
|
||||||
|
A convenience script for building is provided in `.ci/android/build.sh`. The built APK can be put into an `artifacts` directory via `.ci/android/package.sh`. On Windows, these must be done in the Git Bash or MinGW terminal.
|
||||||
|
|
||||||
|
### Additional Resources
|
||||||
|
https://developer.android.com/studio/intro
|
81
docs/build/FreeBSD.md
vendored
Normal file
81
docs/build/FreeBSD.md
vendored
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
## One word of caution before proceeding.
|
||||||
|
This is not the usual or preferred way to build programs on FreeBSD.
|
||||||
|
As of writing there is no official fresh port available for eden-emu, but it is in the works.
|
||||||
|
After it is available you can find a link to the eden-emu fresh port here and on Escarys github repo.
|
||||||
|
See this build as an App Image alternative for FreeBSD.
|
||||||
|
|
||||||
|
## Dependencies.
|
||||||
|
Before we start we need some dependencies.
|
||||||
|
These dependencies are generally needed to build eden-emu on FreeBSD.
|
||||||
|
|
||||||
|
```
|
||||||
|
devel/cmake
|
||||||
|
devel/sdl20
|
||||||
|
devel/boost-libs
|
||||||
|
devel/catch2
|
||||||
|
devel/libfmt
|
||||||
|
devel/nlohmann-json
|
||||||
|
devel/ninja
|
||||||
|
devel/nasm
|
||||||
|
devel/autoconf
|
||||||
|
devel/pkg-config
|
||||||
|
devel/qt6-base
|
||||||
|
|
||||||
|
multimedia/ffnvcodec-headers
|
||||||
|
multimedia/ffmpeg
|
||||||
|
|
||||||
|
audio/opus
|
||||||
|
|
||||||
|
archivers/liblz4
|
||||||
|
|
||||||
|
lang/gcc12
|
||||||
|
|
||||||
|
graphics/glslang
|
||||||
|
graphics/vulkan-utility-libraries
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Build preparations:
|
||||||
|
Run the following command to clone eden with git:
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
```
|
||||||
|
You usually want to add the `--recursive` parameter as it also takes care of the external dependencies for you.
|
||||||
|
|
||||||
|
Now change into the eden directory and create a build directory there:
|
||||||
|
```sh
|
||||||
|
cd eden
|
||||||
|
mkdir build
|
||||||
|
```
|
||||||
|
|
||||||
|
Change into that build directory:
|
||||||
|
```sh
|
||||||
|
cd build
|
||||||
|
```
|
||||||
|
|
||||||
|
Now choose one option either 1 or 2, but not both as one option overwrites the other.
|
||||||
|
|
||||||
|
#### 1. Building in Release Mode (usually preferred and the most performant choice):
|
||||||
|
```sh
|
||||||
|
cmake .. -GNinja -DYUZU_TESTS=OFF
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Building in Release Mode with debugging symbols (useful if you want to debug errors for a eventual fix):
|
||||||
|
```sh
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the emulator locally:
|
||||||
|
```sh
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional: If you wish to install eden globally onto your system issue the following command:
|
||||||
|
```sh
|
||||||
|
sudo ninja install
|
||||||
|
```
|
||||||
|
OR
|
||||||
|
```sh
|
||||||
|
doas -- ninja install
|
||||||
|
```
|
135
docs/build/Linux.md
vendored
Normal file
135
docs/build/Linux.md
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
You'll need to download and install the following to build Eden:
|
||||||
|
|
||||||
|
* [GCC](https://gcc.gnu.org/) v11+ (for C++20 support) & misc
|
||||||
|
* If GCC 12 is installed, [Clang](https://clang.llvm.org/) v14+ is required for compiling
|
||||||
|
* [CMake](https://www.cmake.org/) 3.22+
|
||||||
|
|
||||||
|
The following are handled by Eden's externals:
|
||||||
|
|
||||||
|
* [FFmpeg](https://ffmpeg.org/)
|
||||||
|
* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+
|
||||||
|
* [opus](https://opus-codec.org/downloads/)
|
||||||
|
|
||||||
|
All other dependencies will be downloaded by [vcpkg](https://vcpkg.io/) if needed:
|
||||||
|
|
||||||
|
* [Boost](https://www.boost.org/users/download/) 1.79.0+
|
||||||
|
* [Catch2](https://github.com/catchorg/Catch2) 2.13.7 - 2.13.9
|
||||||
|
* [fmt](https://fmt.dev/) 8.0.1+
|
||||||
|
* [lz4](http://www.lz4.org) 1.8+
|
||||||
|
* [nlohmann_json](https://github.com/nlohmann/json) 3.8+
|
||||||
|
* [OpenSSL](https://www.openssl.org/source/)
|
||||||
|
* [ZLIB](https://www.zlib.net/) 1.2+
|
||||||
|
* [zstd](https://facebook.github.io/zstd/) 1.5+
|
||||||
|
|
||||||
|
If an ARM64 build is intended, export `VCPKG_FORCE_SYSTEM_BINARIES=1`.
|
||||||
|
|
||||||
|
Dependencies are listed here as commands that can be copied/pasted. Of course, they should be inspected before being run.
|
||||||
|
|
||||||
|
- Arch / Manjaro:
|
||||||
|
- `sudo pacman -Syu --needed base-devel boost catch2 cmake ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip`
|
||||||
|
- Building with QT Web Engine requires `qt6-webengine` as well.
|
||||||
|
- Proper wayland support requires `qt6-wayland`
|
||||||
|
- GCC 11 or later is required.
|
||||||
|
- Ubuntu / Linux Mint / Debian:
|
||||||
|
- `sudo apt-get install autoconf cmake g++-11 gcc-11 git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qtbase6-dev qtbase6-private-dev qtwebengine6-dev qtmultimedia6-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev`
|
||||||
|
- Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
|
||||||
|
- Users need to manually specify building with QT Web Engine enabled. This is done using the parameter `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake.
|
||||||
|
- Users need to manually specify building with GCC 11. This can be done by adding the parameters `-DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11` when running CMake. i.e.
|
||||||
|
- Users need to manually disable building SDL2 from externals if they intend to use the version provided by their system by adding the parameters `-DYUZU_USE_EXTERNAL_SDL2=OFF`
|
||||||
|
|
||||||
|
```
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake .. -GNinja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
|
||||||
|
```
|
||||||
|
|
||||||
|
- Fedora:
|
||||||
|
- `sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt5-linguist qt5-qtbase{-private,}-devel qt5-qtwebengine-devel qt5-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel`
|
||||||
|
- Fedora 32 or later is required.
|
||||||
|
- Due to GCC 12, Fedora 36 or later users need to install `clang`, and configure CMake to use it via `-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang`
|
||||||
|
- CMake arguments to force system libraries:
|
||||||
|
- SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF`
|
||||||
|
- FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF`
|
||||||
|
- [RPM Fusion](https://rpmfusion.org/) (free) is required to install `ffmpeg-devel`
|
||||||
|
|
||||||
|
### Cloning Eden with Git
|
||||||
|
|
||||||
|
**Master:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
cd eden
|
||||||
|
```
|
||||||
|
|
||||||
|
The `--recursive` option automatically clones the required Git submodules.
|
||||||
|
|
||||||
|
### Building Eden in Release Mode (Optimised)
|
||||||
|
|
||||||
|
If you need to run ctests, you can disable `-DYUZU_TESTS=OFF` and install Catch2.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -GNinja -DYUZU_TESTS=OFF
|
||||||
|
ninja
|
||||||
|
sudo ninja install
|
||||||
|
```
|
||||||
|
You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..`
|
||||||
|
|
||||||
|
`-DYUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS=OFF` might be needed if ninja command failed with `undefined reference to symbol 'spvOptimizerOptionsCreate`, reason currently unknown
|
||||||
|
|
||||||
|
Optionally, you can use `cmake-gui ..` to adjust various options (e.g. disable the Qt GUI).
|
||||||
|
|
||||||
|
### Building Eden in Debug Mode (Slow)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DYUZU_TESTS=OFF
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building with debug symbols
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU -DYUZU_TESTS=OFF
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building with Scripts
|
||||||
|
A convenience script for building is provided in `.ci/linux/build.sh`. You must provide an arch target for optimization, e.g. `.ci/linux/build.sh amd64`. Valid targets:
|
||||||
|
- `legacy`: x86_64 generic, only needed for CPUs older than 2013 or so
|
||||||
|
- `amd64`: x86_64-v3, for CPUs newer than 2013 or so
|
||||||
|
- `steamdeck` / `zen2`: For Steam Deck or Zen >= 2 AMD CPUs (untested on Intel)
|
||||||
|
- `rog-ally` / `allyx` / `zen4`: For ROG Ally X or Zen >= 4 AMD CPUs (untested on Intel)
|
||||||
|
- `aarch64`: For armv8-a CPUs, older than mid-2021 or so
|
||||||
|
- `armv9`: For armv9-a CPUs, newer than mid-2021 or so
|
||||||
|
- `native`: Optimize to your native host architecture
|
||||||
|
|
||||||
|
Extra flags to pass to CMake should be passed after the arch target.
|
||||||
|
|
||||||
|
Additional environment variables can be used to control building:
|
||||||
|
- `NPROC`: Number of threads to use for compilation (defaults to all)
|
||||||
|
- `TARGET`: Set to `appimage` to disable standalone `eden-cli` and `eden-room` executables
|
||||||
|
- `BUILD_TYPE`: Sets the build type to use. Defaults to `Release`
|
||||||
|
|
||||||
|
The following environment variables are boolean flags. Set to `true` to enable or `false` to disable:
|
||||||
|
- `DEVEL` (default FALSE): Disable Qt update checker
|
||||||
|
- `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine
|
||||||
|
- `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia
|
||||||
|
|
||||||
|
After building, an AppImage can be packaged via `.ci/linux/package.sh`. This script takes the same arch targets as the build script. If the build was created in a different directory, you can specify its path relative to the source directory, e.g. `.ci/linux/package.sh amd64 build-appimage`. Additionally, set the `DEVEL` environment variable to `true` to change the app name to `Eden Nightly`.
|
||||||
|
|
||||||
|
### Running without installing
|
||||||
|
|
||||||
|
After building, the binaries `eden` and `eden-cmd` (depending on your build options) will end up in `build/bin/`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SDL
|
||||||
|
cd build/bin/
|
||||||
|
./eden-cmd
|
||||||
|
|
||||||
|
# Qt
|
||||||
|
cd build/bin/
|
||||||
|
./eden
|
||||||
|
```
|
195
docs/build/Windows.md
vendored
Normal file
195
docs/build/Windows.md
vendored
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
# THIS GUIDE IS INTENDED FOR DEVELOPERS ONLY, SUPPORT WILL ONLY BE GIVEN IF YOU'RE A DEVELOPER.
|
||||||
|
|
||||||
|
## Method I: MSVC Build for Windows
|
||||||
|
|
||||||
|
### Minimal Dependencies
|
||||||
|
|
||||||
|
On Windows, all library dependencies are automatically included within the `externals` folder, or can be downloaded on-demand. To build Eden, you need to install:
|
||||||
|
|
||||||
|
* **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - **Make sure to select C++ support in the installer. Make sure to update to the latest version if already installed.**
|
||||||
|
* **[CMake](https://cmake.org/download/)** - Used to generate Visual Studio project files. Does not matter if either 32-bit or 64-bit version is installed.
|
||||||
|
* **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - **Make sure to select Latest SDK.**
|
||||||
|
- A convenience script to install the latest SDK is provided in `.ci\windows\install-vulkan-sdk.ps1`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* **Git** - We recommend [Git for Windows](https://gitforwindows.org).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* While installing Git Bash, you should tell it to include Git in your system path. (Choose the "Git from the command line and also from 3rd-party software" option.) If you missed that, don't worry, you'll just have to manually tell CMake where your git.exe is, since it's used to include version info into the built executable.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Cloning Eden with Git
|
||||||
|
|
||||||
|
**Master:**
|
||||||
|
```cmd
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
cd eden
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* *(Note: eden by default downloads to `C:\Users\<user-name>\eden` (Master)
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
* Open the CMake GUI application and point it to the `eden` (Master)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* For the build directory, use a `/build` subdirectory inside the source directory or some other directory of your choice. (Tell CMake to create it.)
|
||||||
|
|
||||||
|
* Click the "Configure" button and choose `Visual Studio 17 2022`, with `x64` for the optional platform.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* *(Note: If you used GitHub's own app to clone, run `git submodule update --init --recursive` to get the remaining dependencies)*
|
||||||
|
|
||||||
|
* If you get an error about missing packages, enable `YUZU_USE_BUNDLED_VCPKG`, and then click Configure again.
|
||||||
|
|
||||||
|
* *(You may also want to disable `YUZU_TESTS` in this case since Catch2 is not yet supported with this.)*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Click "Generate" to create the project files.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Open the solution file `yuzu.sln` in Visual Studio 2022, which is located in the build folder.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Depending if you want a graphical user interface or not (`eden` has the graphical user interface, while `eden-cmd` doesn't), select `eden` or `eden-cmd` in the Solution Explorer, right-click and `Set as StartUp Project`.
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
* Select the appropriate build type, Debug for debug purposes or Release for performance (in case of doubt choose Release).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Right-click the project you want to build and press Build in the submenu or press F5.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Method II: MinGW-w64 Build with MSYS2
|
||||||
|
|
||||||
|
### Prerequisites to install
|
||||||
|
|
||||||
|
* [MSYS2](https://www.msys2.org)
|
||||||
|
* [Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows) - **Make sure to select Latest SDK.**
|
||||||
|
* Make sure to follow the instructions and update to the latest version by running `pacman -Syu` as many times as needed.
|
||||||
|
|
||||||
|
### Install eden dependencies for MinGW-w64
|
||||||
|
|
||||||
|
* Open the `MSYS2 MinGW 64-bit` (mingw64.exe) shell
|
||||||
|
* Download and install all dependencies using: `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper`
|
||||||
|
* Add MinGW binaries to the PATH: `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc`
|
||||||
|
* Add glslangValidator to the PATH: `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc`
|
||||||
|
|
||||||
|
### Clone the eden repository with Git
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
cd eden
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run the following commands to build eden (dynamically linked build)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake -G "MSYS Makefiles" -DYUZU_USE_BUNDLED_VCPKG=ON -DYUZU_TESTS=OFF ..
|
||||||
|
make -j$(nproc)
|
||||||
|
# test eden out with
|
||||||
|
./bin/eden.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
* *(Note: This build is not a static build meaning that you need to include all of the DLLs with the .exe in order to use it!)*
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
```Bash
|
||||||
|
cp externals/ffmpeg-*/bin/*.dll bin/
|
||||||
|
```
|
||||||
|
|
||||||
|
Bonus Note: Running programs from inside `MSYS2 MinGW x64` shell has a different %PATH% than directly from explorer. This different %PATH% has the locations of the other DLLs required.
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### Building without Qt (Optional)
|
||||||
|
|
||||||
|
Doesn't require the rather large Qt dependency, but you will lack a GUI frontend:
|
||||||
|
|
||||||
|
* Pass the `-DENABLE_QT=no` flag to cmake
|
||||||
|
|
||||||
|
## Method III: CLion Environment Setup
|
||||||
|
|
||||||
|
### Minimal Dependencies
|
||||||
|
|
||||||
|
To build eden, you need to install the following:
|
||||||
|
|
||||||
|
* [CLion](https://www.jetbrains.com/clion/) - This IDE is not free; for a free alternative, check Method I
|
||||||
|
* [Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows) - Make sure to select the Latest SDK.
|
||||||
|
|
||||||
|
### Cloning eden with CLion
|
||||||
|
|
||||||
|
* Clone the Repository:
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Building & Setup
|
||||||
|
|
||||||
|
* Once Cloned, You will be taken to a prompt like the image below:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Set the settings to the image below:
|
||||||
|
* Change `Build type: Release`
|
||||||
|
* Change `Name: Release`
|
||||||
|
* Change `Toolchain Visual Studio`
|
||||||
|
* Change `Generator: Let CMake decide`
|
||||||
|
* Change `Build directory: build`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient.
|
||||||
|
* Once this process has been completed (No loading bar bottom right), you can now build eden
|
||||||
|
* In the top right, click on the drop-down menu, select all configurations, then select eden
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Building from the command line with MSVC
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
cd eden
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G "Visual Studio 17 2022" -A x64
|
||||||
|
cmake --build . --config Release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building with Scripts
|
||||||
|
A convenience script for building is provided in `.ci/windows/build.sh`. You must run this with Bash, e.g. Git Bash or MinGW TTY. To use this script, you must have windeployqt installed (usually bundled with Qt) and set the `WINDEPLOYQT` environment variable to its canonical Bash location, e.g. `WINDEPLOYQT="/c/Qt/6.9.1/msvc2022_64/bin/windeployqt6.exe" .ci/windows/build.sh`.
|
||||||
|
|
||||||
|
Extra CMake flags should be placed in the arguments of the script.
|
||||||
|
|
||||||
|
Additional environment variables can be used to control building:
|
||||||
|
- `BUILD_TYPE`: Sets the build type to use. Defaults to `Release`
|
||||||
|
|
||||||
|
The following environment variables are boolean flags. Set to `true` to enable or `false` to disable:
|
||||||
|
- `DEVEL` (default FALSE): Disable Qt update checker
|
||||||
|
- `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine
|
||||||
|
- `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia
|
||||||
|
- `BUNDLE_QT` (default FALSE): Use bundled Qt
|
||||||
|
* Note that using system Qt requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`, e.g. `.ci/windows/build.sh -DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6`
|
||||||
|
|
||||||
|
After building, a zip can be packaged via `.ci/windows/package.sh`. Note that you must have 7-zip installed and in your PATH. The resulting zip will be placed into `artifacts` in the source directory.
|
105
docs/build/macOS.md
vendored
Normal file
105
docs/build/macOS.md
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
Please note this article is intended for development, and eden on macOS is not currently ready for regular use.
|
||||||
|
|
||||||
|
This article was written for developers. eden support for macOS is not ready for casual use.
|
||||||
|
|
||||||
|
## Method I: ninja
|
||||||
|
---
|
||||||
|
If you are compiling on Intel Mac or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` to `/usr/local`.
|
||||||
|
|
||||||
|
Install dependencies from Homebrew:
|
||||||
|
```sh
|
||||||
|
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zlib zstd cmake Catch2 molten-vk vulkan-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
Clone the repo
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
|
||||||
|
cd eden
|
||||||
|
```
|
||||||
|
|
||||||
|
Build for release
|
||||||
|
```sh
|
||||||
|
mkdir build && cd build
|
||||||
|
|
||||||
|
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
|
||||||
|
|
||||||
|
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
|
||||||
|
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON
|
||||||
|
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..`
|
||||||
|
|
||||||
|
Build with debug symbols (vcpkg is not currently used due to broken boost-context library):
|
||||||
|
```sh
|
||||||
|
mkdir build && cd build
|
||||||
|
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the output:
|
||||||
|
```
|
||||||
|
bin/eden.app/Contents/MacOS/eden
|
||||||
|
```
|
||||||
|
|
||||||
|
## Method II: Xcode
|
||||||
|
|
||||||
|
---
|
||||||
|
If you are compiling on Intel Mac or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` to `/usr/local`.
|
||||||
|
|
||||||
|
Install dependencies from Homebrew:
|
||||||
|
```sh
|
||||||
|
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zlib zstd cmake Catch2 molten-vk vulkan-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
Clone the repo
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
|
||||||
|
|
||||||
|
cd eden
|
||||||
|
```
|
||||||
|
|
||||||
|
Build for release
|
||||||
|
```sh
|
||||||
|
mkdir build && cd build
|
||||||
|
|
||||||
|
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
|
||||||
|
|
||||||
|
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
|
||||||
|
|
||||||
|
cmake .. -GXcode -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON
|
||||||
|
|
||||||
|
xcodebuild build -project eden.xcodeproj -scheme "eden" -configuration "RelWithDebInfo"
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..`
|
||||||
|
|
||||||
|
Build with debug symbols (vcpkg is not currently used due to broken boost-context library):
|
||||||
|
```sh
|
||||||
|
mkdir build && cd build
|
||||||
|
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
|
||||||
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the output:
|
||||||
|
```
|
||||||
|
bin/eden.app/Contents/MacOS/eden
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
To run with MoltenVK, install additional dependencies:
|
||||||
|
```sh
|
||||||
|
brew install molten-vk vulkan-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with Vulkan loader path:
|
||||||
|
```sh
|
||||||
|
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
|
||||||
|
bin/eden.app/Contents/MacOS/eden
|
||||||
|
```
|
2
externals/dynarmic/externals/catch
vendored
2
externals/dynarmic/externals/catch
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 74fcff6e5b190fb833a231b7f7c1829e3c3ac54d
|
Subproject commit 5aa8d113215bd9a97ecc1a2f3fc9506947a2fa57
|
2
externals/dynarmic/externals/fmt
vendored
2
externals/dynarmic/externals/fmt
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 02de29e00321787fa515ca60f0f5911e61892dc6
|
Subproject commit 35dcc58263d6b55419a5932bd6b0b3029a0a8c00
|
2
externals/dynarmic/externals/xbyak
vendored
2
externals/dynarmic/externals/xbyak
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 44a72f369268f7d552650891b296693e91db86bb
|
Subproject commit 12557954c68a780563f9ab9fc24a3a156c96cba1
|
2
externals/dynarmic/externals/zycore-c
vendored
2
externals/dynarmic/externals/zycore-c
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 7ad36e52110b39cfb62b47bfdb6def94ac531309
|
Subproject commit 75a36c45ae1ad382b0f4e0ede0af84c11ee69928
|
2
externals/dynarmic/externals/zydis
vendored
2
externals/dynarmic/externals/zydis
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 6372690e30389a94db65ece2d8a1f0a2310475ed
|
Subproject commit c2d2bab0255e53a7c3e9b615f4eb69449eb942df
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
* Copyright (c) 2019 MerryMage
|
* Copyright (c) 2019 MerryMage
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
@ -13,6 +16,9 @@
|
||||||
# ifndef __OpenBSD__
|
# ifndef __OpenBSD__
|
||||||
# include <ucontext.h>
|
# include <ucontext.h>
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef __sun__
|
||||||
|
# include <sys/regset.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -145,9 +151,9 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
|
|
||||||
#ifndef MCL_ARCHITECTURE_RISCV
|
#ifndef MCL_ARCHITECTURE_RISCV
|
||||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
|
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
|
||||||
# ifndef __OpenBSD__
|
#ifndef __OpenBSD__
|
||||||
auto& mctx = ucontext->uc_mcontext;
|
auto& mctx = ucontext->uc_mcontext;
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||||
|
@ -167,6 +173,9 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
# elif defined(__OpenBSD__)
|
# elif defined(__OpenBSD__)
|
||||||
# define CTX_RIP (ucontext->sc_rip)
|
# define CTX_RIP (ucontext->sc_rip)
|
||||||
# define CTX_RSP (ucontext->sc_rsp)
|
# define CTX_RSP (ucontext->sc_rsp)
|
||||||
|
# elif defined(__sun__)
|
||||||
|
# define CTX_RIP (mctx.gregs[REG_RIP])
|
||||||
|
# define CTX_RSP (mctx.gregs[REG_RSP])
|
||||||
# else
|
# else
|
||||||
# error "Unknown platform"
|
# error "Unknown platform"
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -415,21 +415,54 @@ void RegAlloc::ReleaseStackSpace(const size_t stack_space) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
HostLoc RegAlloc::SelectARegister(const boost::container::static_vector<HostLoc, 28>& desired_locations) const noexcept {
|
HostLoc RegAlloc::SelectARegister(const boost::container::static_vector<HostLoc, 28>& desired_locations) const noexcept {
|
||||||
boost::container::static_vector<HostLoc, 28> candidates = desired_locations; //Who let someone copy an ENTIRE VECTOR here?
|
// TODO(lizzie): Overspill causes issues (reads to 0 and such) on some games, I need to make a testbench
|
||||||
|
// to later track this down - however I just modified the LRU algo so it prefers empty registers first
|
||||||
// Find all locations that have not been allocated..
|
// we need to test high register pressure (and spills, maybe 32 regs?)
|
||||||
const auto allocated_locs = std::partition(candidates.begin(), candidates.end(), [this](auto loc) noexcept {
|
|
||||||
return !this->LocInfo(loc).IsLocked();
|
|
||||||
});
|
|
||||||
candidates.erase(allocated_locs, candidates.end());
|
|
||||||
ASSERT_MSG(!candidates.empty(), "All candidate registers have already been allocated");
|
|
||||||
|
|
||||||
// Selects the best location out of the available locations.
|
// Selects the best location out of the available locations.
|
||||||
|
// NOTE: Using last is BAD because new REX prefix for each insn using the last regs
|
||||||
// TODO: Actually do LRU or something. Currently we just try to pick something without a value if possible.
|
// TODO: Actually do LRU or something. Currently we just try to pick something without a value if possible.
|
||||||
auto const it = std::find_if(candidates.begin(), candidates.end(), [this](auto const loc) noexcept {
|
auto min_lru_counter = size_t(-1);
|
||||||
return this->LocInfo(loc).IsEmpty();
|
auto it_candidate = desired_locations.cend(); //default fallback if everything fails
|
||||||
});
|
auto it_rex_candidate = desired_locations.cend();
|
||||||
return it != candidates.end() ? *it : candidates.front();
|
auto it_empty_candidate = desired_locations.cend();
|
||||||
|
for (auto it = desired_locations.cbegin(); it != desired_locations.cend(); it++) {
|
||||||
|
auto const& loc_info = LocInfo(*it);
|
||||||
|
// Abstain from using upper registers unless absolutely nescesary
|
||||||
|
if (loc_info.IsLocked()) {
|
||||||
|
// skip, not suitable for allocation
|
||||||
|
} else {
|
||||||
|
if (loc_info.lru_counter < min_lru_counter) {
|
||||||
|
if (loc_info.IsEmpty())
|
||||||
|
it_empty_candidate = it;
|
||||||
|
// Otherwise a "quasi"-LRU
|
||||||
|
min_lru_counter = loc_info.lru_counter;
|
||||||
|
if (*it >= HostLoc::R8 && *it <= HostLoc::R15) {
|
||||||
|
it_rex_candidate = it;
|
||||||
|
} else {
|
||||||
|
it_candidate = it;
|
||||||
|
}
|
||||||
|
if (min_lru_counter == 0)
|
||||||
|
break; //early exit
|
||||||
|
}
|
||||||
|
// only if not assigned (i.e for failcase of all LRU=0)
|
||||||
|
if (it_empty_candidate == desired_locations.cend() && loc_info.IsEmpty())
|
||||||
|
it_empty_candidate = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Final resolution goes as follows:
|
||||||
|
// 1 => Try an empty candidate
|
||||||
|
// 2 => Try normal candidate (no REX prefix)
|
||||||
|
// 3 => Try using a REX prefixed one
|
||||||
|
// We avoid using REX-addressable registers because they add +1 REX prefix which
|
||||||
|
// do we really need? The trade-off may not be worth it.
|
||||||
|
auto const it_final = it_empty_candidate != desired_locations.cend()
|
||||||
|
? it_empty_candidate : it_candidate != desired_locations.cend()
|
||||||
|
? it_candidate : it_rex_candidate;
|
||||||
|
ASSERT_MSG(it_final != desired_locations.cend(), "All candidate registers have already been allocated");
|
||||||
|
// Evil magic - increment LRU counter (will wrap at 256)
|
||||||
|
const_cast<RegAlloc*>(this)->LocInfo(*it_final).lru_counter++;
|
||||||
|
return *it_final;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc) noexcept {
|
void RegAlloc::DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc) noexcept {
|
||||||
|
|
|
@ -92,8 +92,8 @@ private:
|
||||||
uint8_t max_bit_width = 0; //Valid values: 1,2,4,8,16,32,128
|
uint8_t max_bit_width = 0; //Valid values: 1,2,4,8,16,32,128
|
||||||
bool is_scratch : 1 = false; //1
|
bool is_scratch : 1 = false; //1
|
||||||
bool is_set_last_use : 1 = false; //1
|
bool is_set_last_use : 1 = false; //1
|
||||||
|
alignas(16) uint8_t lru_counter = 0; //1
|
||||||
alignas(16) char padding;
|
friend class RegAlloc;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HostLocInfo) == 64);
|
static_assert(sizeof(HostLocInfo) == 64);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ private:
|
||||||
/// Used when an entirely new slab is needed
|
/// Used when an entirely new slab is needed
|
||||||
/// due the current one running out of usable space.
|
/// due the current one running out of usable space.
|
||||||
void AllocateNewSlab() noexcept {
|
void AllocateNewSlab() noexcept {
|
||||||
current_slab = static_cast<char*>(std::malloc(object_size * slab_size));
|
current_slab = static_cast<char*>(std::aligned_alloc(object_size, object_size * slab_size));
|
||||||
current_ptr = current_slab;
|
current_ptr = current_slab;
|
||||||
remaining = slab_size;
|
remaining = slab_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
@ -22,12 +21,7 @@
|
||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
|
|
||||||
Block::Block(const LocationDescriptor& location)
|
Block::Block(const LocationDescriptor& location)
|
||||||
: location{location},
|
: location{location}, end_location{location}, cond{Cond::AL}, instruction_alloc_pool{std::make_unique<InstPool>()} {
|
||||||
end_location{location},
|
|
||||||
cond{Cond::AL},
|
|
||||||
instruction_alloc_pool{std::make_unique<std::remove_reference_t<decltype(*instruction_alloc_pool)>>()}
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepends a new instruction to this basic block before the insertion point,
|
/// Prepends a new instruction to this basic block before the insertion point,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
#include "dynarmic/ir/terminal.h"
|
#include "dynarmic/ir/terminal.h"
|
||||||
#include "dynarmic/ir/value.h"
|
#include "dynarmic/ir/value.h"
|
||||||
#include "dynarmic/ir/dense_list.h"
|
|
||||||
#include "dynarmic/common/memory_pool.h"
|
#include "dynarmic/common/memory_pool.h"
|
||||||
|
|
||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
|
@ -171,8 +170,9 @@ private:
|
||||||
LocationDescriptor end_location;
|
LocationDescriptor end_location;
|
||||||
/// Conditional to pass in order to execute this block
|
/// Conditional to pass in order to execute this block
|
||||||
Cond cond;
|
Cond cond;
|
||||||
|
using InstPool = Common::Pool<sizeof(Inst), 0x200000UL / sizeof(Inst)>;
|
||||||
/// Memory pool for instruction list
|
/// Memory pool for instruction list
|
||||||
std::unique_ptr<Common::Pool<sizeof(Inst), 2097152UL / sizeof(Inst)>> instruction_alloc_pool;
|
std::unique_ptr<InstPool> instruction_alloc_pool;
|
||||||
/// Terminal instruction of this block.
|
/// Terminal instruction of this block.
|
||||||
Terminal terminal = Term::Invalid{};
|
Terminal terminal = Term::Invalid{};
|
||||||
/// Number of cycles this block takes to execute if the conditional fails.
|
/// Number of cycles this block takes to execute if the conditional fails.
|
||||||
|
|
|
@ -23,7 +23,7 @@ constexpr size_t max_arg_count = 4;
|
||||||
/// A representation of a microinstruction. A single ARM/Thumb instruction may be
|
/// A representation of a microinstruction. A single ARM/Thumb instruction may be
|
||||||
/// converted into zero or more microinstructions.
|
/// converted into zero or more microinstructions.
|
||||||
//class Inst final {
|
//class Inst final {
|
||||||
class Inst final : public mcl::intrusive_list_node<Inst> {
|
class alignas(64) Inst final : public mcl::intrusive_list_node<Inst> {
|
||||||
public:
|
public:
|
||||||
explicit Inst(Opcode op) : op(op) {}
|
explicit Inst(Opcode op) : op(op) {}
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ private:
|
||||||
void UndoUse(const Value& value);
|
void UndoUse(const Value& value);
|
||||||
|
|
||||||
// TODO: so much padding wasted with mcl::intrusive_node
|
// TODO: so much padding wasted with mcl::intrusive_node
|
||||||
// 16 + 1, 24
|
// 17
|
||||||
Opcode op; //2 (6)
|
Opcode op; // 20(4)
|
||||||
// Linked list of pseudooperations associated with this instruction.
|
// Linked list of pseudooperations associated with this instruction.
|
||||||
Inst* next_pseudoop = nullptr; //8 (14)
|
Inst* next_pseudoop = nullptr; // 24(8)
|
||||||
unsigned use_count = 0; //4 (0)
|
unsigned use_count = 0; // 32(4)
|
||||||
unsigned name = 0; //4 (4)
|
unsigned name = 0; // 36(4)
|
||||||
alignas(64) std::array<Value, max_arg_count> args; //16 * 4 = 64 (1 cache line)
|
alignas(64) std::array<Value, max_arg_count> args; //16 * 4 = 64 (1 cache line)
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Inst) == 128);
|
static_assert(sizeof(Inst) == 128);
|
||||||
|
|
|
@ -539,7 +539,8 @@ TEST_CASE("arm: Memory access (fastmem)", "[arm][A32]") {
|
||||||
char* backing_memory = reinterpret_cast<char*>(std::align(page_size, memory_size, buffer_ptr, buffer_size_nconst));
|
char* backing_memory = reinterpret_cast<char*>(std::align(page_size, memory_size, buffer_ptr, buffer_size_nconst));
|
||||||
|
|
||||||
A32FastmemTestEnv env{backing_memory};
|
A32FastmemTestEnv env{backing_memory};
|
||||||
Dynarmic::A32::UserConfig config{&env};
|
Dynarmic::A32::UserConfig config{};
|
||||||
|
config.callbacks = &env;
|
||||||
config.fastmem_pointer = reinterpret_cast<uintptr_t>(backing_memory);
|
config.fastmem_pointer = reinterpret_cast<uintptr_t>(backing_memory);
|
||||||
config.recompile_on_fastmem_failure = false;
|
config.recompile_on_fastmem_failure = false;
|
||||||
config.processor_id = 0;
|
config.processor_id = 0;
|
||||||
|
|
250
externals/dynarmic/tests/A64/a64.cpp
vendored
250
externals/dynarmic/tests/A64/a64.cpp
vendored
File diff suppressed because one or more lines are too long
4
externals/dynarmic/tests/A64/fp_min_max.cpp
vendored
4
externals/dynarmic/tests/A64/fp_min_max.cpp
vendored
|
@ -64,7 +64,9 @@ u32 force_default_nan(u32 value) {
|
||||||
template<typename Fn>
|
template<typename Fn>
|
||||||
void run_test(u32 instruction, Fn fn) {
|
void run_test(u32 instruction, Fn fn) {
|
||||||
A64TestEnv env;
|
A64TestEnv env;
|
||||||
A64::Jit jit{A64::UserConfig{&env}};
|
A64::UserConfig jit_user_config{};
|
||||||
|
jit_user_config.callbacks = &env;
|
||||||
|
A64::Jit jit{jit_user_config};
|
||||||
|
|
||||||
env.code_mem.emplace_back(instruction); // FMAX S0, S1, S2
|
env.code_mem.emplace_back(instruction); // FMAX S0, S1, S2
|
||||||
env.code_mem.emplace_back(0x14000000); // B .
|
env.code_mem.emplace_back(0x14000000); // B .
|
||||||
|
|
|
@ -154,7 +154,8 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dynarmic::A64::UserConfig GetUserConfig(A64TestEnv& jit_env) {
|
static Dynarmic::A64::UserConfig GetUserConfig(A64TestEnv& jit_env) {
|
||||||
Dynarmic::A64::UserConfig jit_user_config{&jit_env};
|
Dynarmic::A64::UserConfig jit_user_config{};
|
||||||
|
jit_user_config.callbacks = &jit_env;
|
||||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
||||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||||
jit_user_config.dczid_el0 = 7;
|
jit_user_config.dczid_el0 = 7;
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") {
|
TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") {
|
||||||
A64TestEnv env;
|
A64TestEnv env;
|
||||||
Dynarmic::A64::UserConfig conf{&env};
|
Dynarmic::A64::UserConfig conf{};
|
||||||
|
conf.callbacks = &env;
|
||||||
conf.page_table = nullptr;
|
conf.page_table = nullptr;
|
||||||
conf.detect_misaligned_access_via_page_table = 128;
|
conf.detect_misaligned_access_via_page_table = 128;
|
||||||
conf.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
conf.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
||||||
|
|
|
@ -12,8 +12,8 @@ using namespace Dynarmic;
|
||||||
|
|
||||||
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements", "[a64]") {
|
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements", "[a64]") {
|
||||||
A64TestEnv env;
|
A64TestEnv env;
|
||||||
|
A64::UserConfig conf{};
|
||||||
A64::UserConfig conf{&env};
|
conf.callbacks = &env;
|
||||||
A64::Jit jit{conf};
|
A64::Jit jit{conf};
|
||||||
|
|
||||||
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
||||||
|
@ -64,8 +64,8 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have
|
||||||
|
|
||||||
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements 2", "[a64]") {
|
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements 2", "[a64]") {
|
||||||
A64TestEnv env;
|
A64TestEnv env;
|
||||||
|
A64::UserConfig conf{};
|
||||||
A64::UserConfig conf{&env};
|
conf.callbacks = &env;
|
||||||
A64::Jit jit{conf};
|
A64::Jit jit{conf};
|
||||||
|
|
||||||
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
||||||
|
|
232
externals/dynarmic/tests/test_generator.cpp
vendored
232
externals/dynarmic/tests/test_generator.cpp
vendored
|
@ -23,6 +23,7 @@
|
||||||
#include "./rand_int.h"
|
#include "./rand_int.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
|
#include "dynarmic/common/llvm_disassemble.h"
|
||||||
#include "dynarmic/frontend/A32/ITState.h"
|
#include "dynarmic/frontend/A32/ITState.h"
|
||||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/a32_types.h"
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
|
@ -396,39 +397,41 @@ Dynarmic::A32::UserConfig GetA32UserConfig(TestEnv& testenv, bool noopt) {
|
||||||
|
|
||||||
template<size_t num_jit_reruns = 1, typename TestEnv>
|
template<size_t num_jit_reruns = 1, typename TestEnv>
|
||||||
void RunTestInstance(Dynarmic::A32::Jit& jit,
|
void RunTestInstance(Dynarmic::A32::Jit& jit,
|
||||||
TestEnv& jit_env,
|
TestEnv& jit_env,
|
||||||
const std::array<u32, 16>& regs,
|
const std::array<u32, 16>& regs,
|
||||||
const std::array<u32, 64>& vecs,
|
const std::array<u32, 64>& vecs,
|
||||||
const std::vector<typename TestEnv::InstructionType>& instructions,
|
const std::vector<typename TestEnv::InstructionType>& instructions,
|
||||||
const u32 cpsr,
|
const u32 cpsr,
|
||||||
const u32 fpscr,
|
const u32 fpscr,
|
||||||
const size_t ticks_left) {
|
const size_t ticks_left,
|
||||||
|
const bool show_disas) {
|
||||||
const u32 initial_pc = regs[15];
|
const u32 initial_pc = regs[15];
|
||||||
const u32 num_words = initial_pc / sizeof(typename TestEnv::InstructionType);
|
const u32 num_words = initial_pc / sizeof(typename TestEnv::InstructionType);
|
||||||
const u32 code_mem_size = num_words + static_cast<u32>(instructions.size());
|
const u32 code_mem_size = num_words + static_cast<u32>(instructions.size());
|
||||||
|
|
||||||
fmt::print("instructions:");
|
if (show_disas) {
|
||||||
for (auto instruction : instructions) {
|
fmt::print("instructions:\n");
|
||||||
if constexpr (sizeof(decltype(instruction)) == 2) {
|
auto current_pc = initial_pc;
|
||||||
fmt::print(" {:04x}", instruction);
|
for (auto instruction : instructions) {
|
||||||
} else {
|
if constexpr (sizeof(decltype(instruction)) == 2) {
|
||||||
fmt::print(" {:08x}", instruction);
|
fmt::print("{:04x} ?\n", instruction);
|
||||||
|
} else {
|
||||||
|
fmt::print("{}", Dynarmic::Common::DisassembleAArch64(instruction, current_pc));
|
||||||
|
}
|
||||||
|
current_pc += sizeof(decltype(instruction));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
|
|
||||||
fmt::print("initial_regs:");
|
fmt::print("initial_regs:");
|
||||||
for (u32 i : regs) {
|
for (u32 i : regs)
|
||||||
fmt::print(" {:08x}", i);
|
fmt::print(" {:08x}", i);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("initial_vecs:");
|
||||||
|
for (u32 i : vecs)
|
||||||
|
fmt::print(" {:08x}", i);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("initial_cpsr: {:08x}\n", cpsr);
|
||||||
|
fmt::print("initial_fpcr: {:08x}\n", fpscr);
|
||||||
}
|
}
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("initial_vecs:");
|
|
||||||
for (u32 i : vecs) {
|
|
||||||
fmt::print(" {:08x}", i);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("initial_cpsr: {:08x}\n", cpsr);
|
|
||||||
fmt::print("initial_fpcr: {:08x}\n", fpscr);
|
|
||||||
|
|
||||||
jit.ClearCache();
|
jit.ClearCache();
|
||||||
|
|
||||||
|
@ -450,36 +453,37 @@ void RunTestInstance(Dynarmic::A32::Jit& jit,
|
||||||
jit.Run();
|
jit.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print("final_regs:");
|
if (show_disas) {
|
||||||
for (u32 i : jit.Regs()) {
|
fmt::print("final_regs:");
|
||||||
fmt::print(" {:08x}", i);
|
for (u32 i : jit.Regs()) {
|
||||||
|
fmt::print(" {:08x}", i);
|
||||||
|
}
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("final_vecs:");
|
||||||
|
for (u32 i : jit.ExtRegs()) {
|
||||||
|
fmt::print(" {:08x}", i);
|
||||||
|
}
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("final_cpsr: {:08x}\n", jit.Cpsr());
|
||||||
|
fmt::print("final_fpsr: {:08x}\n", mask_fpsr_cum_bits ? jit.Fpscr() & 0xffffff00 : jit.Fpscr());
|
||||||
|
fmt::print("mod_mem: ");
|
||||||
|
for (auto [addr, value] : jit_env.modified_memory) {
|
||||||
|
fmt::print("{:08x}:{:02x} ", addr, value);
|
||||||
|
}
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("interrupts:\n");
|
||||||
|
for (const auto& i : jit_env.interrupts) {
|
||||||
|
std::puts(i.c_str());
|
||||||
|
}
|
||||||
|
fmt::print("===\n");
|
||||||
|
jit.DumpDisassembly();
|
||||||
}
|
}
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("final_vecs:");
|
|
||||||
for (u32 i : jit.ExtRegs()) {
|
|
||||||
fmt::print(" {:08x}", i);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("final_cpsr: {:08x}\n", jit.Cpsr());
|
|
||||||
fmt::print("final_fpsr: {:08x}\n", mask_fpsr_cum_bits ? jit.Fpscr() & 0xffffff00 : jit.Fpscr());
|
|
||||||
|
|
||||||
fmt::print("mod_mem: ");
|
|
||||||
for (auto [addr, value] : jit_env.modified_memory) {
|
|
||||||
fmt::print("{:08x}:{:02x} ", addr, value);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
|
|
||||||
fmt::print("interrupts:\n");
|
|
||||||
for (const auto& i : jit_env.interrupts) {
|
|
||||||
std::puts(i.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt::print("===\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynarmic::A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
Dynarmic::A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
||||||
Dynarmic::A64::UserConfig jit_user_config{&jit_env};
|
Dynarmic::A64::UserConfig jit_user_config{};
|
||||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
jit_user_config.callbacks = &jit_env;
|
||||||
|
jit_user_config.optimizations = all_safe_optimizations;
|
||||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||||
jit_user_config.dczid_el0 = 7;
|
jit_user_config.dczid_el0 = 7;
|
||||||
jit_user_config.ctr_el0 = 0x80038003;
|
jit_user_config.ctr_el0 = 0x80038003;
|
||||||
|
@ -491,15 +495,16 @@ Dynarmic::A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
||||||
|
|
||||||
template<size_t num_jit_reruns = 2>
|
template<size_t num_jit_reruns = 2>
|
||||||
void RunTestInstance(Dynarmic::A64::Jit& jit,
|
void RunTestInstance(Dynarmic::A64::Jit& jit,
|
||||||
A64TestEnv& jit_env,
|
A64TestEnv& jit_env,
|
||||||
const std::array<u64, 31>& regs,
|
const std::array<u64, 31>& regs,
|
||||||
const std::array<std::array<u64, 2>, 32>& vecs,
|
const std::array<std::array<u64, 2>, 32>& vecs,
|
||||||
const std::vector<u32>& instructions,
|
const std::vector<u32>& instructions,
|
||||||
const u32 pstate,
|
const u32 pstate,
|
||||||
const u32 fpcr,
|
const u32 fpcr,
|
||||||
const u64 initial_sp,
|
const u64 initial_sp,
|
||||||
const u64 start_address,
|
const u64 start_address,
|
||||||
const size_t ticks_left) {
|
const size_t ticks_left,
|
||||||
|
const bool show_disas) {
|
||||||
jit.ClearCache();
|
jit.ClearCache();
|
||||||
|
|
||||||
for (size_t jit_rerun_count = 0; jit_rerun_count < num_jit_reruns; ++jit_rerun_count) {
|
for (size_t jit_rerun_count = 0; jit_rerun_count < num_jit_reruns; ++jit_rerun_count) {
|
||||||
|
@ -522,59 +527,53 @@ void RunTestInstance(Dynarmic::A64::Jit& jit,
|
||||||
jit.Run();
|
jit.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print("instructions:");
|
if (show_disas) {
|
||||||
for (u32 instruction : instructions) {
|
fmt::print("instructions:\n");
|
||||||
fmt::print(" {:08x}", instruction);
|
auto current_pc = start_address;
|
||||||
}
|
for (u32 instruction : instructions) {
|
||||||
fmt::print("\n");
|
fmt::print("{}", Dynarmic::Common::DisassembleAArch64(instruction, current_pc));
|
||||||
|
current_pc += 4;
|
||||||
|
}
|
||||||
|
|
||||||
fmt::print("initial_regs:");
|
fmt::print("initial_regs:");
|
||||||
for (u64 i : regs) {
|
for (u64 i : regs)
|
||||||
fmt::print(" {:016x}", i);
|
fmt::print(" {:016x}", i);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("initial_vecs:");
|
||||||
|
for (auto i : vecs)
|
||||||
|
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("initial_sp: {:016x}\n", initial_sp);
|
||||||
|
fmt::print("initial_pstate: {:08x}\n", pstate);
|
||||||
|
fmt::print("initial_fpcr: {:08x}\n", fpcr);
|
||||||
|
fmt::print("final_regs:");
|
||||||
|
for (u64 i : jit.GetRegisters())
|
||||||
|
fmt::print(" {:016x}", i);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("final_vecs:");
|
||||||
|
for (auto i : jit.GetVectors())
|
||||||
|
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("final_sp: {:016x}\n", jit.GetSP());
|
||||||
|
fmt::print("final_pc: {:016x}\n", jit.GetPC());
|
||||||
|
fmt::print("final_pstate: {:08x}\n", jit.GetPstate());
|
||||||
|
fmt::print("final_fpcr: {:08x}\n", jit.GetFpcr());
|
||||||
|
fmt::print("final_qc : {}\n", FP::FPSR{jit.GetFpsr()}.QC());
|
||||||
|
fmt::print("mod_mem:");
|
||||||
|
for (auto [addr, value] : jit_env.modified_memory)
|
||||||
|
fmt::print(" {:08x}:{:02x}", addr, value);
|
||||||
|
fmt::print("\n");
|
||||||
|
fmt::print("interrupts:\n");
|
||||||
|
for (const auto& i : jit_env.interrupts)
|
||||||
|
std::puts(i.c_str());
|
||||||
|
fmt::print("===\n");
|
||||||
|
jit.DumpDisassembly();
|
||||||
}
|
}
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("initial_vecs:");
|
|
||||||
for (auto i : vecs) {
|
|
||||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("initial_sp: {:016x}\n", initial_sp);
|
|
||||||
fmt::print("initial_pstate: {:08x}\n", pstate);
|
|
||||||
fmt::print("initial_fpcr: {:08x}\n", fpcr);
|
|
||||||
|
|
||||||
fmt::print("final_regs:");
|
|
||||||
for (u64 i : jit.GetRegisters()) {
|
|
||||||
fmt::print(" {:016x}", i);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("final_vecs:");
|
|
||||||
for (auto i : jit.GetVectors()) {
|
|
||||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
fmt::print("final_sp: {:016x}\n", jit.GetSP());
|
|
||||||
fmt::print("final_pc: {:016x}\n", jit.GetPC());
|
|
||||||
fmt::print("final_pstate: {:08x}\n", jit.GetPstate());
|
|
||||||
fmt::print("final_fpcr: {:08x}\n", jit.GetFpcr());
|
|
||||||
fmt::print("final_qc : {}\n", FP::FPSR{jit.GetFpsr()}.QC());
|
|
||||||
|
|
||||||
fmt::print("mod_mem:");
|
|
||||||
for (auto [addr, value] : jit_env.modified_memory) {
|
|
||||||
fmt::print(" {:08x}:{:02x}", addr, value);
|
|
||||||
}
|
|
||||||
fmt::print("\n");
|
|
||||||
|
|
||||||
fmt::print("interrupts:\n");
|
|
||||||
for (const auto& i : jit_env.interrupts) {
|
|
||||||
std::puts(i.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt::print("===\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt) {
|
void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||||
ThumbTestEnv jit_env{};
|
ThumbTestEnv jit_env{};
|
||||||
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
||||||
|
|
||||||
|
@ -597,11 +596,11 @@ void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[15] = start_address;
|
regs[15] = start_address;
|
||||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions);
|
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions, show_disas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestArm(size_t num_instructions, size_t num_iterations, bool noopt) {
|
void TestArm(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||||
ArmTestEnv jit_env{};
|
ArmTestEnv jit_env{};
|
||||||
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
||||||
|
|
||||||
|
@ -623,11 +622,11 @@ void TestArm(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[15] = start_address;
|
regs[15] = start_address;
|
||||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions);
|
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions, show_disas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestA64(size_t num_instructions, size_t num_iterations, bool noopt) {
|
void TestA64(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||||
A64TestEnv jit_env{};
|
A64TestEnv jit_env{};
|
||||||
Dynarmic::A64::Jit jit{GetA64UserConfig(jit_env, noopt)};
|
Dynarmic::A64::Jit jit{GetA64UserConfig(jit_env, noopt)};
|
||||||
|
|
||||||
|
@ -649,7 +648,7 @@ void TestA64(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||||
instructions.emplace_back(GenRandomA64Inst(static_cast<u32>(start_address + 4 * instructions.size()), i == num_instructions - 1));
|
instructions.emplace_back(GenRandomA64Inst(static_cast<u32>(start_address + 4 * instructions.size()), i == num_instructions - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
RunTestInstance(jit, jit_env, regs, vecs, instructions, pstate, fpcr, initial_sp, start_address, num_instructions);
|
RunTestInstance(jit, jit_env, regs, vecs, instructions, pstate, fpcr, initial_sp, start_address, num_instructions, show_disas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,6 +676,7 @@ int main(int argc, char* argv[]) {
|
||||||
const auto instruction_count = str2sz(argv[3]);
|
const auto instruction_count = str2sz(argv[3]);
|
||||||
const auto iterator_count = str2sz(argv[4]);
|
const auto iterator_count = str2sz(argv[4]);
|
||||||
const bool noopt = argc == 6 && (strcmp(argv[5], "noopt") == 0);
|
const bool noopt = argc == 6 && (strcmp(argv[5], "noopt") == 0);
|
||||||
|
const bool show_disas = argc == 6 && (strcmp(argv[5], "disas") == 0);
|
||||||
|
|
||||||
if (!seed || !instruction_count || !iterator_count) {
|
if (!seed || !instruction_count || !iterator_count) {
|
||||||
fmt::print("invalid numeric arguments\n");
|
fmt::print("invalid numeric arguments\n");
|
||||||
|
@ -686,11 +686,11 @@ int main(int argc, char* argv[]) {
|
||||||
detail::g_rand_int_generator.seed(static_cast<std::mt19937::result_type>(*seed));
|
detail::g_rand_int_generator.seed(static_cast<std::mt19937::result_type>(*seed));
|
||||||
|
|
||||||
if (strcmp(argv[1], "thumb") == 0) {
|
if (strcmp(argv[1], "thumb") == 0) {
|
||||||
TestThumb(*instruction_count, *iterator_count, noopt);
|
TestThumb(*instruction_count, *iterator_count, noopt, show_disas);
|
||||||
} else if (strcmp(argv[1], "arm") == 0) {
|
} else if (strcmp(argv[1], "arm") == 0) {
|
||||||
TestArm(*instruction_count, *iterator_count, noopt);
|
TestArm(*instruction_count, *iterator_count, noopt, show_disas);
|
||||||
} else if (strcmp(argv[1], "a64") == 0) {
|
} else if (strcmp(argv[1], "a64") == 0) {
|
||||||
TestA64(*instruction_count, *iterator_count, noopt);
|
TestA64(*instruction_count, *iterator_count, noopt, show_disas);
|
||||||
} else {
|
} else {
|
||||||
fmt::print("unrecognized instruction class\n");
|
fmt::print("unrecognized instruction class\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
3
externals/dynarmic/tests/test_reader.cpp
vendored
3
externals/dynarmic/tests/test_reader.cpp
vendored
|
@ -158,7 +158,8 @@ void RunTestInstance(Dynarmic::A32::Jit& jit,
|
||||||
}
|
}
|
||||||
|
|
||||||
A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
||||||
A64::UserConfig jit_user_config{&jit_env};
|
A64::UserConfig jit_user_config{};
|
||||||
|
jit_user_config.callbacks = &jit_env;
|
||||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
||||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||||
jit_user_config.dczid_el0 = 7;
|
jit_user_config.dczid_el0 = 7;
|
||||||
|
|
|
@ -24,8 +24,8 @@ if (NOT EXISTS "${TZ_DIR}" OR NOT EXISTS "${TZIF_LIST_FILE}")
|
||||||
# separate directory before building.
|
# separate directory before building.
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND
|
COMMAND
|
||||||
${GIT_PROGRAM} clone --depth 1 "file://${TZ_SOURCE_DIR}" "${TZ_TMP_SOURCE_DIR}"
|
${GIT_PROGRAM} clone --depth=1 "file://${TZ_SOURCE_DIR}" "${TZ_TMP_SOURCE_DIR}"
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
# No need to be fatal, on SunOS this works fine - COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "tzif.h"
|
#include "tzif.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
@ -7,7 +10,7 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <cstdint>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
constexpr std::size_t ten_megabytes{(1 << 20) * 10};
|
constexpr std::size_t ten_megabytes{(1 << 20) * 10};
|
||||||
|
@ -92,7 +95,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int8_t *buf = new u_int8_t[filesize];
|
std::uint8_t *buf = new std::uint8_t[filesize];
|
||||||
|
|
||||||
filesize = read(f, buf, filesize);
|
filesize = read(f, buf, filesize);
|
||||||
if (filesize == static_cast<std::size_t>(-1)) {
|
if (filesize == static_cast<std::size_t>(-1)) {
|
||||||
|
@ -124,7 +127,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
|
||||||
std::vector<u_int8_t> output_buffer;
|
std::vector<std::uint8_t> output_buffer;
|
||||||
tzif_data->ReformatNintendo(output_buffer);
|
tzif_data->ReformatNintendo(output_buffer);
|
||||||
|
|
||||||
filename = "(stdout)";
|
filename = "(stdout)";
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "tzif.h"
|
#include "tzif.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/types.h>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace Tzif {
|
namespace Tzif {
|
||||||
|
|
||||||
static std::size_t SkipToVersion2(const u_int8_t *data, std::size_t size) {
|
static std::size_t SkipToVersion2(const std::uint8_t *data, std::size_t size) {
|
||||||
char magic[5];
|
char magic[5];
|
||||||
const u_int8_t *p{data};
|
const std::uint8_t *p{data};
|
||||||
|
|
||||||
std::memcpy(magic, data, 4);
|
std::memcpy(magic, data, 4);
|
||||||
magic[4] = '\0';
|
magic[4] = '\0';
|
||||||
|
@ -28,15 +31,15 @@ static std::size_t SkipToVersion2(const u_int8_t *data, std::size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type> constexpr static void SwapEndianess(Type *value) {
|
template <typename Type> constexpr static void SwapEndianess(Type *value) {
|
||||||
u_int8_t *data = reinterpret_cast<u_int8_t *>(value);
|
std::uint8_t *data = reinterpret_cast<std::uint8_t *>(value);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
u_int8_t data[sizeof(Type)];
|
std::uint8_t data[sizeof(Type)];
|
||||||
Type value;
|
Type value;
|
||||||
} temp;
|
} temp;
|
||||||
|
|
||||||
for (u_int32_t i = 0; i < sizeof(Type); i++) {
|
for (std::uint32_t i = 0; i < sizeof(Type); i++) {
|
||||||
u_int32_t alt_index = sizeof(Type) - i - 1;
|
std::uint32_t alt_index = sizeof(Type) - i - 1;
|
||||||
temp.data[alt_index] = data[i];
|
temp.data[alt_index] = data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,13 +55,13 @@ static void FlipHeader(Header &header) {
|
||||||
SwapEndianess(&header.charcnt);
|
SwapEndianess(&header.charcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
|
std::unique_ptr<DataImpl> ReadData(const std::uint8_t *data, std::size_t size) {
|
||||||
const std::size_t v2_offset = SkipToVersion2(data, size);
|
const std::size_t v2_offset = SkipToVersion2(data, size);
|
||||||
if (v2_offset == static_cast<std::size_t>(-1)) {
|
if (v2_offset == static_cast<std::size_t>(-1)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u_int8_t *p = data + v2_offset;
|
const std::uint8_t *p = data + v2_offset;
|
||||||
|
|
||||||
Header header;
|
Header header;
|
||||||
std::memcpy(&header, p, sizeof(header));
|
std::memcpy(&header, p, sizeof(header));
|
||||||
|
@ -67,10 +70,10 @@ std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
|
||||||
FlipHeader(header);
|
FlipHeader(header);
|
||||||
|
|
||||||
const std::size_t data_block_length =
|
const std::size_t data_block_length =
|
||||||
header.timecnt * sizeof(int64_t) + header.timecnt * sizeof(u_int8_t) +
|
header.timecnt * sizeof(int64_t) + header.timecnt * sizeof(std::uint8_t) +
|
||||||
header.typecnt * sizeof(TimeTypeRecord) +
|
header.typecnt * sizeof(TimeTypeRecord) +
|
||||||
header.charcnt * sizeof(int8_t) + header.isstdcnt * sizeof(u_int8_t) +
|
header.charcnt * sizeof(int8_t) + header.isstdcnt * sizeof(std::uint8_t) +
|
||||||
header.isutcnt * sizeof(u_int8_t);
|
header.isutcnt * sizeof(std::uint8_t);
|
||||||
|
|
||||||
if (v2_offset + data_block_length + sizeof(Header) > size) {
|
if (v2_offset + data_block_length + sizeof(Header) > size) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -81,7 +84,7 @@ std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
|
||||||
|
|
||||||
const auto copy =
|
const auto copy =
|
||||||
[]<typename Type>(std::unique_ptr<Type[]> &array, int length,
|
[]<typename Type>(std::unique_ptr<Type[]> &array, int length,
|
||||||
const u_int8_t *const &ptr) -> const u_int8_t * {
|
const std::uint8_t *const &ptr) -> const std::uint8_t * {
|
||||||
const std::size_t region_length = length * sizeof(Type);
|
const std::size_t region_length = length * sizeof(Type);
|
||||||
array = std::make_unique<Type[]>(length);
|
array = std::make_unique<Type[]>(length);
|
||||||
std::memcpy(array.get(), ptr, region_length);
|
std::memcpy(array.get(), ptr, region_length);
|
||||||
|
@ -110,16 +113,16 @@ std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
|
||||||
return impl;
|
return impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PushToBuffer(std::vector<u_int8_t> &buffer, const void *data,
|
static void PushToBuffer(std::vector<std::uint8_t> &buffer, const void *data,
|
||||||
std::size_t size) {
|
std::size_t size) {
|
||||||
const u_int8_t *p{reinterpret_cast<const u_int8_t *>(data)};
|
const std::uint8_t *p{reinterpret_cast<const std::uint8_t *>(data)};
|
||||||
for (std::size_t i = 0; i < size; i++) {
|
for (std::size_t i = 0; i < size; i++) {
|
||||||
buffer.push_back(*p);
|
buffer.push_back(*p);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataImpl::ReformatNintendo(std::vector<u_int8_t> &buffer) const {
|
void DataImpl::ReformatNintendo(std::vector<std::uint8_t> &buffer) const {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
|
|
||||||
Header header_copy{header};
|
Header header_copy{header};
|
||||||
|
@ -131,7 +134,7 @@ void DataImpl::ReformatNintendo(std::vector<u_int8_t> &buffer) const {
|
||||||
PushToBuffer(buffer, transition_times.get(),
|
PushToBuffer(buffer, transition_times.get(),
|
||||||
header.timecnt * sizeof(int64_t));
|
header.timecnt * sizeof(int64_t));
|
||||||
PushToBuffer(buffer, transition_types.get(),
|
PushToBuffer(buffer, transition_types.get(),
|
||||||
header.timecnt * sizeof(u_int8_t));
|
header.timecnt * sizeof(std::uint8_t));
|
||||||
PushToBuffer(buffer, local_time_type_records.get(),
|
PushToBuffer(buffer, local_time_type_records.get(),
|
||||||
header.typecnt * sizeof(TimeTypeRecord));
|
header.typecnt * sizeof(TimeTypeRecord));
|
||||||
PushToBuffer(buffer, time_zone_designations.get(),
|
PushToBuffer(buffer, time_zone_designations.get(),
|
||||||
|
|
39
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.h
vendored
39
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.h
vendored
|
@ -1,22 +1,25 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/types.h>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Tzif {
|
namespace Tzif {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
u_int8_t version;
|
std::uint8_t version;
|
||||||
u_int8_t reserved[15];
|
std::uint8_t reserved[15];
|
||||||
u_int32_t isutcnt;
|
std::uint32_t isutcnt;
|
||||||
u_int32_t isstdcnt;
|
std::uint32_t isstdcnt;
|
||||||
u_int32_t leapcnt;
|
std::uint32_t leapcnt;
|
||||||
u_int32_t timecnt;
|
std::uint32_t timecnt;
|
||||||
u_int32_t typecnt;
|
std::uint32_t typecnt;
|
||||||
u_int32_t charcnt;
|
std::uint32_t charcnt;
|
||||||
} Header;
|
} Header;
|
||||||
static_assert(sizeof(Header) == 0x2c);
|
static_assert(sizeof(Header) == 0x2c);
|
||||||
|
|
||||||
|
@ -34,9 +37,9 @@ public:
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_int32_t utoff;
|
std::uint32_t utoff;
|
||||||
u_int8_t dst;
|
std::uint8_t dst;
|
||||||
u_int8_t idx;
|
std::uint8_t idx;
|
||||||
} TimeTypeRecord;
|
} TimeTypeRecord;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
static_assert(sizeof(TimeTypeRecord) == 0x6);
|
static_assert(sizeof(TimeTypeRecord) == 0x6);
|
||||||
|
@ -46,7 +49,7 @@ public:
|
||||||
explicit Data() = default;
|
explicit Data() = default;
|
||||||
virtual ~Data() = default;
|
virtual ~Data() = default;
|
||||||
|
|
||||||
virtual void ReformatNintendo(std::vector<u_int8_t> &buffer) const = 0;
|
virtual void ReformatNintendo(std::vector<std::uint8_t> &buffer) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataImpl : public Data {
|
class DataImpl : public Data {
|
||||||
|
@ -54,19 +57,19 @@ public:
|
||||||
explicit DataImpl() = default;
|
explicit DataImpl() = default;
|
||||||
~DataImpl() override = default;
|
~DataImpl() override = default;
|
||||||
|
|
||||||
void ReformatNintendo(std::vector<u_int8_t> &buffer) const override;
|
void ReformatNintendo(std::vector<std::uint8_t> &buffer) const override;
|
||||||
|
|
||||||
Header header;
|
Header header;
|
||||||
Footer footer;
|
Footer footer;
|
||||||
|
|
||||||
std::unique_ptr<int64_t[]> transition_times;
|
std::unique_ptr<int64_t[]> transition_times;
|
||||||
std::unique_ptr<u_int8_t[]> transition_types;
|
std::unique_ptr<std::uint8_t[]> transition_types;
|
||||||
std::unique_ptr<TimeTypeRecord[]> local_time_type_records;
|
std::unique_ptr<TimeTypeRecord[]> local_time_type_records;
|
||||||
std::unique_ptr<int8_t[]> time_zone_designations;
|
std::unique_ptr<int8_t[]> time_zone_designations;
|
||||||
std::unique_ptr<u_int8_t[]> standard_indicators;
|
std::unique_ptr<std::uint8_t[]> standard_indicators;
|
||||||
std::unique_ptr<u_int8_t[]> ut_indicators;
|
std::unique_ptr<std::uint8_t[]> ut_indicators;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size);
|
std::unique_ptr<DataImpl> ReadData(const std::uint8_t *data, std::size_t size);
|
||||||
|
|
||||||
} // namespace Tzif
|
} // namespace Tzif
|
||||||
|
|
11
externals/renderdoc/renderdoc_app.h
vendored
11
externals/renderdoc/renderdoc_app.h
vendored
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Baldur Karlsson
|
// SPDX-FileCopyrightText: Baldur Karlsson
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
@ -38,14 +41,8 @@
|
||||||
|
|
||||||
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
||||||
#define RENDERDOC_CC __cdecl
|
#define RENDERDOC_CC __cdecl
|
||||||
#elif defined(__linux__)
|
|
||||||
#define RENDERDOC_CC
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#define RENDERDOC_CC
|
|
||||||
#elif defined(__FreeBSD__)
|
|
||||||
#define RENDERDOC_CC
|
|
||||||
#else
|
#else
|
||||||
#error "Unknown platform"
|
#define RENDERDOC_CC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
2
externals/xbyak
vendored
2
externals/xbyak
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 0d67fd1530016b7c56f3cd74b3fca920f4c3e2b4
|
Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f
|
|
@ -147,11 +147,6 @@ android {
|
||||||
dimension = "version"
|
dimension = "version"
|
||||||
// No need to set applicationId here
|
// No need to set applicationId here
|
||||||
}
|
}
|
||||||
|
|
||||||
create("genshinSpoof") {
|
|
||||||
dimension = "version"
|
|
||||||
applicationId = "com.miHoYo.Yuanshen"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +169,7 @@ android {
|
||||||
"-DYUZU_USE_BUNDLED_VCPKG=ON",
|
"-DYUZU_USE_BUNDLED_VCPKG=ON",
|
||||||
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
|
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
|
||||||
"-DYUZU_ENABLE_LTO=ON",
|
"-DYUZU_ENABLE_LTO=ON",
|
||||||
|
"-DYUZU_TESTS=OFF",
|
||||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,172 +8,233 @@
|
||||||
|
|
||||||
#include <common/settings_common.h>
|
#include <common/settings_common.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/settings_setting.h"
|
|
||||||
#include "common/settings_enums.h"
|
#include "common/settings_enums.h"
|
||||||
|
#include "common/settings_setting.h"
|
||||||
|
|
||||||
namespace AndroidSettings {
|
namespace AndroidSettings {
|
||||||
|
|
||||||
struct GameDir {
|
struct GameDir {
|
||||||
std::string path;
|
std::string path;
|
||||||
bool deep_scan = false;
|
bool deep_scan = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OverlayControlData {
|
struct OverlayControlData {
|
||||||
std::string id;
|
std::string id;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
std::pair<double, double> landscape_position;
|
std::pair<double, double> landscape_position;
|
||||||
std::pair<double, double> portrait_position;
|
std::pair<double, double> portrait_position;
|
||||||
std::pair<double, double> foldable_position;
|
std::pair<double, double> foldable_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Values {
|
struct Values {
|
||||||
Settings::Linkage linkage;
|
Settings::Linkage linkage;
|
||||||
|
|
||||||
// Path settings
|
// Path settings
|
||||||
std::vector<GameDir> game_dirs;
|
std::vector<GameDir> game_dirs;
|
||||||
|
|
||||||
// Android
|
// Android
|
||||||
Settings::Setting<bool> picture_in_picture{linkage, false, "picture_in_picture",
|
Settings::Setting<bool> picture_in_picture{linkage, false, "picture_in_picture",
|
||||||
Settings::Category::Android};
|
Settings::Category::Android};
|
||||||
Settings::Setting<s32> screen_layout{linkage,
|
Settings::Setting<s32> screen_layout{linkage,
|
||||||
5,
|
5,
|
||||||
"screen_layout",
|
"screen_layout",
|
||||||
Settings::Category::Android,
|
Settings::Category::Android,
|
||||||
Settings::Specialization::Default,
|
Settings::Specialization::Default,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
Settings::Setting<s32> vertical_alignment{linkage,
|
Settings::Setting<s32> vertical_alignment{linkage,
|
||||||
0,
|
0,
|
||||||
"vertical_alignment",
|
"vertical_alignment",
|
||||||
Settings::Category::Android,
|
Settings::Category::Android,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true};
|
||||||
|
|
||||||
|
Settings::SwitchableSetting<std::string, false> driver_path{linkage, "", "driver_path",
|
||||||
|
Settings::Category::GpuDriver};
|
||||||
|
|
||||||
|
// LRU Cache
|
||||||
|
Settings::SwitchableSetting<bool> use_lru_cache{linkage, true, "use_lru_cache",
|
||||||
|
Settings::Category::System};
|
||||||
|
|
||||||
|
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
|
||||||
|
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
||||||
|
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
||||||
|
Settings::Category::Android};
|
||||||
|
|
||||||
|
// Input/performance overlay settings
|
||||||
|
std::vector<OverlayControlData> overlay_control_data;
|
||||||
|
Settings::Setting<s32> overlay_scale{linkage, 50, "control_scale", Settings::Category::Overlay};
|
||||||
|
Settings::Setting<s32> overlay_opacity{linkage, 100, "control_opacity",
|
||||||
|
Settings::Category::Overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> joystick_rel_center{linkage, true, "joystick_rel_center",
|
||||||
|
Settings::Category::Overlay};
|
||||||
|
Settings::Setting<bool> dpad_slide{linkage, true, "dpad_slide", Settings::Category::Overlay};
|
||||||
|
Settings::Setting<bool> haptic_feedback{linkage, true, "haptic_feedback",
|
||||||
|
Settings::Category::Overlay};
|
||||||
|
Settings::Setting<bool> show_performance_overlay{linkage,
|
||||||
|
true,
|
||||||
|
"show_performance_overlay",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Paired,
|
||||||
|
true,
|
||||||
|
true};
|
||||||
|
Settings::Setting<bool> perf_overlay_background{linkage,
|
||||||
|
false,
|
||||||
|
"perf_overlay_background",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<s32> perf_overlay_position{linkage,
|
||||||
|
0,
|
||||||
|
"perf_overlay_position",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> show_fps{linkage,
|
||||||
|
true,
|
||||||
|
"show_fps",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<bool> show_frame_time{linkage,
|
||||||
|
false,
|
||||||
|
"show_frame_time",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<bool> show_app_ram_usage{linkage,
|
||||||
|
false,
|
||||||
|
"show_app_ram_usage",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<bool> show_system_ram_usage{linkage,
|
||||||
|
false,
|
||||||
|
"show_system_ram_usage",
|
||||||
|
Settings::Category::Overlay,
|
||||||
Settings::Specialization::Default,
|
Settings::Specialization::Default,
|
||||||
true,
|
true,
|
||||||
true};
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
Settings::SwitchableSetting<std::string, false> driver_path{linkage, "", "driver_path",
|
Settings::Setting<bool> show_bat_temperature{linkage,
|
||||||
Settings::Category::GpuDriver};
|
false,
|
||||||
|
"show_bat_temperature",
|
||||||
// LRU Cache
|
|
||||||
Settings::SwitchableSetting<bool> use_lru_cache{linkage, true, "use_lru_cache",
|
|
||||||
Settings::Category::System};
|
|
||||||
|
|
||||||
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
|
|
||||||
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
|
||||||
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
|
||||||
Settings::Category::Android};
|
|
||||||
|
|
||||||
// Input/performance overlay settings
|
|
||||||
std::vector<OverlayControlData> overlay_control_data;
|
|
||||||
Settings::Setting<s32> overlay_scale{linkage, 50, "control_scale",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<s32> overlay_opacity{linkage, 100, "control_opacity",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
|
|
||||||
Settings::Setting<bool> joystick_rel_center{linkage, true, "joystick_rel_center",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<bool> dpad_slide{linkage, true, "dpad_slide",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<bool> haptic_feedback{linkage, true, "haptic_feedback",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<bool> show_performance_overlay{linkage, true, "show_performance_overlay",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Paired, true,
|
|
||||||
true};
|
|
||||||
Settings::Setting<bool> perf_overlay_background{linkage, false, "perf_overlay_background",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true,
|
|
||||||
true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<s32> perf_overlay_position{linkage, 0, "perf_overlay_position",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
|
|
||||||
Settings::Setting<bool> show_fps{linkage, true, "show_fps",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<bool> show_frame_time{linkage, false, "show_frame_time",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<bool> show_app_ram_usage{linkage, false, "show_app_ram_usage",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<bool> show_system_ram_usage{linkage, false, "show_system_ram_usage",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<bool> show_bat_temperature{linkage, false, "show_bat_temperature",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<Settings::TemperatureUnits> bat_temperature_unit{linkage,
|
|
||||||
Settings::TemperatureUnits::Celsius,
|
|
||||||
"bat_temperature_unit",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default,
|
|
||||||
true, true,
|
|
||||||
&show_bat_temperature};
|
|
||||||
Settings::Setting<bool> show_power_info{linkage, false, "show_power_info",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
Settings::Setting<bool> show_shaders_building{linkage, true, "show_shaders_building",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_performance_overlay};
|
|
||||||
|
|
||||||
|
|
||||||
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
Settings::Setting<s32> lock_drawer{linkage, false, "lock_drawer",
|
|
||||||
Settings::Category::Overlay};
|
|
||||||
|
|
||||||
/// DEVICE/SOC OVERLAY
|
|
||||||
|
|
||||||
Settings::Setting<bool> show_soc_overlay{linkage, true, "show_soc_overlay",
|
|
||||||
Settings::Category::Overlay,
|
Settings::Category::Overlay,
|
||||||
Settings::Specialization::Paired, true, true};
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
Settings::Setting<bool> show_device_model{linkage, true, "show_device_model",
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<Settings::TemperatureUnits> bat_temperature_unit{
|
||||||
|
linkage,
|
||||||
|
Settings::TemperatureUnits::Celsius,
|
||||||
|
"bat_temperature_unit",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_bat_temperature};
|
||||||
|
Settings::Setting<bool> show_power_info{linkage,
|
||||||
|
false,
|
||||||
|
"show_power_info",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
Settings::Setting<bool> show_shaders_building{linkage,
|
||||||
|
true,
|
||||||
|
"show_shaders_building",
|
||||||
Settings::Category::Overlay,
|
Settings::Category::Overlay,
|
||||||
Settings::Specialization::Default, true, true,
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
&show_performance_overlay};
|
&show_performance_overlay};
|
||||||
|
|
||||||
Settings::Setting<bool> show_gpu_model{linkage, true, "show_gpu_model",
|
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
|
||||||
Settings::Category::Overlay,
|
Settings::Category::Overlay};
|
||||||
Settings::Specialization::Default, true, true,
|
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
|
||||||
&show_performance_overlay};
|
Settings::Setting<s32> lock_drawer{linkage, false, "lock_drawer", Settings::Category::Overlay};
|
||||||
|
|
||||||
Settings::Setting<bool> show_soc_model{linkage, true, "show_soc_model",
|
/// DEVICE/SOC OVERLAY
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_soc_overlay};
|
|
||||||
|
|
||||||
Settings::Setting<bool> show_fw_version{linkage, true, "show_firmware_version",
|
Settings::Setting<bool> show_soc_overlay{linkage,
|
||||||
|
true,
|
||||||
|
"show_soc_overlay",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Paired,
|
||||||
|
true,
|
||||||
|
true};
|
||||||
|
|
||||||
|
Settings::Setting<bool> show_device_model{linkage,
|
||||||
|
true,
|
||||||
|
"show_device_model",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> show_gpu_model{linkage,
|
||||||
|
true,
|
||||||
|
"show_gpu_model",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> show_soc_model{linkage,
|
||||||
|
true,
|
||||||
|
"show_soc_model",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_soc_overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> show_fw_version{linkage,
|
||||||
|
true,
|
||||||
|
"show_firmware_version",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_performance_overlay};
|
||||||
|
|
||||||
|
Settings::Setting<bool> soc_overlay_background{linkage,
|
||||||
|
false,
|
||||||
|
"soc_overlay_background",
|
||||||
|
Settings::Category::Overlay,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&show_soc_overlay};
|
||||||
|
Settings::Setting<s32> soc_overlay_position{linkage,
|
||||||
|
2,
|
||||||
|
"soc_overlay_position",
|
||||||
Settings::Category::Overlay,
|
Settings::Category::Overlay,
|
||||||
Settings::Specialization::Default, true, true,
|
Settings::Specialization::Default,
|
||||||
&show_performance_overlay};
|
true,
|
||||||
|
true,
|
||||||
|
&show_soc_overlay};
|
||||||
|
|
||||||
Settings::Setting<bool> soc_overlay_background{linkage, false, "soc_overlay_background",
|
Settings::Setting<bool> dont_show_eden_veil_warning{
|
||||||
Settings::Category::Overlay,
|
linkage, false, "dont_show_eden_veil_warning", Settings::Category::Miscellaneous};
|
||||||
Settings::Specialization::Default, true,
|
};
|
||||||
true,
|
|
||||||
&show_soc_overlay};
|
|
||||||
Settings::Setting<s32> soc_overlay_position{linkage, 2, "soc_overlay_position",
|
|
||||||
Settings::Category::Overlay,
|
|
||||||
Settings::Specialization::Default, true, true,
|
|
||||||
&show_soc_overlay};
|
|
||||||
|
|
||||||
Settings::Setting<bool> dont_show_eden_veil_warning{linkage, false,
|
extern Values values;
|
||||||
"dont_show_eden_veil_warning",
|
|
||||||
Settings::Category::Miscellaneous};
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Values values;
|
|
||||||
|
|
||||||
} // namespace AndroidSettings
|
} // namespace AndroidSettings
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -24,9 +23,9 @@
|
||||||
#include <frontend_common/content_manager.h>
|
#include <frontend_common/content_manager.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#include "common/android/multiplayer/multiplayer.h"
|
|
||||||
#include "common/android/android_common.h"
|
#include "common/android/android_common.h"
|
||||||
#include "common/android/id_cache.h"
|
#include "common/android/id_cache.h"
|
||||||
|
#include "common/android/multiplayer/multiplayer.h"
|
||||||
#include "common/detached_tasks.h"
|
#include "common/detached_tasks.h"
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
@ -65,23 +64,23 @@
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
#include "jni/native.h"
|
#include "jni/native.h"
|
||||||
|
#include "network/announce_multiplayer_session.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
|
#include "video_core/shader_notify.h"
|
||||||
#include "video_core/vulkan_common/vulkan_instance.h"
|
#include "video_core/vulkan_common/vulkan_instance.h"
|
||||||
#include "video_core/vulkan_common/vulkan_surface.h"
|
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||||
#include "video_core/shader_notify.h"
|
|
||||||
#include "network/announce_multiplayer_session.h"
|
|
||||||
|
|
||||||
#define jconst [[maybe_unused]] const auto
|
#define jconst [[maybe_unused]] const auto
|
||||||
#define jauto [[maybe_unused]] auto
|
#define jauto [[maybe_unused]] auto
|
||||||
|
|
||||||
static EmulationSession s_instance;
|
static EmulationSession s_instance;
|
||||||
|
|
||||||
//Abdroid Multiplayer which can be initialized with parameters
|
// Abdroid Multiplayer which can be initialized with parameters
|
||||||
std::unique_ptr<AndroidMultiplayer> multiplayer{nullptr};
|
std::unique_ptr<AndroidMultiplayer> multiplayer{nullptr};
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
|
|
||||||
//Power Status default values
|
// Power Status default values
|
||||||
std::atomic<int> g_battery_percentage = {100};
|
std::atomic<int> g_battery_percentage = {100};
|
||||||
std::atomic<bool> g_is_charging = {false};
|
std::atomic<bool> g_is_charging = {false};
|
||||||
std::atomic<bool> g_has_battery = {true};
|
std::atomic<bool> g_has_battery = {true};
|
||||||
|
@ -581,7 +580,9 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
||||||
return j_driver_info;
|
return j_driver_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv* env, jobject j_obj,
|
||||||
|
jobject j_surf,
|
||||||
|
jstring j_hook_lib_dir) {
|
||||||
const char* file_redirect_dir_{};
|
const char* file_redirect_dir_{};
|
||||||
int featureFlags{};
|
int featureFlags{};
|
||||||
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
||||||
|
@ -590,11 +591,11 @@ jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, j
|
||||||
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
|
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
|
||||||
InputCommon::InputSubsystem input_subsystem;
|
InputCommon::InputSubsystem input_subsystem;
|
||||||
auto window =
|
auto window =
|
||||||
std::make_unique<EmuWindow_Android>(ANativeWindow_fromSurface(env, j_surf), driver_library);
|
std::make_unique<EmuWindow_Android>(ANativeWindow_fromSurface(env, j_surf), driver_library);
|
||||||
|
|
||||||
Vulkan::vk::InstanceDispatch dld;
|
Vulkan::vk::InstanceDispatch dld;
|
||||||
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
|
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
|
||||||
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
|
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
|
||||||
|
|
||||||
auto surface = Vulkan::CreateSurface(vk_instance, window->GetWindowInfo());
|
auto surface = Vulkan::CreateSurface(vk_instance, window->GetWindowInfo());
|
||||||
|
|
||||||
|
@ -791,16 +792,19 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_firmwareVersion(JNIEnv* env, jclas
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyFirmware(JNIEnv* env, jclass clazz) {
|
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyFirmware(JNIEnv* env, jclass clazz) {
|
||||||
return static_cast<int>(FirmwareManager::VerifyFirmware(EmulationSession::GetInstance().System()));
|
return static_cast<int>(
|
||||||
|
FirmwareManager::VerifyFirmware(EmulationSession::GetInstance().System()));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_gameRequiresFirmware(JNIEnv* env, jclass clazz, jstring jprogramId) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_gameRequiresFirmware(JNIEnv* env, jclass clazz,
|
||||||
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
||||||
|
|
||||||
return FirmwareManager::GameRequiresFirmware(program_id);
|
return FirmwareManager::GameRequiresFirmware(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz, jstring jpath, jstring jext) {
|
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz, jstring jpath,
|
||||||
|
jstring jext) {
|
||||||
const auto path = Common::Android::GetJString(env, jpath);
|
const auto path = Common::Android::GetJString(env, jpath);
|
||||||
const auto ext = Common::Android::GetJString(env, jext);
|
const auto ext = Common::Android::GetJString(env, jext);
|
||||||
|
|
||||||
|
@ -957,105 +961,97 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, jobje
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_org_yuzu_yuzu_1emu_NativeLibrary_initMultiplayer(
|
Java_org_yuzu_yuzu_1emu_NativeLibrary_initMultiplayer(JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
if (multiplayer) {
|
if (multiplayer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>();
|
announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>();
|
||||||
|
|
||||||
multiplayer = std::make_unique<AndroidMultiplayer>(s_instance.System(), announce_multiplayer_session);
|
multiplayer =
|
||||||
|
std::make_unique<AndroidMultiplayer>(s_instance.System(), announce_multiplayer_session);
|
||||||
multiplayer->NetworkInit();
|
multiplayer->NetworkInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayGetPublicRooms(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayGetPublicRooms(
|
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
JNIEnv *env, [[maybe_unused]] jobject obj) {
|
|
||||||
return Common::Android::ToJStringArray(env, multiplayer->NetPlayGetPublicRooms());
|
return Common::Android::ToJStringArray(env, multiplayer->NetPlayGetPublicRooms());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayCreateRoom(
|
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayCreateRoom(
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port, jstring username,
|
||||||
jstring username, jstring preferredGameName, jlong preferredGameId, jstring password,
|
jstring preferredGameName, jlong preferredGameId, jstring password, jstring room_name,
|
||||||
jstring room_name, jint max_players, jboolean isPublic) {
|
jint max_players, jboolean isPublic) {
|
||||||
return static_cast<jint>(
|
return static_cast<jint>(multiplayer->NetPlayCreateRoom(
|
||||||
multiplayer->NetPlayCreateRoom(Common::Android::GetJString(env, ipaddress), port,
|
Common::Android::GetJString(env, ipaddress), port,
|
||||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, preferredGameName),
|
Common::Android::GetJString(env, username),
|
||||||
preferredGameId,Common::Android::GetJString(env, password),
|
Common::Android::GetJString(env, preferredGameName), preferredGameId,
|
||||||
Common::Android::GetJString(env, room_name), max_players, isPublic));
|
Common::Android::GetJString(env, password), Common::Android::GetJString(env, room_name),
|
||||||
|
max_players, isPublic));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayJoinRoom(
|
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayJoinRoom(
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port, jstring username,
|
||||||
jstring username, jstring password) {
|
jstring password) {
|
||||||
return static_cast<jint>(
|
return static_cast<jint>(multiplayer->NetPlayJoinRoom(
|
||||||
multiplayer->NetPlayJoinRoom(Common::Android::GetJString(env, ipaddress), port,
|
Common::Android::GetJString(env, ipaddress), port,
|
||||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password)));
|
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayRoomInfo(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayRoomInfo(
|
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
return Common::Android::ToJStringArray(env, multiplayer->NetPlayRoomInfo());
|
return Common::Android::ToJStringArray(env, multiplayer->NetPlayRoomInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsJoined(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsJoined(
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
return multiplayer->NetPlayIsJoined();
|
return multiplayer->NetPlayIsJoined();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsHostedRoom(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsHostedRoom(
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
return multiplayer->NetPlayIsHostedRoom();
|
return multiplayer->NetPlayIsHostedRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlaySendMessage(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlaySendMessage(
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring msg) {
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring msg) {
|
|
||||||
multiplayer->NetPlaySendMessage(Common::Android::GetJString(env, msg));
|
multiplayer->NetPlaySendMessage(Common::Android::GetJString(env, msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayKickUser(
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayKickUser(
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||||
multiplayer->NetPlayKickUser(Common::Android::GetJString(env, username));
|
multiplayer->NetPlayKickUser(Common::Android::GetJString(env, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayLeaveRoom(
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayLeaveRoom(
|
||||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
multiplayer->NetPlayLeaveRoom();
|
multiplayer->NetPlayLeaveRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsModerator(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsModerator(
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
return multiplayer->NetPlayIsModerator();
|
return multiplayer->NetPlayIsModerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayGetBanList(
|
||||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayGetBanList(
|
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
|
||||||
return Common::Android::ToJStringArray(env, multiplayer->NetPlayGetBanList());
|
return Common::Android::ToJStringArray(env, multiplayer->NetPlayGetBanList());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayBanUser(
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayBanUser(
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||||
multiplayer->NetPlayBanUser(Common::Android::GetJString(env, username));
|
multiplayer->NetPlayBanUser(Common::Android::GetJString(env, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayUnbanUser(
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayUnbanUser(
|
||||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||||
multiplayer->NetPlayUnbanUser(Common::Android::GetJString(env, username));
|
multiplayer->NetPlayUnbanUser(Common::Android::GetJString(env, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_updatePowerState(
|
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_updatePowerState(JNIEnv* env, jobject,
|
||||||
JNIEnv* env,
|
jint percentage,
|
||||||
jobject,
|
jboolean isCharging,
|
||||||
jint percentage,
|
jboolean hasBattery) {
|
||||||
jboolean isCharging,
|
|
||||||
jboolean hasBattery) {
|
|
||||||
|
|
||||||
g_battery_percentage.store(percentage, std::memory_order_relaxed);
|
g_battery_percentage.store(percentage, std::memory_order_relaxed);
|
||||||
g_is_charging.store(isCharging, std::memory_order_relaxed);
|
g_is_charging.store(isCharging, std::memory_order_relaxed);
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace AudioCore::AudioIn {
|
namespace AudioCore::AudioIn {
|
||||||
|
|
||||||
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
: manager{manager_}, parent_mutex{manager.mutex}, event{event_},
|
||||||
session_id_} {}
|
system{system_, event, session_id_} {}
|
||||||
|
|
||||||
void In::Free() {
|
void In::Free() {
|
||||||
std::scoped_lock l{parent_mutex};
|
std::scoped_lock l{parent_mutex};
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
namespace AudioCore::AudioIn {
|
namespace AudioCore::AudioIn {
|
||||||
|
|
||||||
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
|
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
|
||||||
: system{system_}, buffer_event{event_},
|
: system{system_}, buffer_event{event_}, session_id{session_id_},
|
||||||
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
|
session{std::make_unique<DeviceSession>(system_)} {}
|
||||||
|
|
||||||
System::~System() {
|
System::~System() {
|
||||||
Finalize();
|
Finalize();
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace AudioCore::AudioOut {
|
namespace AudioCore::AudioOut {
|
||||||
|
|
||||||
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
: manager{manager_}, parent_mutex{manager.mutex}, event{event_},
|
||||||
session_id_} {}
|
system{system_, event, session_id_} {}
|
||||||
|
|
||||||
void Out::Free() {
|
void Out::Free() {
|
||||||
std::scoped_lock l{parent_mutex};
|
std::scoped_lock l{parent_mutex};
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
namespace AudioCore::AudioOut {
|
namespace AudioCore::AudioOut {
|
||||||
|
|
||||||
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
|
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: system{system_}, buffer_event{event_},
|
: system{system_}, buffer_event{event_}, session_id{session_id_},
|
||||||
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
|
session{std::make_unique<DeviceSession>(system_)} {}
|
||||||
|
|
||||||
System::~System() {
|
System::~System() {
|
||||||
Finalize();
|
Finalize();
|
||||||
|
|
|
@ -19,10 +19,9 @@ namespace AudioCore::Renderer {
|
||||||
|
|
||||||
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
||||||
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
|
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
|
||||||
: input{input_.data() + sizeof(UpdateDataHeader)},
|
: input{input_.data() + sizeof(UpdateDataHeader)}, input_origin{input_},
|
||||||
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
|
output{output_.data() + sizeof(UpdateDataHeader)}, output_origin{output_},
|
||||||
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(
|
in_header{reinterpret_cast<const UpdateDataHeader*>(input_origin.data())},
|
||||||
input_origin.data())},
|
|
||||||
out_header{reinterpret_cast<UpdateDataHeader*>(output_origin.data())},
|
out_header{reinterpret_cast<UpdateDataHeader*>(output_origin.data())},
|
||||||
expected_input_size{input_.size()}, expected_output_size{output_.size()},
|
expected_input_size{input_.size()}, expected_output_size{output_.size()},
|
||||||
process_handle{process_handle_}, behaviour{behaviour_} {
|
process_handle{process_handle_}, behaviour{behaviour_} {
|
||||||
|
|
|
@ -13,8 +13,8 @@ PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
|
||||||
|
|
||||||
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
|
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
|
||||||
u32 pool_count_, bool force_map_)
|
u32 pool_count_, bool force_map_)
|
||||||
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
|
: process_handle{process_handle_}, pool_infos{pool_infos_.data()}, pool_count{pool_count_},
|
||||||
pool_count{pool_count_}, force_map{force_map_} {}
|
force_map{force_map_} {}
|
||||||
|
|
||||||
void PoolMapper::ClearUseState(std::span<MemoryPoolInfo> pools, const u32 count) {
|
void PoolMapper::ClearUseState(std::span<MemoryPoolInfo> pools, const u32 count) {
|
||||||
for (u32 i = 0; i < count; i++) {
|
for (u32 i = 0; i < count; i++) {
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include "audio_core/common/common.h"
|
#include "audio_core/common/common.h"
|
||||||
|
|
|
@ -240,7 +240,9 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
|
||||||
// Successfully dequeued a new buffer.
|
// Successfully dequeued a new buffer.
|
||||||
queued_buffers--;
|
queued_buffers--;
|
||||||
|
|
||||||
{ std::unique_lock lk{release_mutex}; }
|
{
|
||||||
|
std::unique_lock lk{release_mutex};
|
||||||
|
}
|
||||||
|
|
||||||
release_cv.notify_one();
|
release_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
template <typename VaType, size_t AddressSpaceBits>
|
template <typename VaType, size_t AddressSpaceBits>
|
||||||
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >=
|
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= AddressSpaceBits;
|
||||||
AddressSpaceBits;
|
|
||||||
|
|
||||||
struct EmptyStruct {};
|
struct EmptyStruct {};
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ jstring ToJString(JNIEnv* env, std::string_view str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
jobjectArray ToJStringArray(JNIEnv* env, const std::vector<std::string>& strs) {
|
jobjectArray ToJStringArray(JNIEnv* env, const std::vector<std::string>& strs) {
|
||||||
jobjectArray array =
|
jobjectArray array = env->NewObjectArray(
|
||||||
env->NewObjectArray(static_cast<jsize>(strs.size()), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
static_cast<jsize>(strs.size()), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
||||||
for (std::size_t i = 0; i < strs.size(); ++i) {
|
for (std::size_t i = 0; i < strs.size(); ++i) {
|
||||||
env->SetObjectArrayElement(array, static_cast<jsize>(i), ToJString(env, strs[i]));
|
env->SetObjectArrayElement(array, static_cast<jsize>(i), ToJString(env, strs[i]));
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -118,5 +118,4 @@ jmethodID GetYuzuDeviceHasKeys();
|
||||||
jmethodID GetAddNetPlayMessage();
|
jmethodID GetAddNetPlayMessage();
|
||||||
jmethodID ClearChat();
|
jmethodID ClearChat();
|
||||||
|
|
||||||
|
|
||||||
} // namespace Common::Android
|
} // namespace Common::Android
|
||||||
|
|
|
@ -6,23 +6,23 @@
|
||||||
|
|
||||||
#include "common/android/android_common.h"
|
#include "common/android/android_common.h"
|
||||||
|
|
||||||
|
#include "android/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "android/log.h"
|
|
||||||
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "web_service/web_backend.h"
|
|
||||||
#include "web_service/verify_user_jwt.h"
|
#include "web_service/verify_user_jwt.h"
|
||||||
|
#include "web_service/web_backend.h"
|
||||||
#include "web_service/web_result.h"
|
#include "web_service/web_result.h"
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace IDCache = Common::Android;
|
namespace IDCache = Common::Android;
|
||||||
|
|
||||||
AndroidMultiplayer::AndroidMultiplayer(Core::System &system_,
|
AndroidMultiplayer::AndroidMultiplayer(Core::System& system_,
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> session)
|
std::shared_ptr<Core::AnnounceMultiplayerSession> session)
|
||||||
: system{system_}, announce_multiplayer_session(session) {}
|
: system{system_}, announce_multiplayer_session(session) {}
|
||||||
|
|
||||||
AndroidMultiplayer::~AndroidMultiplayer() = default;
|
AndroidMultiplayer::~AndroidMultiplayer() = default;
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ void AndroidMultiplayer::AddNetPlayMessage(jint type, jstring msg) {
|
||||||
IDCache::GetAddNetPlayMessage(), type, msg);
|
IDCache::GetAddNetPlayMessage(), type, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMultiplayer::AddNetPlayMessage(int type, const std::string &msg) {
|
void AndroidMultiplayer::AddNetPlayMessage(int type, const std::string& msg) {
|
||||||
JNIEnv *env = IDCache::GetEnvForThread();
|
JNIEnv* env = IDCache::GetEnvForThread();
|
||||||
AddNetPlayMessage(type, Common::Android::ToJString(env, msg));
|
AddNetPlayMessage(type, Common::Android::ToJString(env, msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,91 +50,91 @@ bool AndroidMultiplayer::NetworkInit() {
|
||||||
|
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
// register the network structs to use in slots and signals
|
// register the network structs to use in slots and signals
|
||||||
member->BindOnStateChanged([this](const Network::RoomMember::State &state) {
|
member->BindOnStateChanged([this](const Network::RoomMember::State& state) {
|
||||||
if (state == Network::RoomMember::State::Joined ||
|
if (state == Network::RoomMember::State::Joined ||
|
||||||
state == Network::RoomMember::State::Moderator) {
|
state == Network::RoomMember::State::Moderator) {
|
||||||
NetPlayStatus status;
|
NetPlayStatus status;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Network::RoomMember::State::Joined:
|
case Network::RoomMember::State::Joined:
|
||||||
status = NetPlayStatus::ROOM_JOINED;
|
status = NetPlayStatus::ROOM_JOINED;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::State::Moderator:
|
case Network::RoomMember::State::Moderator:
|
||||||
status = NetPlayStatus::ROOM_MODERATOR;
|
status = NetPlayStatus::ROOM_MODERATOR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
member->BindOnError([this](const Network::RoomMember::Error &error) {
|
member->BindOnError([this](const Network::RoomMember::Error& error) {
|
||||||
NetPlayStatus status;
|
NetPlayStatus status;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case Network::RoomMember::Error::LostConnection:
|
case Network::RoomMember::Error::LostConnection:
|
||||||
status = NetPlayStatus::LOST_CONNECTION;
|
status = NetPlayStatus::LOST_CONNECTION;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::HostKicked:
|
case Network::RoomMember::Error::HostKicked:
|
||||||
status = NetPlayStatus::HOST_KICKED;
|
status = NetPlayStatus::HOST_KICKED;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::UnknownError:
|
case Network::RoomMember::Error::UnknownError:
|
||||||
status = NetPlayStatus::UNKNOWN_ERROR;
|
status = NetPlayStatus::UNKNOWN_ERROR;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::NameCollision:
|
case Network::RoomMember::Error::NameCollision:
|
||||||
status = NetPlayStatus::NAME_COLLISION;
|
status = NetPlayStatus::NAME_COLLISION;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::IpCollision:
|
case Network::RoomMember::Error::IpCollision:
|
||||||
status = NetPlayStatus::MAC_COLLISION;
|
status = NetPlayStatus::MAC_COLLISION;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::WrongVersion:
|
case Network::RoomMember::Error::WrongVersion:
|
||||||
status = NetPlayStatus::WRONG_VERSION;
|
status = NetPlayStatus::WRONG_VERSION;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::WrongPassword:
|
case Network::RoomMember::Error::WrongPassword:
|
||||||
status = NetPlayStatus::WRONG_PASSWORD;
|
status = NetPlayStatus::WRONG_PASSWORD;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::CouldNotConnect:
|
case Network::RoomMember::Error::CouldNotConnect:
|
||||||
status = NetPlayStatus::COULD_NOT_CONNECT;
|
status = NetPlayStatus::COULD_NOT_CONNECT;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::RoomIsFull:
|
case Network::RoomMember::Error::RoomIsFull:
|
||||||
status = NetPlayStatus::ROOM_IS_FULL;
|
status = NetPlayStatus::ROOM_IS_FULL;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::HostBanned:
|
case Network::RoomMember::Error::HostBanned:
|
||||||
status = NetPlayStatus::HOST_BANNED;
|
status = NetPlayStatus::HOST_BANNED;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::PermissionDenied:
|
case Network::RoomMember::Error::PermissionDenied:
|
||||||
status = NetPlayStatus::PERMISSION_DENIED;
|
status = NetPlayStatus::PERMISSION_DENIED;
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::Error::NoSuchUser:
|
case Network::RoomMember::Error::NoSuchUser:
|
||||||
status = NetPlayStatus::NO_SUCH_USER;
|
status = NetPlayStatus::NO_SUCH_USER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||||
});
|
});
|
||||||
member->BindOnStatusMessageReceived(
|
member->BindOnStatusMessageReceived(
|
||||||
[this](const Network::StatusMessageEntry &status_message) {
|
[this](const Network::StatusMessageEntry& status_message) {
|
||||||
NetPlayStatus status = NetPlayStatus::NO_ERROR;
|
NetPlayStatus status = NetPlayStatus::NO_ERROR;
|
||||||
std::string msg(status_message.nickname);
|
std::string msg(status_message.nickname);
|
||||||
switch (status_message.type) {
|
switch (status_message.type) {
|
||||||
case Network::IdMemberJoin:
|
case Network::IdMemberJoin:
|
||||||
status = NetPlayStatus::MEMBER_JOIN;
|
status = NetPlayStatus::MEMBER_JOIN;
|
||||||
break;
|
break;
|
||||||
case Network::IdMemberLeave:
|
case Network::IdMemberLeave:
|
||||||
status = NetPlayStatus::MEMBER_LEAVE;
|
status = NetPlayStatus::MEMBER_LEAVE;
|
||||||
break;
|
break;
|
||||||
case Network::IdMemberKicked:
|
case Network::IdMemberKicked:
|
||||||
status = NetPlayStatus::MEMBER_KICKED;
|
status = NetPlayStatus::MEMBER_KICKED;
|
||||||
break;
|
break;
|
||||||
case Network::IdMemberBanned:
|
case Network::IdMemberBanned:
|
||||||
status = NetPlayStatus::MEMBER_BANNED;
|
status = NetPlayStatus::MEMBER_BANNED;
|
||||||
break;
|
break;
|
||||||
case Network::IdAddressUnbanned:
|
case Network::IdAddressUnbanned:
|
||||||
status = NetPlayStatus::ADDRESS_UNBANNED;
|
status = NetPlayStatus::ADDRESS_UNBANNED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||||
});
|
});
|
||||||
member->BindOnChatMessageReceived([this](const Network::ChatEntry &chat) {
|
member->BindOnChatMessageReceived([this](const Network::ChatEntry& chat) {
|
||||||
NetPlayStatus status = NetPlayStatus::CHAT_MESSAGE;
|
NetPlayStatus status = NetPlayStatus::CHAT_MESSAGE;
|
||||||
std::string msg(chat.nickname);
|
std::string msg(chat.nickname);
|
||||||
msg += ": ";
|
msg += ": ";
|
||||||
|
@ -146,13 +146,10 @@ bool AndroidMultiplayer::NetworkInit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress, int port,
|
NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(
|
||||||
const std::string &username,
|
const std::string& ipaddress, int port, const std::string& username,
|
||||||
const std::string &preferredGameName,
|
const std::string& preferredGameName, const u64& preferredGameId, const std::string& password,
|
||||||
const u64 &preferredGameId,
|
const std::string& room_name, int max_players, bool isPublic) {
|
||||||
const std::string &password,
|
|
||||||
const std::string &room_name, int max_players,
|
|
||||||
bool isPublic) {
|
|
||||||
auto member = Network::GetRoomMember().lock();
|
auto member = Network::GetRoomMember().lock();
|
||||||
if (!member) {
|
if (!member) {
|
||||||
return NetPlayStatus::NETWORK_ERROR;
|
return NetPlayStatus::NETWORK_ERROR;
|
||||||
|
@ -173,8 +170,8 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress
|
||||||
|
|
||||||
// Placeholder game info
|
// Placeholder game info
|
||||||
const AnnounceMultiplayerRoom::GameInfo game{
|
const AnnounceMultiplayerRoom::GameInfo game{
|
||||||
.name = preferredGameName,
|
.name = preferredGameName,
|
||||||
.id = preferredGameId,
|
.id = preferredGameId,
|
||||||
};
|
};
|
||||||
|
|
||||||
port = (port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
port = (port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
||||||
|
@ -205,8 +202,8 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress
|
||||||
|
|
||||||
std::string token;
|
std::string token;
|
||||||
// TODO(alekpop): properly handle the compile definition, it's not working right
|
// TODO(alekpop): properly handle the compile definition, it's not working right
|
||||||
//#ifdef ENABLE_WEB_SERVICE
|
// #ifdef ENABLE_WEB_SERVICE
|
||||||
// LOG_INFO(WebService, "Web Service enabled");
|
// LOG_INFO(WebService, "Web Service enabled");
|
||||||
if (isPublic) {
|
if (isPublic) {
|
||||||
WebService::Client client(Settings::values.web_api_url.GetValue(),
|
WebService::Client client(Settings::values.web_api_url.GetValue(),
|
||||||
Settings::values.eden_username.GetValue(),
|
Settings::values.eden_username.GetValue(),
|
||||||
|
@ -220,9 +217,9 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress
|
||||||
LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size());
|
LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#else
|
// #else
|
||||||
// LOG_INFO(WebService, "Web Service disabled");
|
// LOG_INFO(WebService, "Web Service disabled");
|
||||||
//#endif
|
// #endif
|
||||||
|
|
||||||
member->Join(username, ipaddress.c_str(), static_cast<u16>(port), 0, Network::NoPreferredIP,
|
member->Join(username, ipaddress.c_str(), static_cast<u16>(port), 0, Network::NoPreferredIP,
|
||||||
password, token);
|
password, token);
|
||||||
|
@ -241,17 +238,15 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress
|
||||||
return NetPlayStatus::CREATE_ROOM_ERROR;
|
return NetPlayStatus::CREATE_ROOM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPlayStatus AndroidMultiplayer::NetPlayJoinRoom(const std::string &ipaddress, int port,
|
NetPlayStatus AndroidMultiplayer::NetPlayJoinRoom(const std::string& ipaddress, int port,
|
||||||
const std::string &username,
|
const std::string& username,
|
||||||
const std::string &password) {
|
const std::string& password) {
|
||||||
auto member = Network::GetRoomMember().lock();
|
auto member = Network::GetRoomMember().lock();
|
||||||
if (!member) {
|
if (!member) {
|
||||||
return NetPlayStatus::NETWORK_ERROR;
|
return NetPlayStatus::NETWORK_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
port =
|
port = (port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
||||||
(port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
|
||||||
|
|
||||||
|
|
||||||
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
|
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
|
||||||
return NetPlayStatus::ALREADY_IN_ROOM;
|
return NetPlayStatus::ALREADY_IN_ROOM;
|
||||||
|
@ -275,7 +270,7 @@ NetPlayStatus AndroidMultiplayer::NetPlayJoinRoom(const std::string &ipaddress,
|
||||||
return NetPlayStatus::WRONG_PASSWORD;
|
return NetPlayStatus::WRONG_PASSWORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMultiplayer::NetPlaySendMessage(const std::string &msg) {
|
void AndroidMultiplayer::NetPlaySendMessage(const std::string& msg) {
|
||||||
if (auto room = Network::GetRoomMember().lock()) {
|
if (auto room = Network::GetRoomMember().lock()) {
|
||||||
if (room->GetState() != Network::RoomMember::State::Joined &&
|
if (room->GetState() != Network::RoomMember::State::Joined &&
|
||||||
room->GetState() != Network::RoomMember::State::Moderator) {
|
room->GetState() != Network::RoomMember::State::Moderator) {
|
||||||
|
@ -286,11 +281,11 @@ void AndroidMultiplayer::NetPlaySendMessage(const std::string &msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMultiplayer::NetPlayKickUser(const std::string &username) {
|
void AndroidMultiplayer::NetPlayKickUser(const std::string& username) {
|
||||||
if (auto room = Network::GetRoomMember().lock()) {
|
if (auto room = Network::GetRoomMember().lock()) {
|
||||||
auto members = room->GetMemberInformation();
|
auto members = room->GetMemberInformation();
|
||||||
auto it = std::find_if(members.begin(), members.end(),
|
auto it = std::find_if(members.begin(), members.end(),
|
||||||
[&username](const Network::RoomMember::MemberInformation &member) {
|
[&username](const Network::RoomMember::MemberInformation& member) {
|
||||||
return member.nickname == username;
|
return member.nickname == username;
|
||||||
});
|
});
|
||||||
if (it != members.end()) {
|
if (it != members.end()) {
|
||||||
|
@ -299,11 +294,11 @@ void AndroidMultiplayer::NetPlayKickUser(const std::string &username) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMultiplayer::NetPlayBanUser(const std::string &username) {
|
void AndroidMultiplayer::NetPlayBanUser(const std::string& username) {
|
||||||
if (auto room = Network::GetRoomMember().lock()) {
|
if (auto room = Network::GetRoomMember().lock()) {
|
||||||
auto members = room->GetMemberInformation();
|
auto members = room->GetMemberInformation();
|
||||||
auto it = std::find_if(members.begin(), members.end(),
|
auto it = std::find_if(members.begin(), members.end(),
|
||||||
[&username](const Network::RoomMember::MemberInformation &member) {
|
[&username](const Network::RoomMember::MemberInformation& member) {
|
||||||
return member.nickname == username;
|
return member.nickname == username;
|
||||||
});
|
});
|
||||||
if (it != members.end()) {
|
if (it != members.end()) {
|
||||||
|
@ -312,7 +307,7 @@ void AndroidMultiplayer::NetPlayBanUser(const std::string &username) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMultiplayer::NetPlayUnbanUser(const std::string &username) {
|
void AndroidMultiplayer::NetPlayUnbanUser(const std::string& username) {
|
||||||
if (auto room = Network::GetRoomMember().lock()) {
|
if (auto room = Network::GetRoomMember().lock()) {
|
||||||
room->SendModerationRequest(Network::RoomMessageTypes::IdModUnban, username);
|
room->SendModerationRequest(Network::RoomMessageTypes::IdModUnban, username);
|
||||||
}
|
}
|
||||||
|
@ -327,7 +322,7 @@ std::vector<std::string> AndroidMultiplayer::NetPlayRoomInfo() {
|
||||||
auto room_info = room->GetRoomInformation();
|
auto room_info = room->GetRoomInformation();
|
||||||
info_list.push_back(room_info.name + "|" + std::to_string(room_info.member_slots));
|
info_list.push_back(room_info.name + "|" + std::to_string(room_info.member_slots));
|
||||||
// all members
|
// all members
|
||||||
for (const auto &member: members) {
|
for (const auto& member : members) {
|
||||||
info_list.push_back(member.nickname);
|
info_list.push_back(member.nickname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,30 +380,24 @@ std::vector<std::string> AndroidMultiplayer::NetPlayGetPublicRooms() {
|
||||||
|
|
||||||
if (auto session = announce_multiplayer_session.lock()) {
|
if (auto session = announce_multiplayer_session.lock()) {
|
||||||
auto rooms = session->GetRoomList();
|
auto rooms = session->GetRoomList();
|
||||||
for (const auto &room: rooms) {
|
for (const auto& room : rooms) {
|
||||||
room_list.push_back(room.information.name + "|" +
|
room_list.push_back(room.information.name + "|" + (room.has_password ? "1" : "0") +
|
||||||
(room.has_password ? "1" : "0") + "|" +
|
"|" + std::to_string(room.information.member_slots) + "|" +
|
||||||
std::to_string(room.information.member_slots) + "|" +
|
room.ip + "|" + std::to_string(room.information.port) + "|" +
|
||||||
room.ip + "|" +
|
|
||||||
std::to_string(room.information.port) + "|" +
|
|
||||||
room.information.description + "|" +
|
room.information.description + "|" +
|
||||||
room.information.host_username + "|" +
|
room.information.host_username + "|" +
|
||||||
std::to_string(room.information.preferred_game.id) + "|" +
|
std::to_string(room.information.preferred_game.id) + "|" +
|
||||||
room.information.preferred_game.name + "|" +
|
room.information.preferred_game.name + "|" +
|
||||||
room.information.preferred_game.version);
|
room.information.preferred_game.version);
|
||||||
|
|
||||||
for (const auto &member: room.members) {
|
for (const auto& member : room.members) {
|
||||||
room_list.push_back("MEMBER|" + room.information.name + "|" +
|
room_list.push_back("MEMBER|" + room.information.name + "|" + member.username +
|
||||||
member.username + "|" +
|
"|" + member.nickname + "|" + std::to_string(member.game.id) +
|
||||||
member.nickname + "|" +
|
"|" + member.game.name);
|
||||||
std::to_string(member.game.id) + "|" +
|
|
||||||
member.game.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return room_list;
|
return room_list;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> AndroidMultiplayer::NetPlayGetBanList() {
|
std::vector<std::string> AndroidMultiplayer::NetPlayGetBanList() {
|
||||||
|
@ -417,27 +406,28 @@ std::vector<std::string> AndroidMultiplayer::NetPlayGetBanList() {
|
||||||
auto [username_bans, ip_bans] = room->GetBanList();
|
auto [username_bans, ip_bans] = room->GetBanList();
|
||||||
|
|
||||||
// Add username bans
|
// Add username bans
|
||||||
for (const auto &username: username_bans) {
|
for (const auto& username : username_bans) {
|
||||||
ban_list.push_back(username);
|
ban_list.push_back(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add IP bans
|
// Add IP bans
|
||||||
for (const auto &ip: ip_bans) {
|
for (const auto& ip : ip_bans) {
|
||||||
ban_list.push_back(ip);
|
ban_list.push_back(ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ban_list;
|
return ban_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Network::VerifyUser::Backend> AndroidMultiplayer::CreateVerifyBackend(bool use_validation) {
|
std::unique_ptr<Network::VerifyUser::Backend> AndroidMultiplayer::CreateVerifyBackend(
|
||||||
|
bool use_validation) {
|
||||||
std::unique_ptr<Network::VerifyUser::Backend> verify_backend;
|
std::unique_ptr<Network::VerifyUser::Backend> verify_backend;
|
||||||
if (use_validation) {
|
if (use_validation) {
|
||||||
//#ifdef ENABLE_WEB_SERVICE
|
// #ifdef ENABLE_WEB_SERVICE
|
||||||
verify_backend =
|
verify_backend =
|
||||||
std::make_unique<WebService::VerifyUserJWT>(Settings::values.web_api_url.GetValue());
|
std::make_unique<WebService::VerifyUserJWT>(Settings::values.web_api_url.GetValue());
|
||||||
//#else
|
// #else
|
||||||
// verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
|
// verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
|
||||||
//#endif
|
// #endif
|
||||||
} else {
|
} else {
|
||||||
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
|
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <common/common_types.h>
|
#include <common/common_types.h>
|
||||||
#include <network/network.h>
|
|
||||||
#include <network/announce_multiplayer_session.h>
|
#include <network/announce_multiplayer_session.h>
|
||||||
|
#include <network/network.h>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
class AnnounceMultiplayerSession;
|
class AnnounceMultiplayerSession;
|
||||||
}
|
} // namespace Core
|
||||||
|
|
||||||
enum class NetPlayStatus : s32 {
|
enum class NetPlayStatus : s32 {
|
||||||
NO_ERROR,
|
NO_ERROR,
|
||||||
|
@ -63,13 +63,14 @@ public:
|
||||||
|
|
||||||
void ClearChat();
|
void ClearChat();
|
||||||
|
|
||||||
NetPlayStatus NetPlayCreateRoom(const std::string &ipaddress, int port,
|
NetPlayStatus NetPlayCreateRoom(const std::string& ipaddress, int port,
|
||||||
const std::string &username, const std::string &preferredGameName,
|
const std::string& username,
|
||||||
const u64 &preferredGameId, const std::string &password,
|
const std::string& preferredGameName,
|
||||||
const std::string &room_name, int max_players, bool isPublic);
|
const u64& preferredGameId, const std::string& password,
|
||||||
|
const std::string& room_name, int max_players, bool isPublic);
|
||||||
|
|
||||||
NetPlayStatus NetPlayJoinRoom(const std::string &ipaddress, int port,
|
NetPlayStatus NetPlayJoinRoom(const std::string& ipaddress, int port,
|
||||||
const std::string &username, const std::string &password);
|
const std::string& username, const std::string& password);
|
||||||
|
|
||||||
std::vector<std::string> NetPlayRoomInfo();
|
std::vector<std::string> NetPlayRoomInfo();
|
||||||
|
|
||||||
|
@ -79,11 +80,11 @@ public:
|
||||||
|
|
||||||
bool NetPlayIsModerator();
|
bool NetPlayIsModerator();
|
||||||
|
|
||||||
void NetPlaySendMessage(const std::string &msg);
|
void NetPlaySendMessage(const std::string& msg);
|
||||||
|
|
||||||
void NetPlayKickUser(const std::string &username);
|
void NetPlayKickUser(const std::string& username);
|
||||||
|
|
||||||
void NetPlayBanUser(const std::string &username);
|
void NetPlayBanUser(const std::string& username);
|
||||||
|
|
||||||
void NetPlayLeaveRoom();
|
void NetPlayLeaveRoom();
|
||||||
|
|
||||||
|
@ -91,12 +92,12 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> NetPlayGetBanList();
|
std::vector<std::string> NetPlayGetBanList();
|
||||||
|
|
||||||
void NetPlayUnbanUser(const std::string &username);
|
void NetPlayUnbanUser(const std::string& username);
|
||||||
|
|
||||||
std::vector<std::string> NetPlayGetPublicRooms();
|
std::vector<std::string> NetPlayGetPublicRooms();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
static std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) ;
|
static std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation);
|
||||||
std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,9 +16,9 @@ concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
|
||||||
// is available on all supported platforms.
|
// is available on all supported platforms.
|
||||||
template <typename Derived, typename Base>
|
template <typename Derived, typename Base>
|
||||||
concept DerivedFrom = requires {
|
concept DerivedFrom = requires {
|
||||||
std::is_base_of_v<Base, Derived>;
|
std::is_base_of_v<Base, Derived>;
|
||||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Replace with std::convertible_to when libc++ implements it.
|
// TODO: Replace with std::convertible_to when libc++ implements it.
|
||||||
template <typename From, typename To>
|
template <typename From, typename To>
|
||||||
|
|
|
@ -27,76 +27,73 @@ extern std::atomic<bool> g_has_battery;
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
PowerStatus GetPowerStatus()
|
PowerStatus GetPowerStatus() {
|
||||||
{
|
PowerStatus info;
|
||||||
PowerStatus info;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
SYSTEM_POWER_STATUS status;
|
SYSTEM_POWER_STATUS status;
|
||||||
if (GetSystemPowerStatus(&status)) {
|
if (GetSystemPowerStatus(&status)) {
|
||||||
if (status.BatteryFlag == 128) {
|
if (status.BatteryFlag == 128) {
|
||||||
info.has_battery = false;
|
|
||||||
} else {
|
|
||||||
info.percentage = status.BatteryLifePercent;
|
|
||||||
info.charging = (status.BatteryFlag & 8) != 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info.has_battery = false;
|
info.has_battery = false;
|
||||||
|
} else {
|
||||||
|
info.percentage = status.BatteryLifePercent;
|
||||||
|
info.charging = (status.BatteryFlag & 8) != 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info.has_battery = false;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__ANDROID__)
|
#elif defined(__ANDROID__)
|
||||||
info.percentage = g_battery_percentage.load(std::memory_order_relaxed);
|
info.percentage = g_battery_percentage.load(std::memory_order_relaxed);
|
||||||
info.charging = g_is_charging.load(std::memory_order_relaxed);
|
info.charging = g_is_charging.load(std::memory_order_relaxed);
|
||||||
info.has_battery = g_has_battery.load(std::memory_order_relaxed);
|
info.has_battery = g_has_battery.load(std::memory_order_relaxed);
|
||||||
|
|
||||||
#elif defined(__APPLE__) && TARGET_OS_MAC
|
#elif defined(__APPLE__) && TARGET_OS_MAC
|
||||||
CFTypeRef info_ref = IOPSCopyPowerSourcesInfo();
|
CFTypeRef info_ref = IOPSCopyPowerSourcesInfo();
|
||||||
CFArrayRef sources = IOPSCopyPowerSourcesList(info_ref);
|
CFArrayRef sources = IOPSCopyPowerSourcesList(info_ref);
|
||||||
if (CFArrayGetCount(sources) > 0) {
|
if (CFArrayGetCount(sources) > 0) {
|
||||||
CFDictionaryRef battery =
|
CFDictionaryRef battery =
|
||||||
IOPSGetPowerSourceDescription(info_ref, CFArrayGetValueAtIndex(sources, 0));
|
IOPSGetPowerSourceDescription(info_ref, CFArrayGetValueAtIndex(sources, 0));
|
||||||
|
|
||||||
CFNumberRef curNum =
|
CFNumberRef curNum =
|
||||||
(CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey));
|
(CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey));
|
||||||
CFNumberRef maxNum =
|
CFNumberRef maxNum = (CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey));
|
||||||
(CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey));
|
int cur = 0, max = 0;
|
||||||
int cur = 0, max = 0;
|
CFNumberGetValue(curNum, kCFNumberIntType, &cur);
|
||||||
CFNumberGetValue(curNum, kCFNumberIntType, &cur);
|
CFNumberGetValue(maxNum, kCFNumberIntType, &max);
|
||||||
CFNumberGetValue(maxNum, kCFNumberIntType, &max);
|
|
||||||
|
|
||||||
if (max > 0)
|
if (max > 0)
|
||||||
info.percentage = (cur * 100) / max;
|
info.percentage = (cur * 100) / max;
|
||||||
|
|
||||||
CFBooleanRef isCharging =
|
CFBooleanRef isCharging =
|
||||||
(CFBooleanRef)CFDictionaryGetValue(battery, CFSTR(kIOPSIsChargingKey));
|
(CFBooleanRef)CFDictionaryGetValue(battery, CFSTR(kIOPSIsChargingKey));
|
||||||
info.charging = CFBooleanGetValue(isCharging);
|
info.charging = CFBooleanGetValue(isCharging);
|
||||||
} else {
|
} else {
|
||||||
info.has_battery = false;
|
info.has_battery = false;
|
||||||
}
|
}
|
||||||
CFRelease(sources);
|
CFRelease(sources);
|
||||||
CFRelease(info_ref);
|
CFRelease(info_ref);
|
||||||
|
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
const char* battery_path = "/sys/class/power_supply/BAT0/";
|
const char* battery_path = "/sys/class/power_supply/BAT0/";
|
||||||
|
|
||||||
std::ifstream capFile(std::string(battery_path) + "capacity");
|
std::ifstream capFile(std::string(battery_path) + "capacity");
|
||||||
if (capFile) {
|
if (capFile) {
|
||||||
capFile >> info.percentage;
|
capFile >> info.percentage;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
info.has_battery = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream statFile(std::string(battery_path) + "status");
|
|
||||||
if (statFile) {
|
|
||||||
std::string status;
|
|
||||||
std::getline(statFile, status);
|
|
||||||
info.charging = (status == "Charging");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
info.has_battery = false;
|
info.has_battery = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream statFile(std::string(battery_path) + "status");
|
||||||
|
if (statFile) {
|
||||||
|
std::string status;
|
||||||
|
std::getline(statFile, status);
|
||||||
|
info.charging = (status == "Charging");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
info.has_battery = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} // namespace Common
|
||||||
|
|
|
@ -598,14 +598,14 @@ public:
|
||||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||||
std::enable_if_t<!std::is_convertible_v<G&&, E>>* = nullptr>
|
std::enable_if_t<!std::is_convertible_v<G&&, E>>* = nullptr>
|
||||||
constexpr explicit Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
constexpr explicit Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||||
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
: impl_base{unexpect_t{}, std::move(e.value())},
|
||||||
detail::default_constructor_tag{}} {}
|
ctor_base{detail::default_constructor_tag{}} {}
|
||||||
|
|
||||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||||
std::enable_if_t<std::is_convertible_v<G&&, E>>* = nullptr>
|
std::enable_if_t<std::is_convertible_v<G&&, E>>* = nullptr>
|
||||||
constexpr Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
constexpr Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||||
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
: impl_base{unexpect_t{}, std::move(e.value())},
|
||||||
detail::default_constructor_tag{}} {}
|
ctor_base{detail::default_constructor_tag{}} {}
|
||||||
|
|
||||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
||||||
constexpr explicit Expected(unexpect_t, Args&&... args)
|
constexpr explicit Expected(unexpect_t, Args&&... args)
|
||||||
|
|
|
@ -88,9 +88,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateEdenPaths() {
|
void CreateEdenPaths() {
|
||||||
std::for_each(eden_paths.begin(), eden_paths.end(), [](auto &path) {
|
std::for_each(eden_paths.begin(), eden_paths.end(),
|
||||||
void(FS::CreateDir(path.second));
|
[](auto& path) { void(FS::CreateDir(path.second)); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEdenPathImpl(EdenPath eden_path, const fs::path& new_path) {
|
void SetEdenPathImpl(EdenPath eden_path, const fs::path& new_path) {
|
||||||
|
@ -116,9 +115,13 @@ public:
|
||||||
eden_path_cache = eden_path / CACHE_DIR;
|
eden_path_cache = eden_path / CACHE_DIR;
|
||||||
eden_path_config = eden_path / CONFIG_DIR;
|
eden_path_config = eden_path / CONFIG_DIR;
|
||||||
|
|
||||||
#define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetAppDataRoamingDirectory() / upperName##_DIR); \
|
#define LEGACY_PATH(titleName, upperName) \
|
||||||
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetAppDataRoamingDirectory() / upperName##_DIR / CONFIG_DIR); \
|
GenerateLegacyPath(LegacyPath::titleName##Dir, \
|
||||||
GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetAppDataRoamingDirectory() / upperName##_DIR / CACHE_DIR);
|
GetAppDataRoamingDirectory() / upperName##_DIR); \
|
||||||
|
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, \
|
||||||
|
GetAppDataRoamingDirectory() / upperName##_DIR / CONFIG_DIR); \
|
||||||
|
GenerateLegacyPath(LegacyPath::titleName##CacheDir, \
|
||||||
|
GetAppDataRoamingDirectory() / upperName##_DIR / CACHE_DIR);
|
||||||
|
|
||||||
LEGACY_PATH(Citron, CITRON)
|
LEGACY_PATH(Citron, CITRON)
|
||||||
LEGACY_PATH(Sudachi, SUDACHI)
|
LEGACY_PATH(Sudachi, SUDACHI)
|
||||||
|
@ -143,9 +146,13 @@ public:
|
||||||
eden_path_config = GetDataDirectory("XDG_CONFIG_HOME") / EDEN_DIR;
|
eden_path_config = GetDataDirectory("XDG_CONFIG_HOME") / EDEN_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetDataDirectory("XDG_DATA_HOME") / upperName##_DIR); \
|
#define LEGACY_PATH(titleName, upperName) \
|
||||||
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetDataDirectory("XDG_CONFIG_HOME") / upperName##_DIR); \
|
GenerateLegacyPath(LegacyPath::titleName##Dir, \
|
||||||
GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetDataDirectory("XDG_CACHE_HOME") / upperName##_DIR);
|
GetDataDirectory("XDG_DATA_HOME") / upperName##_DIR); \
|
||||||
|
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, \
|
||||||
|
GetDataDirectory("XDG_CONFIG_HOME") / upperName##_DIR); \
|
||||||
|
GenerateLegacyPath(LegacyPath::titleName##CacheDir, \
|
||||||
|
GetDataDirectory("XDG_CACHE_HOME") / upperName##_DIR);
|
||||||
|
|
||||||
LEGACY_PATH(Citron, CITRON)
|
LEGACY_PATH(Citron, CITRON)
|
||||||
LEGACY_PATH(Sudachi, SUDACHI)
|
LEGACY_PATH(Sudachi, SUDACHI)
|
||||||
|
@ -301,8 +308,7 @@ void SetEdenPath(EdenPath eden_path, const fs::path& new_path) {
|
||||||
PathManagerImpl::GetInstance().SetEdenPathImpl(eden_path, new_path);
|
PathManagerImpl::GetInstance().SetEdenPathImpl(eden_path, new_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateEdenPaths()
|
void CreateEdenPaths() {
|
||||||
{
|
|
||||||
PathManagerImpl::GetInstance().CreateEdenPaths();
|
PathManagerImpl::GetInstance().CreateEdenPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ HeapTracker::~HeapTracker() = default;
|
||||||
|
|
||||||
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
||||||
MemoryPermission perm, bool is_separate_heap) {
|
MemoryPermission perm, bool is_separate_heap) {
|
||||||
|
bool rebuild_required = false;
|
||||||
|
|
||||||
// When mapping other memory, map pages immediately.
|
// When mapping other memory, map pages immediately.
|
||||||
if (!is_separate_heap) {
|
if (!is_separate_heap) {
|
||||||
m_buffer.Map(virtual_offset, host_offset, length, perm, false);
|
m_buffer.Map(virtual_offset, host_offset, length, perm, false);
|
||||||
|
@ -55,11 +57,29 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
||||||
|
|
||||||
// Insert into mappings.
|
// Insert into mappings.
|
||||||
m_map_count++;
|
m_map_count++;
|
||||||
m_mappings.insert(*map);
|
const auto it = m_mappings.insert(*map);
|
||||||
|
|
||||||
|
// Update tick before possible rebuild.
|
||||||
|
it->tick = m_tick++;
|
||||||
|
|
||||||
|
// Check if we need to rebuild.
|
||||||
|
if (m_resident_map_count >= m_max_resident_map_count) {
|
||||||
|
rebuild_required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the area.
|
||||||
|
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
|
||||||
|
|
||||||
|
// This map is now resident.
|
||||||
|
it->is_resident = true;
|
||||||
|
m_resident_map_count++;
|
||||||
|
m_resident_mappings.insert(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, map.
|
if (rebuild_required) {
|
||||||
this->DeferredMapSeparateHeap(virtual_offset);
|
// A rebuild was required, so perform it now.
|
||||||
|
this->RebuildSeparateHeapAddressSpace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) {
|
void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) {
|
||||||
|
@ -157,51 +177,6 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) {
|
|
||||||
if (m_buffer.IsInVirtualRange(fault_address)) {
|
|
||||||
return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) {
|
|
||||||
bool rebuild_required = false;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
// Check to ensure this was a non-resident separate heap mapping.
|
|
||||||
const auto it = this->GetNearestHeapMapLocked(virtual_offset);
|
|
||||||
if (it == m_mappings.end() || it->is_resident) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update tick before possible rebuild.
|
|
||||||
it->tick = m_tick++;
|
|
||||||
|
|
||||||
// Check if we need to rebuild.
|
|
||||||
if (m_resident_map_count > m_max_resident_map_count) {
|
|
||||||
rebuild_required = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the area.
|
|
||||||
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
|
|
||||||
|
|
||||||
// This map is now resident.
|
|
||||||
it->is_resident = true;
|
|
||||||
m_resident_map_count++;
|
|
||||||
m_resident_mappings.insert(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rebuild_required) {
|
|
||||||
// A rebuild was required, so perform it now.
|
|
||||||
this->RebuildSeparateHeapAddressSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeapTracker::RebuildSeparateHeapAddressSpace() {
|
void HeapTracker::RebuildSeparateHeapAddressSpace() {
|
||||||
std::scoped_lock lk{m_rebuild_lock, m_lock};
|
std::scoped_lock lk{m_rebuild_lock, m_lock};
|
||||||
|
|
||||||
|
|
|
@ -538,7 +538,7 @@ public:
|
||||||
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
||||||
class IntrusiveListMemberTraits;
|
class IntrusiveListMemberTraits;
|
||||||
|
|
||||||
template <class Parent, IntrusiveListNode Parent::*Member, class Derived>
|
template <class Parent, IntrusiveListNode Parent::* Member, class Derived>
|
||||||
class IntrusiveListMemberTraits<Member, Derived> {
|
class IntrusiveListMemberTraits<Member, Derived> {
|
||||||
public:
|
public:
|
||||||
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraits>;
|
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraits>;
|
||||||
|
@ -566,7 +566,7 @@ private:
|
||||||
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
||||||
class IntrusiveListMemberTraitsByNonConstexprOffsetOf;
|
class IntrusiveListMemberTraitsByNonConstexprOffsetOf;
|
||||||
|
|
||||||
template <class Parent, IntrusiveListNode Parent::*Member, class Derived>
|
template <class Parent, IntrusiveListNode Parent::* Member, class Derived>
|
||||||
class IntrusiveListMemberTraitsByNonConstexprOffsetOf<Member, Derived> {
|
class IntrusiveListMemberTraitsByNonConstexprOffsetOf<Member, Derived> {
|
||||||
public:
|
public:
|
||||||
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraitsByNonConstexprOffsetOf>;
|
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraitsByNonConstexprOffsetOf>;
|
||||||
|
|
|
@ -238,10 +238,8 @@ public:
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept HasRedBlackKeyType = requires {
|
concept HasRedBlackKeyType = requires {
|
||||||
{
|
{ std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
|
||||||
std::is_same<typename T::RedBlackKeyType, void>::value
|
};
|
||||||
} -> std::convertible_to<bool>;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
|
@ -497,7 +495,7 @@ public:
|
||||||
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
||||||
class IntrusiveRedBlackTreeMemberTraits;
|
class IntrusiveRedBlackTreeMemberTraits;
|
||||||
|
|
||||||
template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
|
template <class Parent, IntrusiveRedBlackTreeNode Parent::* Member, class Derived>
|
||||||
class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
|
class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
|
||||||
public:
|
public:
|
||||||
template <class Comparator>
|
template <class Comparator>
|
||||||
|
@ -530,7 +528,7 @@ private:
|
||||||
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
template <auto T, class Derived = Common::impl::GetParentType<T>>
|
||||||
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
|
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
|
||||||
|
|
||||||
template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
|
template <class Parent, IntrusiveRedBlackTreeNode Parent::* Member, class Derived>
|
||||||
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
|
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
|
||||||
public:
|
public:
|
||||||
template <class Comparator>
|
template <class Comparator>
|
||||||
|
|
|
@ -90,8 +90,8 @@ public:
|
||||||
auto old_filename = filename;
|
auto old_filename = filename;
|
||||||
old_filename += ".old.txt";
|
old_filename += ".old.txt";
|
||||||
|
|
||||||
// Existence checks are done within the functions themselves.
|
// Existence checks are done within the functions themselves.
|
||||||
// We don't particularly care if these succeed or not.
|
// We don't particularly care if these succeed or not.
|
||||||
static_cast<void>(FS::RemoveFile(old_filename));
|
static_cast<void>(FS::RemoveFile(old_filename));
|
||||||
static_cast<void>(FS::RenameFile(filename, old_filename));
|
static_cast<void>(FS::RenameFile(filename, old_filename));
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Minimal asymmetric stackful cross-platform coroutine library in pure C.
|
Minimal asymmetric stackful cross-platform coroutine library in pure C.
|
||||||
minicoro - v0.2.0 - 15/Nov/2023
|
minicoro - v0.2.0 - 15/Nov/2023
|
||||||
|
@ -467,7 +470,7 @@ extern "C" {
|
||||||
#ifdef MCO_NO_MULTITHREAD
|
#ifdef MCO_NO_MULTITHREAD
|
||||||
#define MCO_THREAD_LOCAL
|
#define MCO_THREAD_LOCAL
|
||||||
#else
|
#else
|
||||||
#ifdef thread_local
|
#if defined(thread_local) || __STDC_VERSION__ >= 202311L || defined(__sun__)
|
||||||
#define MCO_THREAD_LOCAL thread_local
|
#define MCO_THREAD_LOCAL thread_local
|
||||||
#elif __STDC_VERSION__ >= 201112 && !defined(__STDC_NO_THREADS__)
|
#elif __STDC_VERSION__ >= 201112 && !defined(__STDC_NO_THREADS__)
|
||||||
#define MCO_THREAD_LOCAL _Thread_local
|
#define MCO_THREAD_LOCAL _Thread_local
|
||||||
|
|
|
@ -25,12 +25,12 @@ public:
|
||||||
|
|
||||||
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
|
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
|
||||||
: address_space_bits{std::exchange(other.address_space_bits, 0)},
|
: address_space_bits{std::exchange(other.address_space_bits, 0)},
|
||||||
first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
|
first_level_bits{std::exchange(other.first_level_bits, 0)},
|
||||||
other.page_bits, 0)},
|
page_bits{std::exchange(other.page_bits, 0)},
|
||||||
first_level_shift{std::exchange(other.first_level_shift, 0)},
|
first_level_shift{std::exchange(other.first_level_shift, 0)},
|
||||||
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
|
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
|
||||||
first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
|
first_level_map{std::move(other.first_level_map)},
|
||||||
nullptr)} {}
|
base_ptr{std::exchange(other.base_ptr, nullptr)} {}
|
||||||
|
|
||||||
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
|
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
|
||||||
address_space_bits = std::exchange(other.address_space_bits, 0);
|
address_space_bits = std::exchange(other.address_space_bits, 0);
|
||||||
|
|
|
@ -92,7 +92,7 @@ struct OffsetOfCalculator {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CurUnion>
|
template <typename CurUnion>
|
||||||
static constexpr std::ptrdiff_t OffsetOfImpl(MemberType ParentType::*member,
|
static constexpr std::ptrdiff_t OffsetOfImpl(MemberType ParentType::* member,
|
||||||
CurUnion& cur_union) {
|
CurUnion& cur_union) {
|
||||||
constexpr size_t Offset = CurUnion::GetOffset();
|
constexpr size_t Offset = CurUnion::GetOffset();
|
||||||
const auto target = std::addressof(GetPointer(U.parent)->*member);
|
const auto target = std::addressof(GetPointer(U.parent)->*member);
|
||||||
|
@ -111,7 +111,7 @@ struct OffsetOfCalculator {
|
||||||
Offset);
|
Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) {
|
static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::* member) {
|
||||||
return OffsetOfImpl(member, U.first_union);
|
return OffsetOfImpl(member, U.first_union);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,12 +34,12 @@ struct Point {
|
||||||
.y = static_cast<T>(value op rhs.y), \
|
.y = static_cast<T>(value op rhs.y), \
|
||||||
}; \
|
}; \
|
||||||
} \
|
} \
|
||||||
friend constexpr Point& operator compound_op(Point& lhs, const Point& rhs) noexcept { \
|
friend constexpr Point& operator compound_op(Point & lhs, const Point & rhs) noexcept { \
|
||||||
lhs.x = static_cast<T>(lhs.x op rhs.x); \
|
lhs.x = static_cast<T>(lhs.x op rhs.x); \
|
||||||
lhs.y = static_cast<T>(lhs.y op rhs.y); \
|
lhs.y = static_cast<T>(lhs.y op rhs.y); \
|
||||||
return lhs; \
|
return lhs; \
|
||||||
} \
|
} \
|
||||||
friend constexpr Point& operator compound_op(Point& lhs, T value) noexcept { \
|
friend constexpr Point& operator compound_op(Point & lhs, T value) noexcept { \
|
||||||
lhs.x = static_cast<T>(lhs.x op value); \
|
lhs.x = static_cast<T>(lhs.x op value); \
|
||||||
lhs.y = static_cast<T>(lhs.y op value); \
|
lhs.y = static_cast<T>(lhs.y op value); \
|
||||||
return lhs; \
|
return lhs; \
|
||||||
|
|
|
@ -18,9 +18,9 @@ namespace ranges {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept range = requires(T& t) {
|
concept range = requires(T& t) {
|
||||||
begin(t);
|
begin(t);
|
||||||
end(t);
|
end(t);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept input_range = range<T>;
|
concept input_range = range<T>;
|
||||||
|
|
|
@ -339,7 +339,9 @@ void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stop_callback callback(token, [&] {
|
std::stop_callback callback(token, [&] {
|
||||||
{ std::scoped_lock lk2{*lk.mutex()}; }
|
{
|
||||||
|
std::scoped_lock lk2{*lk.mutex()};
|
||||||
|
}
|
||||||
cv.notify_all();
|
cv.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ struct Values {
|
||||||
Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::LLE, "net_connect_applet_mode",
|
Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::LLE, "net_connect_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> player_select_applet_mode{
|
Setting<AppletMode> player_select_applet_mode{
|
||||||
linkage, AppletMode::LLE, "player_select_applet_mode", Category::LibraryApplet};
|
linkage, AppletMode::LLE, "player_select_applet_mode", Category::LibraryApplet};
|
||||||
Setting<AppletMode> swkbd_applet_mode{linkage, AppletMode::HLE, "swkbd_applet_mode",
|
Setting<AppletMode> swkbd_applet_mode{linkage, AppletMode::HLE, "swkbd_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> mii_edit_applet_mode{linkage, AppletMode::LLE, "mii_edit_applet_mode",
|
Setting<AppletMode> mii_edit_applet_mode{linkage, AppletMode::LLE, "mii_edit_applet_mode",
|
||||||
|
@ -160,13 +160,13 @@ struct Values {
|
||||||
Setting<AppletMode> shop_applet_mode{linkage, AppletMode::HLE, "shop_applet_mode",
|
Setting<AppletMode> shop_applet_mode{linkage, AppletMode::HLE, "shop_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> photo_viewer_applet_mode{
|
Setting<AppletMode> photo_viewer_applet_mode{
|
||||||
linkage, AppletMode::LLE, "photo_viewer_applet_mode", Category::LibraryApplet};
|
linkage, AppletMode::LLE, "photo_viewer_applet_mode", Category::LibraryApplet};
|
||||||
Setting<AppletMode> offline_web_applet_mode{linkage, AppletMode::LLE, "offline_web_applet_mode",
|
Setting<AppletMode> offline_web_applet_mode{linkage, AppletMode::LLE, "offline_web_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> login_share_applet_mode{linkage, AppletMode::HLE, "login_share_applet_mode",
|
Setting<AppletMode> login_share_applet_mode{linkage, AppletMode::HLE, "login_share_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> wifi_web_auth_applet_mode{
|
Setting<AppletMode> wifi_web_auth_applet_mode{
|
||||||
linkage, AppletMode::HLE, "wifi_web_auth_applet_mode", Category::LibraryApplet};
|
linkage, AppletMode::HLE, "wifi_web_auth_applet_mode", Category::LibraryApplet};
|
||||||
Setting<AppletMode> my_page_applet_mode{linkage, AppletMode::LLE, "my_page_applet_mode",
|
Setting<AppletMode> my_page_applet_mode{linkage, AppletMode::LLE, "my_page_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
|
|
||||||
|
@ -174,13 +174,13 @@ struct Values {
|
||||||
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
||||||
Category::Audio, Specialization::RuntimeList};
|
Category::Audio, Specialization::RuntimeList};
|
||||||
SwitchableSetting<std::string> audio_output_device_id{
|
SwitchableSetting<std::string> audio_output_device_id{
|
||||||
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
||||||
SwitchableSetting<std::string> audio_input_device_id{
|
SwitchableSetting<std::string> audio_input_device_id{
|
||||||
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
||||||
SwitchableSetting<AudioMode, true> sound_index{
|
SwitchableSetting<AudioMode, true> sound_index{
|
||||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<u8, true> volume{linkage,
|
SwitchableSetting<u8, true> volume{linkage,
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
|
@ -191,9 +191,9 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
Setting<bool, false> audio_muted{
|
Setting<bool, false> audio_muted{
|
||||||
linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true};
|
linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true};
|
||||||
Setting<bool, false> dump_audio_commands{
|
Setting<bool, false> dump_audio_commands{
|
||||||
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
|
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
|
||||||
|
@ -206,7 +206,7 @@ struct Values {
|
||||||
Specialization::Default,
|
Specialization::Default,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<bool> use_speed_limit{
|
SwitchableSetting<bool> use_speed_limit{
|
||||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true};
|
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true};
|
||||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
|
@ -217,7 +217,8 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&use_speed_limit};
|
&use_speed_limit};
|
||||||
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default};
|
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core,
|
||||||
|
Specialization::Default};
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
#ifdef HAS_NCE
|
#ifdef HAS_NCE
|
||||||
|
@ -243,29 +244,14 @@ struct Values {
|
||||||
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
|
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
|
||||||
"cpu_accuracy", Category::Cpu};
|
"cpu_accuracy", Category::Cpu};
|
||||||
|
|
||||||
SwitchableSetting<bool> use_fast_cpu_time{linkage,
|
SwitchableSetting<bool> use_fast_cpu_time{
|
||||||
false,
|
linkage, false, "use_fast_cpu_time", Category::Cpu, Specialization::Paired, true, true};
|
||||||
"use_fast_cpu_time",
|
SwitchableSetting<CpuClock> fast_cpu_time{
|
||||||
Category::Cpu,
|
linkage, CpuClock::Boost, "fast_cpu_time", Category::Cpu, Specialization::Default, true,
|
||||||
Specialization::Paired,
|
true, &use_fast_cpu_time};
|
||||||
true,
|
|
||||||
true};
|
|
||||||
SwitchableSetting<CpuClock> fast_cpu_time{linkage,
|
|
||||||
CpuClock::Boost,
|
|
||||||
"fast_cpu_time",
|
|
||||||
Category::Cpu,
|
|
||||||
Specialization::Default,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
&use_fast_cpu_time};
|
|
||||||
|
|
||||||
SwitchableSetting<bool> use_custom_cpu_ticks{linkage,
|
SwitchableSetting<bool> use_custom_cpu_ticks{
|
||||||
false,
|
linkage, false, "use_custom_cpu_ticks", Category::Cpu, Specialization::Paired, true, true};
|
||||||
"use_custom_cpu_ticks",
|
|
||||||
Category::Cpu,
|
|
||||||
Specialization::Paired,
|
|
||||||
true,
|
|
||||||
true};
|
|
||||||
|
|
||||||
SwitchableSetting<u32, true> cpu_ticks{linkage,
|
SwitchableSetting<u32, true> cpu_ticks{linkage,
|
||||||
16000,
|
16000,
|
||||||
|
@ -302,29 +288,29 @@ struct Values {
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
|
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
|
||||||
Category::CpuUnsafe};
|
Category::CpuUnsafe};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
|
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
|
||||||
linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe};
|
linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
||||||
linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe};
|
linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
|
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
|
||||||
linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe};
|
linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
|
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
|
||||||
linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe};
|
linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
||||||
linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe};
|
linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe};
|
||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||||
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
|
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
|
||||||
"backend", Category::Renderer};
|
"backend", Category::Renderer};
|
||||||
SwitchableSetting<ShaderBackend, true> shader_backend{
|
SwitchableSetting<ShaderBackend, true> shader_backend{
|
||||||
linkage, ShaderBackend::SpirV, ShaderBackend::Glsl, ShaderBackend::SpirV,
|
linkage, ShaderBackend::SpirV, ShaderBackend::Glsl, ShaderBackend::SpirV,
|
||||||
"shader_backend", Category::Renderer, Specialization::RuntimeList};
|
"shader_backend", Category::Renderer, Specialization::RuntimeList};
|
||||||
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
|
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
|
||||||
Specialization::RuntimeList};
|
Specialization::RuntimeList};
|
||||||
SwitchableSetting<bool> enable_raii{linkage, false, "enable_raii", Category::Renderer};
|
SwitchableSetting<bool> enable_raii{linkage, false, "enable_raii", Category::Renderer};
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
SwitchableSetting<bool> frame_interpolation{linkage, true, "frame_interpolation", Category::Renderer,
|
SwitchableSetting<bool> frame_interpolation{linkage, true, "frame_interpolation",
|
||||||
Specialization::RuntimeList};
|
Category::Renderer, Specialization::RuntimeList};
|
||||||
SwitchableSetting<bool> frame_skipping{linkage, false, "frame_skipping", Category::Renderer,
|
SwitchableSetting<bool> frame_skipping{linkage, false, "frame_skipping", Category::Renderer,
|
||||||
Specialization::RuntimeList};
|
Specialization::RuntimeList};
|
||||||
#endif
|
#endif
|
||||||
|
@ -337,7 +323,7 @@ struct Values {
|
||||||
"optimize_spirv_output",
|
"optimize_spirv_output",
|
||||||
Category::Renderer};
|
Category::Renderer};
|
||||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
||||||
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
||||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
AstcDecodeMode::Cpu,
|
AstcDecodeMode::Cpu,
|
||||||
|
@ -349,9 +335,9 @@ struct Values {
|
||||||
"accelerate_astc",
|
"accelerate_astc",
|
||||||
Category::Renderer};
|
Category::Renderer};
|
||||||
SwitchableSetting<VSyncMode, true> vsync_mode{
|
SwitchableSetting<VSyncMode, true> vsync_mode{
|
||||||
linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed,
|
linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed,
|
||||||
"use_vsync", Category::Renderer, Specialization::RuntimeList, true,
|
"use_vsync", Category::Renderer, Specialization::RuntimeList, true,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu,
|
SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu,
|
||||||
"nvdec_emulation", Category::Renderer};
|
"nvdec_emulation", Category::Renderer};
|
||||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||||
|
@ -408,11 +394,11 @@ struct Values {
|
||||||
true};
|
true};
|
||||||
|
|
||||||
SwitchableSetting<u8, false> bg_red{
|
SwitchableSetting<u8, false> bg_red{
|
||||||
linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true};
|
linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true};
|
||||||
SwitchableSetting<u8, false> bg_green{
|
SwitchableSetting<u8, false> bg_green{
|
||||||
linkage, 0, "bg_green", Category::Renderer, Specialization::Default, true, true};
|
linkage, 0, "bg_green", Category::Renderer, Specialization::Default, true, true};
|
||||||
SwitchableSetting<u8, false> bg_blue{
|
SwitchableSetting<u8, false> bg_blue{
|
||||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||||
|
|
||||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
@ -476,13 +462,9 @@ struct Values {
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<bool> use_fast_gpu_time{linkage,
|
SwitchableSetting<bool> use_fast_gpu_time{
|
||||||
true,
|
linkage, true, "use_fast_gpu_time", Category::RendererAdvanced, Specialization::Paired,
|
||||||
"use_fast_gpu_time",
|
true, true};
|
||||||
Category::RendererAdvanced,
|
|
||||||
Specialization::Paired,
|
|
||||||
true,
|
|
||||||
true};
|
|
||||||
|
|
||||||
SwitchableSetting<GpuOverclock> fast_gpu_time{linkage,
|
SwitchableSetting<GpuOverclock> fast_gpu_time{linkage,
|
||||||
GpuOverclock::Low,
|
GpuOverclock::Low,
|
||||||
|
@ -507,17 +489,15 @@ struct Values {
|
||||||
SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
|
SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
|
|
||||||
SwitchableSetting<u8, true> dyna_state{linkage,
|
SwitchableSetting<u8, true> dyna_state{
|
||||||
0,
|
linkage, 0, 0, 3, "dyna_state", Category::RendererExtensions, Specialization::Scalar};
|
||||||
0,
|
|
||||||
3,
|
|
||||||
"dyna_state",
|
|
||||||
Category::RendererExtensions,
|
|
||||||
Specialization::Scalar};
|
|
||||||
|
|
||||||
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
|
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex",
|
||||||
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
|
Category::RendererExtensions};
|
||||||
SwitchableSetting<bool> sample_shading{linkage, false, "sample_shading", Category::RendererExtensions};
|
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing",
|
||||||
|
Category::RendererExtensions};
|
||||||
|
SwitchableSetting<bool> sample_shading{linkage, false, "sample_shading",
|
||||||
|
Category::RendererExtensions};
|
||||||
|
|
||||||
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
||||||
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
|
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
|
||||||
|
@ -525,19 +505,16 @@ struct Values {
|
||||||
Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath",
|
Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
Setting<bool> disable_shader_loop_safety_checks{
|
Setting<bool> disable_shader_loop_safety_checks{
|
||||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||||
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
|
|
||||||
// System
|
// System
|
||||||
SwitchableSetting<Language, true> language_index{linkage,
|
SwitchableSetting<Language, true> language_index{
|
||||||
Language::EnglishAmerican,
|
linkage, Language::EnglishAmerican, Language::Japanese,
|
||||||
Language::Japanese,
|
Language::Serbian, "language_index", Category::System};
|
||||||
Language::Serbian,
|
|
||||||
"language_index",
|
|
||||||
Category::System};
|
|
||||||
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan,
|
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan,
|
||||||
Region::Taiwan, "region_index", Category::System};
|
Region::Taiwan, "region_index", Category::System};
|
||||||
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
||||||
|
@ -545,10 +522,10 @@ struct Values {
|
||||||
"time_zone_index", Category::System};
|
"time_zone_index", Category::System};
|
||||||
// Measured in seconds since epoch
|
// Measured in seconds since epoch
|
||||||
SwitchableSetting<bool> custom_rtc_enabled{
|
SwitchableSetting<bool> custom_rtc_enabled{
|
||||||
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
||||||
SwitchableSetting<s64> custom_rtc{
|
SwitchableSetting<s64> custom_rtc{
|
||||||
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
||||||
false, true, &custom_rtc_enabled};
|
false, true, &custom_rtc_enabled};
|
||||||
SwitchableSetting<s64, true> custom_rtc_offset{linkage,
|
SwitchableSetting<s64, true> custom_rtc_offset{linkage,
|
||||||
0,
|
0,
|
||||||
std::numeric_limits<int>::min(),
|
std::numeric_limits<int>::min(),
|
||||||
|
@ -559,12 +536,12 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<bool> rng_seed_enabled{
|
SwitchableSetting<bool> rng_seed_enabled{
|
||||||
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
|
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
|
||||||
SwitchableSetting<u32> rng_seed{
|
SwitchableSetting<u32> rng_seed{
|
||||||
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
|
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
|
||||||
true, true, &rng_seed_enabled};
|
true, true, &rng_seed_enabled};
|
||||||
Setting<std::string> device_name{
|
Setting<std::string> device_name{
|
||||||
linkage, "eden", "device_name", Category::System, Specialization::Default, true, true};
|
linkage, "eden", "device_name", Category::System, Specialization::Default, true, true};
|
||||||
|
|
||||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||||
|
|
||||||
|
@ -615,21 +592,21 @@ struct Values {
|
||||||
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
||||||
|
|
||||||
Setting<bool> mouse_panning{
|
Setting<bool> mouse_panning{
|
||||||
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
||||||
Setting<u8, true> mouse_panning_sensitivity{
|
Setting<u8, true> mouse_panning_sensitivity{
|
||||||
linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
|
linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
|
||||||
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
||||||
|
|
||||||
Setting<u8, true> mouse_panning_x_sensitivity{
|
Setting<u8, true> mouse_panning_x_sensitivity{
|
||||||
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_y_sensitivity{
|
Setting<u8, true> mouse_panning_y_sensitivity{
|
||||||
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
||||||
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_decay_strength{
|
Setting<u8, true> mouse_panning_decay_strength{
|
||||||
linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls};
|
linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_min_decay{
|
Setting<u8, true> mouse_panning_min_decay{
|
||||||
linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls};
|
linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls};
|
||||||
|
|
||||||
Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
|
Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
|
||||||
Category::Controls};
|
Category::Controls};
|
||||||
|
@ -672,23 +649,22 @@ struct Values {
|
||||||
Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
|
Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
|
||||||
Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
|
Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
|
||||||
Setting<bool> dump_shaders{
|
Setting<bool> dump_shaders{
|
||||||
linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default,
|
linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default,
|
||||||
false};
|
false};
|
||||||
Setting<bool> dump_macros{
|
Setting<bool> dump_macros{
|
||||||
linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false};
|
linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false};
|
||||||
Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
|
Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
|
||||||
Setting<bool> reporting_services{
|
Setting<bool> reporting_services{
|
||||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
||||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
||||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
||||||
Category::DebuggingGraphics};
|
Category::DebuggingGraphics};
|
||||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
||||||
Category::DebuggingGraphics};
|
Category::DebuggingGraphics};
|
||||||
Setting<bool> extended_logging{
|
Setting<bool> extended_logging{
|
||||||
linkage, false, "extended_logging", Category::Debugging, Specialization::Default, false};
|
linkage, false, "extended_logging", Category::Debugging, Specialization::Default, false};
|
||||||
Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging};
|
Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging};
|
||||||
Setting<bool> use_auto_stub{
|
Setting<bool> use_auto_stub{linkage, false, "use_auto_stub", Category::Debugging};
|
||||||
linkage, false, "use_auto_stub", Category::Debugging};
|
|
||||||
Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
|
Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
|
||||||
Category::Debugging};
|
Category::Debugging};
|
||||||
Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
|
Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
|
||||||
|
|
|
@ -150,19 +150,8 @@ ENUM(FullscreenMode, Borderless, Exclusive);
|
||||||
|
|
||||||
ENUM(NvdecEmulation, Off, Cpu, Gpu);
|
ENUM(NvdecEmulation, Off, Cpu, Gpu);
|
||||||
|
|
||||||
ENUM(ResolutionSetup,
|
ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X,
|
||||||
Res1_4X,
|
Res7X, Res8X);
|
||||||
Res1_2X,
|
|
||||||
Res3_4X,
|
|
||||||
Res1X,
|
|
||||||
Res3_2X,
|
|
||||||
Res2X,
|
|
||||||
Res3X,
|
|
||||||
Res4X,
|
|
||||||
Res5X,
|
|
||||||
Res6X,
|
|
||||||
Res7X,
|
|
||||||
Res8X);
|
|
||||||
|
|
||||||
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, Area, MaxEnum);
|
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, Area, MaxEnum);
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <codecvt>
|
|
||||||
#include <locale>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <boost/locale.hpp>
|
||||||
|
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
|
@ -142,18 +141,15 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UTF16ToUTF8(std::u16string_view input) {
|
std::string UTF16ToUTF8(std::u16string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
return boost::locale::conv::utf_to_utf<char>(input.data(), input.data() + input.size());
|
||||||
return convert.to_bytes(input.data(), input.data() + input.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string UTF8ToUTF16(std::string_view input) {
|
std::u16string UTF8ToUTF16(std::string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
return boost::locale::conv::utf_to_utf<char16_t>(input.data(), input.data() + input.size());
|
||||||
return convert.from_bytes(input.data(), input.data() + input.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u32string UTF8ToUTF32(std::string_view input) {
|
std::u32string UTF8ToUTF32(std::string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
|
return boost::locale::conv::utf_to_utf<char32_t>(input.data(), input.data() + input.size());
|
||||||
return convert.from_bytes(input.data(), input.data() + input.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -103,9 +103,9 @@ concept IsRBEntry = CheckRBEntry<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept HasRBEntry = requires(T& t, const T& ct) {
|
concept HasRBEntry = requires(T& t, const T& ct) {
|
||||||
{ t.GetRBEntry() } -> std::same_as<RBEntry<T>&>;
|
{ t.GetRBEntry() } -> std::same_as<RBEntry<T>&>;
|
||||||
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>;
|
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires HasRBEntry<T>
|
requires HasRBEntry<T>
|
||||||
|
|
|
@ -362,7 +362,9 @@ public:
|
||||||
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
||||||
// component names (x<->r) and permutations (xy<->yx)
|
// component names (x<->r) and permutations (xy<->yx)
|
||||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
[[nodiscard]] constexpr Vec2<T> name() const { \
|
||||||
|
return Vec2<T>(a, b); \
|
||||||
|
}
|
||||||
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
||||||
_DEFINE_SWIZZLER2(a, b, a##b); \
|
_DEFINE_SWIZZLER2(a, b, a##b); \
|
||||||
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
||||||
|
@ -555,7 +557,9 @@ public:
|
||||||
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
||||||
// permutations (xy<->yx)
|
// permutations (xy<->yx)
|
||||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
[[nodiscard]] constexpr Vec2<T> name() const { \
|
||||||
|
return Vec2<T>(a, b); \
|
||||||
|
}
|
||||||
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
||||||
_DEFINE_SWIZZLER2(a, a, a##a); \
|
_DEFINE_SWIZZLER2(a, a, a##a); \
|
||||||
_DEFINE_SWIZZLER2(a, a, a2##a2)
|
_DEFINE_SWIZZLER2(a, a, a2##a2)
|
||||||
|
@ -580,7 +584,9 @@ public:
|
||||||
#undef _DEFINE_SWIZZLER2
|
#undef _DEFINE_SWIZZLER2
|
||||||
|
|
||||||
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
||||||
[[nodiscard]] constexpr Vec3<T> name() const { return Vec3<T>(a, b, c); }
|
[[nodiscard]] constexpr Vec3<T> name() const { \
|
||||||
|
return Vec3<T>(a, b, c); \
|
||||||
|
}
|
||||||
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
||||||
_DEFINE_SWIZZLER3(a, a, a, a##a##a); \
|
_DEFINE_SWIZZLER3(a, a, a, a##a##a); \
|
||||||
_DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
|
_DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
|
||||||
|
|
|
@ -33,8 +33,8 @@ public:
|
||||||
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
|
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
|
||||||
|
|
||||||
VirtualBuffer(VirtualBuffer&& other) noexcept
|
VirtualBuffer(VirtualBuffer&& other) noexcept
|
||||||
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
|
: alloc_size{std::exchange(other.alloc_size, 0)},
|
||||||
nullptr} {}
|
base_ptr{std::exchange(other.base_ptr), nullptr} {}
|
||||||
|
|
||||||
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
|
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
|
||||||
alloc_size = std::exchange(other.alloc_size, 0);
|
alloc_size = std::exchange(other.alloc_size, 0);
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace Common::X64 {
|
namespace Common::X64 {
|
||||||
|
|
||||||
NativeClock::NativeClock(u64 rdtsc_frequency_)
|
NativeClock::NativeClock(u64 rdtsc_frequency_)
|
||||||
: rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den,
|
: rdtsc_frequency{rdtsc_frequency_},
|
||||||
rdtsc_frequency)},
|
ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)},
|
||||||
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
|
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
|
||||||
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
|
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
|
||||||
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
|
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
|
||||||
|
|
|
@ -1150,18 +1150,19 @@ add_library(core STATIC
|
||||||
tools/renderdoc.h
|
tools/renderdoc.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_WIFI_SCAN)
|
||||||
# find_package(libiw REQUIRED)
|
# find_package(libiw REQUIRED)
|
||||||
|
target_compile_definitions(core PRIVATE -DENABLE_WIFI_SCAN)
|
||||||
target_link_libraries(core PRIVATE iw)
|
target_link_libraries(core PRIVATE iw)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_compile_definitions(core PRIVATE _WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
target_compile_definitions(core PRIVATE _WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
||||||
|
|
||||||
if(TARGET iw)
|
# if(TARGET iw)
|
||||||
target_link_libraries(core PRIVATE iw)
|
# target_link_libraries(core PRIVATE iw)
|
||||||
message(STATUS "Linking 'core' with iw on Linux.")
|
# message(STATUS "Linking 'core' with iw on Linux.")
|
||||||
endif()
|
# endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
@ -1216,7 +1217,6 @@ endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||||
target_sources(core PRIVATE
|
target_sources(core PRIVATE
|
||||||
arm/dynarmic/arm_dynarmic.cpp
|
|
||||||
arm/dynarmic/arm_dynarmic.h
|
arm/dynarmic/arm_dynarmic.h
|
||||||
arm/dynarmic/arm_dynarmic_64.cpp
|
arm/dynarmic/arm_dynarmic_64.cpp
|
||||||
arm/dynarmic/arm_dynarmic_64.h
|
arm/dynarmic/arm_dynarmic_64.h
|
||||||
|
|
|
@ -14,7 +14,8 @@ void ArmInterface::LogBacktrace(Kernel::KProcess* process) const {
|
||||||
this->GetContext(ctx);
|
this->GetContext(ctx);
|
||||||
|
|
||||||
LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", ctx.sp, ctx.pc);
|
LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", ctx.sp, ctx.pc);
|
||||||
LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address", "Offset", "Symbol");
|
LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
|
||||||
|
"Offset", "Symbol");
|
||||||
LOG_ERROR(Core_ARM, "");
|
LOG_ERROR(Core_ARM, "");
|
||||||
|
|
||||||
const auto backtrace = GetBacktraceFromContext(process, ctx);
|
const auto backtrace = GetBacktraceFromContext(process, ctx);
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
#include "common/signal_chain.h"
|
|
||||||
|
|
||||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
|
||||||
#include "core/hle/kernel/k_process.h"
|
|
||||||
#include "core/memory.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
thread_local Core::Memory::Memory* g_current_memory{};
|
|
||||||
std::once_flag g_registered{};
|
|
||||||
struct sigaction g_old_segv {};
|
|
||||||
|
|
||||||
void HandleSigSegv(int sig, siginfo_t* info, void* ctx) {
|
|
||||||
if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_old_segv.sa_sigaction(sig, info, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) {
|
|
||||||
g_current_memory = std::addressof(process->GetMemory());
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedJitExecution::~ScopedJitExecution() {
|
|
||||||
g_current_memory = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScopedJitExecution::RegisterHandler() {
|
|
||||||
std::call_once(g_registered, [] {
|
|
||||||
struct sigaction sa {};
|
|
||||||
sa.sa_sigaction = &HandleSigSegv;
|
|
||||||
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
|
||||||
Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Core
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -26,24 +26,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
|
||||||
return static_cast<HaltReason>(hr);
|
return static_cast<HaltReason>(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
class ScopedJitExecution {
|
|
||||||
public:
|
|
||||||
explicit ScopedJitExecution(Kernel::KProcess* process);
|
|
||||||
~ScopedJitExecution();
|
|
||||||
static void RegisterHandler();
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class ScopedJitExecution {
|
|
||||||
public:
|
|
||||||
explicit ScopedJitExecution(Kernel::KProcess* process) {}
|
|
||||||
~ScopedJitExecution() {}
|
|
||||||
static void RegisterHandler() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
|
@ -19,8 +19,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
|
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
|
||||||
: m_parent{parent}, m_memory(process->GetMemory()),
|
: m_parent{parent}, m_memory(process->GetMemory()), m_process(process),
|
||||||
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
||||||
m_check_memory_access{m_debugger_enabled ||
|
m_check_memory_access{m_debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
@ -195,11 +195,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
|
||||||
config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
|
config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
|
||||||
config.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
config.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
||||||
|
|
||||||
config.fastmem_pointer = page_table->fastmem_arena ?
|
config.fastmem_pointer =
|
||||||
std::optional<uintptr_t>{reinterpret_cast<uintptr_t>(page_table->fastmem_arena)} :
|
page_table->fastmem_arena
|
||||||
std::nullopt;
|
? std::optional<uintptr_t>{reinterpret_cast<uintptr_t>(page_table->fastmem_arena)}
|
||||||
|
: std::nullopt;
|
||||||
|
|
||||||
config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt;
|
config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt;
|
||||||
config.recompile_on_exclusive_fastmem_failure = true;
|
config.recompile_on_exclusive_fastmem_failure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,15 +337,11 @@ bool ArmDynarmic32::IsInThumbMode() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
|
HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
|
||||||
ScopedJitExecution sj(thread->GetOwnerProcess());
|
|
||||||
|
|
||||||
m_jit->ClearExclusiveState();
|
m_jit->ClearExclusiveState();
|
||||||
return TranslateHaltReason(m_jit->Run());
|
return TranslateHaltReason(m_jit->Run());
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
|
HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
|
||||||
ScopedJitExecution sj(thread->GetOwnerProcess());
|
|
||||||
|
|
||||||
m_jit->ClearExclusiveState();
|
m_jit->ClearExclusiveState();
|
||||||
return TranslateHaltReason(m_jit->Step());
|
return TranslateHaltReason(m_jit->Step());
|
||||||
}
|
}
|
||||||
|
@ -386,7 +383,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc
|
||||||
m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
|
m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
|
||||||
auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
|
auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
|
||||||
m_jit = MakeJit(&page_table_impl);
|
m_jit = MakeJit(&page_table_impl);
|
||||||
ScopedJitExecution::RegisterHandler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArmDynarmic32::~ArmDynarmic32() = default;
|
ArmDynarmic32::~ArmDynarmic32() = default;
|
||||||
|
|
|
@ -19,8 +19,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
|
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
|
||||||
: m_parent{parent}, m_memory(process->GetMemory()),
|
: m_parent{parent}, m_memory(process->GetMemory()), m_process(process),
|
||||||
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
||||||
m_check_memory_access{m_debugger_enabled ||
|
m_check_memory_access{m_debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
@ -242,9 +242,10 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
|
||||||
config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
|
config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
|
||||||
config.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
config.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
||||||
|
|
||||||
config.fastmem_pointer = page_table->fastmem_arena ?
|
config.fastmem_pointer =
|
||||||
std::optional<uintptr_t>{reinterpret_cast<uintptr_t>(page_table->fastmem_arena)} :
|
page_table->fastmem_arena
|
||||||
std::nullopt;
|
? std::optional<uintptr_t>{reinterpret_cast<uintptr_t>(page_table->fastmem_arena)}
|
||||||
|
: std::nullopt;
|
||||||
config.fastmem_address_space_bits = std::uint32_t(address_space_bits);
|
config.fastmem_address_space_bits = std::uint32_t(address_space_bits);
|
||||||
config.silently_mirror_fastmem = false;
|
config.silently_mirror_fastmem = false;
|
||||||
|
|
||||||
|
@ -367,15 +368,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
|
HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
|
||||||
ScopedJitExecution sj(thread->GetOwnerProcess());
|
|
||||||
|
|
||||||
m_jit->ClearExclusiveState();
|
m_jit->ClearExclusiveState();
|
||||||
return TranslateHaltReason(m_jit->Run());
|
return TranslateHaltReason(m_jit->Run());
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
|
HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
|
||||||
ScopedJitExecution sj(thread->GetOwnerProcess());
|
|
||||||
|
|
||||||
m_jit->ClearExclusiveState();
|
m_jit->ClearExclusiveState();
|
||||||
return TranslateHaltReason(m_jit->Step());
|
return TranslateHaltReason(m_jit->Step());
|
||||||
}
|
}
|
||||||
|
@ -415,7 +412,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc
|
||||||
auto& page_table = process->GetPageTable().GetBasePageTable();
|
auto& page_table = process->GetPageTable().GetBasePageTable();
|
||||||
auto& page_table_impl = page_table.GetImpl();
|
auto& page_table_impl = page_table.GetImpl();
|
||||||
m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
|
m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
|
||||||
ScopedJitExecution::RegisterHandler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArmDynarmic64::~ArmDynarmic64() = default;
|
ArmDynarmic64::~ArmDynarmic64() = default;
|
||||||
|
|
|
@ -302,7 +302,7 @@ void ArmNce::Initialize() {
|
||||||
sigaddset(&signal_mask, GuestAlignmentFaultSignal);
|
sigaddset(&signal_mask, GuestAlignmentFaultSignal);
|
||||||
sigaddset(&signal_mask, GuestAccessFaultSignal);
|
sigaddset(&signal_mask, GuestAccessFaultSignal);
|
||||||
|
|
||||||
struct sigaction return_to_run_code_action {};
|
struct sigaction return_to_run_code_action{};
|
||||||
return_to_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
return_to_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||||
return_to_run_code_action.sa_sigaction = reinterpret_cast<HandlerType>(
|
return_to_run_code_action.sa_sigaction = reinterpret_cast<HandlerType>(
|
||||||
&ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler);
|
&ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler);
|
||||||
|
@ -310,21 +310,21 @@ void ArmNce::Initialize() {
|
||||||
Common::SigAction(ReturnToRunCodeByExceptionLevelChangeSignal, &return_to_run_code_action,
|
Common::SigAction(ReturnToRunCodeByExceptionLevelChangeSignal, &return_to_run_code_action,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
struct sigaction break_from_run_code_action {};
|
struct sigaction break_from_run_code_action{};
|
||||||
break_from_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
break_from_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||||
break_from_run_code_action.sa_sigaction =
|
break_from_run_code_action.sa_sigaction =
|
||||||
reinterpret_cast<HandlerType>(&ArmNce::BreakFromRunCodeSignalHandler);
|
reinterpret_cast<HandlerType>(&ArmNce::BreakFromRunCodeSignalHandler);
|
||||||
break_from_run_code_action.sa_mask = signal_mask;
|
break_from_run_code_action.sa_mask = signal_mask;
|
||||||
Common::SigAction(BreakFromRunCodeSignal, &break_from_run_code_action, nullptr);
|
Common::SigAction(BreakFromRunCodeSignal, &break_from_run_code_action, nullptr);
|
||||||
|
|
||||||
struct sigaction alignment_fault_action {};
|
struct sigaction alignment_fault_action{};
|
||||||
alignment_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
alignment_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||||
alignment_fault_action.sa_sigaction =
|
alignment_fault_action.sa_sigaction =
|
||||||
reinterpret_cast<HandlerType>(&ArmNce::GuestAlignmentFaultSignalHandler);
|
reinterpret_cast<HandlerType>(&ArmNce::GuestAlignmentFaultSignalHandler);
|
||||||
alignment_fault_action.sa_mask = signal_mask;
|
alignment_fault_action.sa_mask = signal_mask;
|
||||||
Common::SigAction(GuestAlignmentFaultSignal, &alignment_fault_action, nullptr);
|
Common::SigAction(GuestAlignmentFaultSignal, &alignment_fault_action, nullptr);
|
||||||
|
|
||||||
struct sigaction access_fault_action {};
|
struct sigaction access_fault_action{};
|
||||||
access_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
|
access_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
|
||||||
access_fault_action.sa_sigaction =
|
access_fault_action.sa_sigaction =
|
||||||
reinterpret_cast<HandlerType>(&ArmNce::GuestAccessFaultSignalHandler);
|
reinterpret_cast<HandlerType>(&ArmNce::GuestAccessFaultSignalHandler);
|
||||||
|
@ -405,19 +405,19 @@ void ArmNce::ClearInstructionCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) {
|
void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) {
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
// Align the start address to cache line boundary for better performance
|
// Align the start address to cache line boundary for better performance
|
||||||
const size_t CACHE_LINE_SIZE = 64;
|
const size_t CACHE_LINE_SIZE = 64;
|
||||||
addr &= ~(CACHE_LINE_SIZE - 1);
|
addr &= ~(CACHE_LINE_SIZE - 1);
|
||||||
|
|
||||||
// Round up size to nearest cache line
|
// Round up size to nearest cache line
|
||||||
size = (size + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
|
size = (size + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
|
||||||
|
|
||||||
// Prefetch the range to be invalidated
|
// Prefetch the range to be invalidated
|
||||||
for (size_t offset = 0; offset < size; offset += CACHE_LINE_SIZE) {
|
for (size_t offset = 0; offset < size; offset += CACHE_LINE_SIZE) {
|
||||||
__builtin_prefetch((void*)(addr + offset), 1, 3);
|
__builtin_prefetch((void*)(addr + offset), 1, 3);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->ClearInstructionCache();
|
this->ClearInstructionCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Core {
|
||||||
namespace {
|
namespace {
|
||||||
// Prefetch tuning parameters
|
// Prefetch tuning parameters
|
||||||
constexpr size_t CACHE_LINE_SIZE = 64;
|
constexpr size_t CACHE_LINE_SIZE = 64;
|
||||||
constexpr size_t PREFETCH_STRIDE = 128; // 2 cache lines ahead
|
constexpr size_t PREFETCH_STRIDE = 128; // 2 cache lines ahead
|
||||||
constexpr size_t SIMD_PREFETCH_THRESHOLD = 32; // Bytes
|
constexpr size_t SIMD_PREFETCH_THRESHOLD = 32; // Bytes
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -13,28 +13,34 @@
|
||||||
template <typename KeyType, typename ValueType>
|
template <typename KeyType, typename ValueType>
|
||||||
class LRUCache {
|
class LRUCache {
|
||||||
public:
|
public:
|
||||||
using key_type = KeyType;
|
using key_type = KeyType;
|
||||||
using value_type = ValueType;
|
using value_type = ValueType;
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
|
|
||||||
struct Statistics {
|
struct Statistics {
|
||||||
size_type hits = 0;
|
size_type hits = 0;
|
||||||
size_type misses = 0;
|
size_type misses = 0;
|
||||||
void reset() noexcept { hits = misses = 0; }
|
void reset() noexcept {
|
||||||
|
hits = misses = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit LRUCache(size_type capacity, bool enabled = true)
|
explicit LRUCache(size_type capacity, bool enabled = true)
|
||||||
: enabled_{enabled}, capacity_{capacity} {
|
: enabled_{enabled}, capacity_{capacity} {
|
||||||
cache_map_.reserve(capacity_);
|
cache_map_.reserve(capacity_);
|
||||||
LOG_WARNING(Core, "LRU Cache initialised (state: {} | capacity: {})", enabled_ ? "enabled" : "disabled", capacity_);
|
LOG_WARNING(Core, "LRU Cache initialised (state: {} | capacity: {})",
|
||||||
|
enabled_ ? "enabled" : "disabled", capacity_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-movable copy semantics
|
// Non-movable copy semantics
|
||||||
LRUCache(const LRUCache&) = delete;
|
LRUCache(const LRUCache&) = delete;
|
||||||
LRUCache& operator=(const LRUCache&) = delete;
|
LRUCache& operator=(const LRUCache&) = delete;
|
||||||
LRUCache(LRUCache&& other) noexcept { *this = std::move(other); }
|
LRUCache(LRUCache&& other) noexcept {
|
||||||
|
*this = std::move(other);
|
||||||
|
}
|
||||||
LRUCache& operator=(LRUCache&& other) noexcept {
|
LRUCache& operator=(LRUCache&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
std::unique_lock this_lock(mutex_, std::defer_lock);
|
std::unique_lock this_lock(mutex_, std::defer_lock);
|
||||||
std::unique_lock other_lock(other.mutex_, std::defer_lock);
|
std::unique_lock other_lock(other.mutex_, std::defer_lock);
|
||||||
std::lock(this_lock, other_lock);
|
std::lock(this_lock, other_lock);
|
||||||
|
@ -48,7 +54,8 @@ public:
|
||||||
~LRUCache() = default;
|
~LRUCache() = default;
|
||||||
|
|
||||||
[[nodiscard]] value_type* get(const key_type& key) {
|
[[nodiscard]] value_type* get(const key_type& key) {
|
||||||
if (!enabled_) [[unlikely]] return nullptr;
|
if (!enabled_) [[unlikely]]
|
||||||
|
return nullptr;
|
||||||
std::unique_lock lock(mutex_);
|
std::unique_lock lock(mutex_);
|
||||||
auto it = cache_map_.find(key);
|
auto it = cache_map_.find(key);
|
||||||
if (it == cache_map_.end()) {
|
if (it == cache_map_.end()) {
|
||||||
|
@ -61,7 +68,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] value_type* peek(const key_type& key) const {
|
[[nodiscard]] value_type* peek(const key_type& key) const {
|
||||||
if (!enabled_) [[unlikely]] return nullptr;
|
if (!enabled_) [[unlikely]]
|
||||||
|
return nullptr;
|
||||||
std::shared_lock lock(mutex_);
|
std::shared_lock lock(mutex_);
|
||||||
auto it = cache_map_.find(key);
|
auto it = cache_map_.find(key);
|
||||||
return it == cache_map_.end() ? nullptr : &it->second.second;
|
return it == cache_map_.end() ? nullptr : &it->second.second;
|
||||||
|
@ -69,7 +77,8 @@ public:
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
void put(const key_type& key, V&& value) {
|
void put(const key_type& key, V&& value) {
|
||||||
if (!enabled_) [[unlikely]] return;
|
if (!enabled_) [[unlikely]]
|
||||||
|
return;
|
||||||
std::unique_lock lock(mutex_);
|
std::unique_lock lock(mutex_);
|
||||||
insert_or_update(key, std::forward<V>(value));
|
insert_or_update(key, std::forward<V>(value));
|
||||||
}
|
}
|
||||||
|
@ -88,16 +97,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool contains(const key_type& key) const {
|
[[nodiscard]] bool contains(const key_type& key) const {
|
||||||
if (!enabled_) return false;
|
if (!enabled_)
|
||||||
|
return false;
|
||||||
std::shared_lock lock(mutex_);
|
std::shared_lock lock(mutex_);
|
||||||
return cache_map_.find(key) != cache_map_.end();
|
return cache_map_.find(key) != cache_map_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool erase(const key_type& key) {
|
bool erase(const key_type& key) {
|
||||||
if (!enabled_) return false;
|
if (!enabled_)
|
||||||
|
return false;
|
||||||
std::unique_lock lock(mutex_);
|
std::unique_lock lock(mutex_);
|
||||||
auto it = cache_map_.find(key);
|
auto it = cache_map_.find(key);
|
||||||
if (it == cache_map_.end()) return false;
|
if (it == cache_map_.end())
|
||||||
|
return false;
|
||||||
cache_list_.erase(it->second.first);
|
cache_list_.erase(it->second.first);
|
||||||
cache_map_.erase(it);
|
cache_map_.erase(it);
|
||||||
return true;
|
return true;
|
||||||
|
@ -111,15 +123,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_type size() const {
|
[[nodiscard]] size_type size() const {
|
||||||
if (!enabled_) return 0;
|
if (!enabled_)
|
||||||
|
return 0;
|
||||||
std::shared_lock lock(mutex_);
|
std::shared_lock lock(mutex_);
|
||||||
return cache_map_.size();
|
return cache_map_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_type get_capacity() const { return capacity_; }
|
[[nodiscard]] size_type get_capacity() const {
|
||||||
|
return capacity_;
|
||||||
|
}
|
||||||
|
|
||||||
void resize(size_type new_capacity) {
|
void resize(size_type new_capacity) {
|
||||||
if (!enabled_) return;
|
if (!enabled_)
|
||||||
|
return;
|
||||||
std::unique_lock lock(mutex_);
|
std::unique_lock lock(mutex_);
|
||||||
capacity_ = new_capacity;
|
capacity_ = new_capacity;
|
||||||
shrink_if_needed();
|
shrink_if_needed();
|
||||||
|
@ -130,10 +146,13 @@ public:
|
||||||
std::unique_lock lock(mutex_);
|
std::unique_lock lock(mutex_);
|
||||||
enabled_ = state;
|
enabled_ = state;
|
||||||
LOG_WARNING(Core, "LRU Cache state changed to: {}", state ? "enabled" : "disabled");
|
LOG_WARNING(Core, "LRU Cache state changed to: {}", state ? "enabled" : "disabled");
|
||||||
if (!enabled_) clear();
|
if (!enabled_)
|
||||||
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool isEnabled() const { return enabled_; }
|
[[nodiscard]] bool isEnabled() const {
|
||||||
|
return enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] Statistics stats() const {
|
[[nodiscard]] Statistics stats() const {
|
||||||
std::shared_lock lock(mutex_);
|
std::shared_lock lock(mutex_);
|
||||||
|
@ -141,10 +160,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using list_type = std::list<key_type>;
|
using list_type = std::list<key_type>;
|
||||||
using list_iterator = typename list_type::iterator;
|
using list_iterator = typename list_type::iterator;
|
||||||
using map_value_type = std::pair<list_iterator, value_type>;
|
using map_value_type = std::pair<list_iterator, value_type>;
|
||||||
using map_type = std::unordered_map<key_type, map_value_type>;
|
using map_type = std::unordered_map<key_type, map_value_type>;
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
void insert_or_update(const key_type& key, V&& value) {
|
void insert_or_update(const key_type& key, V&& value) {
|
||||||
|
|
|
@ -16,21 +16,16 @@ namespace Core::NCE {
|
||||||
|
|
||||||
Patcher::Patcher(Patcher&& other) noexcept
|
Patcher::Patcher(Patcher&& other) noexcept
|
||||||
: patch_cache(std::move(other.patch_cache)),
|
: patch_cache(std::move(other.patch_cache)),
|
||||||
m_patch_instructions(std::move(other.m_patch_instructions)),
|
m_patch_instructions(std::move(other.m_patch_instructions)), c(m_patch_instructions),
|
||||||
c(m_patch_instructions),
|
m_save_context(other.m_save_context), m_load_context(other.m_load_context), mode(other.mode),
|
||||||
m_save_context(other.m_save_context),
|
|
||||||
m_load_context(other.m_load_context),
|
|
||||||
mode(other.mode),
|
|
||||||
total_program_size(other.total_program_size),
|
total_program_size(other.total_program_size),
|
||||||
m_relocate_module_index(other.m_relocate_module_index),
|
m_relocate_module_index(other.m_relocate_module_index), modules(std::move(other.modules)),
|
||||||
modules(std::move(other.modules)),
|
|
||||||
curr_patch(nullptr) {
|
curr_patch(nullptr) {
|
||||||
if (!modules.empty()) {
|
if (!modules.empty()) {
|
||||||
curr_patch = &modules.back();
|
curr_patch = &modules.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
using namespace oaknut::util;
|
using namespace oaknut::util;
|
||||||
|
|
||||||
|
@ -41,7 +36,7 @@ constexpr u32 ModuleCodeIndex = 0x24 / sizeof(u32);
|
||||||
|
|
||||||
Patcher::Patcher() : c(m_patch_instructions) {
|
Patcher::Patcher() : c(m_patch_instructions) {
|
||||||
LOG_WARNING(Core_ARM, "Patcher initialized with LRU cache {}",
|
LOG_WARNING(Core_ARM, "Patcher initialized with LRU cache {}",
|
||||||
patch_cache.isEnabled() ? "enabled" : "disabled");
|
patch_cache.isEnabled() ? "enabled" : "disabled");
|
||||||
// The first word of the patch section is always a branch to the first instruction of the
|
// The first word of the patch section is always a branch to the first instruction of the
|
||||||
// module.
|
// module.
|
||||||
c.dw(0);
|
c.dw(0);
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
#include <oaknut/code_block.hpp>
|
#include <oaknut/code_block.hpp>
|
||||||
#include <oaknut/oaknut.hpp>
|
#include <oaknut/oaknut.hpp>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
#include "core/hle/kernel/k_typed_address.h"
|
#include "core/hle/kernel/k_typed_address.h"
|
||||||
#include "core/hle/kernel/physical_memory.h"
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
#include "lru_cache.h"
|
#include "lru_cache.h"
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace Core::NCE {
|
namespace Core::NCE {
|
||||||
|
|
||||||
|
@ -67,8 +67,9 @@ private:
|
||||||
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg);
|
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries
|
static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries
|
||||||
LRUCache<uintptr_t, PatchTextAddress> patch_cache{CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()};
|
LRUCache<uintptr_t, PatchTextAddress> patch_cache{
|
||||||
|
CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()};
|
||||||
|
|
||||||
void BranchToPatch(uintptr_t module_dest) {
|
void BranchToPatch(uintptr_t module_dest) {
|
||||||
if (patch_cache.isEnabled()) {
|
if (patch_cache.isEnabled()) {
|
||||||
|
@ -79,14 +80,16 @@ private:
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch});
|
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(Core_ARM, "LRU cache miss for address {:#x}, creating new patch", module_dest);
|
LOG_DEBUG(Core_ARM, "LRU cache miss for address {:#x}, creating new patch",
|
||||||
|
module_dest);
|
||||||
|
|
||||||
// If not in cache, create new entry and cache it
|
// If not in cache, create new entry and cache it
|
||||||
const auto patch_addr = c.offset();
|
const auto patch_addr = c.offset();
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest});
|
curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest});
|
||||||
patch_cache.put(module_dest, patch_addr);
|
patch_cache.put(module_dest, patch_addr);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(Core_ARM, "LRU cache disabled - creating direct patch for address {:#x}", module_dest);
|
LOG_DEBUG(Core_ARM, "LRU cache disabled - creating direct patch for address {:#x}",
|
||||||
|
module_dest);
|
||||||
// LRU disabled - use pre-LRU approach
|
// LRU disabled - use pre-LRU approach
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "common/x64/cpu_wait.h"
|
#include "common/x64/cpu_wait.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hardware_properties.h"
|
#include "core/hardware_properties.h"
|
||||||
|
|
||||||
|
@ -175,9 +175,9 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreTiming::AddTicks(u64 ticks_to_add) {
|
void CoreTiming::AddTicks(u64 ticks_to_add) {
|
||||||
cpu_ticks = Settings::values.use_custom_cpu_ticks.GetValue()
|
cpu_ticks = Settings::values.use_custom_cpu_ticks.GetValue()
|
||||||
? Settings::values.cpu_ticks.GetValue()
|
? Settings::values.cpu_ticks.GetValue()
|
||||||
: cpu_ticks + ticks_to_add;
|
: cpu_ticks + ticks_to_add;
|
||||||
downcount -= static_cast<s64>(cpu_ticks);
|
downcount -= static_cast<s64>(cpu_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,22 +193,22 @@ u64 CoreTiming::GetClockTicks() const {
|
||||||
u64 fres;
|
u64 fres;
|
||||||
if (is_multicore) [[likely]] {
|
if (is_multicore) [[likely]] {
|
||||||
fres = clock->GetCNTPCT();
|
fres = clock->GetCNTPCT();
|
||||||
} else {
|
} else {
|
||||||
fres = Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
|
fres = Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::values.use_fast_cpu_time) {
|
if (Settings::values.use_fast_cpu_time) {
|
||||||
fres = (u64) ((double) fres
|
fres = (u64)((double)fres * (1.7 + 0.3 * (u32)Settings::values.fast_cpu_time.GetValue()));
|
||||||
* (1.7 + 0.3 * (u32) Settings::values.fast_cpu_time.GetValue()));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings::values.sync_core_speed.GetValue()) {
|
if (Settings::values.sync_core_speed.GetValue()) {
|
||||||
const double ticks = static_cast<double>(fres);
|
const double ticks = static_cast<double>(fres);
|
||||||
const double speed_limit = static_cast<double>(Settings::values.speed_limit.GetValue())*0.01;
|
const double speed_limit =
|
||||||
return static_cast<u64>(ticks/speed_limit);
|
static_cast<double>(Settings::values.speed_limit.GetValue()) * 0.01;
|
||||||
} else {
|
return static_cast<u64>(ticks / speed_limit);
|
||||||
return fres;
|
} else {
|
||||||
}
|
return fres;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CoreTiming::GetGPUTicks() const {
|
u64 CoreTiming::GetGPUTicks() const {
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/version.hpp>
|
|
||||||
#if BOOST_VERSION > 108300 && !defined(_WINDOWS) && !defined(ANDROID)
|
|
||||||
#include <boost/process/v1/async_pipe.hpp>
|
|
||||||
#else
|
|
||||||
#include <boost/process/async_pipe.hpp>
|
#include <boost/process/async_pipe.hpp>
|
||||||
#endif
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/polyfill_thread.h"
|
#include "common/polyfill_thread.h"
|
||||||
|
@ -329,11 +325,7 @@ private:
|
||||||
|
|
||||||
struct ConnectionState {
|
struct ConnectionState {
|
||||||
boost::asio::ip::tcp::socket client_socket;
|
boost::asio::ip::tcp::socket client_socket;
|
||||||
#if BOOST_VERSION > 108300 && !defined(_WINDOWS) && !defined(ANDROID)
|
|
||||||
boost::process::v1::async_pipe signal_pipe;
|
|
||||||
#else
|
|
||||||
boost::process::async_pipe signal_pipe;
|
boost::process::async_pipe signal_pipe;
|
||||||
#endif
|
|
||||||
|
|
||||||
SignalInfo info;
|
SignalInfo info;
|
||||||
Kernel::KScopedAutoObject<Kernel::KThread> active_thread;
|
Kernel::KScopedAutoObject<Kernel::KThread> active_thread;
|
||||||
|
|
|
@ -29,8 +29,8 @@ constexpr std::array partition_names{
|
||||||
|
|
||||||
XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
||||||
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
|
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
|
||||||
partitions(partition_names.size()),
|
partitions(partition_names.size()), partitions_raw(partition_names.size()),
|
||||||
partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
|
keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
const auto header_status = TryReadHeader();
|
const auto header_status = TryReadHeader();
|
||||||
if (header_status != Loader::ResultStatus::Success) {
|
if (header_status != Loader::ResultStatus::Success) {
|
||||||
status = header_status;
|
status = header_status;
|
||||||
|
|
|
@ -87,12 +87,15 @@ private:
|
||||||
u32 m_value;
|
u32 m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr PathFlags() : m_value(0) { /* ... */
|
constexpr PathFlags() : m_value(0) { /* ... */ }
|
||||||
}
|
|
||||||
|
|
||||||
#define DECLARE_PATH_FLAG_HANDLER(__WHICH__) \
|
#define DECLARE_PATH_FLAG_HANDLER(__WHICH__) \
|
||||||
constexpr bool Is##__WHICH__##Allowed() const { return (m_value & __WHICH__##Flag) != 0; } \
|
constexpr bool Is##__WHICH__##Allowed() const { \
|
||||||
constexpr void Allow##__WHICH__() { m_value |= __WHICH__##Flag; }
|
return (m_value & __WHICH__##Flag) != 0; \
|
||||||
|
} \
|
||||||
|
constexpr void Allow##__WHICH__() { \
|
||||||
|
m_value |= __WHICH__##Flag; \
|
||||||
|
}
|
||||||
|
|
||||||
DECLARE_PATH_FLAG_HANDLER(WindowsPath)
|
DECLARE_PATH_FLAG_HANDLER(WindowsPath)
|
||||||
DECLARE_PATH_FLAG_HANDLER(RelativePath)
|
DECLARE_PATH_FLAG_HANDLER(RelativePath)
|
||||||
|
|
|
@ -4,23 +4,18 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
|
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
constexpr inline u32 ILog2(u32 val)
|
constexpr inline u32 ILog2(u32 val) {
|
||||||
{
|
|
||||||
ASSERT(val > 0);
|
ASSERT(val > 0);
|
||||||
return static_cast<u32>((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val));
|
return static_cast<u32>((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrityVerificationStorage::Initialize(VirtualFile hs,
|
void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size,
|
||||||
VirtualFile ds,
|
s64 upper_layer_verif_block_size, bool is_real_data) {
|
||||||
s64 verif_block_size,
|
|
||||||
s64 upper_layer_verif_block_size,
|
|
||||||
bool is_real_data)
|
|
||||||
{
|
|
||||||
// Validate preconditions.
|
// Validate preconditions.
|
||||||
ASSERT(verif_block_size >= HashSize);
|
ASSERT(verif_block_size >= HashSize);
|
||||||
|
|
||||||
|
@ -54,14 +49,12 @@ void IntegrityVerificationStorage::Initialize(VirtualFile hs,
|
||||||
m_is_real_data = is_real_data;
|
m_is_real_data = is_real_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrityVerificationStorage::Finalize()
|
void IntegrityVerificationStorage::Finalize() {
|
||||||
{
|
|
||||||
m_hash_storage = VirtualFile();
|
m_hash_storage = VirtualFile();
|
||||||
m_data_storage = VirtualFile();
|
m_data_storage = VirtualFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const
|
size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const {
|
||||||
{
|
|
||||||
// Succeed if zero size.
|
// Succeed if zero size.
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return size;
|
return size;
|
||||||
|
@ -104,8 +97,7 @@ size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset
|
||||||
return m_data_storage->Read(buffer, read_size, offset);
|
return m_data_storage->Read(buffer, read_size, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IntegrityVerificationStorage::GetSize() const
|
size_t IntegrityVerificationStorage::GetSize() const {
|
||||||
{
|
|
||||||
return m_data_storage->GetSize();
|
return m_data_storage->GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue