Compare commits

..

1 Commits

Author SHA1 Message Date
Elad e9ad8a9219 Update SPULLVMRecompiler.cpp 2026-03-30 13:32:45 +03:00
397 changed files with 5924 additions and 17223 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ cmake .. \
-DUSE_SYSTEM_CURL=ON \
-DUSE_SDL=ON \
-DUSE_SYSTEM_SDL=ON \
-DUSE_SYSTEM_FFMPEG=ON \
-DUSE_SYSTEM_FFMPEG=OFF \
-DUSE_SYSTEM_OPENCV=ON \
-DUSE_DISCORD_RPC=ON \
-DOpenGL_GL_PREFERENCE=LEGACY \
+1 -1
View File
@@ -46,7 +46,7 @@ cmake .. \
-DUSE_SYSTEM_CURL=ON \
-DUSE_SDL=ON \
-DUSE_SYSTEM_SDL=ON \
-DUSE_SYSTEM_FFMPEG=ON \
-DUSE_SYSTEM_FFMPEG=OFF \
-DUSE_SYSTEM_OPENCV=ON \
-DUSE_DISCORD_RPC=ON \
-DOpenGL_GL_PREFERENCE=LEGACY \
-3
View File
@@ -19,9 +19,6 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
APPIMAGE_EXTRACT_AND_RUN=1 linuxdeploy --appdir AppDir --plugin qt --plugin checkrt
# Restore App Icon
ln -sr ./AppDir/rpcs3.svg ./AppDir/.DirIcon
# Remove libwayland-client because it has platform-dependent exports and breaks other OSes
rm -f ./AppDir/usr/lib/libwayland-client.so*
+21 -39
View File
@@ -4,16 +4,11 @@
cd build || exit 1
cd bin
git clone --revision=a075e5e417f87675ea3137b7365f3e5a99608d72 https://github.com/KhronosGroup/MoltenVK.git
cd MoltenVK
./fetchDependencies --macos
sudo xcode-select -switch /Applications/Xcode_16.2.app/Contents/Developer
make macos MVK_USE_METAL_PRIVATE_API=1
cd ../
mkdir -p "rpcs3.app/Contents/Resources/vulkan/icd.d" || true
cp "MoltenVK/Package/Release/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib" "rpcs3.app/Contents/Frameworks/libMoltenVK.dylib"
cp "MoltenVK/Package/Release/MoltenVK/dynamic/dylib/macOS/MoltenVK_icd.json" "rpcs3.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json"
wget https://github.com/KhronosGroup/MoltenVK/releases/download/v1.4.1/MoltenVK-macos-privateapi.tar
tar -xvf MoltenVK-macos-privateapi.tar
cp "MoltenVK/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib" "rpcs3.app/Contents/Frameworks/libMoltenVK.dylib"
cp "MoltenVK/MoltenVK/dynamic/dylib/macOS/MoltenVK_icd.json" "rpcs3.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json"
sed -i '' "s/.\//..\/..\/..\/Frameworks\//g" "rpcs3.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json"
cp "$(realpath $BREW_PATH/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib"
@@ -32,18 +27,21 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
# Download translations
mkdir -p "rpcs3.app/Contents/translations"
ZIP_URL="https://github.com/RPCS3/rpcs3_translations/releases/latest/download/RPCS3-languages.zip"
echo "Downloading translations from: $ZIP_URL"
if curl -fsSL "$ZIP_URL" -o "translations.zip"; then
echo "Successfully downloaded translations."
if unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1; then
rm -f translations.zip
else
echo "Failed to extract translations.zip. Continuing without translations."
rm -f translations.zip
fi
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
| grep "browser_download_url" \
| grep "RPCS3-languages.zip" \
| cut -d '"' -f 4)
if [ -z "$ZIP_URL" ]; then
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
else
echo "Warning: Failed to download translations. Skipping..."
echo "Downloading translations from: $ZIP_URL"
curl -L -o translations.zip "$ZIP_URL" || {
echo "Failed to download translations.zip. Continuing without translations."
exit 0
}
unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1 || \
echo "Failed to extract translations.zip. Continuing without translations."
rm -f translations.zip
fi
# Copy Qt translations manually
@@ -57,25 +55,9 @@ rm -f rpcs3.app/Contents/translations/qt_help_*.qm || true
mv rpcs3.app RPCS3_.app
mv RPCS3_.app RPCS3.app
# Hack to fix rpath issues
BIN="RPCS3.app/Contents/MacOS/rpcs3"
install_name_tool -delete_rpath /opt/homebrew/lib $BIN || true
install_name_tool -delete_rpath /usr/local/lib $BIN || true
# Fix dylib IDs
for lib in RPCS3.app/Contents/Frameworks/*.dylib; do
name=$(basename "$lib")
install_name_tool -id "@rpath/$name" "$lib"
done
# Rewrite any hardcoded Homebrew paths to use @rpath
find "RPCS3.app/Contents/" -type f \( -perm +111 -o -name "*.dylib" \) | while read -r bin; do
otool -L "$bin" | grep -E "/opt/homebrew|/usr/local" | awk '{print $1}' | while read -r dep; do
base=$(basename "$dep")
echo "Fixing $dep -> @rpath/$base in $bin"
install_name_tool -change "$dep" "@rpath/$base" "$bin"
done
done
# Hack
install_name_tool -delete_rpath /opt/homebrew/lib RPCS3.app/Contents/MacOS/rpcs3 || true
install_name_tool -delete_rpath /usr/local/lib RPCS3.app/Contents/MacOS/rpcs3 || true
# NOTE: "--deep" is deprecated
codesign --deep -fs - RPCS3.app
-1
View File
@@ -24,7 +24,6 @@ mkdir ./bin/config
mkdir ./bin/config/input_configs
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -f ISO-8859-1 -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
curl -fsSL 'https://api.rpcs3.net/config/?api=v1' | iconv -f ISO-8859-1 -t UTF-8 1> ./bin/GuiConfigs/config_database.dat
# Download translations
mkdir -p ./bin/share/qt6/translations
-1
View File
@@ -14,7 +14,6 @@ mkdir ./bin/config
mkdir ./bin/config/input_configs
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
curl -fsSL 'https://api.rpcs3.net/config/?api=v1' | iconv -t UTF-8 1> ./bin/GuiConfigs/config_database.dat
# Download translations
mkdir -p ./bin/qt6/translations
+2 -2
View File
@@ -16,7 +16,7 @@ QT_MM_URL="${QT_HOST}${QT_PREFIX}addons.qtmultimedia.${QT_PREFIX_2}qtmultimedia$
QT_SVG_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtsvg${QT_SUFFIX}"
QT_TRANSLATIONS_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttranslations${QT_SUFFIX}"
LLVMLIBS_URL="https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-${LLVM_VER}/llvmlibs_mt.7z"
VULKAN_SDK_URL="https://www.dropbox.com/scl/fi/olpvqk4346ig7i8btadk5/vulkansdk-windows-X64-${VULKAN_VER}.exe?rlkey=huvssch6sy904qkg8ti9p65br&st=pztptdin&dl=1"
VULKAN_SDK_URL="https://www.dropbox.com/scl/fi/sjjh0fc4ld281pjbl2xzu/VulkanSDK-${VULKAN_VER}-Installer.exe?rlkey=f6wzc0lvms5vwkt2z3qabfv9d&dl=1"
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.12.3/ccache-4.12.3-windows-x86_64.zip"
DEP_URLS=" \
@@ -88,7 +88,7 @@ for url in $DEP_URLS; do
*qt*) checksum=$(curl -fL "${url}.sha1"); algo="sha1"; outDir="$QTDIR/" ;;
*llvm*) checksum=$(curl -fL "${url}.sha256"); algo="sha256"; outDir="./build/lib_ext/Release-x64" ;;
*ccache*) checksum=$CCACHE_SHA; algo="sha256"; outDir="$CCACHE_BIN_DIR" ;;
*vulkansdk*)
*Vulkan*)
# Vulkan setup needs to be run in batch environment
# Need to subshell this or else it doesn't wait
download_and_verify "$url" "$VULKAN_SDK_SHA" "sha256" "$fileName"
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
Windows_Build:
if: github.event_name == 'workflow_dispatch'
name: LLVM Windows (MSVC)
runs-on: windows-2025-vs2026
runs-on: windows-2025
env:
COMPILER: msvc
CCACHE_SHA: '859141059ac950e1e8cd042c66f842f26b9e3a62a1669a69fe6ba180cb58bbdf'
+11 -11
View File
@@ -30,23 +30,23 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.14"
docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: clang
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.14"
docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: gcc
- os: ubuntu-24.04-arm
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.14"
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: clang
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64"
- os: ubuntu-24.04-arm
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.14"
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: gcc
name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }}
@@ -134,7 +134,7 @@ jobs:
runs-on: macos-14
env:
CCACHE_DIR: /tmp/ccache_dir
QT_VER: '6.11.1'
QT_VER: '6.11.0'
QT_VER_MAIN: '6'
LLVM_COMPILER_VER: '21'
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
@@ -209,16 +209,16 @@ jobs:
# Only run push event on master branch of main repo, but run all PRs
if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
name: RPCS3 Windows
runs-on: windows-2025-vs2026
runs-on: windows-2025
env:
COMPILER: msvc
QT_VER_MAIN: '6'
QT_VER: '6.11.1'
QT_VER: '6.11.0'
QT_VER_MSVC: 'msvc2022'
QT_DATE: '202605090529'
QT_DATE: '202603180535'
LLVM_VER: '19.1.7'
VULKAN_VER: '1.4.341.1'
VULKAN_SDK_SHA: 'bcf2d75aa9556889ab974858666e20b3655b6055a0db704ccb47279ff33b5bfe'
VULKAN_VER: '1.3.268.0'
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
CCACHE_SHA: '859141059ac950e1e8cd042c66f842f26b9e3a62a1669a69fe6ba180cb58bbdf'
CCACHE_BIN_DIR: 'C:\ccache_bin'
CCACHE_DIR: 'C:\ccache'
@@ -235,7 +235,7 @@ jobs:
fetch-depth: 0
- name: Setup NuGet
uses: nuget/setup-nuget@v4
uses: nuget/setup-nuget@v2
- name: Restore NuGet packages
run: nuget restore rpcs3.sln
+15 -15
View File
@@ -7,24 +7,24 @@ if(USE_SYSTEM_CURL)
target_link_libraries(3rdparty_libcurl INTERFACE CURL::libcurl)
else()
message(STATUS "RPCS3: building libcurl + wolfssl submodules")
set(BUILD_CURL_EXE OFF CACHE INTERNAL "")
set(BUILD_STATIC_CURL OFF CACHE INTERNAL "")
set(BUILD_STATIC_LIBS ON CACHE INTERNAL "")
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
set(BUILD_CURL_EXE OFF CACHE BOOL "Set to ON to build curl executable.")
set(BUILD_STATIC_CURL OFF CACHE BOOL "Set to ON to build curl executable with static libcurl.")
set(BUILD_STATIC_LIBS ON CACHE BOOL "Set to ON to build static libcurl.")
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Set to ON to build shared libcurl.")
find_package(WolfSSL REQUIRED)
set(CURL_USE_WOLFSSL ON CACHE INTERNAL "")
set(CURL_USE_OPENSSL OFF CACHE INTERNAL "")
set(HTTP_ONLY ON CACHE INTERNAL "")
set(USE_LIBIDN2 OFF CACHE INTERNAL "") # Disabled because MacOS CI doesn't work otherwise
set(CURL_CA_PATH "none" CACHE INTERNAL "")
set(CURL_DISABLE_INSTALL ON CACHE INTERNAL "")
set(CURL_USE_WOLFSSL ON CACHE BOOL "enable wolfSSL for SSL/TLS")
set(CURL_USE_OPENSSL OFF CACHE BOOL "Use OpenSSL code. Experimental")
set(HTTP_ONLY ON CACHE BOOL "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)")
set(USE_LIBIDN2 OFF CACHE BOOL "Use libidn2 for IDN support") # Disabled because MacOS CI doesn't work otherwise
set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
option(CURL_DISABLE_INSTALL "Disable installation targets" ON)
if(WIN32)
set(ENABLE_UNICODE ON CACHE INTERNAL "")
set(ENABLE_UNICODE ON CACHE BOOL "enable Unicode")
endif()
set(CURL_USE_LIBSSH2 OFF CACHE INTERNAL "")
set(CURL_USE_LIBPSL OFF CACHE INTERNAL "")
set(BUILD_TESTING OFF CACHE INTERNAL "")
set(BUILD_EXAMPLES OFF CACHE INTERNAL "")
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "Use libSSH2")
set(CURL_USE_LIBPSL OFF CACHE BOOL "Use libPSL")
option(BUILD_TESTING "Build tests" OFF)
option(BUILD_EXAMPLES "Build libcurl examples" OFF)
add_subdirectory(curl EXCLUDE_FROM_ALL)
+3 -11
View File
@@ -66,7 +66,6 @@
<ClCompile Include="curl\lib\asyn-thrdd.c" />
<ClCompile Include="curl\lib\bufq.c" />
<ClCompile Include="curl\lib\bufref.c" />
<ClCompile Include="curl\lib\cf-dns.c" />
<ClCompile Include="curl\lib\cf-h1-proxy.c" />
<ClCompile Include="curl\lib\cf-h2-proxy.c" />
<ClCompile Include="curl\lib\cf-haproxy.c" />
@@ -108,6 +107,7 @@
<ClCompile Include="curl\lib\curl_memrchr.c" />
<ClCompile Include="curl\lib\curl_ntlm_core.c" />
<ClCompile Include="curl\lib\curl_range.c" />
<ClCompile Include="curl\lib\curl_rtmp.c" />
<ClCompile Include="curl\lib\curl_sasl.c" />
<ClCompile Include="curl\lib\curl_sha512_256.c" />
<ClCompile Include="curl\lib\curl_share.c" />
@@ -118,7 +118,6 @@
<ClCompile Include="curl\lib\cw-pause.c" />
<ClCompile Include="curl\lib\dict.c" />
<ClCompile Include="curl\lib\dllmain.c" />
<ClCompile Include="curl\lib\dnscache.c" />
<ClCompile Include="curl\lib\doh.c" />
<ClCompile Include="curl\lib\dynhds.c" />
<ClCompile Include="curl\lib\easy.c" />
@@ -173,7 +172,6 @@
<ClCompile Include="curl\lib\pingpong.c" />
<ClCompile Include="curl\lib\pop3.c" />
<ClCompile Include="curl\lib\progress.c" />
<ClCompile Include="curl\lib\protocol.c" />
<ClCompile Include="curl\lib\psl.c" />
<ClCompile Include="curl\lib\rand.c" />
<ClCompile Include="curl\lib\ratelimit.c" />
@@ -197,8 +195,6 @@
<ClCompile Include="curl\lib\system_win32.c" />
<ClCompile Include="curl\lib\telnet.c" />
<ClCompile Include="curl\lib\tftp.c" />
<ClCompile Include="curl\lib\thrdpool.c" />
<ClCompile Include="curl\lib\thrdqueue.c" />
<ClCompile Include="curl\lib\transfer.c" />
<ClCompile Include="curl\lib\uint-bset.c" />
<ClCompile Include="curl\lib\uint-hash.c" />
@@ -259,7 +255,6 @@
<ClInclude Include="curl\lib\asyn.h" />
<ClInclude Include="curl\lib\bufq.h" />
<ClInclude Include="curl\lib\bufref.h" />
<ClInclude Include="curl\lib\cf-dns.h" />
<ClInclude Include="curl\lib\cf-h1-proxy.h" />
<ClInclude Include="curl\lib\cf-h2-proxy.h" />
<ClInclude Include="curl\lib\cf-haproxy.h" />
@@ -280,6 +275,7 @@
<ClInclude Include="curl\lib\curlx\base64.h" />
<ClInclude Include="curl\lib\curlx\basename.h" />
<ClInclude Include="curl\lib\curlx\binmode.h" />
<ClInclude Include="curl\lib\curlx\curlx.h" />
<ClInclude Include="curl\lib\curlx\dynbuf.h" />
<ClInclude Include="curl\lib\curlx\fopen.h" />
<ClInclude Include="curl\lib\curlx\inet_ntop.h" />
@@ -313,6 +309,7 @@
<ClInclude Include="curl\lib\curl_ntlm_core.h" />
<ClInclude Include="curl\lib\curl_printf.h" />
<ClInclude Include="curl\lib\curl_range.h" />
<ClInclude Include="curl\lib\curl_rtmp.h" />
<ClInclude Include="curl\lib\curl_sasl.h" />
<ClInclude Include="curl\lib\curl_setup.h" />
<ClInclude Include="curl\lib\curl_setup_once.h" />
@@ -325,7 +322,6 @@
<ClInclude Include="curl\lib\cw-out.h" />
<ClInclude Include="curl\lib\cw-pause.h" />
<ClInclude Include="curl\lib\dict.h" />
<ClInclude Include="curl\lib\dnscache.h" />
<ClInclude Include="curl\lib\doh.h" />
<ClInclude Include="curl\lib\dynhds.h" />
<ClInclude Include="curl\lib\easyif.h" />
@@ -336,7 +332,6 @@
<ClInclude Include="curl\lib\file.h" />
<ClInclude Include="curl\lib\fileinfo.h" />
<ClInclude Include="curl\lib\formdata.h" />
<ClInclude Include="curl\lib\ftp-int.h" />
<ClInclude Include="curl\lib\ftp.h" />
<ClInclude Include="curl\lib\ftplistparser.h" />
<ClInclude Include="curl\lib\functypes.h" />
@@ -373,7 +368,6 @@
<ClInclude Include="curl\lib\pingpong.h" />
<ClInclude Include="curl\lib\pop3.h" />
<ClInclude Include="curl\lib\progress.h" />
<ClInclude Include="curl\lib\protocol.h" />
<ClInclude Include="curl\lib\psl.h" />
<ClInclude Include="curl\lib\rand.h" />
<ClInclude Include="curl\lib\ratelimit.h" />
@@ -401,8 +395,6 @@
<ClInclude Include="curl\lib\system_win32.h" />
<ClInclude Include="curl\lib\telnet.h" />
<ClInclude Include="curl\lib\tftp.h" />
<ClInclude Include="curl\lib\thrdpool.h" />
<ClInclude Include="curl\lib\thrdqueue.h" />
<ClInclude Include="curl\lib\transfer.h" />
<ClInclude Include="curl\lib\uint-bset.h" />
<ClInclude Include="curl\lib\uint-hash.h" />
+9 -33
View File
@@ -66,6 +66,9 @@
<ClCompile Include="curl\lib\curl_range.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curl_rtmp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curl_sasl.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -549,21 +552,6 @@
<ClCompile Include="curl\lib\curlx\strdup.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\cf-dns.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\dnscache.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\protocol.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\thrdpool.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\thrdqueue.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="curl\include\curl\curl.h">
@@ -680,6 +668,9 @@
<ClInclude Include="curl\lib\curl_range.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_rtmp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_sasl.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1049,6 +1040,9 @@
<ClInclude Include="curl\lib\curlx\base64.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\curlx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\dynbuf.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1127,24 +1121,6 @@
<ClInclude Include="curl\lib\curlx\strdup.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\cf-dns.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\dnscache.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\ftp-int.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\protocol.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\thrdpool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\thrdqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="curl\lib\libcurl.rc">
-5
View File
@@ -54,9 +54,6 @@
<ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Condition="'$(EnableLibUsbWindowsHotplug)' == 'true'">
<PreprocessorDefinitions>LIBUSB_WINDOWS_HOTPLUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
</Lib>
@@ -67,7 +64,6 @@
<ClCompile Include="libusb\libusb\hotplug.c" />
<ClCompile Include="libusb\libusb\io.c" />
<ClCompile Include="libusb\libusb\os\events_windows.c" />
<ClCompile Condition="'$(EnableLibUsbWindowsHotplug)' == 'true'" Include="libusb\libusb\os\windows_hotplug.c" />
<ClCompile Include="libusb\libusb\strerror.c" />
<ClCompile Include="libusb\libusb\sync.c" />
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
@@ -76,7 +72,6 @@
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Condition="'$(EnableLibUsbWindowsHotplug)' == 'true'" Include="libusb\libusb\os\windows_hotplug.h" />
<ClInclude Include="libusb\msvc\config.h" />
<ClInclude Include="libusb\libusb\hotplug.h" />
<ClInclude Include="libusb\libusb\libusb.h" />
+3 -6
View File
@@ -119,8 +119,7 @@ echo -e "\n\nResult:\n"
# Find the max length of the paths (before '->')
max_len=0
while read -r line; do
left="${line%%->*}"
while IFS='->' read -r left _; do
len=$(echo -n "$left" | wc -c)
if (( len > max_len )); then
max_len=$len
@@ -128,10 +127,8 @@ while read -r line; do
done < "$resultfile"
# Print with padding so '->' lines up
while read -r line; do
left="${line%%->*}"
right="${line#*->}"
right=$(echo "$right" | sed 's/^[[:space:]]*//')
while IFS='->' read -r left right; do
right=$(echo "$right" | sed 's/^[[:space:]]*>*[[:space:]]*//')
printf "%-${max_len}s -> %s\n" "$left" "$right"
done < "$resultfile"
+16 -15
View File
@@ -4,22 +4,23 @@ if(USE_SYSTEM_WOLFSSL)
add_library(wolfssl INTERFACE)
target_link_libraries(wolfssl INTERFACE PkgConfig::WolfSSL)
else()
set(WOLFSSL_TLS13 OFF CACHE INTERNAL "")
set(WOLFSSL_SHA3 ON CACHE INTERNAL "")
set(WOLFSSL_SHAKE256 ON CACHE INTERNAL "")
set(WOLFSSL_BASE64_ENCODE OFF CACHE INTERNAL "")
set(WOLFSSL_DES3 ON CACHE INTERNAL "")
set(WOLFSSL_PWDBASED ON CACHE INTERNAL "")
set(WOLFSSL_FAST_MATH ON CACHE INTERNAL "")
set(WOLFSSL_EXAMPLES OFF CACHE INTERNAL "")
set(WOLFSSL_CRYPT_TESTS OFF CACHE INTERNAL "")
set(WOLFSSL_ASYNC_THREADS OFF CACHE INTERNAL "")
set(WOLFSSL_BUILD_OUT_OF_TREE ON CACHE INTERNAL "")
set(WOLFSSL_SNI ON CACHE INTERNAL "")
set(WOLFSSL_OPENSSLEXTRA ON CACHE INTERNAL "")
set(WOLFSSL_ALT_CERT_CHAINS ON CACHE INTERNAL "")
option(WOLFSSL_TLS13 "Enable wolfSSL TLS v1.3 (default: enabled)" OFF)
set(WOLFSSL_SHA3 ON CACHE STRING "Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)")
set(WOLFSSL_SHAKE256 ON CACHE STRING "Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)")
option(WOLFSSL_BASE64_ENCODE "Enable Base64 encoding (default: enabled on x86_64)" OFF)
option(WOLFSSL_DES3 "Enable DES3 (default: disabled)" ON)
option(WOLFSSL_PWDBASED "Enable PWDBASED (default: disabled)" ON)
option(WOLFSSL_FAST_MATH "Enable fast math ops (default: disabled)" ON)
option(WOLFSSL_EXAMPLES "Enable examples (default: enabled)" OFF)
option(WOLFSSL_CRYPT_TESTS "Enable Crypt Bench/Test (default: enabled)" OFF)
option(WOLFSSL_ASYNC_THREADS "Enable Asynchronous Threading (default: enabled)" OFF)
option(WOLFSSL_BUILD_OUT_OF_TREE "Don't generate files in the source tree (default: yes)" ON)
option(WOLFSSL_SNI "Enable SNI (default: disabled)" ON)
option(WOLFSSL_OPENSSLEXTRA "Enable extra OpenSSL API, size+ (default: disabled)" ON)
option(WOLFSSL_HARDEN "Enable Hardened build, Enables Timing Resistance and Blinding (default: enabled)" OFF)
option(WOLFSSL_ALT_CERT_CHAINS "Enable support for Alternate certification chains (default: disabled)" ON)
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_USE_OPTIONS_H)
target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_NO_OPTIONS_H)
endif()
+7 -7
View File
@@ -20,27 +20,27 @@ The following tools are required to build RPCS3 on Windows 10 or later:
with standalone **CMake** tool.
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
- [Qt 6.11.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.4.341.1](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)). Note that future SDKs may not work.
- [Qt 6.11.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.11.1\msvc2022_64\`
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.11.0\msvc2022_64\`
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.11.1\msvc2022_64\`
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.11.0\msvc2022_64\`
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
- Clang 17+ or GCC 13+
- [CMake 3.28.0+](https://www.cmake.org/download/)
- [Qt 6.11.1](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.4.341.1](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)). Note that future SDKs may not work.
- [Qt 6.11.0](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
**If you have an NVIDIA GPU, you may need to install the libglvnd package.**
@@ -123,7 +123,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
##### Configuring the Qt Plugin (if used)
1) go to `Extensions->Qt VS Tools->Qt Versions`
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.11.1\msvc2022_64`, version will fill in automatically
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.11.0\msvc2022_64`, version will fill in automatically
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
+2 -2
View File
@@ -94,8 +94,8 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew")
list(APPEND CMAKE_SYSTEM_PREFIX_PATH "/opt/homebrew")
include_directories(/opt/homebrew/include)
link_directories(/opt/homebrew/lib)
endif()
if(MSVC)
-10
View File
@@ -23,16 +23,6 @@ If you want to contribute as a developer, please take a look at the following pa
You should also contact any of the developers in the forums or in the Discord server to learn more about the current state of the emulator.
### AI Use
Use of AI tools for research and reverse engineering purposes is permitted. However, contributors are expected to fully own and understand all code they submit. Any communication with the team — including code, code comments, and GitHub comments — must come from the human contributor, not an AI agent acting autonomously.
We have unfortunately seen a rise in untested and unverified AI-generated slop being submitted to this project. This wastes maintainer time and, in worse cases, such changes get merged and break functionality for all users. Repeated violations will result in a ban from the repository. Please be respectful of everyone's time.
**Pull requests opened by AI agents or automated tools must include a disclosure in the PR description** stating the scope of AI involvement — which parts were AI-generated and what human testing or review was performed prior to submission. PRs that omit this disclosure may be closed without review.
If you are unsure about your work, open a discussion issue to talk it through with the team, or reach out to a maintainer on [Discord](https://discord.gg/RPCS3).
## Building
See [BUILDING.md](BUILDING.md) for more information about how to setup an environment to build RPCS3.
+50 -118
View File
@@ -40,7 +40,7 @@ namespace cfg
owner->m_nodes.emplace_back(this);
}
bool _base::from_string(std::string_view /*value*/, bool /*dynamic*/)
bool _base::from_string(std::string_view, bool)
{
cfg_log.fatal("cfg::_base::from_string() purecall");
return false;
@@ -68,7 +68,7 @@ namespace cfg
// Incrementally load config entries from YAML::Node.
// The config value is preserved if the corresponding YAML node doesn't exist.
[[nodiscard]] static bool decode(const YAML::Node& data, class _base& rhs, bool dynamic, bool strict);
static void decode(const YAML::Node& data, class _base& rhs, bool dynamic = false);
}
std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
@@ -76,11 +76,11 @@ std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
return {std::to_string(min), std::to_string(max)};
}
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max, std::string_view name)
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
{
if (value.empty())
{
if (out) cfg_log.error("cfg::try_to_int64('%s'): called with an empty string", name);
if (out) cfg_log.error("cfg::try_to_int64(): called with an empty string");
return false;
}
@@ -107,7 +107,7 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max, std::strin
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
{
if (out) cfg_log.error("cfg::try_to_int64('%s', '%s'): invalid integer", value, name);
if (out) cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value);
return false;
}
@@ -115,7 +115,7 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max, std::strin
if (result < min || result > max)
{
if (out) cfg_log.error("cfg::try_to_int64('%s', '%s'): out of bounds (val=%d, min=%d, max=%d)", value, name, result, min, max);
if (out) cfg_log.error("cfg::try_to_int64('%s'): out of bounds (val=%d, min=%d, max=%d)", value, result, min, max);
return false;
}
@@ -128,11 +128,11 @@ std::vector<std::string> cfg::make_uint_range(u64 min, u64 max)
return {std::to_string(min), std::to_string(max)};
}
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max, std::string_view name)
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
{
if (value.empty())
{
if (out) cfg_log.error("cfg::try_to_uint64('%s'): called with an empty string", name);
if (out) cfg_log.error("cfg::try_to_uint64(): called with an empty string");
return false;
}
@@ -152,13 +152,13 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max, std::stri
if (ret.ec != std::errc() || ret.ptr != end)
{
if (out) cfg_log.error("cfg::try_to_uint64('%s', '%s'): invalid integer", value, name);
if (out) cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value);
return false;
}
if (result < min || result > max)
{
if (out) cfg_log.error("cfg::try_to_uint64('%s', '%s'): out of bounds (val=%u, min=%u, max=%u)", value, name, result, min, max);
if (out) cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (val=%u, min=%u, max=%u)", value, result, min, max);
return false;
}
@@ -166,11 +166,11 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max, std::stri
return true;
}
bool try_to_uint128(u128* out, std::string_view value, std::string_view name)
bool try_to_uint128(u128* out, std::string_view value)
{
if (value.empty())
{
if (out) cfg_log.error("cfg::try_to_uint128('%s'): called with an empty string", name);
if (out) cfg_log.error("cfg::try_to_uint128(): called with an empty string");
return false;
}
@@ -193,7 +193,7 @@ bool try_to_uint128(u128* out, std::string_view value, std::string_view name)
if (ret.ec != std::errc() || ret.ptr != end)
{
if (out) cfg_log.error("cfg::try_to_uint128('%s', '%s'): invalid integer", value, name);
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
return false;
}
@@ -207,7 +207,7 @@ bool try_to_uint128(u128* out, std::string_view value, std::string_view name)
if (ret.ec != std::errc() || ret.ptr != start_low64)
{
if (out) cfg_log.error("cfg::try_to_uint128('%s', '%s'): invalid integer", value, name);
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
return false;
}
@@ -220,11 +220,11 @@ std::vector<std::string> cfg::make_float_range(f64 min, f64 max)
return {std::to_string(min), std::to_string(max)};
}
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max, std::string_view name)
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
{
if (value.empty())
{
if (out) cfg_log.error("cfg::try_to_float('%s'): called with an empty string", name);
if (out) cfg_log.error("cfg::try_to_float(): called with an empty string");
return false;
}
@@ -237,13 +237,13 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max, std::strin
if (end_check != str.data() + str.size())
{
if (out) cfg_log.error("cfg::try_to_float('%s', '%s'): invalid float", value, name);
if (out) cfg_log.error("cfg::try_to_float('%s'): invalid float", value);
return false;
}
if (result < min || result > max)
{
if (out) cfg_log.error("cfg::try_to_float('%s', '%s'): out of bounds (val=%f, min=%f, max=%f)", value, name, result, min, max);
if (out) cfg_log.error("cfg::try_to_float('%s'): out of bounds (val=%f, min=%f, max=%f)", value, result, min, max);
return false;
}
@@ -251,8 +251,12 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max, std::strin
return true;
}
bool try_to_string(std::string* out, f64 value, std::string_view name)
bool try_to_string(std::string* out, const f64& value)
{
#ifdef __APPLE__
if (out) *out = std::to_string(value);
return true;
#else
std::array<char, 32> str{};
if (auto [ptr, ec] = std::to_chars(str.data(), str.data() + str.size(), value, std::chars_format::fixed); ec == std::errc())
@@ -262,15 +266,14 @@ bool try_to_string(std::string* out, f64 value, std::string_view name)
}
else
{
if (out) cfg_log.error("cfg::try_to_string('%s'): could not convert value '%f' to string. error='%s'", name, value, std::make_error_code(ec).message());
if (out) cfg_log.error("cfg::try_to_string(): could not convert value '%f' to string. error='%s'", value, std::make_error_code(ec).message());
return false;
}
#endif
}
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value, std::string_view name)
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value)
{
ensure(func);
u64 max = umax;
for (u64 i = 0;; i++)
@@ -299,7 +302,7 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
const char* end = start + value.size();
int base = 10;
if (value.size() >= 2 && start[0] == '0' && (start[1] == 'x' || start[1] == 'X'))
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X'))
{
// Limited hex support
base = 16;
@@ -310,13 +313,13 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
if (ret.ec != std::errc() || ret.ptr != end)
{
if (out) cfg_log.error("cfg::try_to_enum_value('%s', '%s'): invalid enum or integer", value, name);
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): invalid enum or integer", value);
return false;
}
if (result > max)
{
if (out) cfg_log.error("cfg::try_to_enum_value('%s', '%s'): out of bounds(val=%u, min=0, max=%u)", value, name, result, max);
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): out of bounds(val=%u, min=0, max=%u)", value, result, max);
return false;
}
@@ -465,50 +468,37 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
}
}
bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool strict)
void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
{
if (dynamic && !rhs.get_is_dynamic())
{
return true;
return;
}
switch (rhs.get_type())
{
case type::node:
{
if (!data.IsMap())
if (data.IsScalar() || data.IsSequence())
{
cfg_log.error("node node is not a map");
return false;
return; // ???
}
bool success = true;
for (const auto& pair : data)
{
if (!pair.first.IsScalar()) continue;
// Find the key among existing nodes
const auto& nodes = static_cast<node&>(rhs).get_nodes();
const auto it = std::find_if(nodes.cbegin(), nodes.cend(), [&pair](const auto& node) { return ensure(node)->get_name() == pair.first.Scalar(); });
if (it == nodes.cend())
for (const auto& node : static_cast<node&>(rhs).get_nodes())
{
if (strict)
if (node->get_name() == pair.first.Scalar())
{
cfg_log.error("Unknown key found: '%s'", pair.first.Scalar());
success = false;
decode(pair.second, *node, dynamic);
}
continue;
}
if (!decode(pair.second, *ensure(*it), dynamic, strict) && strict)
{
success = false;
}
}
return success;
break;
}
case type::set:
{
@@ -516,10 +506,7 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str
if (YAML::convert<decltype(values)>::decode(data, values))
{
if (!rhs.from_list(std::move(values)) && strict)
{
return false;
}
rhs.from_list(std::move(values));
}
break;
@@ -529,8 +516,7 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str
{
if (!data.IsMap())
{
cfg_log.error("map node is not a map");
return false;
return;
}
map_of_type<std::string> values;
@@ -547,36 +533,22 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str
}
case type::log:
{
if (!data.IsMap())
if (data.IsScalar() || data.IsSequence())
{
cfg_log.error("log node is not a map");
return false;
return; // ???
}
map_of_type<logs::level> values;
for (const auto& pair : data)
{
if (!pair.first.IsScalar() || !pair.second.IsScalar())
{
if (strict)
{
if (!pair.first.IsScalar())
cfg_log.error("Key in map is not a scalar");
else
cfg_log.error("Value in map is not a scalar. key='%s'", pair.first.Scalar());
return false;
}
continue;
}
if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue;
u64 value;
if (!cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar(), pair.first.Scalar()) && strict)
if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar()))
{
return false;
values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value)));
}
values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value)));
}
static_cast<log_entry&>(rhs).set_map(std::move(values));
@@ -586,43 +558,20 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str
{
if (!data.IsMap())
{
cfg_log.error("device node is not a map");
return false;
return; // ???
}
map_of_type<device_info> values;
for (const auto& pair : data)
{
if (!pair.first.IsScalar() || !pair.second.IsMap())
{
if (strict)
{
if (!pair.first.IsScalar())
cfg_log.error("Key in device map is not a scalar");
else
cfg_log.error("Value in device map is not a map. key='%s'", pair.first.Scalar());
return false;
}
continue;
}
if (!pair.first.IsScalar() || !pair.second.IsMap()) continue;
device_info info{};
for (const auto& key_value : pair.second)
{
if (!key_value.first.IsScalar() || !key_value.second.IsScalar())
{
if (strict)
{
if (!key_value.first.IsScalar())
cfg_log.error("Key in device info map is not a scalar");
else
cfg_log.error("Value in device map is not a scalar. key='%s'", key_value.first.Scalar());
return false;
}
continue;
}
if (!key_value.first.IsScalar() || !key_value.second.IsScalar()) continue;
if (key_value.first.Scalar() == "Path")
info.path = key_value.second.Scalar();
@@ -649,17 +598,12 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str
if (YAML::convert<std::string>::decode(data, value))
{
if (!rhs.from_string(value, dynamic) && strict)
{
return false;
}
rhs.from_string(value, dynamic);
}
break; // ???
}
}
return true;
}
std::string cfg::node::to_string() const
@@ -676,7 +620,8 @@ bool cfg::node::from_string(std::string_view value, bool dynamic)
if (error.empty())
{
return cfg::decode(result, *this, dynamic, false);
cfg::decode(result, *this, dynamic);
return true;
}
cfg_log.error("Failed to load node: %s", error);
@@ -699,19 +644,6 @@ void cfg::node::restore_defaults()
}
}
bool cfg::node::validate(std::string_view value)
{
auto [result, error] = yaml_load(std::string(value));
if (error.empty())
{
return cfg::decode(result, *this, false, true);
}
cfg_log.error("Failed to load node: %s", error);
return false;
}
std::string cfg::map_entry::get_value(std::string_view key)
{
if (auto it = m_map.find(key); it != m_map.end())
+9 -17
View File
@@ -25,7 +25,7 @@ namespace cfg
std::vector<std::string> make_float_range(f64 min, f64 max);
// Internal hack
bool try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value, std::string_view name = {});
bool try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view);
// Internal hack
std::vector<std::string> try_to_enum_list(decltype(&fmt_class_string<int>::format) func);
@@ -110,7 +110,7 @@ namespace cfg
}
// Try to convert from string (optional)
virtual bool from_string(std::string_view value, bool dynamic = false);
virtual bool from_string(std::string_view, bool /*dynamic*/ = false);
// Get string list (optional)
virtual std::vector<std::string> to_list() const
@@ -161,9 +161,6 @@ namespace cfg
// Restore default members
void restore_defaults() override;
// Try to convert from string and validate
bool validate(std::string_view value);
};
class _bool final : public _base
@@ -304,7 +301,7 @@ namespace cfg
{
u64 result;
if (try_to_enum_value(&result, &fmt_class_string<T>::format, value, m_name))
if (try_to_enum_value(&result, &fmt_class_string<T>::format, value))
{
// No narrowing check, it's hard to do right there
m_value = static_cast<T>(static_cast<std::underlying_type_t<T>>(result));
@@ -385,7 +382,7 @@ namespace cfg
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
s64 result;
if (try_to_int64(&result, value, Min, Max, m_name))
if (try_to_int64(&result, value, Min, Max))
{
m_value = static_cast<int_type>(result);
return true;
@@ -454,7 +451,7 @@ namespace cfg
std::string to_string() const override
{
std::string result;
if (try_to_string(&result, m_value, m_name))
if (try_to_string(&result, m_value))
{
return result;
}
@@ -465,7 +462,7 @@ namespace cfg
std::string def_to_string() const override
{
std::string result;
if (try_to_string(&result, def, m_name))
if (try_to_string(&result, def))
{
return result;
}
@@ -476,7 +473,7 @@ namespace cfg
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
f64 result;
if (try_to_float(&result, value, Min, Max, m_name))
if (try_to_float(&result, value, Min, Max))
{
m_value = static_cast<float_type>(result);
return true;
@@ -563,7 +560,7 @@ namespace cfg
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
u64 result;
if (try_to_uint64(&result, value, Min, Max, m_name))
if (try_to_uint64(&result, value, Min, Max))
{
m_value = static_cast<int_type>(result);
return true;
@@ -649,7 +646,7 @@ namespace cfg
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
u128 result;
if (try_to_uint128(&result, value, m_name))
if (try_to_uint128(&result, value))
{
m_value = result;
return true;
@@ -717,11 +714,6 @@ namespace cfg
m_value = std::string(value);
return true;
}
void set(std::string_view value)
{
m_value = std::string(value);
}
};
// Simple set entry (TODO: template for various types)
+7 -99
View File
@@ -38,17 +38,6 @@ static std::unique_ptr<wchar_t[]> to_wchar(std::string_view source)
// Buffer for max possible output length
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size + 8 + 32768]);
// If path points to an optical raw device, copy it AS IS
if (fs::is_optical_raw_device(std::string(source)))
{
ensure(MultiByteToWideChar(CP_UTF8, 0, source.data(), size, buffer.get() + 32768, size)); // "to_wchar"
// Canonicalize wide path (replace '/', ".", "..", \\ repetitions, etc)
ensure(GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1); // "to_wchar"
return buffer;
}
// Prepend wide path prefix (4 characters)
std::memcpy(buffer.get() + 32768, L"\\\\\?\\", 4 * sizeof(wchar_t));
@@ -177,7 +166,6 @@ static fs::error to_error(int e)
case ENOTEMPTY: return fs::error::notempty;
case EROFS: return fs::error::readonly;
case EISDIR: return fs::error::isdir;
case ENOTDIR: return fs::error::notdir;
case ENOSPC: return fs::error::nospace;
case EXDEV: return fs::error::xdev;
default: return fs::error::unknown;
@@ -411,12 +399,11 @@ namespace fs
class windows_file final : public file_base
{
HANDLE m_handle;
bool m_raw_device;
atomic_t<u64> m_pos {0};
public:
windows_file(HANDLE handle, bool raw_device = false)
: m_handle(handle), m_raw_device(raw_device)
windows_file(HANDLE handle)
: m_handle(handle)
{
}
@@ -576,20 +563,11 @@ namespace fs
u64 size() override
{
if (!m_raw_device)
{
// NOTE: this can fail if we access a mounted empty drive (e.g. after unmounting an iso).
LARGE_INTEGER size;
// NOTE: this can fail if we access a mounted empty drive (e.g. after unmounting an iso).
LARGE_INTEGER size;
ensure(GetFileSizeEx(m_handle, &size)); // "file::size"
ensure(GetFileSizeEx(m_handle, &size)); // "file::size"
return size.QuadPart;
}
// For a raw device, we need to use DeviceIoControl.
DISK_GEOMETRY_EX geometry;
ensure(DeviceIoControl(m_handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nullptr, 0, &geometry, sizeof(geometry), nullptr, nullptr));
return geometry.DiskSize.QuadPart;
return size.QuadPart;
}
native_handle get_handle() override
@@ -1112,55 +1090,6 @@ bool fs::is_symlink(const std::string& path)
return true;
}
bool fs::is_optical_raw_device([[maybe_unused]] const std::string& path)
{
#ifdef _WIN32
if (path.starts_with("\\\\.\\"))
{
return true;
}
#endif
return false;
}
bool fs::get_optical_raw_device(const std::string& path, std::string* raw_device)
{
if (fs::is_optical_raw_device(path))
{
if (raw_device)
{
*raw_device = path;
}
return true;
}
#ifdef _WIN32
// Skip a useless check to detect an optical raw device if navigating on subfolders (e.g. C:\subfolder_1\subfolder_2\),
// it means we are on a HDD/SSD. A path for an optical drive should include only the drive letter (e.g. E:\)
const size_t drive_delim_pos = path.find_first_of(":");
if (drive_delim_pos != 1 || drive_delim_pos != path.find_last_not_of(delim))
{
return false;
}
const std::string drive_letter = path.substr(0, drive_delim_pos + 1); // e.g. "E:"
const std::string drive_path = drive_letter + "\\"; // e.g. "E:\"
if (GetDriveTypeA(drive_path.c_str()) == DRIVE_CDROM)
{
if (raw_device)
{
*raw_device = "\\\\.\\" + drive_letter;
}
return true;
}
#endif
return false;
}
bool fs::statfs(const std::string& path, fs::device_stat& info)
{
if (auto device = get_virtual_device(path))
@@ -1728,29 +1657,9 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return;
}
// If path points to an optical raw device, complete the file opening
// (the following GetFileInformationByHandle() would always fail on a raw device).
if (is_optical_raw_device(path))
{
DISK_GEOMETRY_EX geometry;
// Try to retrieve information on content. If it fails, no disc is probably mounted so abort the file opening
if (!DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nullptr, 0, &geometry, sizeof(geometry), nullptr, nullptr))
{
const DWORD last_error = GetLastError();
CloseHandle(handle);
g_tls_error = to_error(last_error);
return;
}
m_file = std::make_unique<windows_file>(handle, true);
return;
}
// Check if the handle is actually valid.
// This can fail on empty mounted drives (e.g. with ERROR_NOT_READY or ERROR_INVALID_FUNCTION).
BY_HANDLE_FILE_INFORMATION info{};
if (!GetFileInformationByHandle(handle, &info))
{
const DWORD last_error = GetLastError();
@@ -1761,7 +1670,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
g_tls_error = fs::error::isdir;
return;
}
g_tls_error = to_error(last_error);
return;
}
@@ -2924,7 +2833,6 @@ void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
case fs::error::notempty: return "Not empty";
case fs::error::readonly: return "Read only";
case fs::error::isdir: return "Is a directory";
case fs::error::notdir: return "Not a directory";
case fs::error::toolong: return "Path too long";
case fs::error::nospace: return "Not enough space on the device";
case fs::error::xdev: return "Device mismatch";
-7
View File
@@ -213,12 +213,6 @@ namespace fs
// Check whether the path points to an existing symlink
bool is_symlink(const std::string& path);
// Check whether the path points to a raw device
bool is_optical_raw_device(const std::string& path);
// Check whether the path points to an optical drive. If so, provide the raw device in "raw_device" if requested
bool get_optical_raw_device(const std::string& path, std::string* raw_device = nullptr);
// Get filesystem information
bool statfs(const std::string& path, device_stat& info);
@@ -689,7 +683,6 @@ namespace fs
notempty,
readonly,
isdir,
notdir,
toolong,
nospace,
xdev,
-13
View File
@@ -493,10 +493,6 @@ inline FT build_function_asm(std::string_view name, F&& builder, ::jit_runtime*
return reinterpret_cast<FT>(uptr(result));
}
#if defined(__INTELLISENSE__) && !defined(LLVM_AVAILABLE)
#define LLVM_AVAILABLE
#endif
#ifdef LLVM_AVAILABLE
namespace llvm
@@ -543,15 +539,9 @@ public:
// Add module (path to obj cache dir)
void add(std::unique_ptr<llvm::Module> _module, const std::string& path);
// Returns false after LLVM fatal recovery. The compiler must be discarded.
bool try_add(std::unique_ptr<llvm::Module> _module, const std::string& path, std::string& error);
// Add module (not cached)
void add(std::unique_ptr<llvm::Module> _module);
// Returns false after LLVM fatal recovery. The compiler must be discarded.
bool try_add(std::unique_ptr<llvm::Module> _module, std::string& error);
// Add object (path to obj file)
bool add(const std::string& path);
@@ -564,9 +554,6 @@ public:
// Finalize
void fin();
// Returns false after LLVM fatal recovery. The compiler must be discarded.
bool try_fin(std::string& error);
// Get compiled function address
u64 get(const std::string& name);
-115
View File
@@ -12,10 +12,6 @@
#include <charconv>
#if defined(__APPLE__)
#include <pthread.h>
#endif
LOG_CHANNEL(jit_log, "JIT");
#ifdef LLVM_AVAILABLE
@@ -54,44 +50,6 @@ LOG_CHANNEL(jit_log, "JIT");
#include "Emu/CPU/Backends/AArch64/AArch64Common.h"
#endif
namespace
{
thread_local std::string* g_llvm_fatal_message = nullptr;
template <typename F>
bool run_recoverable_llvm(F&& func, std::string& error)
{
error.clear();
// Run LLVM codegen in a disposable thread. If LLVM invokes the fatal
// handler, only this helper thread exits.
named_thread worker("LLVM JIT", [&]()
{
#if defined(__APPLE__)
pthread_jit_write_protect_np(false);
#endif
g_llvm_fatal_message = &error;
std::forward<F>(func)();
g_llvm_fatal_message = nullptr;
#if defined(__APPLE__)
pthread_jit_write_protect_np(true);
#endif
});
worker();
const bool result = static_cast<thread_state>(worker) == thread_state::finished;
if (!result && error.empty())
{
error = "LLVM crash recovery invoked";
}
return result;
}
}
const bool jit_initialize = []() -> bool
{
llvm::InitializeNativeTarget();
@@ -691,13 +649,6 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
llvm::install_fatal_error_handler([](void*, const char* msg, bool)
{
const std::string_view out = msg ? msg : "";
if (g_llvm_fatal_message)
{
*g_llvm_fatal_message = out;
thread_ctrl::silent_exit();
}
fmt::throw_exception("LLVM Emergency Exit Invoked: '%s'", out);
}, nullptr);
@@ -750,15 +701,6 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
else
attributes.push_back("-dotprod");
// The recompilers emit i8mm intrinsics (e.g. ummla) gated on utils::has_i8mm().
// The JIT target features must advertise i8mm too, otherwise the backend fails
// with "Cannot select: intrinsic %llvm.aarch64.neon.ummla" whenever the resolved
// -mcpu does not already imply it (e.g. the cortex-a78 fallback on Apple silicon).
if (utils::has_i8mm())
attributes.push_back("+i8mm");
else
attributes.push_back("-i8mm");
if (utils::has_sve())
attributes.push_back("+sve");
else
@@ -846,33 +788,6 @@ void jit_compiler::add(std::unique_ptr<llvm::Module> _module, const std::string&
}
}
bool jit_compiler::try_add(std::unique_ptr<llvm::Module> _module, const std::string& path, std::string& error)
{
ObjectCache cache{path, this};
m_engine->setObjectCache(&cache);
const auto ptr = _module.get();
m_engine->addModule(std::move(_module));
if (!run_recoverable_llvm([&]()
{
m_engine->generateCodeForModule(ptr);
}, error))
{
return false;
}
m_engine->setObjectCache(nullptr);
for (auto& func : ptr->functions())
{
// Delete IR to lower memory consumption
func.deleteBody();
}
return true;
}
void jit_compiler::add(std::unique_ptr<llvm::Module> _module)
{
const auto ptr = _module.get();
@@ -886,28 +801,6 @@ void jit_compiler::add(std::unique_ptr<llvm::Module> _module)
}
}
bool jit_compiler::try_add(std::unique_ptr<llvm::Module> _module, std::string& error)
{
const auto ptr = _module.get();
m_engine->addModule(std::move(_module));
if (!run_recoverable_llvm([&]()
{
m_engine->generateCodeForModule(ptr);
}, error))
{
return false;
}
for (auto& func : ptr->functions())
{
// Delete IR to lower memory consumption
func.deleteBody();
}
return true;
}
bool jit_compiler::add(const std::string& path)
{
auto cache = ObjectCache::load(path);
@@ -959,14 +852,6 @@ void jit_compiler::fin()
m_engine->finalizeObject();
}
bool jit_compiler::try_fin(std::string& error)
{
return run_recoverable_llvm([&]()
{
m_engine->finalizeObject();
}, error);
}
u64 jit_compiler::get(const std::string& name)
{
return m_engine->getGlobalValueAddress(name);
+5 -5
View File
@@ -23,19 +23,19 @@ inline void strcpy_trunc(D&& dst, const T& src)
}
// Convert string to signed integer
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max, std::string_view name = {});
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max);
// Convert string to unsigned integer
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max, std::string_view name = {});
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max);
// Convert string to unsigned int128_t
bool try_to_uint128(u128* out, std::string_view value, std::string_view name = {});
bool try_to_uint128(u128* out, std::string_view value);
// Convert string to float
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max, std::string_view name = {});
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max);
// Convert float to string locale independent
bool try_to_string(std::string* out, f64 value, std::string_view name = {});
bool try_to_string(std::string* out, const f64& value);
// Get the file extension of a file path ("png", "jpg", etc.)
std::string get_file_extension(const std::string& file_path);
+11 -131
View File
@@ -25,7 +25,6 @@
#include <process.h>
#include <sysinfoapi.h>
#include "stack_trace.h"
#include "util/dyn_lib.hpp"
DYNAMIC_IMPORT_RENAME("Kernel32.dll", SetThreadDescriptionImport, "SetThreadDescription", HRESULT(HANDLE hThread, PCWSTR lpThreadDescription));
@@ -1384,7 +1383,11 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
return false;
}
bool handled = true;
if (a_size != 4)
{
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
break;
}
switch (op)
{
@@ -1394,37 +1397,14 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
case X64OP_LOAD_TEST:
{
u32 value;
const u32 addr_aligned = addr & -4;
if (addr % 4 + a_size > 4)
{
handled = false;
break;
}
if (is_writing || !thread->read_reg(addr_aligned, value))
if (is_writing || !thread->read_reg(addr, value))
{
return false;
}
// Adjust value for 8-bit and 16-bit reads
value >>= ((4 - a_size) * 8) - ((addr % 4) * 8);
value &= a_size == 4 ? u32{umax} : ((1u << (a_size * 8)) - 1);
if (op != X64OP_LOAD_BE)
{
if (a_size == 4)
{
value = stx::se_storage<u32>::swap(value);
}
else if (a_size == 2)
{
value = stx::se_storage<u16>::swap(value);
}
else
{
ensure(a_size == 1);
}
value = stx::se_storage<u32>::swap(value);
}
if (op == X64OP_LOAD_CMP)
@@ -1459,35 +1439,12 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
case X64OP_BEXTR:
{
u32 value;
const u32 addr_aligned = addr & -4;
if (addr % 4 + a_size > 4)
{
handled = false;
break;
}
if (is_writing || !thread->read_reg(addr_aligned, value))
if (is_writing || !thread->read_reg(addr, value))
{
return false;
}
// Adjust value for 8-bit and 16-bit reads
value >>= ((4 - a_size) * 8) - ((addr % 4) * 8);
value &= a_size == 4 ? u32{umax} : ((1u << (a_size * 8)) - 1);
if (a_size == 4)
{
value = stx::se_storage<u32>::swap(value);
}
else if (a_size == 2)
{
value = stx::se_storage<u16>::swap(value);
}
else
{
ensure(a_size == 1);
}
value = stx::se_storage<u32>::swap(value);
u64 ctrl;
if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, ctrl))
@@ -1513,13 +1470,6 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
case X64OP_STORE:
case X64OP_STORE_BE:
{
if (a_size != 4)
{
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
handled = false;
break;
}
u64 reg_value;
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value))
{
@@ -1538,19 +1488,12 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
case X64OP_STOS:
default:
{
sig_log.error("Invalid or unsupported operation (op=%d, addr=0x%x, reg=%d, d_size=%lld, i_size=%lld, a_size=%d)", +op, addr, +reg, d_size, i_size, a_size);
sig_log.error("Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", +op, +reg, d_size, i_size);
report_opcode();
return false;
}
}
if (!handled)
{
sig_log.error("Invalid or unsupported operation (op=%d, addr=0x%x, reg=%d, d_size=%lld, i_size=%lld, a_size=%d)", +op, addr, +reg, d_size, i_size, a_size);
report_opcode();
break;
}
// skip processed instruction
RIP(context) += i_size;
g_tls_fault_spu++;
@@ -2038,39 +1981,9 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
}
fmt::append(msg, "RPCS3 image base: %p.\n", GetModuleHandle(NULL));
#if defined(ARCH_X64)
fmt::append(msg, "RAX: %016llX RBX: %016llX\n", pExp->ContextRecord->Rax, pExp->ContextRecord->Rbx);
fmt::append(msg, "RCX: %016llX RDX: %016llX\n", pExp->ContextRecord->Rcx, pExp->ContextRecord->Rdx);
fmt::append(msg, "RSI: %016llX RDI: %016llX\n", pExp->ContextRecord->Rsi, pExp->ContextRecord->Rdi);
fmt::append(msg, "RBP: %016llX RSP: %016llX\n", pExp->ContextRecord->Rbp, pExp->ContextRecord->Rsp);
fmt::append(msg, "R8: %016llX R9: %016llX\n", pExp->ContextRecord->R8, pExp->ContextRecord->R9);
fmt::append(msg, "R10: %016llX R11: %016llX\n", pExp->ContextRecord->R10, pExp->ContextRecord->R11);
fmt::append(msg, "R12: %016llX R13: %016llX\n", pExp->ContextRecord->R12, pExp->ContextRecord->R13);
fmt::append(msg, "R14: %016llX R15: %016llX\n", pExp->ContextRecord->R14, pExp->ContextRecord->R15);
fmt::append(msg, "RFLAGS: %08X\n", pExp->ContextRecord->EFlags);
#elif defined(ARCH_ARM64)
for (int i = 0; i < 29; i += 2)
{
if (i + 1 < 29)
fmt::append(msg, "X%-2d: %016llX X%-2d: %016llX\n", i, pExp->ContextRecord->X[i], i + 1, pExp->ContextRecord->X[i + 1]);
else
fmt::append(msg, "X%-2d: %016llX\n", i, pExp->ContextRecord->X[i]);
}
fmt::append(msg, "SP: %016llX FP: %016llX LR: %016llX\n", pExp->ContextRecord->Sp, pExp->ContextRecord->Fp, pExp->ContextRecord->Lr);
fmt::append(msg, "CPSR: %08X\n", pExp->ContextRecord->Cpsr);
#endif
const auto stack_trace = utils::get_backtrace(64, pExp->ContextRecord);
const auto stack_symbols = utils::get_backtrace_symbols(stack_trace);
// TODO: print registers and the callstack
msg += "Stack Trace:\n";
for (const auto& symbol : stack_symbols)
{
fmt::append(msg, "%s\n", symbol);
}
sys_log.fatal("\n%s", msg);
logs::listener::sync_all();
@@ -2939,13 +2852,6 @@ void thread_base::exec()
}
}
void thread_ctrl::set_name(std::string name)
{
ensure(g_tls_this_thread);
g_tls_this_thread->m_tname.store(make_single<std::string>(name));
g_tls_this_thread->set_name(std::move(name));
}
[[noreturn]] void thread_ctrl::emergency_exit(std::string_view reason)
{
// Print stacktrace
@@ -3044,32 +2950,6 @@ void thread_ctrl::set_name(std::string name)
report_fatal_error(reason);
}
void thread_ctrl::silent_exit() noexcept
{
if (const auto _this = g_tls_this_thread)
{
g_tls_error_callback();
u64 _self = _this->finalize(thread_state::errored);
if (_self == umax)
{
// Unused, detached thread support remnant
delete _this;
}
thread_base::finalize(umax);
}
#ifdef _WIN32
_endthreadex(0);
#else
pthread_exit(nullptr);
#endif
std::abort();
}
void thread_ctrl::detect_cpu_layout()
{
if (!g_native_core_layout.compare_and_swap_test(native_core_arrangement::undefined, native_core_arrangement::generic))
+12 -10
View File
@@ -129,7 +129,7 @@ public:
const native_entry entry_point;
// Set name for debugger
static void set_name(std::string name);
static void set_name(std::string);
private:
// Thread handle (platform-specific)
@@ -232,7 +232,11 @@ public:
}
// Set current thread name (not recommended)
static void set_name(std::string name);
static void set_name(std::string name)
{
g_tls_this_thread->m_tname.store(make_single<std::string>(name));
g_tls_this_thread->set_name(std::move(name));
}
// Set thread name (not recommended)
template <typename T>
@@ -315,9 +319,6 @@ public:
// Exit.
[[noreturn]] static void emergency_exit(std::string_view reason);
// Exit the current named thread as errored without reporting a fatal error.
[[noreturn]] static void silent_exit() noexcept;
// Get current thread (may be nullptr)
static thread_base* get_current()
{
@@ -800,30 +801,31 @@ public:
m_count = 0;
// Create all threads
for (; m_count < count - 1; m_count++)
for (u32 i = 0; i < count - 1; i++)
{
// Copy the context
std::remove_cvref_t<Context> context(static_cast<const Context&>(f));
// Perform the check and additional preparations for each context
if (!std::invoke(std::forward<CheckAndPrepare>(check), m_count, context))
if (!std::invoke(std::forward<CheckAndPrepare>(check), i, context))
{
return;
}
new (static_cast<void*>(m_threads + m_count)) Thread(std::string(name) + std::to_string(m_count + 1), std::move(context));
m_count++;
new (static_cast<void*>(m_threads + i)) Thread(std::string(name) + std::to_string(i + 1), std::move(context));
}
// Move the context (if movable)
std::remove_cvref_t<Context> context(std::forward<Context>(f));
if (!std::invoke(std::forward<CheckAndPrepare>(check), m_count, context))
if (!std::invoke(std::forward<CheckAndPrepare>(check), m_count - 1, context))
{
return;
}
new (static_cast<void*>(m_threads + m_count)) Thread(std::string(name) + std::to_string(m_count + 1), std::move(context));
m_count++;
new (static_cast<void*>(m_threads + m_count - 1)) Thread(std::string(name) + std::to_string(m_count - 1), std::move(context));
}
// Default constructor
-4
View File
@@ -1,6 +1,5 @@
#pragma once
#include <array>
#include <cmath>
#include <type_traits>
@@ -1028,6 +1027,3 @@ using color1u = color1_base<unsigned int>;
using color1i = color1_base<int>;
using color1f = color1_base<float>;
using color1d = color1_base<double>;
using mat3f = color3_base<float>[3];
static_assert(sizeof(mat3f) == sizeof(float) * 3 * 3);
-13
View File
@@ -10,19 +10,6 @@ rXmlNode::rXmlNode(const pugi::xml_node& node)
handle = node;
}
std::shared_ptr<rXmlNode> rXmlNode::GetChild(std::string_view name)
{
if (handle)
{
if (const pugi::xml_node child = handle.child(name))
{
return std::make_shared<rXmlNode>(child);
}
}
return nullptr;
}
std::shared_ptr<rXmlNode> rXmlNode::GetChildren()
{
if (handle)
-1
View File
@@ -20,7 +20,6 @@ struct rXmlNode
{
rXmlNode();
rXmlNode(const pugi::xml_node& node);
std::shared_ptr<rXmlNode> GetChild(std::string_view name);
std::shared_ptr<rXmlNode> GetChildren();
std::shared_ptr<rXmlNode> GetNext();
std::string GetName();
+12 -31
View File
@@ -30,61 +30,42 @@ namespace utils
return out.data();
}
std::vector<void*> get_backtrace(int max_depth, PCONTEXT ctx)
std::vector<void*> get_backtrace(int max_depth)
{
static struct sym_initer_t
{
sym_initer_t() noexcept
{
SymInitialize(GetCurrentProcess(), NULL, TRUE);
}
~sym_initer_t() noexcept
{
SymCleanup(GetCurrentProcess());
}
} s_initer{};
std::vector<void*> result = {};
const auto hProcess = ::GetCurrentProcess();
const auto hThread = ::GetCurrentThread();
CONTEXT context{};
if (ctx)
context = *ctx;
else
RtlCaptureContext(&context);
RtlCaptureContext(&context);
STACKFRAME64 stack = {};
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Mode = AddrModeFlat;
#if defined(ARCH_X64)
const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
stack.AddrPC.Offset = context.Rip;
stack.AddrStack.Offset = context.Rsp;
stack.AddrFrame.Offset = context.Rbp;
#elif defined(ARCH_ARM64)
const DWORD machineType = IMAGE_FILE_MACHINE_ARM64;
stack.AddrPC.Offset = context.Pc;
stack.AddrStack.Offset = context.Sp;
stack.AddrFrame.Offset = context.Fp;
#else
#error "Unsupported architecture"
#endif
while (max_depth--)
{
if (!StackWalk64(
machineType,
hProcess,
hThread,
&stack,
&context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL))
IMAGE_FILE_MACHINE_AMD64,
hProcess,
hThread,
&stack,
&context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL))
{
break;
}
@@ -135,7 +116,7 @@ namespace utils
}
else
{
result.push_back(fmt::format("rpcs3@0x%p", pointer));
result.push_back(fmt::format("rpcs3@0xp", pointer));
}
}
-10
View File
@@ -2,11 +2,6 @@
#include <util/types.hpp>
#include <util/logs.hpp>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
namespace utils
{
namespace stack_trace
@@ -35,12 +30,7 @@ namespace utils
};
}
#ifdef _WIN32
std::vector<void*> get_backtrace(int max_depth = 255, PCONTEXT ctx = nullptr);
#else
std::vector<void*> get_backtrace(int max_depth = 255);
#endif
std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack);
FORCE_INLINE void print_trace(stack_trace::Logger auto& logger, int max_depth = 255)
-159
View File
@@ -1,159 +0,0 @@
#include "stdafx.h"
#include "stereo_config.h"
#include "Emu/system_config.h"
stereo_config::stereo_matrices::stereo_matrices(const std::array<color3_base<f32>, 3>& l, const std::array<color3_base<f32>, 3>& r)
{
for (usz i = 0; i < 3; i++)
{
left[i] = l[i];
right[i] = r[i];
}
}
atomic_t<bool> stereo_config::s_live_preview_enabled = false;
stereo_config::stereo_matrices stereo_config::m_live_matrices = {};
const std::unordered_map<stereo_render_mode_options, stereo_config::stereo_matrices> stereo_config::m_matrices =
{
{stereo_render_mode_options::anaglyph_red_cyan, stereo_matrices(
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 0)
},
{
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 1, 0),
color3_base<f32>(0, 0, 1)
}
)},
{stereo_render_mode_options::anaglyph_red_green, stereo_matrices(
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 0)
},
{
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 1, 0),
color3_base<f32>(0, 0, 0)
}
)},
{stereo_render_mode_options::anaglyph_red_blue, stereo_matrices(
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 0)
},
{
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 1)
}
)},
{stereo_render_mode_options::anaglyph_magenta_cyan, stereo_matrices(
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 0.5f)
},
{
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 1, 0),
color3_base<f32>(0, 0, 0.5f)
}
)},
{stereo_render_mode_options::anaglyph_trioscopic, stereo_matrices(
{
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 1, 0),
color3_base<f32>(0, 0, 0)
},
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 0, 0),
color3_base<f32>(0, 0, 1)
}
)},
{stereo_render_mode_options::anaglyph_amber_blue, stereo_matrices(
{
color3_base<f32>(1, 0, 0),
color3_base<f32>(0, 1, 0),
color3_base<f32>(0, 0, 0)
},
{
color3_base<f32>(0, 0, 1.0f / 3.0f),
color3_base<f32>(0, 0, 1.0f / 3.0f),
color3_base<f32>(0, 0, 1.0f / 3.0f)
}
)},
};
void stereo_config::update_from_config(bool stereo_enabled)
{
m_stereo_mode = stereo_enabled ? g_cfg.video.stereo_render_mode.get() : stereo_render_mode_options::disabled;
if (m_stereo_mode == stereo_render_mode_options::anaglyph_custom)
{
stereo_config::convert_matrix(m_custom_matrices.left, g_cfg.video.custom_anaglyph_matrices.left.get_map());
stereo_config::convert_matrix(m_custom_matrices.right, g_cfg.video.custom_anaglyph_matrices.right.get_map());
}
}
const stereo_config::stereo_matrices& stereo_config::matrices() const
{
if (m_in_emulation && s_live_preview_enabled)
{
return m_live_matrices;
}
switch (m_stereo_mode)
{
case stereo_render_mode_options::disabled:
case stereo_render_mode_options::side_by_side:
case stereo_render_mode_options::over_under:
case stereo_render_mode_options::interlaced:
break;
case stereo_render_mode_options::anaglyph_red_green:
case stereo_render_mode_options::anaglyph_red_blue:
case stereo_render_mode_options::anaglyph_red_cyan:
case stereo_render_mode_options::anaglyph_magenta_cyan:
case stereo_render_mode_options::anaglyph_trioscopic:
case stereo_render_mode_options::anaglyph_amber_blue:
return ::at32(m_matrices, m_stereo_mode);
case stereo_render_mode_options::anaglyph_custom:
return m_custom_matrices;
}
static const stereo_matrices s_left_only_matrices = stereo_matrices(
{
color3_base<float>(1, 0, 0),
color3_base<float>(0, 1, 0),
color3_base<float>(0, 0, 1)
},
{
color3_base<float>(0, 0, 0),
color3_base<float>(0, 0, 0),
color3_base<float>(0, 0, 0)
});
return s_left_only_matrices;
}
std::map<std::string, std::string> stereo_config::get_custom_matrix(bool is_left) const
{
return convert_matrix(is_left ? m_custom_matrices.left : m_custom_matrices.right);
}
std::map<std::string, std::string> stereo_config::convert_matrix(const mat3f& mat)
{
std::map<std::string, std::string> values {};
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
values[fmt::format("%d%d", i, j)] = fmt::format("%f", mat[i].rgb[j]);
}
}
return values;
}
-79
View File
@@ -1,79 +0,0 @@
#pragma once
#include "geometry.h"
#include "Emu/system_config_types.h"
#include "util/atomic.hpp"
#include "Utilities/StrFmt.h"
#include "Utilities/StrUtil.h"
#include <map>
#include <mutex>
struct stereo_config
{
public:
struct stereo_matrices
{
stereo_matrices() = default;
stereo_matrices(const std::array<color3_base<f32>, 3>& l, const std::array<color3_base<f32>, 3>& r);
mat3f left {};
mat3f right {};
};
stereo_config(bool in_emulation) : m_in_emulation(in_emulation) {}
void set_stereo_mode(stereo_render_mode_options mode) { m_stereo_mode = mode; }
stereo_render_mode_options stereo_mode() const { return m_stereo_mode; }
const stereo_matrices& matrices() const;
void update_from_config(bool stereo_enabled);
void set_custom_matrices(const stereo_matrices& matrices) { m_custom_matrices = matrices; }
static void set_live_matrices(const stereo_matrices& matrices) { m_live_matrices = matrices; }
std::map<std::string, std::string> get_custom_matrix(bool is_left) const;
template <typename T>
static void convert_matrix(mat3f& mat, const T& values)
{
mat[0] = {};
mat[1] = {};
mat[2] = {};
if (values.empty())
{
return;
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
const std::string key = fmt::format("%d%d", i, j);
const auto it = values.find(key);
if (it == values.cend()) continue;
const std::string& val_s = it->second;
if (val_s.empty()) continue;
if (f64 val = 0.0f; try_to_float(&val, val_s, -10.0f, 10.0f))
{
mat[i].rgb[j] = static_cast<f32>(val);
}
}
}
}
static std::map<std::string, std::string> convert_matrix(const mat3f& mat);
static atomic_t<bool> s_live_preview_enabled;
private:
stereo_matrices m_custom_matrices {};
stereo_render_mode_options m_stereo_mode = stereo_render_mode_options::disabled;
bool m_in_emulation = false;
static stereo_matrices m_live_matrices;
static const std::unordered_map<stereo_render_mode_options, stereo_matrices> m_matrices;
};
+1 -1
View File
@@ -74,7 +74,7 @@ enum
};
#endif
inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* timeout = nullptr, [[maybe_unused]] uint mask = 0)
inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* timeout = nullptr, uint mask = 0)
{
#ifdef __linux__
return syscall(SYS_futex, uaddr, futex_op, static_cast<int>(val), timeout, nullptr, static_cast<int>(mask));
@@ -349,24 +349,24 @@ QPushButton:disabled {
}
QDialog QDialogButtonBox QPushButton:default {
QDialog QDialogButtonBox QPushButton {
color: #000000;
background-color: #4CC2FF;
border-color: #5AC7FF;
}
QDialog QDialogButtonBox QPushButton:default:hover {
QDialog QDialogButtonBox QPushButton:hover {
background-color: #48B2E9;
border-color: #56B8EB;
}
QDialog QDialogButtonBox QPushButton:default:pressed {
QDialog QDialogButtonBox QPushButton:pressed {
color: #22526A;
background-color: #45A4D5;
border-color: #45A4D5;
}
QDialog QDialogButtonBox QPushButton:default:disabled {
QDialog QDialogButtonBox QPushButton:disabled {
color: #ABABAB;
background-color: #4C4C4C;
border-color: #4C4C4C;
@@ -614,15 +614,10 @@ QComboBox QAbstractItemView {
QComboBox QAbstractItemView::item {
color: #FFFFFF;
padding: 4px 6px;
margin: 2px 0px;
background-color: transparent;
border-radius: 4px;
}
QComboBox QAbstractItemView::item:hover {
background-color: #383838;
}
QComboBox QAbstractItemView::item:selected {
background-color: #383838;
}
@@ -647,7 +642,7 @@ QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
border-radius: 4px;
width: 8px;
height: 8px;
padding: 3px 4px;
padding: 3px 4px;
}
QSpinBox::up-button:hover, QSpinBox::down-button:hover,
@@ -714,16 +709,6 @@ QSlider::handle:horizontal:disabled {
image: url("GuiConfigs/dark/slider-handle-disabled.svg");
}
QSlider::sub-page:horizontal {
background-color: #4CC2FF;
border-radius: 2px;
height: 4px;
}
QSlider::sub-page:horizontal:disabled {
background-color: #767A7D;
}
/* LINE EDIT */
QLineEdit {
@@ -806,7 +791,7 @@ QMenuBar::item:pressed {
QMenu {
background-color: #2C2C2C;
border: 1px solid #3E3E3E;
border: 1px solid #131313;
padding: 4px 0px;
}
@@ -814,12 +799,12 @@ QMenu::item {
color: #FFFFFF;
background-color: transparent;
border-radius: 4px;
padding: 4px 20px;
padding: 8px 20px;
margin: 0px 4px;
}
QMenu::item:selected {
background-color: #353535;
background-color: #383838;
}
QMenu::item:disabled {
@@ -829,8 +814,8 @@ QMenu::item:disabled {
QMenu::separator {
height: 1px;
background: #3E3E3E;
margin: 4px 8px;
background: #131313;
margin: 4px 0px;
}
QMenu::indicator, QMenu::right-arrow {
@@ -349,24 +349,24 @@ QPushButton:disabled {
}
QDialog QDialogButtonBox QPushButton:default {
QDialog QDialogButtonBox QPushButton {
color: #FFFFFF;
background-color: #0067C0;
border-color: #1473C5;
}
QDialog QDialogButtonBox QPushButton:default:hover {
QDialog QDialogButtonBox QPushButton:hover {
background-color: #1A76C6;
border-color: #2C80CA;
}
QDialog QDialogButtonBox QPushButton:default:pressed {
QDialog QDialogButtonBox QPushButton:pressed {
color: #C2DAEF;
background-color: #3284CB;
border-color: #3284CB;
}
QDialog QDialogButtonBox QPushButton:default:disabled {
QDialog QDialogButtonBox QPushButton:disabled {
color: #FFFFFF;
background-color: #C5C5C5;
border-color: #C5C5C5;
@@ -614,15 +614,10 @@ QComboBox QAbstractItemView {
QComboBox QAbstractItemView::item {
color: #1B1B1B;
padding: 4px 6px;
margin: 2px 0px;
background-color: transparent;
border-radius: 4px;
}
QComboBox QAbstractItemView::item:hover {
background-color: #F0F0F0;
}
QComboBox QAbstractItemView::item:selected {
background-color: #F0F0F0;
}
@@ -647,7 +642,7 @@ QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
border-radius: 4px;
width: 8px;
height: 8px;
padding: 3px 4px;
padding: 3px 4px;
}
QSpinBox::up-button:hover, QSpinBox::down-button:hover,
@@ -714,16 +709,6 @@ QSlider::handle:horizontal:disabled {
image: url("GuiConfigs/light/slider-handle-disabled.svg");
}
QSlider::sub-page:horizontal {
background-color: #1A76C6;
border-radius: 2px;
height: 4px;
}
QSlider::sub-page:horizontal:disabled {
background-color: #868788;
}
/* LINE EDIT */
QLineEdit {
@@ -806,7 +791,7 @@ QMenuBar::item:pressed {
QMenu {
background-color: #F9F9F9;
border: 1px solid #E5E5E5;
border: 1px solid #EEEEEE;
padding: 4px 0px;
}
@@ -814,7 +799,7 @@ QMenu::item {
color: #1B1B1B;
background-color: transparent;
border-radius: 4px;
padding: 4px 20px;
padding: 8px 20px;
margin: 0px 4px;
}
@@ -829,8 +814,8 @@ QMenu::item:disabled {
QMenu::separator {
height: 1px;
background: #E5E5E5;
margin: 4px 8px;
background: #EEEEEE;
margin: 4px 0px;
}
QMenu::indicator, QMenu::right-arrow {
-3
View File
@@ -3,9 +3,6 @@
<!-- Common default props for defining properties without macros. Import right before Microsoft.Cpp.Default.props -->
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<EnableLibUsbWindowsHotplug>true</EnableLibUsbWindowsHotplug>
</PropertyGroup>
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
-2
View File
@@ -9,8 +9,6 @@
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
<GTestPath>$(SolutionDir)packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.8\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.targets</GTestPath>
<GTestInstalled Condition="Exists('$(GTestPath)')">true</GTestInstalled>
<OpenCvBuildDir>$(SolutionDir)3rdparty\opencv\opencv\opencv413\build</OpenCvBuildDir>
<OpenCvWorld>opencv_world4130</OpenCvWorld>
</PropertyGroup>
<ItemDefinitionGroup>
<Lib>
+1
View File
@@ -2,6 +2,7 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<Optimization>Full</Optimization>
-2
View File
@@ -182,13 +182,11 @@ if(BUILD_RPCS3_TESTS)
target_sources(rpcs3_test
PRIVATE
tests/test.cpp
tests/test_bit_set.cpp
tests/test_fmt.cpp
tests/test_pair.cpp
tests/test_tuple.cpp
tests/test_simple_array.cpp
tests/test_address_range.cpp
tests/test_sys_fs.cpp
tests/test_rsx_cfg.cpp
tests/test_rsx_fp_asm.cpp
tests/test_dmux_pamf.cpp
+1 -2
View File
@@ -807,8 +807,7 @@ bool package_reader::set_install_path()
}
// TODO: Verify whether other content types require appending title ID
// Append title ID depending on content type
if (m_metadata.content_type != PKG_CONTENT_TYPE_THEME && m_metadata.content_type != PKG_CONTENT_TYPE_LICENSE)
if (m_metadata.content_type != PKG_CONTENT_TYPE_LICENSE)
dir += m_install_dir + '/';
// If false, an existing directory is being overwritten: cannot cancel the operation
+2 -2
View File
@@ -126,7 +126,7 @@ struct PKGEntry
struct PKGMetaData
{
private:
static std::string to_hex_string(const u8* buf, usz size)
static std::string to_hex_string(u8 buf[], usz size)
{
std::stringstream sstream;
for (usz i = 0; i < size; i++)
@@ -135,7 +135,7 @@ private:
}
return sstream.str();
}
static std::string to_hex_string(const u8* buf, usz size, usz dotpos)
static std::string to_hex_string(u8 buf[], usz size, usz dotpos)
{
std::string result = to_hex_string(buf, size);
if (result.size() > dotpos)
+7 -19
View File
@@ -807,8 +807,6 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
self_f.seek(0);
sce_hdr.Load(self_f);
const usz self_size = self_f.size();
if (out_info)
{
*out_info = {};
@@ -882,9 +880,8 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
for(u32 i = 0; i < (isElf32 ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
{
if (self_f.pos() >= self_size)
if (self_f.pos() >= self_f.size())
{
// Read out of bounds (file is truncated or corrupted)
return false;
}
@@ -892,23 +889,15 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
m_seg_ext_hdr.back().Load(self_f);
}
if (m_ext_hdr.version_hdr_offset == 0)
if (m_ext_hdr.version_hdr_offset == 0 || utils::add_saturate<u64>(m_ext_hdr.version_hdr_offset, sizeof(version_header)) > self_f.size())
{
// 0.85 Selfs have version_hdr_offset set to 0
m_version_hdr = {};
}
else if (utils::add_saturate<u64>(m_ext_hdr.version_hdr_offset, sizeof(version_header)) > self_size)
{
// Read out of bounds (file is truncated or corrupted)
return false;
}
else
{
// Read SCE version info.
self_f.seek(m_ext_hdr.version_hdr_offset);
m_version_hdr.Load(self_f);
}
// Read SCE version info.
self_f.seek(m_ext_hdr.version_hdr_offset);
m_version_hdr.Load(self_f);
// Read control info.
m_supplemental_hdr_arr.clear();
@@ -916,9 +905,8 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
for (u64 i = 0; i < m_ext_hdr.supplemental_hdr_size;)
{
if (self_f.pos() >= self_size)
if (self_f.pos() >= self_f.size())
{
// Read out of bounds (file is truncated or corrupted)
return false;
}
+1 -26
View File
@@ -23,32 +23,7 @@
// Auxiliary functions (endian swap, xor).
// Bytes conversion auxiliary function.
void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int data_length)
{
size_t str_length = data_length * 2;
hex_str.resize(str_length);
for (size_t i = 0; i < str_length; i += 2)
{
const auto [ptr, err] = std::to_chars(hex_str.data() + i, hex_str.data() + i + 2, *data++, 16);
if (err != std::errc())
{
fmt::throw_exception("Failed to read bytes: %s", std::make_error_code(err).message());
}
// Padding handling for values < 0x10 (e.g. 0x05 becomes "5" instead of "05")
// If to_chars only writes 1 character, we move to the right and put '0'
if (ptr == &hex_str[i] + 1)
{
hex_str[i + 1] = hex_str[i];
hex_str[i] = '0';
}
}
}
// Hex string conversion auxiliary function.
// Hex string conversion auxiliary functions.
void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length)
{
const auto strn_length = (str_length > 0) ? str_length : hex_str.size();
+1 -4
View File
@@ -15,10 +15,7 @@ char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PA
std::string sha256_get_hash(const char* data, usz size, bool lower_case);
// Bytes conversion auxiliary function.
void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int data_length);
// Hex string conversion auxiliary function.
// Hex string conversion auxiliary functions.
void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length);
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
+68 -208
View File
@@ -13,112 +13,82 @@ LOG_CHANNEL(FAudio_, "FAudio");
FAudioBackend::FAudioBackend()
: AudioBackend()
{
FAudio *instance = nullptr;
FAudio *instance;
const u32 res = FAudioCreate(&instance, 0, FAUDIO_DEFAULT_PROCESSOR);
if (res != 0)
if (u32 res = FAudioCreate(&instance, 0, FAUDIO_DEFAULT_PROCESSOR))
{
FAudio_.error("FAudioCreate() failed with error code 0x%08x", res);
FAudio_.error("FAudioCreate() failed(0x%08x)", res);
return;
}
if (!instance)
{
FAudio_.error("FAudioCreate() succeeded but returned null instance");
return;
}
// Initialize callbacks
OnProcessingPassStart = nullptr;
OnProcessingPassEnd = nullptr;
OnCriticalError = OnCriticalError_func;
const u32 callback_res = FAudio_RegisterForCallbacks(instance, this);
if (callback_res != 0)
if (u32 res = FAudio_RegisterForCallbacks(instance, this))
{
// Some error recovery functionality will be lost, but otherwise backend is operational
FAudio_.warning("FAudio_RegisterForCallbacks() failed with error code 0x%08x - error recovery may be limited", callback_res);
FAudio_.error("FAudio_RegisterForCallbacks() failed(0x%08x)", res);
}
// All succeeded, commit the instance
// All succeeded, "commit"
m_instance = instance;
FAudio_.success("FAudio backend initialized successfully");
}
FAudioBackend::~FAudioBackend()
{
Close();
if (m_instance)
if (m_instance != nullptr)
{
// Unregister callbacks before stopping engine
FAudio_UnregisterForCallbacks(m_instance, this);
FAudio_StopEngine(m_instance);
FAudio_Release(m_instance);
m_instance = nullptr;
}
FAudio_.notice("FAudio backend destroyed successfully");
}
void FAudioBackend::Play()
{
if (!m_source_voice)
if (m_source_voice == nullptr)
{
FAudio_.error("Play() called with uninitialized source voice");
FAudio_.error("Play() called uninitialized");
return;
}
if (m_playing) return;
std::lock_guard lock(m_cb_mutex);
if (!m_playing)
{
m_playing = true;
FAudio_.trace("Audio playback started");
}
m_playing = true;
}
void FAudioBackend::Pause()
{
if (!m_source_voice)
if (m_source_voice == nullptr)
{
FAudio_.error("Pause() called with uninitialized source voice");
FAudio_.error("Pause() called uninitialized");
return;
}
bool was_playing = false;
if (!m_playing) return;
{
std::lock_guard lock(m_cb_mutex);
was_playing = m_playing;
if (m_playing)
{
m_playing = false;
m_last_sample.fill(0);
}
m_playing = false;
m_last_sample.fill(0);
}
if (was_playing)
if (u32 res = FAudioSourceVoice_FlushSourceBuffers(m_source_voice))
{
const u32 res = FAudioSourceVoice_FlushSourceBuffers(m_source_voice);
if (res != 0)
{
FAudio_.error("FAudioSourceVoice_FlushSourceBuffers() failed with error code 0x%08x", res);
}
else
{
FAudio_.trace("Audio playback paused and buffers flushed");
}
FAudio_.error("FAudioSourceVoice_FlushSourceBuffers() failed(0x%08x)", res);
}
}
void FAudioBackend::CloseUnlocked()
{
if (m_source_voice)
if (m_source_voice != nullptr)
{
const u32 stop_res = FAudioSourceVoice_Stop(m_source_voice, 0, FAUDIO_COMMIT_NOW);
if (stop_res != 0)
if (u32 res = FAudioSourceVoice_Stop(m_source_voice, 0, FAUDIO_COMMIT_NOW))
{
FAudio_.error("FAudioSourceVoice_Stop() failed with error code 0x%08x", stop_res);
FAudio_.error("FAudioSourceVoice_Stop() failed(0x%08x)", res);
}
FAudioVoice_DestroyVoice(m_source_voice);
@@ -133,10 +103,6 @@ void FAudioBackend::CloseUnlocked()
m_playing = false;
m_last_sample.fill(0);
m_data_buf.clear();
m_data_buf.shrink_to_fit(); // Free memory
FAudio_.trace("FAudio voices and resources cleaned up");
}
void FAudioBackend::Close()
@@ -152,41 +118,34 @@ bool FAudioBackend::Initialized()
bool FAudioBackend::Operational()
{
return m_source_voice != nullptr && m_instance != nullptr && !m_reset_req.observe();
return m_source_voice != nullptr && !m_reset_req.observe();
}
bool FAudioBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt, audio_channel_layout layout)
{
if (!Initialized())
{
FAudio_.error("Open() called on uninitialized backend");
FAudio_.error("Open() called uninitialized");
return false;
}
FAudio_.notice("Opening FAudio device: dev_id='%s', freq=%u, sample_size=%u, channels=%u",
dev_id.empty() ? "default" : std::string(dev_id).c_str(),
static_cast<u32>(freq), static_cast<u32>(sample_size), static_cast<u32>(ch_cnt));
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
const bool use_default_dev = dev_id.empty() || dev_id == audio_device_enumerator::DEFAULT_DEV_ID;
u64 devid = 0;
u64 devid{};
if (!use_default_dev)
{
if (!try_to_uint64(&devid, dev_id, 0, UINT32_MAX))
{
FAudio_.error("Invalid device ID format: '%s'", dev_id);
FAudio_.error("Invalid device id - %s", dev_id);
return false;
}
}
const u32 master_res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice,
FAUDIO_DEFAULT_CHANNELS, FAUDIO_DEFAULT_SAMPLERATE, 0, static_cast<u32>(devid), nullptr);
if (master_res != 0)
if (u32 res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, FAUDIO_DEFAULT_CHANNELS, FAUDIO_DEFAULT_SAMPLERATE, 0, static_cast<u32>(devid), nullptr))
{
FAudio_.error("FAudio_CreateMasteringVoice() failed with error code 0x%08x", master_res);
FAudio_.error("FAudio_CreateMasteringVoice() failed(0x%08x)", res);
m_master_voice = nullptr;
return false;
}
@@ -196,22 +155,19 @@ bool FAudioBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSiz
if (vd.InputChannels == 0)
{
FAudio_.error("Master voice reports invalid channel count of 0");
FAudio_.error("Channel count of 0 is invalid");
CloseUnlocked();
return false;
}
FAudio_.notice("Master voice created with %u input channels", vd.InputChannels);
FAudio_.notice("Channel count is %d", vd.InputChannels);
// Store audio parameters
m_sampling_rate = freq;
m_sample_size = sample_size;
// Setup channel layout with validation
setup_channel_layout(static_cast<u32>(ch_cnt), vd.InputChannels, layout, FAudio_);
// Configure wave format
FAudioWaveFormatEx waveformatex{};
FAudioWaveFormatEx waveformatex;
waveformatex.wFormatTag = get_convert_to_s16() ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = get_channels();
waveformatex.nSamplesPerSec = get_sampling_rate();
@@ -220,11 +176,6 @@ bool FAudioBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSiz
waveformatex.wBitsPerSample = get_sample_size() * 8;
waveformatex.cbSize = 0;
FAudio_.trace("Wave format: %s, %u channels, %u Hz, %u bits per sample",
get_convert_to_s16() ? "PCM" : "IEEE_FLOAT",
waveformatex.nChannels, waveformatex.nSamplesPerSec, waveformatex.wBitsPerSample);
// Initialize voice callbacks
OnVoiceProcessingPassStart = OnVoiceProcessingPassStart_func;
OnVoiceProcessingPassEnd = nullptr;
OnStreamEnd = nullptr;
@@ -233,183 +184,92 @@ bool FAudioBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSiz
OnLoopEnd = nullptr;
OnVoiceError = nullptr;
const u32 source_res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex,
0, FAUDIO_DEFAULT_FREQ_RATIO, this, nullptr, nullptr);
if (source_res != 0)
if (u32 res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex, 0, FAUDIO_DEFAULT_FREQ_RATIO, this, nullptr, nullptr))
{
FAudio_.error("FAudio_CreateSourceVoice() failed with error code 0x%08x", source_res);
FAudio_.error("FAudio_CreateSourceVoice() failed(0x%08x)", res);
CloseUnlocked();
return false;
}
const u32 start_res = FAudioSourceVoice_Start(m_source_voice, 0, FAUDIO_COMMIT_NOW);
if (start_res != 0)
if (u32 res = FAudioSourceVoice_Start(m_source_voice, 0, FAUDIO_COMMIT_NOW))
{
FAudio_.error("FAudioSourceVoice_Start() failed with error code 0x%08x", start_res);
FAudio_.error("FAudioSourceVoice_Start() failed(0x%08x)", res);
CloseUnlocked();
return false;
}
const u32 volume_res = FAudioVoice_SetVolume(m_source_voice, 1.0f, FAUDIO_COMMIT_NOW);
if (volume_res != 0)
if (u32 res = FAudioVoice_SetVolume(m_source_voice, 1.0f, FAUDIO_COMMIT_NOW))
{
FAudio_.warning("FAudioVoice_SetVolume() failed with error code 0x%08x", volume_res);
FAudio_.error("FAudioVoice_SetVolume() failed(0x%08x)", res);
}
// Pre-allocate audio buffer with some safety margin
const usz buffer_size = static_cast<usz>(get_sampling_rate()) * get_sample_size() * get_channels() * INTERNAL_BUF_SIZE_MS / 1000;
m_data_buf.reserve(buffer_size + 1024); // Extra safety margin
m_data_buf.resize(buffer_size);
FAudio_.success("FAudio device opened successfully - %u Hz, %u channels, %u-bit %s",
get_sampling_rate(), get_channels(), get_sample_size() * 8,
get_convert_to_s16() ? "PCM" : "float");
m_data_buf.resize(get_sampling_rate() * get_sample_size() * get_channels() * INTERNAL_BUF_SIZE_MS / 1000);
return true;
}
f64 FAudioBackend::GetCallbackFrameLen()
{
constexpr f64 fallback_10ms = 0.01;
constexpr f64 _10ms = 0.01;
if (!m_instance)
if (m_instance == nullptr)
{
FAudio_.error("GetCallbackFrameLen() called on uninitialized instance");
return fallback_10ms;
FAudio_.error("GetCallbackFrameLen() called uninitialized");
return _10ms;
}
u32 samples_per_quantum = 0;
u32 frequency = 0;
FAudio_GetProcessingQuantum(m_instance, &samples_per_quantum, &frequency);
f64 min_latency{};
if (frequency == 0 || samples_per_quantum == 0)
u32 samples_per_q = 0, freq = 0;
FAudio_GetProcessingQuantum(m_instance, &samples_per_q, &freq);
if (freq)
{
FAudio_.warning("Invalid processing quantum values: samples=%u, freq=%u", samples_per_quantum, frequency);
return fallback_10ms;
min_latency = static_cast<f64>(samples_per_q) / freq;
}
const f64 calculated_latency = static_cast<f64>(samples_per_quantum) / frequency;
const f64 final_latency = std::max(calculated_latency, fallback_10ms);
FAudio_.trace("Calculated frame length: %.3f ms (quantum: %u samples @ %u Hz)",
final_latency * 1000.0, samples_per_quantum, frequency);
return final_latency;
return std::max<f64>(min_latency, _10ms);
}
void FAudioBackend::OnVoiceProcessingPassStart_func(FAudioVoiceCallback *cb_obj, u32 BytesRequired)
{
if (!cb_obj || BytesRequired == 0)
{
return; // Nothing to do
}
FAudioBackend *faudio = static_cast<FAudioBackend *>(cb_obj);
// Validate backend state
if (!faudio->m_source_voice || faudio->m_reset_req.observe())
{
return; // Backend is in invalid state
}
// Use a shorter timeout to avoid blocking the audio thread
std::unique_lock lock(faudio->m_cb_mutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::microseconds{100}))
if (BytesRequired && !faudio->m_reset_req.observe() && lock.try_lock_for(std::chrono::microseconds{50}) && faudio->m_write_callback && faudio->m_playing)
{
return; // Could not acquire lock in reasonable time
}
ensure(BytesRequired <= faudio->m_data_buf.size(), "FAudio internal buffer is too small. Report to developers!");
// Double-check state after acquiring lock
if (!faudio->m_write_callback || !faudio->m_playing)
{
return; // No callback or not playing
}
const u32 sample_size = faudio->get_sample_size() * faudio->get_channels();
u32 written = std::min(faudio->m_write_callback(BytesRequired, faudio->m_data_buf.data()), BytesRequired);
written -= written % sample_size;
// Validate buffer size
if (BytesRequired > faudio->m_data_buf.size())
{
// This should never happen with proper initialization, but let's be safe
FAudio_.error("FAudio internal buffer is too small (%u requested, %zu available). Report to developers!",
BytesRequired, faudio->m_data_buf.size());
return;
}
const u32 sample_size = faudio->get_sample_size() * faudio->get_channels();
if (sample_size == 0)
{
return; // Invalid configuration
}
// Get audio data from callback
u32 written = 0;
if (faudio->m_write_callback)
{
written = faudio->m_write_callback(BytesRequired, faudio->m_data_buf.data());
written = std::min(written, BytesRequired);
written -= written % sample_size; // Align to sample boundary
}
// Update last sample for padding if we got any data
if (written >= sample_size)
{
const usz last_sample_offset = written - sample_size;
if (last_sample_offset + sample_size <= faudio->m_data_buf.size())
if (written >= sample_size)
{
std::memcpy(faudio->m_last_sample.data(),
faudio->m_data_buf.data() + last_sample_offset,
std::min(sample_size, static_cast<u32>(faudio->m_last_sample.size())));
memcpy(faudio->m_last_sample.data(), faudio->m_data_buf.data() + written - sample_size, sample_size);
}
}
// Pad remaining buffer with last sample to avoid audio glitches
for (u32 i = written; i < BytesRequired; i += sample_size)
{
const u32 copy_size = std::min(sample_size, BytesRequired - i);
if (i + copy_size <= faudio->m_data_buf.size())
for (u32 i = written; i < BytesRequired; i += sample_size)
{
std::memcpy(faudio->m_data_buf.data() + i, faudio->m_last_sample.data(), copy_size);
memcpy(faudio->m_data_buf.data() + i, faudio->m_last_sample.data(), sample_size);
}
FAudioBuffer buffer{};
buffer.AudioBytes = BytesRequired;
buffer.pAudioData = static_cast<const u8*>(faudio->m_data_buf.data());
// Avoid logging in callback and assume that this always succeeds, all errors are caught by error callback anyway
FAudioSourceVoice_SubmitSourceBuffer(faudio->m_source_voice, &buffer, nullptr);
}
// Submit buffer to FAudio
FAudioBuffer buffer{};
buffer.AudioBytes = BytesRequired;
buffer.pAudioData = static_cast<const u8*>(faudio->m_data_buf.data());
buffer.Flags = 0;
buffer.PlayBegin = 0;
buffer.PlayLength = 0;
buffer.LoopBegin = 0;
buffer.LoopLength = 0;
buffer.LoopCount = 0;
buffer.pContext = nullptr;
// Submit buffer - errors are handled by the error callback
FAudioSourceVoice_SubmitSourceBuffer(faudio->m_source_voice, &buffer, nullptr);
}
void FAudioBackend::OnCriticalError_func(FAudioEngineCallback *cb_obj, u32 Error)
{
// Log the critical error
FAudio_.error("OnCriticalError() - FAudio engine encountered critical error 0x%08x", Error);
if (!cb_obj)
{
FAudio_.error("OnCriticalError() called with null callback object");
return;
}
FAudio_.error("OnCriticalError() failed(0x%08x)", Error);
FAudioBackend *faudio = static_cast<FAudioBackend *>(cb_obj);
// Use try_lock to avoid potential deadlock in error conditions
std::unique_lock lock(faudio->m_state_cb_mutex, std::try_to_lock);
if (!lock.owns_lock())
{
FAudio_.warning("Could not acquire state callback mutex during critical error handling");
return;
}
// Set reset request flag and notify application if we haven't already
std::lock_guard lock(faudio->m_state_cb_mutex);
if (!faudio->m_reset_req.test_and_set() && faudio->m_state_callback)
{
faudio->m_state_callback(AudioStateEvent::UNSPECIFIED_ERROR);
+1 -14
View File
@@ -77,7 +77,6 @@ target_sources(rpcs3_emu PRIVATE
../../Utilities/sema.cpp
../../Utilities/simple_ringbuf.cpp
../../Utilities/stack_trace.cpp
../../Utilities/stereo_config.cpp
../../Utilities/StrFmt.cpp
../../Utilities/Thread.cpp
../../Utilities/version.cpp
@@ -127,8 +126,6 @@ target_sources(rpcs3_emu PRIVATE
../Loader/PUP.cpp
../Loader/TAR.cpp
../Loader/ISO.cpp
../Loader/iso_cache.cpp
../Loader/iso_validation.cpp
../Loader/TROPUSR.cpp
../Loader/TRP.cpp
)
@@ -163,7 +160,7 @@ if(WIN32)
Audio/XAudio2/xaudio2_enumerator.cpp
)
target_compile_definitions(rpcs3_emu PRIVATE UNICODE _UNICODE _WIN32_WINNT=0x0A00)
target_link_libraries(rpcs3_emu PRIVATE pdh bcrypt dbghelp)
target_link_libraries(rpcs3_emu PRIVATE pdh bcrypt)
endif()
# Cell
@@ -336,17 +333,9 @@ target_sources(rpcs3_emu PRIVATE
Cell/Modules/HLE_PATCHES.cpp
Cell/Modules/libad_async.cpp
Cell/Modules/libad_core.cpp
Cell/Modules/libavcdec.cpp
Cell/Modules/libdivx311dec.cpp
Cell/Modules/libdivxdec.cpp
Cell/Modules/libmedi.cpp
Cell/Modules/libmixer.cpp
Cell/Modules/libmvcdec.cpp
Cell/Modules/libsjvtd.cpp
Cell/Modules/libsmvd2.cpp
Cell/Modules/libsmvd4.cpp
Cell/Modules/libsnd3.cpp
Cell/Modules/libsvc1d.cpp
Cell/Modules/libsynth2.cpp
Cell/Modules/sceNp2.cpp
Cell/Modules/sceNpClans.cpp
@@ -410,7 +399,6 @@ target_sources(rpcs3_emu PRIVATE
Io/Dimensions.cpp
Io/evdev_gun_handler.cpp
Io/GameTablet.cpp
Io/gem_config.cpp
Io/GHLtar.cpp
Io/GunCon3.cpp
Io/Infinity.cpp
@@ -552,7 +540,6 @@ target_sources(rpcs3_emu PRIVATE
RSX/Program/GLSLCommon.cpp
RSX/Program/ProgramStateCache.cpp
RSX/Program/program_util.cpp
RSX/Program/ShaderInterpreter.cpp
RSX/Program/SPIRVCommon.cpp
RSX/Program/VertexProgramDecompiler.cpp
RSX/GSFrameBase.cpp
@@ -39,7 +39,7 @@ namespace aarch64
if (head->magic == ESR_CTX_MAGIC)
{
return utils::bless<const aarch64_esr_ctx>(head);
return reinterpret_cast<const aarch64_esr_ctx*>(head);
}
offset += head->size;
+2 -9
View File
@@ -61,7 +61,6 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
case cpu_flag::notify: return "ntf";
case cpu_flag::yield: return "y";
case cpu_flag::preempt: return "PREEMPT";
case cpu_flag::req_exit: return "REQ-EXIT";
case cpu_flag::dbg_global_pause: return "G-PAUSE";
case cpu_flag::dbg_pause: return "PAUSE";
case cpu_flag::dbg_step: return "STEP";
@@ -730,14 +729,8 @@ void cpu_thread::operator()()
{
if (_this)
{
sys_log.warning("CPU Thread '%s' terminated abnormally!", name);
cleanup();
auto log_thread = named_thread("CPU Thread Cleanup Logger", [name = name]()
{
sys_log.warning("CPU Thread '%s' terminated abnormally!", name);
});
log_thread();
}
}
} cleanup;
@@ -1509,7 +1502,7 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
{
for (u32 i = 0; i < work->prf_size; i++)
{
utils::prefetch_write(work->prf_list[i]);
utils::prefetch_write(work->prf_list[0]);
}
}
+27 -65
View File
@@ -207,25 +207,10 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
{
m_use_dotprod = true;
}
if (utils::has_i8mm())
{
m_use_i8mm = true;
}
if (utils::has_sve() && utils::sve_length() == 128)
{
m_use_sve_128 = true;
}
if (utils::has_sve2() && utils::sve_length() == 128)
{
m_use_sve2_128 = true;
}
#endif
}
llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type, std::source_location src_loc) const
llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
{
uint s1 = type->getScalarSizeInBits();
uint s2 = val->getType()->getScalarSizeInBits();
@@ -237,7 +222,7 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type, std::so
if (s1 != s2)
{
fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)\nCalled from: %s", s1, s2, src_loc);
fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)", s1, s2);
}
if (val->getType() == type)
@@ -259,48 +244,36 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type, std::so
}
}
// Skip use iteration for values that don't have use lists
#if LLVM_VERSION_MAJOR >= 21
if (source_val->hasUseList())
#endif
for (auto it = source_val->use_begin(); it != source_val->use_end(); ++it)
{
for (llvm::Value* it_val : source_val->uses())
llvm::Value* it_val = *it;
if (!it_val)
{
if (!it_val)
continue;
}
llvm::CastInst* bci = llvm::dyn_cast_or_null<llvm::CastInst>(it_val);
// Walk through bitcasts
while (bci && bci->getOpcode() == llvm::Instruction::BitCast)
{
if (bci->getParent() != m_ir->GetInsertBlock())
{
continue;
break;
}
llvm::CastInst* bci = llvm::dyn_cast_or_null<llvm::CastInst>(it_val);
// Walk through bitcasts
while (bci && bci->getOpcode() == llvm::Instruction::BitCast)
if (bci->getType() == type)
{
if (bci->getParent() != m_ir->GetInsertBlock())
{
break;
}
if (bci->getType() == type)
{
return bci;
}
// Check if bci has use list before accessing use_begin()
#if LLVM_VERSION_MAJOR >= 21
if (!bci->hasUseList())
{
break;
}
#endif
if (bci->use_begin() == bci->use_end())
{
break;
}
bci = llvm::dyn_cast_or_null<llvm::CastInst>(*bci->use_begin());
return bci;
}
if (bci->use_begin() == bci->use_end())
{
break;
}
bci = llvm::dyn_cast_or_null<llvm::CastInst>(*bci->use_begin());
}
}
@@ -580,25 +553,14 @@ void cpu_translator::erase_stores(llvm::ArrayRef<llvm::Value*> args)
{
for (auto v : args)
{
// Skip use iteration for values that don't have use lists
#if LLVM_VERSION_MAJOR >= 21
if (!v->hasUseList())
continue;
#endif
for (llvm::Value* i : v->uses())
for (auto it = v->use_begin(); it != v->use_end(); ++it)
{
llvm::Value* i = *it;
llvm::CastInst* bci = nullptr;
// Walk through bitcasts
while (i && (bci = llvm::dyn_cast<llvm::CastInst>(i)) && bci->getOpcode() == llvm::Instruction::BitCast)
{
// Check if bci has use list before accessing use_begin()
#if LLVM_VERSION_MAJOR >= 21
if (!bci->hasUseList())
break;
#endif
i = *bci->use_begin();
}
+3 -301
View File
@@ -43,7 +43,6 @@
#include <functional>
#include <unordered_map>
#include <source_location>
// Helper function
llvm::Value* peek_through_bitcasts(llvm::Value*);
@@ -3120,16 +3119,6 @@ protected:
// ARMv8 SDOT/UDOT
bool m_use_dotprod = false;
// ARMv8.6 SMMLA/UMMLA
bool m_use_i8mm = false;
// Allow direct TBL2/TBX2 emission.
bool m_use_tbl2 = true;
bool m_use_sve_128 = false;
bool m_use_sve2_128 = false;
#else
// Allow FMA
bool m_use_fma = false;
@@ -3250,7 +3239,7 @@ public:
}
// Bitcast with immediate constant folding
llvm::Value* bitcast(llvm::Value* val, llvm::Type* type, std::source_location src_loc = std::source_location::current()) const;
llvm::Value* bitcast(llvm::Value* val, llvm::Type* type) const;
template <typename T>
llvm::Value* bitcast(llvm::Value* val)
@@ -3730,170 +3719,8 @@ template <typename T1, typename T2, typename T3>
result.value = m_ir->CreateCall(get_intrinsic<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_sdot), {data0, data1, data2});
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u32[4]> ummla(T1 a, T2 b, T3 c)
{
value_t<u32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_ummla), {data0, data1, data2});
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u32[4]> smmla(T1 a, T2 b, T3 c)
{
value_t<u32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_smmla), {data0, data1, data2});
return result;
}
template <typename T1, typename T2>
value_t<s32[4]> smull(T1 a, T2 b)
{
value_t<s32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<s32[4]>(llvm::Intrinsic::aarch64_neon_smull), {data0, data1});
return result;
}
template <typename T1, typename T2>
value_t<u32[4]> umull(T1 a, T2 b)
{
value_t<u32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u32[4]>(llvm::Intrinsic::aarch64_neon_umull), {data0, data1});
return result;
}
llvm::Value* to_sve_vector(llvm::Value* value)
{
if (llvm::isa<llvm::ScalableVectorType>(value->getType()))
{
return value;
}
const auto fixed_type = llvm::cast<llvm::FixedVectorType>(value->getType());
const auto scalable_type = llvm::ScalableVectorType::get(fixed_type->getElementType(), fixed_type->getNumElements());
return m_ir->CreateInsertVector(scalable_type, llvm::UndefValue::get(scalable_type), value, m_ir->getInt64(0));
}
llvm::Value* from_sve_vector(llvm::Value* value, llvm::FixedVectorType* fixed_type)
{
if (value->getType() == fixed_type)
{
return value;
}
return m_ir->CreateExtractVector(fixed_type, value, m_ir->getInt64(0));
}
llvm::Value* sve_ptrue(llvm::FixedVectorType* fixed_type)
{
const auto pred_type = llvm::ScalableVectorType::get(m_ir->getInt1Ty(), fixed_type->getNumElements());
return m_ir->CreateIntrinsic(llvm::Intrinsic::aarch64_sve_ptrue, {pred_type}, {m_ir->getInt32(31)});
}
llvm::Value* sve_fnmls(llvm::Value* acc, llvm::Value* lhs, llvm::Value* rhs)
{
const auto fixed_type = llvm::cast<llvm::FixedVectorType>(acc->getType());
const auto vacc = to_sve_vector(acc);
const auto vlhs = to_sve_vector(lhs);
const auto vrhs = to_sve_vector(rhs);
const auto result = m_ir->CreateIntrinsic(llvm::Intrinsic::aarch64_sve_fnmls, {vacc->getType()}, {sve_ptrue(fixed_type), vacc, vlhs, vrhs});
return from_sve_vector(result, fixed_type);
}
template <typename T, typename T1, typename T2>
value_t<T> sve_mull(llvm::Intrinsic::ID id, T1 a, T2 b)
{
value_t<T> result;
const auto fixed_type = llvm::cast<llvm::FixedVectorType>(get_type<T>());
const auto scalable_type = llvm::ScalableVectorType::get(fixed_type->getElementType(), fixed_type->getNumElements());
const auto data0 = to_sve_vector(a.eval(m_ir));
const auto data1 = to_sve_vector(b.eval(m_ir));
const std::array<llvm::Type*, 1> types{scalable_type};
result.value = from_sve_vector(m_ir->CreateIntrinsic(id, types, {data0, data1}), fixed_type);
return result;
}
template <typename T, typename T0, typename T1, typename T2>
value_t<T> sve_mlal(llvm::Intrinsic::ID id, T0 acc, T1 a, T2 b)
{
value_t<T> result;
const auto fixed_type = llvm::cast<llvm::FixedVectorType>(get_type<T>());
const auto scalable_type = llvm::ScalableVectorType::get(fixed_type->getElementType(), fixed_type->getNumElements());
const auto data0 = to_sve_vector(acc.eval(m_ir));
const auto data1 = to_sve_vector(a.eval(m_ir));
const auto data2 = to_sve_vector(b.eval(m_ir));
const std::array<llvm::Type*, 1> types{scalable_type};
result.value = from_sve_vector(m_ir->CreateIntrinsic(id, types, {data0, data1, data2}), fixed_type);
return result;
}
template <typename T1, typename T2>
value_t<s32[4]> sve_smullb(T1 a, T2 b)
{
return sve_mull<s32[4]>(llvm::Intrinsic::aarch64_sve_smullb, a, b);
}
template <typename T1, typename T2>
value_t<s32[4]> sve_smullt(T1 a, T2 b)
{
return sve_mull<s32[4]>(llvm::Intrinsic::aarch64_sve_smullt, a, b);
}
template <typename T1, typename T2>
value_t<u32[4]> sve_umullb(T1 a, T2 b)
{
return sve_mull<u32[4]>(llvm::Intrinsic::aarch64_sve_umullb, a, b);
}
template <typename T1, typename T2>
value_t<u32[4]> sve_umullt(T1 a, T2 b)
{
return sve_mull<u32[4]>(llvm::Intrinsic::aarch64_sve_umullt, a, b);
}
template <typename T0, typename T1, typename T2>
value_t<s32[4]> sve_smlalb(T0 acc, T1 a, T2 b)
{
return sve_mlal<s32[4]>(llvm::Intrinsic::aarch64_sve_smlalb, acc, a, b);
}
template <typename T0, typename T1, typename T2>
value_t<s32[4]> sve_smlalt(T0 acc, T1 a, T2 b)
{
return sve_mlal<s32[4]>(llvm::Intrinsic::aarch64_sve_smlalt, acc, a, b);
}
template <typename T0, typename T1, typename T2>
value_t<u32[4]> sve_umlalt(T0 acc, T1 a, T2 b)
{
return sve_mlal<u32[4]>(llvm::Intrinsic::aarch64_sve_umlalt, acc, a, b);
}
template <typename T1, typename T2>
template <typename T1, typename T2>
auto addp(T1 a, T2 b)
{
using T_vector = typename is_llvm_expr<T1>::type;
@@ -4202,131 +4029,6 @@ public:
});
}
#ifdef ARCH_ARM64
template <typename T1, typename T2>
value_t<u8[16]> tbl(T1 a, T2 b)
{
value_t<u8[16]> result;
const auto data0 = a.eval(m_ir);
const auto index = b.eval(m_ir);
const auto zeros = llvm::ConstantAggregateZero::get(get_type<u8[16]>());
if (auto c = llvm::dyn_cast<llvm::Constant>(index))
{
v128 mask{};
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
if (cv)
{
for (u32 i = 0; i < 16; i++)
{
const u64 b_val = cv->getElementAsInteger(i);
mask._u8[i] = (b_val < 16) ? static_cast<u8>(b_val) : static_cast<u8>(16);
}
}
if (cv || llvm::isa<llvm::ConstantAggregateZero>(c))
{
result.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(reinterpret_cast<const u8*>(&mask), 16));
result.value = m_ir->CreateZExt(result.value, get_type<u32[16]>());
result.value = m_ir->CreateShuffleVector(data0, zeros, result.value);
return result;
}
}
result.value = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbl1), { data0, index });
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u8[16]> tbl2(T1 a, T2 b, T3 indices)
{
value_t<u8[16]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto index = indices.eval(m_ir);
if (m_use_tbl2)
{
if (auto c = llvm::dyn_cast<llvm::Constant>(index))
{
v128 mask{};
v128 bitmask{};
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
if (cv)
{
for (u32 i = 0; i < 16; i++)
{
const u64 b_val = cv->getElementAsInteger(i);
mask._u8[i] = (b_val < 32) ? static_cast<u8>(b_val) : static_cast<u8>(0);
bitmask._u8[i] = (b_val < 32) ? static_cast<u8>(0xFF) : static_cast<u8>(0x00);
}
}
else if (llvm::isa<llvm::ConstantAggregateZero>(c))
{
bitmask = v128::from8p(0xFF);
}
if (cv || llvm::isa<llvm::ConstantAggregateZero>(c))
{
auto m_val = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(reinterpret_cast<const u8*>(&mask), 16));
auto m_ext = m_ir->CreateZExt(m_val, get_type<u32[16]>());
auto lookup = m_ir->CreateShuffleVector(data0, data1, m_ext);
auto z_mask = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(reinterpret_cast<const u8*>(&bitmask), 16));
result.value = m_ir->CreateAnd(lookup, z_mask);
return result;
}
}
result.value = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbl2), { data0, data1, index });
return result;
}
const auto data0_lookup = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbl1), { data0, index });
const auto data1_index = m_ir->CreateSub(index, llvm::ConstantInt::get(get_type<u8[16]>(), 16));
const auto data1_lookup = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbl1), { data1, data1_index });
result.value = m_ir->CreateOr(data0_lookup, data1_lookup);
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u8[16]> tbx(T1 fallback, T2 a, T3 indices)
{
value_t<u8[16]> result;
const auto v_fallback = fallback.eval(m_ir);
const auto data0 = a.eval(m_ir);
const auto index = indices.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbx1), { v_fallback, data0, index });
return result;
}
template <typename T1, typename T2, typename T3, typename T4>
value_t<u8[16]> tbx2(T1 fallback, T2 a, T3 b, T4 indices)
{
value_t<u8[16]> result;
const auto v_fallback = fallback.eval(m_ir);
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto index = indices.eval(m_ir);
if (m_use_tbl2)
{
result.value = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbx2), { v_fallback, data0, data1, index });
return result;
}
const auto first_lookup = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbx1), { v_fallback, data0, index });
const auto data1_index = m_ir->CreateSub(index, llvm::ConstantInt::get(get_type<u8[16]>(), 16));
result.value = m_ir->CreateCall(get_intrinsic<u8[16]>(llvm::Intrinsic::aarch64_neon_tbx1), { first_lookup, data1, data1_index });
return result;
}
#endif
// (m << 3) >= 0 ? a : b
template <typename T, typename U, typename V>
static auto select_by_bit4(T&& m, U&& a, V&& b)
+1 -1
View File
@@ -4,7 +4,7 @@
namespace rpcs3
{
#if defined(ARCH_X64)
#if defined(ARCH_x64)
union hypervisor_context_t
{
u64 regs[1];
-2
View File
@@ -81,8 +81,6 @@
#if defined(__GNUC__) || defined(__clang__)
#pragma push_macro("FORCE_INLINE")
#pragma push_macro("ALIGN_STRUCT")
#undef FORCE_INLINE
#undef ALIGN_STRUCT
#define FORCE_INLINE static inline __attribute__((always_inline))
#define ALIGN_STRUCT(x) __attribute__((aligned(x)))
#define _sse2neon_likely(x) __builtin_expect(!!(x), 1)
+27 -27
View File
@@ -398,7 +398,7 @@ cell_audio_thread::cell_audio_thread(utils::serial& ar)
ar(key_count, event_period);
keys.resize(ar.pop<u64>());
keys.resize(ar);
for (key_info& k : keys)
{
@@ -421,7 +421,7 @@ void cell_audio_thread::save(utils::serial& ar)
USING_SERIALIZATION_VERSION(cellAudio);
ar(key_count, event_period);
ar(static_cast<u64>(keys.size()));
ar(keys.size());
for (const key_info& k : keys)
{
@@ -1662,35 +1662,36 @@ error_code AudioSetNotifyEventQueue(ppu_thread& ppu, u64 key, u32 iFlags)
lv2_sleep(20, &ppu);
// Dirty hack for sound: confirm the creation of _mxr000 event queue by _cellsurMixerMain thread
constexpr u64 c_mxr000 = 0x8000cafe02460300;
constexpr u64 c_mxr000 = 0x8000cafe0246030;
if (key == c_mxr000 || key == 0)
{
const bool has_sur_mixer_thread = idm::select<named_thread<ppu_thread>>([&](u32 id, named_thread<ppu_thread>& test_ppu)
bool has_sur_mixer_thread = false;
for (usz count = 0; !lv2_event_queue::find(c_mxr000) && count < 100; count++)
{
// Confirm thread existence
if (id == ppu.id)
if (has_sur_mixer_thread || idm::select<named_thread<ppu_thread>>([&](u32 id, named_thread<ppu_thread>& test_ppu)
{
return false;
// Confirm thread existence
if (id == ppu.id)
{
return false;
}
const auto ptr = test_ppu.ppu_tname.load();
if (!ptr)
{
return false;
}
return *ptr == "_cellsurMixerMain"sv;
}).ret)
{
has_sur_mixer_thread = true;
}
const auto ptr = test_ppu.ppu_tname.load();
if (!ptr)
else
{
return false;
}
return *ptr == "_cellsurMixerMain"sv;
}).ret;
bool was_mxr000_queue_found = false;
for (usz count = 0; has_sur_mixer_thread && count < 100; count++)
{
if (lv2_event_queue::find(c_mxr000))
{
was_mxr000_queue_found = true;
break;
}
@@ -1700,14 +1701,13 @@ error_code AudioSetNotifyEventQueue(ppu_thread& ppu, u64 key, u32 iFlags)
return {};
}
(count < 3 ? cellAudio.warning : cellAudio.error)("AudioSetNotifyEventQueue(): Waiting for _mxr000. x%d", count);
cellAudio.error("AudioSetNotifyEventQueue(): Waiting for _mxr000. x%d", count);
lv2_sleep(50'000, &ppu);
}
if (key == 0 && was_mxr000_queue_found)
if (has_sur_mixer_thread && lv2_event_queue::find(c_mxr000))
{
// Correct key value argument
key = c_mxr000;
}
}
+10 -2
View File
@@ -524,11 +524,19 @@ error_code cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
{
// Return Playstation 3D display value
// Some games call this function when 3D is enabled
*screenSize = static_cast<f32>(g_cfg.video.screen_size.get());
*screenSize = 24.f;
return CELL_OK;
}
// Let's just return not set for now
// TODO: Use virtual screen size
#ifdef _WIN32
// HDC screen = GetDC(NULL);
// float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
#else
// TODO: Linux implementation, without using wx
// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f);
#endif
return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET;
}
File diff suppressed because it is too large Load Diff
+31 -91
View File
@@ -1,8 +1,7 @@
#pragma once
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Utilities/BitField.h"
#include "cellPamf.h"
// Error Codes
enum CellDmuxError :u32
@@ -19,10 +18,6 @@ enum CellDmuxStreamType : s32
CELL_DMUX_STREAM_TYPE_UNDEF = 0,
CELL_DMUX_STREAM_TYPE_PAMF = 1,
CELL_DMUX_STREAM_TYPE_TERMINATOR = 2,
// Only used in cellSail
CELL_DMUX_STREAM_TYPE_MP4 = 0x81,
CELL_DMUX_STREAM_TYPE_AVI = 0x82
};
enum CellDmuxMsgType : s32
@@ -53,14 +48,13 @@ struct CellDmuxEsMsg
struct CellDmuxType
{
be_t<s32> streamType; // CellDmuxStreamType
be_t<s32> reserved1;
be_t<s32> reserved2;
be_t<u32> reserved[2];
};
struct CellDmuxType2
{
be_t<s32> streamType;
vm::bcptr<void> streamSpecificInfo;
be_t<s32> streamType; // CellDmuxStreamType
be_t<u32> streamSpecificInfo;
};
struct CellDmuxResource
@@ -79,8 +73,8 @@ struct CellDmuxResourceEx
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
vm::bptr<void> spurs; // CellSpurs*
be_t<u64, 1> priority;
be_t<u32> spurs_addr;
u8 priority[8];
be_t<u32> maxContention;
};
@@ -91,23 +85,33 @@ struct CellDmuxResourceSpurs
be_t<u32> maxContention;
};
/*
struct CellDmuxResource2Ex
{
b8 isResourceEx; //true
CellDmuxResourceEx resourceEx;
};
struct CellDmuxResource2NoEx
{
b8 isResourceEx; //false
CellDmuxResource resource;
};
*/
struct CellDmuxResource2
{
b8 isResourceEx;
union
{
CellDmuxResource resource;
CellDmuxResourceEx resourceEx;
};
be_t<u32> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
be_t<u32> shit[4];
};
struct DmuxContext;
struct DmuxEsContext;
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
using CellDmuxCbMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
using CellDmuxCbEsMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::ptr<DmuxEsContext> esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
// Used for internal callbacks as well
template <typename F>
@@ -173,70 +177,6 @@ struct DmuxAuInfo
be_t<u32> specific_info_size;
};
struct DmuxAuQueueElement
{
be_t<u32> index;
u8 unk; // unused
DmuxAuInfo au_info;
};
CHECK_SIZE(DmuxAuQueueElement, 0x38);
enum DmuxState : u32
{
DMUX_STOPPED = 1 << 0,
DMUX_RUNNING = 1 << 1,
};
struct alignas(0x10) DmuxContext // CellDmuxHandle = DmuxContext*
{
vm::bptr<DmuxContext> _this;
be_t<u32> _this_size;
be_t<u32> version;
be_t<u32> dmux_state;
CellDmuxType dmux_type;
CellDmuxCb dmux_cb;
b8 stream_is_set;
vm::bptr<void> core_handle;
be_t<u32> version_; // Same value as 'version'
be_t<u64> user_data;
be_t<s32> max_enabled_es_num;
be_t<s32> enabled_es_num;
be_t<u32> _dx_mhd; // sys_mutex_t
u8 reserved[0x7c];
};
CHECK_SIZE_ALIGN(DmuxContext, 0xc0, 0x10);
struct alignas(0x10) DmuxEsContext // CellDmuxEsHandle = DmuxEsContext*
{
be_t<u32> _dx_mes; // sys_mutex_t
be_t<u32> is_enabled;
be_t<u32> error_mem_size;
be_t<u32> error_count;
vm::bptr<void> error_mem_addr;
vm::bptr<DmuxEsContext> _this;
be_t<u32> _this_size;
be_t<s32> _this_index;
vm::bptr<DmuxContext> dmux_handle;
CellDmuxEsCb es_cb;
vm::bptr<void> core_es_handle;
bf_t<be_t<u32>, 0, 1> flush_started;
struct
{
be_t<s32> max_size;
be_t<s32> allocated_size;
be_t<s32> size;
be_t<s32> front;
be_t<s32> back;
be_t<s32> allocated_back;
}
au_queue;
};
CHECK_SIZE_ALIGN(DmuxEsContext, 0x50, 0x10);
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);
using DmuxNotifyProgEndCode = error_code(vm::ptr<void>, vm::ptr<void>);
@@ -254,10 +194,10 @@ using CellDmuxCoreOpSetStream = error_code(vm::ptr<void>, vm::cptr<void>, u32, b
using CellDmuxCoreOpReleaseAu = error_code(vm::ptr<void>, vm::ptr<void>, u32);
using CellDmuxCoreOpQueryEsAttr = error_code(vm::cptr<void>, vm::cptr<void>, vm::ptr<CellDmuxPamfEsAttr>);
using CellDmuxCoreOpEnableEs = error_code(vm::ptr<void>, vm::cptr<void>, vm::cptr<CellDmuxEsResource>, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>>, vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>>, vm::cptr<void>, vm::pptr<void>);
using CellDmuxCoreOpDisableEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpFlushEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpResetEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpResetStreamAndWaitDone = error_code(vm::ptr<void>);
using CellDmuxCoreOpDisableEs = u32(vm::ptr<void>);
using CellDmuxCoreOpFlushEs = u32(vm::ptr<void>);
using CellDmuxCoreOpResetEs = u32(vm::ptr<void>);
using CellDmuxCoreOpResetStreamAndWaitDone = u32(vm::ptr<void>);
struct CellDmuxCoreOps
{
+1 -1
View File
@@ -2591,7 +2591,7 @@ template <bool raw_es>
error_code _CellDmuxCoreOpEnableEs(ppu_thread& ppu, vm::ptr<CellDmuxPamfHandle> handle, vm::cptr<void> esFilterId, vm::cptr<CellDmuxEsResource> esResource, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>> notifyAuFound,
vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>> notifyFlushDone, vm::cptr<void> esSpecificInfo, vm::pptr<CellDmuxPamfEsHandle> esHandle)
{
cellDmuxPamf.notice("_CellDmuxCoreOpEnableEs<raw_es=%d>(handle=*0x%x, esFilterId=*0x%x, esResource=*0x%x, notifyAuFound=*0x%x, notifyFlushDone=*0x%x, esSpecificInfo=*0x%x, esHandle=**0x%x)",
cellDmuxPamf.notice("_CellDmuxCoreOpEnableEs<raw_es=%d>(handle=*0x%x, esFilterId=*0x%x, esResource=*0x%x, notifyAuFound=*0x%x, notifyFlushDone=*0x%x, esSpecificInfo=*0x%x, esHandle)",
raw_es, handle, esFilterId, esResource, notifyAuFound, notifyFlushDone, esSpecificInfo, esHandle);
if (!handle || !esFilterId || !esResource || !esResource->memAddr || esResource->memSize == 0u || !notifyAuFound || !notifyAuFound->cbFunc || !notifyAuFound->cbArg || !notifyFlushDone || !notifyFlushDone->cbFunc || !notifyFlushDone->cbArg)
+4 -5
View File
@@ -520,11 +520,10 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
return CELL_GAMEDATA_ERROR_PARAM;
}
// Nuked until correctly reversed engineered
//if (!fs::create_path(vfs::get(usrdir)))
//{
// return {CELL_GAME_ERROR_ACCESS_ERROR, usrdir};
//}
if (!fs::create_path(vfs::get(usrdir)))
{
return {CELL_GAME_ERROR_ACCESS_ERROR, usrdir};
}
}
// Nuked until correctly reversed engineered
+87 -354
View File
@@ -27,6 +27,39 @@
LOG_CHANNEL(cellGem);
template <>
void fmt_class_string<gem_btn>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](gem_btn value)
{
switch (value)
{
case gem_btn::start: return "Start";
case gem_btn::select: return "Select";
case gem_btn::triangle: return "Triangle";
case gem_btn::circle: return "Circle";
case gem_btn::cross: return "Cross";
case gem_btn::square: return "Square";
case gem_btn::move: return "Move";
case gem_btn::t: return "T";
case gem_btn::x_axis: return "X-Axis";
case gem_btn::y_axis: return "Y-Axis";
case gem_btn::combo: return "Combo";
case gem_btn::combo_start: return "Combo Start";
case gem_btn::combo_select: return "Combo Select";
case gem_btn::combo_triangle: return "Combo Triangle";
case gem_btn::combo_circle: return "Combo Circle";
case gem_btn::combo_cross: return "Combo Cross";
case gem_btn::combo_square: return "Combo Square";
case gem_btn::combo_move: return "Combo Move";
case gem_btn::combo_t: return "Combo T";
case gem_btn::count: return "Count";
}
return unknown;
});
}
template <>
void fmt_class_string<CellGemError>::format(std::string& out, u64 arg)
{
@@ -201,7 +234,7 @@ public:
struct gem_controller
{
u32 status = CELL_GEM_STATUS_DISCONNECTED; // Connection status (CELL_GEM_STATUS_DISCONNECTED or CELL_GEM_STATUS_READY)
u32 ext_status = 0; // External port connection status
u32 ext_status = CELL_GEM_NO_EXTERNAL_PORT_DEVICE; // External port connection status
u32 ext_id = 0; // External device ID (type). For example SHARP_SHOOTER_DEVICE_ID
u32 port = 0; // Assigned port
bool enabled_magnetometer = true; // Whether the magnetometer is enabled (probably used for additional rotational precision)
@@ -221,8 +254,6 @@ public:
u64 calibration_start_us{0}; // The start timestamp of the calibration in microseconds
u64 calibration_status_flags = 0; // The calibration status flags
u8 firing_mode = button_flags::ss_firing_mode_1; // The firing mode of the sharpshooter. Used with fake PS-Move. This is a physical switch with 3 positions, not a button that can be pressed.
static constexpr u64 calibration_time_us = 500000; // The calibration supposedly takes 0.5 seconds (500000 microseconds)
};
@@ -2118,337 +2149,6 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co
}
}
static const std::unordered_map<gem_btn, u16> ext_btn_map =
{
{ gem_btn::sharpshooter_firing_mode_1, button_flags::ss_firing_mode_1 },
{ gem_btn::sharpshooter_firing_mode_2, button_flags::ss_firing_mode_2 },
{ gem_btn::sharpshooter_firing_mode_3, button_flags::ss_firing_mode_3 },
{ gem_btn::sharpshooter_trigger, button_flags::ss_trigger },
{ gem_btn::sharpshooter_reload, button_flags::ss_reload },
{ gem_btn::racing_wheel_d_pad_up, CELL_PAD_CTRL_UP },
{ gem_btn::racing_wheel_d_pad_right, CELL_PAD_CTRL_RIGHT },
{ gem_btn::racing_wheel_d_pad_down, CELL_PAD_CTRL_DOWN },
{ gem_btn::racing_wheel_d_pad_left, CELL_PAD_CTRL_LEFT },
{ gem_btn::racing_wheel_throttle, 0 },
{ gem_btn::racing_wheel_l1, CELL_PAD_CTRL_L1 },
{ gem_btn::racing_wheel_r1, CELL_PAD_CTRL_R1 },
{ gem_btn::racing_wheel_l2, 0 },
{ gem_btn::racing_wheel_r2, 0 },
{ gem_btn::racing_wheel_paddle_l, button_flags::rw_paddle_l },
{ gem_btn::racing_wheel_paddle_r, button_flags::rw_paddle_r },
{ gem_btn::combo_sharpshooter_firing_mode_1, button_flags::ss_firing_mode_1 },
{ gem_btn::combo_sharpshooter_firing_mode_2, button_flags::ss_firing_mode_2 },
{ gem_btn::combo_sharpshooter_firing_mode_3, button_flags::ss_firing_mode_3 },
{ gem_btn::combo_sharpshooter_trigger, button_flags::ss_trigger },
{ gem_btn::combo_sharpshooter_reload, button_flags::ss_reload },
{ gem_btn::combo_racing_wheel_d_pad_up, CELL_PAD_CTRL_UP },
{ gem_btn::combo_racing_wheel_d_pad_right, CELL_PAD_CTRL_RIGHT },
{ gem_btn::combo_racing_wheel_d_pad_down, CELL_PAD_CTRL_DOWN },
{ gem_btn::combo_racing_wheel_d_pad_left, CELL_PAD_CTRL_LEFT },
{ gem_btn::combo_racing_wheel_throttle, 0 },
{ gem_btn::combo_racing_wheel_l1, CELL_PAD_CTRL_L1 },
{ gem_btn::combo_racing_wheel_r1, CELL_PAD_CTRL_R1 },
{ gem_btn::combo_racing_wheel_l2, 0 },
{ gem_btn::combo_racing_wheel_r2, 0 },
{ gem_btn::combo_racing_wheel_paddle_l, button_flags::rw_paddle_l },
{ gem_btn::combo_racing_wheel_paddle_r, button_flags::rw_paddle_r },
};
static const std::unordered_map<gem_btn, u16> ext_btn_indices =
{
{ gem_btn::racing_wheel_throttle, 0 },
{ gem_btn::racing_wheel_l2, 1 },
{ gem_btn::racing_wheel_r2, 2 },
{ gem_btn::racing_wheel_paddle_l, 3 },
{ gem_btn::racing_wheel_paddle_r, 4 },
{ gem_btn::combo_racing_wheel_throttle, 0 },
{ gem_btn::combo_racing_wheel_l2, 1 },
{ gem_btn::combo_racing_wheel_r2, 2 },
{ gem_btn::combo_racing_wheel_paddle_l, 3 },
{ gem_btn::combo_racing_wheel_paddle_r, 4 },
};
static u32 ext_device_id(gem_ext_id id)
{
switch (id)
{
case gem_ext_id::disconnected: return 0;
case gem_ext_id::sharpshooter: return SHARP_SHOOTER_DEVICE_ID;
case gem_ext_id::racing_wheel: return RACING_WHEEL_DEVICE_ID;
}
fmt::throw_exception("Mo ID found for id = %d", static_cast<s32>(id));
}
template <bool has_combo, bool is_combo>
static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::set<pad_button>& combos, gem_btn btn, pad_button pad_btn, u16 value, bool pressed)
{
if (!pressed)
return;
const auto set_firing_mode = [&ext](gem_btn btn)
{
// The firing mode is exclusive
ext.custom[0] &= ~button_flags::ss_firing_mode_mask;
ext.custom[0] |= ::at32(ext_btn_map, btn);
};
if constexpr (has_combo && is_combo)
{
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_sharpshooter_firing_mode_1:
case gem_btn::combo_sharpshooter_firing_mode_2:
case gem_btn::combo_sharpshooter_firing_mode_3:
set_firing_mode(btn);
combos.insert(pad_btn);
break;
case gem_btn::combo_sharpshooter_trigger:
case gem_btn::combo_sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
default:
break;
}
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
default:
break;
}
}
}
else
{
if constexpr (has_combo)
{
if (combos.contains(pad_btn))
{
return;
}
}
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
{
case gem_btn::sharpshooter_firing_mode_1:
case gem_btn::sharpshooter_firing_mode_2:
case gem_btn::sharpshooter_firing_mode_3:
set_firing_mode(btn);
break;
case gem_btn::sharpshooter_trigger:
case gem_btn::sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
break;
default:
break;
}
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
break;
default:
break;
}
}
}
}
static void real_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected() || pad->is_copilot())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
ps_move_data& move_data = pad->move_data;
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
if (!move_data.external_device_connected)
{
return;
}
// TODO:
// ext.analog_left_x
// ext.analog_left_y
// ext.analog_right_x
// ext.analog_right_y
// ext.digital1
// ext.digital2
ext.status = controller.ext_status;
std::memcpy(ext.custom, move_data.external_device_data.data(), 5);
}
static void fake_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected() || pad->is_copilot())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
ps_move_data& move_data = pad->move_data;
const auto& cfg = ::at32(g_cfg_gem_fake.players, gem_num);
move_data.external_device_id = ext_device_id(cfg->external_device);
move_data.external_device_connected = move_data.external_device_id != 0;
move_data.external_device_data = {};
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
if (!move_data.external_device_connected)
{
return;
}
// Restore firing mode
ext.custom[0] = controller.firing_mode;
cfg->handle_input(pad, true, [&move_data, &ext](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
static std::set<pad_button> s_combos = {};
input_to_ext<false, false>(move_data.external_device_id, ext, s_combos, btn, pad_btn, value, pressed);
});
ext.status = controller.ext_status;
// Save firing mode
controller.firing_mode = ext.custom[0] & button_flags::ss_firing_mode_mask;
}
static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
auto& handler = g_fxo->get<MouseHandlerBase>();
std::scoped_lock lock(handler.mutex);
// Make sure that the mouse handler is initialized
handler.Init(std::min<u32>(g_fxo->get<gem_config>().attribute.max_connect, CELL_GEM_MAX_NUM));
if (mouse_no >= handler.GetMice().size())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
const Mouse& mouse_data = ::at32(handler.GetMice(), mouse_no);
const auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
const u32 external_device_id = ext_device_id(cfg->external_device);
const bool external_device_connected = external_device_id != 0;
controller.ext_status = external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = external_device_connected ? external_device_id : 0;
if (!external_device_connected)
{
return;
}
// Restore firing mode
ext.custom[0] = controller.firing_mode;
bool combo_active = false;
std::set<pad_button> combos;
// Check combo button first
cfg->handle_input(mouse_data, [&combo_active](gem_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& abort)
{
if (pressed && btn == gem_btn::combo)
{
combo_active = true;
abort = true;
}
});
// Check combos
if (combo_active)
{
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
input_to_ext<true, true>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
});
}
// Check normal buttons
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
input_to_ext<true, false>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
});
ext.status = controller.ext_status;
// Save firing mode
controller.firing_mode = ext.custom[0] & button_flags::ss_firing_mode_mask;
}
/**
* \brief Maps external Move controller data to DS3 input. (This can be input from any physical pad, not just the DS3)
* Implementation detail: CellGemExtPortData's digital/analog fields map the same way as
@@ -2457,7 +2157,7 @@ static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& control
* \param ext External data to modify
* \return true on success, false if controller is disconnected
*/
static void get_external_device_input(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
ext = {};
@@ -2466,6 +2166,53 @@ static void get_external_device_input(u32 gem_num, gem_config::gem_controller& c
return;
}
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected() || pad->is_copilot())
{
return;
}
const auto& move_data = pad->move_data;
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
ext.status = controller.ext_status;
for (const AnalogStick& stick : pad->m_sticks_external)
{
switch (stick.m_offset)
{
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: ext.analog_left_x = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: ext.analog_left_y = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: ext.analog_right_x = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: ext.analog_right_y = stick.m_value; break;
default: break;
}
}
for (const Button& button : pad->m_buttons_external)
{
if (!button.m_pressed)
continue;
switch (button.m_offset)
{
case CELL_PAD_BTN_OFFSET_DIGITAL1: ext.digital1 |= button.m_outKeyCode; break;
case CELL_PAD_BTN_OFFSET_DIGITAL2: ext.digital2 |= button.m_outKeyCode; break;
default: break;
}
}
if (!move_data.external_device_connected)
{
return;
}
// The sharpshooter only sets the custom bytes as follows:
// custom[0] (0x01): Firing mode selector is in position 1.
// custom[0] (0x02): Firing mode selector is in position 2.
@@ -2480,21 +2227,7 @@ static void get_external_device_input(u32 gem_num, gem_config::gem_controller& c
// custom[3] (0x01): Left paddle
// custom[3] (0x02): Right paddle
switch (g_cfg.io.move)
{
case move_handler::real:
real_input_to_ext(gem_num, controller, ext);
break;
case move_handler::fake:
fake_input_to_ext(gem_num, controller, ext);
break;
case move_handler::mouse:
case move_handler::raw_mouse:
mouse_input_to_ext(gem_num, controller, ext);
break;
default:
break;
}
std::memcpy(ext.custom, move_data.external_device_data.data(), 5);
}
/**
@@ -2527,7 +2260,7 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
}
const Mouse& mouse_data = ::at32(handler.GetMice(), mouse_no);
const auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
bool combo_active = false;
std::set<pad_button> combos;
@@ -3265,7 +2998,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
if (g_cfg.io.move != move_handler::null)
{
get_external_device_input(gem_num, gem.controllers[gem_num], inertial_state->ext);
ds3_input_to_ext(gem_num, gem.controllers[gem_num], inertial_state->ext);
inertial_state->timestamp = (get_guest_system_time() - gem.start_timestamp_us);
inertial_state->counter = gem.inertial_counter++;
@@ -3459,7 +3192,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
if (g_cfg.io.move != move_handler::null)
{
get_external_device_input(gem_num, controller, gem_state->ext);
ds3_input_to_ext(gem_num, controller, gem_state->ext);
if (controller.enabled_tracking)
{
@@ -3876,7 +3609,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr<u32> ext_id, v
{
// Get external device status
CellGemExtPortData ext_port_data{};
get_external_device_input(gem_num, controller, ext_port_data);
ds3_input_to_ext(gem_num, controller, ext_port_data);
}
if (!(controller.ext_status & CELL_GEM_EXT_CONNECTED))
-35
View File
@@ -278,38 +278,3 @@ struct CellGemVideoConvertAttribute
ENABLE_BITWISE_SERIALIZATION;
};
namespace
{
enum button_flags : u16
{
select = 0x01,
start = 0x08,
triangle = 0x10,
circle = 0x20,
cross = 0x40,
square = 0x80,
ps = 0x0001,
move = 0x4008,
t = 0x8010,
ext_dev = 0x1000,
// Sharpshooter
ss_firing_mode_1 = 0x01,
ss_firing_mode_2 = 0x02,
ss_firing_mode_3 = 0x04,
ss_firing_mode_mask = ss_firing_mode_1 | ss_firing_mode_2 | ss_firing_mode_3,
ss_trigger = 0x40,
ss_reload = 0x80,
// Racing Wheel
rw_d_pad_up = 0x10,
rw_d_pad_right = 0x20,
rw_d_pad_down = 0x40,
rw_d_pad_left = 0x80,
rw_l1 = 0x04,
rw_r1 = 0x08,
rw_paddle_l = 0x01,
rw_paddle_r = 0x02,
};
}
+1
View File
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Memory/vm_ref.h"
#ifdef _WIN32
#include <Windows.h>
+14 -73
View File
@@ -66,7 +66,6 @@ void fmt_class_string<CellMusic2Error>::format(std::string& out, u64 arg)
struct music_state
{
public:
shared_mutex mutex;
vm::ptr<void(u32 event, vm::ptr<void> param, vm::ptr<void> userData)> func{};
@@ -80,58 +79,33 @@ public:
music_state()
{
handler = Emu.GetCallbacks().get_music_handler();
handler->set_event_status_callback([this](u32 status)
handler->set_status_callback([this](music_handler_base::player_status status)
{
// TODO: disabled until I find a game that uses CELL_MUSIC_EVENT_STATUS_NOTIFICATION
return;
if (!func)
{
return;
}
// Known to be used by NFS: Hot Pursuit
sysutil_register_cb([this, state = status](ppu_thread& ppu) -> s32
{
cellMusic.notice("Sending status notification %d", state);
func(ppu, CELL_MUSIC_EVENT_STATUS_NOTIFICATION, vm::addr_t(state), userData);
return CELL_OK;
});
});
handler->set_playback_status_callback([this](music_handler_base::player_status status)
{
s32 result = CELL_OK;
switch (status)
{
case music_handler_base::player_status::end_of_media:
// Let's just play the next song for now if we are in list mode.
// Due to potential main thread recursion this may cause a deadlock with the internal mutex of the handler.
// Let's just call it from another thread instead.
m_wake_up_thread = 1;
m_wake_up_thread.notify_one();
result = CELL_MUSIC_PLAYBACK_FINISHED;
break;
default:
return;
}
});
m_thread = std::make_unique<named_thread<std::function<void()>>>("cellMusic State", [this]()
{
while (thread_ctrl::state() != thread_state::aborting)
sysutil_register_cb([this, &result](ppu_thread& ppu) -> s32
{
while (thread_ctrl::state() != thread_state::aborting && !m_wake_up_thread)
{
thread_ctrl::wait_on(m_wake_up_thread, 0);
}
m_wake_up_thread = 0;
if (thread_ctrl::state() == thread_state::aborting)
{
return;
}
// Play the next song
if (const error_code error = set_playback_command(CELL_MUSIC_PB_CMD_NEXT_TRACK))
{
cellMusic.error("Failed to play next track. error=0x%x", +error);
}
}
cellMusic.notice("Sending status notification %d", result);
func(ppu, CELL_MUSIC_EVENT_STATUS_NOTIFICATION, vm::addr_t(result), userData);
return CELL_OK;
});
});
}
@@ -141,19 +115,6 @@ public:
save(ar);
}
~music_state()
{
if (m_thread)
{
auto& thread = *m_thread;
thread = thread_state::aborting;
m_wake_up_thread = 1;
m_wake_up_thread.notify_one();
thread();
m_thread.reset();
}
}
void save(utils::serial& ar)
{
ar(func);
@@ -169,7 +130,7 @@ public:
}
// NOTE: This function only uses CELL_MUSIC enums. CELL_MUSIC2 enums are identical.
error_code set_playback_command(u32 command)
error_code set_playback_command(s32 command)
{
switch (command)
{
@@ -184,27 +145,11 @@ public:
case CELL_MUSIC_PB_CMD_FASTREVERSE:
case CELL_MUSIC_PB_CMD_NEXT:
case CELL_MUSIC_PB_CMD_PREV:
case CELL_MUSIC_PB_CMD_NEXT_TRACK:
{
std::string path;
bool automatic = false;
bool no_more_tracks = false;
{
std::lock_guard lock(mtx);
// Handle auto-play of the next track in the current playlist.
if (command == CELL_MUSIC_PB_CMD_NEXT_TRACK)
{
// We only auto-play the next song if we are in list mode and the music is playing.
if (current_selection_context.content_type != CELL_SEARCH_CONTENTTYPE_MUSICLIST || handler->get_state() != CELL_MUSIC_PB_STATUS_PLAY)
{
return CELL_OK;
}
command = CELL_MUSIC_PB_CMD_NEXT;
automatic = true;
}
const std::vector<std::string>& playlist = current_selection_context.playlist;
const u32 current_track = current_selection_context.current_track;
u32 next_track = current_track;
@@ -246,7 +191,7 @@ public:
handler->fast_reverse(path);
break;
default:
handler->play(path, automatic);
handler->play(path);
break;
}
@@ -258,10 +203,6 @@ public:
return CELL_OK;
}
private:
std::unique_ptr<named_thread<std::function<void()>>> m_thread;
atomic_t<u32> m_wake_up_thread{0};
};
error_code cell_music_select_contents()
-2
View File
@@ -90,8 +90,6 @@ enum
CELL_MUSIC_PB_CMD_PREV = 4,
CELL_MUSIC_PB_CMD_FASTFORWARD = 5,
CELL_MUSIC_PB_CMD_FASTREVERSE = 6,
CELL_MUSIC_PB_CMD_NEXT_TRACK = 7, // RPCS3 helper for auto-play of the next track in the current playlist
};
enum
+3 -12
View File
@@ -74,7 +74,6 @@ struct music_decode
cellMusicDecode.notice("set_decode_command(START): context: %s", current_selection_context.to_string());
music_selection_context context = current_selection_context;
context.current_track = context.first_track;
for (usz i = 0; i < context.playlist.size(); i++)
{
@@ -91,7 +90,6 @@ struct music_decode
case CELL_MUSIC_DECODE_CMD_PREV:
{
decoder.stop();
read_pos = 0;
if (decoder.set_next_index(command == CELL_MUSIC_DECODE_CMD_NEXT) == umax)
{
@@ -197,10 +195,9 @@ error_code cell_music_decode_read(vm::ptr<void> buf, vm::ptr<u32> startTime, u64
if (dec.decoder.m_size == 0)
{
return { CELL_MUSIC_DECODE_ERROR_NO_LPCM_DATA, "m_size == 0" };
return CELL_MUSIC_DECODE_ERROR_NO_LPCM_DATA;
}
ensure(dec.decoder.m_size >= dec.read_pos);
const u64 size_left = dec.decoder.m_size - dec.read_pos;
if (dec.read_pos == 0)
@@ -232,10 +229,10 @@ error_code cell_music_decode_read(vm::ptr<void> buf, vm::ptr<u32> startTime, u64
if (size_to_read == 0)
{
return { CELL_MUSIC_DECODE_ERROR_NO_LPCM_DATA, "size_to_read == 0" }; // TODO: speculative
return CELL_MUSIC_DECODE_ERROR_NO_LPCM_DATA; // TODO: speculative
}
std::memcpy(buf.get_ptr(), &::at32(dec.decoder.data, dec.read_pos), size_to_read);
std::memcpy(buf.get_ptr(), &dec.decoder.data[dec.read_pos], size_to_read);
if (size_to_read < reqSize)
{
@@ -387,12 +384,6 @@ error_code cellMusicDecodeSetDecodeCommand(s32 command)
return CELL_OK;
});
//sysutil_register_cb([&dec, command](ppu_thread& ppu) -> s32
//{
// dec.func(ppu, CELL_MUSIC_DECODE_EVENT_STATUS_NOTIFICATION, vm::addr_t(command), dec.userData);
// return CELL_OK;
//});
return CELL_OK;
}
@@ -267,10 +267,9 @@ void music_selection_context::set_track(std::string_view track)
for (usz i = 0; i < playlist.size(); i++)
{
cellMusicSelectionContext.notice("set_track: Comparing track '%s' vs '%s'", track, playlist[i]);
cellMusicSelectionContext.error("set_track: Comparing track '%s' vs '%s'", track, playlist[i]);
if (track.ends_with(playlist[i]))
{
cellMusicSelectionContext.notice("set_track: Found track '%s': '%s'", track, playlist[i]);
first_track = current_track = static_cast<u32>(i);
return;
}
@@ -288,8 +287,6 @@ u32 music_selection_context::step_track(bool next)
return umax;
}
const std::string last_track = (current_track < playlist.size()) ? playlist[current_track] : "";
switch (repeat_mode)
{
case CELL_SEARCH_REPEATMODE_NONE:
@@ -301,7 +298,7 @@ u32 music_selection_context::step_track(bool next)
{
// We are at the end of the playlist.
cellMusicSelectionContext.notice("step_track: No more tracks to play in playlist...");
current_track = ::size32(playlist) - 1; // NOTE: We could use size instead of size - 1 to allow to use PREV to play the last track again.
current_track = umax;
return umax;
}
}
@@ -312,6 +309,7 @@ u32 music_selection_context::step_track(bool next)
{
// We are at the start of the playlist.
cellMusicSelectionContext.notice("step_track: No more tracks to play in playlist...");
current_track = umax;
return umax;
}
@@ -336,7 +334,7 @@ u32 music_selection_context::step_track(bool next)
// Play the previous track. Start with the last track if we reached the start of the playlist.
if (current_track == 0)
{
current_track = ::size32(playlist) - 1;
current_track = ::narrow<u32>(playlist.size() - 1);
}
else
{
@@ -364,15 +362,8 @@ u32 music_selection_context::step_track(bool next)
{
// We reached the first or last track again. Let's shuffle!
cellMusicSelectionContext.notice("step_track: Shuffling playlist...");
std::random_device rd;
auto engine = std::default_random_engine{rd()};
auto engine = std::default_random_engine{};
std::shuffle(std::begin(playlist), std::end(playlist), engine);
// Don't play the same track twice
if (last_track == ::at32(playlist, current_track))
{
current_track = (current_track + 1) % playlist.size();
}
}
}
+1 -40
View File
@@ -192,46 +192,7 @@ error_code cellNetCtlDelHandler(s32 hid)
error_code cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info)
{
bool log_it_once = false;
switch (code)
{
case CELL_NET_CTL_INFO_ETHER_ADDR:
case CELL_NET_CTL_INFO_DEVICE:
case CELL_NET_CTL_INFO_MTU:
case CELL_NET_CTL_INFO_LINK_TYPE:
case CELL_NET_CTL_INFO_IP_CONFIG:
case CELL_NET_CTL_INFO_IP_ADDRESS:
case CELL_NET_CTL_INFO_NETMASK:
case CELL_NET_CTL_INFO_DEFAULT_ROUTE:
case CELL_NET_CTL_INFO_HTTP_PROXY_CONFIG:
case CELL_NET_CTL_INFO_UPNP_CONFIG:
{
log_it_once = true;
break;
}
default:
{
break;
}
}
bool log_it = true;
if (log_it_once && vm::check_addr(info.addr()))
{
struct logged_t
{
std::array<atomic_t<bool>, 256> logged_code{};
};
if (g_fxo->get<logged_t>().logged_code[::narrow<u8>(code)].exchange(true))
{
log_it = false;
}
}
(log_it ? cellNetCtl.warning : cellNetCtl.trace)("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info);
cellNetCtl.warning("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
+5 -5
View File
@@ -56,9 +56,9 @@ void fmt_class_string<CellPadFilterError>::format(std::string& out, u64 arg)
extern void sys_io_serialize(utils::serial& ar);
pad_info::pad_info(utils::serial& ar)
: max_connect(ar.pop<u32>())
, port_setting(ar.pop<decltype(port_setting)>())
, reported_info(ar.pop<decltype(reported_info)>())
: max_connect(ar)
, port_setting(ar)
, reported_info(ar)
{
//reported_info = {};
sys_io_serialize(ar);
@@ -418,7 +418,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
};
for (const ButtonExternal& button : pad->m_buttons_external)
for (const Button& button : pad->m_buttons_external)
{
// here we check btns, and set pad accordingly,
// if something changed, set btnChanged
@@ -497,7 +497,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
}
for (const AnalogStickExternal& stick : pad->m_sticks_external)
for (const AnalogStick& stick : pad->m_sticks_external)
{
switch (stick.m_offset)
{
+12 -6
View File
@@ -1,10 +1,18 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "util/bit_set.hpp"
#include <bitset>
#include "cellPamf.h"
const std::function<bool()> SQUEUE_ALWAYS_EXIT = []() { return true; };
const std::function<bool()> SQUEUE_NEVER_EXIT = []() { return false; };
bool squeue_test_exit()
{
return Emu.IsStopped();
}
LOG_CHANNEL(cellPamf);
template<>
@@ -500,7 +508,7 @@ error_code pamfVerify(vm::cptr<PamfHeader> pAddr, u64 fileSize, vm::ptr<CellPamf
const auto streams = &pAddr->seq_info.grouping_periods.groups.streams;
std::array<bit_set<16>, 6> channels_used{};
std::bitset<16> channels_used[6]{};
u32 end_of_streams_addr = 0;
u32 next_ep_table_addr = 0;
@@ -516,16 +524,14 @@ error_code pamfVerify(vm::cptr<PamfHeader> pAddr, u64 fileSize, vm::ptr<CellPamf
return CELL_PAMF_ERROR_UNKNOWN_STREAM;
}
bit_set<16>& used_channels = ::at32(channels_used, *type);
// Every channel may only be used once per type
if (used_channels.test(*ch))
if (channels_used[*type].test(*ch))
{
return { CELL_PAMF_ERROR_INVALID_PAMF, "pamfVerify() failed: invalid channel" };
}
// Mark channel as used
used_channels.set(*ch, true);
channels_used[*type].set(*ch);
const u32 ep_offset = streams[stream_idx].ep_offset;
const u32 ep_num = streams[stream_idx].ep_num;
+342
View File
@@ -595,3 +595,345 @@ struct CellPamfReader
CHECK_SIZE(CellPamfReader, 128);
error_code cellPamfReaderInitialize(vm::ptr<CellPamfReader> pSelf, vm::cptr<PamfHeader> pAddr, u64 fileSize, u32 attribute);
#include <mutex>
#include <condition_variable>
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
bool squeue_test_exit();
// TODO: eliminate this boolshit
template<typename T, u32 sq_size = 256>
class squeue_t
{
struct squeue_sync_var_t
{
struct
{
u32 position : 31;
u32 pop_lock : 1;
};
struct
{
u32 count : 31;
u32 push_lock : 1;
};
};
atomic_t<squeue_sync_var_t> m_sync;
mutable std::mutex m_rcv_mutex;
mutable std::mutex m_wcv_mutex;
mutable std::condition_variable m_rcv;
mutable std::condition_variable m_wcv;
T m_data[sq_size];
enum squeue_sync_var_result : u32
{
SQSVR_OK = 0,
SQSVR_LOCKED = 1,
SQSVR_FAILED = 2,
};
public:
squeue_t()
: m_sync(squeue_sync_var_t{})
{
}
static u32 get_max_size()
{
return sq_size;
}
bool is_full() const
{
return m_sync.load().count == sq_size;
}
bool push(const T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.push_lock)
{
return SQSVR_LOCKED;
}
if (sync.count == sq_size)
{
return SQSVR_FAILED;
}
sync.push_lock = 1;
pos = sync.position + sync.count;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> wcv_lock(m_wcv_mutex);
m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1));
}
m_data[pos >= sq_size ? pos - sq_size : pos] = data;
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.push_lock);
sync.push_lock = 0;
sync.count++;
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool push(const T& data, const volatile bool* do_exit)
{
return push(data, [do_exit]() { return do_exit && *do_exit; });
}
bool push(const T& data)
{
return push(data, SQUEUE_NEVER_EXIT);
}
bool try_push(const T& data)
{
return push(data, SQUEUE_ALWAYS_EXIT);
}
bool pop(T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (!sync.count)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
sync.pop_lock = 0;
sync.position++;
sync.count--;
if (sync.position == sq_size)
{
sync.position = 0;
}
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool pop(T& data, const volatile bool* do_exit)
{
return pop(data, [do_exit]() { return do_exit && *do_exit; });
}
bool pop(T& data)
{
return pop(data, SQUEUE_NEVER_EXIT);
}
bool try_pop(T& data)
{
return pop(data, SQUEUE_ALWAYS_EXIT);
}
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
{
ensure(start_pos < sq_size);
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.count <= start_pos)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position + start_pos;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos >= sq_size ? pos - sq_size : pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
sync.pop_lock = 0;
});
m_rcv.notify_one();
return true;
}
bool peek(T& data, u32 start_pos, const volatile bool* do_exit)
{
return peek(data, start_pos, [do_exit]() { return do_exit && *do_exit; });
}
bool peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_NEVER_EXIT);
}
bool try_peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_ALWAYS_EXIT);
}
class squeue_data_t
{
T* const m_data;
const u32 m_pos;
const u32 m_count;
squeue_data_t(T* data, u32 pos, u32 count)
: m_data(data)
, m_pos(pos)
, m_count(count)
{
}
public:
T& operator [] (u32 index)
{
ensure(index < m_count);
index += m_pos;
index = index < sq_size ? index : index - sq_size;
return m_data[index];
}
};
void process(void(*proc)(squeue_data_t data))
{
u32 pos, count;
while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
pos = sync.position;
count = sync.count;
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
proc(squeue_data_t(m_data, pos, count));
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
ensure(!!sync.push_lock);
sync.pop_lock = 0;
sync.push_lock = 0;
});
m_wcv.notify_one();
m_rcv.notify_one();
}
void clear()
{
while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
m_sync.exchange({});
m_wcv.notify_one();
m_rcv.notify_one();
}
};
+12 -34
View File
@@ -1711,6 +1711,12 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<Ce
auto content = std::find_if(searchObject->content_ids.begin(), searchObject->content_ids.end(), [&content_hash](const content_id_type& cid){ return cid.first == content_hash; });
if (content != searchObject->content_ids.cend() && content->second)
{
// Check if the type of the found content is correct
if (content->second->type != CELL_SEARCH_CONTENTTYPE_MUSIC)
{
return { CELL_SEARCH_ERROR_INVALID_CONTENTTYPE, "Type: %d, Expected: CELL_SEARCH_CONTENTTYPE_MUSIC"};
}
// Check if the type of the found content matches our search content type
if (content->second->type != first_content->type)
{
@@ -1718,36 +1724,8 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<Ce
}
// Use the found content
if (content->second->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
{
const std::string path = content->second->infoPath.contentPath;
const std::string vfs_path = vfs::get(path);
if (!fs::is_dir(vfs_path))
{
return { CELL_SEARCH_ERROR_CONTENT_NOT_FOUND, "Not a directory: Path='%s'", vfs_path };
}
for (auto&& dir_entry : fs::dir{vfs_path})
{
if (dir_entry.name == "." || dir_entry.name == "..")
{
continue;
}
std::string track = path + "/" + dir_entry.name;
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning found track: Type=0x%x, Path='%s'", content_hash, +content->second->type, track);
context.playlist.push_back(std::move(track));
}
}
else if (content->second->type == CELL_SEARCH_CONTENTTYPE_MUSIC)
{
context.playlist.push_back(content->second->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning found track: Type=0x%x, Path='%s'", content_hash, +content->second->type, context.playlist.back());
}
else
{
return { CELL_SEARCH_ERROR_INVALID_CONTENTTYPE, "Type: %d, Expected: CELL_SEARCH_CONTENTTYPE_MUSIC or CELL_SEARCH_CONTENTTYPE_MUSICLIST", +content->second->type };
}
context.playlist.push_back(content->second->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning found track: Type=0x%x, Path=%s", content_hash, +content->second->type, context.playlist.back());
}
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
{
@@ -1760,14 +1738,14 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<Ce
// TODO: whole playlist
shared_ptr<search_content_t> content = get_random_content();
context.playlist.push_back(content->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning random track: Type=0x%x, Path='%s'", content_hash, +content->type, context.playlist.back());
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning random track: Type=0x%x, Path=%s", content_hash, +content->type, context.playlist.back());
}
else
{
// Select the first track by default
// TODO: whole playlist
context.playlist.push_back(first_content->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning first track: Type=0x%x, Path='%s'", content_hash, +first_content->type, context.playlist.back());
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning first track: Type=0x%x, Path=%s", content_hash, +first_content->type, context.playlist.back());
}
}
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
@@ -1781,14 +1759,14 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<Ce
// TODO: whole playlist
shared_ptr<search_content_t> content = get_random_content();
context.playlist.push_back(content->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Assigning random track: Type=0x%x, Path='%s'", +content->type, context.playlist.back());
cellSearch.notice("cellSearchGetMusicSelectionContext(): Assigning random track: Type=0x%x, Path=%s", +content->type, context.playlist.back());
}
else
{
// Select the first track by default
// TODO: whole playlist
context.playlist.push_back(first_content->infoPath.contentPath);
cellSearch.notice("cellSearchGetMusicSelectionContext(): Assigning first track: Type=0x%x, Path='%s'", +first_content->type, context.playlist.back());
cellSearch.notice("cellSearchGetMusicSelectionContext(): Assigning first track: Type=0x%x, Path=%s", +first_content->type, context.playlist.back());
}
context.content_type = first_content->type;
+9 -11
View File
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include <bitset>
#include <string>
#include "cellSsl.h"
@@ -7,7 +8,6 @@
#include "Utilities/File.h"
#include "Emu/VFS.h"
#include "Emu/IdManager.h"
#include "util/bit_set.hpp"
#include "cellRtc.h"
@@ -92,7 +92,7 @@ std::string getCert(const std::string& certPath, const int certID, const bool is
newID = certID - 1;
}
const std::string filePath = fmt::format("%sCA%02d.cer", certPath, newID);
std::string filePath = fmt::format("%sCA%02d.cer", certPath, newID);
if (!fs::exists(filePath))
{
@@ -106,7 +106,7 @@ error_code cellSslCertificateLoader(u64 flag, vm::ptr<char> buffer, u32 size, vm
{
cellSsl.trace("cellSslCertificateLoader(flag=%llu, buffer=*0x%x, size=%zu, required=*0x%x)", flag, buffer, size, required);
const bit_set<58> flagBits(flag);
const std::bitset<58> flagBits(flag);
const std::string certPath = vfs::get("/dev_flash/data/cert/");
if (required)
@@ -114,11 +114,10 @@ error_code cellSslCertificateLoader(u64 flag, vm::ptr<char> buffer, u32 size, vm
*required = 0;
for (uint i = 1; i <= flagBits.size(); i++)
{
if (!flagBits.test(i - 1))
if (!flagBits[i-1])
continue;
// If we're loading cert 6 (the baltimore cert), then we need set that we're loading the 'normal' set of certs.
*required += ::size32(getCert(certPath, i, flagBits.test(BaltimoreCert - 1)));
*required += ::size32(getCert(certPath, i, flagBits[BaltimoreCert-1]));
}
}
else
@@ -126,15 +125,14 @@ error_code cellSslCertificateLoader(u64 flag, vm::ptr<char> buffer, u32 size, vm
std::string final;
for (uint i = 1; i <= flagBits.size(); i++)
{
if (!flagBits.test(i - 1))
if (!flagBits[i-1])
continue;
// If we're loading cert 6 (the baltimore cert), then we need set that we're loading the 'normal' set of certs.
final.append(getCert(certPath, i, flagBits.test(BaltimoreCert - 1)));
final.append(getCert(certPath, i, flagBits[BaltimoreCert-1]));
}
std::memset(buffer.get_ptr(), '\0', size - 1);
std::memcpy(buffer.get_ptr(), final.c_str(), final.size());
memset(buffer.get_ptr(), '\0', size - 1);
memcpy(buffer.get_ptr(), final.c_str(), final.size());
}
return CELL_OK;
File diff suppressed because it is too large Load Diff
+3 -121
View File
@@ -9,11 +9,10 @@ enum CellVdecError : u32
CELL_VDEC_ERROR_EMPTY = 0x80610104,
CELL_VDEC_ERROR_AU = 0x80610105,
CELL_VDEC_ERROR_PIC = 0x80610106,
CELL_VDEC_ERROR_UNK = 0x80610110,
CELL_VDEC_ERROR_FATAL = 0x80610180,
};
enum CellVdecCodecType : u32
enum CellVdecCodecType : s32
{
CELL_VDEC_CODEC_TYPE_MPEG2 = 0,
CELL_VDEC_CODEC_TYPE_AVC = 1,
@@ -97,7 +96,7 @@ struct CellVdecTypeEx
{
be_t<s32> codecType; // CellVdecCodecType
be_t<u32> profileLevel;
vm::bcptr<void> codecSpecificInfo;
be_t<u32> codecSpecificInfo_addr;
};
// Library Attributes
@@ -221,7 +220,7 @@ enum
CELL_VDEC_AVC_CCD_MAX = 128,
};
enum AVC_level : u32
enum AVC_level : u8
{
CELL_VDEC_AVC_LEVEL_1P0 = 10,
CELL_VDEC_AVC_LEVEL_1P1 = 11,
@@ -236,7 +235,6 @@ enum AVC_level : u32
CELL_VDEC_AVC_LEVEL_4P0 = 40,
CELL_VDEC_AVC_LEVEL_4P1 = 41,
CELL_VDEC_AVC_LEVEL_4P2 = 42,
CELL_VDEC_AVC_LEVEL_UNK = 1042 // Same as 4.2, but disables the deblocking filter
};
struct CellVdecAvcSpecificInfo
@@ -401,7 +399,6 @@ enum DIVX_level : u8
CELL_VDEC_DIVX_HOME_THEATER = 12,
CELL_VDEC_DIVX_HD_720 = 13,
CELL_VDEC_DIVX_HD_1080 = 14,
CELL_VDEC_DIVX_UNK = 15 // Only used for DivX version 3.11
};
struct CellVdecDivxSpecificInfo
@@ -698,118 +695,3 @@ struct CellVdecMpeg4SpecificInfo
be_t<u16> maxDecodedFrameWidth;
be_t<u16> maxDecodedFrameHeight;
};
enum VC1_level
{
CELL_VDEC_VC1_SP_LL,
CELL_VDEC_VC1_SP_ML,
CELL_VDEC_VC1_MP_LL,
CELL_VDEC_VC1_MP_ML,
CELL_VDEC_VC1_MP_HL,
CELL_VDEC_VC1_AP_L0,
CELL_VDEC_VC1_AP_L1,
CELL_VDEC_VC1_AP_L2,
CELL_VDEC_VC1_AP_L3,
CELL_VDEC_VC1_AP_L4
};
struct CellVdecVc1SpecificInfo
{
be_t<u32> thisSize;
be_t<u16> maxDecodedFrameWidth;
be_t<u16> maxDecodedFrameHeight;
};
struct VdecDecoderAttr
{
be_t<u32> mem_size;
be_t<u32> unk1;
u8 cmd_depth;
be_t<u32> unk2;
be_t<u32> decoder_version;
};
struct VdecDecoderSpecificOps
{
error_code (&query_attr)(ppu_thread& ppu, VdecDecoderAttr& attr, u32 profile_level, const void* codec_specific_info);
// TODO remaining functions
};
// Abstraction layer for decoders with "S...D" in their names
enum class VdecSceDecoderType : u8
{
mpeg2,
mpeg4,
vc1,
jvt
};
template <typename param_t>
struct VdecSceDecoderOps
{
error_code (&get_memory_size)(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel);
error_code (&get_memory_size_2)(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<param_t> params);
error_code (&get_version_number)(ppu_thread& ppu, vm::ptr<u32> version);
// TODO remaining functions
};
struct VdecSceDecoderUnk
{
u32 unk1;
u32 unk2;
u32 unk3;
u32 unk4;
};
constexpr VdecSceDecoderOps<Smvd2Params> VDEC_SCE_DECODER_OPS_MPEG2 =
{
.get_memory_size = ppu_execute<&smvd2GetMemorySize>,
.get_memory_size_2 = ppu_execute<&smvd2GetMemorySize2>,
.get_version_number = ppu_execute<&smvd2GetVersionNumber>,
// TODO remaining functions
};
constexpr VdecSceDecoderOps<Smvd4Params> VDEC_SCE_DECODER_OPS_MPEG4 =
{
.get_memory_size = ppu_execute<&smvd4GetMemorySize>,
.get_memory_size_2 = ppu_execute<&smvd4GetMemorySize2>,
.get_version_number = ppu_execute<&smvd4GetVersionNumber>,
// TODO remaining functions
};
constexpr VdecSceDecoderOps<Svc1dParams> VDEC_SCE_DECODER_OPS_VC1 =
{
.get_memory_size = ppu_execute<&svc1dGetMemorySize>,
.get_memory_size_2 = ppu_execute<&svc1dGetMemorySize2>,
.get_version_number = ppu_execute<&svc1dGetVersionNumber>,
// TODO remaining functions
};
constexpr VdecSceDecoderOps<SjvtdParams> VDEC_SCE_DECODER_OPS_JVT =
{
.get_memory_size = ppu_execute<&sjvtdGetMemorySize>,
.get_memory_size_2 = ppu_execute<&sjvtdGetMemorySize2>,
.get_version_number = ppu_execute<&sjvtdGetVersionNumber>,
// TODO remaining functions
};
constexpr std::array VDEC_SCE_DECODER_ERROR_BASE_MAP = { 0x80615000u, 0x80615100u, 0x80615300u, 0x80615800u };
constexpr std::array VDEC_SCE_DECODER_MAX_MEM_SIZE_MAP =
{
std::array<u32, 13>{ 0xc8400, 0x295680, 0x9b8200, 0xce4f00 },
std::array<u32, 13>{ 0x44480, 0x44480, 0xa8b00, 0x1e6800, 0x1b4d00, 0x23e400 },
std::array<u32, 13>{ 0x1b44f0, 0x2dfef0, 0x38f9f0, 0x999e30, 0x2827f70, 0x2dfef0, 0x754130, 0x11bd9f0, 0x1fdee70, 0x3900070 },
std::array<u32, 13>{ 0x380fd0, 0x380fd0, 0x380fd0, 0x380fd0, 0x780950, 0xcb6d50, 0xcb6d50, 0x17a4950, 0x3245ed0, 0x4499fd0, 0x4499fd0, 0x4499fd0, 0x6b979d0 }
};
constexpr std::array VDEC_SCE_DECODER_UNK_MAP =
{
VdecSceDecoderUnk{ .unk1 = 2, .unk2 = 0, .unk4 = 0x1c8 },
VdecSceDecoderUnk{ .unk1 = 1, .unk2 = 6, .unk4 = 0x38 },
VdecSceDecoderUnk{ .unk1 = 3, .unk2 = 6, .unk4 = 0x170 },
VdecSceDecoderUnk{ .unk1 = 4, .unk2 = 6, .unk4 = 0x160 }
};
error_code cellVdecQueryAttrEx(ppu_thread& ppu, vm::cptr<CellVdecTypeEx> type, vm::ptr<CellVdecAttr> attr);
-107
View File
@@ -1,107 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libavcdec.h"
LOG_CHANNEL(libavcdec)
template<>
void fmt_class_string<AvcDecError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(AVC_DEC_ERROR_ARG);
}
return unknown;
});
}
error_code avcDecQueryMemory([[maybe_unused]] ppu_thread& ppu, vm::cptr<AvcDecParams> params, vm::ptr<AvcDecAttr> attr)
{
libavcdec.todo("avcDecQueryMemory(params=*0x%x, attr=*0x%x)", params, attr);
return CELL_OK;
}
void avcDecGetVersion([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> version)
{
libavcdec.notice("avcDecGetVersion(version=*0x%x)", version);
if (version)
{
*version = 0x11300;
}
}
error_code avcDecQueryCharacteristics([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> unk)
{
libavcdec.notice("avcDecGetVersion(unk=*0x%x)", unk);
if (!unk)
{
return AVC_DEC_ERROR_ARG;
}
unk[0] = 5; // Command queue depth
unk[1] = 20;
return CELL_OK;
}
error_code avcDecOpen()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecClose()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecReset()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecFlush()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecAccessUnit()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecRlsFrame()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
error_code avcDecGetStatus()
{
UNIMPLEMENTED_FUNC(libavcdec);
return CELL_OK;
}
DECLARE(ppu_module_manager::libavcdec)("libavcdec", []
{
REG_FUNC(libavcdec, avcDecQueryMemory);
REG_FUNC(libavcdec, avcDecGetVersion);
REG_FUNC(libavcdec, avcDecQueryCharacteristics);
REG_FUNC(libavcdec, avcDecOpen);
REG_FUNC(libavcdec, avcDecClose);
REG_FUNC(libavcdec, avcDecReset);
REG_FUNC(libavcdec, avcDecFlush);
REG_FUNC(libavcdec, avcDecAccessUnit);
REG_FUNC(libavcdec, avcDecRlsFrame);
REG_FUNC(libavcdec, avcDecGetStatus);
});
-26
View File
@@ -1,26 +0,0 @@
#pragma once
enum AvcDecError : u32
{
AVC_DEC_ERROR_ARG = 0x80615201,
};
struct AvcDecParams
{
u8 profile_level;
b8 disable_deblocking_filter;
u8 number_of_decoded_frame_buffer;
be_t<u16> max_decoded_frame_width;
be_t<u16> max_decoded_frame_height;
};
struct AvcDecAttr
{
u32 unk;
be_t<u32> mem_size;
be_t<u32> mem_align;
};
error_code avcDecQueryMemory(ppu_thread& ppu, vm::cptr<AvcDecParams> params, vm::ptr<AvcDecAttr> attr);
void avcDecGetVersion(ppu_thread& ppu, vm::ptr<u32> version);
error_code avcDecQueryCharacteristics(ppu_thread& ppu, vm::ptr<u32> unk);
-87
View File
@@ -1,87 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libdivx311dec.h"
LOG_CHANNEL(libdivx311dec)
template<>
void fmt_class_string<Divx311DecError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(DIVX311_DEC_ERROR_ARG);
}
return unknown;
});
}
error_code divx311DecQueryAttr([[maybe_unused]] ppu_thread& ppu, vm::cptr<DivxDecParams> params, vm::ptr<u32> memSize, vm::ptr<u32> version)
{
libdivx311dec.todo("divx311DecQueryAttr(params=*0x%x, memSize=*0x%x, version=*0x%x)", params, memSize, version);
return CELL_OK;
}
error_code divx311DecOpen()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecClose()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecReset()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecFlushPicture()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecGetNumOfPictures()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecGetPicture()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecDecodeAu()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
error_code divx311DecReleasePicture()
{
UNIMPLEMENTED_FUNC(libdivx311dec);
return CELL_OK;
}
DECLARE(ppu_module_manager::libdivx311dec)("libdivx311dec", []
{
REG_FUNC(libdivx311dec, divx311DecQueryAttr);
REG_FUNC(libdivx311dec, divx311DecOpen);
REG_FUNC(libdivx311dec, divx311DecClose);
REG_FUNC(libdivx311dec, divx311DecReset);
REG_FUNC(libdivx311dec, divx311DecFlushPicture);
REG_FUNC(libdivx311dec, divx311DecGetNumOfPictures);
REG_FUNC(libdivx311dec, divx311DecGetPicture);
REG_FUNC(libdivx311dec, divx311DecDecodeAu);
REG_FUNC(libdivx311dec, divx311DecReleasePicture);
});
-10
View File
@@ -1,10 +0,0 @@
#pragma once
enum Divx311DecError : u32
{
DIVX311_DEC_ERROR_ARG = 0x80615502,
};
struct DivxDecParams;
error_code divx311DecQueryAttr(ppu_thread& ppu, vm::cptr<DivxDecParams> params, vm::ptr<u32> memSize, vm::ptr<u32> version);
-87
View File
@@ -1,87 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libdivxdec.h"
LOG_CHANNEL(libdivxdec)
template<>
void fmt_class_string<DivxDecError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(DIVX_DEC_ERROR_ARG);
}
return unknown;
});
}
error_code divxDecQueryAttr([[maybe_unused]] ppu_thread& ppu, vm::cptr<DivxDecParams> params, vm::ptr<u32> memSize, vm::ptr<u32> version)
{
libdivxdec.todo("divxDecQueryAttr(params=*0x%x, memSize=*0x%x, version=*0x%x)", params, memSize, version);
return CELL_OK;
}
error_code divxDecOpen()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecClose()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecReset()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecFlushPicture()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecGetNumOfPictures()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecGetPicture()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecDecodeAu()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
error_code divxDecReleasePicture()
{
UNIMPLEMENTED_FUNC(libdivxdec);
return CELL_OK;
}
DECLARE(ppu_module_manager::libdivxdec)("libdivxdec", []
{
REG_FUNC(libdivxdec, divxDecQueryAttr);
REG_FUNC(libdivxdec, divxDecOpen);
REG_FUNC(libdivxdec, divxDecClose);
REG_FUNC(libdivxdec, divxDecReset);
REG_FUNC(libdivxdec, divxDecFlushPicture);
REG_FUNC(libdivxdec, divxDecGetNumOfPictures);
REG_FUNC(libdivxdec, divxDecGetPicture);
REG_FUNC(libdivxdec, divxDecDecodeAu);
REG_FUNC(libdivxdec, divxDecReleasePicture);
});
-16
View File
@@ -1,16 +0,0 @@
#pragma once
enum DivxDecError : u32
{
DIVX_DEC_ERROR_ARG = 0x80615502,
};
struct DivxDecParams
{
be_t<u32> profile_level;
be_t<u32> max_decoded_frame_width;
be_t<u32> max_decoded_frame_height;
be_t<u32> number_of_decoded_frame_buffer;
};
error_code divxDecQueryAttr(ppu_thread& ppu, vm::cptr<DivxDecParams> params, vm::ptr<u32> memSize, vm::ptr<u32> version);
-100
View File
@@ -1,100 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libmvcdec.h"
LOG_CHANNEL(libmvcdec)
template<>
void fmt_class_string<MvcDecError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(MVC_DEC_ERROR_ARG);
}
return unknown;
});
}
error_code mvcDecQueryMemory([[maybe_unused]] ppu_thread& ppu, vm::cptr<AvcDecParams> params, vm::ptr<AvcDecAttr> attr)
{
libmvcdec.todo("mvcDecQueryMemory(params=*0x%x, attr=*0x%x)", params, attr);
return CELL_OK;
}
void mvcDecGetVersion([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> version)
{
libmvcdec.notice("mvcDecGetVersion(version=*0x%x)", version);
if (version)
{
*version = 0x10804;
}
}
error_code mvcDecQueryCharacteristics([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> unk)
{
libmvcdec.notice("mvcDecGetVersion(unk=*0x%x)", unk);
if (!unk)
{
return MVC_DEC_ERROR_ARG;
}
unk[0] = 5; // Command queue depth
unk[1] = 36;
return CELL_OK;
}
error_code mvcDecOpen()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
error_code mvcDecClose()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
error_code mvcDecReset()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
error_code mvcDecFlush()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
error_code mvcDecAccessUnit()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
error_code mvcDecRlsFrame()
{
UNIMPLEMENTED_FUNC(libmvcdec);
return CELL_OK;
}
DECLARE(ppu_module_manager::libmvcdec)("libmvcdec", []
{
REG_FUNC(libmvcdec, mvcDecQueryMemory);
REG_FUNC(libmvcdec, mvcDecGetVersion);
REG_FUNC(libmvcdec, mvcDecQueryCharacteristics);
REG_FUNC(libmvcdec, mvcDecOpen);
REG_FUNC(libmvcdec, mvcDecClose);
REG_FUNC(libmvcdec, mvcDecReset);
REG_FUNC(libmvcdec, mvcDecFlush);
REG_FUNC(libmvcdec, mvcDecAccessUnit);
REG_FUNC(libmvcdec, mvcDecRlsFrame);
});
-13
View File
@@ -1,13 +0,0 @@
#pragma once
enum MvcDecError : u32
{
MVC_DEC_ERROR_ARG = 0x80615901,
};
struct AvcDecAttr;
struct AvcDecParams;
error_code mvcDecQueryMemory(ppu_thread& ppu, vm::cptr<AvcDecParams> params, vm::ptr<AvcDecAttr> attr);
void mvcDecGetVersion(ppu_thread& ppu, vm::ptr<u32> version);
error_code mvcDecQueryCharacteristics(ppu_thread& ppu, vm::ptr<u32> unk);
-165
View File
@@ -1,165 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libsjvtd.h"
LOG_CHANNEL(libsjvtd)
template<>
void fmt_class_string<SjvtdError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(SJVTD_ERROR_ARG);
}
return unknown;
});
}
error_code sjvtdGetMemorySize([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel)
{
libsjvtd.todo("sjvtdGetMemorySize(memSize=*0x%x, profileLevel=%d)", memSize, +profileLevel);
return CELL_OK;
}
error_code sjvtdGetMemorySize2([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<SjvtdParams> params)
{
libsjvtd.todo("sjvtdGetMemorySize2(memSize=*0x%x, profileLevel=%d, params=*0x%x)", memSize, profileLevel, params);
return CELL_OK;
}
error_code sjvtdGetVersionNumber([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> version)
{
libsjvtd.notice("sjvtdGetVersionNumber(version=*0x%x)", version);
if (!version)
{
return SJVTD_ERROR_ARG;
}
*version = 0x1050000;
return CELL_OK;
}
error_code sjvtdInitialize()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdCreateInstance2()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdReleaseInstance()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdCancelDecode()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdFlushPicture()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetNumPicture()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetPicture()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdReleasePicture()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetAuxData()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetSideInfoSeq()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetSideInfoPic()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdSetAuxData()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdSetDecodeMode()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdDecodePicture()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdGetExistenceFlag()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
error_code sjvtdDiscontinue()
{
UNIMPLEMENTED_FUNC(libsjvtd);
return CELL_OK;
}
DECLARE(ppu_module_manager::libsjvtd)("libsjvtd", []
{
REG_FUNC(libsjvtd, sjvtdGetMemorySize);
REG_FUNC(libsjvtd, sjvtdGetMemorySize2);
REG_FUNC(libsjvtd, sjvtdGetVersionNumber);
REG_FUNC(libsjvtd, sjvtdInitialize);
REG_FUNC(libsjvtd, sjvtdCreateInstance2);
REG_FUNC(libsjvtd, sjvtdReleaseInstance);
REG_FUNC(libsjvtd, sjvtdCancelDecode);
REG_FUNC(libsjvtd, sjvtdFlushPicture);
REG_FUNC(libsjvtd, sjvtdGetNumPicture);
REG_FUNC(libsjvtd, sjvtdGetPicture);
REG_FUNC(libsjvtd, sjvtdReleasePicture);
REG_FUNC(libsjvtd, sjvtdGetAuxData);
REG_FUNC(libsjvtd, sjvtdGetSideInfoSeq);
REG_FUNC(libsjvtd, sjvtdGetSideInfoPic);
REG_FUNC(libsjvtd, sjvtdSetAuxData);
REG_FUNC(libsjvtd, sjvtdSetDecodeMode);
REG_FUNC(libsjvtd, sjvtdDecodePicture);
REG_FUNC(libsjvtd, sjvtdGetExistenceFlag);
REG_FUNC(libsjvtd, sjvtdDiscontinue);
});
-39
View File
@@ -1,39 +0,0 @@
#pragma once
enum SjvtdError : u32
{
SJVTD_ERROR_ARG = 0x80615841,
};
enum SjvtdProfileLevel : u8
{
SJVTD_LEVEL_1P0 = 1,
SJVTD_LEVEL_1P1,
SJVTD_LEVEL_1P2,
SJVTD_LEVEL_1P3,
SJVTD_LEVEL_2P0,
SJVTD_LEVEL_2P1,
SJVTD_LEVEL_2P2,
SJVTD_LEVEL_3P0,
SJVTD_LEVEL_3P1,
SJVTD_LEVEL_3P2,
SJVTD_LEVEL_4P0,
SJVTD_LEVEL_4P1,
SJVTD_LEVEL_4P2
};
struct SjvtdParams
{
be_t<u32> unk1;
be_t<u32> unk2;
be_t<u32> unk3;
be_t<s32> max_decoded_frame_width;
be_t<s32> max_decoded_frame_height;
be_t<u32> enable_deblocking_filter;
be_t<u32> unk;
be_t<u32> number_of_decoded_frame_buffer;
};
error_code sjvtdGetMemorySize(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel);
error_code sjvtdGetMemorySize2(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<SjvtdParams> params);
error_code sjvtdGetVersionNumber(ppu_thread& ppu, vm::ptr<u32> version);
-179
View File
@@ -1,179 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libsmvd2.h"
LOG_CHANNEL(libsmvd2)
template<>
void fmt_class_string<Smvd2Error>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(SMVD2_ERROR_ARG);
}
return unknown;
});
}
error_code smvd2GetMemorySize([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel)
{
libsmvd2.todo("smvd2GetMemorySize(memSize=*0x%x, profileLevel=%d)", memSize, +profileLevel);
return CELL_OK;
}
error_code smvd2GetMemorySize2([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<Smvd2Params> params)
{
libsmvd2.todo("smvd2GetMemorySize2(memSize=*0x%x, profileLevel=%d, params=*0x%x)", memSize, profileLevel, params);
return CELL_OK;
}
error_code smvd2GetVersionNumber([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> version)
{
libsmvd2.notice("smvd2GetVersionNumber(version=*0x%x)", version);
if (!version)
{
return SMVD2_ERROR_ARG;
}
*version = 0x1030000;
return CELL_OK;
}
error_code smvd2Initialize()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2CreateInstance2()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2ReleaseInstance()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2CancelDecode()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2FlushPicture()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetNumPicture()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetPicture()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2ReleasePicture()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetAuxData()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetSideInfoSeq()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetBnrData()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetSideInfoPic()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2SetAuxData()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2SetDecodeMode()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2DecodePicture()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2DecodePicture2()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2GetExistenceFlag()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
error_code smvd2Discontinue()
{
UNIMPLEMENTED_FUNC(libsmvd2);
return CELL_OK;
}
DECLARE(ppu_module_manager::libsmvd2)("libsmvd2", []
{
REG_FUNC(libsmvd2, smvd2GetMemorySize);
REG_FUNC(libsmvd2, smvd2GetMemorySize2);
REG_FUNC(libsmvd2, smvd2GetVersionNumber);
REG_FUNC(libsmvd2, smvd2Initialize);
REG_FUNC(libsmvd2, smvd2CreateInstance2);
REG_FUNC(libsmvd2, smvd2ReleaseInstance);
REG_FUNC(libsmvd2, smvd2CancelDecode);
REG_FUNC(libsmvd2, smvd2FlushPicture);
REG_FUNC(libsmvd2, smvd2GetNumPicture);
REG_FUNC(libsmvd2, smvd2GetPicture);
REG_FUNC(libsmvd2, smvd2ReleasePicture);
REG_FUNC(libsmvd2, smvd2GetAuxData);
REG_FUNC(libsmvd2, smvd2GetSideInfoSeq);
REG_FUNC(libsmvd2, smvd2GetBnrData);
REG_FUNC(libsmvd2, smvd2GetSideInfoPic);
REG_FUNC(libsmvd2, smvd2SetAuxData);
REG_FUNC(libsmvd2, smvd2SetDecodeMode);
REG_FUNC(libsmvd2, smvd2DecodePicture);
REG_FUNC(libsmvd2, smvd2DecodePicture2);
REG_FUNC(libsmvd2, smvd2GetExistenceFlag);
REG_FUNC(libsmvd2, smvd2Discontinue);
});
-27
View File
@@ -1,27 +0,0 @@
#pragma once
enum Smvd2Error : u32
{
SMVD2_ERROR_ARG = 0x80615041,
};
enum Smvd2ProfileLevel : u32
{
SMVD2_MP_LL = 1,
SMVD2_MP_ML,
SMVD2_MP_H14,
SMVD2_MP_HL
};
struct Smvd2Params
{
be_t<u32> unk1;
be_t<u32> unk2;
be_t<u32> unk3;
be_t<u32> max_decoded_frame_width;
be_t<u32> max_decoded_frame_height;
};
error_code smvd2GetMemorySize(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel);
error_code smvd2GetMemorySize2(ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<Smvd2Params> params);
error_code smvd2GetVersionNumber(ppu_thread& ppu, vm::ptr<u32> version);
-158
View File
@@ -1,158 +0,0 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "libsmvd4.h"
LOG_CHANNEL(libsmvd4)
template<>
void fmt_class_string<Smvd4Error>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(SMVD4_ERROR_ARG);
}
return unknown;
});
}
error_code smvd4GetMemorySize([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel)
{
libsmvd4.todo("smvd4GetMemorySize(memSize=*0x%x, profileLevel=%d)", memSize, +profileLevel);
return CELL_OK;
}
error_code smvd4GetMemorySize2([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> memSize, u32 profileLevel, vm::cptr<Smvd4Params> params)
{
libsmvd4.todo("smvd4GetMemorySize2(memSize=*0x%x, profileLevel=%d, params=*0x%x)", memSize, profileLevel, params);
return CELL_OK;
}
error_code smvd4GetVersionNumber([[maybe_unused]] ppu_thread& ppu, vm::ptr<u32> version)
{
libsmvd4.notice("smvd4GetVersionNumber(version=*0x%x)", version);
if (!version)
{
return SMVD4_ERROR_ARG;
}
*version = 0x1080000;
return CELL_OK;
}
error_code smvd4Initialize()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4CreateInstance2()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4ReleaseInstance()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4CancelDecode()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4FlushPicture()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetNumPicture()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetPicture()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4ReleasePicture()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetAuxData()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetSideInfoSeq()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetSideInfoPic()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4SetAuxData()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4DecodePicture()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4GetExistenceFlag()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
error_code smvd4Discontinue()
{
UNIMPLEMENTED_FUNC(libsmvd4);
return CELL_OK;
}
DECLARE(ppu_module_manager::libsmvd4)("libsmvd4", []
{
REG_FUNC(libsmvd4, smvd4GetMemorySize);
REG_FUNC(libsmvd4, smvd4GetMemorySize2);
REG_FUNC(libsmvd4, smvd4GetVersionNumber);
REG_FUNC(libsmvd4, smvd4Initialize);
REG_FUNC(libsmvd4, smvd4CreateInstance2);
REG_FUNC(libsmvd4, smvd4ReleaseInstance);
REG_FUNC(libsmvd4, smvd4CancelDecode);
REG_FUNC(libsmvd4, smvd4FlushPicture);
REG_FUNC(libsmvd4, smvd4GetNumPicture);
REG_FUNC(libsmvd4, smvd4GetPicture);
REG_FUNC(libsmvd4, smvd4ReleasePicture);
REG_FUNC(libsmvd4, smvd4GetAuxData);
REG_FUNC(libsmvd4, smvd4GetSideInfoSeq);
REG_FUNC(libsmvd4, smvd4GetSideInfoPic);
REG_FUNC(libsmvd4, smvd4SetAuxData);
REG_FUNC(libsmvd4, smvd4DecodePicture);
REG_FUNC(libsmvd4, smvd4GetExistenceFlag);
REG_FUNC(libsmvd4, smvd4Discontinue);
});

Some files were not shown because too many files have changed in this diff Show More