Compare commits

...

167 Commits

Author SHA1 Message Date
Ani df718bcb0f rpcs3_version: Bump to 0.0.26 2023-01-07 22:47:41 +00:00
Eladash 8eefbcae45 VSH/UI: Add VSH to game grid
* Custom VSH config.
* VSH shortcut creation.
2023-01-07 22:52:50 +01:00
Megamouse 8cf28730cb Update submodules 2023-01-07 21:50:02 +01:00
Megamouse f894e2b9a2 Qt: Fix open_dir for paths with multiple slashes 2023-01-07 16:07:41 +01:00
Megamouse e3cd31f057 update_manager: Simplify wchar conversion 2023-01-07 16:07:41 +01:00
Foxxcoon 05086cda3b Fix #11126 2023-01-07 16:40:39 +03:00
Elad Ashkenazi 7c2d6f8a23 PKG: Pack multiple PKGs into fast+efficient install (#13147) 2023-01-03 15:31:39 +03:00
kd-11 7423abb136 rsx: Remove incorrect hack 2023-01-02 23:03:39 +03:00
Megamouse 310fa7127d VS: Add SDL dependency to rpcs3 project 2022-12-30 22:02:41 +01:00
Elad Ashkenazi 3250c16cdc Restrict package installation to 1 thread
It is possible that a package contains the same file multiple times.
This leads to possible corruption or installation failure when they are extracted on different threads.
(easy to reproduce with DeS)
2022-12-30 21:10:23 +01:00
Eladash 02f35383bd PKG: Implement Multi-threaded installation 2022-12-30 17:48:14 +03:00
Eladash 1d5fef4930 PKG: Create directories first 2022-12-30 17:48:14 +03:00
Eladash dddea008e9 unedat.cpp: Remove outdated lock 2022-12-30 17:48:14 +03:00
Elad Ashkenazi dd8ec8f09e PKG install hotfix 2022-12-30 17:48:14 +03:00
Megamouse 98dbbd84ac Qt: fix size watcher cancellation on soft refresh
Also setting the cancel flag manually since the canceled signal seems to be very unreliable (I managed to trigger it rarely)
2022-12-30 13:43:55 +01:00
Elad Ashkenazi 382a27cb2f Allow to cancel dir size calculation (#13134) 2022-12-30 09:34:35 +01:00
Nekotekina eeda958f33 fs: fix read/read_at/write (Unix)
It's known that too huge read can require multiple syscalls.
2022-12-29 16:19:54 +03:00
Nekotekina 2f9cac8d18 fs: implement file::read_at
Reads from the given offset; does not seek; thread-safe.
2022-12-29 16:19:54 +03:00
kd-11 9d432187aa vk: Fix bug that made fall-out barriers never get triggered 2022-12-28 17:37:50 +03:00
kd-11 b13165f95a vk/rtts: Account for corner case where the same texture can be bound to more than 1 slot 2022-12-28 17:37:50 +03:00
kd-11 110c20d25f vk: Restructure framebuffer loop barrier management 2022-12-28 17:37:50 +03:00
kd-11 4def7f143c rsx: Fix logicOp behavior when blending is also active 2022-12-27 02:56:43 +03:00
kd-11 908d524631 vk: Add some missing PCI IDs 2022-12-27 02:00:28 +03:00
Megamouse 6c74274502 Qt: fix size_on_disk filetype 2022-12-25 17:16:49 +03:00
Eladash ee8cd82e9d Demote PRX export already loaded error 2022-12-25 16:10:32 +03:00
Eladash 820e692e57 PRX: Implement multi-referenced library management 2022-12-25 16:10:32 +03:00
Megamouse 5b95cfda40 Qt: Improve Check Config utility
Warn if the user selects a weird file.
Allow more file types and show them all by default.
2022-12-22 23:51:32 +01:00
Megamouse b2c4fed39c Qt: stop all async refresh threads on close 2022-12-22 21:47:47 +01:00
Megamouse 96c6dc01eb Qt: Implement config check in Utilities and log viewer 2022-12-22 09:09:51 +01:00
Megamouse f545532556 cellSaveData: add some more info to log error 2022-12-22 09:09:51 +01:00
Megamouse 8ac9968096 Qt: optimize log viewer file loading 2022-12-19 23:18:58 +01:00
Megamouse a9ee9a69a4 Qt: show some more info about the current log viewer state 2022-12-19 23:18:58 +01:00
Megamouse 46a50265a3 Qt: save some log viewer filter settings 2022-12-19 23:18:58 +01:00
kd-11 41e9e0b965 rsx: Restructure color format enum to clearly separate float from int formats 2022-12-19 23:13:25 +03:00
kd-11 388d090b91 rsx: Propagate surface format changes to shader ROP control 2022-12-19 23:13:25 +03:00
Ani 1a60fb3c96 cirrus: Update rpcs3-ci-bionic to 1.6 (#13064) 2022-12-18 16:07:11 +00:00
Elad Ashkenazi baa2768a69 StrUtil.h: Prevent an overflow in strcpy_trunc 2022-12-17 19:55:16 +01:00
kd-11 04fb86556a rsx: Fix surface metadata life-cycle
- Beware of clone operations. Blindly inheriting the parent's metadata is wrong.
- It is possible, especially when reusing a pre-existing slice, that the parent and child info has diverged
2022-12-17 20:16:58 +03:00
kd-11 90cf47cdce rsx: Handle some corner cases in surface locking 2022-12-17 20:16:58 +03:00
kd-11 bf96cbe980 rsx: Fix const RTV/DSV cast from texture cache 2022-12-17 20:16:58 +03:00
kd-11 66dc1cc15d rsx: Conditionally skip flush if no new data was introduced 2022-12-17 20:16:58 +03:00
kd-11 a05e3f02b8 rsx: Avoid expensive protection scan by sharing some data between surface and texture cache 2022-12-17 20:16:58 +03:00
Megamouse 8ec01450f8 Qt: check dir size async 2022-12-17 16:19:22 +01:00
Megamouse b2962e0522 Qt: show item count in category filter 2022-12-17 16:19:22 +01:00
Eladash 8980fc5524 rsx: Fix exceptions 2022-12-17 14:27:20 +01:00
Eladash f54da22f6f UI: Report Game Size On Disk, Make Game Removal An Informed Decision 2022-12-17 12:27:17 +01:00
kd-11 cebc0ec4a1 vk: Add missing memory barrier 2022-12-17 13:10:32 +03:00
brian218 812224f7f7 Stop LV2 Watchdog when CELL_SYSUTIL_REQUEST_EXITGAME is issued 2022-12-15 13:12:40 +03:00
brian218 d78e2dad29 sys_game: Made the LV2 Watchdog restarts the game forcefully 2022-12-15 13:12:40 +03:00
kd-11 7e35679ec2 vk: Revise some TRANSFER->TRANSFER barriers that introduced RAW hazards when copying images 2022-12-14 03:24:37 +03:00
kd-11 b39f457363 vk: Zero-initialize scratch VRAM allocations 2022-12-14 03:24:37 +03:00
Megamouse 18b7955384 SDL handler 2022-12-13 11:56:48 +01:00
Ani 0e625e6928 PSF: Add AS as valid category
Used for some PS3 Applications
2022-12-13 09:34:21 +01:00
brian218 65ae85061f Misc and minor improvements of syscalls used by VSH (#13067) 2022-12-13 07:33:17 +01:00
Megamouse e2c1547d95 Qt: facepalm fix in open_dir 2022-12-12 20:19:07 +01:00
kd-11 2d5a427bd4 gl: Throw exception if we cannot initialize critical requirements 2022-12-12 14:23:06 +03:00
Megamouse 45bd0d1f25 rsx_debugger: fix overflow and some warning 2022-12-11 21:39:18 +01:00
Megamouse f38084f0cf Qt: don't show message if only the rpcs3 games dir shortcut was created 2022-12-11 21:39:18 +01:00
Ani 0d929a210f NP: Disable some logging (#13061) 2022-12-11 16:49:14 +00:00
Megamouse 057f5beac6 Qt: remove cache dir when deleting games 2022-12-11 15:29:01 +01:00
kd-11 26021e11f7 gl: Require GLSL 450 when using barycentric extension 2022-12-11 15:21:58 +03:00
kd-11 941ecc76a1 ci: Update glslang to sdk-1.3.224.1 2022-12-11 15:21:58 +03:00
kd-11 12806af6aa Bump windows vulkan SDK version 2022-12-11 15:21:58 +03:00
kd-11 55886b0a50 gl: Fix shader extension requirements 2022-12-11 15:21:58 +03:00
kd-11 577b5ef2bd Support compiling with older SDK headers 2022-12-11 15:21:58 +03:00
kd-11 780c38a5e5 gl: Silence compiler warning spam 2022-12-11 15:21:58 +03:00
kd-11 6756bf7d4b rsx: Only request attribute interpolation if the GPU requires it and the driver supports it 2022-12-11 15:21:58 +03:00
kd-11 9c0b2338cf rsx: Fix shader compilation 2022-12-11 15:21:58 +03:00
kd-11 a0ef1a672c rsx: Implement interpolation using barycentrics 2022-12-11 15:21:58 +03:00
kd-11 1fd265d316 rsx: Properly flag the program control if needed 2022-12-11 15:21:58 +03:00
kd-11 e3b23822fd rsx: Pass on shader flags to the cache 2022-12-11 15:21:58 +03:00
brian218 ab3c8268f0 sys_sm: Implemented sys_sm_shutdown() (#13048) 2022-12-11 09:10:06 +01:00
Megamouse 6f306121a6 Qt: fix opening folders by using util functions 2022-12-10 22:54:26 +01:00
Megamouse 8399516475 cli: fix title_path 2022-12-10 18:18:16 +01:00
Megamouse a60ea61291 linux: fix shortcut cli args 2022-12-10 18:18:16 +01:00
Megamouse 64cff74861 Qt: simplify shortcut creation 2022-12-10 18:18:16 +01:00
Elad Ashkenazi e2c1e656b9 RSSX Debugger: Do not show invalid color buffers 2022-12-10 16:51:49 +01:00
brian218 cdc1d0c02b sys_fs: sys_fs_get_mount_info(): Made g_mp_sys_dev_root always reported as mounted 2022-12-10 15:28:04 +01:00
Eladash 151a0955cf rsx: Implement draw call stepping 2022-12-10 15:09:42 +01:00
Eladash 40406bd3fe RSX debugger: Implement Texture Dumper
Also fix many bugs in textures display.
2022-12-10 15:09:42 +01:00
Megamouse 1cc3e6e510 cellRec: hotfix for pre-recording 2022-12-10 04:10:40 +01:00
Megamouse 064ab58f3c cellRec: move data instead of memcpy 2022-12-10 03:24:40 +01:00
Megamouse 85c0a2e602 cellRec: add more logging 2022-12-10 03:24:40 +01:00
shinra-electric 809e880bd1 [3rdParty] Update MoltenVK to 1.3.236 & set MSL Fastmath to On Demand (#13035)
* Update MoltenVK to 1.2.236

* Change mvk_config.fastMathEnabled from a bool to Int

fastMathEnabled now has three options:
NEVER = 0
ALWAYS = 1 
ON_DEMAND = 2

On demand seems better, since it will use fast math except for shaders that are incompatible.
2022-12-09 20:49:56 +01:00
Eladash 7df093c94b Make it work with LLVM
Allow multiple entries for a single code.
2022-12-09 21:16:05 +03:00
Eladash f572e29a13 PPU: Add new patch function for SONIC 06 2022-12-09 21:16:05 +03:00
brian218 681a6ef73c Qt: Improved the shown path in overlay message "Recording stopped" 2022-12-09 16:40:38 +01:00
shinra-electric bf37087a10 Fix build errors by changing AVCodec* to a const
...rather than a variable. 

Allows RPCS3 to build on macOS again (Xcode 14.1)
2022-12-09 14:21:37 +03:00
Eladash a18b46d8ad Path hotfix 2022-12-09 12:20:57 +03:00
Eladash 74bb90b414 System.cpp: protect boot arguments 2022-12-09 12:20:57 +03:00
Eladash 8334767c16 GUI: bring relative game shortcut to the GUI 2022-12-09 12:20:57 +03:00
Eladash 0d126afb1f PKG: Ask to user if he wants to install game shortcut on PKG installation 2022-12-09 12:20:57 +03:00
Eladash b7d80ab335 Add support to boot using PS3 game path or TITLEID in CLI and shortcuts
Allowing to move of game directories without having to update the shortcut path. (as long as it is registered within RPCS3 UI).
2022-12-09 12:20:57 +03:00
Megamouse b0e376ae76 rsx/qt: add recording to game window 2022-12-08 21:08:37 +01:00
Megamouse a3bcb6c15a cellRec: implement proper recording
Everything should work mostly. I didn't find a game to test the external input though.
2022-12-08 21:08:37 +01:00
Megamouse 88269636d3 utils: implement video encoder and image sink 2022-12-08 21:08:37 +01:00
Megamouse 4f5076346d Qt: minor camera config warning fixes 2022-12-08 21:08:37 +01:00
Megamouse 89de913e95 Qt: reset screenshot toggle in gs_frame desctructor 2022-12-08 21:08:37 +01:00
Megamouse 0e73c4598e cellVideoExport: fix file paths 2022-12-08 21:08:37 +01:00
Megamouse 6b8aef9fdd cellAdec: fix some uninitialized member warnings 2022-12-08 21:08:37 +01:00
Jan Beich 1811dd67bf CI: switch FreeBSD to Clang/libc++ 15 2022-12-08 19:36:12 +01:00
brian218 6d4379059c sys_fs: Integrated get_mount_count() into sys_fs_get_mount_info_size() 2022-12-08 18:31:46 +01:00
brian218 a0f3704b41 sys_fs: Integrated the function of get_vfs() into get_mp() 2022-12-08 18:31:46 +01:00
brian218 9274b3f14d USIO: Fixed "Card Reader Not Connected" Error 2022-12-07 20:20:52 +01:00
brian218 0a3e540a10 sys_fs: get_vfs() minor fixup 2022-12-07 20:20:52 +01:00
Megamouse 4657afd899 Qt: remove entire cache dir of a serial on remove all caches 2022-12-07 18:55:56 +01:00
Megamouse 2082f06443 Qt: remove empty cache dirs if possible 2022-12-07 18:55:56 +01:00
Megamouse b49f8623f6 Windows: Check WSAStartup result 2022-12-07 18:11:01 +01:00
Megamouse 69e4138223 Try to fix dll checks 2022-12-07 00:00:45 +01:00
Elad Ashkenazi 5fec8666e3 Dont append main thread's ID on fatal error dialog (#13021) 2022-12-06 22:18:26 +01:00
Megamouse 8af4a94864 Qt: add context menu to trophy game table 2022-12-06 21:30:08 +01:00
Megamouse ab873129f8 Qt: add copy name and description to trophy context menu 2022-12-06 21:30:08 +01:00
kd-11 6155207407 ux: Instruct the user to delete the dlls from the installation folder. 2022-12-06 20:46:35 +01:00
kd-11 98a58daf57 Fix build 2022-12-06 20:46:35 +01:00
kd-11 0aaa40cd53 ux: Update vcredist links and optionally disable help text from error dialog 2022-12-06 20:46:35 +01:00
Megamouse a6b44ea1bb Qt: support fatal error as htmk 2022-12-06 20:46:35 +01:00
kd-11 ca0ca2e5a8 ux/core: Add module verification step for some critical libraries
- Prevents running the emu with downloaded dll files
2022-12-06 20:46:35 +01:00
RipleyTom 14a388b3fe Increase max number of skylanders to 8 2022-12-06 18:14:58 +01:00
Eladash 82a8d96fba sys_fs hotfix
Co-Authored-By: brian218 <17809637+brian218@users.noreply.github.com>
2022-12-03 17:53:39 +01:00
Elad Ashkenazi ad3ea966cb Add RPCS3/games/ for automatic games detection, support PSN games outside HDD0 (#12982)
* SFO: Do not load PARAM.SFO with illegal TITLE_ID
* Add support for PSN games outside HDD0
* Add RPCS3/games/ for automatic game detection
2022-12-02 13:18:07 +03:00
brian218 8d9dd1d19c Implemented sys_fs_newfs() 2022-12-02 08:18:46 +01:00
Megamouse 337ee77a99 evdev_gun: "fix" BSD 2022-11-30 19:38:42 +01:00
Megamouse c09991ebdb evdev_gun: convert udev code to evdev 2022-11-30 19:38:42 +01:00
Megamouse 5188293242 evdev gun support cleanup 2022-11-30 19:38:42 +01:00
Nicolas Adenis-Lamarre 2805fe0a06 evdev gun support
supports guns via evdev. multiple guns.
extra buttons are configurable (guns can be configured for that).

Signed-off-by: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
2022-11-30 19:38:42 +01:00
Team XLink Developers b4757b514d Add ability to have sockets bind to a local IP address (#12998) 2022-11-30 18:35:42 +03:00
Elad Ashkenazi 630edde10f logs.cpp: fix regression (#12995)
Fixes #12994
2022-11-29 22:56:18 +03:00
Eladash e9e139c364 logs improvements
* Do not use unsafe pointer arithmetics exceeding existing memory. (exceeding m_fptr)
* Properly use the enire 32MB of the buffer, previously only 16MB were used for cuncurrent access.
* Fix a bug occurring after attempting to push 1TB (40 bits).
* Flush the log before hitting a debugging breakpoint.
2022-11-28 18:52:11 +03:00
Julien Reichardt 60c01ef9a9 Use uppercase RPCS3 name in the metainfo file 2022-11-28 06:20:48 +03:00
Megamouse 5dbadccd7f Log PSF path on error 2022-11-27 22:07:15 +01:00
Megamouse 49a968219f Silence some usually irrelevant errors 2022-11-27 22:07:15 +01:00
Eladash 8b934abcf2 Improve error_code, make HDD1 errors be warnings 2022-11-26 16:33:47 +03:00
Nekotekina fa74d3e88c vm: implement lock-free try_access with range locking 2022-11-26 09:30:11 +03:00
Nekotekina 1123e25136 Implement ref_ptr (see read_from_ptr)
Type `aref`: reference wrapper
2022-11-26 09:30:11 +03:00
Nekotekina 7c15001042 Implement read_from_ptr<>() util
Doing std::bit_cast on a "span".
Should be usable in constexpr.
2022-11-26 09:30:11 +03:00
Nekotekina bf388e5428 cfmt/StrFmt: support s128 formatting (untested) 2022-11-26 09:30:11 +03:00
Paweł Kotiuk 661be41c5a Update AppStream Metadata
Add some fields according to specification from https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html
2022-11-24 20:45:04 +01:00
kd-11 8be4ac6869 gl: Fix rotation operations in blit engine 2022-11-22 12:15:18 +03:00
kd-11 81f9259063 gl: Add support for capture debug markers 2022-11-22 12:15:18 +03:00
kd-11 a97424d46c rsx: Fix low precision shader option 2022-11-22 12:15:18 +03:00
brian218 b639f3c8ec Fixed up lv2_fs_mount_point stuff & Fixed loop.tmp potential leak 2022-11-19 10:42:49 +01:00
brian218 13ca1a7f09 Further implemented sys_fs_get_mount_info() and sys_fs_get_mount_info_size() 2022-11-19 10:42:49 +01:00
brian218 16098c38c8 sys_ss_appliance_info_manager(): Fixed VSH error 80029567 and 80029564 2022-11-19 10:42:49 +01:00
kd-11 c4b259e0f8 rsx: Always enable ROP output quantization on NV 2022-11-18 23:06:47 +03:00
kd-11 e04855a0da rsx: Improve ROP output handling
- Perform 8-bit quantization/rounding before emulated operations like ALPHA_TEST
2022-11-18 23:06:47 +03:00
Megamouse 8199f97e7a Qt: add option to automatically resize the game window 2022-11-17 19:58:18 +01:00
Megamouse 2eef3ab645 Update glslang and SPIRV from sdk-1.3.224.1 to sdk-1.3.231.0 2022-11-17 16:04:18 +01:00
Megamouse d56ec56458 Update wolfssl from v5.4.0 to v5.5.0 2022-11-17 16:04:18 +01:00
Megamouse 0293415db1 Update curl from 7.84 to 7.86 2022-11-17 16:04:18 +01:00
Megamouse 6e935d9d84 Update pugixml from v1.12.1 to v1.13 2022-11-17 16:04:18 +01:00
Elad Ashkenazi 99ae561caa cellPad: Noise-cancelling log changes (#12958) 2022-11-16 20:00:22 +01:00
MSuih 3f8421fc17 Add enable exclusive fullscreen mode setting 2022-11-14 17:50:13 +01:00
Megamouse 324b1039cf set cellVideoOutSetGamma to trace
It is spammed a lot in some games and we already know it works.
2022-11-12 11:23:58 +03:00
Megamouse 961d905433 Loader: disable unsupported PPU decoder settings 2022-11-12 11:23:58 +03:00
Megamouse 3c79f3943f Minor simplifcation in ppu_finalize 2022-11-12 11:23:58 +03:00
Megamouse 1e7b2c052a Loader: skip savestate check in add_only mode 2022-11-12 11:23:58 +03:00
Megamouse ff082b98cb VS: fix compilation on VS 17.4 2022-11-12 11:23:58 +03:00
kd-11 3236931416 Whitespace fix only 2022-11-11 12:09:23 +03:00
kd-11 ed0c798252 Wait for renderer to initialize before skipping it for system progress initialization. 2022-11-11 12:09:23 +03:00
kd-11 5943b802d7 grammar 2022-11-11 12:09:23 +03:00
Eladash b875a86e1d PRX: export functions on start() 2022-11-09 02:28:12 +03:00
Eladash 0a35a62235 sys_prx: Make PPU imports/exports thread-safe 2022-11-09 02:28:12 +03:00
kd-11 e98b07de03 vk: Set line width when rasterizing points (workaround)
- Fixes point rendering when using AMD drivers.
2022-11-07 23:12:31 +03:00
kd-11 de5217745c gl: Fix point size export 2022-11-07 23:12:31 +03:00
RipleyTom ec53adc2b7 Fix get_member_and_attrs 2022-11-07 12:31:18 +01:00
Eladash b57ab74ee7 cfg: Partial support for case-insensitivity for true-false settings 2022-11-05 10:36:46 +01:00
Eladash 69368d972d Savestates: Move "Start Paused" setting to UI 2022-11-05 10:36:46 +01:00
226 changed files with 10164 additions and 1905 deletions
+5 -3
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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 \
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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:
+4
View File
@@ -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
+25 -2
View File
@@ -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})
+1 -1
View File
@@ -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
+9 -3
View File
@@ -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
View File
@@ -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">
+11
View File
@@ -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)
Vendored Submodule
+1
Submodule 3rdparty/libsdl-org/SDL added at f070c83a60
+461
View File
@@ -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
View File
@@ -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>
+2 -2
View File
@@ -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.**
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+30 -22
View File
@@ -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
+2
View File
@@ -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
)
-5
View File
@@ -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);
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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;
};
+4 -1
View File
@@ -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
View File
@@ -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)
{
}
+58
View File
@@ -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);
});
+1 -1
View File
@@ -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));
+11 -15
View File
@@ -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)
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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)
{
+7 -7
View File
@@ -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());
+4 -4
View File
@@ -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;
}
+181 -65
View File
@@ -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");
}
}
+2 -2
View File
@@ -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
}
+2 -2
View File
@@ -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;
}
+3 -3
View File
@@ -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)
+5 -5
View File
@@ -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());
+8 -8
View File
@@ -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
+1 -1
View File
@@ -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,
+5 -5
View File
@@ -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)
{
+5
View File
@@ -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)
{
+2 -2
View File
@@ -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))
{
+2 -2
View File
@@ -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
View File
@@ -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())
{
+2 -1
View File
@@ -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
View File
@@ -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;
}
+1 -1
View File
@@ -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
View File
@@ -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;
+8 -5
View File
@@ -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);
+10 -1
View File
@@ -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);
+2
View File
@@ -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));
+7
View File
@@ -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]);
+1
View File
@@ -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
View File
@@ -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
{
+25 -14
View File
@@ -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&) {}
+45 -2
View File
@@ -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;
}
+2 -1
View File
@@ -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;
+16 -10
View File
@@ -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:
{
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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;
};
+5 -5
View File
@@ -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
+3 -2
View File
@@ -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
{
}
+3
View File
@@ -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
+3
View File
@@ -13,6 +13,9 @@ enum class pad_handler
xinput,
mm,
#endif
#ifdef HAVE_SDL2
sdl,
#endif
#ifdef HAVE_LIBEVDEV
evdev,
#endif
+44
View File
@@ -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);
}
}
+23
View File
@@ -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
View File
@@ -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
View File
@@ -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, ""};
+9 -2
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -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{};
+4 -4
View File
@@ -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);
+1 -1
View File
@@ -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)
{
+10
View File
@@ -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);
}
};
}
+10 -11
View File
@@ -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:
+80 -3
View File
@@ -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);
}
};
}
+1
View File
@@ -583,6 +583,7 @@ namespace rsx
}
data.flushed = true;
update_cache_tag();
}
+33 -9
View File
@@ -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
View File
@@ -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 -46
View File
@@ -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