Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| df718bcb0f | |||
| 8eefbcae45 | |||
| 8cf28730cb | |||
| f894e2b9a2 | |||
| e3cd31f057 | |||
| 05086cda3b | |||
| 7c2d6f8a23 | |||
| 7423abb136 | |||
| 310fa7127d | |||
| 3250c16cdc | |||
| 02f35383bd | |||
| 1d5fef4930 | |||
| dddea008e9 | |||
| dd8ec8f09e | |||
| 98dbbd84ac | |||
| 382a27cb2f | |||
| eeda958f33 | |||
| 2f9cac8d18 | |||
| 9d432187aa | |||
| b13165f95a | |||
| 110c20d25f | |||
| 4def7f143c | |||
| 908d524631 | |||
| 6c74274502 | |||
| ee8cd82e9d | |||
| 820e692e57 | |||
| 5b95cfda40 | |||
| b2c4fed39c | |||
| 96c6dc01eb | |||
| f545532556 | |||
| 8ac9968096 | |||
| a9ee9a69a4 | |||
| 46a50265a3 | |||
| 41e9e0b965 | |||
| 388d090b91 | |||
| 1a60fb3c96 | |||
| baa2768a69 | |||
| 04fb86556a | |||
| 90cf47cdce | |||
| bf96cbe980 | |||
| 66dc1cc15d | |||
| a05e3f02b8 | |||
| 8ec01450f8 | |||
| b2962e0522 | |||
| 8980fc5524 | |||
| f54da22f6f | |||
| cebc0ec4a1 | |||
| 812224f7f7 | |||
| d78e2dad29 | |||
| 7e35679ec2 | |||
| b39f457363 | |||
| 18b7955384 | |||
| 0e625e6928 | |||
| 65ae85061f | |||
| e2c1547d95 | |||
| 2d5a427bd4 | |||
| 45bd0d1f25 | |||
| f38084f0cf | |||
| 0d929a210f | |||
| 057f5beac6 | |||
| 26021e11f7 | |||
| 941ecc76a1 | |||
| 12806af6aa | |||
| 55886b0a50 | |||
| 577b5ef2bd | |||
| 780c38a5e5 | |||
| 6756bf7d4b | |||
| 9c0b2338cf | |||
| a0ef1a672c | |||
| 1fd265d316 | |||
| e3b23822fd | |||
| ab3c8268f0 | |||
| 6f306121a6 | |||
| 8399516475 | |||
| a60ea61291 | |||
| 64cff74861 | |||
| e2c1e656b9 | |||
| cdc1d0c02b | |||
| 151a0955cf | |||
| 40406bd3fe | |||
| 1cc3e6e510 | |||
| 064ab58f3c | |||
| 85c0a2e602 | |||
| 809e880bd1 | |||
| 7df093c94b | |||
| f572e29a13 | |||
| 681a6ef73c | |||
| bf37087a10 | |||
| a18b46d8ad | |||
| 74bb90b414 | |||
| 8334767c16 | |||
| 0d126afb1f | |||
| b7d80ab335 | |||
| b0e376ae76 | |||
| a3bcb6c15a | |||
| 88269636d3 | |||
| 4f5076346d | |||
| 89de913e95 | |||
| 0e73c4598e | |||
| 6b8aef9fdd | |||
| 1811dd67bf | |||
| 6d4379059c | |||
| a0f3704b41 | |||
| 9274b3f14d | |||
| 0a3e540a10 | |||
| 4657afd899 | |||
| 2082f06443 | |||
| b49f8623f6 | |||
| 69e4138223 | |||
| 5fec8666e3 | |||
| 8af4a94864 | |||
| ab873129f8 | |||
| 6155207407 | |||
| 98a58daf57 | |||
| 0aaa40cd53 | |||
| a6b44ea1bb | |||
| ca0ca2e5a8 | |||
| 14a388b3fe | |||
| 82a8d96fba | |||
| ad3ea966cb | |||
| 8d9dd1d19c | |||
| 337ee77a99 | |||
| c09991ebdb | |||
| 5188293242 | |||
| 2805fe0a06 | |||
| b4757b514d | |||
| 630edde10f | |||
| e9e139c364 | |||
| 60c01ef9a9 | |||
| 5dbadccd7f | |||
| 49a968219f | |||
| 8b934abcf2 | |||
| fa74d3e88c | |||
| 1123e25136 | |||
| 7c15001042 | |||
| bf388e5428 | |||
| 661be41c5a | |||
| 8be4ac6869 | |||
| 81f9259063 | |||
| a97424d46c | |||
| b639f3c8ec | |||
| 13ca1a7f09 | |||
| 16098c38c8 | |||
| c4b259e0f8 | |||
| e04855a0da | |||
| 8199f97e7a | |||
| 2eef3ab645 | |||
| d56ec56458 | |||
| 0293415db1 | |||
| 6e935d9d84 | |||
| 99ae561caa | |||
| 3f8421fc17 | |||
| 324b1039cf | |||
| 961d905433 | |||
| 3c79f3943f | |||
| 1e7b2c052a | |||
| ff082b98cb | |||
| 3236931416 | |||
| ed0c798252 | |||
| 5943b802d7 | |||
| b875a86e1d | |||
| 0a35a62235 | |||
| e98b07de03 | |||
| de5217745c | |||
| ec53adc2b7 | |||
| b57ab74ee7 | |||
| 69368d972d |
@@ -7,11 +7,12 @@ git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ { print $3 }'
|
||||
|
||||
# Prefer newer Clang than in base system (see also .ci/install-freebsd.sh)
|
||||
# libc++ isn't in llvm* packages, so download manually
|
||||
fetch https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-13.0.1-rc1.tar.gz
|
||||
tar xf llvm*.tar.gz
|
||||
export CC=clang13 CXX=clang++13
|
||||
fetch https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/llvm-project-15.0.6.src.tar.xz
|
||||
tar xf llvm*.tar.xz
|
||||
export CC=clang15 CXX=clang++15
|
||||
cmake -B libcxx_build -G Ninja -S llvm*/libcxx \
|
||||
-DLLVM_CCACHE_BUILD=ON \
|
||||
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=libcxx_prefix
|
||||
cmake --build libcxx_build
|
||||
cmake --install libcxx_build
|
||||
@@ -20,6 +21,7 @@ export LDFLAGS="$LDFLAGS -nostdlib++ -L$PWD/libcxx_prefix/lib -l:libc++.a -lcxxr
|
||||
|
||||
CONFIGURE_ARGS="
|
||||
-DWITH_LLVM=OFF
|
||||
-DUSE_SDL=OFF
|
||||
-DUSE_PRECOMPILED_HEADERS=OFF
|
||||
-DUSE_NATIVE_INSTRUCTIONS=OFF
|
||||
-DUSE_SYSTEM_FFMPEG=ON
|
||||
|
||||
@@ -51,6 +51,7 @@ cmake .. \
|
||||
-DCMAKE_AR="$AR" \
|
||||
-DCMAKE_RANLIB="$RANLIB" \
|
||||
-DUSE_SYSTEM_CURL=ON \
|
||||
-DUSE_SDL=OFF \
|
||||
-DOpenGL_GL_PREFERENCE=LEGACY \
|
||||
-G Ninja
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVer
|
||||
mkdir build && cd build || exit 1
|
||||
|
||||
cmake .. \
|
||||
-DUSE_DISCORD_RPC=OFF -DUSE_VULKAN=ON -DUSE_ALSA=OFF -DUSE_PULSE=OFF -DUSE_AUDIOUNIT=ON \
|
||||
-DUSE_SDL=ON -DUSE_DISCORD_RPC=OFF -DUSE_VULKAN=ON -DUSE_ALSA=OFF -DUSE_PULSE=OFF -DUSE_AUDIOUNIT=ON \
|
||||
-DLLVM_CCACHE_BUILD=OFF -DLLVM_TARGETS_TO_BUILD="X86" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF \
|
||||
-DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF \
|
||||
-DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_PERF=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF \
|
||||
|
||||
@@ -9,7 +9,7 @@ export ASSUME_ALWAYS_YES=true
|
||||
pkg info # debug
|
||||
|
||||
# Prefer newer Clang than in base system (see also .ci/build-freebsd.sh)
|
||||
pkg install llvm13
|
||||
pkg install llvm15
|
||||
|
||||
# Mandatory dependencies (qt5-dbus and qt5-gui are pulled via qt5-widgets)
|
||||
pkg install git ccache cmake ninja qt5-qmake qt5-buildtools qt5-widgets qt5-concurrent qt5-multimedia qt5-svg glew openal-soft ffmpeg
|
||||
|
||||
@@ -21,7 +21,7 @@ QT_MM_URL="${QT_HOST}${QT_PREFIX}qtmultimedia${QT_SUFFIX}"
|
||||
QT_SVG_URL="${QT_HOST}${QT_PREFIX}qtsvg${QT_SUFFIX}"
|
||||
LLVMLIBS_URL='https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win/llvmlibs_mt.7z'
|
||||
GLSLANG_URL='https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z'
|
||||
VULKAN_SDK_URL="https://www.dropbox.com/s/o918fc11pfk8x9c/VulkanSDK-${VULKAN_VER}-Installer.exe"
|
||||
VULKAN_SDK_URL="https://www.dropbox.com/s/cs77c3iv5mbo0bt/VulkanSDK-${VULKAN_VER}-Installer.exe"
|
||||
|
||||
DEP_URLS=" \
|
||||
$QT_BASE_URL \
|
||||
|
||||
+3
-3
@@ -23,8 +23,8 @@ windows_task:
|
||||
QT_VER_MSVC: 'msvc2019'
|
||||
QT_DATE: '202011130602'
|
||||
QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64
|
||||
VULKAN_VER: '1.3.204.0'
|
||||
VULKAN_SDK_SHA: '41f4996335cc5a545d7b2f6e5ff29cf3867789aae4be053a7069aa93408861fa'
|
||||
VULKAN_VER: '1.3.224.1'
|
||||
VULKAN_SDK_SHA: '2029e652e39ee6a6036cff3765da31e1e6c595fd2413d3cd111dfab7855621ea'
|
||||
VULKAN_SDK: C:\VulkanSDK\${VULKAN_VER}
|
||||
CACHE_DIR: "./cache"
|
||||
UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e
|
||||
@@ -61,7 +61,7 @@ windows_task:
|
||||
|
||||
linux_task:
|
||||
container:
|
||||
image: rpcs3/rpcs3-ci-bionic:1.5
|
||||
image: rpcs3/rpcs3-ci-bionic:1.6
|
||||
cpu: 4
|
||||
memory: 16G
|
||||
env:
|
||||
|
||||
@@ -76,3 +76,7 @@
|
||||
path = 3rdparty/SoundTouch/soundtouch
|
||||
url = ../../RPCS3/soundtouch.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/libsdl-org/SDL"]
|
||||
path = 3rdparty/libsdl-org/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
ignore = dirty
|
||||
|
||||
Vendored
+25
-2
@@ -165,10 +165,10 @@ if(USE_VULKAN)
|
||||
message("-- RPCS3: MoltenVK submodule")
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK"
|
||||
)
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK"
|
||||
)
|
||||
|
||||
add_library(moltenvk_lib SHARED IMPORTED)
|
||||
@@ -329,6 +329,28 @@ add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
|
||||
# CURL
|
||||
add_subdirectory(curl EXCLUDE_FROM_ALL)
|
||||
|
||||
# SDL2
|
||||
set(SDL2_TARGET 3rdparty_dummy_lib)
|
||||
if(USE_SDL)
|
||||
if(USE_SYSTEM_SDL)
|
||||
find_package(SDL2)
|
||||
if(SDL2_FOUND AND NOT SDL2_VERSION VERSION_LESS 2.24.0)
|
||||
message(STATUS "Using system SDL2")
|
||||
add_library(3rdparty_sdl2 INTERFACE)
|
||||
target_compile_definitions(3rdparty_sdl2 INTERFACE -DHAVE_SDL2=1)
|
||||
set(SDL2_TARGET 3rdparty_sdl2)
|
||||
else()
|
||||
message(FATAL_ERROR "SDL2 is not available on this system")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using static SDL2 from 3rdparty")
|
||||
add_library(3rdparty_sdl2 INTERFACE)
|
||||
target_compile_definitions(3rdparty_sdl2 INTERFACE -DHAVE_SDL2=1)
|
||||
add_subdirectory(libsdl-org EXCLUDE_FROM_ALL)
|
||||
set(SDL2_TARGET 3rdparty_sdl2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# add nice ALIAS targets for ease of use
|
||||
if(USE_SYSTEM_LIBUSB)
|
||||
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
|
||||
@@ -355,3 +377,4 @@ add_library(3rdparty::glew ALIAS 3rdparty_glew)
|
||||
add_library(3rdparty::wolfssl ALIAS wolfssl)
|
||||
add_library(3rdparty::libcurl ALIAS libcurl)
|
||||
add_library(3rdparty::soundtouch ALIAS soundtouch)
|
||||
add_library(3rdparty::sdl2 ALIAS ${SDL2_TARGET})
|
||||
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ include(ExternalProject)
|
||||
|
||||
ExternalProject_Add(moltenvk
|
||||
GIT_REPOSITORY https://github.com/KhronosGroup/MoltenVK.git
|
||||
GIT_TAG 260bad4
|
||||
GIT_TAG a307b24
|
||||
BUILD_IN_SOURCE 1
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
|
||||
CONFIGURE_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/fetchDependencies" --macos
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/SPIRV/SPIRV-Headers updated: b2a156e1c0...85a1ed200d
Vendored
+1
-1
Submodule 3rdparty/SPIRV/SPIRV-Tools updated: 5e61ea2098...eb0a36633d
Vendored
+1
-1
Submodule 3rdparty/curl/curl updated: 45ac4d0194...c12fb3ddaf
Vendored
+9
-3
@@ -66,12 +66,12 @@
|
||||
<ClCompile Include="curl\lib\base64.c" />
|
||||
<ClCompile Include="curl\lib\bufref.c" />
|
||||
<ClCompile Include="curl\lib\c-hyper.c" />
|
||||
<ClCompile Include="curl\lib\cfilters.c" />
|
||||
<ClCompile Include="curl\lib\conncache.c" />
|
||||
<ClCompile Include="curl\lib\connect.c" />
|
||||
<ClCompile Include="curl\lib\content_encoding.c" />
|
||||
<ClCompile Include="curl\lib\cookie.c" />
|
||||
<ClCompile Include="curl\lib\curl_addrinfo.c" />
|
||||
<ClCompile Include="curl\lib\curl_ctype.c" />
|
||||
<ClCompile Include="curl\lib\curl_des.c" />
|
||||
<ClCompile Include="curl\lib\curl_endian.c" />
|
||||
<ClCompile Include="curl\lib\curl_fnmatch.c" />
|
||||
@@ -90,7 +90,6 @@
|
||||
<ClCompile Include="curl\lib\curl_threads.c" />
|
||||
<ClCompile Include="curl\lib\dict.c" />
|
||||
<ClCompile Include="curl\lib\doh.c" />
|
||||
<ClCompile Include="curl\lib\dotdot.c" />
|
||||
<ClCompile Include="curl\lib\dynbuf.c" />
|
||||
<ClCompile Include="curl\lib\easy.c" />
|
||||
<ClCompile Include="curl\lib\easygetopt.c" />
|
||||
@@ -123,7 +122,7 @@
|
||||
<ClCompile Include="curl\lib\http_negotiate.c" />
|
||||
<ClCompile Include="curl\lib\http_ntlm.c" />
|
||||
<ClCompile Include="curl\lib\http_proxy.c" />
|
||||
<ClCompile Include="curl\lib\idn_win32.c" />
|
||||
<ClCompile Include="curl\lib\idn.c" />
|
||||
<ClCompile Include="curl\lib\if2ip.c" />
|
||||
<ClCompile Include="curl\lib\imap.c" />
|
||||
<ClCompile Include="curl\lib\inet_ntop.c" />
|
||||
@@ -140,6 +139,7 @@
|
||||
<ClCompile Include="curl\lib\multi.c" />
|
||||
<ClCompile Include="curl\lib\netrc.c" />
|
||||
<ClCompile Include="curl\lib\nonblock.c" />
|
||||
<ClCompile Include="curl\lib\noproxy.c" />
|
||||
<ClCompile Include="curl\lib\openldap.c" />
|
||||
<ClCompile Include="curl\lib\parsedate.c" />
|
||||
<ClCompile Include="curl\lib\pingpong.c" />
|
||||
@@ -215,6 +215,7 @@
|
||||
<ClCompile Include="curl\lib\vtls\sectransp.c" />
|
||||
<ClCompile Include="curl\lib\vtls\vtls.c" />
|
||||
<ClCompile Include="curl\lib\vtls\wolfssl.c" />
|
||||
<ClCompile Include="curl\lib\ws.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="curl\include\curl\curl.h" />
|
||||
@@ -232,6 +233,7 @@
|
||||
<ClInclude Include="curl\lib\asyn.h" />
|
||||
<ClInclude Include="curl\lib\bufref.h" />
|
||||
<ClInclude Include="curl\lib\c-hyper.h" />
|
||||
<ClInclude Include="curl\lib\cfilters.h" />
|
||||
<ClInclude Include="curl\lib\config-amigaos.h" />
|
||||
<ClInclude Include="curl\lib\config-dos.h" />
|
||||
<ClInclude Include="curl\lib\config-mac.h" />
|
||||
@@ -288,6 +290,7 @@
|
||||
<ClInclude Include="curl\lib\formdata.h" />
|
||||
<ClInclude Include="curl\lib\ftp.h" />
|
||||
<ClInclude Include="curl\lib\ftplistparser.h" />
|
||||
<ClInclude Include="curl\lib\functypes.h" />
|
||||
<ClInclude Include="curl\lib\getinfo.h" />
|
||||
<ClInclude Include="curl\lib\gopher.h" />
|
||||
<ClInclude Include="curl\lib\h2h3.h" />
|
||||
@@ -303,6 +306,7 @@
|
||||
<ClInclude Include="curl\lib\http_negotiate.h" />
|
||||
<ClInclude Include="curl\lib\http_ntlm.h" />
|
||||
<ClInclude Include="curl\lib\http_proxy.h" />
|
||||
<ClInclude Include="curl\lib\idn.h" />
|
||||
<ClInclude Include="curl\lib\if2ip.h" />
|
||||
<ClInclude Include="curl\lib\imap.h" />
|
||||
<ClInclude Include="curl\lib\inet_ntop.h" />
|
||||
@@ -315,6 +319,7 @@
|
||||
<ClInclude Include="curl\lib\multiif.h" />
|
||||
<ClInclude Include="curl\lib\netrc.h" />
|
||||
<ClInclude Include="curl\lib\nonblock.h" />
|
||||
<ClInclude Include="curl\lib\noproxy.h" />
|
||||
<ClInclude Include="curl\lib\parsedate.h" />
|
||||
<ClInclude Include="curl\lib\pingpong.h" />
|
||||
<ClInclude Include="curl\lib\pop3.h" />
|
||||
@@ -380,6 +385,7 @@
|
||||
<ClInclude Include="curl\lib\vtls\sectransp.h" />
|
||||
<ClInclude Include="curl\lib\vtls\vtls.h" />
|
||||
<ClInclude Include="curl\lib\vtls\wolfssl.h" />
|
||||
<ClInclude Include="curl\lib\ws.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="curl\lib\libcurl.rc" />
|
||||
|
||||
+27
-9
@@ -48,9 +48,6 @@
|
||||
<ClCompile Include="curl\lib\curl_addrinfo.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\curl_ctype.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\curl_des.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -105,9 +102,6 @@
|
||||
<ClCompile Include="curl\lib\doh.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\dotdot.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\easy.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -180,9 +174,6 @@
|
||||
<ClCompile Include="curl\lib\http_proxy.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\idn_win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\if2ip.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -483,6 +474,18 @@
|
||||
<ClCompile Include="curl\lib\fopen.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\noproxy.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\ws.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\cfilters.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\idn.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="curl\include\curl\curl.h">
|
||||
@@ -974,6 +977,21 @@
|
||||
<ClInclude Include="curl\lib\fopen.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\functypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\noproxy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\ws.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\cfilters.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\idn.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="curl\lib\libcurl.rc">
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/hidapi/hidapi updated: c2aa9dd37c...a3ce129931
Vendored
+1
-1
Submodule 3rdparty/libpng/libpng updated: 0a158f3506...07b8803110
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
option(SDL2_DISABLE_SDL2MAIN "" ON)
|
||||
option(SDL2_DISABLE_INSTALL "" ON)
|
||||
option(SDL2_DISABLE_UNINSTALL "" ON)
|
||||
set(SDL_SHARED OFF)
|
||||
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
|
||||
set(SDL_STATIC ON)
|
||||
set(SDL_STATIC_ENABLED_BY_DEFAULT ON)
|
||||
set(SDL_TEST OFF)
|
||||
set(SDL_TEST_ENABLED_BY_DEFAULT OFF)
|
||||
set(OPT_DEF_LIBC ON)
|
||||
add_subdirectory(SDL EXCLUDE_FROM_ALL)
|
||||
+1
Submodule 3rdparty/libsdl-org/SDL added at f070c83a60
Vendored
+461
@@ -0,0 +1,461 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SDL\include\begin_code.h" />
|
||||
<ClInclude Include="SDL\include\close_code.h" />
|
||||
<ClInclude Include="SDL\include\SDL.h" />
|
||||
<ClInclude Include="SDL\include\SDL_assert.h" />
|
||||
<ClInclude Include="SDL\include\SDL_atomic.h" />
|
||||
<ClInclude Include="SDL\include\SDL_audio.h" />
|
||||
<ClInclude Include="SDL\include\SDL_bits.h" />
|
||||
<ClInclude Include="SDL\include\SDL_blendmode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_clipboard.h" />
|
||||
<ClInclude Include="SDL\include\SDL_config.h" />
|
||||
<ClInclude Include="SDL\include\SDL_config_windows.h" />
|
||||
<ClInclude Include="SDL\include\SDL_copying.h" />
|
||||
<ClInclude Include="SDL\include\SDL_cpuinfo.h" />
|
||||
<ClInclude Include="SDL\include\SDL_egl.h" />
|
||||
<ClInclude Include="SDL\include\SDL_endian.h" />
|
||||
<ClInclude Include="SDL\include\SDL_error.h" />
|
||||
<ClInclude Include="SDL\include\SDL_events.h" />
|
||||
<ClInclude Include="SDL\include\SDL_filesystem.h" />
|
||||
<ClInclude Include="SDL\include\SDL_gamecontroller.h" />
|
||||
<ClInclude Include="SDL\include\SDL_gesture.h" />
|
||||
<ClInclude Include="SDL\include\SDL_guid.h" />
|
||||
<ClInclude Include="SDL\include\SDL_haptic.h" />
|
||||
<ClInclude Include="SDL\include\SDL_hints.h" />
|
||||
<ClInclude Include="SDL\include\SDL_hidapi.h" />
|
||||
<ClInclude Include="SDL\include\SDL_joystick.h" />
|
||||
<ClInclude Include="SDL\include\SDL_keyboard.h" />
|
||||
<ClInclude Include="SDL\include\SDL_keycode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_loadso.h" />
|
||||
<ClInclude Include="SDL\include\SDL_locale.h" />
|
||||
<ClInclude Include="SDL\include\SDL_log.h" />
|
||||
<ClInclude Include="SDL\include\SDL_main.h" />
|
||||
<ClInclude Include="SDL\include\SDL_messagebox.h" />
|
||||
<ClInclude Include="SDL\include\SDL_metal.h" />
|
||||
<ClInclude Include="SDL\include\SDL_misc.h" />
|
||||
<ClInclude Include="SDL\include\SDL_mouse.h" />
|
||||
<ClInclude Include="SDL\include\SDL_mutex.h" />
|
||||
<ClInclude Include="SDL\include\SDL_name.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengl.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengl_glext.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2ext.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2platform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_khrplatform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_pixels.h" />
|
||||
<ClInclude Include="SDL\include\SDL_platform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_power.h" />
|
||||
<ClInclude Include="SDL\include\SDL_quit.h" />
|
||||
<ClInclude Include="SDL\include\SDL_rect.h" />
|
||||
<ClInclude Include="SDL\include\SDL_render.h" />
|
||||
<ClInclude Include="SDL\include\SDL_revision.h" />
|
||||
<ClInclude Include="SDL\include\SDL_rwops.h" />
|
||||
<ClInclude Include="SDL\include\SDL_scancode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_sensor.h" />
|
||||
<ClInclude Include="SDL\include\SDL_shape.h" />
|
||||
<ClInclude Include="SDL\include\SDL_stdinc.h" />
|
||||
<ClInclude Include="SDL\include\SDL_surface.h" />
|
||||
<ClInclude Include="SDL\include\SDL_system.h" />
|
||||
<ClInclude Include="SDL\include\SDL_syswm.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_assert.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_common.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_compare.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_crc32.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_font.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_fuzzer.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_harness.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_images.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_log.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_md5.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_memory.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_random.h" />
|
||||
<ClInclude Include="SDL\include\SDL_thread.h" />
|
||||
<ClInclude Include="SDL\include\SDL_timer.h" />
|
||||
<ClInclude Include="SDL\include\SDL_touch.h" />
|
||||
<ClInclude Include="SDL\include\SDL_types.h" />
|
||||
<ClInclude Include="SDL\include\SDL_version.h" />
|
||||
<ClInclude Include="SDL\include\SDL_video.h" />
|
||||
<ClInclude Include="SDL\include\SDL_vulkan.h" />
|
||||
<ClInclude Include="SDL\src\audio\directsound\SDL_directsound.h" />
|
||||
<ClInclude Include="SDL\src\audio\disk\SDL_diskaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\dummy\SDL_dummyaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_audio_c.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_audiodev_c.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_sysaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_wave.h" />
|
||||
<ClInclude Include="SDL\src\audio\wasapi\SDL_wasapi.h" />
|
||||
<ClInclude Include="SDL\src\audio\winmm\SDL_winmm.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_directx.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_hid.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_immdevice.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_windows.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_xinput.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_overrides.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_procs.h" />
|
||||
<ClInclude Include="SDL\src\events\blank_cursor.h" />
|
||||
<ClInclude Include="SDL\src\events\default_cursor.h" />
|
||||
<ClInclude Include="SDL\src\events\scancodes_windows.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_clipboardevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_displayevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_dropevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_events_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_gesture_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_keyboard_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_mouse_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_touch_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_windowevents_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\SDL_haptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\SDL_syshaptic.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_dinputhaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_windowshaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_xinputhaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\hidapi\hidapi\hidapi.h" />
|
||||
<ClInclude Include="SDL\src\hidapi\SDL_hidapi_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\controller_type.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_nintendo.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_gamecontrollerdb.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_joystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_sysjoystick.h" />
|
||||
<ClInclude Include="SDL\src\joystick\usb_ids.h" />
|
||||
<ClInclude Include="SDL\src\joystick\virtual\SDL_virtualjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_dinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_rawinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_windowsjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_xinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\libm\math_libm.h" />
|
||||
<ClInclude Include="SDL\src\libm\math_private.h" />
|
||||
<ClInclude Include="SDL\src\locale\SDL_syslocale.h" />
|
||||
<ClInclude Include="SDL\src\misc\SDL_sysurl.h" />
|
||||
<ClInclude Include="SDL\src\power\SDL_syspower.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d\SDL_shaders_d3d.h" />
|
||||
<ClInclude Include="SDL\src\render\opengles2\SDL_gles2funcs.h" />
|
||||
<ClInclude Include="SDL\src\render\opengles2\SDL_shaders_gles2.h" />
|
||||
<ClInclude Include="SDL\src\render\opengl\SDL_glfuncs.h" />
|
||||
<ClInclude Include="SDL\src\render\opengl\SDL_shaders_gl.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_d3dmath.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_sysrender.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_yuv_sw_c.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendfillrect.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendline.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendpoint.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_draw.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_drawline.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_drawpoint.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_render_sw_c.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_rotate.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_triangle.h" />
|
||||
<ClInclude Include="SDL\src\SDL_assert_c.h" />
|
||||
<ClInclude Include="SDL\src\SDL_dataqueue.h" />
|
||||
<ClInclude Include="SDL\src\SDL_error_c.h" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps3.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_steam.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_wii.c" />
|
||||
<ClCompile Include="SDL\src\SDL_guid.c" />
|
||||
<ClInclude Include="SDL\src\SDL_hints_c.h" />
|
||||
<ClInclude Include="SDL\src\SDL_internal.h" />
|
||||
<ClInclude Include="SDL\src\SDL_list.h" />
|
||||
<ClInclude Include="SDL\src\SDL_log_c.h" />
|
||||
<ClInclude Include="SDL\src\sensor\dummy\SDL_dummysensor.h" />
|
||||
<ClInclude Include="SDL\src\sensor\SDL_sensor_c.h" />
|
||||
<ClInclude Include="SDL\src\sensor\SDL_syssensor.h" />
|
||||
<ClInclude Include="SDL\src\sensor\windows\SDL_windowssensor.h" />
|
||||
<ClInclude Include="SDL\src\thread\SDL_systhread.h" />
|
||||
<ClInclude Include="SDL\src\thread\SDL_thread_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\generic\SDL_syscond_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\windows\SDL_sysmutex_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\windows\SDL_systhread_c.h" />
|
||||
<ClInclude Include="SDL\src\timer\SDL_timer_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullevents_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullframebuffer_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_icd.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_layer.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_platform.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_sdk_platform.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.hpp" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_android.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_beta.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_core.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_directfb.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_fuchsia.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_ggp.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_ios.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_macos.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_metal.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_vi.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_wayland.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_win32.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xcb.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib_xrandr.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_auto.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_copy.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_slow.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_egl_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_pixels_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_rect_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_RLEaccel_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_shape_internals.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_sysvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_vulkan_internal.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_yuv_c.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_msctf.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_vkeys.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsclipboard.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsevents.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsframebuffer.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowskeyboard.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmessagebox.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmodes.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmouse.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengl.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengles.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsshape.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsvulkan.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowswindow.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\wmmsg.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_sse_func.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_std_func.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SDL\src\atomic\SDL_atomic.c" />
|
||||
<ClCompile Include="SDL\src\atomic\SDL_spinlock.c" />
|
||||
<ClCompile Include="SDL\src\audio\directsound\SDL_directsound.c" />
|
||||
<ClCompile Include="SDL\src\audio\disk\SDL_diskaudio.c" />
|
||||
<ClCompile Include="SDL\src\audio\dummy\SDL_dummyaudio.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audio.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiocvt.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiodev.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiotypecvt.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_mixer.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_wave.c" />
|
||||
<ClCompile Include="SDL\src\audio\winmm\SDL_winmm.c" />
|
||||
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi.c" />
|
||||
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi_win32.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_hid.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_immdevice.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_windows.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_xinput.c" />
|
||||
<ClCompile Include="SDL\src\cpuinfo\SDL_cpuinfo.c" />
|
||||
<ClCompile Include="SDL\src\dynapi\SDL_dynapi.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_clipboardevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_displayevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_dropevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_events.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_gesture.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_keyboard.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_mouse.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_quit.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_touch.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_windowevents.c" />
|
||||
<ClCompile Include="SDL\src\file\SDL_rwops.c" />
|
||||
<ClCompile Include="SDL\src\filesystem\windows\SDL_sysfilesystem.c" />
|
||||
<ClCompile Include="SDL\src\haptic\dummy\SDL_syshaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\SDL_haptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_dinputhaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_windowshaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_xinputhaptic.c" />
|
||||
<ClCompile Include="SDL\src\hidapi\SDL_hidapi.c" />
|
||||
<ClCompile Include="SDL\src\joystick\controller_type.c" />
|
||||
<ClCompile Include="SDL\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_combined.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps5.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_shield.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_stadia.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_switch.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
|
||||
<ClCompile Include="SDL\src\joystick\SDL_gamecontroller.c" />
|
||||
<ClCompile Include="SDL\src\joystick\SDL_joystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\virtual\SDL_virtualjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_dinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_rawinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_windowsjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_windows_gaming_input.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_xinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_atan2.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_exp.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_fmod.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_log.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_log10.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_pow.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_rem_pio2.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_sqrt.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_cos.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_rem_pio2.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_sin.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_tan.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_atan.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_copysign.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_cos.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_fabs.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_floor.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_scalbn.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_sin.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_tan.c" />
|
||||
<ClCompile Include="SDL\src\loadso\windows\SDL_sysloadso.c" />
|
||||
<ClCompile Include="SDL\src\locale\SDL_locale.c" />
|
||||
<ClCompile Include="SDL\src\locale\windows\SDL_syslocale.c" />
|
||||
<ClCompile Include="SDL\src\misc\SDL_url.c" />
|
||||
<ClCompile Include="SDL\src\misc\windows\SDL_sysurl.c" />
|
||||
<ClCompile Include="SDL\src\power\SDL_power.c" />
|
||||
<ClCompile Include="SDL\src\power\windows\SDL_syspower.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d12\SDL_render_d3d12.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d\SDL_render_d3d.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d11\SDL_render_d3d11.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d\SDL_shaders_d3d.c" />
|
||||
<ClCompile Include="SDL\src\render\opengl\SDL_render_gl.c" />
|
||||
<ClCompile Include="SDL\src\render\opengl\SDL_shaders_gl.c" />
|
||||
<ClCompile Include="SDL\src\render\opengles2\SDL_render_gles2.c" />
|
||||
<ClCompile Include="SDL\src\render\opengles2\SDL_shaders_gles2.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_d3dmath.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_render.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_yuv_sw.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendfillrect.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendline.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendpoint.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_drawline.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_drawpoint.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_render_sw.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_rotate.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_triangle.c" />
|
||||
<ClCompile Include="SDL\src\SDL.c" />
|
||||
<ClCompile Include="SDL\src\SDL_assert.c" />
|
||||
<ClCompile Include="SDL\src\SDL_dataqueue.c" />
|
||||
<ClCompile Include="SDL\src\SDL_list.c" />
|
||||
<ClCompile Include="SDL\src\SDL_error.c" />
|
||||
<ClCompile Include="SDL\src\SDL_hints.c" />
|
||||
<ClCompile Include="SDL\src\SDL_log.c" />
|
||||
<ClCompile Include="SDL\src\SDL_utils.c" />
|
||||
<ClCompile Include="SDL\src\sensor\dummy\SDL_dummysensor.c" />
|
||||
<ClCompile Include="SDL\src\sensor\SDL_sensor.c" />
|
||||
<ClCompile Include="SDL\src\sensor\windows\SDL_windowssensor.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_crc16.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_crc32.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_getenv.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_iconv.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_malloc.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_mslibc.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_qsort.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_stdlib.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_string.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_strtokr.c" />
|
||||
<ClCompile Include="SDL\src\thread\generic\SDL_syscond.c" />
|
||||
<ClCompile Include="SDL\src\thread\SDL_thread.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_syscond_cv.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_sysmutex.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_syssem.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_systhread.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_systls.c" />
|
||||
<ClCompile Include="SDL\src\timer\SDL_timer.c" />
|
||||
<ClCompile Include="SDL\src\timer\windows\SDL_systimer.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullevents.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullframebuffer.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullvideo.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_0.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_1.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_A.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_auto.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_copy.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_N.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_slow.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_bmp.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_clipboard.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_egl.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_fillrect.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_pixels.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_rect.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_RLEaccel.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_shape.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_stretch.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_surface.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_video.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_vulkan_utils.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_yuv.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsclipboard.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsevents.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsframebuffer.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowskeyboard.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmessagebox.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmodes.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmouse.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengl.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengles.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsshape.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsvideo.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsvulkan.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowswindow.c" />
|
||||
<ClCompile Include="SDL\src\video\yuv2rgb\yuv_rgb.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+413
@@ -0,0 +1,413 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SDL\src\SDL_guid.c" />
|
||||
<ClCompile Include="SDL\src\atomic\SDL_atomic.c" />
|
||||
<ClCompile Include="SDL\src\atomic\SDL_spinlock.c" />
|
||||
<ClCompile Include="SDL\src\audio\directsound\SDL_directsound.c" />
|
||||
<ClCompile Include="SDL\src\audio\disk\SDL_diskaudio.c" />
|
||||
<ClCompile Include="SDL\src\audio\dummy\SDL_dummyaudio.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audio.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiocvt.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiodev.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_audiotypecvt.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_mixer.c" />
|
||||
<ClCompile Include="SDL\src\audio\SDL_wave.c" />
|
||||
<ClCompile Include="SDL\src\audio\winmm\SDL_winmm.c" />
|
||||
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi.c" />
|
||||
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi_win32.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_hid.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_immdevice.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_windows.c" />
|
||||
<ClCompile Include="SDL\src\core\windows\SDL_xinput.c" />
|
||||
<ClCompile Include="SDL\src\cpuinfo\SDL_cpuinfo.c" />
|
||||
<ClCompile Include="SDL\src\dynapi\SDL_dynapi.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_clipboardevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_displayevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_dropevents.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_events.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_gesture.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_keyboard.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_mouse.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_quit.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_touch.c" />
|
||||
<ClCompile Include="SDL\src\events\SDL_windowevents.c" />
|
||||
<ClCompile Include="SDL\src\file\SDL_rwops.c" />
|
||||
<ClCompile Include="SDL\src\filesystem\windows\SDL_sysfilesystem.c" />
|
||||
<ClCompile Include="SDL\src\haptic\dummy\SDL_syshaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\SDL_haptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_dinputhaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_windowshaptic.c" />
|
||||
<ClCompile Include="SDL\src\haptic\windows\SDL_xinputhaptic.c" />
|
||||
<ClCompile Include="SDL\src\hidapi\SDL_hidapi.c" />
|
||||
<ClCompile Include="SDL\src\joystick\controller_type.c" />
|
||||
<ClCompile Include="SDL\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_combined.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps5.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_shield.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_stadia.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_switch.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
|
||||
<ClCompile Include="SDL\src\joystick\SDL_gamecontroller.c" />
|
||||
<ClCompile Include="SDL\src\joystick\SDL_joystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\virtual\SDL_virtualjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_dinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_rawinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_windowsjoystick.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_windows_gaming_input.c" />
|
||||
<ClCompile Include="SDL\src\joystick\windows\SDL_xinputjoystick.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_atan2.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_exp.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_fmod.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_log.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_log10.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_pow.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_rem_pio2.c" />
|
||||
<ClCompile Include="SDL\src\libm\e_sqrt.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_cos.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_rem_pio2.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_sin.c" />
|
||||
<ClCompile Include="SDL\src\libm\k_tan.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_atan.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_copysign.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_cos.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_fabs.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_floor.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_scalbn.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_sin.c" />
|
||||
<ClCompile Include="SDL\src\libm\s_tan.c" />
|
||||
<ClCompile Include="SDL\src\loadso\windows\SDL_sysloadso.c" />
|
||||
<ClCompile Include="SDL\src\locale\SDL_locale.c" />
|
||||
<ClCompile Include="SDL\src\locale\windows\SDL_syslocale.c" />
|
||||
<ClCompile Include="SDL\src\misc\SDL_url.c" />
|
||||
<ClCompile Include="SDL\src\misc\windows\SDL_sysurl.c" />
|
||||
<ClCompile Include="SDL\src\power\SDL_power.c" />
|
||||
<ClCompile Include="SDL\src\power\windows\SDL_syspower.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d12\SDL_render_d3d12.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d\SDL_render_d3d.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d11\SDL_render_d3d11.c" />
|
||||
<ClCompile Include="SDL\src\render\direct3d\SDL_shaders_d3d.c" />
|
||||
<ClCompile Include="SDL\src\render\opengl\SDL_render_gl.c" />
|
||||
<ClCompile Include="SDL\src\render\opengl\SDL_shaders_gl.c" />
|
||||
<ClCompile Include="SDL\src\render\opengles2\SDL_render_gles2.c" />
|
||||
<ClCompile Include="SDL\src\render\opengles2\SDL_shaders_gles2.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_d3dmath.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_render.c" />
|
||||
<ClCompile Include="SDL\src\render\SDL_yuv_sw.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendfillrect.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendline.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_blendpoint.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_drawline.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_drawpoint.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_render_sw.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_rotate.c" />
|
||||
<ClCompile Include="SDL\src\render\software\SDL_triangle.c" />
|
||||
<ClCompile Include="SDL\src\SDL.c" />
|
||||
<ClCompile Include="SDL\src\SDL_assert.c" />
|
||||
<ClCompile Include="SDL\src\SDL_dataqueue.c" />
|
||||
<ClCompile Include="SDL\src\SDL_list.c" />
|
||||
<ClCompile Include="SDL\src\SDL_error.c" />
|
||||
<ClCompile Include="SDL\src\SDL_hints.c" />
|
||||
<ClCompile Include="SDL\src\SDL_log.c" />
|
||||
<ClCompile Include="SDL\src\SDL_utils.c" />
|
||||
<ClCompile Include="SDL\src\sensor\dummy\SDL_dummysensor.c" />
|
||||
<ClCompile Include="SDL\src\sensor\SDL_sensor.c" />
|
||||
<ClCompile Include="SDL\src\sensor\windows\SDL_windowssensor.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_crc16.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_crc32.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_getenv.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_iconv.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_malloc.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_mslibc.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_qsort.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_stdlib.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_string.c" />
|
||||
<ClCompile Include="SDL\src\stdlib\SDL_strtokr.c" />
|
||||
<ClCompile Include="SDL\src\thread\generic\SDL_syscond.c" />
|
||||
<ClCompile Include="SDL\src\thread\SDL_thread.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_syscond_cv.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_sysmutex.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_syssem.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_systhread.c" />
|
||||
<ClCompile Include="SDL\src\thread\windows\SDL_systls.c" />
|
||||
<ClCompile Include="SDL\src\timer\SDL_timer.c" />
|
||||
<ClCompile Include="SDL\src\timer\windows\SDL_systimer.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullevents.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullframebuffer.c" />
|
||||
<ClCompile Include="SDL\src\video\dummy\SDL_nullvideo.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_0.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_1.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_A.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_auto.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_copy.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_N.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_blit_slow.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_bmp.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_clipboard.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_egl.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_fillrect.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_pixels.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_rect.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_RLEaccel.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_shape.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_stretch.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_surface.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_video.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_vulkan_utils.c" />
|
||||
<ClCompile Include="SDL\src\video\SDL_yuv.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsclipboard.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsevents.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsframebuffer.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowskeyboard.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmessagebox.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmodes.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsmouse.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengl.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengles.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsshape.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsvideo.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowsvulkan.c" />
|
||||
<ClCompile Include="SDL\src\video\windows\SDL_windowswindow.c" />
|
||||
<ClCompile Include="SDL\src\video\yuv2rgb\yuv_rgb.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_ps3.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_steam.c" />
|
||||
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_wii.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SDL\include\begin_code.h" />
|
||||
<ClInclude Include="SDL\include\close_code.h" />
|
||||
<ClInclude Include="SDL\include\SDL.h" />
|
||||
<ClInclude Include="SDL\include\SDL_assert.h" />
|
||||
<ClInclude Include="SDL\include\SDL_atomic.h" />
|
||||
<ClInclude Include="SDL\include\SDL_audio.h" />
|
||||
<ClInclude Include="SDL\include\SDL_bits.h" />
|
||||
<ClInclude Include="SDL\include\SDL_blendmode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_clipboard.h" />
|
||||
<ClInclude Include="SDL\include\SDL_config.h" />
|
||||
<ClInclude Include="SDL\include\SDL_config_windows.h" />
|
||||
<ClInclude Include="SDL\include\SDL_copying.h" />
|
||||
<ClInclude Include="SDL\include\SDL_cpuinfo.h" />
|
||||
<ClInclude Include="SDL\include\SDL_egl.h" />
|
||||
<ClInclude Include="SDL\include\SDL_endian.h" />
|
||||
<ClInclude Include="SDL\include\SDL_error.h" />
|
||||
<ClInclude Include="SDL\include\SDL_events.h" />
|
||||
<ClInclude Include="SDL\include\SDL_filesystem.h" />
|
||||
<ClInclude Include="SDL\include\SDL_gamecontroller.h" />
|
||||
<ClInclude Include="SDL\include\SDL_gesture.h" />
|
||||
<ClInclude Include="SDL\include\SDL_guid.h" />
|
||||
<ClInclude Include="SDL\include\SDL_haptic.h" />
|
||||
<ClInclude Include="SDL\include\SDL_hints.h" />
|
||||
<ClInclude Include="SDL\include\SDL_hidapi.h" />
|
||||
<ClInclude Include="SDL\include\SDL_joystick.h" />
|
||||
<ClInclude Include="SDL\include\SDL_keyboard.h" />
|
||||
<ClInclude Include="SDL\include\SDL_keycode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_loadso.h" />
|
||||
<ClInclude Include="SDL\include\SDL_locale.h" />
|
||||
<ClInclude Include="SDL\include\SDL_log.h" />
|
||||
<ClInclude Include="SDL\include\SDL_main.h" />
|
||||
<ClInclude Include="SDL\include\SDL_messagebox.h" />
|
||||
<ClInclude Include="SDL\include\SDL_metal.h" />
|
||||
<ClInclude Include="SDL\include\SDL_misc.h" />
|
||||
<ClInclude Include="SDL\include\SDL_mouse.h" />
|
||||
<ClInclude Include="SDL\include\SDL_mutex.h" />
|
||||
<ClInclude Include="SDL\include\SDL_name.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengl.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengl_glext.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2ext.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_gl2platform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_opengles2_khrplatform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_pixels.h" />
|
||||
<ClInclude Include="SDL\include\SDL_platform.h" />
|
||||
<ClInclude Include="SDL\include\SDL_power.h" />
|
||||
<ClInclude Include="SDL\include\SDL_quit.h" />
|
||||
<ClInclude Include="SDL\include\SDL_rect.h" />
|
||||
<ClInclude Include="SDL\include\SDL_render.h" />
|
||||
<ClInclude Include="SDL\include\SDL_revision.h" />
|
||||
<ClInclude Include="SDL\include\SDL_rwops.h" />
|
||||
<ClInclude Include="SDL\include\SDL_scancode.h" />
|
||||
<ClInclude Include="SDL\include\SDL_sensor.h" />
|
||||
<ClInclude Include="SDL\include\SDL_shape.h" />
|
||||
<ClInclude Include="SDL\include\SDL_stdinc.h" />
|
||||
<ClInclude Include="SDL\include\SDL_surface.h" />
|
||||
<ClInclude Include="SDL\include\SDL_system.h" />
|
||||
<ClInclude Include="SDL\include\SDL_syswm.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_assert.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_common.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_compare.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_crc32.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_font.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_fuzzer.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_harness.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_images.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_log.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_md5.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_memory.h" />
|
||||
<ClInclude Include="SDL\include\SDL_test_random.h" />
|
||||
<ClInclude Include="SDL\include\SDL_thread.h" />
|
||||
<ClInclude Include="SDL\include\SDL_timer.h" />
|
||||
<ClInclude Include="SDL\include\SDL_touch.h" />
|
||||
<ClInclude Include="SDL\include\SDL_types.h" />
|
||||
<ClInclude Include="SDL\include\SDL_version.h" />
|
||||
<ClInclude Include="SDL\include\SDL_video.h" />
|
||||
<ClInclude Include="SDL\include\SDL_vulkan.h" />
|
||||
<ClInclude Include="SDL\src\audio\directsound\SDL_directsound.h" />
|
||||
<ClInclude Include="SDL\src\audio\disk\SDL_diskaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\dummy\SDL_dummyaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_audio_c.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_audiodev_c.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_sysaudio.h" />
|
||||
<ClInclude Include="SDL\src\audio\SDL_wave.h" />
|
||||
<ClInclude Include="SDL\src\audio\wasapi\SDL_wasapi.h" />
|
||||
<ClInclude Include="SDL\src\audio\winmm\SDL_winmm.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_directx.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_hid.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_immdevice.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_windows.h" />
|
||||
<ClInclude Include="SDL\src\core\windows\SDL_xinput.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_overrides.h" />
|
||||
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_procs.h" />
|
||||
<ClInclude Include="SDL\src\events\blank_cursor.h" />
|
||||
<ClInclude Include="SDL\src\events\default_cursor.h" />
|
||||
<ClInclude Include="SDL\src\events\scancodes_windows.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_clipboardevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_displayevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_dropevents_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_events_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_gesture_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_keyboard_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_mouse_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_touch_c.h" />
|
||||
<ClInclude Include="SDL\src\events\SDL_windowevents_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\SDL_haptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\SDL_syshaptic.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_dinputhaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_windowshaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\haptic\windows\SDL_xinputhaptic_c.h" />
|
||||
<ClInclude Include="SDL\src\hidapi\hidapi\hidapi.h" />
|
||||
<ClInclude Include="SDL\src\hidapi\SDL_hidapi_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\controller_type.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_gamecontrollerdb.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_joystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\SDL_sysjoystick.h" />
|
||||
<ClInclude Include="SDL\src\joystick\usb_ids.h" />
|
||||
<ClInclude Include="SDL\src\joystick\virtual\SDL_virtualjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_dinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_rawinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_windowsjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\joystick\windows\SDL_xinputjoystick_c.h" />
|
||||
<ClInclude Include="SDL\src\libm\math_libm.h" />
|
||||
<ClInclude Include="SDL\src\libm\math_private.h" />
|
||||
<ClInclude Include="SDL\src\locale\SDL_syslocale.h" />
|
||||
<ClInclude Include="SDL\src\misc\SDL_sysurl.h" />
|
||||
<ClInclude Include="SDL\src\power\SDL_syspower.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.h" />
|
||||
<ClInclude Include="SDL\src\render\direct3d\SDL_shaders_d3d.h" />
|
||||
<ClInclude Include="SDL\src\render\opengles2\SDL_gles2funcs.h" />
|
||||
<ClInclude Include="SDL\src\render\opengles2\SDL_shaders_gles2.h" />
|
||||
<ClInclude Include="SDL\src\render\opengl\SDL_glfuncs.h" />
|
||||
<ClInclude Include="SDL\src\render\opengl\SDL_shaders_gl.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_d3dmath.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_sysrender.h" />
|
||||
<ClInclude Include="SDL\src\render\SDL_yuv_sw_c.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendfillrect.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendline.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_blendpoint.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_draw.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_drawline.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_drawpoint.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_render_sw_c.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_rotate.h" />
|
||||
<ClInclude Include="SDL\src\render\software\SDL_triangle.h" />
|
||||
<ClInclude Include="SDL\src\SDL_assert_c.h" />
|
||||
<ClInclude Include="SDL\src\SDL_dataqueue.h" />
|
||||
<ClInclude Include="SDL\src\SDL_error_c.h" />
|
||||
<ClInclude Include="SDL\src\SDL_hints_c.h" />
|
||||
<ClInclude Include="SDL\src\SDL_internal.h" />
|
||||
<ClInclude Include="SDL\src\SDL_list.h" />
|
||||
<ClInclude Include="SDL\src\SDL_log_c.h" />
|
||||
<ClInclude Include="SDL\src\sensor\dummy\SDL_dummysensor.h" />
|
||||
<ClInclude Include="SDL\src\sensor\SDL_sensor_c.h" />
|
||||
<ClInclude Include="SDL\src\sensor\SDL_syssensor.h" />
|
||||
<ClInclude Include="SDL\src\sensor\windows\SDL_windowssensor.h" />
|
||||
<ClInclude Include="SDL\src\thread\SDL_systhread.h" />
|
||||
<ClInclude Include="SDL\src\thread\SDL_thread_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\generic\SDL_syscond_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\windows\SDL_sysmutex_c.h" />
|
||||
<ClInclude Include="SDL\src\thread\windows\SDL_systhread_c.h" />
|
||||
<ClInclude Include="SDL\src\timer\SDL_timer_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullevents_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullframebuffer_c.h" />
|
||||
<ClInclude Include="SDL\src\video\dummy\SDL_nullvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_icd.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_layer.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_platform.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_sdk_platform.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.hpp" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_android.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_beta.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_core.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_directfb.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_fuchsia.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_ggp.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_ios.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_macos.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_metal.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_vi.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_wayland.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_win32.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xcb.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib.h" />
|
||||
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib_xrandr.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_auto.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_copy.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_blit_slow.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_egl_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_pixels_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_rect_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_RLEaccel_c.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_shape_internals.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_sysvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_vulkan_internal.h" />
|
||||
<ClInclude Include="SDL\src\video\SDL_yuv_c.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_msctf.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_vkeys.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsclipboard.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsevents.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsframebuffer.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowskeyboard.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmessagebox.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmodes.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsmouse.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengl.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengles.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsshape.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsvideo.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowsvulkan.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\SDL_windowswindow.h" />
|
||||
<ClInclude Include="SDL\src\video\windows\wmmsg.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_sse_func.h" />
|
||||
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_std_func.h" />
|
||||
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_nintendo.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Vendored
+1
-1
Submodule 3rdparty/pugixml updated: dd50fa5b45...a0e0643363
Vendored
+1
-1
Submodule 3rdparty/wolfssl/wolfssl updated: 57aac1c50b...44f81f8bc0
+2
-2
@@ -11,7 +11,7 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
|
||||
* [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
||||
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
|
||||
* [Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
||||
* [Vulkan SDK 1.2.198+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
|
||||
* [Vulkan SDK 1.2.224+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
|
||||
|
||||
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.15.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
|
||||
|
||||
@@ -22,7 +22,7 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst
|
||||
* Clang 12+ or GCC 11+
|
||||
* [CMake 3.16.9+](https://www.cmake.org/download/)
|
||||
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
|
||||
* [Vulkan SDK 1.2.198+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
|
||||
* [Vulkan SDK 1.2.224+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
|
||||
* [SDL2](https://www.libsdl.org/download-2.0.php) (for the FAudio backend)
|
||||
|
||||
**If you have an NVIDIA GPU, you may need to install the libglvnd package.**
|
||||
|
||||
@@ -21,6 +21,8 @@ option(USE_DISCORD_RPC "Discord rich presence integration" OFF)
|
||||
option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON)
|
||||
option(USE_VULKAN "Vulkan render backend" ON)
|
||||
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
|
||||
option(USE_SDL "Enables SDL input handler" OFF)
|
||||
option(USE_SYSTEM_SDL "Prefer system SDL instead of the builtin one" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/buildfiles/cmake")
|
||||
|
||||
|
||||
+51
-5
@@ -80,7 +80,13 @@ namespace cfg
|
||||
// Convert to string (optional)
|
||||
virtual std::string to_string() const
|
||||
{
|
||||
return{};
|
||||
return {};
|
||||
}
|
||||
|
||||
// Convert default to string (optional)
|
||||
virtual std::string def_to_string() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// Try to convert from string (optional)
|
||||
@@ -89,7 +95,7 @@ namespace cfg
|
||||
// Get string list (optional)
|
||||
virtual std::vector<std::string> to_list() const
|
||||
{
|
||||
return{};
|
||||
return {};
|
||||
}
|
||||
|
||||
// Set multiple values. Implementation-specific, optional.
|
||||
@@ -163,11 +169,24 @@ namespace cfg
|
||||
return m_value ? "true" : "false";
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return def ? "true" : "false";
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
if (value == "false")
|
||||
if (value.size() != 4 && value.size() != 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char copy[5];
|
||||
std::transform(value.begin(), value.end(), std::begin(copy), ::tolower);
|
||||
|
||||
if (value.size() == 5 && std::string_view{copy, 5} == "false")
|
||||
m_value = false;
|
||||
else if (value == "true")
|
||||
else if (value.size() == 4 && std::string_view{copy, 4} == "true")
|
||||
m_value = true;
|
||||
else
|
||||
return false;
|
||||
@@ -224,6 +243,13 @@ namespace cfg
|
||||
return result; // TODO: ???
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
std::string result;
|
||||
fmt_class_string<T>::format(result, fmt_unveil<T>::get(def));
|
||||
return result; // TODO: ???
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
u64 result;
|
||||
@@ -289,6 +315,11 @@ namespace cfg
|
||||
return std::to_string(m_value);
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return std::to_string(def);
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
s64 result;
|
||||
@@ -355,6 +386,11 @@ namespace cfg
|
||||
return std::to_string(m_value);
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return std::to_string(def);
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
f64 result;
|
||||
@@ -429,6 +465,11 @@ namespace cfg
|
||||
return std::to_string(m_value);
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return std::to_string(def);
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
u64 result;
|
||||
@@ -500,6 +541,11 @@ namespace cfg
|
||||
return *m_value.load().get();
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return def;
|
||||
}
|
||||
|
||||
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
m_value = std::string(value);
|
||||
@@ -533,7 +579,7 @@ namespace cfg
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
return{ m_set.begin(), m_set.end() };
|
||||
return { m_set.begin(), m_set.end() };
|
||||
}
|
||||
|
||||
bool from_list(std::vector<std::string>&& list) override
|
||||
|
||||
+151
-16
@@ -437,6 +437,9 @@ std::string fs::get_parent_dir(std::string_view path, u32 levels)
|
||||
|
||||
bool fs::stat(const std::string& path, stat_t& info)
|
||||
{
|
||||
// Ensure consistent information on failure
|
||||
info = {};
|
||||
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
return device->stat(path, info);
|
||||
@@ -1103,10 +1106,12 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
class windows_file final : public file_base
|
||||
{
|
||||
const HANDLE m_handle;
|
||||
atomic_t<u64> m_pos;
|
||||
|
||||
public:
|
||||
windows_file(HANDLE handle)
|
||||
: m_handle(handle)
|
||||
, m_pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1162,7 +1167,39 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||
|
||||
DWORD nread = 0;
|
||||
ensure(ReadFile(m_handle, data, size, &nread, nullptr)); // "file::read"
|
||||
OVERLAPPED ovl{};
|
||||
const u64 pos = m_pos;
|
||||
ovl.Offset = DWORD(pos);
|
||||
ovl.OffsetHigh = DWORD(pos >> 32);
|
||||
ensure(ReadFile(m_handle, data, size, &nread, &ovl) || GetLastError() == ERROR_HANDLE_EOF); // "file::read"
|
||||
nread_sum += nread;
|
||||
m_pos += nread;
|
||||
|
||||
if (nread < size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
count -= size;
|
||||
data += size;
|
||||
}
|
||||
|
||||
return nread_sum;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||
{
|
||||
u64 nread_sum = 0;
|
||||
|
||||
for (char* data = static_cast<char*>(buffer); count;)
|
||||
{
|
||||
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||
|
||||
DWORD nread = 0;
|
||||
OVERLAPPED ovl{};
|
||||
ovl.Offset = DWORD(offset);
|
||||
ovl.OffsetHigh = DWORD(offset >> 32);
|
||||
ensure(ReadFile(m_handle, data, size, &nread, &ovl) || GetLastError() == ERROR_HANDLE_EOF); // "file::read"
|
||||
nread_sum += nread;
|
||||
|
||||
if (nread < size)
|
||||
@@ -1172,6 +1209,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
count -= size;
|
||||
data += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return nread_sum;
|
||||
@@ -1186,8 +1224,13 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||
|
||||
DWORD nwritten = 0;
|
||||
ensure(WriteFile(m_handle, data, size, &nwritten, nullptr)); // "file::write"
|
||||
OVERLAPPED ovl{};
|
||||
const u64 pos = m_pos;
|
||||
ovl.Offset = DWORD(pos);
|
||||
ovl.OffsetHigh = DWORD(pos >> 32);
|
||||
ensure(WriteFile(m_handle, data, size, &nwritten, &ovl)); // "file::write"
|
||||
nwritten_sum += nwritten;
|
||||
m_pos += nwritten;
|
||||
|
||||
if (nwritten < size)
|
||||
{
|
||||
@@ -1208,20 +1251,19 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
fmt::throw_exception("Invalid whence (0x%x)", whence);
|
||||
}
|
||||
|
||||
LARGE_INTEGER pos;
|
||||
pos.QuadPart = offset;
|
||||
const s64 new_pos =
|
||||
whence == fs::seek_set ? offset :
|
||||
whence == fs::seek_cur ? offset + m_pos :
|
||||
whence == fs::seek_end ? offset + size() : -1;
|
||||
|
||||
const DWORD mode =
|
||||
whence == seek_set ? FILE_BEGIN :
|
||||
whence == seek_cur ? FILE_CURRENT : FILE_END;
|
||||
|
||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
||||
if (new_pos < 0)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
fs::g_tls_error = fs::error::inval;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pos.QuadPart;
|
||||
m_pos = new_pos;
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
@@ -1340,16 +1382,55 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::read(m_fd, buffer, count);
|
||||
ensure(result != -1); // "file::read"
|
||||
u64 result = 0;
|
||||
|
||||
// Loop because (huge?) read can be processed partially
|
||||
while (auto r = ::read(m_fd, buffer, count))
|
||||
{
|
||||
ensure(r > 0); // "file::read"
|
||||
count -= r;
|
||||
result += r;
|
||||
buffer = static_cast<u8*>(buffer) + r;
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||
{
|
||||
u64 result = 0;
|
||||
|
||||
// For safety; see read()
|
||||
while (auto r = ::pread(m_fd, buffer, count, offset))
|
||||
{
|
||||
ensure(r > 0); // "file::read_at"
|
||||
count -= r;
|
||||
offset += r;
|
||||
result += r;
|
||||
buffer = static_cast<u8*>(buffer) + r;
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::write(m_fd, buffer, count);
|
||||
ensure(result != -1); // "file::write"
|
||||
u64 result = 0;
|
||||
|
||||
// For safety; see read()
|
||||
while (auto r = ::write(m_fd, buffer, count))
|
||||
{
|
||||
ensure(r > 0); // "file::write"
|
||||
count -= r;
|
||||
result += r;
|
||||
buffer = static_cast<const u8*>(buffer) + r;
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1463,6 +1544,21 @@ fs::file::file(const void* ptr, usz size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||
{
|
||||
if (offset < m_size)
|
||||
{
|
||||
// Get readable size
|
||||
if (const u64 result = std::min<u64>(count, m_size - offset))
|
||||
{
|
||||
std::memcpy(buffer, m_ptr + offset, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
@@ -1828,7 +1924,7 @@ bool fs::remove_all(const std::string& path, bool remove_root, bool is_no_dir_ok
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
|
||||
u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment, atomic_t<bool>* cancel_flag)
|
||||
{
|
||||
u64 result = 0;
|
||||
|
||||
@@ -1841,6 +1937,11 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
|
||||
|
||||
for (const auto& entry : root_dir)
|
||||
{
|
||||
if (cancel_flag && *cancel_flag)
|
||||
{
|
||||
return umax;
|
||||
}
|
||||
|
||||
if (entry.name == "." || entry.name == "..")
|
||||
{
|
||||
continue;
|
||||
@@ -1948,6 +2049,40 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 read_at(u64 start, void* buffer, u64 size) override
|
||||
{
|
||||
if (start < end)
|
||||
{
|
||||
u64 pos = start;
|
||||
|
||||
// Get readable size
|
||||
if (const u64 max = std::min<u64>(size, end - pos))
|
||||
{
|
||||
u8* buf_out = static_cast<u8*>(buffer);
|
||||
u64 buf_max = max;
|
||||
|
||||
for (auto it = ends.upper_bound(pos); it != ends.end(); ++it)
|
||||
{
|
||||
const u64 count = std::min<u64>(it->first - pos, buf_max);
|
||||
const u64 read = files[it->second].read_at(files[it->second].size() + pos - it->first, buf_out, count);
|
||||
|
||||
buf_out += count;
|
||||
buf_max -= count;
|
||||
pos += read;
|
||||
|
||||
if (read < count || buf_max == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos - start;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
|
||||
+31
-1
@@ -93,6 +93,7 @@ namespace fs
|
||||
virtual void sync();
|
||||
virtual bool trunc(u64 length) = 0;
|
||||
virtual u64 read(void* buffer, u64 size) = 0;
|
||||
virtual u64 read_at(u64 offset, void* buffer, u64 size) = 0;
|
||||
virtual u64 write(const void* buffer, u64 size) = 0;
|
||||
virtual u64 seek(s64 offset, seek_mode whence) = 0;
|
||||
virtual u64 size() = 0;
|
||||
@@ -301,6 +302,17 @@ namespace fs
|
||||
return m_file->read(buffer, count);
|
||||
}
|
||||
|
||||
// Read the data from the file at specified offset in thread-safe manner
|
||||
u64 read_at(u64 offset, void* buffer, u64 count,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->read_at(offset, buffer, count);
|
||||
}
|
||||
|
||||
// Write the data to the file and return the amount of data actually written
|
||||
u64 write(const void* buffer, u64 count,
|
||||
u32 line = __builtin_LINE(),
|
||||
@@ -657,7 +669,7 @@ namespace fs
|
||||
bool remove_all(const std::string& path, bool remove_root = true, bool is_no_dir_ok = false);
|
||||
|
||||
// Get size of all files recursively
|
||||
u64 get_dir_size(const std::string& path, u64 rounding_alignment = 1);
|
||||
u64 get_dir_size(const std::string& path, u64 rounding_alignment = 1, atomic_t<bool>* cancel_flag = nullptr);
|
||||
|
||||
enum class error : uint
|
||||
{
|
||||
@@ -724,6 +736,24 @@ namespace fs
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||
{
|
||||
const u64 end = obj.size();
|
||||
|
||||
if (offset < end)
|
||||
{
|
||||
// Get readable size
|
||||
if (const u64 max = std::min<u64>(size, end - offset))
|
||||
{
|
||||
std::copy(obj.cbegin() + offset, obj.cbegin() + offset + max, static_cast<value_type*>(buffer));
|
||||
update_time();
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 size) override
|
||||
{
|
||||
const u64 old_size = obj.size();
|
||||
|
||||
@@ -449,7 +449,7 @@ struct fmt::cfmt_src
|
||||
{
|
||||
// Hack: use known function pointers to determine type
|
||||
#define TYPE(type) \
|
||||
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type);
|
||||
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type);
|
||||
|
||||
TYPE(int);
|
||||
TYPE(llong);
|
||||
@@ -457,10 +457,11 @@ struct fmt::cfmt_src
|
||||
TYPE(short);
|
||||
if (std::is_signed<char>::value) TYPE(char);
|
||||
TYPE(long);
|
||||
TYPE(u128);
|
||||
TYPE(s128);
|
||||
|
||||
#undef TYPE
|
||||
if (sup[extra].fmt_string == &fmt_class_string<u128>::format)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ std::string utf16_to_utf8(std::u16string_view src);
|
||||
template <typename D, typename T>
|
||||
inline void strcpy_trunc(D& dst, const T& src)
|
||||
{
|
||||
const usz count = std::size(src) >= std::size(dst) ? std::size(dst) - 1 : std::size(src);
|
||||
const usz count = std::size(src) >= std::size(dst) ? std::max<usz>(std::size(dst), 1) - 1 : std::size(src);
|
||||
std::memcpy(std::data(dst), std::data(src), count);
|
||||
std::memset(std::data(dst) + count, 0, std::size(dst) - count);
|
||||
}
|
||||
|
||||
+13
-13
@@ -96,27 +96,21 @@ thread_local bool g_tls_access_violation_recovered = false;
|
||||
extern thread_local std::string(*g_tls_log_prefix)();
|
||||
|
||||
// Report error and call std::abort(), defined in main.cpp
|
||||
[[noreturn]] void report_fatal_error(std::string_view);
|
||||
[[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true);
|
||||
|
||||
std::string dump_useful_thread_info()
|
||||
{
|
||||
thread_local volatile bool guard = false;
|
||||
|
||||
std::string result;
|
||||
|
||||
// In case the dumping function was the cause for the exception/access violation
|
||||
// Avoid recursion
|
||||
if (std::exchange(guard, true))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
cpu->dump_all(result);
|
||||
// Wrap it to disable some internal exceptions when printing (not thrown on main thread)
|
||||
Emu.BlockingCallFromMainThread([&]()
|
||||
{
|
||||
cpu->dump_all(result);
|
||||
});
|
||||
}
|
||||
|
||||
guard = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1927,7 +1921,10 @@ const bool s_terminate_handler_set = []() -> bool
|
||||
std::set_terminate([]()
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
logs::listener::sync_all();
|
||||
utils::trap();
|
||||
}
|
||||
|
||||
report_fatal_error("RPCS3 has abnormally terminated.");
|
||||
});
|
||||
@@ -2065,7 +2062,7 @@ void thread_base::set_name(std::string name)
|
||||
u64 thread_base::finalize(thread_state result_state) noexcept
|
||||
{
|
||||
// Report pending errors
|
||||
error_code::error_report(0, 0, 0, 0);
|
||||
error_code::error_report(0, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
static thread_local ULONG64 tls_cycles{};
|
||||
@@ -2650,7 +2647,10 @@ void thread_base::exec()
|
||||
sig_log.fatal("Thread terminated due to fatal error: %s", reason);
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
logs::listener::sync_all();
|
||||
utils::trap();
|
||||
}
|
||||
|
||||
if (const auto _this = g_tls_this_thread)
|
||||
{
|
||||
|
||||
+30
-12
@@ -703,8 +703,6 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
}
|
||||
case patch_type::code_alloc:
|
||||
{
|
||||
relocate_instructions_at = 0;
|
||||
|
||||
const u32 out_branch = vm::try_get_addr(dst + (offset & -4)).first;
|
||||
|
||||
// Allow only if points to a PPU executable instruction
|
||||
@@ -715,10 +713,17 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
|
||||
const u32 alloc_size = utils::align(static_cast<u32>(p.value.long_value + 1) * 4, 0x10000);
|
||||
|
||||
// Check if should maybe reuse previous code cave allocation (0 size)
|
||||
if (alloc_size - 4 != 0)
|
||||
{
|
||||
// Nope
|
||||
relocate_instructions_at = 0;
|
||||
}
|
||||
|
||||
// Always executable
|
||||
u64 flags = vm::alloc_executable | vm::alloc_unwritable;
|
||||
|
||||
switch (p.offset % patch_engine::mem_protection::mask)
|
||||
switch (p.offset & patch_engine::mem_protection::mask)
|
||||
{
|
||||
case patch_engine::mem_protection::rw:
|
||||
case patch_engine::mem_protection::wx:
|
||||
@@ -738,7 +743,7 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
|
||||
// Range allowed for absolute branches to operate at
|
||||
// It takes into account that we need to put a branch for return at the end of memory space
|
||||
const u32 addr = p.alloc_addr = alloc_map->alloc(alloc_size, nullptr, 0x10000, flags);
|
||||
const u32 addr = p.alloc_addr = (relocate_instructions_at ? relocate_instructions_at : alloc_map->alloc(alloc_size, nullptr, 0x10000, flags));
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
@@ -751,18 +756,31 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
// NOP filled
|
||||
std::fill_n(vm::get_super_ptr<u32>(addr), p.value.long_value, 0x60000000);
|
||||
|
||||
// Register code
|
||||
ppu_register_range(addr, alloc_size);
|
||||
// Check if already registered by previous code allocation
|
||||
if (relocate_instructions_at != addr)
|
||||
{
|
||||
// Register code
|
||||
ppu_register_range(addr, alloc_size);
|
||||
}
|
||||
|
||||
// Write branch to code
|
||||
ppu_form_branch_to_code(out_branch, addr);
|
||||
resval = out_branch & -4;
|
||||
|
||||
// Write address of the allocated memory to the code entry
|
||||
*vm::get_super_ptr<u32>(resval) = addr;
|
||||
|
||||
// Write branch to return to code
|
||||
ppu_form_branch_to_code(addr + static_cast<u32>(p.value.long_value) * 4, resval + 4);
|
||||
if (!ppu_form_branch_to_code(addr + static_cast<u32>(p.value.long_value) * 4, resval + 4))
|
||||
{
|
||||
patch_log.error("Failed to write return jump at 0x%x", addr + static_cast<u32>(p.value.long_value) * 4);
|
||||
ensure(alloc_map->dealloc(addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Write branch to code
|
||||
if (!ppu_form_branch_to_code(out_branch, addr))
|
||||
{
|
||||
patch_log.error("Failed to jump to code cave at 0x%x", out_branch);
|
||||
ensure(alloc_map->dealloc(addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
relocate_instructions_at = addr;
|
||||
break;
|
||||
}
|
||||
|
||||
+33
-20
@@ -367,9 +367,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctx.type)
|
||||
const usz src_type = src.type(ctx.args);
|
||||
|
||||
if (!ctx.type || src_type > 8)
|
||||
{
|
||||
ctx.type = static_cast<u8>(src.type(ctx.args));
|
||||
ctx.type = static_cast<u8>(src_type);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
@@ -379,7 +381,13 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
// Sign-extended argument expected
|
||||
const u64 val = src.template get<u64>(ctx.args);
|
||||
const bool negative = ctx.type && static_cast<s64>(val) < 0;
|
||||
bool negative = ctx.type && ctx.type <= 8 && static_cast<s64>(val) < 0;
|
||||
|
||||
if (ctx.type == 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<const u128*>(val);
|
||||
negative = !!(val2 & (u128{1} << 127));
|
||||
}
|
||||
|
||||
const usz start = out.size();
|
||||
|
||||
@@ -398,15 +406,14 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
out.push_back(' ');
|
||||
}
|
||||
|
||||
if (ctx.type == 16)
|
||||
if (ctx.type >= 16)
|
||||
{
|
||||
// TODO: support negative values (s128)
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
write_decimal(val2, ctx.prec);
|
||||
u128 val2 = *reinterpret_cast<const u128*>(val);
|
||||
write_decimal(negative ? u128{} - val2 : val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_decimal(negative ? 0 - val : val, ctx.prec);
|
||||
write_decimal(negative ? u64{} - val : val, ctx.prec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,9 +445,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctx.type)
|
||||
const usz src_type = src.type(ctx.args);
|
||||
|
||||
if (!ctx.type || src_type > 8)
|
||||
{
|
||||
ctx.type = static_cast<u8>(src.type(ctx.args));
|
||||
ctx.type = static_cast<u8>(src_type);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
@@ -471,9 +480,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
|
||||
{
|
||||
if (ctx.type == 16)
|
||||
if (ctx.type >= 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
u128 val2 = *reinterpret_cast<const u128*>(val);
|
||||
write_octal(val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
@@ -504,9 +513,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctx.type)
|
||||
const usz src_type = src.type(ctx.args);
|
||||
|
||||
if (!ctx.type || src_type > 8)
|
||||
{
|
||||
ctx.type = static_cast<u8>(src.type(ctx.args));
|
||||
ctx.type = static_cast<u8>(src_type);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
@@ -537,9 +548,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
|
||||
{
|
||||
if (ctx.type == 16)
|
||||
if (ctx.type >= 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
u128 val2 = *reinterpret_cast<const u128*>(val);
|
||||
write_hex(val2, ch == 'X', ctx.prec);
|
||||
}
|
||||
else
|
||||
@@ -576,9 +587,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctx.type)
|
||||
const usz src_type = src.type(ctx.args);
|
||||
|
||||
if (!ctx.type || src_type > 8)
|
||||
{
|
||||
ctx.type = static_cast<u8>(src.type(ctx.args));
|
||||
ctx.type = static_cast<u8>(src_type);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
@@ -599,9 +612,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
if (!ctx.dot || ctx.prec)
|
||||
{
|
||||
if (ctx.type == 16)
|
||||
if (ctx.type >= 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
u128 val2 = *reinterpret_cast<const u128*>(val);
|
||||
write_decimal(val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
|
||||
+28
-2
@@ -4,17 +4,43 @@
|
||||
|
||||
namespace utils
|
||||
{
|
||||
namespace stack_trace
|
||||
{
|
||||
// Printing utilities
|
||||
|
||||
template <typename T>
|
||||
concept Logger = requires (T& t, const std::string& msg)
|
||||
{
|
||||
{ t.print(msg) };
|
||||
};
|
||||
|
||||
struct print_to_log
|
||||
{
|
||||
logs::channel& log;
|
||||
|
||||
public:
|
||||
print_to_log(logs::channel& chan)
|
||||
: log(chan)
|
||||
{}
|
||||
|
||||
void print(const std::string& s)
|
||||
{
|
||||
log.error("%s", s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<void*> get_backtrace(int max_depth = 255);
|
||||
std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack);
|
||||
|
||||
FORCE_INLINE void print_trace(logs::channel& logger, int max_depth = 255)
|
||||
FORCE_INLINE void print_trace(stack_trace::Logger auto& logger, int max_depth = 255)
|
||||
{
|
||||
const auto trace = get_backtrace(max_depth);
|
||||
const auto lines = get_backtrace_symbols(trace);
|
||||
|
||||
for (const auto& line : lines)
|
||||
{
|
||||
logger.error("%s", line);
|
||||
logger.print(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -70,8 +70,8 @@ jobs:
|
||||
QT_VER_MSVC: 'msvc2019'
|
||||
QT_DATE: '202011130602'
|
||||
QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64
|
||||
VULKAN_VER: '1.3.204.0'
|
||||
VULKAN_SDK_SHA: '41f4996335cc5a545d7b2f6e5ff29cf3867789aae4be053a7069aa93408861fa'
|
||||
VULKAN_VER: '1.3.224.1'
|
||||
VULKAN_SDK_SHA: '2029e652e39ee6a6036cff3765da31e1e6c595fd2413d3cd111dfab7855621ea'
|
||||
VULKAN_SDK: C:\VulkanSDK\$(VULKAN_VER)
|
||||
CACHE_DIR: ./cache
|
||||
UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29306.81
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32929.385
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "3rdparty\asmjit\asmjit.vcxproj", "{AC40FF01-426E-4838-A317-66354CEFAE88}"
|
||||
EndProject
|
||||
@@ -40,22 +40,23 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-cpp", "3rdparty\yaml-c
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88} = {AC40FF01-426E-4838-A317-66354CEFAE88}
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {A107C21C-418A-4697-BB10-20C3AA60E2E4}
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038} = {C4A10229-4712-4BD2-B63E-50D93C67A038}
|
||||
{78CB2F39-B809-4A06-8329-8C0A19119D3D} = {78CB2F39-B809-4A06-8329-8C0A19119D3D}
|
||||
{3384223A-6D97-4799-9862-359F85312892} = {3384223A-6D97-4799-9862-359F85312892}
|
||||
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF}
|
||||
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}
|
||||
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E}
|
||||
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2} = {9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A} = {FDA7B080-03B0-48C8-B24F-88118981422A}
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21} = {508c291a-3d18-49f5-b25d-f7c8db92cb21}
|
||||
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}
|
||||
{FDC361C5-7734-493B-8CFB-037308B35122} = {FDC361C5-7734-493B-8CFB-037308B35122}
|
||||
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {8F85B6CC-250F-4ACA-A617-E820A74E3E3C}
|
||||
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
|
||||
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21} = {508C291A-3D18-49F5-B25D-F7C8DB92CB21}
|
||||
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}
|
||||
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF}
|
||||
{78CB2F39-B809-4A06-8329-8C0A19119D3D} = {78CB2F39-B809-4A06-8329-8C0A19119D3D}
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}
|
||||
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {8F85B6CC-250F-4ACA-A617-E820A74E3E3C}
|
||||
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2} = {9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {A107C21C-418A-4697-BB10-20C3AA60E2E4}
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88} = {AC40FF01-426E-4838-A317-66354CEFAE88}
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038} = {C4A10229-4712-4BD2-B63E-50D93C67A038}
|
||||
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E}
|
||||
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A} = {FDA7B080-03B0-48C8-B24F-88118981422A}
|
||||
{FDC361C5-7734-493B-8CFB-037308B35122} = {FDC361C5-7734-493B-8CFB-037308B35122}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "3rdparty\hidapi\hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
@@ -83,7 +84,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cubeb", "rpcs3\Cubeb.vcxpro
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcubeb", "3rdparty\cubeb\libcubeb.vcxproj", "{FDA7B080-03B0-48C8-B24F-88118981422A}"
|
||||
EndProject
|
||||
Project("{508c291a-3d18-49f5-b25d-f7c8db92cb21}") = "soundtouch", "3rdparty\SoundTouch\soundtouch.vcxproj", "{508c291a-3d18-49f5-b25d-f7c8db92cb21}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soundtouch", "3rdparty\SoundTouch\soundtouch.vcxproj", "{508C291A-3D18-49F5-B25D-F7C8DB92CB21}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL", "3rdparty\libsdl-org\SDL.vcxproj", "{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pine", "pine", "{A55DA1B5-CC17-4525-BE7F-1659CE17BB56}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
@@ -176,10 +179,14 @@ Global
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A}.Debug|x64.Build.0 = Debug|x64
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A}.Release|x64.ActiveCfg = Release|x64
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A}.Release|x64.Build.0 = Release|x64
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Debug|x64.Build.0 = Debug|x64
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Release|x64.ActiveCfg = Release|x64
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Release|x64.Build.0 = Release|x64
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21}.Debug|x64.Build.0 = Debug|x64
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21}.Release|x64.ActiveCfg = Release|x64
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21}.Release|x64.Build.0 = Release|x64
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Debug|x64.Build.0 = Debug|x64
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Release|x64.ActiveCfg = Release|x64
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -206,7 +213,8 @@ Global
|
||||
{A37E4273-85DB-4217-B775-CE971B87D9DF} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
|
||||
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
|
||||
{FDA7B080-03B0-48C8-B24F-88118981422A} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{508c291a-3d18-49f5-b25d-f7c8db92cb21} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{A55DA1B5-CC17-4525-BE7F-1659CE17BB56} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
|
||||
@@ -66,10 +66,12 @@ set(RPCS3_SRC
|
||||
Input/ds4_pad_handler.cpp
|
||||
Input/dualsense_pad_handler.cpp
|
||||
Input/evdev_joystick_handler.cpp
|
||||
Input/evdev_gun_handler.cpp
|
||||
Input/hid_pad_handler.cpp
|
||||
Input/keyboard_pad_handler.cpp
|
||||
Input/mm_joystick_handler.cpp
|
||||
Input/pad_thread.cpp
|
||||
Input/sdl_pad_handler.cpp
|
||||
Input/xinput_pad_handler.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
|
||||
LOG_CHANNEL(edat_log, "EDAT");
|
||||
|
||||
// Static variables are being modified concurrently in ec.cpp, for now use a mutex
|
||||
static shared_mutex ec_mtx;
|
||||
|
||||
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
|
||||
{
|
||||
int mode = crypto_mode & 0xF0000000;
|
||||
@@ -482,8 +479,6 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
|
||||
unsigned char signature_s[0x15] = { 0 };
|
||||
unsigned char zero_buf[0x15] = { 0 };
|
||||
|
||||
std::lock_guard lock(ec_mtx);
|
||||
|
||||
// Setup ECDSA curve and public key.
|
||||
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
|
||||
ecdsa_set_pub(VSH_PUB);
|
||||
|
||||
@@ -115,6 +115,11 @@ public:
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||
{
|
||||
return ReadData(offset, static_cast<u8*>(buffer), size);
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
|
||||
+203
-74
@@ -4,12 +4,17 @@
|
||||
#include "key_vault.h"
|
||||
#include "util/logs.hpp"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Utilities/mutex.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_utils.hpp"
|
||||
#include "Emu/VFS.h"
|
||||
#include "unpkg.h"
|
||||
#include "util/sysinfo.hpp"
|
||||
#include "Loader/PSF.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
LOG_CHANNEL(pkg_log, "PKG");
|
||||
|
||||
package_reader::package_reader(const std::string& path)
|
||||
@@ -189,8 +194,7 @@ bool package_reader::read_metadata()
|
||||
|
||||
// Read title ID and use it as an installation directory
|
||||
m_install_dir.resize(9);
|
||||
archive_seek(55);
|
||||
archive_read(&m_install_dir.front(), m_install_dir.size());
|
||||
archive_read_block(55, &m_install_dir.front(), m_install_dir.size());
|
||||
|
||||
// Read package metadata
|
||||
|
||||
@@ -509,7 +513,7 @@ bool package_reader::read_param_sfo()
|
||||
|
||||
std::vector<PKGEntry> entries(m_header.file_count);
|
||||
|
||||
std::memcpy(entries.data(), m_buf.get(), entries.size() * sizeof(PKGEntry));
|
||||
std::memcpy(entries.data(), m_bufs.back().get(), entries.size() * sizeof(PKGEntry));
|
||||
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
@@ -523,7 +527,7 @@ bool package_reader::read_param_sfo()
|
||||
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data());
|
||||
|
||||
const std::string_view name{reinterpret_cast<char*>(m_buf.get()), entry.name_size};
|
||||
const std::string_view name{reinterpret_cast<char*>(m_bufs.back().get()), entry.name_size};
|
||||
|
||||
// We're looking for the PARAM.SFO file, if there is any
|
||||
if (usz ndelim = name.find_first_not_of('/'); ndelim == umax || name.substr(ndelim) != "PARAM.SFO")
|
||||
@@ -538,13 +542,13 @@ bool package_reader::read_param_sfo()
|
||||
{
|
||||
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
|
||||
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data()) != block_size)
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data()).size() != block_size)
|
||||
{
|
||||
pkg_log.error("Failed to decrypt PARAM.SFO file");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tmp.write(m_buf.get(), block_size) != block_size)
|
||||
if (tmp.write(m_bufs.back().get(), block_size) != block_size)
|
||||
{
|
||||
pkg_log.error("Failed to write to temporary PARAM.SFO file");
|
||||
return false;
|
||||
@@ -553,7 +557,7 @@ bool package_reader::read_param_sfo()
|
||||
|
||||
tmp.seek(0);
|
||||
|
||||
m_psf = psf::load_object(tmp);
|
||||
m_psf = psf::load_object(tmp, name);
|
||||
|
||||
if (m_psf.empty())
|
||||
{
|
||||
@@ -610,7 +614,8 @@ package_error package_reader::check_target_app_version() const
|
||||
return package_error::no_error;
|
||||
}
|
||||
|
||||
const fs::file installed_sfo_file(rpcs3::utils::get_hdd0_dir() + "game/" + std::string(title_id) + "/PARAM.SFO");
|
||||
const std::string sfo_path = rpcs3::utils::get_hdd0_dir() + "game/" + std::string(title_id) + "/PARAM.SFO";
|
||||
const fs::file installed_sfo_file(sfo_path);
|
||||
if (!installed_sfo_file)
|
||||
{
|
||||
if (!target_app_ver.empty())
|
||||
@@ -624,7 +629,7 @@ package_error package_reader::check_target_app_version() const
|
||||
return package_error::no_error;
|
||||
}
|
||||
|
||||
const auto installed_psf = psf::load_object(installed_sfo_file);
|
||||
const auto installed_psf = psf::load_object(installed_sfo_file, sfo_path);
|
||||
|
||||
const auto installed_title_id = psf::get_string(installed_psf, "TITLE_ID", "");
|
||||
const auto installed_app_ver = psf::get_string(installed_psf, "APP_VER", "");
|
||||
@@ -686,15 +691,19 @@ package_error package_reader::check_target_app_version() const
|
||||
return package_error::app_version;
|
||||
}
|
||||
|
||||
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic, bool verbose = false);
|
||||
|
||||
bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
bool package_reader::fill_data(std::map<std::string, install_entry*>& all_install_entries)
|
||||
{
|
||||
if (!m_is_valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_install_entries.clear();
|
||||
m_install_path.clear();
|
||||
m_bootable_file_path.clear();
|
||||
m_entry_indexer = 0;
|
||||
m_written_bytes = 0;
|
||||
|
||||
// Get full path and create the directory
|
||||
std::string dir = rpcs3::utils::get_hdd0_dir();
|
||||
|
||||
@@ -730,7 +739,7 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
dir += m_install_dir + '/';
|
||||
|
||||
// If false, an existing directory is being overwritten: cannot cancel the operation
|
||||
const bool was_null = !fs::is_dir(dir);
|
||||
m_was_null = !fs::is_dir(dir);
|
||||
|
||||
if (!fs::create_path(dir))
|
||||
{
|
||||
@@ -738,6 +747,8 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_install_path = dir;
|
||||
|
||||
if (!decrypt_data())
|
||||
{
|
||||
return false;
|
||||
@@ -747,23 +758,107 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
|
||||
std::vector<PKGEntry> entries(m_header.file_count);
|
||||
|
||||
std::memcpy(entries.data(), m_buf.get(), entries.size() * sizeof(PKGEntry));
|
||||
std::memcpy(entries.data(), m_bufs.back().get(), entries.size() * sizeof(PKGEntry));
|
||||
|
||||
// Create directories first
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
if (entry.name_size > 256)
|
||||
if (entry.name_size > PKG_MAX_FILENAME_SIZE)
|
||||
{
|
||||
num_failures++;
|
||||
pkg_log.error("PKG name size is too big (0x%x)", entry.name_size);
|
||||
break;
|
||||
}
|
||||
|
||||
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0u;
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data());
|
||||
|
||||
const std::string name{reinterpret_cast<char*>(m_bufs.back().get()), entry.name_size};
|
||||
std::string path = dir + vfs::escape(name);
|
||||
|
||||
const bool log_error = entry.pad || (entry.type & ~PKG_FILE_ENTRY_KNOWN_BITS);
|
||||
|
||||
(log_error ? pkg_log.error : pkg_log.notice)("Entry 0x%08x: %s (pad=0x%x)", entry.type, name, entry.pad);
|
||||
|
||||
switch (const u8 entry_type = entry.type & 0xff)
|
||||
{
|
||||
case PKG_FILE_ENTRY_FOLDER:
|
||||
case 0x12:
|
||||
{
|
||||
if (fs::is_dir(path))
|
||||
{
|
||||
pkg_log.warning("Reused existing directory %s", path);
|
||||
}
|
||||
else if (fs::create_path(path))
|
||||
{
|
||||
pkg_log.notice("Created directory %s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
num_failures++;
|
||||
pkg_log.error("Failed to create directory %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
const std::string true_path = std::filesystem::weakly_canonical(std::filesystem::u8path(path)).string();
|
||||
auto map_ptr = &*all_install_entries.try_emplace(true_path).first;
|
||||
|
||||
m_install_entries.push_back({ map_ptr, name, entry.file_offset, entry.file_size, entry.type, entry.pad });
|
||||
|
||||
if (map_ptr->second && !(entry.type & PKG_FILE_ENTRY_OVERWRITE))
|
||||
{
|
||||
// Cannot override
|
||||
continue;
|
||||
}
|
||||
|
||||
// Link
|
||||
map_ptr->second = &m_install_entries.back();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_failures != 0)
|
||||
{
|
||||
pkg_log.error("Package installation failed: %s", dir);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic, bool verbose = false);
|
||||
|
||||
usz package_reader::extract_worker(thread_key thread_data_key, std::map<std::string, install_entry*>& all_install_entries)
|
||||
{
|
||||
usz num_failures = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const usz maybe_index = m_entry_indexer++;
|
||||
|
||||
if (maybe_index >= m_install_entries.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const install_entry& entry = ::at32(m_install_entries, maybe_index);
|
||||
|
||||
if (!entry.is_dominating())
|
||||
{
|
||||
// Overwritten by another entry
|
||||
m_written_bytes += entry.file_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0u;
|
||||
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data());
|
||||
|
||||
const std::string name{reinterpret_cast<char*>(m_buf.get()), entry.name_size};
|
||||
const std::string path = dir + vfs::escape(name);
|
||||
const std::string& path = entry.weak_reference->first;
|
||||
const std::string& name = entry.name;
|
||||
|
||||
const bool log_error = entry.pad || (entry.type & ~PKG_FILE_ENTRY_KNOWN_BITS);
|
||||
(log_error ? pkg_log.error : pkg_log.notice)("Entry 0x%08x: %s (pad=0x%x)", entry.type, name, entry.pad);
|
||||
@@ -798,43 +893,33 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
|
||||
if (entry_type == PKG_FILE_ENTRY_NPDRMEDAT)
|
||||
{
|
||||
pkg_log.todo("NPDRM EDAT!");
|
||||
pkg_log.warning("NPDRM EDAT!");
|
||||
}
|
||||
|
||||
if (fs::file out = is_buffered ? fs::make_stream<std::vector<u8>>() : fs::file{ path, fs::rewrite })
|
||||
if (fs::file out = is_buffered ? fs::make_stream<std::vector<u8>>() : fs::file{ path, did_overwrite ? fs::rewrite : fs::write_new })
|
||||
{
|
||||
bool extract_success = true;
|
||||
for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE)
|
||||
{
|
||||
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
|
||||
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data()) != block_size)
|
||||
const std::span<const char> data_span = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), thread_data_key);
|
||||
|
||||
if (data_span.size() != block_size)
|
||||
{
|
||||
extract_success = false;
|
||||
pkg_log.error("Failed to extract file %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
if (out.write(m_buf.get(), block_size) != block_size)
|
||||
if (out.write(data_span.data(), block_size) != block_size)
|
||||
{
|
||||
extract_success = false;
|
||||
pkg_log.error("Failed to write file %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sync.fetch_add((block_size + 0.0) / m_header.data_size) < 0.)
|
||||
{
|
||||
if (was_null)
|
||||
{
|
||||
pkg_log.error("Package installation cancelled: %s", dir);
|
||||
out.close();
|
||||
fs::remove_all(dir, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot cancel the installation
|
||||
sync += 1.;
|
||||
}
|
||||
m_written_bytes += block_size;
|
||||
}
|
||||
|
||||
if (is_buffered)
|
||||
@@ -857,6 +942,12 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
else
|
||||
{
|
||||
pkg_log.notice("Created file %s", path);
|
||||
|
||||
if (name == "USRDIR/EBOOT.BIN" && entry.file_size > 4)
|
||||
{
|
||||
// Expose the creation of a bootable file
|
||||
m_bootable_file_path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -872,43 +963,67 @@ bool package_reader::extract_data(atomic_t<double>& sync)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PKG_FILE_ENTRY_FOLDER:
|
||||
case 0x12:
|
||||
{
|
||||
if (fs::create_dir(path))
|
||||
{
|
||||
pkg_log.notice("Created directory %s", path);
|
||||
}
|
||||
else if (fs::is_dir(path))
|
||||
{
|
||||
pkg_log.warning("Reused existing directory %s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
num_failures++;
|
||||
pkg_log.error("Failed to create directory %s", path);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
num_failures++;
|
||||
pkg_log.error("Unknown PKG entry type (0x%x) %s", entry.type, name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_failures == 0)
|
||||
return num_failures;
|
||||
}
|
||||
|
||||
bool package_reader::extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths)
|
||||
{
|
||||
std::map<std::string, install_entry*> all_install_entries;
|
||||
|
||||
for (auto& reader : readers)
|
||||
{
|
||||
pkg_log.success("Package successfully installed to %s", dir);
|
||||
if (!reader.fill_data(all_install_entries))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
usz num_failures = 0;
|
||||
|
||||
for (auto& reader : readers)
|
||||
{
|
||||
fs::remove_all(dir, true);
|
||||
pkg_log.error("Package installation failed: %s", dir);
|
||||
reader.m_bufs.resize(std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size()));
|
||||
|
||||
atomic_t<usz> thread_indexer = 0;
|
||||
|
||||
named_thread_group workers("PKG Installer "sv, std::max<usz>(reader.m_bufs.size(), 1) - 1, [&]()
|
||||
{
|
||||
num_failures += reader.extract_worker(thread_key{thread_indexer++}, all_install_entries);
|
||||
});
|
||||
|
||||
num_failures += reader.extract_worker(thread_key{thread_indexer++}, all_install_entries);
|
||||
workers.join();
|
||||
|
||||
reader.m_bufs.clear();
|
||||
reader.m_bufs.shrink_to_fit();
|
||||
|
||||
if (num_failures)
|
||||
{
|
||||
if (reader.m_was_null)
|
||||
{
|
||||
fs::remove_all(reader.m_install_path, true);
|
||||
}
|
||||
|
||||
pkg_log.success("Package failed to install ('%s')", reader.m_install_path);
|
||||
break;
|
||||
}
|
||||
else if (reader.get_progress(1) != 1)
|
||||
{
|
||||
pkg_log.warning("Missing %d bytes from PKG total files size.", reader.m_header.data_size - reader.m_written_bytes);
|
||||
reader.m_written_bytes = reader.m_header.data_size; // Mark as completed anyway
|
||||
}
|
||||
|
||||
// May be empty
|
||||
bootable_paths.emplace_back(std::move(reader.m_bootable_file_path));
|
||||
}
|
||||
|
||||
return num_failures == 0;
|
||||
@@ -922,28 +1037,42 @@ void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damo
|
||||
u64 package_reader::archive_read(void* data_ptr, const u64 num_bytes)
|
||||
{
|
||||
return m_file ? m_file.read(data_ptr, num_bytes) : 0;
|
||||
};
|
||||
}
|
||||
|
||||
u64 package_reader::decrypt(u64 offset, u64 size, const uchar* key)
|
||||
std::span<const char> package_reader::archive_read_block(u64 offset, void* data_ptr, u64 num_bytes)
|
||||
{
|
||||
const usz read_n = m_file.read_at(offset, data_ptr, num_bytes);
|
||||
|
||||
return {static_cast<const char*>(data_ptr), read_n};
|
||||
}
|
||||
|
||||
std::span<const char> package_reader::decrypt(u64 offset, u64 size, const uchar* key, thread_key thread_data_key)
|
||||
{
|
||||
if (!m_is_valid)
|
||||
{
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!m_buf)
|
||||
if (m_bufs.empty())
|
||||
{
|
||||
// Assume in single-threaded mode still
|
||||
m_bufs.resize(1);
|
||||
}
|
||||
|
||||
auto& local_buf = ::at32(m_bufs, thread_data_key.unique_num);
|
||||
|
||||
if (!local_buf)
|
||||
{
|
||||
// Allocate buffer with BUF_SIZE size or more if required
|
||||
m_buf.reset(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * m_header.file_count) / sizeof(u128)]);
|
||||
local_buf.reset(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * m_header.file_count) / sizeof(u128)]);
|
||||
}
|
||||
|
||||
archive_seek(m_header.data_offset + offset);
|
||||
|
||||
// Read the data and set available size
|
||||
const u64 read = archive_read(m_buf.get(), size);
|
||||
const auto data_span = archive_read_block(m_header.data_offset + offset, local_buf.get(), size);
|
||||
ensure(data_span.data() == static_cast<void*>(local_buf.get()));
|
||||
|
||||
// Get block count
|
||||
const u64 blocks = (read + 15) / 16;
|
||||
const u64 blocks = (data_span.size() + 15) / 16;
|
||||
|
||||
if (m_header.pkg_type == PKG_RELEASE_TYPE_DEBUG)
|
||||
{
|
||||
@@ -969,7 +1098,7 @@ u64 package_reader::decrypt(u64 offset, u64 size, const uchar* key)
|
||||
|
||||
sha1(reinterpret_cast<const u8*>(input), sizeof(input), hash.data);
|
||||
|
||||
m_buf[i] ^= hash._v128;
|
||||
local_buf[i] ^= hash._v128;
|
||||
}
|
||||
}
|
||||
else if (m_header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
|
||||
@@ -989,7 +1118,7 @@ u64 package_reader::decrypt(u64 offset, u64 size, const uchar* key)
|
||||
|
||||
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const u8*>(&input), reinterpret_cast<u8*>(&key));
|
||||
|
||||
m_buf[i] ^= key;
|
||||
local_buf[i] ^= key;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -998,5 +1127,5 @@ u64 package_reader::decrypt(u64 offset, u64 size, const uchar* key)
|
||||
}
|
||||
|
||||
// Return the amount of data written in buf
|
||||
return read;
|
||||
return data_span;
|
||||
};
|
||||
|
||||
+65
-7
@@ -6,12 +6,15 @@
|
||||
#include "Utilities/File.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <span>
|
||||
#include <deque>
|
||||
|
||||
// Constants
|
||||
enum
|
||||
enum : u32
|
||||
{
|
||||
PKG_HEADER_SIZE = 0xC0, // sizeof(pkg_header) + sizeof(pkg_unk_checksum)
|
||||
PKG_HEADER_SIZE2 = 0x280,
|
||||
PKG_MAX_FILENAME_SIZE = 256,
|
||||
};
|
||||
|
||||
enum : u16
|
||||
@@ -303,35 +306,90 @@ enum class package_error
|
||||
|
||||
class package_reader
|
||||
{
|
||||
struct thread_key
|
||||
{
|
||||
const usz unique_num = umax;
|
||||
};
|
||||
|
||||
struct install_entry
|
||||
{
|
||||
typename std::map<std::string, install_entry*>::value_type* weak_reference{};
|
||||
std::string name;
|
||||
|
||||
u64 file_offset{};
|
||||
u64 file_size{};
|
||||
u32 type{};
|
||||
u32 pad{};
|
||||
|
||||
// Check if the entry is the same one registered in entries to install
|
||||
bool is_dominating() const
|
||||
{
|
||||
return weak_reference->second == this;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
package_reader(const std::string& path);
|
||||
~package_reader();
|
||||
|
||||
bool is_valid() const { return m_is_valid; }
|
||||
package_error check_target_app_version() const;
|
||||
bool extract_data(atomic_t<double>& sync);
|
||||
static bool extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths);
|
||||
psf::registry get_psf() const { return m_psf; }
|
||||
|
||||
int get_progress(int maximum = 100) const
|
||||
{
|
||||
const usz wr = m_written_bytes;
|
||||
|
||||
return wr >= m_header.data_size ? maximum : ::narrow<int>(wr * maximum / m_header.data_size);
|
||||
}
|
||||
|
||||
void abort_extract()
|
||||
{
|
||||
m_entry_indexer.fetch_op([this](usz& v)
|
||||
{
|
||||
if (v < m_install_entries.size())
|
||||
{
|
||||
v = m_install_entries.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
bool read_header();
|
||||
bool read_metadata();
|
||||
bool read_param_sfo();
|
||||
bool decrypt_data();
|
||||
void archive_seek(const s64 new_offset, const fs::seek_mode damode = fs::seek_set);
|
||||
u64 archive_read(void* data_ptr, const u64 num_bytes);
|
||||
u64 decrypt(u64 offset, u64 size, const uchar* key);
|
||||
void archive_seek(s64 new_offset, const fs::seek_mode damode = fs::seek_set);
|
||||
u64 archive_read(void* data_ptr, u64 num_bytes);
|
||||
bool fill_data(std::map<std::string, install_entry*>& all_install_entries);
|
||||
std::span<const char> archive_read_block(u64 offset, void* data_ptr, u64 num_bytes);
|
||||
std::span<const char> decrypt(u64 offset, u64 size, const uchar* key, thread_key thread_data_key = {0});
|
||||
usz extract_worker(thread_key thread_data_key, std::map<std::string, install_entry*>& all_install_entries);
|
||||
|
||||
const usz BUF_SIZE = 8192 * 1024; // 8 MB
|
||||
std::deque<install_entry> m_install_entries;
|
||||
std::string m_install_path;
|
||||
atomic_t<usz> m_entry_indexer = 0;
|
||||
atomic_t<usz> m_written_bytes = 0;
|
||||
bool m_was_null = false;
|
||||
|
||||
static constexpr usz BUF_SIZE = 8192 * 1024; // 8 MB
|
||||
|
||||
bool m_is_valid = false;
|
||||
|
||||
std::string m_path{};
|
||||
std::string m_install_dir{};
|
||||
fs::file m_file{};
|
||||
std::unique_ptr<u128[]> m_buf{};
|
||||
std::vector<std::unique_ptr<u128[]>> m_bufs{};
|
||||
std::array<uchar, 16> m_dec_key{};
|
||||
|
||||
PKGHeader m_header{};
|
||||
PKGMetaData m_metadata{};
|
||||
psf::registry m_psf{};
|
||||
|
||||
// Expose bootable file installed (if installed such)
|
||||
std::string m_bootable_file_path;
|
||||
};
|
||||
|
||||
@@ -41,6 +41,7 @@ target_include_directories(rpcs3_emu
|
||||
target_sources(rpcs3_emu PRIVATE
|
||||
../util/atomic.cpp
|
||||
../util/media_utils.cpp
|
||||
../util/video_provider.cpp
|
||||
../util/logs.cpp
|
||||
../util/yaml.cpp
|
||||
../util/vm_native.cpp
|
||||
@@ -321,6 +322,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||
Cell/Modules/cellVoice.cpp
|
||||
Cell/Modules/cellVpost.cpp
|
||||
Cell/Modules/cellWebBrowser.cpp
|
||||
Cell/Modules/HLE_PATCHES.cpp
|
||||
Cell/Modules/libad_async.cpp
|
||||
Cell/Modules/libad_core.cpp
|
||||
Cell/Modules/libmedi.cpp
|
||||
@@ -380,6 +382,7 @@ target_link_libraries(rpcs3_emu
|
||||
# Io
|
||||
target_sources(rpcs3_emu PRIVATE
|
||||
Io/camera_config.cpp
|
||||
Io/recording_config.cpp
|
||||
Io/interception.cpp
|
||||
Io/KeyboardHandler.cpp
|
||||
Io/pad_config.cpp
|
||||
@@ -538,7 +541,7 @@ endif()
|
||||
|
||||
target_link_libraries(rpcs3_emu
|
||||
PUBLIC
|
||||
3rdparty::ffmpeg
|
||||
3rdparty::ffmpeg 3rdparty::sdl2
|
||||
3rdparty::opengl 3rdparty::stblib
|
||||
3rdparty::vulkan 3rdparty::glew
|
||||
3rdparty::libusb 3rdparty::wolfssl
|
||||
|
||||
+35
-16
@@ -3,35 +3,54 @@
|
||||
#include "util/types.hpp"
|
||||
#include "Utilities/StrFmt.h"
|
||||
|
||||
namespace logs
|
||||
{
|
||||
struct message;
|
||||
}
|
||||
|
||||
// Error code type (return type), implements error reporting.
|
||||
class error_code
|
||||
{
|
||||
s32 value;
|
||||
|
||||
public:
|
||||
error_code() = default;
|
||||
|
||||
// Implementation must be provided independently
|
||||
static s32 error_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args);
|
||||
|
||||
// Common constructor
|
||||
template<typename ET>
|
||||
error_code(const ET& value)
|
||||
: value(error_report(static_cast<s32>(value), " : %s", fmt::type_info_v<ET>, fmt_args_t<ET>{fmt_unveil<ET>::get(value)}))
|
||||
template <typename ET> requires requires (ET v) { static_cast<s32>(v); }
|
||||
error_code(const logs::message* ch, const ET& value) noexcept
|
||||
: value(error_report(static_cast<s32>(value), ch, " : %s", fmt::type_info_v<ET>, fmt_args_t<ET>{fmt_unveil<ET>::get(value)}))
|
||||
{
|
||||
}
|
||||
|
||||
// Error constructor (2 args)
|
||||
template<typename ET, typename T>
|
||||
error_code(const ET& value, const T& arg)
|
||||
: value(error_report(static_cast<s32>(value), " : %s, %s", fmt::type_info_v<ET, T>, fmt_args_t<ET, T>{fmt_unveil<ET>::get(value), fmt_unveil<T>::get(arg)}))
|
||||
template <typename ET, typename T> requires requires (ET v) { static_cast<s32>(v); }
|
||||
error_code(const logs::message* ch, const ET& value, const T& arg) noexcept
|
||||
: value(error_report(static_cast<s32>(value), ch, " : %s, %s", fmt::type_info_v<ET, T>, fmt_args_t<ET, T>{fmt_unveil<ET>::get(value), fmt_unveil<T>::get(arg)}))
|
||||
{
|
||||
}
|
||||
|
||||
// Formatting constructor (error, format string, variadic list)
|
||||
template <typename ET, typename... Args> requires (sizeof...(Args) > 0)
|
||||
error_code(const ET& value, const const_str& fmt, const Args&... args)
|
||||
: value(error_report(static_cast<s32>(value), fmt, fmt::type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...}))
|
||||
template <typename ET, typename... Args> requires requires (ET v) { static_cast<s32>(v); }
|
||||
error_code(const logs::message* ch, const ET& value, const const_str& fmt, const Args&... args) noexcept
|
||||
: value(error_report(static_cast<s32>(value), ch, fmt, fmt::type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...}))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
// Implementation must be provided independently
|
||||
static s32 error_report(s32 result, const logs::message* channel, const char* fmt, const fmt_type_info* sup, const u64* args);
|
||||
|
||||
error_code() = default;
|
||||
|
||||
// Constructor without channel
|
||||
template <typename... Args> requires (sizeof...(Args) > 0 && !(std::is_same_v<std::decay_t<std::remove_pointer_t<Args>>, logs::message> || ...))
|
||||
error_code(const Args&... args) noexcept
|
||||
: error_code(std::add_pointer_t<const logs::message>{}, args...)
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor with channel
|
||||
template <typename... Args>
|
||||
error_code(const logs::message& ch, const Args&... args) noexcept
|
||||
: error_code(std::addressof(ch), args...)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -51,7 +70,7 @@ enum CellNotAnError : s32
|
||||
|
||||
// Constructor specialization that doesn't trigger reporting
|
||||
template <>
|
||||
constexpr FORCE_INLINE error_code::error_code(const CellNotAnError& value)
|
||||
constexpr FORCE_INLINE error_code::error_code(const CellNotAnError& value) noexcept
|
||||
: value(value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
// SONIC THE HEDGEDOG: a fix for a race condition between SPUs and PPUs causing missing graphics (SNR is overriden when non-empty)
|
||||
void WaitForSPUsToEmptySNRs(ppu_thread& ppu, u32 spu_id, u32 snr_mask)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
auto [spu, group] = lv2_spu_group::get_thread(spu_id);
|
||||
|
||||
if ((!spu && spu_id != umax) || snr_mask % 4 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait until specified SNRs are reported empty at least once
|
||||
for (bool has_busy = true; has_busy && !ppu.is_stopped(); std::this_thread::yield())
|
||||
{
|
||||
has_busy = false;
|
||||
|
||||
auto for_one = [&](u32, spu_thread& spu)
|
||||
{
|
||||
if ((snr_mask & 1) && spu.ch_snr1.get_count())
|
||||
{
|
||||
has_busy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((snr_mask & 2) && spu.ch_snr2.get_count())
|
||||
{
|
||||
has_busy = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (spu)
|
||||
{
|
||||
// Wait for a single SPU
|
||||
for_one(spu->id, *spu);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait for all SPUs
|
||||
idm::select<named_thread<spu_thread>>(for_one);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE(ppu_module_manager::hle_patches)("RPCS3_HLE_LIBRARY", []()
|
||||
{
|
||||
REG_FUNC(RPCS3_HLE_LIBRARY, WaitForSPUsToEmptySNRs);
|
||||
});
|
||||
@@ -163,7 +163,7 @@ bool statichle_handler::check_against_patterns(vm::cptr<u8>& data, u32 size, u32
|
||||
}
|
||||
|
||||
const auto sfunc = &::at32(smodule->functions, pat.fnid);
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(sfunc->index) + 4;
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(sfunc->index, true);
|
||||
|
||||
// write stub
|
||||
vm::write32(addr, ppu_instructions::LIS(0, (target&0xFFFF0000)>>16));
|
||||
|
||||
@@ -282,15 +282,10 @@ public:
|
||||
|
||||
struct AudioReader
|
||||
{
|
||||
u32 addr;
|
||||
u32 size;
|
||||
bool init;
|
||||
bool has_ats;
|
||||
|
||||
AudioReader()
|
||||
: init(false)
|
||||
{
|
||||
}
|
||||
u32 addr{};
|
||||
u32 size{};
|
||||
bool init{};
|
||||
bool has_ats{};
|
||||
|
||||
} reader;
|
||||
|
||||
@@ -304,13 +299,14 @@ public:
|
||||
u32 memBias = 0;
|
||||
|
||||
AdecTask task;
|
||||
u64 last_pts, first_pts;
|
||||
u64 last_pts{};
|
||||
u64 first_pts{};
|
||||
|
||||
u32 ch_out;
|
||||
u32 ch_cfg;
|
||||
u32 frame_size;
|
||||
u32 sample_rate;
|
||||
bool use_ats_headers;
|
||||
u32 ch_out{};
|
||||
u32 ch_cfg{};
|
||||
u32 frame_size{};
|
||||
u32 sample_rate{};
|
||||
bool use_ats_headers{};
|
||||
|
||||
AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
|
||||
: ppu_thread({}, "", 0)
|
||||
|
||||
@@ -39,7 +39,7 @@ audio_out_configuration::audio_out_configuration()
|
||||
std::vector<CellAudioOutSoundMode>& primary_modes = primary_output.sound_modes;
|
||||
std::vector<CellAudioOutSoundMode>& secondary_modes = secondary_output.sound_modes;
|
||||
|
||||
const psf::registry sfo = psf::load_object(fs::file(Emu.GetSfoDir(true) + "/PARAM.SFO"));
|
||||
const psf::registry sfo = psf::load_object(Emu.GetSfoDir(true) + "/PARAM.SFO");
|
||||
const s32 sound_format = psf::get_integer(sfo, "SOUND_FORMAT", psf::sound_format_flag::lpcm_2); // Default to Linear PCM 2 Ch.
|
||||
|
||||
const bool supports_lpcm_2 = (sound_format & psf::sound_format_flag::lpcm_2); // Linear PCM 2 Ch.
|
||||
|
||||
@@ -298,7 +298,7 @@ error_code cellAudioOutGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioOutDev
|
||||
|
||||
error_code cellVideoOutSetGamma(u32 videoOut, f32 gamma)
|
||||
{
|
||||
cellAvconfExt.warning("cellVideoOutSetGamma(videoOut=%d, gamma=%f)", videoOut, gamma);
|
||||
cellAvconfExt.trace("cellVideoOutSetGamma(videoOut=%d, gamma=%f)", videoOut, gamma);
|
||||
|
||||
if (gamma < 0.8f || gamma > 1.2f)
|
||||
{
|
||||
|
||||
@@ -415,7 +415,7 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
|
||||
else
|
||||
{
|
||||
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
|
||||
const psf::registry psf = psf::load_object(fs::file(local_dir +"/PARAM.SFO"));
|
||||
const psf::registry psf = psf::load_object(local_dir + "/PARAM.SFO");
|
||||
|
||||
// Some following fields may be zero in old FW 1.00 version PARAM.SFO
|
||||
if (psf.contains("PARENTAL_LEVEL")) get->getParam.parentalLevel = ::at32(psf, "PARENTAL_LEVEL").as_integer();
|
||||
@@ -670,7 +670,7 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||
*attributes = 0; // TODO
|
||||
// TODO: dirName might be a read only string when BootCheck is called on a disc game. (e.g. Ben 10 Ultimate Alien: Cosmic Destruction)
|
||||
|
||||
sfo = psf::load_object(fs::file(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")));
|
||||
sfo = psf::load_object(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO"));
|
||||
}
|
||||
else if (cat == "GD")
|
||||
{
|
||||
@@ -679,7 +679,7 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||
*type = CELL_GAME_GAMETYPE_DISC;
|
||||
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
||||
|
||||
sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO")));
|
||||
sfo = psf::load_object(vfs::get(Emu.GetDir() + "PARAM.SFO"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -688,7 +688,7 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||
*type = CELL_GAME_GAMETYPE_HDD;
|
||||
*attributes = 0; // TODO
|
||||
|
||||
sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO")));
|
||||
sfo = psf::load_object(vfs::get(Emu.GetDir() + "PARAM.SFO"));
|
||||
dir = Emu.GetTitleID();
|
||||
}
|
||||
|
||||
@@ -723,7 +723,7 @@ error_code cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> r
|
||||
return CELL_GAME_ERROR_NOTPATCH;
|
||||
}
|
||||
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO")));
|
||||
psf::registry sfo = psf::load_object(vfs::get(Emu.GetDir() + "PARAM.SFO"));
|
||||
|
||||
auto& perm = g_fxo->get<content_permission>();
|
||||
|
||||
@@ -1698,7 +1698,7 @@ error_code cellDiscGameGetBootDiscInfo(vm::ptr<CellDiscGameSystemFileParam> getP
|
||||
}
|
||||
|
||||
// Always sets 0 at first dword
|
||||
*utils::bless<nse_t<u32, 1>>(getParam->titleId + 0) = 0;
|
||||
write_to_ptr<u32>(getParam->titleId, 0);
|
||||
|
||||
// This is also called by non-disc games, see NPUB90029
|
||||
static const std::string dir = "/dev_bdvd/PS3_GAME"s;
|
||||
@@ -1708,7 +1708,7 @@ error_code cellDiscGameGetBootDiscInfo(vm::ptr<CellDiscGameSystemFileParam> getP
|
||||
return CELL_DISCGAME_ERROR_NOT_DISCBOOT;
|
||||
}
|
||||
|
||||
const psf::registry psf = psf::load_object(fs::file(vfs::get(dir + "/PARAM.SFO")));
|
||||
const psf::registry psf = psf::load_object(vfs::get(dir + "/PARAM.SFO"));
|
||||
|
||||
if (psf.contains("PARENTAL_LEVEL")) getParam->parentalLevel = ::at32(psf, "PARENTAL_LEVEL").as_integer();
|
||||
if (psf.contains("TITLE_ID")) strcpy_trunc(getParam->titleId, ::at32(psf, "TITLE_ID").as_string());
|
||||
|
||||
@@ -529,7 +529,7 @@ void cellGcmSetFlipHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetFlipHandler(handler=*0x%x)", handler);
|
||||
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_initialized)
|
||||
{
|
||||
rsx->flip_handler = handler;
|
||||
}
|
||||
@@ -681,7 +681,7 @@ void cellGcmSetUserHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetUserHandler(handler=*0x%x)", handler);
|
||||
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_initialized)
|
||||
{
|
||||
rsx->user_handler = handler;
|
||||
}
|
||||
@@ -707,7 +707,7 @@ void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetVBlankHandler(handler=*0x%x)", handler);
|
||||
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_initialized)
|
||||
{
|
||||
rsx->vblank_handler = handler;
|
||||
}
|
||||
@@ -923,7 +923,7 @@ void cellGcmSetQueueHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetQueueHandler(handler=*0x%x)", handler);
|
||||
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_initialized)
|
||||
{
|
||||
rsx->queue_handler = handler;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,12 @@
|
||||
#include "Emu/RSX/Overlays/overlay_cursor.h"
|
||||
#include "Input/pad_thread.h"
|
||||
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
#include "Input/evdev_gun_handler.h"
|
||||
#endif
|
||||
|
||||
#include <cmath> // for fmod
|
||||
#include <type_traits>
|
||||
|
||||
LOG_CHANNEL(cellGem);
|
||||
|
||||
@@ -88,6 +93,46 @@ void fmt_class_string<CellGemVideoConvertFormatEnum>::format(std::string& out, u
|
||||
// * HLE helper structs *
|
||||
// **********************
|
||||
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
struct gun_handler
|
||||
{
|
||||
public:
|
||||
gun_handler() = default;
|
||||
|
||||
static constexpr auto thread_name = "Evdev Gun Thread"sv;
|
||||
|
||||
evdev_gun_handler handler{};
|
||||
atomic_t<u32> num_devices{0};
|
||||
|
||||
void operator()()
|
||||
{
|
||||
if (g_cfg.io.move != move_handler::gun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
|
||||
{
|
||||
const bool is_active = !Emu.IsPaused() && handler.is_init();
|
||||
|
||||
if (is_active)
|
||||
{
|
||||
for (u32 i = 0; i < num_devices; i++)
|
||||
{
|
||||
std::scoped_lock lock(handler.mutex);
|
||||
handler.poll(i);
|
||||
}
|
||||
}
|
||||
|
||||
thread_ctrl::wait_for(is_active ? 1000 : 10000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using gun_thread = named_thread<gun_handler>;
|
||||
|
||||
#endif
|
||||
|
||||
struct gem_config_data
|
||||
{
|
||||
public:
|
||||
@@ -214,6 +259,16 @@ public:
|
||||
connected_controllers = 1;
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
case move_handler::gun:
|
||||
{
|
||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
||||
std::scoped_lock lock(gun.handler.mutex);
|
||||
connected_controllers = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
||||
gun.num_devices = connected_controllers;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case move_handler::null:
|
||||
default:
|
||||
break;
|
||||
@@ -646,9 +701,10 @@ static inline void ds3_get_stick_values(const std::shared_ptr<Pad>& pad, s32& x_
|
||||
}
|
||||
}
|
||||
|
||||
static void ds3_pos_to_gem_image_state(const u32 port_no, const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state)
|
||||
template <typename T>
|
||||
static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!is_input_allowed())
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -666,30 +722,14 @@ static void ds3_pos_to_gem_image_state(const u32 port_no, const gem_config::gem_
|
||||
s32 ds3_pos_x, ds3_pos_y;
|
||||
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
|
||||
|
||||
pos_to_gem_image_state(port_no, controller, gem_image_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
|
||||
{
|
||||
if (!is_input_allowed())
|
||||
if constexpr (std::is_same<T, vm::ptr<CellGemState>>::value)
|
||||
{
|
||||
return;
|
||||
pos_to_gem_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
const auto& pad = ::at32(handler->GetPads(), port_no);
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
else if constexpr (std::is_same<T, vm::ptr<CellGemImageState>>::value)
|
||||
{
|
||||
return;
|
||||
pos_to_gem_image_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
s32 ds3_pos_x, ds3_pos_y;
|
||||
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
|
||||
|
||||
pos_to_gem_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -803,31 +843,8 @@ static bool mouse_input_to_pad(const u32 mouse_no, be_t<u16>& digital_buttons, b
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mouse_pos_to_gem_image_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state)
|
||||
{
|
||||
if (!gem_image_state || !is_input_allowed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& mouse = ::at32(handler.GetMice(), mouse_no);
|
||||
|
||||
pos_to_gem_image_state(mouse_no, controller, gem_image_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
}
|
||||
|
||||
static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
|
||||
template <typename T>
|
||||
static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
@@ -848,9 +865,83 @@ static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_con
|
||||
|
||||
const auto& mouse = ::at32(handler.GetMice(), mouse_no);
|
||||
|
||||
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
if constexpr (std::is_same<T, vm::ptr<CellGemState>>::value)
|
||||
{
|
||||
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
}
|
||||
else if constexpr (std::is_same<T, vm::ptr<CellGemImageState>>::value)
|
||||
{
|
||||
pos_to_gem_image_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
static bool gun_input_to_pad(const u32 gem_no, be_t<u16>& digital_buttons, be_t<u16>& analog_t)
|
||||
{
|
||||
digital_buttons = 0;
|
||||
analog_t = 0;
|
||||
|
||||
if (!is_input_allowed())
|
||||
return false;
|
||||
|
||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
||||
std::scoped_lock lock(gun.handler.mutex);
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_left) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_T;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_right) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_MOVE;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_middle) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_SELECT;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_1) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_START;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_2) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_CROSS;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_3) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_CIRCLE;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_4) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_SQUARE;
|
||||
|
||||
if (gun.handler.get_button(gem_no, gun_button::btn_5) == 1)
|
||||
digital_buttons |= CELL_GEM_CTRL_TRIANGLE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void gun_pos_to_gem_state(const u32 gem_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
return;
|
||||
|
||||
int x_pos, y_pos, x_max, y_max;
|
||||
{
|
||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
||||
std::scoped_lock lock(gun.handler.mutex);
|
||||
|
||||
x_pos = gun.handler.get_axis_x(gem_no);
|
||||
y_pos = gun.handler.get_axis_y(gem_no);
|
||||
x_max = gun.handler.get_axis_x_max(gem_no);
|
||||
y_max = gun.handler.get_axis_y_max(gem_no);
|
||||
}
|
||||
|
||||
if constexpr (std::is_same<T, vm::ptr<CellGemState>>::value)
|
||||
{
|
||||
pos_to_gem_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max);
|
||||
}
|
||||
else if constexpr (std::is_same<T, vm::ptr<CellGemImageState>>::value)
|
||||
{
|
||||
pos_to_gem_image_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// *********************
|
||||
// * cellGem functions *
|
||||
// *********************
|
||||
@@ -1232,7 +1323,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
|
||||
|
||||
*gem_image_state = {};
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake || g_cfg.io.move == move_handler::mouse)
|
||||
if (g_cfg.io.move != move_handler::null)
|
||||
{
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
gem_image_state->frame_timestamp = shared_data.frame_timestamp.load();
|
||||
@@ -1242,13 +1333,21 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
|
||||
gem_image_state->visible = gem.is_controller_ready(gem_num);
|
||||
gem_image_state->r_valid = true;
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake)
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
ds3_pos_to_gem_image_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
}
|
||||
else if (g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
mouse_pos_to_gem_image_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
case move_handler::fake:
|
||||
ds3_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
break;
|
||||
case move_handler::mouse:
|
||||
mouse_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
break;
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
case move_handler::gun:
|
||||
gun_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
break;
|
||||
#endif
|
||||
case move_handler::null:
|
||||
fmt::throw_exception("Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,7 +1379,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
||||
|
||||
*inertial_state = {};
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake || g_cfg.io.move == move_handler::mouse)
|
||||
if (g_cfg.io.move != move_handler::null)
|
||||
{
|
||||
ds3_input_to_ext(gem_num, gem.controllers[gem_num], inertial_state->ext);
|
||||
|
||||
@@ -1288,13 +1387,21 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
||||
inertial_state->counter = gem.inertial_counter++;
|
||||
inertial_state->accelerometer[0] = 10; // Current gravity in m/s²
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake)
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
case move_handler::fake:
|
||||
ds3_input_to_pad(gem_num, inertial_state->pad.digitalbuttons, inertial_state->pad.analog_T);
|
||||
}
|
||||
else if (g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
break;
|
||||
case move_handler::mouse:
|
||||
mouse_input_to_pad(gem_num, inertial_state->pad.digitalbuttons, inertial_state->pad.analog_T);
|
||||
break;
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
case move_handler::gun:
|
||||
gun_input_to_pad(gem_num, inertial_state->pad.digitalbuttons, inertial_state->pad.analog_T);
|
||||
break;
|
||||
#endif
|
||||
case move_handler::null:
|
||||
fmt::throw_exception("Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1442,7 +1549,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
|
||||
|
||||
*gem_state = {};
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake || g_cfg.io.move == move_handler::mouse)
|
||||
if (g_cfg.io.move != move_handler::null)
|
||||
{
|
||||
ds3_input_to_ext(gem_num, gem.controllers[gem_num], gem_state->ext);
|
||||
|
||||
@@ -1456,15 +1563,24 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
|
||||
gem_state->camera_pitch_angle = 0.f;
|
||||
gem_state->quat[3] = 1.f;
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake)
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
case move_handler::fake:
|
||||
ds3_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
|
||||
ds3_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_state);
|
||||
}
|
||||
else if (g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
break;
|
||||
case move_handler::mouse:
|
||||
mouse_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
|
||||
mouse_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_state);
|
||||
break;
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
case move_handler::gun:
|
||||
gun_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
|
||||
gun_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_state);
|
||||
break;
|
||||
#endif
|
||||
case move_handler::null:
|
||||
fmt::throw_exception("Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -296,8 +296,8 @@ error_code cellGifDecReadHeader(vm::ptr<GifDecoder> mainHandle, vm::ptr<GifStrea
|
||||
default: break; // TODO
|
||||
}
|
||||
|
||||
if (*utils::bless<be_t<u32>>(buffer + 0) != 0x47494638u ||
|
||||
(*utils::bless<le_t<u16>>(buffer + 4) != 0x6139u && *utils::bless<le_t<u16>>(buffer + 4) != 0x6137u)) // Error: The first 6 bytes are not a valid GIF signature
|
||||
if (read_from_ptr<be_t<u32>>(buffer + 0) != 0x47494638u ||
|
||||
(read_from_ptr<le_t<u16>>(buffer + 4) != 0x6139u && read_from_ptr<le_t<u16>>(buffer + 4) != 0x6137u)) // Error: The first 6 bytes are not a valid GIF signature
|
||||
{
|
||||
return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ error_code cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDe
|
||||
default: break; // TODO
|
||||
}
|
||||
|
||||
if (*utils::bless<le_t<u32>>(buffer.get() + 0) != 0xE0FFD8FF || // Error: Not a valid SOI header
|
||||
*utils::bless<u32>(buffer.get() + 6) != "JFIF"_u32) // Error: Not a valid JFIF string
|
||||
if (read_from_ptr<le_t<u32>>(buffer.get() + 0) != 0xE0FFD8FF || // Error: Not a valid SOI header
|
||||
read_from_ptr<u32>(buffer.get() + 6) != "JFIF"_u32) // Error: Not a valid JFIF string
|
||||
{
|
||||
return CELL_JPGDEC_ERROR_HEADER;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ error_code cellKbClearBuf(u32 port_no)
|
||||
const KbInfo& current_info = handler.GetInfo();
|
||||
|
||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||
return CELL_KB_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||
|
||||
KbData& current_data = handler.GetData(port_no);
|
||||
current_data.len = 0;
|
||||
@@ -331,7 +331,7 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
|
||||
const KbInfo& current_info = handler.GetInfo();
|
||||
|
||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||
return CELL_KB_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||
|
||||
KbData& current_data = handler.GetData(port_no);
|
||||
|
||||
@@ -474,7 +474,7 @@ error_code cellKbGetConfiguration(u32 port_no, vm::ptr<CellKbConfig> config)
|
||||
const KbInfo& current_info = handler.GetInfo();
|
||||
|
||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||
return CELL_KB_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||
|
||||
// tests show that config is checked only after the device's status
|
||||
if (!config)
|
||||
|
||||
@@ -104,7 +104,7 @@ error_code cellMouseClearBuf(u32 port_no)
|
||||
|
||||
if (port_no >= handler.GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_MOUSE_ERROR_NO_DEVICE);
|
||||
}
|
||||
|
||||
handler.GetDataList(port_no).clear();
|
||||
@@ -229,7 +229,7 @@ error_code cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
|
||||
|
||||
if (port_no >= handler.GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_MOUSE_ERROR_NO_DEVICE);
|
||||
}
|
||||
|
||||
std::memset(data.get_ptr(), 0, data.size());
|
||||
@@ -279,7 +279,7 @@ error_code cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
|
||||
|
||||
if (port_no >= handler.GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_MOUSE_ERROR_NO_DEVICE);
|
||||
}
|
||||
|
||||
std::memset(data.get_ptr(), 0, data.size());
|
||||
@@ -368,7 +368,7 @@ error_code cellMouseGetTabletDataList(u32 port_no, vm::ptr<CellMouseTabletDataLi
|
||||
|
||||
if (port_no >= handler.GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_MOUSE_ERROR_NO_DEVICE);
|
||||
}
|
||||
|
||||
std::memset(data.get_ptr(), 0, data.size());
|
||||
@@ -424,7 +424,7 @@ error_code cellMouseGetRawData(u32 port_no, vm::ptr<CellMouseRawData> data)
|
||||
|
||||
if (port_no >= handler.GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_MOUSE_ERROR_NO_DEVICE);
|
||||
}
|
||||
|
||||
std::memset(data.get_ptr(), 0, data.size());
|
||||
|
||||
@@ -144,7 +144,7 @@ error_code cellPadClearBuf(u32 port_no)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
clear_pad_buffer(pad);
|
||||
|
||||
@@ -177,7 +177,7 @@ error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
pad_get_data(port_no, data.get_ptr());
|
||||
return CELL_OK;
|
||||
@@ -504,7 +504,7 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr<CellPadPeriphData> data)
|
||||
const auto& pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
pad_get_data(port_no, &data->cellpad_data);
|
||||
|
||||
@@ -539,7 +539,7 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
// ?
|
||||
|
||||
@@ -605,7 +605,7 @@ error_code cellPadSetActDirect(u32 port_no, vm::ptr<CellPadActParam> param)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
// TODO: find out if this is checked here or later or at all
|
||||
if (!(pad->m_device_capability & CELL_PAD_CAPABILITY_ACTUATOR))
|
||||
@@ -753,7 +753,7 @@ error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr<CellPadCapabilityInfo>
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
// Should return the same as device capability mask, psl1ght has it backwards in pad->h
|
||||
memset(info->info, 0, CELL_PAD_MAX_CAPABILITY_INFO * sizeof(u32));
|
||||
@@ -811,7 +811,7 @@ error_code cellPadInfoPressMode(u32 port_no)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
return not_an_error((pad->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) ? 1 : 0);
|
||||
}
|
||||
@@ -840,7 +840,7 @@ error_code cellPadInfoSensorMode(u32 port_no)
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
|
||||
|
||||
return not_an_error((pad->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) ? 1 : 0);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -148,7 +148,7 @@ enum
|
||||
CELL_REC_SETINFO_MOVIE_START_TIME_MSEC = 100,
|
||||
CELL_REC_SETINFO_MOVIE_END_TIME_MSEC = 101,
|
||||
CELL_REC_SETINFO_MOVIE_META = 200,
|
||||
CELL_REC_SETINFO_SCEME_META = 201,
|
||||
CELL_REC_SETINFO_SCENE_META = 201,
|
||||
|
||||
CELL_REC_MOVIE_META_GAME_TITLE_LEN = 128,
|
||||
CELL_REC_MOVIE_META_MOVIE_TITLE_LEN = 128,
|
||||
|
||||
@@ -228,7 +228,7 @@ static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir,
|
||||
}
|
||||
|
||||
// PSF parameters
|
||||
const psf::registry psf = psf::load_object(fs::file(base_dir + entry.name + "/PARAM.SFO"));
|
||||
const psf::registry psf = psf::load_object(base_dir + entry.name + "/PARAM.SFO");
|
||||
|
||||
if (psf.empty())
|
||||
{
|
||||
@@ -755,7 +755,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
listGet->dirListNum++; // number of directories in list
|
||||
|
||||
// PSF parameters
|
||||
const psf::registry psf = psf::load_object(fs::file(base_dir + entry.name + "/PARAM.SFO"));
|
||||
const psf::registry psf = psf::load_object(base_dir + entry.name + "/PARAM.SFO");
|
||||
|
||||
if (psf.empty())
|
||||
{
|
||||
@@ -1372,7 +1372,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
const std::string old_path = base_dir + ".backup_" + save_entry.escaped + "/";
|
||||
const std::string new_path = base_dir + ".working_" + save_entry.escaped + "/";
|
||||
|
||||
psf::registry psf = psf::load_object(fs::file(dir_path + "PARAM.SFO"));
|
||||
psf::registry psf = psf::load_object(dir_path + "PARAM.SFO");
|
||||
bool has_modified = false;
|
||||
bool recreated = false;
|
||||
|
||||
@@ -1830,7 +1830,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
|
||||
if (file == all_files.cend() || file->second.size() <= fileSet->fileOffset)
|
||||
{
|
||||
cellSaveData.error("Failed to open file %s%s", dir_path, file_path);
|
||||
cellSaveData.error("Failed to open file %s%s (size=%d, fileOffset=%d)", dir_path, file_path, file->second.size(), fileSet->fileOffset);
|
||||
savedata_result = CELL_SAVEDATA_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
@@ -2070,7 +2070,7 @@ static NEVER_INLINE error_code savedata_get_list_item(vm::cptr<char> dirName, vm
|
||||
return CELL_SAVEDATA_ERROR_NODATA;
|
||||
}
|
||||
|
||||
const psf::registry psf = psf::load_object(fs::file(sfo));
|
||||
const psf::registry psf = psf::load_object(sfo);
|
||||
|
||||
if (sysFileParam)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/Modules/cellGame.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_game.h"
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
@@ -126,6 +127,10 @@ extern s32 sysutil_send_system_cmd(u64 status, u64 param)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (status == CELL_SYSUTIL_REQUEST_EXITGAME)
|
||||
{
|
||||
abort_lv2_watchdog();
|
||||
}
|
||||
|
||||
for (sysutil_cb_manager::registered_cb cb : cbm->callbacks)
|
||||
{
|
||||
|
||||
@@ -228,7 +228,7 @@ error_code cellVideoExportFromFileWithCopy(vm::cptr<char> srcHddDir, vm::cptr<ch
|
||||
|
||||
cellVideoExport.notice("cellVideoExportFromFileWithCopy: param: title=%s, game_title=%s, game_comment=%s, editable=%d", param->title, param->game_title, param->game_comment, param->editable);
|
||||
|
||||
const std::string file_path = fmt::format("%s/%s", srcHddDir, srcHddFile);
|
||||
const std::string file_path = fmt::format("%s/%s", srcHddDir.get_ptr(), srcHddFile.get_ptr());
|
||||
|
||||
if (!check_movie_path(file_path))
|
||||
{
|
||||
@@ -292,7 +292,7 @@ error_code cellVideoExportFromFile(vm::cptr<char> srcHddDir, vm::cptr<char> srcH
|
||||
|
||||
cellVideoExport.notice("cellVideoExportFromFile: param: title=%s, game_title=%s, game_comment=%s, editable=%d", param->title, param->game_title, param->game_comment, param->editable);
|
||||
|
||||
const std::string file_path = fmt::format("%s/%s", srcHddDir, srcHddFile);
|
||||
const std::string file_path = fmt::format("%s/%s", srcHddDir.get_ptr(), srcHddFile.get_ptr());
|
||||
|
||||
if (!check_movie_path(file_path))
|
||||
{
|
||||
|
||||
@@ -290,14 +290,14 @@ public:
|
||||
return access(llvm);
|
||||
}
|
||||
|
||||
u32 func_addr(u32 index) const
|
||||
u32 func_addr(u32 index, bool is_code_addr = false) const
|
||||
{
|
||||
if (index >= access().size() || !addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr + index * 8;
|
||||
return addr + index * 8 + (is_code_addr ? 4 : 0);
|
||||
}
|
||||
|
||||
// Allocation address
|
||||
|
||||
+134
-14
@@ -22,8 +22,10 @@
|
||||
#include "Emu/Cell/Modules/StaticHLE.h"
|
||||
|
||||
#include <map>
|
||||
#include <span>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <shared_mutex>
|
||||
#include "util/asm.hpp"
|
||||
|
||||
LOG_CHANNEL(ppu_loader);
|
||||
@@ -143,15 +145,18 @@ struct ppu_linkage_info
|
||||
};
|
||||
|
||||
// FNID -> (export; [imports...])
|
||||
std::unordered_map<u32, info, value_hash<u32>> functions{};
|
||||
std::unordered_map<u32, info, value_hash<u32>> variables{};
|
||||
std::map<u32, info> functions{};
|
||||
std::map<u32, info> variables{};
|
||||
|
||||
// Obsolete
|
||||
bool imported = false;
|
||||
};
|
||||
|
||||
// Module map
|
||||
std::unordered_map<std::string, module_data> modules{};
|
||||
std::map<std::string, module_data> modules{};
|
||||
std::map<std::string, atomic_t<bool>, std::less<>> lib_lock;
|
||||
shared_mutex lib_lock_mutex;
|
||||
shared_mutex mutex;
|
||||
};
|
||||
|
||||
// Initialize static modules.
|
||||
@@ -275,6 +280,7 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
|
||||
&ppu_module_manager::sys_libc,
|
||||
&ppu_module_manager::sys_lv2dbg,
|
||||
&ppu_module_manager::static_hle,
|
||||
&ppu_module_manager::hle_patches,
|
||||
};
|
||||
|
||||
// Initialize double-purpose fake OPD array for HLE functions
|
||||
@@ -597,6 +603,12 @@ static void ppu_patch_refs(std::vector<ppu_reloc>* out_relocs, u32 fref, u32 fad
|
||||
}
|
||||
}
|
||||
|
||||
enum PRX_EXPORT_ATTRIBUTES : u16
|
||||
{
|
||||
PRX_EXPORT_LIBRARY_FLAG = 1,
|
||||
PRX_EXPORT_PRX_MANAGEMENT_FUNCTIONS_FLAG = 0x8000,
|
||||
};
|
||||
|
||||
// Export or import module struct
|
||||
struct ppu_prx_module_info
|
||||
{
|
||||
@@ -626,16 +638,61 @@ extern u32 ppu_get_exported_func_addr(u32 fnid, const std::string& module_name)
|
||||
return g_fxo->get<ppu_linkage_info>().modules[module_name].functions[fnid].export_addr;
|
||||
}
|
||||
|
||||
extern bool ppu_register_library_lock(std::string_view libname, bool lock_lib)
|
||||
{
|
||||
auto link = g_fxo->try_get<ppu_linkage_info>();
|
||||
|
||||
if (!link || libname.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
reader_lock lock(link->lib_lock_mutex);
|
||||
|
||||
if (auto it = link->lib_lock.find(libname); it != link->lib_lock.cend())
|
||||
{
|
||||
return lock_lib ? !it->second.test_and_set() : it->second.test_and_reset();
|
||||
}
|
||||
|
||||
if (!lock_lib)
|
||||
{
|
||||
// If lock hasn't been installed it wasn't locked in the first place
|
||||
return false;
|
||||
}
|
||||
|
||||
lock.upgrade();
|
||||
|
||||
auto& lib_lock = link->lib_lock.emplace(std::string{libname}, false).first->second;
|
||||
|
||||
return !lib_lock.test_and_set();
|
||||
}
|
||||
|
||||
// Load and register exports; return special exports found (nameless module)
|
||||
static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 exports_end)
|
||||
static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 exports_end, bool for_observing_callbacks = false, std::basic_string<bool>* loaded_flags = nullptr)
|
||||
{
|
||||
std::unordered_map<u32, u32> result;
|
||||
|
||||
for (u32 addr = exports_start; addr < exports_end;)
|
||||
{
|
||||
const auto& lib = vm::_ref<const ppu_prx_module_info>(addr);
|
||||
// Flags were already provided meaning it's an unload operation
|
||||
const bool unload_exports = loaded_flags && !loaded_flags->empty();
|
||||
|
||||
if (!lib.name)
|
||||
std::lock_guard lock(link->mutex);
|
||||
|
||||
usz unload_index = 0;
|
||||
|
||||
for (u32 addr = exports_start; addr < exports_end; unload_index++)
|
||||
{
|
||||
ppu_prx_module_info lib{};
|
||||
std::memcpy(&lib, vm::base(addr), sizeof(lib));
|
||||
|
||||
const bool is_library = !!(lib.attributes & PRX_EXPORT_LIBRARY_FLAG);
|
||||
const bool is_management = !is_library && !!(lib.attributes & PRX_EXPORT_PRX_MANAGEMENT_FUNCTIONS_FLAG);
|
||||
|
||||
if (loaded_flags && !unload_exports)
|
||||
{
|
||||
loaded_flags->push_back(false);
|
||||
}
|
||||
|
||||
if (is_management)
|
||||
{
|
||||
// Set special exports
|
||||
for (u32 i = 0, end = lib.num_func + lib.num_var; i < end; i++)
|
||||
@@ -659,15 +716,53 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_library)
|
||||
{
|
||||
// Skipped if none of the flags is set
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (for_observing_callbacks)
|
||||
{
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string module_name(lib.name.get_ptr());
|
||||
|
||||
ppu_loader.notice("** Exported module '%s' (0x%x, 0x%x, 0x%x, 0x%x)", module_name, lib.vnids, lib.vstubs, lib.unk4, lib.unk5);
|
||||
if (unload_exports)
|
||||
{
|
||||
if (::at32(*loaded_flags, unload_index))
|
||||
{
|
||||
ppu_register_library_lock(module_name, false);
|
||||
}
|
||||
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
ppu_loader.notice("** Exported module '%s' (vnids=0x%x, vstubs=0x%x, version=0x%x, attributes=0x%x, unk4=0x%x, unk5=0x%x)", module_name, lib.vnids, lib.vstubs, lib.version, lib.attributes, lib.unk4, lib.unk5);
|
||||
|
||||
if (lib.num_tlsvar)
|
||||
{
|
||||
ppu_loader.fatal("Unexpected num_tlsvar (%u)!", lib.num_tlsvar);
|
||||
}
|
||||
|
||||
const bool should_load = ppu_register_library_lock(module_name, true);
|
||||
|
||||
if (loaded_flags)
|
||||
{
|
||||
loaded_flags->back() = should_load;
|
||||
}
|
||||
|
||||
if (!should_load)
|
||||
{
|
||||
ppu_loader.notice("** Skipped module '%s' (already loaded)", module_name);
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Static module
|
||||
const auto _sm = ppu_module_manager::get_module(module_name);
|
||||
|
||||
@@ -694,7 +789,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
|
||||
if (flink.export_addr)
|
||||
{
|
||||
ppu_loader.error("Already linked function '%s' in module '%s'", ppu_get_function_name(module_name, fnid), module_name);
|
||||
ppu_loader.notice("Already linked function '%s' in module '%s'", ppu_get_function_name(module_name, fnid), module_name);
|
||||
}
|
||||
//else
|
||||
{
|
||||
@@ -704,7 +799,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
if (_sf && (_sf->flags & MFF_FORCED_HLE))
|
||||
{
|
||||
// Inject a branch to the HLE implementation
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(_sf->index) + 4;
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(_sf->index, true);
|
||||
|
||||
// Set exported function
|
||||
flink.export_addr = target - 4;
|
||||
@@ -777,6 +872,8 @@ static auto ppu_load_imports(std::vector<ppu_reloc>& relocs, ppu_linkage_info* l
|
||||
{
|
||||
std::unordered_map<u32, void*> result;
|
||||
|
||||
reader_lock lock(link->mutex);
|
||||
|
||||
for (u32 addr = imports_start; addr < imports_end;)
|
||||
{
|
||||
const auto& lib = vm::_ref<const ppu_prx_module_info>(addr);
|
||||
@@ -861,12 +958,18 @@ static auto ppu_load_imports(std::vector<ppu_reloc>& relocs, ppu_linkage_info* l
|
||||
}
|
||||
|
||||
// For _sys_prx_register_module
|
||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size)
|
||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<bool>& loaded_flags)
|
||||
{
|
||||
auto& _main = g_fxo->get<ppu_module>();
|
||||
auto& link = g_fxo->get<ppu_linkage_info>();
|
||||
|
||||
ppu_load_exports(&link, exports_start, exports_start + exports_size);
|
||||
ppu_load_exports(&link, exports_start, exports_start + exports_size, false, &loaded_flags);
|
||||
|
||||
if (!imports_size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ppu_load_imports(_main.relocs, &link, imports_start, imports_start + imports_size);
|
||||
}
|
||||
|
||||
@@ -1413,10 +1516,13 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||
prx->module_info_version[0] = lib_info->version[0];
|
||||
prx->module_info_version[1] = lib_info->version[1];
|
||||
prx->module_info_attributes = lib_info->attributes;
|
||||
|
||||
prx->exports_start = lib_info->exports_start;
|
||||
prx->exports_end = lib_info->exports_end;
|
||||
|
||||
ppu_loader.warning("Library %s (rtoc=0x%x):", lib_name, lib_info->toc);
|
||||
|
||||
prx->specials = ppu_load_exports(&link, lib_info->exports_start, lib_info->exports_end);
|
||||
prx->specials = ppu_load_exports(&link, prx->exports_start, prx->exports_end, true);
|
||||
prx->imports = ppu_load_imports(prx->relocs, &link, lib_info->imports_start, lib_info->imports_end);
|
||||
std::stable_sort(prx->relocs.begin(), prx->relocs.end());
|
||||
toc = lib_info->toc;
|
||||
@@ -1498,9 +1604,16 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||
|
||||
void ppu_unload_prx(const lv2_prx& prx)
|
||||
{
|
||||
std::unique_lock lock(g_fxo->get<ppu_linkage_info>().mutex, std::defer_lock);
|
||||
|
||||
// Clean linkage info
|
||||
for (auto& imp : prx.imports)
|
||||
{
|
||||
if (!lock)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
auto pinfo = static_cast<ppu_linkage_info::module_data::info*>(imp.second);
|
||||
pinfo->frefss.erase(imp.first);
|
||||
pinfo->imports.erase(imp.first);
|
||||
@@ -1523,6 +1636,11 @@ void ppu_unload_prx(const lv2_prx& prx)
|
||||
// }
|
||||
//}
|
||||
|
||||
if (lock)
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
if (prx.path.ends_with("sys/external/liblv2.sprx"sv))
|
||||
{
|
||||
liblv2_begin = 0;
|
||||
@@ -2037,6 +2155,8 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar)
|
||||
ppu_loader.warning("Loading library: %s", name);
|
||||
|
||||
auto prx = ppu_load_prx(obj, lle_dir + name, 0, nullptr);
|
||||
prx->state = PRX_STATE_STARTED;
|
||||
prx->load_exports();
|
||||
|
||||
if (prx->funcs.empty())
|
||||
{
|
||||
|
||||
@@ -80,9 +80,9 @@ public:
|
||||
std::unordered_map<u32, ppu_static_function, value_hash<u32>> functions{};
|
||||
std::unordered_map<u32, ppu_static_variable, value_hash<u32>> variables{};
|
||||
|
||||
public:
|
||||
ppu_static_module(const char* name);
|
||||
|
||||
public:
|
||||
ppu_static_module(const char* name, void(*init)())
|
||||
: ppu_static_module(name)
|
||||
{
|
||||
@@ -278,6 +278,7 @@ public:
|
||||
static const ppu_static_module sys_libc;
|
||||
static const ppu_static_module sys_lv2dbg;
|
||||
static const ppu_static_module static_hle;
|
||||
static const ppu_static_module hle_patches;
|
||||
|
||||
private:
|
||||
inline static std::unordered_map<std::string, ppu_static_module*> s_module_map;
|
||||
|
||||
+114
-58
@@ -617,34 +617,20 @@ struct ppu_far_jumps_t
|
||||
bool with_toc;
|
||||
std::string module_name;
|
||||
ppu_intrp_func_t func;
|
||||
};
|
||||
|
||||
ppu_far_jumps_t(int) noexcept {}
|
||||
|
||||
std::unordered_map<u32, all_info_t> vals;
|
||||
::jit_runtime rt;
|
||||
|
||||
mutable shared_mutex mutex;
|
||||
|
||||
// Get target address, 'ppu' is used in ppu_far_jump in order to modify registers
|
||||
u32 get_target(const u32 pc, ppu_thread* ppu = nullptr)
|
||||
{
|
||||
reader_lock lock(mutex);
|
||||
|
||||
if (auto it = vals.find(pc); it != vals.end())
|
||||
u32 get_target(u32 pc, ppu_thread* ppu = nullptr) const
|
||||
{
|
||||
all_info_t& all_info = it->second;
|
||||
u32 target = all_info.target;
|
||||
u32 direct_target = this->target;
|
||||
|
||||
bool link = all_info.link;
|
||||
bool from_opd = all_info.with_toc;
|
||||
bool to_link = this->link;
|
||||
bool from_opd = this->with_toc;
|
||||
|
||||
if (!all_info.module_name.empty())
|
||||
if (!this->module_name.empty())
|
||||
{
|
||||
target = ppu_get_exported_func_addr(target, all_info.module_name);
|
||||
direct_target = ppu_get_exported_func_addr(direct_target, this->module_name);
|
||||
}
|
||||
|
||||
if (from_opd && !vm::check_addr<sizeof(ppu_func_opd_t)>(target))
|
||||
if (from_opd && !vm::check_addr<sizeof(ppu_func_opd_t)>(direct_target))
|
||||
{
|
||||
// Avoid reading unmapped memory under mutex
|
||||
from_opd = false;
|
||||
@@ -652,11 +638,11 @@ struct ppu_far_jumps_t
|
||||
|
||||
if (from_opd)
|
||||
{
|
||||
auto& opd = vm::_ref<ppu_func_opd_t>(target);
|
||||
target = opd.addr;
|
||||
auto& opd = vm::_ref<ppu_func_opd_t>(direct_target);
|
||||
direct_target = opd.addr;
|
||||
|
||||
// We modify LR to custom values here
|
||||
link = false;
|
||||
to_link = false;
|
||||
|
||||
if (ppu)
|
||||
{
|
||||
@@ -667,23 +653,74 @@ struct ppu_far_jumps_t
|
||||
// NOTE: In order to clean up this information all calls must return in order
|
||||
auto& saved_info = calls_info.emplace_back();
|
||||
saved_info.cia = pc;
|
||||
saved_info.saved_lr = std::exchange(ppu->lr, FIND_FUNC(ppu_return_from_far_jump));
|
||||
saved_info.saved_lr = std::exchange(ppu->lr, g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(ppu_return_from_far_jump), true));
|
||||
saved_info.saved_r2 = std::exchange(ppu->gpr[2], opd.rtoc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (link && ppu)
|
||||
if (to_link && ppu)
|
||||
{
|
||||
ppu->lr = pc + 4;
|
||||
}
|
||||
|
||||
return target;
|
||||
return direct_target;
|
||||
}
|
||||
};
|
||||
|
||||
ppu_far_jumps_t(int) noexcept {}
|
||||
|
||||
std::map<u32, all_info_t> vals;
|
||||
::jit_runtime rt;
|
||||
|
||||
mutable shared_mutex mutex;
|
||||
|
||||
// Get target address, 'ppu' is used in ppu_far_jump in order to modify registers
|
||||
u32 get_target(u32 pc, ppu_thread* ppu = nullptr)
|
||||
{
|
||||
reader_lock lock(mutex);
|
||||
|
||||
if (auto it = vals.find(pc); it != vals.end())
|
||||
{
|
||||
all_info_t& all_info = it->second;
|
||||
return all_info.get_target(pc, ppu);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get function patches in range (entry -> target)
|
||||
std::vector<std::pair<u32, u32>> get_targets(u32 pc, u32 size)
|
||||
{
|
||||
std::vector<std::pair<u32, u32>> targets;
|
||||
|
||||
reader_lock lock(mutex);
|
||||
|
||||
auto it = vals.lower_bound(pc);
|
||||
|
||||
if (it == vals.end())
|
||||
{
|
||||
return targets;
|
||||
}
|
||||
|
||||
if (it->first >= pc + size)
|
||||
{
|
||||
return targets;
|
||||
}
|
||||
|
||||
for (auto end = vals.lower_bound(pc + size); it != end; it++)
|
||||
{
|
||||
all_info_t& all_info = it->second;
|
||||
|
||||
if (u32 target = all_info.get_target(it->first))
|
||||
{
|
||||
targets.emplace_back(it->first, target);
|
||||
}
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
// Generate a mini-function which updates PC (for LLVM) and jumps to ppu_far_jump to handle redirections
|
||||
template <bool Locked = true>
|
||||
ppu_intrp_func_t gen_jump(u32 pc)
|
||||
{
|
||||
@@ -1019,7 +1056,7 @@ void ppu_thread::dump_regs(std::string& ret) const
|
||||
|
||||
if (const_value != reg)
|
||||
{
|
||||
// Expectation of pretictable code path has not been met (such as a branch directly to the instruction)
|
||||
// Expectation of predictable code path has not been met (such as a branch directly to the instruction)
|
||||
is_const = false;
|
||||
}
|
||||
|
||||
@@ -1243,7 +1280,7 @@ std::vector<std::pair<u32, u32>> ppu_thread::dump_callstack_list() const
|
||||
}
|
||||
|
||||
// Ignore HLE stop address
|
||||
return addr == g_fxo->get<ppu_function_manager>().func_addr(1) + 4;
|
||||
return addr == g_fxo->get<ppu_function_manager>().func_addr(1, true);
|
||||
};
|
||||
|
||||
if (is_invalid(addr))
|
||||
@@ -1921,7 +1958,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc)
|
||||
interrupt_thread_executing = true;
|
||||
cia = addr;
|
||||
gpr[2] = rtoc;
|
||||
lr = g_fxo->get<ppu_function_manager>().func_addr(1) + 4; // HLE stop address
|
||||
lr = g_fxo->get<ppu_function_manager>().func_addr(1, true); // HLE stop address
|
||||
current_function = nullptr;
|
||||
|
||||
if (std::exchange(loaded_from_savestate, false))
|
||||
@@ -1957,7 +1994,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc)
|
||||
|
||||
if (auto name = get_prx_name_by_cia(cia))
|
||||
{
|
||||
return fmt::format("PPU[0x%x] Thread (%s) [%s: 0x%08x]", _this->id, *name_cache.get(), name, cia);
|
||||
return fmt::format("PPU[0x%x] Thread (%s) [%s: 0x%08x]", _this->id, *name_cache.get(), name, cia);
|
||||
}
|
||||
|
||||
return fmt::format("PPU[0x%x] Thread (%s) [0x%08x]", _this->id, *name_cache.get(), cia);
|
||||
@@ -2769,6 +2806,11 @@ namespace
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||
{
|
||||
return m_file.read_at(offset + m_off, buffer, size);
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
@@ -2807,36 +2849,32 @@ extern fs::file make_file_view(fs::file&& _file, u64 offset)
|
||||
|
||||
extern void ppu_finalize(const ppu_module& info)
|
||||
{
|
||||
// Get cache path for this executable
|
||||
std::string cache_path;
|
||||
|
||||
if (info.name.empty())
|
||||
{
|
||||
// Don't remove main module from memory
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
const std::string dev_flash = vfs::get("/dev_flash/sys/");
|
||||
|
||||
if (info.path.starts_with(dev_flash) || Emu.GetCat() == "1P")
|
||||
{
|
||||
// Get PPU cache location
|
||||
cache_path = fs::get_cache_dir() + "cache/";
|
||||
|
||||
const std::string dev_flash = vfs::get("/dev_flash/sys/");
|
||||
|
||||
if (info.path.starts_with(dev_flash) || Emu.GetCat() == "1P")
|
||||
{
|
||||
// Don't remove dev_flash prx from memory
|
||||
return;
|
||||
}
|
||||
else if (!Emu.GetTitleID().empty())
|
||||
{
|
||||
cache_path += Emu.GetTitleID();
|
||||
cache_path += '/';
|
||||
}
|
||||
|
||||
// Add PPU hash and filename
|
||||
fmt::append(cache_path, "ppu-%s-%s/", fmt::base57(info.sha1), info.path.substr(info.path.find_last_of('/') + 1));
|
||||
// Don't remove dev_flash prx from memory
|
||||
return;
|
||||
}
|
||||
|
||||
// Get cache path for this executable
|
||||
std::string cache_path = fs::get_cache_dir() + "cache/";
|
||||
|
||||
if (!Emu.GetTitleID().empty())
|
||||
{
|
||||
cache_path += Emu.GetTitleID();
|
||||
cache_path += '/';
|
||||
}
|
||||
|
||||
// Add PPU hash and filename
|
||||
fmt::append(cache_path, "ppu-%s-%s/", fmt::base57(info.sha1), info.path.substr(info.path.find_last_of('/') + 1));
|
||||
|
||||
#ifdef LLVM_AVAILABLE
|
||||
g_fxo->get<jit_module_manager>().remove(cache_path + info.name);
|
||||
#endif
|
||||
@@ -3192,6 +3230,13 @@ extern void ppu_initialize()
|
||||
if (ptr->path.starts_with(firmware_sprx_path))
|
||||
{
|
||||
compile_fw |= ppu_initialize(*ptr, true);
|
||||
|
||||
// Fixup for compatibility with old savestates
|
||||
if (Emu.DeserialManager() && ptr->name == "liblv2.sprx")
|
||||
{
|
||||
static_cast<lv2_prx*>(ptr)->state = PRX_STATE_STARTED;
|
||||
static_cast<lv2_prx*>(ptr)->load_exports();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3475,14 +3520,25 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
|
||||
}
|
||||
}
|
||||
|
||||
if (jit)
|
||||
if (g_fxo->is_init<ppu_far_jumps_t>())
|
||||
{
|
||||
const auto far_jump = ppu_get_far_jump(func.addr) ? g_fxo->get<ppu_far_jumps_t>().gen_jump(func.addr) : nullptr;
|
||||
auto targets = g_fxo->get<ppu_far_jumps_t>().get_targets(func.addr, func.size);
|
||||
|
||||
if (far_jump)
|
||||
for (auto [source, target] : targets)
|
||||
{
|
||||
auto far_jump = ensure(g_fxo->get<ppu_far_jumps_t>().gen_jump(source));
|
||||
|
||||
if (source == func.addr && jit)
|
||||
{
|
||||
jit->update_global_mapping(fmt::format("__0x%x", func.addr - reloc), reinterpret_cast<u64>(far_jump));
|
||||
}
|
||||
|
||||
ppu_register_function_at(source, 4, far_jump);
|
||||
}
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
// Replace the function with ppu_far_jump
|
||||
jit->update_global_mapping(fmt::format("__0x%x", func.addr - reloc), reinterpret_cast<u64>(far_jump));
|
||||
fpos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_sysc
|
||||
BIND_SYSC(_sys_game_watchdog_clear), //374 (0x176)
|
||||
NULL_FUNC(sys_game_set_system_sw_version), //375 (0x177) ROOT
|
||||
BIND_SYSC(_sys_game_get_system_sw_version), //376 (0x178) ROOT
|
||||
NULL_FUNC(sys_sm_set_shop_mode), //377 (0x179) ROOT
|
||||
BIND_SYSC(sys_sm_set_shop_mode), //377 (0x179) ROOT
|
||||
BIND_SYSC(sys_sm_get_ext_event2), //378 (0x17A) ROOT
|
||||
BIND_SYSC(sys_sm_shutdown), //379 (0x17B) ROOT
|
||||
BIND_SYSC(sys_sm_get_params), //380 (0x17C) DBG
|
||||
|
||||
+311
-129
@@ -20,17 +20,48 @@
|
||||
|
||||
LOG_CHANNEL(sys_fs);
|
||||
|
||||
lv2_fs_mount_point g_mp_sys_dev_root;
|
||||
lv2_fs_mount_point g_mp_sys_no_device;
|
||||
lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0", 512, 0x24FAEA98};
|
||||
lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", 512, 0x3FFFF8, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache};
|
||||
lv2_fs_mount_point g_mp_sys_dev_usb{"", 512, 0x100, 4096, lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_bdvd{"", 2048, 0x4D955, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_dvd{"", 2048, 0x100, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_host_root{"", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash{"", 512, 0x63E00, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash2{"", 512, 0x8000, 8192, lv2_mp_flag::no_uid_gid}; // TODO confirm
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash3{"", 512, 0x400, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; // TODO confirm
|
||||
lv2_fs_mount_point g_mp_sys_dev_usb{"/dev_usb", "CELL_FS_FAT", "CELL_FS_IOS:USB_MASS_STORAGE", 512, 0x100, 4096, lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_dvd{"/dev_ps2disc", "CELL_FS_ISO9660", "CELL_FS_IOS:PATA1_BDVD_DRIVE", 2048, 0x100, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_usb};
|
||||
lv2_fs_mount_point g_mp_sys_dev_bdvd{"/dev_bdvd", "CELL_FS_ISO9660", "CELL_FS_IOS:PATA0_BDVD_DRIVE", 2048, 0x4D955, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_dvd};
|
||||
lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", "CELL_FS_FAT", "CELL_FS_UTILITY:HDD1", 512, 0x3FFFF8, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache, &g_mp_sys_dev_bdvd};
|
||||
lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0", "CELL_FS_UFS", "CELL_FS_UTILITY:HDD0", 512, 0x24FAEA98, 4096, {}, &g_mp_sys_dev_hdd1};
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash3{"/dev_flash3", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH3", 512, 0x400, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_hdd0}; // TODO confirm
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash2{"/dev_flash2", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH2", 512, 0x8000, 8192, lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_flash3}; // TODO confirm
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash{"/dev_flash", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH1", 512, 0x63E00, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_flash2};
|
||||
lv2_fs_mount_point g_mp_sys_host_root{"/host_root", "CELL_FS_DUMMYFS", "CELL_FS_DUMMY:/", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid, &g_mp_sys_dev_flash};
|
||||
lv2_fs_mount_point g_mp_sys_app_home{"/app_home", "CELL_FS_DUMMYFS", "CELL_FS_DUMMY:", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid, &g_mp_sys_host_root};
|
||||
lv2_fs_mount_point g_mp_sys_dev_root{"/", "CELL_FS_ADMINFS", "CELL_FS_ADMINFS:", 512, 0x100, 512, lv2_mp_flag::read_only + lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid, &g_mp_sys_app_home};
|
||||
lv2_fs_mount_point g_mp_sys_no_device{};
|
||||
|
||||
struct mount_point_reset
|
||||
{
|
||||
SAVESTATE_INIT_POS(49);
|
||||
|
||||
mount_point_reset() = default;
|
||||
|
||||
mount_point_reset(const mount_point_reset&) = delete;
|
||||
|
||||
mount_point_reset& operator =(const mount_point_reset&) = delete;
|
||||
|
||||
~mount_point_reset()
|
||||
{
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
lv2_fs_object::vfs_unmount(fmt::format("%s%03d", mp->root, i), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lv2_fs_object::vfs_unmount(mp->root, true);
|
||||
}
|
||||
}
|
||||
g_fxo->get<mount_point_reset>(); // Register destructor
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void fmt_class_string<lv2_file_type>::format(std::string& out, u64 arg)
|
||||
@@ -174,76 +205,135 @@ std::string_view lv2_fs_object::get_device_path(std::string_view filename)
|
||||
return mp_name;
|
||||
}
|
||||
|
||||
lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename)
|
||||
lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename, std::string* vfs_path)
|
||||
{
|
||||
auto result = &g_mp_sys_no_device; // Default fallback
|
||||
const auto mp_name = get_device_path(filename);
|
||||
|
||||
if (!mp_name.empty())
|
||||
if (filename.starts_with('/'))
|
||||
{
|
||||
if (mp_name == "dev_hdd0"sv)
|
||||
return &g_mp_sys_dev_hdd0;
|
||||
if (mp_name == "dev_hdd1"sv)
|
||||
return &g_mp_sys_dev_hdd1;
|
||||
if (mp_name.starts_with("dev_usb"sv))
|
||||
return &g_mp_sys_dev_usb;
|
||||
if (mp_name == "dev_bdvd"sv)
|
||||
return &g_mp_sys_dev_bdvd;
|
||||
if (mp_name == "dev_ps2disc"sv)
|
||||
return &g_mp_sys_dev_dvd;
|
||||
if (mp_name == "app_home"sv && filename.data() != Emu.argv[0].data())
|
||||
return lv2_fs_object::get_mp(Emu.argv[0]);
|
||||
if (mp_name == "host_root"sv)
|
||||
return &g_mp_sys_host_root;
|
||||
if (mp_name == "dev_flash"sv)
|
||||
return &g_mp_sys_dev_flash;
|
||||
if (mp_name == "dev_flash2"sv)
|
||||
return &g_mp_sys_dev_flash2;
|
||||
if (mp_name == "dev_flash3"sv)
|
||||
return &g_mp_sys_dev_flash3;
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
const auto pos = mp->root.find_first_not_of('/');
|
||||
const auto mp_root = pos != umax ? mp->root.substr(pos) : mp->root;
|
||||
|
||||
// Default
|
||||
return &g_mp_sys_dev_hdd0;
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (fmt::format("%s%03d", mp_root, i) == mp_name)
|
||||
{
|
||||
result = mp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp_root == mp_name)
|
||||
{
|
||||
result = mp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default fallback
|
||||
return &g_mp_sys_dev_root;
|
||||
if (vfs_path)
|
||||
{
|
||||
if (result == &g_mp_sys_dev_hdd0)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir());
|
||||
else if (result == &g_mp_sys_dev_hdd1)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, rpcs3::utils::get_emu_dir());
|
||||
else if (result == &g_mp_sys_dev_usb)
|
||||
*vfs_path = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, fmt::format("/%s", mp_name), rpcs3::utils::get_emu_dir()).path;
|
||||
else if (result == &g_mp_sys_dev_bdvd)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, rpcs3::utils::get_emu_dir());
|
||||
else if (result == &g_mp_sys_dev_dvd)
|
||||
*vfs_path = {}; // Unsupported in VFS
|
||||
else if (result == &g_mp_sys_app_home)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.app_home, rpcs3::utils::get_emu_dir());
|
||||
else if (result == &g_mp_sys_host_root)
|
||||
*vfs_path = g_cfg.vfs.host_root ? "/" : std::string();
|
||||
else if (result == &g_mp_sys_dev_flash)
|
||||
*vfs_path = g_cfg_vfs.get_dev_flash();
|
||||
else if (result == &g_mp_sys_dev_flash2)
|
||||
*vfs_path = g_cfg_vfs.get_dev_flash2();
|
||||
else if (result == &g_mp_sys_dev_flash3)
|
||||
*vfs_path = g_cfg_vfs.get_dev_flash3();
|
||||
else
|
||||
*vfs_path = {};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string lv2_fs_object::get_vfs(std::string_view filename)
|
||||
std::string lv2_fs_object::device_name_to_path(std::string_view device_name)
|
||||
{
|
||||
const auto mp_name = get_device_path(filename);
|
||||
|
||||
if (!mp_name.empty())
|
||||
auto hdd_check = [&](lv2_fs_mount_point* mp)
|
||||
{
|
||||
if (mp_name == "dev_hdd0"sv)
|
||||
return g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir());
|
||||
if (mp_name == "dev_hdd1"sv)
|
||||
return g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, rpcs3::utils::get_emu_dir());
|
||||
if (mp_name.starts_with("dev_usb"sv))
|
||||
return g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, fmt::format("/%s", mp_name), rpcs3::utils::get_emu_dir()).path;
|
||||
if (mp_name == "dev_bdvd"sv)
|
||||
return g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, rpcs3::utils::get_emu_dir());
|
||||
if (mp_name == "dev_ps2disc"sv)
|
||||
return {}; // Unsupported in VFS
|
||||
if (mp_name == "app_home"sv && filename.data() != Emu.argv[0].data())
|
||||
return lv2_fs_object::get_vfs(Emu.argv[0]);
|
||||
if (mp_name == "host_root"sv)
|
||||
return g_cfg.vfs.host_root ? "/" : std::string();
|
||||
if (mp_name == "dev_flash"sv)
|
||||
return g_cfg_vfs.get_dev_flash();
|
||||
if (mp_name == "dev_flash2"sv)
|
||||
return g_cfg_vfs.get_dev_flash2();
|
||||
if (mp_name == "dev_flash3"sv)
|
||||
return g_cfg_vfs.get_dev_flash3();
|
||||
if (mp == &g_mp_sys_dev_hdd0 && device_name == "CELL_FS_IOS:PATA0_HDD_DRIVE"sv)
|
||||
return true;
|
||||
else if (mp == &g_mp_sys_dev_hdd1 && device_name == "CELL_FS_IOS:PATA1_HDD_DRIVE"sv)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
// Default
|
||||
return g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir());
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (fmt::format("%s%03d", mp->device, i) == device_name)
|
||||
{
|
||||
return fmt::format("%s%03d", mp->root, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mp->device == device_name || hdd_check(mp))
|
||||
{
|
||||
return std::string(mp->root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default fallback
|
||||
return {};
|
||||
}
|
||||
|
||||
bool lv2_fs_object::vfs_unmount(std::string_view vpath, bool no_error)
|
||||
{
|
||||
const std::string local_path = vfs::get(vpath);
|
||||
|
||||
if (local_path.empty())
|
||||
{
|
||||
if (no_error)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_fs.error("\"%s\" is not mounted!", vpath);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fs::is_file(local_path))
|
||||
{
|
||||
if (fs::remove_file(local_path))
|
||||
{
|
||||
sys_fs.notice("Removed loop file \"%s\"", local_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_fs.error("Failed to remove loop file \"%s\"", local_path);
|
||||
}
|
||||
}
|
||||
|
||||
return vfs::unmount(vpath);
|
||||
}
|
||||
|
||||
lv2_fs_object::lv2_fs_object(utils::serial& ar, bool)
|
||||
: name(ar)
|
||||
, mp(get_mp(name.data()))
|
||||
@@ -489,6 +579,11 @@ struct lv2_file::file_view : fs::file_base
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||
{
|
||||
return m_file->file.read_at(offset, buffer, size);
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
@@ -866,7 +961,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
return not_an_error(CELL_EEXIST);
|
||||
}
|
||||
|
||||
return {error, path};
|
||||
return {lv2_fs_object::get_mp(vpath) == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, error, path};
|
||||
}
|
||||
|
||||
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([&ppath = ppath, &file = file, mode, flags, &real = real, &type = type]() -> std::shared_ptr<lv2_file>
|
||||
@@ -1167,7 +1262,7 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
||||
{
|
||||
if (ext.empty())
|
||||
{
|
||||
return {CELL_ENOENT, path};
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1356,7 +1451,7 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
|
||||
break;
|
||||
}
|
||||
|
||||
return {CELL_ENOENT, path};
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -1484,8 +1579,14 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
||||
{
|
||||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
case fs::error::exist: return {CELL_EEXIST, path};
|
||||
case fs::error::noent:
|
||||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
case fs::error::exist:
|
||||
{
|
||||
return {sys_fs.warning, CELL_EEXIST, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_mkdir(): unknown error %s", error);
|
||||
}
|
||||
|
||||
@@ -1658,7 +1759,10 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
|
||||
{
|
||||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
case fs::error::noent:
|
||||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_unlink(): unknown error %s", error);
|
||||
}
|
||||
|
||||
@@ -2281,7 +2385,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||
strcpy_trunc(entry.entry_name.d_name, info->name);
|
||||
}
|
||||
|
||||
// Apparently all this function does to additional buffer elements is to zeroize them
|
||||
// Apparently all this function does to additional buffer elements is to zeroize them
|
||||
std::memset(arg_ptr.get_ptr() + read_count, 0, (max - read_count) * arg->ptr.size());
|
||||
}
|
||||
|
||||
@@ -2611,7 +2715,10 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
||||
{
|
||||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
case fs::error::noent:
|
||||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_truncate(): unknown error %s", error);
|
||||
}
|
||||
|
||||
@@ -2811,7 +2918,10 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUti
|
||||
{
|
||||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
case fs::error::noent:
|
||||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_utime(): unknown error %s", error);
|
||||
}
|
||||
|
||||
@@ -2932,81 +3042,159 @@ error_code sys_fs_truncate2(ppu_thread&, u32 fd, u64 size)
|
||||
|
||||
error_code sys_fs_get_mount_info_size(ppu_thread&, vm::ptr<u64> len)
|
||||
{
|
||||
sys_fs.todo("sys_fs_get_mount_info_size(len=*0x%x)", len);
|
||||
sys_fs.trace("sys_fs_get_mount_info_size(len=*0x%x)", len);
|
||||
|
||||
if (!len)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
*len = 0x9;
|
||||
u64 count = 0;
|
||||
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!vfs::get(fmt::format("%s%03d", mp->root, i)).empty())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp == &g_mp_sys_dev_root || !vfs::get(mp->root).empty())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*len = count;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u32 len, vm::ptr<u64> out_len)
|
||||
error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u64 len, vm::ptr<u64> out_len)
|
||||
{
|
||||
sys_fs.todo("sys_fs_get_mount_info(info=*0x%x, len=0x%x, out_len=*0x%x)", info, len, out_len);
|
||||
sys_fs.trace("sys_fs_get_mount_info(info=*0x%x, len=0x%x, out_len=*0x%x)", info, len, out_len);
|
||||
|
||||
if (!out_len)
|
||||
if (!info || !out_len)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
// TODO there is a case where 'something' happens if !info or len == 0
|
||||
if (!info || len == 0)
|
||||
{
|
||||
sys_fs.todo("sys_fs_get_mount_info special case TODO");
|
||||
}
|
||||
|
||||
const u32 max_len = std::min<u32>(len, 9);
|
||||
*out_len = max_len;
|
||||
|
||||
struct mount_info
|
||||
{
|
||||
std::string_view path, filesystem, dev_name;
|
||||
be_t<u32> unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0;
|
||||
const std::string_view path, filesystem, dev_name;
|
||||
const be_t<u32> unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0;
|
||||
};
|
||||
|
||||
static constexpr std::array<mount_info, 9> data
|
||||
u64 count = 0;
|
||||
|
||||
auto push_info = [&](mount_info&& data)
|
||||
{
|
||||
mount_info{.path = "/", .filesystem = "CELL_FS_ADMINFS", .dev_name = "CELL_FS_ADMINFS:", .unk5 = 0x10000000},
|
||||
mount_info{.path = "/app_home", .filesystem = "CELL_FS_DUMMY", .dev_name = "CELL_FS_DUMMY:"},
|
||||
mount_info{.path = "/host_root", .filesystem = "CELL_FS_DUMMY", .dev_name = "CELL_FS_DUMMY:"},
|
||||
mount_info{.path = "/dev_flash", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH1:", .unk5 = 0x10000000},
|
||||
mount_info{.path = "/dev_flash2", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH2:"},
|
||||
mount_info{.path = "/dev_flash3", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH3:"},
|
||||
mount_info{.path = "/dev_hdd0", .filesystem = "CELL_FS_UFS", .dev_name = "CELL_FS_UTILITY:HDD0:"},
|
||||
mount_info{.path = "/dev_hdd1", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_UTILITY:HDD1:"},
|
||||
mount_info{.path = "/dev_bdvd", .filesystem = "CELL_FS_ISO9660", .dev_name = "CELL_FS_IOS:PATA0_BDVD_DRIVE"},
|
||||
if (count >= len)
|
||||
return;
|
||||
|
||||
strcpy_trunc(info->mount_path, data.path);
|
||||
strcpy_trunc(info->filesystem, data.filesystem);
|
||||
strcpy_trunc(info->dev_name, data.dev_name);
|
||||
std::memcpy(&info->unk1, &data.unk1, sizeof(be_t<u32>) * 5);
|
||||
|
||||
info++, count++;
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < max_len; info++, i++)
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
strcpy_trunc(info->mount_path, data[i].path);
|
||||
strcpy_trunc(info->filesystem, data[i].filesystem);
|
||||
strcpy_trunc(info->dev_name, data[i].dev_name);
|
||||
std::memcpy(&info->unk1, &data[i].unk1, sizeof(be_t<u32>) * 5);
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!vfs::get(fmt::format("%s%03d", mp->root, i)).empty())
|
||||
{
|
||||
push_info(mount_info{.path = fmt::format("%s%03d", mp->root, i), .filesystem = mp->file_system, .dev_name = fmt::format("%s%03d", mp->device, i)});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp == &g_mp_sys_dev_root || !vfs::get(mp->root).empty())
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_root || mp == &g_mp_sys_dev_flash)
|
||||
{
|
||||
push_info(mount_info{.path = mp->root, .filesystem = mp->file_system, .dev_name = mp->device, .unk5 = 0x10000000});
|
||||
}
|
||||
else
|
||||
{
|
||||
push_info(mount_info{.path = mp->root, .filesystem = mp->file_system, .dev_name = mp->device});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = count;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_fs_newfs(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1)
|
||||
error_code sys_fs_newfs(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1)
|
||||
{
|
||||
sys_fs.todo("sys_fs_newfs(dev_name=%s, file_system=%s, unk1=0x%x, str1=%s)", dev_name, file_system, unk1, str1);
|
||||
sys_fs.trace("sys_fs_newfs(dev_name=%s, file_system=%s, unk1=0x%x, str1=%s)", dev_name, file_system, unk1, str1);
|
||||
|
||||
if (!g_ps3_process_info.has_root_perm())
|
||||
{
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
const auto [dev_error, device_name] = translate_to_sv(dev_name, false);
|
||||
|
||||
if (dev_error)
|
||||
{
|
||||
return { dev_error, device_name };
|
||||
}
|
||||
|
||||
const auto device_path = lv2_fs_object::device_name_to_path(device_name);
|
||||
|
||||
if (!vfs::get(device_path).empty())
|
||||
{
|
||||
sys_fs.error("sys_fs_newfs(): %s is not unmounted!", device_path);
|
||||
return CELL_EABORT;
|
||||
}
|
||||
|
||||
std::string vfs_path;
|
||||
const auto mp = lv2_fs_object::get_mp(device_path, &vfs_path);
|
||||
bool success = true;
|
||||
|
||||
auto vfs_newfs = [&](const std::string& path)
|
||||
{
|
||||
if (!path.empty() && fs::remove_all(path, false))
|
||||
{
|
||||
sys_fs.success("sys_fs_newfs(): Successfully cleared \"%s\" at \"%s\"", device_path, path);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_fs.error("sys_fs_newfs(): Failed to clear \"%s\" at \"%s\"", device_path, path);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (mp == &g_mp_sys_dev_hdd1)
|
||||
{
|
||||
const std::string_view appname = g_ps3_process_info.get_cellos_appname();
|
||||
success = vfs_newfs(fmt::format("%s/caches/%s", vfs_path, appname.substr(0, appname.find_last_of('.'))));
|
||||
}
|
||||
else
|
||||
{
|
||||
//success = vfs_newfs(vfs_path); // We are not supporting formatting devices other than /dev_hdd1 via this syscall currently
|
||||
}
|
||||
|
||||
if (!success)
|
||||
return CELL_EIO;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> file_system, vm::cptr<char> path, s32 unk1, s32 prot, s32 unk3, vm::cptr<char> str1, u32 str_len)
|
||||
{
|
||||
sys_fs.warning("sys_fs_mount(dev_name=%s, file_system=%s, path=%s, unk1=0x%x, prot=0x%x, unk3=0x%x, str1=%s, str_len=%d)", dev_name, file_system, path, unk1, prot, unk3, str1, str_len);
|
||||
sys_fs.trace("sys_fs_mount(dev_name=%s, file_system=%s, path=%s, unk1=0x%x, prot=0x%x, unk3=0x%x, str1=%s, str_len=%d)", dev_name, file_system, path, unk1, prot, unk3, str1, str_len);
|
||||
|
||||
if (!g_ps3_process_info.has_root_perm())
|
||||
{
|
||||
@@ -3027,11 +3215,23 @@ error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> fil
|
||||
return { fs_error, filesystem };
|
||||
}
|
||||
|
||||
const auto mp = lv2_fs_object::get_mp(vpath);
|
||||
std::string vfs_path;
|
||||
const auto mp = lv2_fs_object::get_mp(vpath, &vfs_path);
|
||||
bool success = true;
|
||||
|
||||
auto vfs_mount = [&vpath = vpath, &filesystem = filesystem, &mp = mp](std::string mount_path)
|
||||
{
|
||||
const std::string local_path = vfs::get(vpath);
|
||||
if (!local_path.empty())
|
||||
{
|
||||
sys_fs.error("\"%s\" has already been mounted to \"%s\"", vpath, local_path);
|
||||
return false;
|
||||
}
|
||||
if (mount_path.empty())
|
||||
{
|
||||
sys_fs.error("Failed to resolve VFS path for \"%s\"", vpath);
|
||||
return false;
|
||||
}
|
||||
if (!mount_path.ends_with('/'))
|
||||
mount_path += '/';
|
||||
if (!fs::is_dir(mount_path) && !fs::create_dir(mount_path))
|
||||
@@ -3062,11 +3262,11 @@ error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> fil
|
||||
if (mp == &g_mp_sys_dev_hdd1)
|
||||
{
|
||||
const std::string_view appname = g_ps3_process_info.get_cellos_appname();
|
||||
success = vfs_mount(fmt::format("%s/caches/%s", lv2_fs_object::get_vfs(vpath), appname.substr(0, appname.find_last_of('.'))));
|
||||
success = vfs_mount(fmt::format("%s/caches/%s", vfs_path, appname.substr(0, appname.find_last_of('.'))));
|
||||
}
|
||||
else
|
||||
{
|
||||
//success = vfs_mount(lv2_fs_object::get_vfs(vpath)); // We are not supporting mounting devices other than /dev_hdd1 via this syscall currently
|
||||
//success = vfs_mount(vfs_path); // We are not supporting mounting devices other than /dev_hdd1 via this syscall currently
|
||||
}
|
||||
|
||||
if (!success)
|
||||
@@ -3077,7 +3277,7 @@ error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> fil
|
||||
|
||||
error_code sys_fs_unmount(ppu_thread&, vm::cptr<char> path, s32 unk1, s32 unk2)
|
||||
{
|
||||
sys_fs.warning("sys_fs_unmount(path=%s, unk1=0x%x, unk2=0x%x)", path, unk1, unk2);
|
||||
sys_fs.trace("sys_fs_unmount(path=%s, unk1=0x%x, unk2=0x%x)", path, unk1, unk2);
|
||||
|
||||
if (!g_ps3_process_info.has_root_perm())
|
||||
{
|
||||
@@ -3094,26 +3294,8 @@ error_code sys_fs_unmount(ppu_thread&, vm::cptr<char> path, s32 unk1, s32 unk2)
|
||||
const auto mp = lv2_fs_object::get_mp(vpath);
|
||||
bool success = true;
|
||||
|
||||
auto vfs_unmount = [&vpath = vpath]()
|
||||
{
|
||||
const std::string local_path = vfs::get(vpath);
|
||||
if (fs::is_file(local_path))
|
||||
{
|
||||
if (fs::remove_file(local_path))
|
||||
{
|
||||
sys_fs.notice("Removed loop file \"%s\"", local_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_fs.error("Failed to remove loop file \"%s\"", local_path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return vfs::unmount(vpath);
|
||||
};
|
||||
|
||||
if (mp == &g_mp_sys_dev_hdd1) // We are not supporting unmounting devices other than /dev_hdd1 via this syscall currently
|
||||
success = vfs_unmount();
|
||||
success = lv2_fs_object::vfs_unmount(vpath);
|
||||
|
||||
if (!success)
|
||||
return CELL_EIO;
|
||||
|
||||
@@ -148,16 +148,18 @@ enum class lv2_file_type
|
||||
struct lv2_fs_mount_point
|
||||
{
|
||||
const std::string_view root;
|
||||
const std::string_view file_system;
|
||||
const std::string_view device;
|
||||
const u32 sector_size = 512;
|
||||
const u64 sector_count = 256;
|
||||
const u32 block_size = 4096;
|
||||
const bs_t<lv2_mp_flag> flags{};
|
||||
lv2_fs_mount_point* const next = nullptr;
|
||||
|
||||
mutable std::recursive_mutex mutex;
|
||||
};
|
||||
|
||||
extern lv2_fs_mount_point g_mp_sys_dev_hdd0;
|
||||
extern lv2_fs_mount_point g_mp_sys_dev_hdd1;
|
||||
|
||||
struct lv2_fs_object
|
||||
{
|
||||
@@ -188,8 +190,9 @@ public:
|
||||
lv2_fs_object& operator=(const lv2_fs_object&) = delete;
|
||||
|
||||
static std::string_view get_device_path(std::string_view filename);
|
||||
static lv2_fs_mount_point* get_mp(std::string_view filename);
|
||||
static std::string get_vfs(std::string_view filename);
|
||||
static lv2_fs_mount_point* get_mp(std::string_view filename, std::string* vfs_path = nullptr);
|
||||
static std::string device_name_to_path(std::string_view device_name);
|
||||
static bool vfs_unmount(std::string_view vpath, bool no_error = false);
|
||||
|
||||
static std::array<char, 0x420> get_name(std::string_view filename)
|
||||
{
|
||||
@@ -619,6 +622,6 @@ error_code sys_fs_mapped_free(ppu_thread& ppu, u32 fd, vm::ptr<void> ptr);
|
||||
error_code sys_fs_truncate2(ppu_thread& ppu, u32 fd, u64 size);
|
||||
error_code sys_fs_newfs(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1);
|
||||
error_code sys_fs_mount(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, vm::cptr<char> path, s32 unk1, s32 prot, s32 unk3, vm::cptr<char> str1, u32 str_len);
|
||||
error_code sys_fs_unmount(ppu_thread&, vm::cptr<char> path, s32 unk1, s32 unk2);
|
||||
error_code sys_fs_unmount(ppu_thread& ppu, vm::cptr<char> path, s32 unk1, s32 unk2);
|
||||
error_code sys_fs_get_mount_info_size(ppu_thread& ppu, vm::ptr<u64> len);
|
||||
error_code sys_fs_get_mount_info(ppu_thread& ppu, vm::ptr<CellFsMountInfo> info, u32 len, vm::ptr<u64> out_len);
|
||||
error_code sys_fs_get_mount_info(ppu_thread& ppu, vm::ptr<CellFsMountInfo> info, u64 len, vm::ptr<u64> out_len);
|
||||
|
||||
@@ -69,7 +69,7 @@ struct watchdog_t
|
||||
|
||||
Emu.CallFromMainThread([]()
|
||||
{
|
||||
Emu.Restart();
|
||||
Emu.Restart(false);
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -82,6 +82,15 @@ struct watchdog_t
|
||||
static constexpr auto thread_name = "LV2 Watchdog Thread"sv;
|
||||
};
|
||||
|
||||
void abort_lv2_watchdog()
|
||||
{
|
||||
if (auto thr = g_fxo->try_get<named_thread<watchdog_t>>())
|
||||
{
|
||||
sys_game.notice("Aborting %s...", thr->thread_name);
|
||||
*thr = thread_state::aborting;
|
||||
}
|
||||
}
|
||||
|
||||
error_code _sys_game_watchdog_start(u32 timeout)
|
||||
{
|
||||
sys_game.trace("sys_game_watchdog_start(timeout=%d)", timeout);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
void abort_lv2_watchdog();
|
||||
|
||||
error_code _sys_game_watchdog_start(u32 timeout);
|
||||
error_code _sys_game_watchdog_stop();
|
||||
error_code _sys_game_watchdog_clear();
|
||||
|
||||
@@ -129,10 +129,18 @@ s32 lv2_socket_native::bind(const sys_net_sockaddr& addr)
|
||||
|
||||
const auto* psa_in = reinterpret_cast<const sys_net_sockaddr_in*>(&addr);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
u32 saddr = nph.get_bind_ip();
|
||||
if (saddr == 0)
|
||||
{
|
||||
// If zero use the supplied address
|
||||
saddr = std::bit_cast<u32>(psa_in->sin_addr);
|
||||
}
|
||||
|
||||
::sockaddr_in native_addr{};
|
||||
native_addr.sin_family = AF_INET;
|
||||
native_addr.sin_port = std::bit_cast<u16>(psa_in->sin_port);
|
||||
native_addr.sin_addr.s_addr = std::bit_cast<u32>(psa_in->sin_addr);
|
||||
native_addr.sin_addr.s_addr = saddr;
|
||||
::socklen_t native_addr_len = sizeof(native_addr);
|
||||
|
||||
sys_net.warning("[Native] Trying to bind %s:%d", native_addr.sin_addr, std::bit_cast<be_t<u16>, u16>(native_addr.sin_port));
|
||||
|
||||
@@ -402,6 +402,13 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> ar
|
||||
|
||||
// TODO: set prio, flags
|
||||
|
||||
lv2_exitspawn(ppu, argv, envp, data);
|
||||
}
|
||||
|
||||
void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<std::string>& envp, std::vector<u8>& data)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
Emu.CallFromMainThread([argv = std::move(argv), envp = std::move(envp), data = std::move(data)]() mutable
|
||||
{
|
||||
sys_process.success("Process finished -> %s", argv[0]);
|
||||
|
||||
@@ -101,6 +101,7 @@ extern ps3_process_info_t g_ps3_process_info;
|
||||
// Auxiliary functions
|
||||
s32 process_getpid();
|
||||
s32 process_get_sdk_version(u32 pid, s32& ver);
|
||||
void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<std::string>& envp, std::vector<u8>& data);
|
||||
|
||||
enum CellError : u32;
|
||||
CellError process_is_spu_lock_line_reservation_address(u32 addr, u64 flags);
|
||||
|
||||
+107
-14
@@ -170,6 +170,8 @@ extern const std::map<std::string_view, int> g_prx_list
|
||||
{ "libwmadec.sprx", 0 },
|
||||
};
|
||||
|
||||
bool ppu_register_library_lock(std::string_view libname, bool lock_lib);
|
||||
|
||||
static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<sys_prx_load_module_option_t> /*pOpt*/, fs::file src = {}, s64 file_offset = 0)
|
||||
{
|
||||
if (flags != 0)
|
||||
@@ -191,16 +193,6 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
const std::string path = vfs::get(vpath, nullptr, &vpath0);
|
||||
const std::string name = vpath0.substr(vpath0.find_last_of('/') + 1);
|
||||
|
||||
const auto existing = idm::select<lv2_obj, lv2_prx>([&](u32, lv2_prx& prx)
|
||||
{
|
||||
return prx.path == path && prx.offset == file_offset;
|
||||
});
|
||||
|
||||
if (existing)
|
||||
{
|
||||
return CELL_PRX_ERROR_LIBRARY_FOUND;
|
||||
}
|
||||
|
||||
bool ignore = false;
|
||||
|
||||
constexpr std::string_view firmware_sprx_dir = "/dev_flash/sys/external/";
|
||||
@@ -295,6 +287,8 @@ fs::file make_file_view(fs::file&& _file, u64 offset);
|
||||
|
||||
std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||
{
|
||||
[[maybe_unused]] const s32 version = GET_SERIALIZATION_VERSION(lv2_prx_overlay);
|
||||
|
||||
const std::string path = vfs::get(ar.operator std::string());
|
||||
const s64 offset = ar;
|
||||
const u32 state = ar;
|
||||
@@ -313,6 +307,13 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||
|
||||
if (seg_count)
|
||||
{
|
||||
std::basic_string<bool> loaded_flags;
|
||||
|
||||
if (version >= 3)
|
||||
{
|
||||
ar(loaded_flags);
|
||||
}
|
||||
|
||||
fs::file file{path.substr(0, path.size() - (offset ? fmt::format("_x%x", offset).size() : 0))};
|
||||
|
||||
if (file)
|
||||
@@ -320,6 +321,23 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
|
||||
file = make_file_view(std::move(file), offset);
|
||||
prx = ppu_load_prx(ppu_prx_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, path, 0, &ar);
|
||||
prx->m_loaded_flags = std::move(loaded_flags);
|
||||
|
||||
if (version == 2 && state == PRX_STATE_STARTED)
|
||||
{
|
||||
prx->load_exports();
|
||||
}
|
||||
|
||||
if (version == 3 && state == PRX_STATE_STARTED)
|
||||
{
|
||||
prx->restore_exports();
|
||||
}
|
||||
|
||||
if (version == 1)
|
||||
{
|
||||
prx->load_exports();
|
||||
}
|
||||
|
||||
ensure(prx);
|
||||
}
|
||||
else
|
||||
@@ -355,6 +373,11 @@ void lv2_prx::save(utils::serial& ar)
|
||||
// Save segments count
|
||||
ar.serialize_vle(segs.size());
|
||||
|
||||
if (!segs.empty())
|
||||
{
|
||||
ar(m_loaded_flags);
|
||||
}
|
||||
|
||||
for (const ppu_segment& seg : segs)
|
||||
{
|
||||
if (seg.type == 0x1u && seg.size) ar(seg.addr);
|
||||
@@ -498,12 +521,19 @@ error_code _sys_prx_start_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
std::lock_guard lock(prx->mutex);
|
||||
|
||||
if (!prx->state.compare_and_swap_test(PRX_STATE_INITIALIZED, PRX_STATE_STARTING))
|
||||
{
|
||||
// The only error code here
|
||||
if (prx->state == PRX_STATE_DESTROYED)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
return CELL_PRX_ERROR_ERROR;
|
||||
}
|
||||
|
||||
prx->load_exports();
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
@@ -525,6 +555,7 @@ error_code _sys_prx_start_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys
|
||||
|
||||
// Thread-safe if called from liblv2.sprx, due to internal lwmutex lock before it
|
||||
prx->state = PRX_STATE_STOPPED;
|
||||
prx->unload_exports();
|
||||
_sys_prx_unload_module(ppu, id, 0, vm::null);
|
||||
|
||||
// Return the exact value returned by the start function (as an error)
|
||||
@@ -590,6 +621,7 @@ error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_
|
||||
case PRX_STATE_STOPPED: return CELL_PRX_ERROR_ALREADY_STOPPED;
|
||||
case PRX_STATE_STOPPING: return CELL_PRX_ERROR_ALREADY_STOPPING; // Internal error
|
||||
case PRX_STATE_STARTING: return CELL_PRX_ERROR_ERROR; // Internal error
|
||||
case PRX_STATE_DESTROYED: return CELL_ESRCH;
|
||||
case PRX_STATE_STARTED: break;
|
||||
default:
|
||||
fmt::throw_exception("Invalid prx state (%d)", old);
|
||||
@@ -607,6 +639,11 @@ error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_
|
||||
case 0:
|
||||
{
|
||||
// No error code on invalid state, so throw on unexpected state
|
||||
std::lock_guard lock(prx->mutex);
|
||||
ensure(prx->exports_end <= prx->exports_start || (prx->state == PRX_STATE_STOPPING));
|
||||
|
||||
prx->unload_exports();
|
||||
|
||||
ensure(prx->state.compare_and_swap_test(PRX_STATE_STOPPING, PRX_STATE_STOPPED));
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -628,6 +665,7 @@ error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_
|
||||
case PRX_STATE_STOPPED: return CELL_PRX_ERROR_ALREADY_STOPPED;
|
||||
case PRX_STATE_STOPPING: return CELL_PRX_ERROR_ALREADY_STOPPING; // Internal error
|
||||
case PRX_STATE_STARTING: return CELL_PRX_ERROR_ERROR; // Internal error
|
||||
case PRX_STATE_DESTROYED: return CELL_ESRCH;
|
||||
case PRX_STATE_STARTED: break;
|
||||
default:
|
||||
fmt::throw_exception("Invalid prx state (%d)", old);
|
||||
@@ -660,7 +698,16 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
|
||||
// Get the PRX, free the used memory and delete the object and its ID
|
||||
const auto prx = idm::withdraw<lv2_obj, lv2_prx>(id, [](lv2_prx& prx) -> CellPrxError
|
||||
{
|
||||
switch (prx.state)
|
||||
switch (prx.state.fetch_op([](u32& value)
|
||||
{
|
||||
if (value == PRX_STATE_INITIALIZED || value == PRX_STATE_STOPPED)
|
||||
{
|
||||
value = PRX_STATE_DESTROYED;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}).first)
|
||||
{
|
||||
case PRX_STATE_INITIALIZED:
|
||||
case PRX_STATE_STOPPED:
|
||||
@@ -683,6 +730,8 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
|
||||
|
||||
sys_prx.success("_sys_prx_unload_module(id=0x%x, flags=0x%x, pOpt=*0x%x): name='%s'", id, flags, pOpt, prx->name);
|
||||
|
||||
prx->mutex.lock_unlock();
|
||||
|
||||
ppu_unload_prx(*prx);
|
||||
|
||||
ppu_finalize(*prx);
|
||||
@@ -692,7 +741,51 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size);
|
||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<bool>& loaded_flags);
|
||||
|
||||
void lv2_prx::load_exports()
|
||||
{
|
||||
if (exports_end <= exports_start)
|
||||
{
|
||||
// Nothing to load
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_loaded_flags.empty())
|
||||
{
|
||||
// Already loaded
|
||||
return;
|
||||
}
|
||||
|
||||
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, m_loaded_flags);
|
||||
}
|
||||
|
||||
void lv2_prx::restore_exports()
|
||||
{
|
||||
constexpr usz sizeof_export_data = 0x1C;
|
||||
|
||||
std::basic_string<bool> loaded_flags_empty;
|
||||
|
||||
for (usz start = exports_start, i = 0; start < exports_end; i++, start += sizeof_export_data)
|
||||
{
|
||||
if (::at32(m_loaded_flags, i))
|
||||
{
|
||||
loaded_flags_empty.clear();
|
||||
ppu_manual_load_imports_exports(0, 0, start, sizeof_export_data, loaded_flags_empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv2_prx::unload_exports()
|
||||
{
|
||||
if (m_loaded_flags.empty())
|
||||
{
|
||||
// Not loaded
|
||||
return;
|
||||
}
|
||||
|
||||
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, m_loaded_flags);
|
||||
}
|
||||
|
||||
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt)
|
||||
{
|
||||
@@ -741,7 +834,7 @@ error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::pt
|
||||
{
|
||||
if (g_ps3_process_info.get_cellos_appname() == "vsh.self"sv)
|
||||
{
|
||||
ppu_manual_load_imports_exports(info.lib_stub_ea.addr(), info.lib_stub_size, info.lib_entries_ea.addr(), info.lib_entries_size);
|
||||
ppu_manual_load_imports_exports(info.lib_stub_ea.addr(), info.lib_stub_size, info.lib_entries_ea.addr(), info.lib_entries_size, *std::make_unique<std::basic_string<bool>>());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -63,17 +63,17 @@ struct sys_prx_segment_info_t
|
||||
|
||||
struct sys_prx_module_info_t
|
||||
{
|
||||
be_t<u64> size;
|
||||
char name[30];
|
||||
char version[2];
|
||||
be_t<u32> modattribute;
|
||||
be_t<u32> start_entry;
|
||||
be_t<u32> stop_entry;
|
||||
be_t<u32> all_segments_num;
|
||||
vm::bptr<char> filename;
|
||||
be_t<u32> filename_size;
|
||||
vm::bptr<sys_prx_segment_info_t> segments;
|
||||
be_t<u32> segments_num;
|
||||
be_t<u64> size; // 0
|
||||
char name[30]; // 8
|
||||
char version[2]; // 0x26
|
||||
be_t<u32> modattribute; // 0x28
|
||||
be_t<u32> start_entry; // 0x2c
|
||||
be_t<u32> stop_entry; // 0x30
|
||||
be_t<u32> all_segments_num; // 0x34
|
||||
vm::bptr<char> filename; // 0x38
|
||||
be_t<u32> filename_size; // 0x3c
|
||||
vm::bptr<sys_prx_segment_info_t> segments; // 0x40
|
||||
be_t<u32> segments_num; // 0x44
|
||||
};
|
||||
|
||||
struct sys_prx_module_info_option_t
|
||||
@@ -169,6 +169,7 @@ enum : u32
|
||||
PRX_STATE_STARTED,
|
||||
PRX_STATE_STOPPING, // In-between state between started and stopped (internal)
|
||||
PRX_STATE_STOPPED, // Last state, the module cannot be restarted
|
||||
PRX_STATE_DESTROYED, // Last state, the module cannot be restarted
|
||||
};
|
||||
|
||||
struct lv2_prx final : lv2_obj, ppu_module
|
||||
@@ -176,6 +177,7 @@ struct lv2_prx final : lv2_obj, ppu_module
|
||||
static const u32 id_base = 0x23000000;
|
||||
|
||||
atomic_t<u32> state = PRX_STATE_INITIALIZED;
|
||||
shared_mutex mutex;
|
||||
|
||||
std::unordered_map<u32, u32> specials;
|
||||
std::unordered_map<u32, void*> imports;
|
||||
@@ -186,9 +188,18 @@ struct lv2_prx final : lv2_obj, ppu_module
|
||||
vm::ptr<s32(u64 callback, u64 argc, vm::ptr<void, u64> argv)> epilogue = vm::null;
|
||||
vm::ptr<s32()> exit = vm::null;
|
||||
|
||||
char module_info_name[28];
|
||||
u8 module_info_version[2];
|
||||
be_t<u16> module_info_attributes;
|
||||
char module_info_name[28]{};
|
||||
u8 module_info_version[2]{};
|
||||
be_t<u16> module_info_attributes{};
|
||||
|
||||
u32 exports_start = umax;
|
||||
u32 exports_end = 0;
|
||||
|
||||
std::basic_string<bool> m_loaded_flags;
|
||||
|
||||
void load_exports(); // (Re)load exports
|
||||
void restore_exports(); // For savestates
|
||||
void unload_exports();
|
||||
|
||||
lv2_prx() noexcept = default;
|
||||
lv2_prx(utils::serial&) {}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
|
||||
#include "sys_sm.h"
|
||||
|
||||
@@ -41,9 +44,49 @@ error_code sys_sm_get_ext_event2(vm::ptr<u64> a1, vm::ptr<u64> a2, vm::ptr<u64>
|
||||
return not_an_error(CELL_EAGAIN);
|
||||
}
|
||||
|
||||
error_code sys_sm_shutdown(u16 op, vm::ptr<void> param, u64 size)
|
||||
error_code sys_sm_shutdown(ppu_thread& ppu, u16 op, vm::ptr<void> param, u64 size)
|
||||
{
|
||||
sys_sm.todo("sys_sm_shutdown(op=0x%x, param=*0x%x, size=0x%x)", op, param, size);
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_sm.success("sys_sm_shutdown(op=0x%x, param=*0x%x, size=0x%x)", op, param, size);
|
||||
|
||||
if (!g_ps3_process_info.has_root_perm())
|
||||
{
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x1100:
|
||||
{
|
||||
sys_sm.success("Received shutdown request from application");
|
||||
_sys_process_exit(ppu, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
case 0x200:
|
||||
case 0x1200:
|
||||
{
|
||||
sys_sm.success("Received reboot request from application");
|
||||
lv2_exitspawn(ppu, Emu.argv, Emu.envp, Emu.data);
|
||||
break;
|
||||
}
|
||||
case 0x8201:
|
||||
case 0x8202:
|
||||
case 0x8204:
|
||||
{
|
||||
sys_sm.warning("Unsupported LPAR operation: 0x%x", op);
|
||||
return CELL_ENOTSUP;
|
||||
}
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_sm_set_shop_mode(s32 mode)
|
||||
{
|
||||
sys_sm.todo("sys_sm_set_shop_mode(mode=0x%x)", mode);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
// SysCalls
|
||||
|
||||
error_code sys_sm_get_ext_event2(vm::ptr<u64> a1, vm::ptr<u64> a2, vm::ptr<u64> a3, u64 a4);
|
||||
error_code sys_sm_shutdown(u16 op, vm::ptr<void> param, u64 size);
|
||||
error_code sys_sm_shutdown(ppu_thread& ppu, u16 op, vm::ptr<void> param, u64 size);
|
||||
error_code sys_sm_get_params(vm::ptr<u8> a, vm::ptr<u8> b, vm::ptr<u32> c, vm::ptr<u64> d);
|
||||
error_code sys_sm_set_shop_mode(s32 mode);
|
||||
error_code sys_sm_control_led(u8 led, u8 action);
|
||||
error_code sys_sm_ring_buzzer(u64 packet, u64 a1, u64 a2);
|
||||
constexpr auto sys_sm_ring_buzzer2 = sys_sm_ring_buzzer;
|
||||
|
||||
@@ -124,19 +124,16 @@ error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_ss_get_console_id(vm::ptr<u8> buf)
|
||||
error_code sys_ss_get_console_id(vm::ptr<u8> buf)
|
||||
{
|
||||
sys_ss.todo("sys_ss_get_console_id(buf=*0x%x)", buf);
|
||||
sys_ss.notice("sys_ss_get_console_id(buf=*0x%x)", buf);
|
||||
|
||||
// TODO: Return some actual IDPS?
|
||||
*buf = 0;
|
||||
|
||||
return CELL_OK;
|
||||
return sys_ss_appliance_info_manager(0x19003, buf);
|
||||
}
|
||||
|
||||
s32 sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid)
|
||||
error_code sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid)
|
||||
{
|
||||
sys_ss.warning("sys_ss_get_open_psid(psid=*0x%x)", psid);
|
||||
sys_ss.notice("sys_ss_get_open_psid(psid=*0x%x)", psid);
|
||||
|
||||
psid->high = g_cfg.sys.console_psid_high;
|
||||
psid->low = g_cfg.sys.console_psid_low;
|
||||
@@ -146,7 +143,7 @@ s32 sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid)
|
||||
|
||||
error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||
{
|
||||
sys_ss.warning("sys_ss_appliance_info_manager(code=0x%x, buffer=*0x%x)", code, buffer);
|
||||
sys_ss.notice("sys_ss_appliance_info_manager(code=0x%x, buffer=*0x%x)", code, buffer);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
@@ -158,6 +155,11 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||
case 0x19002:
|
||||
{
|
||||
// AIM_get_device_type
|
||||
constexpr u8 product_code[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89 };
|
||||
std::memcpy(buffer.get_ptr(), product_code, 16);
|
||||
if (g_cfg.core.debug_console_mode)
|
||||
buffer[15] = 0xA0;
|
||||
break;
|
||||
}
|
||||
case 0x19003:
|
||||
{
|
||||
@@ -165,7 +167,7 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||
constexpr u8 idps[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x89, 0x00, 0x0B, 0x14, 0x00, 0xEF, 0xDD, 0xCA, 0x25, 0x52, 0x66 };
|
||||
std::memcpy(buffer.get_ptr(), idps, 16);
|
||||
if (g_cfg.core.debug_console_mode)
|
||||
buffer[5] = 0x81;
|
||||
buffer[5] = 0xA0;
|
||||
break;
|
||||
}
|
||||
case 0x19004:
|
||||
@@ -178,6 +180,10 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||
case 0x19005:
|
||||
{
|
||||
// AIM_get_open_ps_id
|
||||
be_t<u64> psid[2] = { +g_cfg.sys.console_psid_high, +g_cfg.sys.console_psid_low };
|
||||
u8* psid_bytes = reinterpret_cast<u8*>(psid);
|
||||
std::memcpy(buffer.get_ptr(), psid_bytes, 16);
|
||||
break;
|
||||
}
|
||||
case 0x19006:
|
||||
{
|
||||
|
||||
@@ -20,8 +20,8 @@ struct CellSsOpenPSID
|
||||
|
||||
error_code sys_ss_random_number_generator(u64 pkg_id, vm::ptr<void> buf, u64 size);
|
||||
error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3);
|
||||
s32 sys_ss_get_console_id(vm::ptr<u8> buf);
|
||||
s32 sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid);
|
||||
error_code sys_ss_get_console_id(vm::ptr<u8> buf);
|
||||
error_code sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid);
|
||||
error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer);
|
||||
error_code sys_ss_get_cache_of_product_mode(vm::ptr<u8> ptr);
|
||||
error_code sys_ss_secure_rtc(u64 cmd, u64 a2, u64 a3, u64 a4);
|
||||
|
||||
@@ -396,7 +396,7 @@ error_code sys_timer_sleep(ppu_thread& ppu, u32 sleep_time)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_timer.warning("sys_timer_sleep(sleep_time=%d)", sleep_time);
|
||||
sys_timer.trace("sys_timer_sleep(sleep_time=%d)", sleep_time);
|
||||
|
||||
return sys_timer_usleep(ppu, sleep_time * u64{1000000});
|
||||
}
|
||||
|
||||
+8
-29
@@ -6,14 +6,14 @@
|
||||
struct GameInfo
|
||||
{
|
||||
std::string path;
|
||||
|
||||
std::string icon_path;
|
||||
std::string name;
|
||||
std::string serial;
|
||||
std::string app_ver;
|
||||
std::string version;
|
||||
std::string category;
|
||||
std::string fw;
|
||||
|
||||
std::string name = "Unknown";
|
||||
std::string serial = "Unknown";
|
||||
std::string app_ver = "Unknown";
|
||||
std::string version = "Unknown";
|
||||
std::string category = "Unknown";
|
||||
std::string fw = "Unknown";
|
||||
|
||||
u32 attr = 0;
|
||||
u32 bootable = 0;
|
||||
@@ -21,26 +21,5 @@ struct GameInfo
|
||||
u32 sound_format = 0;
|
||||
u32 resolution = 0;
|
||||
|
||||
GameInfo()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
path.clear();
|
||||
|
||||
name = "Unknown";
|
||||
serial = "Unknown";
|
||||
app_ver = "Unknown";
|
||||
version = "Unknown";
|
||||
category = "Unknown";
|
||||
fw = "Unknown";
|
||||
|
||||
attr = 0;
|
||||
bootable = 0;
|
||||
parental_lvl = 0;
|
||||
sound_format = 0;
|
||||
resolution = 0;
|
||||
}
|
||||
u64 size_on_disk = umax;
|
||||
};
|
||||
|
||||
@@ -92,10 +92,10 @@ void sky_portal::get_status(u8* reply_buf)
|
||||
}
|
||||
|
||||
std::memset(reply_buf, 0, 0x20);
|
||||
reply_buf[0] = 0x53;
|
||||
*utils::bless<le_t<u16>>(reply_buf + 1) = status;
|
||||
reply_buf[5] = interrupt_counter++;
|
||||
reply_buf[6] = 0x01;
|
||||
reply_buf[0] = 0x53;
|
||||
write_to_ptr<le_t<u16>>(reply_buf, 1, status);
|
||||
reply_buf[5] = interrupt_counter++;
|
||||
reply_buf[6] = 0x01;
|
||||
}
|
||||
|
||||
void sky_portal::query_block(u8 sky_num, u8 block, u8* reply_buf)
|
||||
@@ -159,7 +159,7 @@ u8 sky_portal::load_skylander(u8* buf, fs::file in_file)
|
||||
{
|
||||
std::lock_guard lock(sky_mutex);
|
||||
|
||||
u32 sky_serial = *utils::bless<le_t<u32>>(buf);
|
||||
u32 sky_serial = read_from_ptr<le_t<u32>>(buf);
|
||||
u8 found_slot = 0xFF;
|
||||
|
||||
// mimics spot retaining on the portal
|
||||
|
||||
@@ -7,10 +7,11 @@ LOG_CHANNEL(camera_log, "Camera");
|
||||
cfg_camera g_cfg_camera;
|
||||
|
||||
cfg_camera::cfg_camera()
|
||||
: cfg::node()
|
||||
#ifdef _WIN32
|
||||
: path(fs::get_config_dir() + "config/camera.yml")
|
||||
, path(fs::get_config_dir() + "config/camera.yml")
|
||||
#else
|
||||
: path(fs::get_config_dir() + "camera.yml")
|
||||
, path(fs::get_config_dir() + "camera.yml")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ void fmt_class_string<pad_handler>::format(std::string& out, u64 arg)
|
||||
case pad_handler::xinput: return "XInput";
|
||||
case pad_handler::mm: return "MMJoystick";
|
||||
#endif
|
||||
#ifdef HAVE_SDL2
|
||||
case pad_handler::sdl: return "SDL";
|
||||
#endif
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
case pad_handler::evdev: return "Evdev";
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@ enum class pad_handler
|
||||
xinput,
|
||||
mm,
|
||||
#endif
|
||||
#ifdef HAVE_SDL2
|
||||
sdl,
|
||||
#endif
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
evdev,
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "stdafx.h"
|
||||
#include "recording_config.h"
|
||||
#include <charconv>
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
cfg_recording g_cfg_recording;
|
||||
|
||||
cfg_recording::cfg_recording()
|
||||
: cfg::node()
|
||||
#ifdef _WIN32
|
||||
, path(fs::get_config_dir() + "config/recording.yml")
|
||||
#else
|
||||
, path(fs::get_config_dir() + "recording.yml")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
bool cfg_recording::load()
|
||||
{
|
||||
cfg_log.notice("Loading recording config from '%s'", path);
|
||||
|
||||
if (fs::file cfg_file{path, fs::read})
|
||||
{
|
||||
return from_string(cfg_file.to_string());
|
||||
}
|
||||
|
||||
cfg_log.notice("Recording config missing. Using default settings. Path: %s", path);
|
||||
from_default();
|
||||
save();
|
||||
return false;
|
||||
}
|
||||
|
||||
void cfg_recording::save() const
|
||||
{
|
||||
cfg_log.notice("Saving recording config to '%s'", path);
|
||||
|
||||
fs::pending_file cfg_file(path);
|
||||
|
||||
if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit()))
|
||||
{
|
||||
cfg_log.error("Failed to save recording config to '%s'", path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/Config.h"
|
||||
|
||||
struct cfg_recording final : cfg::node
|
||||
{
|
||||
cfg_recording();
|
||||
bool load();
|
||||
void save() const;
|
||||
|
||||
cfg::uint<0, 60> framerate{this, "Framerate", 30};
|
||||
cfg::uint<0, 7680> width{this, "Width", 1280};
|
||||
cfg::uint<0, 4320> height{this, "Height", 720};
|
||||
cfg::uint<0, 192> pixel_format{this, "AVPixelFormat", 0}; // AVPixelFormat::AV_PIX_FMT_YUV420P
|
||||
cfg::uint<0, 32813> video_codec{this, "AVCodecID", 12}; // AVCodecID::AV_CODEC_ID_MPEG4
|
||||
cfg::uint<0, 25000000> video_bps{this, "Video Bitrate", 4000000};
|
||||
cfg::uint<0, 5> max_b_frames{this, "Max B-Frames", 2};
|
||||
cfg::uint<0, 20> gop_size{this, "Group of Pictures Size", 12};
|
||||
|
||||
const std::string path;
|
||||
};
|
||||
|
||||
extern cfg_recording g_cfg_recording;
|
||||
+10
-3
@@ -394,15 +394,22 @@ void usb_device_usio::usio_read(u8 channel, u16 reg, u16 size)
|
||||
{
|
||||
// Get Buffer, rarely gives a reply on real HW
|
||||
// First U16 seems to be a timestamp of sort
|
||||
// Purpose seems related to BananaPass
|
||||
// Purpose seems related to connectivity check
|
||||
q_replies.push({0x7E, 0xE4, 0x00, 0x00, 0x74, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||
break;
|
||||
}
|
||||
case 0x0080:
|
||||
{
|
||||
// Purpose unknown
|
||||
// Card reader check - 1
|
||||
ensure(size == 0x10);
|
||||
q_replies.push({0x02, 0x03, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x10, 0x00});
|
||||
q_replies.push({0x02, 0x03, 0x06, 0x00, 0xFF, 0x0F, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x10, 0x00});
|
||||
break;
|
||||
}
|
||||
case 0x7000:
|
||||
{
|
||||
// Card reader check - 2
|
||||
ensure(size == 0x06);
|
||||
// No data returned
|
||||
break;
|
||||
}
|
||||
case 0x1080:
|
||||
|
||||
+90
-10
@@ -495,15 +495,24 @@ namespace vm
|
||||
{
|
||||
to_clear = for_all_range_locks(to_clear, [&](u64 addr2, u32 size2)
|
||||
{
|
||||
// TODO (currently not possible): handle 2 64K pages (inverse range), or more pages
|
||||
if (u64 is_shared = g_shmem[addr2 >> 16]) [[unlikely]]
|
||||
// Split and check every 64K page separately
|
||||
for (u64 hi = addr2 >> 16, max = (addr2 + size2 - 1) >> 16; hi <= max; hi++)
|
||||
{
|
||||
addr2 = static_cast<u16>(addr2) | is_shared;
|
||||
}
|
||||
u64 addr3 = addr2;
|
||||
u32 size3 = std::min<u64>(addr2 + size2, utils::align(addr2, 0x10000)) - addr2;
|
||||
|
||||
if (point - (addr2 / 128) <= (addr2 + size2 - 1) / 128 - (addr2 / 128)) [[unlikely]]
|
||||
{
|
||||
return 1;
|
||||
if (u64 is_shared = g_shmem[hi]) [[unlikely]]
|
||||
{
|
||||
addr3 = static_cast<u16>(addr2) | is_shared;
|
||||
}
|
||||
|
||||
if (point - (addr3 / 128) <= (addr3 + size3 - 1) / 128 - (addr3 / 128)) [[unlikely]]
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr2 += size3;
|
||||
size2 -= size3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1919,10 +1928,8 @@ namespace vm
|
||||
return _map(addr, area_size, flags);
|
||||
}
|
||||
|
||||
bool try_access(u32 addr, void* ptr, u32 size, bool is_write)
|
||||
static bool try_access_internal(u32 addr, void* ptr, u32 size, bool is_write)
|
||||
{
|
||||
vm::writer_lock lock;
|
||||
|
||||
if (vm::check_addr(addr, is_write ? page_writable : page_readable, size))
|
||||
{
|
||||
void* src = vm::g_sudo_addr + addr;
|
||||
@@ -1955,6 +1962,79 @@ namespace vm
|
||||
return false;
|
||||
}
|
||||
|
||||
bool try_access(u32 begin, void* ptr, u32 size, bool is_write)
|
||||
{
|
||||
auto* range_lock = alloc_range_lock(); // Released at the end of function
|
||||
|
||||
range_lock->store(begin | (u64{size} << 32));
|
||||
|
||||
for (u64 i = 0;; i++)
|
||||
{
|
||||
const u64 lock_val = g_range_lock.load();
|
||||
const u64 is_share = g_shmem[begin >> 16].load();
|
||||
|
||||
u64 lock_addr = static_cast<u32>(lock_val); // -> u64
|
||||
u32 lock_size = static_cast<u32>(lock_val << range_bits >> (range_bits + 32));
|
||||
|
||||
u64 addr = begin;
|
||||
|
||||
if ((lock_val & range_full_mask) == range_locked) [[likely]]
|
||||
{
|
||||
lock_size = 128;
|
||||
|
||||
if (is_share)
|
||||
{
|
||||
addr = static_cast<u16>(addr) | is_share;
|
||||
lock_addr = lock_val;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr + size <= lock_addr || addr >= lock_addr + lock_size) [[likely]]
|
||||
{
|
||||
if (vm::check_addr(begin, is_write ? page_writable : page_readable, size)) [[likely]]
|
||||
{
|
||||
const u64 new_lock_val = g_range_lock.load();
|
||||
|
||||
if (!new_lock_val || new_lock_val == lock_val) [[likely]]
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free_range_lock(range_lock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (lock_val & range_readable && lock_val & range_writable)
|
||||
{
|
||||
// Probably a safe case of page protection change
|
||||
break;
|
||||
}
|
||||
else if (!is_write && lock_val & range_readable)
|
||||
{
|
||||
// Same but for read-only access
|
||||
break;
|
||||
}
|
||||
else if ((lock_val & range_full_mask) != range_locked)
|
||||
{
|
||||
free_range_lock(range_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait a bit before accessing global lock
|
||||
range_lock->release(0);
|
||||
|
||||
busy_wait(200);
|
||||
|
||||
range_lock->store(begin | (u64{size} << 32));
|
||||
}
|
||||
|
||||
const bool result = try_access_internal(begin, ptr, size, is_write);
|
||||
free_range_lock(range_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline namespace ps3_
|
||||
{
|
||||
static utils::shm s_hook{0x800000000, ""};
|
||||
|
||||
@@ -232,8 +232,15 @@ namespace np
|
||||
ptr_member->flagAttr = member.flagAttr;
|
||||
}
|
||||
|
||||
const u32 needed_data_size = sizeof(SceNpOnlineName) + sizeof(SceNpAvatarUrl) + sizeof(SceNpMatching2RoomGroup) +
|
||||
(binattrs_list.size() * (sizeof(SceNpMatching2RoomMemberBinAttrInternal) + SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE));
|
||||
u32 needed_data_size = sizeof(SceNpOnlineName) + sizeof(SceNpAvatarUrl) + sizeof(SceNpMatching2RoomGroup);
|
||||
|
||||
for (usz i = 0; i < binattrs_list.size(); i++)
|
||||
{
|
||||
if (member.bins.contains(binattrs_list[i]))
|
||||
{
|
||||
needed_data_size += (sizeof(SceNpMatching2RoomMemberBinAttrInternal) + ::at32(member.bins, binattrs_list[i]).data.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_data || !ptr_member)
|
||||
{
|
||||
|
||||
+30
-13
@@ -192,9 +192,9 @@ namespace np
|
||||
}
|
||||
|
||||
ticket_data tdata{};
|
||||
const auto* ptr = data() + index;
|
||||
tdata.id = *reinterpret_cast<const be_t<u16>*>(ptr);
|
||||
tdata.len = *reinterpret_cast<const be_t<u16>*>(ptr + 2);
|
||||
const auto* ptr = data() + index;
|
||||
tdata.id = read_from_ptr<be_t<u16>>(ptr);
|
||||
tdata.len = read_from_ptr<be_t<u16>>(ptr + 2);
|
||||
const auto* data_ptr = data() + index + 4;
|
||||
|
||||
auto check_size = [&](std::size_t expected) -> bool
|
||||
@@ -219,7 +219,7 @@ namespace np
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
tdata.data.data_u32 = *reinterpret_cast<const be_t<u32>*>(data_ptr);
|
||||
tdata.data.data_u32 = read_from_ptr<be_t<u32>>(data_ptr);
|
||||
break;
|
||||
case 2:
|
||||
case 7:
|
||||
@@ -227,7 +227,7 @@ namespace np
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
tdata.data.data_u64 = *reinterpret_cast<const be_t<u64>*>(data_ptr);
|
||||
tdata.data.data_u64 = read_from_ptr<be_t<u64>>(data_ptr);
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
@@ -277,14 +277,14 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
version = *reinterpret_cast<const be_t<u32>*>(data());
|
||||
version = read_from_ptr<be_t<u32>>(data());
|
||||
if (version != 0x21010000)
|
||||
{
|
||||
ticket_log.error("Invalid version: 0x%08x", version);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 given_size = *reinterpret_cast<const be_t<u32>*>(data() + 4);
|
||||
u32 given_size = read_from_ptr<be_t<u32>>(data() + 4);
|
||||
if ((given_size + 8) != size())
|
||||
{
|
||||
ticket_log.error("Size mismatch (gs: %d vs s: %d)", given_size, size());
|
||||
@@ -371,6 +371,18 @@ namespace np
|
||||
{
|
||||
dns_ip = conv.s_addr;
|
||||
}
|
||||
|
||||
// Convert bind address
|
||||
conv = {};
|
||||
if (!inet_pton(AF_INET, g_cfg.net.bind_address.to_string().c_str(), &conv))
|
||||
{
|
||||
// Do not set to disconnected on invalid IP just error and continue using default (0.0.0.0)
|
||||
nph_log.error("Provided IP(%s) address for bind is invalid!", g_cfg.net.bind_address.to_string());
|
||||
}
|
||||
else
|
||||
{
|
||||
bind_ip = conv.s_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +468,7 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
nph_log.notice("discover_ip_address: Hostname was determined to be %s", hostname.c_str());
|
||||
// nph_log.notice("discover_ip_address: Hostname was determined to be %s", hostname.c_str());
|
||||
|
||||
hostent* host = gethostbyname(hostname.data());
|
||||
if (!host)
|
||||
@@ -471,12 +483,12 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
local_ip_addr = *reinterpret_cast<u32*>(host->h_addr_list[0]);
|
||||
local_ip_addr = read_from_ptr<u32>(host->h_addr_list[0]);
|
||||
|
||||
// Set public address to local discovered address for now, may be updated later from RPCN socket
|
||||
public_ip_addr = local_ip_addr;
|
||||
|
||||
nph_log.notice("discover_ip_address: IP was determined to be %s", ip_to_string(local_ip_addr));
|
||||
// nph_log.notice("discover_ip_address: IP was determined to be %s", ip_to_string(local_ip_addr));
|
||||
}
|
||||
|
||||
bool np_handler::discover_ether_address()
|
||||
@@ -494,7 +506,7 @@ namespace np
|
||||
sockaddr_dl* sdp = reinterpret_cast<sockaddr_dl*>(p->ifa_addr);
|
||||
memcpy(ether_address.data(), sdp->sdl_data + sdp->sdl_nlen, 6);
|
||||
freeifaddrs(ifap);
|
||||
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
// nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -511,7 +523,7 @@ namespace np
|
||||
{
|
||||
PIP_ADAPTER_INFO info = reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data());
|
||||
memcpy(ether_address.data(), info[0].Address, 6);
|
||||
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
// nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
@@ -551,7 +563,7 @@ namespace np
|
||||
if (success)
|
||||
{
|
||||
memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6);
|
||||
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
// nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -585,6 +597,11 @@ namespace np
|
||||
return dns_ip;
|
||||
}
|
||||
|
||||
u32 np_handler::get_bind_ip() const
|
||||
{
|
||||
return bind_ip;
|
||||
}
|
||||
|
||||
s32 np_handler::get_net_status() const
|
||||
{
|
||||
return is_connected ? CELL_NET_CTL_STATE_IPObtained : CELL_NET_CTL_STATE_Disconnected;
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace np
|
||||
u32 get_local_ip_addr() const;
|
||||
u32 get_public_ip_addr() const;
|
||||
u32 get_dns_ip() const;
|
||||
u32 get_bind_ip() const;
|
||||
|
||||
s32 get_psn_status() const;
|
||||
s32 get_net_status() const;
|
||||
@@ -290,6 +291,7 @@ namespace np
|
||||
be_t<u32> local_ip_addr{};
|
||||
be_t<u32> public_ip_addr{};
|
||||
be_t<u32> dns_ip = 0x08080808;
|
||||
be_t<u32> bind_ip = 0x00000000;
|
||||
|
||||
// User infos
|
||||
SceNpId npid{};
|
||||
|
||||
@@ -206,10 +206,10 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 room_id = reinterpret_cast<le_t<u64>&>(data[0]);
|
||||
const u16 member_id = reinterpret_cast<le_t<u16>&>(data[8]);
|
||||
const u16 port_p2p = reinterpret_cast<be_t<u16>&>(data[10]);
|
||||
const u32 addr_p2p = reinterpret_cast<le_t<u32>&>(data[12]);
|
||||
const u64 room_id = read_from_ptr<le_t<u64>>(data);
|
||||
const u16 member_id = read_from_ptr<le_t<u16>>(data, 8);
|
||||
const u16 port_p2p = read_from_ptr<be_t<u16>>(data, 10);
|
||||
const u32 addr_p2p = read_from_ptr<le_t<u32>>(data, 12);
|
||||
|
||||
rpcn_log.notice("Received notification to connect to member(%d) of room(%d): %s:%d", member_id, room_id, ip_to_string(addr_p2p), port_p2p);
|
||||
|
||||
|
||||
@@ -732,7 +732,7 @@ namespace rpcn
|
||||
}
|
||||
|
||||
update_local_addr(client_addr.sin_addr.s_addr);
|
||||
rpcn_log.notice("Updated local address to %s", np::ip_to_string(std::bit_cast<u32, be_t<u32>>(local_addr_sig.load())));
|
||||
// rpcn_log.notice("Updated local address to %s", np::ip_to_string(std::bit_cast<u32, be_t<u32>>(local_addr_sig.load())));
|
||||
|
||||
if (wolfSSL_set_fd(read_wssl, sockfd) != WOLFSSL_SUCCESS)
|
||||
{
|
||||
|
||||
@@ -313,5 +313,15 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sort(std::predicate<const Ty&, const Ty&> auto predicate)
|
||||
{
|
||||
if (_size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::sort(begin(), end(), predicate);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -705,8 +705,7 @@ namespace rsx
|
||||
std::vector<u8> marker(range.length() + sizeof(overrun_cookie_value), 0);
|
||||
|
||||
// Tag end
|
||||
u32* overrun_test_ptr = utils::bless<u32>(marker.data() + range.length());
|
||||
*overrun_test_ptr = overrun_cookie_value;
|
||||
write_to_ptr(marker, range.length(), overrun_cookie_value);
|
||||
|
||||
u32 removed_count = 0;
|
||||
|
||||
@@ -717,10 +716,10 @@ namespace rsx
|
||||
|
||||
while (length >= 8)
|
||||
{
|
||||
auto& value = *utils::bless<u64>(dst_ptr);
|
||||
const u64 value = read_from_ptr<u64>(dst_ptr);
|
||||
const u64 block_mask = ~value; // If the value is not all 1s, set valid to true
|
||||
mask |= block_mask;
|
||||
value = umax;
|
||||
write_to_ptr<u64>(dst_ptr, umax);
|
||||
|
||||
dst_ptr += 8;
|
||||
length -= 8;
|
||||
@@ -728,10 +727,10 @@ namespace rsx
|
||||
|
||||
if (length >= 4)
|
||||
{
|
||||
auto& value = *utils::bless<u32>(dst_ptr);
|
||||
const u32 value = read_from_ptr<u32>(dst_ptr);
|
||||
const u32 block_mask = ~value;
|
||||
mask |= block_mask;
|
||||
value = umax;
|
||||
write_to_ptr<u32>(dst_ptr, umax);
|
||||
|
||||
dst_ptr += 4;
|
||||
length -= 4;
|
||||
@@ -739,10 +738,10 @@ namespace rsx
|
||||
|
||||
if (length >= 2)
|
||||
{
|
||||
auto& value = *utils::bless<u16>(dst_ptr);
|
||||
const u16 value = read_from_ptr<u16>(dst_ptr);
|
||||
const u16 block_mask = ~value;
|
||||
mask |= block_mask;
|
||||
value = umax;
|
||||
write_to_ptr<u16>(dst_ptr, umax);
|
||||
|
||||
dst_ptr += 2;
|
||||
length -= 2;
|
||||
@@ -750,10 +749,10 @@ namespace rsx
|
||||
|
||||
if (length)
|
||||
{
|
||||
auto& value = *dst_ptr;
|
||||
const u8 value = *dst_ptr;
|
||||
const u8 block_mask = ~value;
|
||||
mask |= block_mask;
|
||||
value = umax;
|
||||
*dst_ptr = umax;
|
||||
}
|
||||
|
||||
return !!mask;
|
||||
@@ -824,7 +823,7 @@ namespace rsx
|
||||
rsx_log.notice("rsx::surface_cache::check_for_duplicates_fallback analysed %u overlapping sections and removed %u", ::size32(sections), removed_count);
|
||||
|
||||
// Verify no OOB
|
||||
ensure(*overrun_test_ptr == overrun_cookie_value);
|
||||
ensure(read_from_ptr<u32>(marker, range.length()) == overrun_cookie_value);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace rsx
|
||||
};
|
||||
|
||||
template <typename image_storage_type>
|
||||
struct render_target_descriptor
|
||||
struct render_target_descriptor : public rsx::ref_counted
|
||||
{
|
||||
u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to
|
||||
u32 base_addr = 0;
|
||||
@@ -165,6 +165,13 @@ namespace rsx
|
||||
}
|
||||
format_info;
|
||||
|
||||
struct
|
||||
{
|
||||
u64 timestamp = 0;
|
||||
bool locked = false;
|
||||
}
|
||||
texture_cache_metadata;
|
||||
|
||||
render_target_descriptor() {}
|
||||
|
||||
virtual ~render_target_descriptor()
|
||||
@@ -178,7 +185,11 @@ namespace rsx
|
||||
|
||||
virtual image_storage_type get_surface(rsx::surface_access access_type) = 0;
|
||||
virtual bool is_depth_surface() const = 0;
|
||||
virtual void release_ref(image_storage_type) const = 0;
|
||||
|
||||
void reset()
|
||||
{
|
||||
texture_cache_metadata = {};
|
||||
}
|
||||
|
||||
template<rsx::surface_metrics Metrics = rsx::surface_metrics::pixels, typename T = u32>
|
||||
T get_surface_width() const
|
||||
@@ -381,6 +392,9 @@ namespace rsx
|
||||
ensure(native_pitch);
|
||||
ensure(rsx_pitch);
|
||||
|
||||
// Clear metadata
|
||||
reset();
|
||||
|
||||
base_addr = address;
|
||||
|
||||
const u32 size_x = (native_pitch > 8)? (native_pitch - 8) : 0u;
|
||||
@@ -438,7 +452,7 @@ namespace rsx
|
||||
{
|
||||
for (auto &e : old_contents)
|
||||
{
|
||||
release_ref(e.source);
|
||||
ensure(dynamic_cast<rsx::ref_counted*>(e.source))->release();
|
||||
}
|
||||
|
||||
old_contents.clear();
|
||||
@@ -696,5 +710,68 @@ namespace rsx
|
||||
ensure(access_type.is_read() || access_type.is_transfer());
|
||||
transform_samples_to_pixels(region);
|
||||
}
|
||||
|
||||
void on_lock()
|
||||
{
|
||||
add_ref();
|
||||
texture_cache_metadata.locked = true;
|
||||
texture_cache_metadata.timestamp = rsx::get_shared_tag();
|
||||
}
|
||||
|
||||
void on_unlock()
|
||||
{
|
||||
texture_cache_metadata.locked = false;
|
||||
texture_cache_metadata.timestamp = rsx::get_shared_tag();
|
||||
release();
|
||||
}
|
||||
|
||||
void on_swap_out()
|
||||
{
|
||||
if (is_locked())
|
||||
{
|
||||
on_unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
void on_swap_in(bool lock)
|
||||
{
|
||||
if (!is_locked() && lock)
|
||||
{
|
||||
on_lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
add_ref();
|
||||
}
|
||||
}
|
||||
|
||||
void on_clone_from(const render_target_descriptor* ref)
|
||||
{
|
||||
if (ref->is_locked() && !is_locked())
|
||||
{
|
||||
// Propagate locked state only.
|
||||
texture_cache_metadata = ref->texture_cache_metadata;
|
||||
}
|
||||
|
||||
rsx_pitch = ref->get_rsx_pitch();
|
||||
last_use_tag = ref->last_use_tag;
|
||||
raster_type = ref->raster_type; // Can't actually cut up swizzled data
|
||||
}
|
||||
|
||||
bool is_locked() const
|
||||
{
|
||||
return texture_cache_metadata.locked;
|
||||
}
|
||||
|
||||
bool has_flushable_data() const
|
||||
{
|
||||
ensure(is_locked());
|
||||
ensure(texture_cache_metadata.timestamp);
|
||||
return (texture_cache_metadata.timestamp < last_use_tag);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -583,6 +583,7 @@ namespace rsx
|
||||
}
|
||||
|
||||
data.flushed = true;
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1324,6 +1324,26 @@ namespace rsx
|
||||
return (get_protection() == utils::protection::no);
|
||||
}
|
||||
|
||||
bool is_synchronized() const
|
||||
{
|
||||
return synchronized;
|
||||
}
|
||||
|
||||
bool is_flushed() const
|
||||
{
|
||||
return flushed;
|
||||
}
|
||||
|
||||
bool should_flush() const
|
||||
{
|
||||
if (context == rsx::texture_upload_context::framebuffer_storage)
|
||||
{
|
||||
const auto surface = derived()->get_render_target();
|
||||
return surface->has_flushable_data();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -1355,18 +1375,18 @@ namespace rsx
|
||||
if (context == rsx::texture_upload_context::framebuffer_storage && !Emu.IsStopped())
|
||||
{
|
||||
// Lock, unlock
|
||||
auto surface = derived()->get_render_target();
|
||||
|
||||
if (prot == utils::protection::no && old_prot != utils::protection::no)
|
||||
{
|
||||
// Locked memory. We have to take ownership of the object in the surface cache as well
|
||||
auto surface = derived()->get_render_target();
|
||||
surface->add_ref();
|
||||
surface->on_lock();
|
||||
}
|
||||
else if (old_prot == utils::protection::no && prot != utils::protection::no)
|
||||
{
|
||||
// Release the surface, the cache can remove it if needed
|
||||
ensure(prot == utils::protection::rw);
|
||||
auto surface = derived()->get_render_target();
|
||||
surface->release();
|
||||
surface->on_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1625,12 +1645,18 @@ namespace rsx
|
||||
ensure(exists());
|
||||
AUDIT(is_locked());
|
||||
|
||||
// If we are fully inside the flush exclusions regions, we just mark ourselves as flushed and return
|
||||
if (get_confirmed_range().inside(flush_exclusions))
|
||||
auto cleanup_flush = [&]()
|
||||
{
|
||||
flushed = true;
|
||||
flush_exclusions.clear();
|
||||
on_flush();
|
||||
};
|
||||
|
||||
// If we are fully inside the flush exclusions regions, we just mark ourselves as flushed and return
|
||||
// We apply the same skip if there is nothing new in the surface data
|
||||
if (!should_flush() || get_confirmed_range().inside(flush_exclusions))
|
||||
{
|
||||
cleanup_flush();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1642,10 +1668,8 @@ namespace rsx
|
||||
|
||||
// Finish up
|
||||
// Its highly likely that this surface will be reused, so we just leave resources in place
|
||||
flushed = true;
|
||||
derived()->finish_flush();
|
||||
flush_exclusions.clear();
|
||||
on_flush();
|
||||
cleanup_flush();
|
||||
}
|
||||
|
||||
void add_flush_exclusion(const address_range& rng)
|
||||
|
||||
+39
-30
@@ -48,11 +48,11 @@ namespace gl
|
||||
case rsx::blend_equation::add: return GL_FUNC_ADD;
|
||||
case rsx::blend_equation::min: return GL_MIN;
|
||||
case rsx::blend_equation::max: return GL_MAX;
|
||||
case rsx::blend_equation::substract: return GL_FUNC_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_substract_signed:
|
||||
case rsx::blend_equation::subtract: return GL_FUNC_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_subtract_signed:
|
||||
rsx_log.trace("blend equation reverse_subtract_signed used. Emulating using FUNC_REVERSE_SUBTRACT");
|
||||
[[fallthrough]];
|
||||
case rsx::blend_equation::reverse_substract: return GL_FUNC_REVERSE_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_subtract: return GL_FUNC_REVERSE_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_add_signed:
|
||||
default:
|
||||
rsx_log.error("Blend equation 0x%X is unimplemented!", static_cast<u32>(op));
|
||||
@@ -210,36 +210,45 @@ void GLGSRender::update_draw_state()
|
||||
gl_state.color_maski(index, color_mask_r, color_mask_g, color_mask_b, color_mask_a);
|
||||
}
|
||||
|
||||
bool mrt_blend_enabled[] =
|
||||
{
|
||||
rsx::method_registers.blend_enabled(),
|
||||
rsx::method_registers.blend_enabled_surface_1(),
|
||||
rsx::method_registers.blend_enabled_surface_2(),
|
||||
rsx::method_registers.blend_enabled_surface_3()
|
||||
};
|
||||
|
||||
if (mrt_blend_enabled[0] || mrt_blend_enabled[1] || mrt_blend_enabled[2] || mrt_blend_enabled[3])
|
||||
{
|
||||
glBlendFuncSeparate(gl::blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_sfactor_a()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_dfactor_a()));
|
||||
|
||||
auto blend_colors = rsx::get_constant_blend_colors();
|
||||
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
|
||||
|
||||
glBlendEquationSeparate(gl::blend_equation(rsx::method_registers.blend_equation_rgb()),
|
||||
gl::blend_equation(rsx::method_registers.blend_equation_a()));
|
||||
}
|
||||
|
||||
gl_state.enablei(mrt_blend_enabled[0], GL_BLEND, 0);
|
||||
gl_state.enablei(mrt_blend_enabled[1], GL_BLEND, 1);
|
||||
gl_state.enablei(mrt_blend_enabled[2], GL_BLEND, 2);
|
||||
gl_state.enablei(mrt_blend_enabled[3], GL_BLEND, 3);
|
||||
|
||||
// LogicOp and Blend are mutually exclusive. If both are enabled, LogicOp takes precedence.
|
||||
// In OpenGL, this behavior is enforced in spec, but let's enforce it at renderer level as well.
|
||||
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
|
||||
{
|
||||
gl_state.logic_op(gl::logic_op(rsx::method_registers.logic_operation()));
|
||||
|
||||
gl_state.enablei(GL_FALSE, GL_BLEND, 0);
|
||||
gl_state.enablei(GL_FALSE, GL_BLEND, 1);
|
||||
gl_state.enablei(GL_FALSE, GL_BLEND, 2);
|
||||
gl_state.enablei(GL_FALSE, GL_BLEND, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool mrt_blend_enabled[] =
|
||||
{
|
||||
rsx::method_registers.blend_enabled(),
|
||||
rsx::method_registers.blend_enabled_surface_1(),
|
||||
rsx::method_registers.blend_enabled_surface_2(),
|
||||
rsx::method_registers.blend_enabled_surface_3()
|
||||
};
|
||||
|
||||
if (mrt_blend_enabled[0] || mrt_blend_enabled[1] || mrt_blend_enabled[2] || mrt_blend_enabled[3])
|
||||
{
|
||||
glBlendFuncSeparate(gl::blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_sfactor_a()),
|
||||
gl::blend_factor(rsx::method_registers.blend_func_dfactor_a()));
|
||||
|
||||
auto blend_colors = rsx::get_constant_blend_colors();
|
||||
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
|
||||
|
||||
glBlendEquationSeparate(gl::blend_equation(rsx::method_registers.blend_equation_rgb()),
|
||||
gl::blend_equation(rsx::method_registers.blend_equation_a()));
|
||||
}
|
||||
|
||||
gl_state.enablei(mrt_blend_enabled[0], GL_BLEND, 0);
|
||||
gl_state.enablei(mrt_blend_enabled[1], GL_BLEND, 1);
|
||||
gl_state.enablei(mrt_blend_enabled[2], GL_BLEND, 2);
|
||||
gl_state.enablei(mrt_blend_enabled[3], GL_BLEND, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,68 +28,50 @@ std::string GLFragmentDecompilerThread::compareFunction(COMPARE f, const std::st
|
||||
|
||||
void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS)
|
||||
{
|
||||
OS << "#version 430\n";
|
||||
int gl_version = 430;
|
||||
std::vector<std::string> required_extensions;
|
||||
|
||||
if (device_props.has_native_half_support)
|
||||
{
|
||||
const auto driver_caps = gl::get_driver_caps();
|
||||
if (driver_caps.NV_gpu_shader5_supported)
|
||||
{
|
||||
OS << "#extension GL_NV_gpu_shader5: require\n";
|
||||
required_extensions.push_back("GL_NV_gpu_shader5");
|
||||
}
|
||||
else if (driver_caps.AMD_gpu_shader_half_float_supported)
|
||||
{
|
||||
OS << "#extension GL_AMD_gpu_shader_half_float: require\n";
|
||||
required_extensions.push_back("GL_AMD_gpu_shader_half_float");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION)
|
||||
{
|
||||
gl_version = std::max(gl_version, 450);
|
||||
required_extensions.push_back("GL_NV_fragment_shader_barycentric");
|
||||
}
|
||||
|
||||
OS << "#version " << gl_version << "\n";
|
||||
for (const auto& ext : required_extensions)
|
||||
{
|
||||
OS << "#extension " << ext << ": require\n";
|
||||
}
|
||||
|
||||
glsl::insert_subheader_block(OS);
|
||||
}
|
||||
|
||||
void GLFragmentDecompilerThread::insertInputs(std::stringstream & OS)
|
||||
{
|
||||
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
||||
{
|
||||
for (const ParamItem& PI : PT.items)
|
||||
glsl::insert_fragment_shader_inputs_block(
|
||||
OS,
|
||||
glsl::extension_flavour::NV,
|
||||
m_prog,
|
||||
m_parr.params[PF_PARAM_IN],
|
||||
{
|
||||
//ssa is defined in the program body and is not a varying type
|
||||
if (PI.name == "ssa") continue;
|
||||
|
||||
const auto reg_location = gl::get_varying_register_location(PI.name);
|
||||
std::string var_name = PI.name;
|
||||
|
||||
if (var_name == "fogc")
|
||||
{
|
||||
var_name = "fog_c";
|
||||
}
|
||||
else if (m_prog.two_sided_lighting)
|
||||
{
|
||||
if (var_name == "diff_color")
|
||||
{
|
||||
var_name = "diff_color0";
|
||||
}
|
||||
else if (var_name == "spec_color")
|
||||
{
|
||||
var_name = "spec_color0";
|
||||
}
|
||||
}
|
||||
|
||||
OS << "layout(location=" << reg_location << ") in vec4 " << var_name << ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_prog.two_sided_lighting)
|
||||
{
|
||||
if (properties.in_register_mask & in_diff_color)
|
||||
{
|
||||
OS << "layout(location=" << gl::get_varying_register_location("diff_color1") << ") in vec4 diff_color1;\n";
|
||||
}
|
||||
|
||||
if (properties.in_register_mask & in_spec_color)
|
||||
{
|
||||
OS << "layout(location=" << gl::get_varying_register_location("spec_color1") << ") in vec4 spec_color1;\n";
|
||||
}
|
||||
}
|
||||
.two_sided_color = !!(properties.in_register_mask & in_diff_color),
|
||||
.two_sided_specular = !!(properties.in_register_mask & in_spec_color)
|
||||
},
|
||||
gl::get_varying_register_location
|
||||
);
|
||||
}
|
||||
|
||||
void GLFragmentDecompilerThread::insertOutputs(std::stringstream & OS)
|
||||
@@ -211,10 +193,10 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
m_shader_props.require_linear_to_srgb = properties.has_pkg;
|
||||
m_shader_props.emulate_coverage_tests = true; // g_cfg.video.antialiasing_level == msaa_level::none;
|
||||
m_shader_props.emulate_shadow_compare = device_props.emulate_depth_compare;
|
||||
m_shader_props.low_precision_tests = ::gl::get_driver_caps().vendor_NVIDIA;
|
||||
m_shader_props.low_precision_tests = ::gl::get_driver_caps().vendor_NVIDIA && !(m_prog.ctrl & RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION);
|
||||
m_shader_props.disable_early_discard = !::gl::get_driver_caps().vendor_NVIDIA;
|
||||
m_shader_props.supports_native_fp16 = device_props.has_native_half_support;
|
||||
m_shader_props.srgb_output_rounding = ::gl::get_driver_caps().vendor_NVIDIA;
|
||||
m_shader_props.ROP_output_rounding = ::gl::get_driver_caps().vendor_NVIDIA;
|
||||
|
||||
glsl::insert_glsl_legacy_function(OS, m_shader_props);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user