Compare commits

..

554 Commits

Author SHA1 Message Date
Ani 09a9d08466 rpcs3_version: Bump to 0.0.13 (#9192) 2020-11-02 20:20:12 +00:00
Nekotekina 1b8bf081b5 Upgrade to LLVM 11 Stable 2020-11-02 21:23:25 +03:00
Nekotekina 06ecc2ae68 vm::range_lock cleanup and minor optimization
Removed unused arg.
Linearized some branches.
2020-11-01 23:29:33 +03:00
Nekotekina 46d3066c62 Optimize vm::range_lock
Only test address on `range_locked`
Don't check current transaction
Remove vm::clear_range_locks completely
2020-11-01 16:46:06 +03:00
Nekotekina 8d12816001 TSX: fix transaction limit settings 2020-11-01 14:58:04 +03:00
Nekotekina fe03b55046 TSX: tiny optimization of transaction functions
Because new memory manager puts them in first 2G.
2020-11-01 14:44:59 +03:00
Nekotekina ca57f25f26 Fix vm::page_protect and range flags
Should fix assertion in vm.cpp
Minor refactoring of internal locking
2020-11-01 02:30:10 +03:00
Eladash 3c639ff8e1 SPU: Fix Accurate DMA edge case 2020-11-01 00:35:48 +03:00
Nekotekina 78c986b5dd Improve vm::range_lock
Not sure how it ever worked
Clear redundant vm::clear_range_lock usage
2020-10-31 23:53:14 +03:00
Megamouse a42663b09b Qt: Pass events to dialog when not remapping 2020-10-31 20:44:09 +01:00
Megamouse 36149fd986 overlays: kinda fix performance graph margins (#9181) 2020-10-31 16:32:31 +00:00
Eladash c2c559f8d9 Disasm: do not allow to access previous instructions in non-interpreter mode 2020-10-31 17:15:47 +03:00
Eladash 5e8419af0d SPU Debugger: SHUFB insertion patterns 2020-10-31 17:15:47 +03:00
Nekotekina 86fc842c89 TSX: new fallback method (time-based)
Basically, using timestamp counter.
Rewritten vm::reservation_op with the same principle.
Rewritten another transaction helper.
Add two new settings for configuring fallbacks.
Two limits are specified in nanoseconds (first and second).
Fix PUTLLC reload logic (prevent reusing garbage).
2020-10-31 15:34:14 +03:00
Nekotekina 80530e8aef vm: rename g_addr_lock to g_range_lock
Reduce size to 29 bits and use 3 bits to communicate some information.
This information can be used to to a very cheap lock-free access tests.
2020-10-31 15:08:49 +03:00
Nekotekina ba26e16411 Rename vm::reservation_light_op -> light_op
Rename vm::reservation_peek_op -> peek_op
Also remove overkill assertion for cpu_flag::temp.
2020-10-31 15:08:49 +03:00
Megamouse 2cee26c3e7 Cleanup some includes 2020-10-31 11:53:46 +01:00
Megamouse 5d55e509ec cellSubDisplay: Add some constants (#9178) 2020-10-31 01:40:38 +00:00
Megamouse 4984e87776 implement interception for cellKb and cellMouse
this needs to be tested
2020-10-31 02:11:27 +03:00
Megamouse c65b7d0aea HLE: Add some constants 2020-10-31 02:11:27 +03:00
Megamouse 54fd224fd8 Add License Area Setting 2020-10-31 02:10:30 +03:00
Megamouse 5ca2b1200d Qt: Fix Resolution combobox default value 2020-10-31 02:08:42 +03:00
Eladash b5014d56ab rsx: Fix transform contants load 2020-10-31 02:08:03 +03:00
Nekotekina c4e89f8bb4 Actually start rsx replay thread 2020-10-30 22:25:33 +03:00
Nekotekina 7dd85b207f vm: optimize range lock slot allocations
Doesn't seem to need a barrier.
2020-10-30 22:20:20 +03:00
Nekotekina cb0431d960 sys_fs/sys_usbd: add cpu_flag::wait 2020-10-30 20:14:32 +03:00
Nekotekina 58adb6a1aa sys_ppu_thread: add cpu_flag::wait 2020-10-30 18:27:15 +03:00
Nekotekina 13c564f2af sys_memory: add cpu_flag::wait 2020-10-30 18:09:30 +03:00
Nekotekina 95aeebe4b5 sys_rsx: add cpu_flag::wait 2020-10-30 18:00:25 +03:00
Nekotekina 605d57c541 sys_event: cleanup (replace vm::temporary_unlock)
Also made minor changes in sys_rsx.cpp.
Removed unused exception std headers.
2020-10-30 17:49:07 +03:00
Nekotekina f972fa26a4 Derive RSX Replay thread from cpu_thread
Its id is set to 0, so fix some id_type() usages.
2020-10-30 17:36:11 +03:00
Nekotekina 150e18539c Allow cpu_thread& arg passed to the syscalls
Minor cleanup. cpu_mem(), cpu_unmem() removed.
2020-10-30 17:03:32 +03:00
Eladash f03d4cf8fd PPU: Optimize reservation load for success 2020-10-30 10:49:47 +02:00
Nekotekina 3419d15878 vm: add extern clear_range_locks function
Allows to wait for range locks to clear for specified range.
vm::range_lock now monitors specified reservation lock as well.
2020-10-30 07:58:16 +03:00
Nekotekina 0da24f21d6 CPU: improve cpu_thread::suspend_all for cache efficiency (TSX)
Add prefetch hint list parameter.
Workloads may be executed by another thread on another CPU core.
It means they may benefit from directly prefetching the data as hinted.
Also implement mov_rdata_nt, for "streaming" data from such workloads.
2020-10-30 05:22:09 +03:00
Nekotekina e794109a67 perf_meter.hpp: fix double rdtsc bug, add restart() method 2020-10-30 03:19:13 +03:00
Nekotekina 006c783aba SPU: make do_dma_transfer() static with _this arg
Instead of this, nullptr will be passed from another thread.
MMIO via MMIO is disabled if it even possible.
2020-10-30 02:58:39 +03:00
Nekotekina 4378a09867 PPU: reload old data on STCX failure
In 128-byte reservation mode, it can reload the whole cache line.
2020-10-30 02:58:39 +03:00
Nekotekina fb24b06a5d PPU: add LARX perf counter
Also refactor ppu_store_reservation a bit.
2020-10-30 02:58:39 +03:00
Nekotekina 425fce5070 SPU: load previous data on PUTLLC failure
Since it will most likely execute GETLLAR to load it again.
Only implemented for TSX at moment.
2020-10-30 02:58:39 +03:00
Nekotekina d5667a859a CPU: improve cpu_thread::suspend_all (TSX)
Try to make more clever busy-waiting on cpu_flag::pause.
2020-10-30 02:58:39 +03:00
Nekotekina 95dbcf2fd7 Logs: add callback for cpu_thread to set cpu_flag::wait
May improve waiting time in critical suspend_all ops.
2020-10-29 18:57:57 +03:00
Nekotekina 8ce0819b42 SPU: add stx/ftx counters
Just count pure transaction successes and failures.
2020-10-29 18:57:57 +03:00
Nekotekina 688a456642 TSX tweaks
Allow to do more in first-chance transactions.
Give PUTLLC +1 priority (minor change).
2020-10-29 18:57:57 +03:00
Megamouse 59b3a3d26b Qt: Add "Configure Game Patches" to game list (#9154) 2020-10-29 06:02:05 +00:00
Ani ea1cdbfdd8 ci: Update docker to 1.6
Bumps Windows VulkanSDK version to 1.2.154.1 to stay synchronised with
docker
2020-10-29 03:57:39 +00:00
Ani 3641926333 ci: Use system cURL on Linux build 2020-10-29 03:57:39 +00:00
Nekotekina 280958ee74 Revert "TSX: adjust transaction logic"
This reverts commit ff550b5c3c.
2020-10-28 21:59:12 +03:00
Bevan Weiss f4070731a8 NET: Add SO_RCVBUF / SO_SNDBUF defaults to .._bnet_socket
The OS defaults for SO_RCVBUF / SO_SNDBUF may not match what the defaults for the PS3 are.
And the code may be happy with the PS3 defaults, so may not set this explicitly.
So we'll do it when we establish the socket.
It also looks like the Windows recv behaviour is different for the MSG_PEEK option (and possibly in all situations where a smaller buffer is provided). I believe other platforms will return the size of the data received into the socket buffer, even if the supplied user buffer is smaller. Windows returns WSAEMSGSIZE instead. For the length of '1' MSG_PEEK request that is currently seen, we just mask this and return the full size of the buffer. This might need to be the case in all situations, I assume there will be applications that will supply an artificially small buffer and resize it as necessary based on the size of the received packet.
Add some additional translations from native->PS3 error codes

Rewrote handling of MSG_PEEK to just be a copy of what GalCiv suggested
Added WSAESHUTDOWN, and WSASetLastError as done by Cygwin
2020-10-28 20:54:29 +03:00
Eladash e791678dfc atomic.cpp: fix memory ordering loads and release stores 2020-10-28 20:45:13 +03:00
RipleyTom 6f5bbf550a Revert part of CellHddGameCheck 2020-10-28 20:44:38 +03:00
Nekotekina ff550b5c3c TSX: adjust transaction logic
Allow more in first-chance transactions.
Allow abandonment of PUTLLC as in original path.
Make PUTLLUC unconditionally shared-locked.
Give PUTLLC +1 priority (minor change).
2020-10-28 14:00:09 +03:00
Nekotekina d6daa0d05b Fix cpu_flag::temp, make sure it removes cpu_flag::wait 2020-10-28 14:00:09 +03:00
Nekotekina 86785dffa4 SPU: make vm::check_addr checks safe under vm::range_lock
Reuse some internal locking mechanisms.
Also fix vm::range_lock missing check.
2020-10-28 14:00:09 +03:00
Nekotekina c491b73f3a SPU: improve accurate DMA
Remove vm::reservation_lock from it.
Use lock bits to prevent memory clobbering in GETLLAR.
Improve u128 for MSVC since it's used for bitlocking.
Improve 128 bit atomics for the same reason.
Improve vm::reservation_op and friends.
2020-10-28 03:47:41 +03:00
Nekotekina c50233cc92 atomics.cpp: add support for waiting on 128-bit atomics
Complementarily.
Also refactored to make waiting mask non-template arg.
2020-10-28 03:47:41 +03:00
Nekotekina 13de773486 Remove some vm::reservation_lock instances 2020-10-27 17:56:19 +03:00
Nekotekina 4966f6de73 vm: improve range_lock and shareable cache (Non-TSX)
Allocate "personal" range lock variable for each spu_thread.
Switch from reservation_lock to range lock for all stores.
Detect actual memory mirrors in shareable cache setup logic.
2020-10-27 17:56:19 +03:00
Nekotekina 6806e3d5c7 atomic.cpp: implement notify callback
Notification can be very heavy, especially if we need to wake many threads.
Callback is set for cpu_thread in order to set wait flag accordingly.
2020-10-27 17:56:19 +03:00
Megamouse 0a121e9d26 DS4: Add error logging and remove some unused code 2020-10-27 15:25:08 +01:00
Megamouse 15e8cba398 Qt: fix never played nonsense 2020-10-27 12:50:43 +01:00
kd-11 b32eecb5a7 rsx: Driver compatibility improvements (#9131)
* rsx: Refactor vertex clip emit to avoid using f64 unnecessarily

- Fixes driver crash on intel

* vk: Add NVIDIA driver version check

- Warn if user has outdated drivers with known problems
2020-10-27 13:22:15 +03:00
Megamouse 8ce0eaa9d0 Qt: move TTY option to TTY tab (#9147) 2020-10-27 02:47:07 +00:00
Ani 8307f82f86 ci: Set glslang checksum back to auto-builds
Forgot to set on #9124
2020-10-26 06:16:08 +03:00
Cebtenzzre 2b6a56c21c Partially revert "Fix debug build gcc/clang linker."
This reverts commit 4599d58413.

The issue this works around was fixed in 3265772 ("idm: Implement
creation/destruction invalidation counter") by making the variables
constexpr.

Fixes #6896
2020-10-26 04:12:04 +03:00
Nekotekina f1e66085cd Fixup for cpu_flag::temp
Wrong check_state() result was triggering assertion.
2020-10-26 01:18:26 +03:00
Nekotekina d344701fd5 atomic.cpp: add sparse atomics
Set alignment as second template argument (typically cache line).
2020-10-26 01:15:31 +03:00
Nekotekina 130a0ef20e Implement cpu_flag::temp flag
Accompanies wait flag, indicating that it was set in limited conditions.
Such condition don't allow thread to terminate after its removal.
2020-10-25 21:48:20 +03:00
kd-11 18ca3ed449 rsx: Block-level reservation access 2020-10-25 20:21:04 +03:00
Nekotekina af6fcb19a8 atomic.cpp: add std primitive fallback for other platforms
Other platforms = not Windows or Linux.
2020-10-25 16:45:22 +03:00
Ani eec2dfad7b ci: Set GLSLANG_URL back to auto-builds 2020-10-25 16:44:06 +03:00
Eladash 0fcf767ee9 SPURS: Implement spursJobchainPopUrgentCommand 2020-10-25 16:43:38 +03:00
Eladash 1e7bf218e0 CellSpurs: Minor fixes 2020-10-25 16:43:38 +03:00
Eladash 4ea7628204 SPU: Fix LS capture entry point 2020-10-25 16:39:40 +03:00
Nekotekina 7db77a5580 atomic.cpp: use new thread alerting API (Win8+)
Win7 will remain using old API (keyed events).
2020-10-24 19:06:02 +03:00
Nekotekina 97ae5ab561 Add imports for some undocumented NTDLL functions
Some of them are available only since Windows 8.
2020-10-24 14:16:32 +03:00
Nekotekina 89d9813a45 Fix UTF-8 strings in perf_meter files 2020-10-24 14:16:32 +03:00
Nekotekina 2b52b4a749 SPU: use normal notify() thread function
Using raw_notify() everywhere was overkill.
2020-10-24 14:16:32 +03:00
Nekotekina c479d431a4 atomic.cpp: experimental optimization (Win7+)
Try non-blocking wake up function first.
2020-10-24 14:16:32 +03:00
Nekotekina 8628fc441d atomic.cpp: rewrite internals (again)
Use individual semaphore for each thread.
Unfortunately, limit max thread waiting for single address (60).
If limit is reached, use busy waiting.
2020-10-24 14:16:32 +03:00
Nekotekina d48d67767a atomic.cpp: integrate callback check in ptr_cmp function 2020-10-24 14:16:32 +03:00
Nekotekina 10caa2981f Improve raw_notify a bit 2020-10-24 14:16:32 +03:00
Eladash 49610f52f5 SPU: Save LS capture executable in one segment 2020-10-24 14:13:19 +03:00
Megamouse 27643cb715 HLE: improve cellHddGameCheck 2020-10-24 00:26:41 +03:00
Megamouse fe3c7926f7 Qt: add custom game icons
This shouldn't interfere with emulation as replacing actual files would
2020-10-23 23:13:22 +02:00
Eladash 552d8e6aec Debugger: Fix SignedHex
It didnt take into account INTx_MIN. (UB for std::abs)
2020-10-23 13:13:04 +03:00
Eladash 0bb3609cad Debugger: Simplify thread pause state change 2020-10-23 13:13:04 +03:00
Eladash b56bc7e087 SPU: cleanup channels logging 2020-10-23 13:13:04 +03:00
Eladash abcf265bc7 SPU Debugger: Implement basic instructions's constants propagation
Only functional in WRCH and ILHU+IOHL pattern atm.
ILHU+IOHL is extremely common pattern to create 32-bit constants such as SPPU libraries error codes.
2020-10-23 13:13:04 +03:00
Eladash 6d3c421823 Debugger: Optimize thread disasm type select
Some correctness fixes as well: dont use raw pointers where its not compatible, use std::weak_ptr instead.
2020-10-23 13:13:04 +03:00
Eladash e70f430b5a SPU Debugger: Add made-up MR mnemonic 2020-10-23 13:13:04 +03:00
Eladash 8c927d3cc8 kernel-explorer: Add SPURS wkl arg 2020-10-23 13:13:04 +03:00
Eladash b998852385 LV2: cleanup syscall table (#9106)
Remove old ppu_get_syscall_name from PPUFunction.cpp for deduplication.
2020-10-21 10:04:34 +03:00
Nekotekina 59d9e7ce98 Revert "Atomics: use WaitOnAddress if available (Win8+)"
This reverts commit f0fd7e2e19.
2020-10-21 09:59:08 +03:00
Nekotekina 306593a0c5 Revert "atomic.cpp: fixup for WaitOnAddress path"
This reverts commit 3b8bce1bed.
2020-10-21 09:54:22 +03:00
Nekotekina 3b8bce1bed atomic.cpp: fixup for WaitOnAddress path
Also fix wait quantum.
2020-10-21 08:18:27 +03:00
Nekotekina f0fd7e2e19 Atomics: use WaitOnAddress if available (Win8+) 2020-10-21 00:22:08 +03:00
Nekotekina 4384ae15b4 Improve vm::reservation_op
Remove XABORT, sync status handling with SPU/PPU transaction.
Limit max number of transaction attempts in loop.
Add Ack template parameter, as in vm::reservation_light_op.
Remove utils::tx_abort, improve utils::tx_start as well.
2020-10-20 09:10:21 +03:00
Nekotekina dc8252bb9f Remove XABORT in PPU/SPU transactions.
It's expensive for unknown reason. Simply XEND is usually much cheaper.
Add some minor improvements. Use g_sudo_addr.
2020-10-20 09:10:21 +03:00
Nekotekina 182a998cb6 Add "Enable Performance Report" debug setting 2020-10-20 07:09:24 +03:00
Nekotekina ea8e435b32 Fixup for perf_meter.hpp
Don't try to push reports if they are empty.
2020-10-19 21:25:42 +03:00
Nekotekina 72d1ac22aa SPU: report too many PUTLLC attempts (TSX)
Mirrored to PPU STCX code and PUTLLUC (STORE128).
2020-10-19 19:41:28 +03:00
Nekotekina 8ce5392390 TSX: add prefetchw instruction in transaction code 2020-10-19 19:41:28 +03:00
Nekotekina 311682b341 SPU: fix GETLLAR regression
Misplaced mov_rdata
2020-10-19 19:41:28 +03:00
Nekotekina 44c90c060a TSX: improve transaction repeat handling
Handle status 0 as fatal.
2020-10-19 19:41:28 +03:00
Nekotekina a5eb11d79f Improve cpu_thread::suspend_all (TSX-FA)
Add prefetching of cpu->state fields.
2020-10-19 19:41:28 +03:00
Nekotekina 120849c734 Implement perf stat counter for PPU/SPU reservation ops
Adds Emu/perf_meter.hpp header file.
Uses RDTSC for speed.
Prints stats at exit.
2020-10-19 19:41:28 +03:00
Nekotekina adf50b7c4b Implement cpu_thread::if_suspended
Use it for opportunistic guaranteed GETLLAR execution (TSX-FA).
2020-10-18 20:10:48 +03:00
Nekotekina f5c575961f Implement priorities for cpu_thread::suspend_all tasks
Give PUTLLUC increased priority.
2020-10-18 20:10:48 +03:00
kd-11 a90801e2aa vk: Add VK_FORMAT_D32_SFLOAT to format conversion table
- This format is required to emulate RSX_FORMAT_CLASS_D16_FLOAT
2020-10-18 19:30:40 +03:00
Eladash 402e8b12a6 SPU: Touch unmapoed memory in reservation mismatch 2020-10-18 11:42:54 +03:00
Eladash 701f7f39d6 Improve SPURS debugger (#9090) 2020-10-18 11:07:01 +03:00
Eladash 6590366f8e PPU Debugger: fix typo in STDX 2020-10-17 22:00:22 +03:00
Eladash fa0b02ed30 PPU Debugger: Improve move from/to CR registers instructions 2020-10-17 22:00:22 +03:00
Nekotekina 15efb73aae Add assert in build_function_asm to not ignore errors 2020-10-17 21:55:22 +03:00
Nekotekina d0057c92e4 Fix spu_putlluc_tx (insignificant) 2020-10-17 21:27:19 +03:00
Nekotekina 4078f43984 Fix ppu_stcx_accurate_tx (operand size mismatch) 2020-10-17 21:26:17 +03:00
Nekotekina 3d980a9f66 Reimplement ASMJIT runtime
Try to emplace generated code in lower address area.
Protect generated code from writing.
2020-10-17 21:25:43 +03:00
Bevan Weiss a0d95a823e BUGFIX: LibUSB Transfer list deletion (#9084)
It looks like I was too hasty in picking the latest libusb commit (to fix a few Windows build warnings) prior to landing my merged PR.
libusb commit eee6998 had a transfer list bug.  Have just tested on c33990a and it's resolved now.
2020-10-17 13:41:59 +01:00
RipleyTom 9e14d240a8 Implement ethernet address determination 2020-10-16 22:53:48 +03:00
RipleyTom 1393bb2caf Fix getsockname on windows for unbound sockets 2020-10-16 22:53:48 +03:00
RipleyTom e9914f3004 Add sys_net error for EISCONN 2020-10-16 22:53:48 +03:00
RipleyTom 073772a801 Fixes setsockopt 2020-10-16 22:53:48 +03:00
RipleyTom 2babe4c236 Add better handling of RTT for STREAM_P2P 2020-10-16 22:53:48 +03:00
RipleyTom bbda618beb Improve poll for p2p sockets 2020-10-16 22:53:48 +03:00
RipleyTom 344c813eb1 Avoid double locking with start_sig 2020-10-16 22:53:48 +03:00
RipleyTom abaa8f855f sceNpManagerGetAccountRegion impl 2020-10-16 22:53:48 +03:00
RipleyTom ea1171f624 Add notification logging 2020-10-16 22:53:48 +03:00
Bevan Weiss 1e83d2a4e9 LibUSB: Update to upstream master (and turn off YAML_CPP_INSTALL CMake property)
May resolve some outstanding issues around libusb/hidapi (i.e. DS4 not being released on rpcs3 shutdown etc..) or may not.
Fixes three outstanding compile warnings on non-Windows OS... introduces a few more warnings in WindowsOS (issue raised upstream with libusb around WINAPI_CHECK macro)
Re-ordered the 3rd party CMake so libusb is in file order above hidapi (just to have document flow match logical flow)

Also took this opportunity to remove the YAML INSTALL action (by setting YAML_CPP_INSTALL to OFF)
Provided capability to use system library for libusb by providing USE_SYS_LIBUSB option to CMAKE

Tested under:
- [X] Windows 10 2004 OS with DS4 controller
- [X] Windows 10 2004 OS with GCon3 controller
- [X] Linux (Mint 20) with DS4 controller
2020-10-16 22:51:52 +03:00
Eladash 443c2b920d PPU: Handle cache line inconsistencies (PPU 128 reservations) 2020-10-16 22:51:30 +03:00
Eladash 953663e00b Fix ppu_execute<Func> for HLE functions 2020-10-16 22:48:02 +03:00
Eladash 5185ddb8b5 CellSpurs: JobChain functions and some more (#9080) 2020-10-16 18:35:20 +01:00
Nekotekina 583ed61712 SPU: return some give-up behaviour for PUTLLC (TSX)
Despite using concept of "shared" lock, allow only first to proceed.
This is similar how conditional stores for PPU are implemented.
2020-10-16 12:14:42 +03:00
Nekotekina 492ed27495 RSX: fix rsx::nv406e::semaphore_release partially
Properly release reservation (non-TSX path).
At least update and notify reservation (TSX).
2020-10-15 20:58:59 +03:00
Nekotekina facde63460 PPU: fix ppu_stcx_accurate_tx
Don't destroy xmm6/xmm7 state on exit.
Improve addr arg handling (simplify).
2020-10-15 19:24:00 +03:00
Nekotekina 494953997e PPU/SPU: give up on conditional stores if locking fails
Restores Non-TSX behaviour partially.
2020-10-15 17:18:49 +03:00
Nekotekina 1b89ad00e7 SPU: restore some LR event setting logic after #9048 2020-10-15 17:18:49 +03:00
Nekotekina 40558e7ac1 Use std::invoke in cpu_thread::suspend_all 2020-10-14 02:53:58 +03:00
Nekotekina 3bddba0c7a SPU: fix spu_getllar_tx
Was not executing.
2020-10-14 02:53:29 +03:00
Nekotekina 97cd641da9 TSX: reimplement spu_getllar_tx
Only used as a backup method of reading reservation data.
Increase long GETLLAR reporting threshold.
2020-10-13 21:10:04 +03:00
Nekotekina 91db4b724c SPU: fix PUTLLC (TSX-FA)
Some forgotten checks may affect performance.
2020-10-13 17:46:03 +03:00
Nekotekina dcff8c2637 Fix remaining vm::reservation_lock usages (for now)
Optimization can be restored later.
2020-10-13 12:04:59 +03:00
Nekotekina 7a76fb1469 PPU: Add loop logging in STWCX/STDCX 2020-10-13 11:06:58 +03:00
Nekotekina 17f805ae64 PPU: cleanup for TSX path remnant 2020-10-13 10:54:10 +03:00
Nekotekina 1606f97177 CPU: print and reset suspend_all statistics 2020-10-13 00:33:20 +03:00
Nekotekina dc39a9b84f SPU: Report 'GETLLAR took too long'
Also move similar code in PPU.
2020-10-13 00:12:11 +03:00
Nekotekina 4ff23a9943 sys_fs: fix file opening from /app_home
Typo.
2020-10-12 21:41:57 +03:00
Nekotekina a806be8bc4 SPU: Implement S1/S2 (SNR) events (closes #8789)
Add TSX path in push_snr()
Add locks bits in ch_events
2020-10-12 21:41:57 +03:00
Nekotekina b57a9c31f0 Implement utils::tx_start (for TSX)
Implement utils::tx_abort helper.
2020-10-12 15:20:24 +03:00
Eladash 95c1443e30 SPU: Validate reservation in GET commands (Accurate DMA) (#9062) 2020-10-12 15:20:06 +03:00
Nekotekina 5bd5a382c0 PPU: fix LDARX/LWARX in accurate mode (closes #9058)
Fixup after #9048
Use SSE intrinsics in mov_rdata.
2020-10-11 19:52:10 +03:00
Nekotekina 1885e4345c Improve vm::reservation_update
Only respect unique lock.
2020-10-11 17:22:28 +03:00
Nekotekina 2f329cf7b5 PPU: minor improvement for LWARX/LDARX
Improve chances of loading actual data in memory.
2020-10-11 17:22:28 +03:00
Nekotekina f2d2a6b605 JIT cleanup for PPU LLVM
Remove MemoryManager3 as unnecessary.
Rewrite MemoryManager1 to use its own 512M reservations.
Disabled unwind info registration on all platforms.
Use 64-bit executable pointers under vm::g_exec_addr area.
Stop relying on deploying PPU LLVM objects in first 2G of address space.
Implement jit_module_manager, protect its data with mutex.
2020-10-11 17:22:28 +03:00
Eladash 3c935f7834 SPU: Fix minor segfaults (#9015)
SPU: Remove "RawSPU Not Found" exception.
Fix edge case in access violation handler.
2020-10-11 14:59:18 +03:00
Bevan Weiss 2c8b3f05ac FIX: MAX_PATH is used within Windows headers, we should use a different define internally
Replace MAX_PATH usage with EMU_MAX_PATH, this prevents the redefine warning, and ensures that we don't mess up other usages (which will likely want MAX_PATH as 260, like Windows defines, not 4096 like we do).
The replacement has been done based on what MSVC was telling me the define values were at each point (i.e. whether we wanted it or not, these usages were using our 4906 value, not the 260 value from Windows)
2020-10-10 23:09:05 +03:00
Nekotekina e8e3a3b2a2 PPU: improve LWARX/LDARX progression
Should reduce spam ("...took too long")
2020-10-10 17:36:41 +03:00
Nekotekina ec7d243ee9 More optimization for cpu_thread::suspend_all
Try to not pause inactive threads.
2020-10-10 14:22:12 +03:00
Nekotekina b74c5e04f5 Optimize cpu_thread::suspend_all
Reduce internal thread status polling.
Refactor utility functions.
2020-10-10 14:12:49 +03:00
Nekotekina 050c3e1d6b Rewrite cpu_thread::suspend_all
Now it's a function of higher order.
Make only one thread do the hard work of thread pausing.
2020-10-10 13:58:48 +03:00
Nekotekina 6d83c9cc0e PPU: remove ppu_stcx_tx
Very small transaction, benefit questionable.
2020-10-10 13:58:48 +03:00
Nekotekina 346a1d4433 vm: rewrite reservation bits
Implement classic unique/shared locking concept.
Implement vm::reservation_light_op.
2020-10-10 13:58:48 +03:00
Bevan Weiss d962bb018d wolfssl: Add WC_NO_HARDEN suppression to compiler defines, and remove duplicate defines in MSVC
Silence the wolf from telling us:
#warning "For timing resistance / side-channel attack prevention consider using harden options"

Also removed duplicate defines for Visual Studio project, to remove some additional warnings there.
2020-10-10 13:57:24 +03:00
kd-11 bca3a3f4ed vk: Open CB before doing frame cleanup so that callbacks work (#9041) 2020-10-10 10:02:55 +01:00
Eladash ffea52dc36 Add some more info to SPURS kernel explorer 2020-10-08 19:05:14 +03:00
Eladash 865464f607 SPU Local Storage capture 2020-10-08 19:05:14 +03:00
Eladash 73f96f48ee Fix SPU ELF loader 2020-10-08 19:05:14 +03:00
Nekotekina 89f1248140 Implement vm::reservation_op
Implement vm::reservation_peek (memory load)
Implement vm::unsafe_ptr_cast helper
Example use in cellSpurs.cpp
Fix dma_lockb value and description
2020-10-07 20:11:59 +03:00
Eladash 59be63167f Prettify SPU image name of dumped images 2020-10-07 01:12:45 +03:00
Eladash c628147521 cellSpurs: Implement more HLE functions (part 1) 2020-10-07 01:12:21 +03:00
Eladash a5cff8b186 kernel-explorer: Initial SPURS debugger 2020-10-06 14:20:23 +03:00
Eladash 983547af7e SPU: Embedded PRX/overlay image patching and dumping 2020-10-06 13:06:25 +03:00
kd-11 d5f7e7b179 vk: Reimplement GPU query management 2020-10-06 12:02:53 +03:00
Eladash 2a258dc21e Fix GCC compilation (#9035) 2020-10-05 06:39:56 +01:00
Eladash ec1244bb82 Minor cellSpurs fixup 2020-10-04 19:54:56 +03:00
Eladash ac6e042223 Implement sys_process_is_spu_lock_line_reservation_address 2020-10-04 19:54:56 +03:00
Eladash a0b387e0a9 cellSpurs: Fix HLE workload signalling, taskset fixes 2020-10-03 22:35:59 +03:00
Eladash 4cafd5a31c SPU: Remove dead additions in Accurate Xfloat 2020-10-03 20:31:35 +03:00
Eladash 888b520b31 sys_fs: return ENOENT for relative paths 2020-10-03 19:09:09 +03:00
Eladash 493e57837b SPU: Fix extremely rare bug of GETLLAR (#9011) 2020-10-03 09:31:28 +01:00
Roman bddfa76b2e Update BUILDING.md
Wrong link to the VS Qt Plugin (2017 instead of 2019)
2020-10-02 22:46:07 +03:00
Nekotekina ee00fdb61b fs: improve handling root mountpoint
Path such as simply "/" falls into this category.
2020-10-02 14:37:58 +03:00
Nekotekina 9b22661c19 fs: improve mountpoint detection
Properly handle . and .. path components in mountpoint detection.
Remove app_home mountpoint and use mountpoint from argv[0] instead.
Add dev_root mountpoint for special purposes.
2020-10-02 12:32:35 +03:00
Nekotekina 0ac3dbfec9 Improve Trophy Installer robustness
Relax paranoidal mount point locking and temp dir creation mechanism.
It was incompatible with a setup where user directory is symlinked.
Instead, create temp dir as close to target as possible (see savedata).
2020-10-01 22:00:57 +03:00
Eladash 56cebd99c2 SPU: Simplify logging of MFC commands (#9004) 2020-10-01 19:52:39 +03:00
Eladash 04c3d8d1bb Set max PPU threads to 100 2020-10-01 19:51:56 +03:00
Eladash 7fdf3dd760 cellSpurs: Add CellSpursJobOpcode definitions 2020-10-01 18:16:13 +03:00
Eladash 1f28bee86a cellSpurs: Add error codes formatting (unused) 2020-10-01 18:16:13 +03:00
Eladash aed560b630 Implemnt various HLE CellSpurs functions 2020-10-01 18:16:13 +03:00
Eladash 871b15f6e1 PPU: fixup for Accurate 128-byte reservations (#8998) 2020-10-01 18:15:07 +03:00
Megamouse ef0faf03fd Overlays: Use Back instead of Cancel 2020-10-01 12:26:18 +02:00
Megamouse 5226076676 Emu: use vulkan as default renderer 2020-10-01 09:19:13 +02:00
Megamouse 046923d9f7 Add Accurate PPU 128 Reservations to Debug tab 2020-09-29 10:26:23 +02:00
Megamouse 531eb04fd7 cellGameSetParamString: fix string sizes 2020-09-29 08:44:25 +02:00
Eladash f4ca6f02a1 PPU: Implement support for 128-byte reservations coherency 2020-09-28 22:34:42 +03:00
Eladash 3f7eba19c8 PPU: Upgrade reservations to 8-byte always 2020-09-28 22:34:42 +03:00
kd-11 04ff7913b4 rsx/codegen: Workaround for borked hardware
- Bitwise or does not evaluate correctly for some hardware.
  Substitute with subtraction instead.
2020-09-28 22:18:36 +03:00
Eladash 09cddc84be SPU/PPU: Implement Atomic Cache Line Stores 2020-09-27 20:09:21 +03:00
kd-11 9baef8c705 rsx: Emit simpler fragment program code
- Optimize clamp16
- Use bfe instead of shift-and
2020-09-27 18:56:04 +03:00
kd-11 a14a358b73 rsx: Optimize vertex decoder to generate simpler code
- Significantly improves compilation speed by simplifying most of the code and doing something similar to LICM.
  * Actual decoding is now vectorized and performed in one step rather than in a loop.
  * Switches inside loops are removed and replaced with simple comparison. Generates much nicer (and smaller) GCN bytecode.
2020-09-27 18:56:04 +03:00
kd-11 259844f4f3 vk: Disable spirv optimizer
- I've not found it to be very useful and it just breaks good code right now.
  TODO: Re-enable when things improve.
2020-09-27 18:56:04 +03:00
Bevan Weiss 264df11132 xxHash: Update to v0.8.0 xxHash (#8980)
* xxHash: Update to v0.8.0 xxHash

Removed build of XXHSUM test application for xxHash also.
2020-09-27 01:10:31 +01:00
Eladash 53c8ed6a63 vm: Fix stack memory release, always reset memory flags 2020-09-26 21:48:12 +03:00
Eladash f22348a9f9 sys_memory: Improve sys_memory_get_page_attribute for stack 2020-09-26 21:48:12 +03:00
Eladash 83d71519e0 Implement HLE sys_config stack allocation 2020-09-26 21:48:12 +03:00
Eladash 8ad36e2526 Fix fs::delim type, fix "." and ".." processing in fs::get_parent_dir (#8975)
* Fix fs::delim type

* Fix fs::get_parent_dir: "." and ".." processing
2020-09-26 19:18:32 +01:00
Eladash 0f67c68993 sys_mmapper: return ENOMEM on memory greater than UINT32_MAX (#8982) 2020-09-26 18:06:06 +01:00
Eladash b79d236bfa cellSearch: use std::hash (#8981) 2020-09-26 17:28:19 +01:00
Bevan Weiss 92efaf0bba GUI: Fix exception on invalid AudioRenderer
The findData() on the invalid value correction wasn't working, and was still returning -1.
This was then used in the enable_buffering lambda as the IndexChanged callback, and throwing the Assert.

Have replaced this usage with a lambda to manually find the appropriate entry. Since we localise the text displayed, neither findData nor findText of the combo box did the job.
I haven't touched the is_ranged use of findData.
2020-09-25 16:40:32 +02:00
Eladash 3b11f22062 MSVC bug workaround 2020-09-25 13:26:08 +03:00
Eladash 6164b3d2e2 Compilation fix 2020-09-24 21:00:23 +03:00
Eladash c806da51f8 Implement cellGameDeleteGameData (#8962) 2020-09-24 20:13:19 +03:00
Eladash 183aa31319 cellSysCache: Global hdd1 lock
Take advantage of recursive locking.
2020-09-24 18:06:51 +03:00
Eladash 7b3c0a69f3 kernel-explorer: Implement Filesystem Destcriptors information 2020-09-24 18:06:51 +03:00
Eladash 6b11d82dd0 Win32 FS: Always use FILE_SHARE_DELETE 2020-09-24 18:06:51 +03:00
Eladash d0f1b29b39 Win32 FS: Fix fs::utime for directories 2020-09-24 18:06:51 +03:00
Eladash b8fa6fb4c4 Win32 FS: Rewrite (fix) vfs::host::rename 2020-09-24 18:06:51 +03:00
Eladash 22269ca0d7 Registers Editor: Implement PPU/SPU reservation control (#8968) 2020-09-24 11:44:17 +02:00
kd-11 9ea478008c vk: Properly initialize float64 support for SPIRV 2020-09-24 01:30:21 +03:00
Bevan Weiss 20f1eb865b Update rpcs3/Emu/system_config.h
Co-authored-by: Megamouse <studienricky89@googlemail.com>
2020-09-23 21:15:45 +02:00
Bevan Weiss 53212ba7a9 Core: Add date/time offset capability for console time
Provides a setting which can be applied per game, and allows for a custom date/time to be set.
The console time will then apply this as an offset to the computer wallclock.

This allows for games which look at the console time to determine their gameplay to be adjusted.
2020-09-23 21:15:45 +02:00
Eladash 3372409590 cellGameContentPermit: Fix missing PARAM.SFO writeback (#8934) 2020-09-23 20:35:06 +03:00
Morgan Creekmore 4fe2951509 Fixed formatting 2020-09-23 20:27:30 +03:00
Morgan Creekmore ff8a94714f Add additional NV4097 methods to gcm_printing 2020-09-23 20:27:30 +03:00
Morgan Creekmore b45d6fee2d Fix methods_name indentation 2020-09-23 20:27:30 +03:00
Morgan Creekmore f44e696edf Added missing NV methods for gcm_printing 2020-09-23 20:27:30 +03:00
Eladash 5a049322ed HLE: Always return empty paths if game content does not exist in cellGameContentPermit 2020-09-23 20:24:21 +03:00
Bevan Weiss 04deb97f94 MSVC 16.8 Preview 3.1 compiler fix
The latest MSVC 16.8 Preview 3.1 cl.exe no longer likes the implicit conversion from false->std::shared_ptr
But it's happy with nullptr

Not the ideal solution, but it will kick the can down the road a little.
2020-09-23 12:44:32 +02:00
Eladash 0c3c34179e TROPUSR.DAT fixup (#8960) 2020-09-23 03:47:54 +01:00
Silent e938ddda2c Add playtime to the value from settings
Fixes playtime being wiped out when running
the game with --no-gui.
2020-09-23 00:06:29 +02:00
Eladash 97e26f9d6c Trophy fixup 2020-09-22 22:42:43 +03:00
Eladash bfa78870cb SPU: Fix unregistered channels in RCHCNT
Shouldn't throw exception on realhw.
2020-09-22 19:47:47 +03:00
Eladash ad37259ccc SPU: Implement many missing channel counts 2020-09-22 19:47:47 +03:00
Eladash 418968d974 sceNpTrophy: Add logging of commSign 2020-09-22 19:46:52 +03:00
Eladash 89905bc1c4 sceNpTrophyRegisterContext: Implement SCE_NP_TROPHY_STATUS_NOT_INSTALLED 2020-09-22 19:46:52 +03:00
Eladash 3a96d99187 sceNpTrophyRegisterContext: Atomically create trophy data 2020-09-22 19:46:52 +03:00
kd-11 a50ea09053 rsx: Properly pass format_class information during RTV/DSV resource barrier
- Also takes the opportunity to remove repeating code in a minor refactor.
2020-09-22 12:19:54 +03:00
kd-11 d012abd924 vk: Improve image transfer and scaling
- Handle typeless src and dst with aliased typeless format
- Optimize typeless transfers by only dealing with affected texels.
  * Eliminates redundant dst->typeless transfer of full image (very expensive)
  * Eliminates full src->typeless transfer of full image and replaces with only affected region
  * Requires significantly smaller output buffers, saving on VRAM cost
2020-09-22 12:19:54 +03:00
kd-11 7ed82c0791 rsx: Always force typeless copy if memory is crossing aspect boundary 2020-09-22 12:19:54 +03:00
Eladash cf61198fe3 HLE: Implement ERROR_BROKEN in cellGameDataCheck (#8945) 2020-09-22 10:30:31 +02:00
Megamouse 5d50602397 Qt/Input: fix default pad handler
We accidentally always saved keyboard to Player 1 if null was selected.
The new code will only apply keyboard by default if the config file was not found.
2020-09-22 06:59:38 +02:00
Megamouse 34eff440eb Qt: Fix playtime datatype 2020-09-21 22:17:40 +02:00
Megamouse 0b42cf06f8 sceNpTrophyCreateContext: improve commId logging 2020-09-21 15:32:02 +02:00
Megamouse 4c4be331f5 HLE: Fix sceNpTrophyCreateContext
fixes #7431 Soldner-X
Assuming that a SceNpCommunicationId should have a format like "TEST12345", then there is no need to delete termination characters after we already created a truncated string with 9 characters + null terminator.
The current behaviour does not work at all, because in case that we actually have a non-null termination character, deleteTerminateChar will step over the last x chars in the already truncated ID until it forcefully finds a character of its liking. eg. term='2': "TEST12345" => "TEST1" => "TEST1_00"
2020-09-21 15:32:02 +02:00
Megamouse 511e9920c2 patch_engine: Apply patch when APP_VER is unknown 2020-09-21 11:59:57 +02:00
Eladash 75c3fdcb6f Fix cellGameBootCheck PARAM.SFO reads 2020-09-21 06:36:34 +03:00
Eladash 9031c5a6e0 Win32 FS: Fix fs::stat for drives 2020-09-21 06:35:42 +03:00
Eladash 5ac6f090fc Fix cellGamePatchCheck (#8933) 2020-09-19 19:38:22 +01:00
Eladash 0d183a24be cellFs: Rewrite cellFsGetFreeSize 2020-09-19 13:53:04 +01:00
Eladash a21790b992 sys_fs: Fix sys_fs_disk_free 2020-09-19 13:53:04 +01:00
Eladash 762ceaf87e sys_fs: Do not expose real hard drive available space!!!!!!!!!!!!! 2020-09-19 13:53:04 +01:00
Eladash 2620a51cc9 cellSaveData: Minor fix 2020-09-19 13:53:04 +01:00
Eladash f1e8739608 Always reset size in cellGameGetSizeKB
Reversed.
2020-09-19 13:53:04 +01:00
Eladash b31a0115b2 cellFsStat Improvements 2020-09-19 13:53:04 +01:00
Eladash ed032dc985 cellGame: Improvements 2020-09-19 13:53:04 +01:00
Eladash c436ef0c6f SPU: Implement channels 70, 71, add naming for channel 69 (#8932) 2020-09-19 13:08:35 +01:00
kd-11 9db97278f3 rsx: Lower error message to warning
- Mismatched texture handling is a TODO that will be handled with texturing rewrites
2020-09-19 01:55:59 +03:00
kd-11 d3898fda57 rsx: Release misconfigured texture memory before attempting reupload 2020-09-19 01:55:59 +03:00
eladash 36ac68b436 SPU: Implement events channel count, minor interrupts fixes 2020-09-18 21:57:24 +03:00
Bevan Weiss cdc3ee6c1c GUI: Small changes to terminology
In line with #4259
Trophies are changed to be 'Earned' / 'Not Earned', which also matches both the RSX displays the notification frame
And changed window title of Screenshot Preview -> Screenshot Viewer because as mentioned in the issue, the screenshot has been taken already, so it's not a preview (it is the view).
2020-09-18 08:21:39 +02:00
Megamouse 6540393df5 Look for rap file for network license
A network license should be the same as a local license, with the difference that a local license is only checked online once, while a network license is checked online on each boot.
Since we don't check online anyway, the two should theoretically be identical for our purposes.
2020-09-17 00:39:41 +02:00
Megamouse 3f534b33ec Qt: allow handling of the game window while the settings dialog is open (#8921)
This should make it easier to handle dynamic settings.
2020-09-16 23:32:27 +02:00
SEt 9a6aac1662 Improve pad support (#8800)
* Add support for another DS3 HID Report ID for Win7
* Add support for reading accel/gyro pad data over SCP
2020-09-16 22:36:06 +02:00
Megamouse 4c70864588 Add rsx capture shortcut 2020-09-16 21:57:55 +02:00
Eladash 17c8b34088 atomic.cpp: Optimize sema_get to not always use atomic instruction (#8907) 2020-09-16 22:15:14 +03:00
kd-11 7900780cea vk: Fix nul section crash due to unexpected format (B8) 2020-09-16 20:14:44 +03:00
Eladash 0eb739756e kernel-explorer: Account for PPU IDs invalidation in lwmutex 2020-09-16 14:31:15 +02:00
Eladash 05364908f3 kernel-explorer: Fix lwmutex owner display 2020-09-16 08:07:49 +02:00
kd-11 92d65ff3c2 rsx: Add support for mixed data types when sampling shadow coordinates 2020-09-15 17:37:52 +03:00
Eladash a52a16807f PPU: Use SEQ-CST memory barrier in reservation load 2020-09-15 11:20:17 +02:00
Megamouse 8df1d74395 Add disambiguations to the new translations
We need this in case there are identical strings in the same file
2020-09-14 18:24:18 +02:00
Megamouse f84697ad5c move localized_string_id to own file
I dont know if there was a circular dependency issue
2020-09-14 18:24:18 +02:00
Megamouse a2da187615 HLE: localize most - if not all - exposed strings 2020-09-14 18:24:18 +02:00
Megamouse d0ffbbfc4d Qt/overlays: use Argument list for translatable strings
This is somewhat crippled for now. It only takes a single argument in the callback
2020-09-14 18:24:18 +02:00
Megamouse 460a933267 Qt/overlays: Localize most rsx overlays 2020-09-14 18:24:18 +02:00
Eladash fe9c61fe73 atomic.hpp: Fix atomic_storage_futex::raw_notify 2020-09-12 22:11:40 +03:00
Eladash 3206378ae6 sys_spu: Fix overexecution of cpu_return() 2020-09-12 22:11:40 +03:00
Eladash 7ce790f369 SPU: Use ASM for AVX2 coompilation instead of intrinsics 2020-09-12 18:49:49 +03:00
Eladash 5db1427923 cellGame: Implement cellHddGameCheck2 2020-09-12 11:00:24 +02:00
Eladash 81eceb1728 cellSysUtil: Implement CELL_SYSUTIL_SYSTEMPARAM_ID_LICENSE_AREA 2020-09-12 11:00:24 +02:00
Megamouse 639650c65a Add more defines to cellSysutil 2020-09-12 09:56:51 +02:00
Eladash 9d034ea4a2 Register Editor: Allow to modify PPU priority 2020-09-11 21:54:24 +02:00
Eladash 9ff0b460a2 SPU: Make PUTLLUC LR event accurate 2020-09-11 09:02:18 +02:00
Eladash 4f0125a0e9 SPU: Remove "Accurate PUTLLUC" setting (always accurate) 2020-09-11 09:02:18 +02:00
RipleyTom 54493747a8 Updates wolfssl and curl to official repos 2020-09-10 23:09:36 +02:00
Eladash b48c036636 Fix bitfield operator &= 2020-09-10 19:04:53 +02:00
Eladash d489b02fc1 PPU: Do not allow unaligned/unmapped reservation addresses 2020-09-10 13:35:57 +02:00
Megamouse 595fdb2f57 patch_manager: fix downloader location
it was spawning on the main window instead of the patch manager
2020-09-10 09:13:39 +02:00
Megamouse 8d56dd1969 patch_manager: use rename to back up old patch file 2020-09-10 06:58:44 +02:00
Megamouse 44371dedd9 fix fs::copy_file on linux 2020-09-10 06:58:44 +02:00
Megamouse fb62c297fa patch_manager: log g_tls_error 2020-09-10 06:58:44 +02:00
RipleyTom 676fed7cfc Only bind 3658 with RPCN 2020-09-09 23:56:25 +02:00
RipleyTom d9d354c981 Makes DNS processing more consistent 2020-09-09 23:56:25 +02:00
Eladash 8c8048f037 Win32 FS: Use FindFirstFileExW in fs::stat, fs::exists, fs::is_dir, fs::is_file
Co-Authored-By: Bevan Weiss <bevanweiss@users.noreply.github.com>
2020-09-09 21:57:01 +02:00
kd-11 da6760ed98 vk: Simplify shadow comparison operations for non-integer formats
- Just use hardware PCF, it makes everyone's life easier.
2020-09-09 22:11:12 +03:00
Megamouse 1d04f14a53 patch_manager: fix success message 2020-09-09 20:34:17 +02:00
Megamouse 570eee3202 patch_manager: handle sha256 checksum 2020-09-09 20:34:17 +02:00
Megamouse ca07605835 patch_manager: layout fixes 2020-09-09 20:34:17 +02:00
Megamouse 46e8b4f561 patch_manager: add download button 2020-09-09 20:34:17 +02:00
Eladash 1e4655aef6 SPU: Remove STOP 0x0 hack (#8873) 2020-09-09 11:36:04 +01:00
Megamouse 3e1b76258e Qt: Update tooltip for "disable keyboard hotkeys" 2020-09-09 00:22:48 +02:00
Megamouse a845a0395a Input/Qt: Properly reset mouse hide timer 2020-09-09 00:22:48 +02:00
Megamouse f0053bfc1a Input/Qt: Dont lock unused mouse in keyboard pad 2020-09-09 00:22:48 +02:00
Ani 22dc2947b3 hle: Implement ID_CURRENT_USER_HAS_NP_ACCOUNT (#8864) 2020-09-08 15:12:47 +01:00
Eladash 43fce92aa9 PPU: reduce LARX logging level to warning 2020-09-08 15:23:55 +02:00
kd-11 6380e67af9 rsx: Fix depth clipping
- Fix special case where n=f making (f-n) = 0
- Dynamically update depth range by setting dirty bits
- Fix depth bounds when n=f and bounds test is disabled
2020-09-08 15:33:08 +03:00
kd-11 dc465df3bc rsx: Enable support for extended range in depth buffer
- Software clipping emulation is used here as OpenGL does not have explicit clip control.
- Hardware clip control for vulkan to be enabled after this.
2020-09-08 15:33:08 +03:00
kd-11 2e88924cb9 rsx/gl: Refactoring and cleanup
- Fix incorrect memory requirement calculation for D32FS8X24_PACK64 data type on GL
- Removes a lot of spaghetti code in GL backend from years of accumulation
- Retires several now-useless methods from RSX util toolbox
2020-09-08 13:53:06 +03:00
Megamouse fee96ec92d fix some warnings 2020-09-08 12:05:51 +02:00
Bevan Weiss c39ad1ee12 Fix Windows UNC Path Handling
In Windows, when using Open Install Folder etc with UNC paths, nothing would happen.
This replaces the "file://"+path usage with QUrl::fromLocalFile(path) which appears to handle this better.
Needs testing under non-Windows.
2020-09-08 09:38:39 +02:00
Rafał Mikrut 5669c7497d Update Building.md for Ubuntu based distros 2020-09-08 09:12:24 +02:00
QuadDamage 60f8fc293d VFS: fix off-by-one error in vfs::escape() 2020-09-08 08:20:41 +02:00
Eladash 9134388f94 sys_process: Implement exitspawn error checking 2020-09-08 07:36:36 +02:00
RipleyTom 10820fa135 Implement sceNpSignaling & signaling improvements (#8836) 2020-09-07 22:50:17 +01:00
Eladash 2f3e0044f1 PPU: Cleanup & unify reservation loads (#8849) 2020-09-07 22:06:09 +01:00
Eladash 5060c779da SPU: Use unaligned instructions in mov_rdata_avx (MSVC) (#8851) 2020-09-07 21:32:44 +01:00
kd-11 6d2cb94e3e gl/vk: Support swizzled data for RCB/RDB 2020-09-07 22:31:57 +03:00
kd-11 85e5b077f7 gl: Overhaul upload and download routines for textures to go through shared image_to_buffer and buffer_to_image routines.
- This automatically adds support for depth float textures as well
2020-09-07 18:25:54 +03:00
kd-11 85dd1b4ea9 vk: Fix fconvert job issues
- Fix compilation bug caused by typo
- Invert to/from for consistent declarations
- Fix dst_swap when From == 2
2020-09-07 18:25:54 +03:00
kd-11 220e86bbd1 gl: Accelerate D24X8_UINT operations
- Adds compute decoding for D24X8_UINT on both download and upload routines
- Adds support for D24X8_UINT operations for typeless copy
2020-09-07 18:25:54 +03:00
Eladash abc715bc5c SPU: Make PUT transfers use SEQ-CST ordering on Accurate DMA (#8844) 2020-09-06 12:09:14 +01:00
Bevan Weiss e1adb18491 GUI: Additional translation entries
A few more items:
Standardising on 'OK' for all base language uses (rather than 'Ok', or 'Okay').
It's perceived as the 'most correct' variant, and importantly having a single variant is best from a translation perspective.

Added plurality handling for multiple PPU caches created.

Added plurality handling for multiple items deleted in save manager.

Capitalised trophy grade to align with Sony terminology.
Brought trophy name position into translatable string (for languages that might really want to deviate from SVO)
2020-09-06 11:50:27 +02:00
Eladash 2688081656 SPU: Use unaligned AVX instructions for cmp_data_avx 2020-09-06 07:51:12 +03:00
Eladash e4abd3dc5a SPU: Do not ignore pending PUT tranfers just becase GET may not be cache-line atomic
This is not the proper way to emulate non-atomic GET tranfers, as it makes it seems as if PUT atomic tranfers arent atomic. (TODO)
Incomplete GET cache line accesses still do not verify data though.
2020-09-05 22:23:55 +03:00
Eladash c7a185d4e7 SPU: Fix not acuiring reservation locks on DMA with more than one cache line (Accurate DMA) 2020-09-05 22:23:55 +03:00
Bevan Weiss baf96b3eb6 RSX: Update manual string creation -> std::string()
Replace manual string creation with call to std::string() constructor passing in char*
This appears to drastically reduce the cache impact here
2020-09-05 10:38:32 +03:00
Eladash 8e2b07ba9e sceNpDrm: Relax file extension checks 2020-09-04 22:35:18 +02:00
Eladash 0b023d4e28 SPU: Make Accurate GETLLAR, PUTLLUC settings dynamically adjustable 2020-09-04 10:20:44 +02:00
Eladash 4ffc58a8ce SPU: Cleanup for Accurate PUTLLUC
Should no longer affect GET commands because Accurate DMA is available for this functionality.
2020-09-04 10:20:44 +02:00
Eladash c5c9ea1b21 SPU: Make GET's full and aligned cache line accesses atomic with Accurate DMA 2020-09-04 10:20:44 +02:00
kd-11 3c43d8fe05 rsx: Fix execution barrier insertion
- In case of element re-arrangement, the barrier should obey the current insertion pointer
2020-09-04 09:34:13 +03:00
Megamouse 21f06e1074 improve tooltip coverage 2020-09-03 18:31:11 +02:00
Bevan Weiss 875e252db3 GUI: Tooltips for mouse hide if idle and resize on boot
The original commits for the mouse hide on idle included definitions for tooltips, but didn't assign them correctly.
This fixes that up, so that tooltips exist.

And the resize height / width settings didn't have any tooltip applied.
So this extends the current resize setting tooltip to also trigger on the height / width hover (at least indicating that they are associated with this setting).
2020-09-03 18:31:11 +02:00
Bevan Weiss 610e71b71b Internationalisation updates
Added description 'Never played' for games with no elapsed time indicated.

Tidied up game list times to handle translation for larger unit of time in each time pairing.
NOTE: Latin will be a problem (sorry for any native Latin speakers)
2020-09-03 11:49:21 +02:00
Eladash 73d23eb6e6 SPU: Implement Accurate DMA (#8822) 2020-09-02 23:58:29 +02:00
Jacques Yakoub ddfa077c3e Qt: simplify GetVerboseTimeByMs logic (#8824)
* Qt: simplify GetVerboseTimeByMs logic

Follow recommandation from QT : https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals
#8473
2020-09-02 18:06:16 +02:00
Megamouse 006f546e7c Fix idle timer 2020-09-02 14:22:00 +02:00
Megamouse 1dac01498c Update mouse lock logic
- fix headers
- update cursor whenever the mouse is moved
- unify cursor logic
- move m_mouse_hide_and_lock logic to handle_cursor (toggle_fullscreen is the trigger, not the handler)
- disable mouse lock and idle timer if the window is inactive
2020-09-02 14:22:00 +02:00
Bevan Weiss ae0e454fc2 Use dynamic_cast to convert QWindow m_target to gs_frame
Used to access get_mouse_lock_state rather than going through the QWindow property tables.

Modify mouse hide and lock to default OFF when entering Windowed mode, and to default ON when entering Fullscreen unless 'show cursor in fullscreen' is configured
2020-09-02 14:22:00 +02:00
Bevan Weiss ca3ee019cc GUI: Mouse Hide and Lock Keyboard Shortcut
This should address the second point of #4502.

A few notes:
1. it changes the current behaviour of the 'Fullscreen cursor'.  Currently it defaults to be captive.  This changes it so that it defaults to NOT being captive, but can be made captive with the CTRL+L key combination.
2. There are situations when in windowed mode it's possible to escape the captivity (it's like a minigame if you will).  This requires the mouse movement to exceed the bounds of the window in a single event scan.  It will just show up as a temporary visibility of the cursor when outside of the window bounds.  It's not too difficult to 'fix', but might not be a likely enough scenario to warrant either.
3. There currently isn't an ability to change what this keyboard combo maps to, but it's inline with a collection of other similar keyboard mappings.  I think adding such a more generic keyboard mapping system (not for just keypad items, but system items.. e.g. so that Emulator stop could be mapped to something other than CTRL+S etc) is a bit out-of-scope of this particular PR.
2020-09-02 14:22:00 +02:00
Ani a86a3d2fee rpcs3_version: Bump to 0.0.12 (#8815) 2020-08-31 23:38:51 +01:00
kd-11 a917f55ef8 vk/sdk: Sync with vulkan SDK v148 (#8814)
- Sync with vulkan SDK 148
- glslang library was split into several smaller libraries
- HLSL is no longer needed
2020-09-01 00:57:38 +03:00
Ani 21b535b5c5 gui/themes: Convert kot-bg to jpg (95%) (#8809)
No perceived loss of image quality, reduces size from 8.1 MB to 2.0 MB
2020-08-31 05:35:42 +01:00
kd-11 af9e217fa4 vk: Improve D16F handling
- Adds upload and download routines. Mostly untested, which is why the error message exists
2020-08-30 09:26:37 +03:00
Bevan Weiss 9a51f22265 Remove call to start m_mousehide_timer in gs_frame constructor 2020-08-29 16:14:11 +02:00
Bevan Weiss 144b185802 Woops... premature commit/push.
Fixed up the usage of connect
2020-08-29 16:14:11 +02:00
Bevan Weiss 3c0f6a2919 Used new Qt connect syntax
Fixed indenting
Renamed click callback argument from 'val'->'checked'
Converted m_gui re-usage to just reference ui
Removed implicit capture from spinbox lambda
Corrected millisecond acronym from mS->ms
Removed superfluous QTimer include in gs_frame.cpp
2020-08-29 16:14:11 +02:00
Bevan Weiss 22c33d4fb4 Added settings and logic for auto-hide of mouse cursor.
In line with the Show Cursor in Fullscreen settings, these settings are only updated when the render window is first launched, and not during the game.
This could be revised (along with the Fullscreen Cursor) if it's more desired.
2020-08-29 16:14:11 +02:00
kd-11 e9cdb248a0 glsl: Properly implement shadow filtering when running emulated shadow compare
- Previous code was completely borked
2020-08-29 02:03:09 +01:00
kd-11 e8274d5a59 vk: Fix depth format mismatch detection in copy_image 2020-08-29 02:03:09 +01:00
Eladash 6952be5ce4 Debugger: Replace SPU register perefix '$' with 'r' 2020-08-28 20:44:13 +02:00
RipleyTom 4317291827 tcp_timeout_monitor deadlock fix (#8783) 2020-08-28 01:06:01 +01:00
Nekotekina bd40430d2b Fix some warnng in lv2.cpp 2020-08-28 01:54:39 +03:00
Nekotekina ebc4a0188a Restore some code 2020-08-28 01:54:39 +03:00
Nekotekina bfa4fcf584 Use g_fxo for progress_dialog_server 2020-08-28 01:54:39 +03:00
Eladash 48f70fbf10 Fix UB in Emulator::Load 2020-08-27 23:52:37 +01:00
Eladash 019d2d5dcf Implement HLE cellSpursAddUrgentCommand 2020-08-27 23:52:37 +01:00
Eladash 17f7f329a8 Log PRX segment end for usage with kernel explorer 2020-08-27 23:52:37 +01:00
Eladash 933737e8f0 PPU: log LR in HLE functions 2020-08-27 23:52:37 +01:00
Eladash 47b545282e SPU: Fix events ACK, minor optimizations (#8771) 2020-08-27 21:36:54 +01:00
RipleyTom 190822c2b2 RPCN Client (#8663) 2020-08-27 20:47:04 +01:00
kd-11 d000d648b0 vk: Fix some minor spec violation
- Stencil clear pass does not consume an image, do not bind one.
- Add push_barrier to allow push-pop semantics for texture barrier insert.
2020-08-27 12:52:28 +03:00
kd-11 d257ba5156 vk: Add some more diagnostic messages for unoptimized image transfer setups 2020-08-27 12:52:28 +03:00
kd-11 9828d6146b rsx: Fix format matching when aggregating textures
- When copying depth-depth, prefer own format over depth int format
2020-08-27 12:52:28 +03:00
kd-11 9e4bec8cec vk: Fix some missing render target declarations 2020-08-27 12:52:28 +03:00
kd-11 65ead08880 rsx: Refactor and improve image memory manipulation routines 2020-08-27 12:52:28 +03:00
kd-11 f6c6c04648 vk: Implement transport for D24S8_FLOAT data 2020-08-27 12:52:28 +03:00
kd-11 794378d5e9 rsx: Do not create depth textures as blit engine targets. 2020-08-27 12:52:28 +03:00
kd-11 a5ac5a9861 rsx: Separate uint depth formats from float depth formats 2020-08-27 12:52:28 +03:00
kd-11 faaf28b41d rsx: Basic support for creating depth float formats 2020-08-27 12:52:28 +03:00
GooseWing 700c540434 Add Nekotekina skin (#8776)
* adding kots

* More sharper neko on background

Co-authored-by: Megamouse <studienricky89@googlemail.com>
2020-08-27 07:15:24 +02:00
RipleyTom c177bf7480 Forces MSVC Toolkit to 14.25.28610 in Azure Pipelines 2020-08-27 06:39:46 +02:00
Eladash bccfb1cda7 Fix empty input in Registers Editor 2020-08-26 08:20:16 +02:00
Eladash c099bb817f Debugger: Disable PPU address redirection
It causes more confusion than it helps.
2020-08-25 17:43:07 +02:00
Eladash 7fe98d8d66 Debugger: Add missing PPU stack register checks 2020-08-25 17:43:07 +02:00
Eladash d356e0d1e7 Debugger: Register Editor Improvements 2020-08-25 17:43:07 +02:00
Eladash 3ce7fd7894 Debugger: Fix instructions editor 2020-08-25 17:43:07 +02:00
Eladash 6f42297b58 Debugger: Fix scrolling using PageUp, PageDown, KeyUp, KeyDown 2020-08-25 17:43:07 +02:00
Eladash c5aebe4564 Debugger: Implement PPU SLWI, SRWI, SLDI mnemonics 2020-08-24 02:10:51 +03:00
Eladash 841b8fad38 SPU: Fix timer events 2020-08-24 01:57:32 +03:00
Bevan Weiss ab0df0a0f5 Support for Namco GCon3 gun (#8757)
This gun now works (passes calibration) in Time Crisis 4.
2020-08-22 15:41:08 +02:00
Eladash 27e3317449 [HOTFIX] Fix UB in Emu/System.cpp 2020-08-22 11:55:08 +02:00
Eladash edc09e22b4 PSF: Avoid redundent string copies in psf::array/string/get_string (#8707) 2020-08-21 23:55:17 +01:00
Megamouse b487c09d34 Revert "Qt: speed up list refresh"
This reverts commit 715f4f0669.
2020-08-21 09:51:36 +02:00
Eladash 4a40ef6a19 Debugger: Use Signed Hexadecimal formatting (#8751) 2020-08-20 22:07:31 +01:00
Eladash bcddbc15f0 Debugger: Fix PPU stepping on non-TSX 2020-08-19 19:48:35 +01:00
Eladash 2a19d0a579 kernel-explorer: Add RSX handlers events info 2020-08-19 09:09:24 +02:00
Megamouse 9af66e22da evdev: log axis information in pad settings 2020-08-18 18:29:35 +02:00
Megamouse 715f4f0669 Qt: speed up list refresh 2020-08-18 11:00:04 +02:00
Megamouse e6e753f37f Qt/Linux: fix QT_AUTO_SCREEN_SCALE_FACTOR typo 2020-08-18 10:04:31 +02:00
Megamouse e958c3cc6a Qt: fix YoRHa QTreeWidget item style for CheckBoxes 2020-08-18 10:04:31 +02:00
Eladash 19500ac9ad Fix truncation warning in sys_cond.cpp 2020-08-17 17:36:27 +01:00
Eladash 25dee4a78e Fix bitops test 2020-08-17 17:36:27 +01:00
Eladash ee953f7953 Fix vm::reservation_update 2020-08-16 22:58:49 +03:00
Zion Nimchuk acee590733 Ensure pushing builds to Github is only done on master branch 2020-08-16 17:35:19 +01:00
Zion Nimchuk cd94d9849d Windows GitHub release hotfix
Improve id variable parsing and print release.json to catch error
2020-08-16 17:35:19 +01:00
Zion c3709fa744 Manually upload Windows Github Release using curl. Actually fixes #7938 (#8715)
For some reason Azure would evaluate the GitHub release instantly and
complain about missing/invalid GitHub Release deployment and fail to
even start the build, this fixes the issue by just manually uploading it
via the GitHub API and curl.
2020-08-15 20:46:53 +01:00
Eladash 853e2b90a3 rsx: Minor rsx::ceil_log2 bugfix 2020-08-15 20:39:21 +03:00
Eladash 995cb8125e SPU LLVM: Improve approx FCGT (#8728) 2020-08-14 19:33:35 +01:00
Bevan Weiss 01d3585bf3 Bring back the non-compliant define, but version limited
As noted, we've done something we shouldn't have with MSVC compiler specific defines.  But to avoid breaking the MSVC build environment, leave this define in there until the MSVC version when it is actually exposed by the compiler itself (v16.8).
2020-08-14 18:34:34 +01:00
Bevan Weiss a11afe05bf MSVC changes
Add support for compilation on x64 toolchain (x86 cl.exe was running out of heap space in vm.cpp)

Also took the opportunity to change compile optimisation from /Ox to /O2, as /O2 provides better optimisation than does /Ox

Also, we shouldn't be explicitely setting compiler tool defines (__cpp_lib_bitops), so remove that from types.h
2020-08-14 18:34:34 +01:00
Whatcookie 9e4f43f4d1 SPU LLVM: Add icelake optimized paths for SHUFB (#8712) 2020-08-13 15:00:56 +01:00
Eladash 8cdfe5952a SPU/PPU LLVM: Improve 0 addend FMA detection (#8709) 2020-08-13 04:13:08 +03:00
Eladash 0f8ca1f7c5 SPU: Implement RSX accurate reservations on TSX (#8721) 2020-08-13 00:00:37 +01:00
kd-11 fd2607ad52 rsx: Fix XBGR vs XRGB screenshots 2020-08-12 20:19:19 +03:00
kd-11 7e1b24224d rsx: Support XBGR flip image load from Cell memory 2020-08-12 20:19:19 +03:00
kd-11 56c63170b9 vk: Warn if GPU does not support RGBA8 natively 2020-08-12 20:19:19 +03:00
kd-11 b41349546c rsx: Proper support for typeless transform of ABGR framebuffers using the RGBA8 format 2020-08-12 20:19:19 +03:00
kd-11 6850533b50 rsx: Unify composite texture creation and management
- Some texture accesses require image compositing steps to assemble the requested image from existing subresources.
  Handle all the common routines in a unified manner to avoid having one broken path (e.g mipmap gather not supporting bitcast operations)
2020-08-10 13:31:22 +03:00
Whatcookie 4ce2ad54a8 PPU LLVM: Use VPERM2B to emulate VPERM (#8704)
- The VPERM2B instructions are a match of VPERM's behavior, besides operating in reverse byte order
2020-08-09 01:50:26 +01:00
Eladash 0c85d4c0d0 cellSaveData: Fix loss of "BLIST" and files' information in PARAM.SFO (#8706) 2020-08-08 23:40:47 +01:00
Eladash 57471f8c94 SPU LLVM: Fix signed zeroes handling on Accurate xfloat 2020-08-08 22:21:22 +01:00
Eladash 7e11855330 SPU/PPU LLVM: Fix FMA signed zeroes handling 2020-08-08 22:21:22 +01:00
Malcolm Jestadt f188589685 Utils: Add detection for Icelake-client tier AVX-512
- Implies support for everything that Skylake-X supports as well as AVX512IFMA, AVX512VBMI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, AVX512VPCLMULQDQ, AVX512GFNI, AVX512VAES
2020-08-08 00:33:22 +02:00
Megamouse 96428a7555 Log username 2020-08-07 21:57:08 +02:00
illusion d3585e1f80 move accurate rsx reservation to advanced 2020-08-07 09:34:27 +02:00
illusion c0c86521a2 add missing settings to configure 2020-08-07 09:34:27 +02:00
kd-11 22f5e7a9be vk: Generate valid image+image_view combinations for placeholder texture descriptors 2020-08-06 20:34:49 +03:00
Megamouse 06c42bba5d Qt: fixup for PKG installation 2020-08-06 17:32:29 +02:00
Bevan Weiss ada6db2df4 Replace ppu_module_manager Function Static with Class Static variable (static module map) (#8669)
* Replace ppu_module_manager Function Static with Class Static

Makes for a slightly 'cleaner' interface in my opinion, may also assist with adding thread read/write concurrency support in future if ever required (have left that out of this commit to match existing function).

Very slight performance improvements were seen in representative testing.
https://quick-bench.com/q/GMbgeNc-mZc21aqOKCofnbzPZvg

I didn't investigate whether static initialisation of the static_modules might actually be possible here, perhaps there's a way to do a constexpr / consteval of this.

* Fix up for old style cast syntax..

* Fixups from PR comments

Plus remove spurious type_traits include (from me) not picked up in previous PR

* Remove old code

* Update rpcs3/Emu/Cell/PPUModule.h

Co-authored-by: Eladash <elad3356p@gmail.com>

* Fix naming of static variable

Co-authored-by: Eladash <elad3356p@gmail.com>
2020-08-06 12:34:08 +02:00
Bevan Weiss eee5e812f7 Fix for incorrect assignment of ghlguitar
found_ghltar was potentially being overwritten if multiple USB devices were present
2020-08-06 12:01:21 +02:00
Bevan Weiss eb5ae94c24 sys_usbd tidy ups
Tidy up fake transfer iterator handling. erase invalidates all iterators including the current iterator (i.e. 'it'), given precedence ordering this was UB prior to C++17.  Splitting out to use return iterator from erase seems cleaner.
Also added some additional info to usb debug message to potentially help with #8666, and used the atomic (dev_counter) less often
2020-08-06 12:01:21 +02:00
kd-11 7109fe9889 rsx: Improve swizzled layout detection
- Reset swizzle flag to false automatically on section reset.
- Detect render target payload and extract swizzle information from it.
2020-08-05 23:23:38 +03:00
Megamouse 17557df9f4 Qt: unify package installation logic 2020-08-05 08:10:22 +02:00
Megamouse fab1f7d939 Qt: add rap files to pkg install file dialog 2020-08-05 08:10:22 +02:00
Megamouse 815d6f4223 Qt: fix input lag in pad settings
Looks like repainting stuff inside a resizeable layout is slow AF
2020-08-04 16:15:13 +02:00
Megamouse 25d73f5a70 Try to fix ugly GUIs 2020-08-03 22:03:15 +02:00
Megamouse d633a266c1 Add config override as cli arg: --config <path>
And add some more logging
2020-08-03 21:31:53 +02:00
dio-gh 938bf8624c make some cfg logs error instead of fatal
- in case there's a default value to fall back to, log with error
  instead of with a fatal
2020-08-03 20:59:47 +02:00
Megamouse 2cdb46b167 Qt: do not use on_<obj>_<action> syntax for slots
Qt tries to auto connect those
2020-08-03 20:17:35 +02:00
Megamouse 8799eebfe1 Qt: move some more settings to persistent_settings 2020-08-03 20:17:35 +02:00
Eladash 70fb5712e5 PPU interpreters: Fix VMAXFP NaN and signed zeroes handling 2020-08-03 15:43:00 +01:00
Eladash 6a51c27fde PPU LLVM: Fix VMAXFP, VMINFP NaN handling 2020-08-03 15:43:00 +01:00
Eladash 17f965c171 lv2: Minor fix of "unspecific ppu" path of _sys_lwcond_signal 2020-08-03 02:57:20 +03:00
kd-11 bd21930d1a rsx: Decode swizzled GPU data on CPU readback
- Currently this conversion is being done on the CPU to reuse as much code as possible.
  The expectation is that this almost never happens, so there is not point in increasing maintenance burden by adding compute paths
2020-08-02 16:14:11 +03:00
kd-11 4df933275b rsx: Propagate raster type of fbo sourced data throughout the pipeline.
- Tracks which kind of raster was done (Z-ordered vs linear) throughout the application.
- This allows to identify if data is in the expected format or not.
2020-08-02 16:14:11 +03:00
Megamouse 107129f95a Fix missing GPU in game window title 2020-07-31 01:13:00 +02:00
JohnHolmesII e11734f971 CI: Avoid trying to publish builds on forks 2020-07-30 23:36:10 +02:00
Megamouse 3bba9708d9 Gracefully abort headless mode with unsupported video renderers
Also fix no_return bug
2020-07-30 20:03:51 +02:00
Eladash dd497625a5 PPU LLVM: Fix constant folding of BitCast 2020-07-30 17:06:24 +01:00
Eladash f6764767f6 SPU/PPU LLVM: Fix cpu_translator::get_const_vector<v128>() 2020-07-30 17:06:24 +01:00
Eladash e52dd9dc6f SPU: Implement SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE (#8657) 2020-07-30 14:01:25 +01:00
Megamouse 03ae1481fb Don't open an error dialog in headless mode 2020-07-30 12:17:35 +02:00
Eladash 82068cf802 SPU: Fix spu_thread::cpu_stop() missed executions (#8656) 2020-07-30 10:07:18 +01:00
Megamouse ebf832214e cheat_manager: notify if no game is running 2020-07-29 13:18:33 +02:00
Megamouse 4315363f4b cheat_manager: make sure that the patches path exists 2020-07-29 13:18:33 +02:00
Megamouse f073ff8fe8 overlays: fix minor warning 2020-07-29 13:18:33 +02:00
Megamouse 47040be3ad cheat_manager: improve parser errors 2020-07-29 13:18:33 +02:00
Megamouse d0bb9d2b62 cheat_manager: move cheats.yml to patches folder 2020-07-29 13:18:33 +02:00
Megamouse cb6e536fbd cheat_manager: use enum values for columns 2020-07-29 13:18:33 +02:00
Megamouse f820a7a205 cheat_manager: disable search buttons if nothing was entered in the search field 2020-07-29 13:18:33 +02:00
Megamouse 16212854b4 cheat_manager: fix long search result lists 2020-07-29 13:18:33 +02:00
Megamouse 1c6003acd5 Improve error handling of config nodes
These conditions are most likely only gonna be met during development
2020-07-29 11:28:16 +02:00
Megamouse ef3e8d26ce Improve error handling during config loading 2020-07-29 11:28:16 +02:00
Eladash 21a1072117 SPU LLVM: Minor cleanup after #8559 2020-07-29 03:32:21 +03:00
MSuih 2ce49e3674 Improve error messages in firmware install 2020-07-28 20:55:33 +02:00
Megamouse e58e1ebfd9 Qt: fix download menu visibility 2020-07-28 20:07:21 +02:00
Bevan Weiss 609182b131 Update cellAudio to use float constants instead of doubles
Another simple Clang recommendation
2020-07-26 17:23:02 +03:00
Bevan Weiss 7898ae6fe6 VK_REMAP enum is signed.. but later case comparison is unsigned
another clang directed fix up... might be involved with swizzle..
2020-07-26 15:27:51 +03:00
Malcolm Jestadt a9d0ffcac1 SPU LLVM: Avoid additional endian swapping
- Avoid additional endian swapping with the ROTQBY and ROTQBYBI instructions
- ROTQBYI is left out intentionally, since it caused worse codegen
2020-07-26 11:36:50 +01:00
Malcolm Jestadt 824be77bba SPU LLVM: Avoid redundant endian swapping
- PSHUFB operates in reverse byte order from SHUFB, so we can take advantage of that to swap endianness without additional transformations in some situations
2020-07-26 11:36:50 +01:00
Ani 74c8a44d84 rsx: Fix cache skipping shaders on load+compile (#8633)
When on single worker mode (OpenGL or an hypothetical scenario of a 
single core PC with Vulkan), load and compile would skip 10% of the 
shaders on queue each stage.

Co-authored-by: kd-11 <karokidii@gmail.com>
2020-07-26 08:47:50 +01:00
Whatcookie 9f829b375a SPU/PPU LLVM: Optimize VSEL/SELB with constant mask (#8559) 2020-07-25 17:59:35 +01:00
Eladash da44d5f10d PPU: Fix DIVW, DIVWU, MULHW, MULLW, MULHWU when op.rc is set (#8630) 2020-07-25 17:13:58 +01:00
kd-11 be4b71b805 vk: Fixup for PR #8590
- This change was lost during rebase
2020-07-25 14:48:11 +03:00
kd-11 b0c7ca6d1f vk: Improve video memory manager to attempt recovery in out of memory situations 2020-07-25 14:48:11 +03:00
kd-11 4d8de282f9 vk: Improve typeless texture succession
- Ensure incoming texture is large enough that the original one fits inside it to avoid back-and-forth succession.
- Make use of the resource manager to remove the obsolete textures to avoid holding on to the them which "leaks" VRAM.
  The memory isn't leaking, it's just wasting space in temporary pool until renderer is closed.
2020-07-25 14:48:11 +03:00
Bevan Weiss c5d39ace2b Update types.h to fix static_cast test (#8627)
Trivial fix up to resolve invalid is_constructible test (To,To) to match desired (To,From)
2020-07-25 09:46:47 +01:00
Megamouse de80a4b6c7 overlays: try to fix unexpected font crop 2020-07-25 10:21:52 +03:00
Eladash 917069e31a PPU Precise/LLVM: Support NJ modes (#8617) 2020-07-25 07:41:41 +01:00
Eladash 3354c800d7 SPU/PPU LLVM: Improve expressions matching (#8620) 2020-07-24 16:53:48 +01:00
Megamouse bb3ac62126 cellMic: use s32 consistently 2020-07-24 14:47:10 +02:00
Megamouse 6e25fea16a use not_an_error in sys_spinlock_trylock 2020-07-24 14:47:10 +02:00
Megamouse 5e7c6853c2 fix truncation warnings 2020-07-24 14:47:10 +02:00
Megamouse f76a011ba0 fix sceNpCommerce2CreateCtx log message 2020-07-24 14:47:10 +02:00
Megamouse d854a39500 add a gazillion more error_code 2020-07-24 14:47:10 +02:00
Megamouse a00ebacef3 cellFont: add error_code 2020-07-24 14:47:10 +02:00
Megamouse c2f4244c4d cellMic: error_code, random cleanup and stubbing 2020-07-24 14:47:10 +02:00
Megamouse 7437c324c6 cellMusic: add error_code 2020-07-24 14:47:10 +02:00
Eladash 54b87b6dbb cellSaveData: Increase sleep time 2020-07-23 13:45:58 +03:00
Eladash a029a94c73 SPU: Use waitable atomics for SPU channels interface 2020-07-23 13:45:58 +03:00
illusion 3157a10428 move executable hash log level to success 2020-07-22 10:51:19 +02:00
Eladash f8d2d8ca11 SPU/Windows: Fix LS memory mirrors
This is a workaround but this is because of how utils::shm works on Windows path.
2020-07-19 17:58:49 +03:00
Eladash 0d8152cd4e SPU/Linux: Ensure aligned 64k allocations in utils::memory_reserve 2020-07-19 17:58:49 +03:00
Eladash c37bc3c55c SPU: Make spu_thread::offset private 2020-07-19 17:58:49 +03:00
Malcolm Jestadt 6cc0fe4221 SPU LLVM: Avoid negative clamping when the input is known to be positive 2020-07-19 17:56:59 +03:00
Eladash af1ceb1151 SPU LLVM: LS Memory Mirrors (Optimize loads/stores) 2020-07-18 02:01:33 +03:00
Eladash c1a80b8146 Minor fixup after #8501 2020-07-16 21:52:08 +03:00
Eladash 268bcd1c7b rsx: Fix false desync events 2020-07-16 19:26:10 +02:00
kd-11 42a9ac9e6c rsx: Brute-force removal of superseded surfaces 2020-07-16 19:11:26 +03:00
kd-11 182b20c33d rsx: Fix draw count append when draw ranges are out of order
- It is common for draw counts to truncate at 256 even when it makes no sense to do so.
- e.g 256 is not a multiple of 3 so triangles will glitch out
2020-07-14 16:04:44 +03:00
Eladash 58e2465369 Make std::bit_cast hack-implementation constexpr in simple cases 2020-07-14 12:14:44 +03:00
Eladash 07a44d0ff9 Implement constexpr byteswapping 2020-07-14 12:14:44 +03:00
Jan Beich d00f882c23 Qt/input: unbreak with Qt 5.15 after 881e8e4723
rpcs3/rpcs3qt/pad_settings_dialog.cpp:674:16: error: variable has incomplete type 'QPainterPath'
                QPainterPath path;
                             ^
/usr/local/include/qt5/QtGui/qmatrix.h:54:7: note: forward declaration of 'QPainterPath'
class QPainterPath;
      ^
2020-07-14 08:33:56 +02:00
Megamouse e70e534bfa Qt: Fix YoRHa background for some widgets 2020-07-14 02:08:15 +02:00
Megamouse d345916241 Qt: Fix Skyline's QSpinBox and QDoubleSpinBox buttons 2020-07-14 02:08:15 +02:00
Megamouse fe8bcac270 Qt/input: add tooltips to pad settings 2020-07-14 00:06:43 +02:00
illusion 60f05fdbf3 move applied patch log level to success 2020-07-13 22:33:03 +02:00
Megamouse ad0f12c742 Qt/input: add checkbox for emulated stick values 2020-07-13 21:23:48 +02:00
Megamouse 2f2a03b37b Qt/input: fix stick preview for disconnected pads 2020-07-13 21:23:48 +02:00
Megamouse 881e8e4723 Qt/input: show emulated sticks in pad settings 2020-07-13 21:23:48 +02:00
Megamouse e1af6dc4af Qt/input: add squircle to pad settings dialog 2020-07-13 21:23:48 +02:00
Megamouse 4d9533ea54 input: use left and right squircle values 2020-07-13 21:23:48 +02:00
Eladash d6623e0f22 RSX debugger: fix command count on non-method commands (#8578)
* RSX debugger: fix command count on non-method commands

* fixup

* constants and variables
2020-07-12 12:40:47 +02:00
kd-11 ab3d36f0f3 rsx: Fix depth bounds test
- Allow depth bounds test to access the Z buffer even when depth test is disabled.
2020-07-10 15:59:15 +03:00
kd-11 632af8d723 rsx: Support partial texture descriptors
- It is safe to declare w > pitch and it works as long as sampling inside the legal 2D area is obeyed.
2020-07-10 15:26:07 +03:00
Eladash 282b00674a SPU LLVM: Optimize non-constant Tag Update requests 2020-07-10 02:52:02 +03:00
Eladash 235d12aa6b SPU MFC: Never clear tag status in WrTagUpdate 2020-07-10 02:52:02 +03:00
Eladash 5d1fc546a8 SPU MFC: Fix MFC_WrTagUpdate channel count
Always report available, in realhw this is just a hint if the previous tag update hasnt been checked yet by the MFC, avoiding blocking writes and allowing the SPU to execute some code while it processes the previous update request.
Except for MFC_TAG_UPDATE_IMMEDIATE, where it also waits for MFC to process it.
2020-07-10 02:52:02 +03:00
Eladash eb993781ef RawSPU: Log MMIO access 2020-07-09 23:24:47 +03:00
Megamouse 0756fd9c7e Qt: fix pad settings resize when switching tabs 2020-07-09 08:20:37 +02:00
Megamouse a3e79fc105 Qt: fix scrollArea focus during pad button choice
Assigning arrow keys was broken because of this
2020-07-09 08:20:37 +02:00
Eladash 84470c34db SPU: Disable PUTLLC NOP transfers detection on TSX path 2020-07-09 03:17:35 +01:00
Eladash f8dbfa1d1e SPU: Implement GETLLAR polling detection 2020-07-09 03:17:35 +01:00
Eladash d9750e8f9f SPU/PPU reservations: Optimizations for reservation locks and check_state() (non-TSX) 2020-07-09 03:17:35 +01:00
Megamouse e09c4b72c8 Qt: fix update menu for linux 2020-07-08 22:21:27 +02:00
Megamouse 53b95fea19 audio: rename audio channels to audio downmix
The setting does not actually define the channels themselves, only the downmix option that the PS3 provides.
Channels might be changed seperately in the future.
2020-07-08 21:11:23 +02:00
Megamouse e2fd4e46f7 Only reboot audio if a relevant setting changed 2020-07-08 21:11:23 +02:00
Megamouse 20d6664dc1 Try to make most audio configs dynamic 2020-07-08 21:11:23 +02:00
Megamouse 8ee953ef8e XAudio2: Call CoInitializeEx to prevent errors
I could not properly reset the audio backend and call CreateMasteringVoice without getting errors
2020-07-08 21:11:23 +02:00
Megamouse 5b7ee43352 XAudio2: print readable errors 2020-07-08 21:11:23 +02:00
Megamouse 8add57f8e9 VS: show linux audio backends in solution explorer 2020-07-08 21:11:23 +02:00
Megamouse bb0aaea92d cellAudio: implement downmix to 5.1 2020-07-08 21:11:23 +02:00
kd-11 987ede2e6c vk: Inject memory barrier upon conclusion of a framebuffer feedback loop
- Do not write to the texture until previous draw call is completed using it.
- This is usually not much of a problem until blending operations come into play.
2020-07-08 19:23:29 +03:00
Megamouse 5fae1b3637 HLE: fix sceNpDrmGetTimelimit invalid param error 2020-07-07 09:43:32 +02:00
Derrik Touve cb08c53f2f sys_net: Use np_handler dns if possible for sys_net_infoctl (#8557)
Without this, cellHttpSendRequest will use the hardcoded dns 192.168.1.1, which won't work if you're not on that network.
2020-07-07 08:25:29 +02:00
Megamouse 171e4fafed Emu: simplify Emu::Stop some more 2020-07-06 21:14:16 +02:00
Megamouse 8d2ce2815c Emu: Make prevent_display_sleep dynamic 2020-07-06 21:14:16 +02:00
Megamouse d91551c277 Emu: always use Emu.Quit() to quit RPCS3
This creates a single possible point of failure for calling quit()
2020-07-06 21:14:16 +02:00
Megamouse 332f9cae77 Qt: Remove obsolete main window close()
The gui settings aren't part of the main window anymore
2020-07-06 21:14:16 +02:00
Eladash dc25a3fa2a PPU debugger: Show stack address of each function 2020-07-06 18:58:16 +02:00
Eladash c98ec4d014 PPU debugger: Fix functions stack bounds check 2020-07-06 18:58:16 +02:00
kd-11 05dc6ad610 gl: Silence warnings 2020-07-05 16:58:44 +03:00
kd-11 3fe8499956 rsx: Improve ZCULL queued requests finalization
- Unifies the code
- Allows conditionals to be evaluated with a forwarder present
2020-07-05 16:58:44 +03:00
Megamouse f1b1c9053c Input/Qt: Check if gui callbacks are nullptr 2020-07-04 14:28:19 +02:00
Megamouse ea4cc0b395 Qt: use button box for most buttons 2020-07-04 14:28:19 +02:00
Megamouse be8980fc23 Qt: add scrollarea to pad settings dialog 2020-07-04 14:28:19 +02:00
Megamouse e4a9c177e6 Qt: Random unimportant stuff 2020-07-04 14:28:19 +02:00
Megamouse 99be645fcc Qt: Add stick multipliers to the pad dialog 2020-07-04 14:28:19 +02:00
Megamouse f8920edb2e patch_manager: save "owned games only" state 2020-07-03 18:09:06 +02:00
kd-11 acf51f0ead rsx: Fix transfer descriptors for partially overlapping slices in head
- Height must be corrected to skip the piece that exists before the current slice
2020-07-03 14:29:54 +03:00
Megamouse ddd202b5ff Qt: fix signal_update_available
m_update_message has to be non empty
2020-07-03 00:21:58 +02:00
Megamouse 78eb7e73bc Qt: remove automatic param from update logic
At that point we already had user interaction, so there is no point in hiding the error dialogs
2020-07-03 00:21:58 +02:00
Eladash 72337f2678 SPU LLVM: Fix barrier commands enqueuing 2020-07-02 22:46:02 +03:00
Megamouse 14200c1a1f Qt: refactor curl stuff into a downloader
And add 'Background' updater
2020-07-02 20:22:58 +02:00
Megamouse c495ef10b0 Qt: fix random QWinTaskbarProgress crashes 2020-07-02 20:22:58 +02:00
Megamouse 3bdce6050b Qt: random cleanups 2020-07-02 20:22:58 +02:00
kd-11 c9c0d7361d rsx: Implement fast ZCULL barrier when query object is already known 2020-07-02 20:11:57 +03:00
kd-11 d7ffc8b4ac rsx: Fix leaking ZCULL queries after a barrier
- Multiple queries can be queued up, process them all before completing the barrier
2020-07-02 20:11:57 +03:00
Megamouse b5f01372ee Windows: distinguish left and right modifiers
This is just some workaround until we either use a different input api for keyboards or until we refactor the keyboard_pad_handler to use Qt with native scan codes
2020-07-02 12:55:27 +02:00
Megamouse bec6bde919 Qt/Input: update keyboard_pad_handler shortcuts
This is just some patchwork before the shortcuts get refactored eventually
2020-07-02 12:55:27 +02:00
Megamouse 1f25924384 Qt/Input: remove unused function: GetModifierCode 2020-07-02 12:55:27 +02:00
Jacques Yakoub 36cf5dca82 localized.h: follow Sony Naming Conventions (#8539)
* localized.h: follow Sony Naming Conventions

See this : https://github.com/RPCS3/rpcs3/issues/4259 (Main Window -> (Localized) Replace the category names with either something more gramatically correct or something used in Sony Naming Conventions)
2020-07-02 09:39:10 +02:00
Bird Egop eea12bad07 Implement Caret upwards and downwards move in overlay_edit_text (#8342)
* Implement caret upwards and downwards move in overlay_edit_text

* Optimize caret up and down movement

Co-authored-by: Megamouse <studienricky89@googlemail.com>
2020-07-02 09:06:37 +02:00
508 changed files with 37744 additions and 16429 deletions
+1
View File
@@ -48,6 +48,7 @@ cmake .. \
-DCMAKE_CXX_FLAGS="$CFLAGS" \
-DCMAKE_AR="$AR" \
-DCMAKE_RANLIB="$RANLIB" \
-DUSE_SYSTEM_CURL=ON \
-G Ninja
ninja; build_status=$?;
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh -ex
ARTIFACT_DIR="$BUILD_ARTIFACTSTAGINGDIRECTORY"
generate_post_data()
{
body=$(cat GitHubReleaseMessage.txt)
cat <<EOF
{
"tag_name": "build-${BUILD_SOURCEVERSION}",
"target_commitish": "7d09e3be30805911226241afbb14f8cdc2eb054e",
"name": "${AVVER}",
"body": "$body",
"draft": false,
"prerelease": false
}
EOF
}
repo_full_name="RPCS3/rpcs3-binaries-win"
curl -s \
-H "Authorization: token ${RPCS3_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
--data "$(generate_post_data)" "https://api.github.com/repos/$repo_full_name/releases" >> release.json
cat release.json
id=$(grep '"id"' release.json | cut -d ':' -f2 | head -n1 | awk '{$1=$1;print}')
id=${id%?}
echo ${id:?}
upload_file()
{
curl -s \
-H "Authorization: token ${RPCS3_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/octet-stream" \
--data-binary @"$2"/"$3" \
"https://uploads.github.com/repos/$repo_full_name/releases/$1/assets?name=$3"
}
for file in "$ARTIFACT_DIR"/*; do
name=$(basename "$file")
upload_file "$id" "$ARTIFACT_DIR" "$name"
done
+1 -1
View File
@@ -18,7 +18,7 @@ QT_DECL_URL="${QT_HOST}${QT_PREFIX}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}qttools${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/4xppf4rz8v2gd8x/VulkanSDK-${VULKAN_VER}-Installer.exe"
VULKAN_SDK_URL="https://www.dropbox.com/s/kn005de7gsv5whe/VulkanSDK-1.2.154.1-Installer.exe"
DEP_URLS=" \
$QT_BASE_URL \
+6 -3
View File
@@ -65,10 +65,13 @@
ignore = dirty
[submodule "3rdparty/curl"]
path = 3rdparty/curl
url = https://github.com/RipleyTom/curl.git
url = https://github.com/curl/curl.git
ignore = dirty
[submodule "3rdparty/wolfssl"]
path = 3rdparty/wolfssl
url = https://github.com/RipleyTom/wolfssl.git
url = https://github.com/wolfSSL/wolfssl.git
ignore = dirty
[submodule "3rdparty/flatbuffers"]
path = 3rdparty/flatbuffers
url = https://github.com/google/flatbuffers.git
ignore = dirty
+4 -4
View File
@@ -10,8 +10,8 @@ jobs:
services: docker
cache: ccache
compiler: gcc
install: "docker pull rpcs3/rpcs3-travis-xenial:1.4"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.4 /rpcs3/.ci/build-linux.sh'
install: "docker pull rpcs3/rpcs3-travis-xenial:1.6"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.6 /rpcs3/.ci/build-linux.sh'
- os: linux
dist: xenial
env:
@@ -20,8 +20,8 @@ jobs:
services: docker
cache: ccache
compiler: clang
install: "docker pull rpcs3/rpcs3-travis-xenial:1.4"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.4 /rpcs3/.ci/build-linux.sh'
install: "docker pull rpcs3/rpcs3-travis-xenial:1.6"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.6 /rpcs3/.ci/build-linux.sh'
# - os: freebsd
# compiler: clang
# cache: ccache
+3
View File
@@ -111,6 +111,9 @@
</PropertyGroup>
<Import Project="..\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="..\common_default_macros.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
+73 -18
View File
@@ -74,6 +74,9 @@ else()
add_library(3rdparty_7z INTERFACE)
endif()
add_library(3rdparty_flatbuffers INTERFACE)
target_include_directories(3rdparty_flatbuffers INTERFACE flatbuffers/include)
# libPNG
# Select the version of libpng to use, default is builtin
if (NOT USE_SYSTEM_LIBPNG)
@@ -103,6 +106,36 @@ endif()
add_subdirectory(pugixml EXCLUDE_FROM_ALL)
# libusb
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0>=1.0 )
CMAKE_DEPENDENT_OPTION( USE_SYS_LIBUSB "Use system libusb-1.0 as shared library" ON
"LIBUSB_FOUND" OFF)
else()
pkg_check_modules(LIBUSB IMPORTED_TARGET libusb-1.0>=1.0 )
CMAKE_DEPENDENT_OPTION( USE_SYS_LIBUSB "Use system libusb-1.0 as shared library" OFF
"LIBUSB_FOUND" OFF)
endif()
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
# Always use system libusb as reference implementation isn't supported
add_library(usb-1.0-shared INTERFACE)
target_link_libraries(usb-1.0-shared INTERFACE PkgConfig::LIBUSB)
elseif(MSVC)
# Windows time.h defines timespec but doesn't add any flag for it, which makes libusb attempt to define it again
add_definitions(-DHAVE_STRUCT_TIMESPEC=1)
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
else()
if(USE_SYS_LIBUSB)
# we have the system libusb and have selected to use it
add_library(usb-1.0-shared INTERFACE)
target_link_libraries(usb-1.0-shared INTERFACE PkgConfig::LIBUSB)
else()
# we don't have the system libusb, so we compile from submodule
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
endif()
endif()
# hidapi
add_library(3rdparty_hidapi INTERFACE)
target_include_directories(3rdparty_hidapi INTERFACE hidapi/hidapi)
@@ -130,24 +163,11 @@ else()
endif()
# libusb
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
# Always use system libusb as reference implementation isn't supported
add_library(usb-1.0-static INTERFACE)
target_link_libraries(usb-1.0-static INTERFACE usb)
elseif(MSVC)
# Windows time.h defines timespec but doesn't add any flag for it, which makes libusb attempt to define it again
add_definitions(-DHAVE_STRUCT_TIMESPEC=1)
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
else()
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
endif()
# yaml-cpp
# We don't want to install yaml-cpp but its cmake file doesn't have option
# to disable it...
# So we just install it to a different directory
set(YAML_CPP_INSTALL OFF CACHE BOOL "Don't install YAML")
set(CMAKE_INSTALL_PREFIX_OLD ${CMAKE_INSTALL_PREFIX})
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/yaml-cpp_install)
@@ -161,6 +181,7 @@ set(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX_OLD})
# xxHash
set(XXHASH_BUNDLED_MODE ON)
set(XXHASH_BUILD_XXHSUM OFF)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Make xxHash build static libs")
add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL)
target_include_directories(xxhash INTERFACE xxHash)
@@ -413,23 +434,57 @@ endif()
# LLVM
include(llvm.cmake)
# WOLFSSL
if(USE_SYSTEM_WOLFSSL)
message("-- RPCS3: using shared wolfssl")
find_package(WolfSSL REQUIRED)
add_library(wolfssl INTERFACE)
target_link_libraries(wolfssl INTERFACE WolfSSL_LIBRARIES)
target_include_directories(wolfssl INTERFACE WolfSSL_INCLUDE_DIRS)
else()
SET(BUILD_TESTS NO CACHE BOOL "Build test applications")
add_compile_definitions(HAVE_FFDHE_2048 TFM_TIMING_RESISTANT ECC_TIMING_RESISTANT
WC_RSA_BLINDING HAVE_AESGCM WOLFSSL_SHA512 WOLFSSL_SHA384 NO_DSA HAVE_ECC TFM_ECC256 ECC_SHAMIR
NO_RC4 NO_HC128 NO_RABBIT WOLFSSL_SHA224 WOLFSSL_SHA3 WOLFSSL_SHAKE256 HAVE_POLY1305
HAVE_ONE_TIME_AUTH HAVE_CHACHA HAVE_HASHDRBG HAVE_TLS_EXTENSIONS HAVE_SNI HAVE_SUPPORTED_CURVES
HAVE_EXTENDED_MASTER NO_RC4 HAVE_ENCRYPT_THEN_MAC NO_PSK NO_MD4
WC_NO_ASYNC_THREADING OPENSSL_EXTRA WOLFSSL_DES_ECB WC_NO_HARDEN)
set(ENABLED_HARDEN OFF CACHE BOOL "Disable Harden")
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
target_include_directories(wolfssl INTERFACE "wolfssl/")
# This is needed for CURL
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/wolfssl/options.h.in ${CMAKE_CURRENT_BINARY_DIR}/wolfssl/wolfssl/options.h)
set(WolfSSL_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/libwolfssl.a")
set(WolfSSL_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/libwolfssl.a")
set(WolfSSL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/" "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/")
set(WolfSSL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/" "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/")
endif()
# CURL
if(USE_SYSTEM_CURL)
message("-- RPCS3: using shared libcurl")
find_package(CURL REQUIRED)
add_library(wolfssl-3-static INTERFACE)
add_library(libcurl INTERFACE)
target_link_libraries(libcurl INTERFACE CURL::libcurl)
else()
message("-- RPCS3: building libcurl + wolfssl submodules")
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
option(BUILD_CURL_EXE "Set to ON to build curl executable." OFF)
option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" ON)
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" ON)
option(CURL_ZLIB "Set to ON to enable building curl with zlib support." OFF)
set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
add_subdirectory(curl EXCLUDE_FROM_ALL)
endif()
# add nice ALIAS targets for ease of use
add_library(3rdparty::libusb ALIAS usb-1.0-static)
if(USE_SYS_LIBUSB)
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
else()
add_library(3rdparty::libusb ALIAS usb-1.0-static)
endif()
add_library(3rdparty::zlib ALIAS 3rdparty_zlib)
add_library(3rdparty::7z ALIAS 3rdparty_7z)
add_library(3rdparty::flatbuffers ALIAS 3rdparty_flatbuffers)
add_library(3rdparty::pugixml ALIAS pugixml)
add_library(3rdparty::yaml-cpp ALIAS yaml-cpp)
add_library(3rdparty::xxhash ALIAS xxhash)
@@ -448,5 +503,5 @@ add_library(3rdparty::vulkan ALIAS ${VULKAN_TARGET})
add_library(3rdparty::openal ALIAS 3rdparty_openal)
add_library(3rdparty::ffmpeg ALIAS 3rdparty_ffmpeg)
add_library(3rdparty::glew ALIAS 3rdparty_glew)
add_library(3rdparty::wolfssl ALIAS wolfssl-3-static)
add_library(3rdparty::wolfssl ALIAS wolfssl)
add_library(3rdparty::libcurl ALIAS libcurl)
+1 -1
+40
View File
@@ -0,0 +1,40 @@
/* options.h.in
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* default blank options for autoconf */
#ifndef WOLFSSL_OPTIONS_H
#define WOLFSSL_OPTIONS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_OPTIONS_H */
Vendored Submodule
+1
Submodule 3rdparty/flatbuffers added at 9e7e8cbe9f
+3
View File
@@ -27,6 +27,9 @@
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+16 -2
View File
@@ -31,6 +31,9 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -48,8 +51,8 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>curl\include;curl\lib;wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_SNI;NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>curl\include;curl\lib;curl_extra;wolfssl;wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_SNI;NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;SIZEOF_LONG=4;SIZEOF_LONG_LONG=8;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
@@ -94,6 +97,7 @@
<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\escape.c" />
<ClCompile Include="curl\lib\file.c" />
@@ -132,6 +136,7 @@
<ClCompile Include="curl\lib\memdebug.c" />
<ClCompile Include="curl\lib\mime.c" />
<ClCompile Include="curl\lib\mprintf.c" />
<ClCompile Include="curl\lib\mqtt.c" />
<ClCompile Include="curl\lib\multi.c" />
<ClCompile Include="curl\lib\netrc.c" />
<ClCompile Include="curl\lib\non-ascii.c" />
@@ -175,6 +180,7 @@
<ClCompile Include="curl\lib\url.c" />
<ClCompile Include="curl\lib\urlapi.c" />
<ClCompile Include="curl\lib\version.c" />
<ClCompile Include="curl\lib\version_win32.c" />
<ClCompile Include="curl\lib\warnless.c" />
<ClCompile Include="curl\lib\wildcard.c" />
<ClCompile Include="curl\lib\x509asn1.c" />
@@ -192,12 +198,14 @@
<ClCompile Include="curl\lib\vauth\vauth.c" />
<ClCompile Include="curl\lib\vquic\ngtcp2.c" />
<ClCompile Include="curl\lib\vquic\quiche.c" />
<ClCompile Include="curl\lib\vquic\vquic.c" />
<ClCompile Include="curl\lib\vssh\libssh.c" />
<ClCompile Include="curl\lib\vssh\libssh2.c" />
<ClCompile Include="curl\lib\vssh\wolfssh.c" />
<ClCompile Include="curl\lib\vtls\bearssl.c" />
<ClCompile Include="curl\lib\vtls\gskit.c" />
<ClCompile Include="curl\lib\vtls\gtls.c" />
<ClCompile Include="curl\lib\vtls\keylog.c" />
<ClCompile Include="curl\lib\vtls\mbedtls.c" />
<ClCompile Include="curl\lib\vtls\mbedtls_threadlock.c" />
<ClCompile Include="curl\lib\vtls\mesalink.c" />
@@ -271,6 +279,7 @@
<ClInclude Include="curl\lib\dict.h" />
<ClInclude Include="curl\lib\doh.h" />
<ClInclude Include="curl\lib\dotdot.h" />
<ClInclude Include="curl\lib\dynbuf.h" />
<ClInclude Include="curl\lib\easyif.h" />
<ClInclude Include="curl\lib\escape.h" />
<ClInclude Include="curl\lib\file.h" />
@@ -297,6 +306,7 @@
<ClInclude Include="curl\lib\llist.h" />
<ClInclude Include="curl\lib\memdebug.h" />
<ClInclude Include="curl\lib\mime.h" />
<ClInclude Include="curl\lib\mqtt.h" />
<ClInclude Include="curl\lib\multihandle.h" />
<ClInclude Include="curl\lib\multiif.h" />
<ClInclude Include="curl\lib\netrc.h" />
@@ -316,6 +326,7 @@
<ClInclude Include="curl\lib\setopt.h" />
<ClInclude Include="curl\lib\setup-os400.h" />
<ClInclude Include="curl\lib\setup-vms.h" />
<ClInclude Include="curl\lib\setup-win32.h" />
<ClInclude Include="curl\lib\share.h" />
<ClInclude Include="curl\lib\sigpipe.h" />
<ClInclude Include="curl\lib\slist.h" />
@@ -339,6 +350,7 @@
<ClInclude Include="curl\lib\url.h" />
<ClInclude Include="curl\lib\urlapi-int.h" />
<ClInclude Include="curl\lib\urldata.h" />
<ClInclude Include="curl\lib\version_win32.h" />
<ClInclude Include="curl\lib\warnless.h" />
<ClInclude Include="curl\lib\wildcard.h" />
<ClInclude Include="curl\lib\x509asn1.h" />
@@ -347,11 +359,13 @@
<ClInclude Include="curl\lib\vauth\vauth.h" />
<ClInclude Include="curl\lib\vquic\ngtcp2.h" />
<ClInclude Include="curl\lib\vquic\quiche.h" />
<ClInclude Include="curl\lib\vquic\vquic.h" />
<ClInclude Include="curl\lib\vssh\ssh.h" />
<ClInclude Include="curl\lib\vssh\wolfssh.h" />
<ClInclude Include="curl\lib\vtls\bearssl.h" />
<ClInclude Include="curl\lib\vtls\gskit.h" />
<ClInclude Include="curl\lib\vtls\gtls.h" />
<ClInclude Include="curl\lib\vtls\keylog.h" />
<ClInclude Include="curl\lib\vtls\mbedtls.h" />
<ClInclude Include="curl\lib\vtls\mbedtls_threadlock.h" />
<ClInclude Include="curl\lib\vtls\mesalink.h" />
+4 -1
View File
@@ -28,6 +28,9 @@
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Library|x64'" Label="PropertySheets">
@@ -97,7 +100,7 @@
<DisableSpecificWarnings>$(DisableSpecificWarnings)</DisableSpecificWarnings>
<AdditionalIncludeDirectories>$(ZLibSrcDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>$(TreatWarningAsError)</TreatWarningAsError>
<Optimization>Full</Optimization>
<Optimization>MaxSpeed</Optimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
+7 -4
View File
@@ -6,6 +6,7 @@ if (CMAKE_USE_PTHREADS_INIT)
endif()
if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
add_compile_definitions(PLATFORM_WINDOWS=1)
set(OS_WINDOWS 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
# Enable MingW support for RC language (for CMake pre-2.8)
@@ -22,9 +23,9 @@ if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
endif()
list(APPEND PLATFORM_SRC
poll_windows.c
events_windows.c
windows_usbdk.c
windows_nt_common.c
windows_common.c
windows_winusb.c
threads_windows.c
)
@@ -36,13 +37,14 @@ if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
endif()
elseif (APPLE)
# Apple != OSX alone
add_compile_definitions(PLATFORM_POSIX=1 HAVE_CLOCK_GETTIME)
set(OS_DARWIN 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(PLATFORM_SRC
darwin_usb.c
threads_posix.c
poll_posix.c
events_posix.c
)
find_package(IOKit REQUIRED)
@@ -72,6 +74,7 @@ int main()
endif()
elseif (UNIX)
# Unix is for all *NIX systems including OSX
add_compile_definitions(PLATFORM_POSIX=1 HAVE_CLOCK_GETTIME)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(OS_LINUX 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
@@ -79,7 +82,7 @@ elseif (UNIX)
linux_usbfs.c
linux_netlink.c
threads_posix.c
poll_posix.c
events_posix.c
)
list(APPEND LIBUSB_LIBRARIES rt)
+8 -6
View File
@@ -24,6 +24,9 @@
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -38,8 +41,9 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>libusb\msvc;libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WINVER=0x0600;_WIN32_WINNT=0x0600;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
@@ -61,11 +65,11 @@
<ClCompile Include="libusb\libusb\descriptor.c" />
<ClCompile Include="libusb\libusb\hotplug.c" />
<ClCompile Include="libusb\libusb\io.c" />
<ClCompile Include="libusb\libusb\os\poll_windows.c" />
<ClCompile Include="libusb\libusb\os\events_windows.c" />
<ClCompile Include="libusb\libusb\strerror.c" />
<ClCompile Include="libusb\libusb\sync.c" />
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
<ClCompile Include="libusb\libusb\os\windows_nt_common.c" />
<ClCompile Include="libusb\libusb\os\windows_common.c" />
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
</ItemGroup>
@@ -74,13 +78,11 @@
<ClInclude Include="libusb\libusb\hotplug.h" />
<ClInclude Include="libusb\libusb\libusb.h" />
<ClInclude Include="libusb\libusb\libusbi.h" />
<ClInclude Include="libusb\libusb\os\poll_windows.h" />
<ClInclude Include="libusb\libusb\os\events_windows.h" />
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
<ClInclude Include="libusb\libusb\version.h" />
<ClInclude Include="libusb\libusb\version_nano.h" />
<ClInclude Include="libusb\libusb\os\windows_common.h" />
<ClInclude Include="libusb\libusb\os\windows_nt_common.h" />
<ClInclude Include="libusb\libusb\os\windows_nt_shared_types.h" />
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
</ItemGroup>
-1
View File
@@ -11,7 +11,6 @@ if(WITH_LLVM)
option(LLVM_INCLUDE_TESTS OFF)
option(LLVM_INCLUDE_TOOLS OFF)
option(LLVM_INCLUDE_UTILS OFF)
option(WITH_POLLY OFF)
option(LLVM_CCACHE_BUILD ON)
set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS})
+3
View File
@@ -21,6 +21,9 @@
</PropertyGroup>
<Import Project="$(SolutionDir)\3rdparty\zlib.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+5 -2
View File
@@ -28,6 +28,9 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
@@ -45,7 +48,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;ECC_TIMING_RESISTANT;WC_RSA_BLINDING;HAVE_AESGCM;WOLFSSL_SHA512;WOLFSSL_SHA384;NO_DSA;HAVE_ECC;TFM_ECC256;ECC_SHAMIR;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_TLS_EXTENSIONS;HAVE_SNI;HAVE_SUPPORTED_CURVES;HAVE_EXTENDED_MASTER;NO_RC4;HAVE_ENCRYPT_THEN_MAC;NO_PSK;NO_MD4;WC_NO_ASYNC_THREADING;OPENSSL_EXTRA;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -59,7 +62,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WC_NO_HARDEN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
+7 -1
View File
@@ -27,6 +27,9 @@
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -41,7 +44,10 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="xxHash/xxhash.c" />
+4
View File
@@ -22,6 +22,9 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
@@ -40,6 +43,7 @@
<ItemDefinitionGroup>
<ClCompile>
<ExceptionHandling>Sync</ExceptionHandling>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
+4 -1
View File
@@ -31,6 +31,9 @@
<Import Project="$(SolutionDir)\3rdparty\zlib.props" />
<Import Project="..\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="..\common_default_macros.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -79,7 +82,7 @@
<ClCompile>
<WarningLevel>$(WarningLevel)</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Full</Optimization>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<WholeProgramOptimization>true</WholeProgramOptimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
+9 -9
View File
@@ -13,7 +13,7 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
* [Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
* [Vulkan SDK 1.1.126+](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.14.2\msvc2017_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools-19123)**
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.14.2\msvc2017_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
### Linux
@@ -40,11 +40,11 @@ Ubuntu is usually horrendously out of date, and some packages need to be downloa
Ubuntu usually does not have a new enough Qt package to suit rpcs3's needs. There is a PPA available to work around this. Run the following:
```
ucodename=$(lsb_release -sc)
sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-$ucodename
. /etc/os-release
sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-$UBUNTU_CODENAME
sudo apt-get update
. /opt/qt514/bin/qt514-env.sh >/dev/null 2>&1
sudo apt-get install qt514-meta-minimal qt514svg
. /opt/qt514/bin/qt514-env.sh >/dev/null 2>&1
```
##### GCC 9.x installation
@@ -62,22 +62,22 @@ You can either use `update-alternatives` to setup `gcc-9`/`g++-9` as your defaul
For Ubuntu systems, it is strongly recommended to use the PPA from [LunarG](https://packages.lunarg.com/) which will provide a compatible Vulkan SDK to compile RPCS3. If your Vulkan SDK is older, it can lead to compilation errors.
```
ucodename=$(lsb_release -sc)
wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.1.126-$ucodename.list http://packages.lunarg.com/vulkan/1.1.126/lunarg-vulkan-1.1.126-$ucodename.list
. /etc/os-release
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.148/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list
sudo apt update
sudo apt install vulkan-sdk
```
##### CMake
```
. /etc/os-release
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add -
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -sc) main"
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $UBUNTU_CODENAME main"
sudo apt-get update
sudo apt-get install kitware-archive-keyring
sudo apt-key --keyring /etc/apt/trusted.gpg del C1F34CDD40CD72DA
sudo apt-get install cmake
```
#### Fedora
+4 -4
View File
@@ -492,10 +492,10 @@ template <typename T>
using to_le_t = typename to_se<T, std::endian::big == std::endian::native>::type;
// BE/LE aliases for atomic_t
template <typename T>
using atomic_be_t = atomic_t<be_t<T>>;
template <typename T>
using atomic_le_t = atomic_t<le_t<T>>;
template <typename T, std::size_t Align = alignof(T)>
using atomic_be_t = atomic_t<be_t<T>, Align>;
template <typename T, std::size_t Align = alignof(T)>
using atomic_le_t = atomic_t<le_t<T>, Align>;
template <typename T, bool Se, std::size_t Align>
struct fmt_unveil<se_t<T, Se, Align>, void>
+1 -1
View File
@@ -147,7 +147,7 @@ struct bf_t : bf_base<T, N>
bf_t& operator &=(vtype right)
{
this->m_data &= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
this->m_data &= static_cast<vtype>(((static_cast<utype>(right) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos));
return *this;
}
+6 -1
View File
@@ -203,6 +203,11 @@ namespace cfg
return m_value;
}
void set(T value)
{
m_value = value;
}
void from_default() override
{
m_value = def;
@@ -384,7 +389,7 @@ namespace cfg
using uint64 = uint<0, UINT64_MAX>;
// Simple string entry with mutex
class string final : public _base
class string : public _base
{
const std::string m_name;
+190 -118
View File
@@ -322,26 +322,12 @@ std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name,
std::string fs::get_parent_dir(const std::string& path)
{
// Search upper bound (set to the last character, npos for empty string)
auto last = path.size() - 1;
// Get (basically) processed path
const auto real_path = fs::escape_path(path);
#ifdef _WIN32
const auto& delim = "/\\";
#else
const auto& delim = "/";
#endif
const auto pos = real_path.find_last_of(delim);
while (true)
{
const auto pos = path.find_last_of(delim, last, sizeof(delim) - 1);
// Contiguous slashes are ignored at the end
if (std::exchange(last, pos - 1) != pos)
{
// Return empty string if the path doesn't contain at least 2 elements
return path.substr(0, pos != umax && path.find_last_not_of(delim, pos, sizeof(delim) - 1) != umax ? pos : 0);
}
}
return real_path.substr(0, pos == umax ? 0 : pos);
}
bool fs::stat(const std::string& path, stat_t& info)
@@ -352,16 +338,83 @@ bool fs::stat(const std::string& path, stat_t& info)
}
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
std::string_view epath = path;
// '/' and '\\' Not allowed by FindFirstFileExW at the end of path but we should allow it
if (auto not_del = epath.find_last_not_of(delim); not_del != umax && not_del != epath.size() - 1)
{
epath.remove_suffix(epath.size() - 1 - not_del);
}
// Handle drives specially
if (epath.find_first_of(delim) == umax && epath.ends_with(':'))
{
WIN32_FILE_ATTRIBUTE_DATA attrs;
// Must end with a delimiter
if (!GetFileAttributesExW(to_wchar(std::string(epath) + '/').get(), GetFileExInfoStandard, &attrs))
{
g_tls_error = to_error(GetLastError());
return false;
}
info.is_directory = true; // Handle drives as directories
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = attrs.nFileSizeLow | (u64{attrs.nFileSizeHigh} << 32);
info.atime = to_time(attrs.ftLastAccessTime);
info.mtime = to_time(attrs.ftLastWriteTime);
info.ctime = info.mtime;
if (info.atime < info.mtime)
info.atime = info.mtime;
return true;
}
WIN32_FIND_DATA attrs;
// Allowed by FindFirstFileExW but we should not allow it
if (epath.ends_with("*"))
{
g_tls_error = fs::error::noent;
return false;
}
const auto wchar_ptr = to_wchar(std::string(epath));
const std::wstring_view wpath_view = wchar_ptr.get();
const HANDLE handle = FindFirstFileExW(wpath_view.data(), FindExInfoStandard, &attrs, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_CASE_SENSITIVE);
if (handle == INVALID_HANDLE_VALUE)
{
g_tls_error = to_error(GetLastError());
return false;
}
struct close_t
{
HANDLE handle;
~close_t() { FindClose(handle); }
};
for (close_t find_manage{handle}; attrs.cFileName != wpath_view.substr(wpath_view.find_last_of(wdelim) + 1);)
{
if (!FindNextFileW(handle, &attrs))
{
if (const DWORD err = GetLastError(); err != ERROR_NO_MORE_FILES)
{
g_tls_error = to_error(err);
return false;
}
g_tls_error = fs::error::noent;
return false;
}
}
info.is_directory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = (u64)attrs.nFileSizeLow | ((u64)attrs.nFileSizeHigh << 32);
info.size = attrs.nFileSizeLow | (u64{attrs.nFileSizeHigh} << 32);
info.atime = to_time(attrs.ftLastAccessTime);
info.mtime = to_time(attrs.ftLastWriteTime);
info.ctime = info.mtime;
@@ -389,73 +442,19 @@ bool fs::stat(const std::string& path, stat_t& info)
bool fs::exists(const std::string& path)
{
if (auto device = get_virtual_device(path))
{
stat_t info;
return device->stat(path, info);
}
#ifdef _WIN32
if (GetFileAttributesW(to_wchar(path).get()) == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
return true;
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
return true;
#endif
fs::stat_t info{};
return fs::stat(path, info);
}
bool fs::is_file(const std::string& path)
{
if (auto device = get_virtual_device(path))
fs::stat_t info{};
if (!fs::stat(path, info))
{
stat_t info;
if (!device->stat(path, info))
{
return false;
}
if (info.is_directory)
{
g_tls_error = error::exist;
return false;
}
return true;
}
#ifdef _WIN32
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
#endif
// TODO: correct file type check
#ifdef _WIN32
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)
#else
if (S_ISDIR(file_info.st_mode))
#endif
if (info.is_directory)
{
g_tls_error = error::exist;
return false;
@@ -466,44 +465,13 @@ bool fs::is_file(const std::string& path)
bool fs::is_dir(const std::string& path)
{
if (auto device = get_virtual_device(path))
fs::stat_t info{};
if (!fs::stat(path, info))
{
stat_t info;
if (!device->stat(path, info))
{
return false;
}
if (info.is_directory == false)
{
g_tls_error = error::exist;
return false;
}
return true;
}
#ifdef _WIN32
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
#endif
#ifdef _WIN32
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
#else
if (!S_ISDIR(file_info.st_mode))
#endif
if (!info.is_directory)
{
g_tls_error = error::exist;
return false;
@@ -781,7 +749,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
// sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytes_copied = 0;
struct ::stat fileinfo = { 0 };
if (::fstat(input, &fileinfo) || ::sendfile(output, input, &bytes_copied, fileinfo.st_size))
if (::fstat(input, &fileinfo) == -1 || ::sendfile(output, input, &bytes_copied, fileinfo.st_size) == -1)
#else
#error "Native file copy implementation is missing"
#endif
@@ -899,7 +867,7 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
#ifdef _WIN32
// Open the file
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
g_tls_error = to_error(GetLastError());
@@ -985,7 +953,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
disp = mode & fs::trunc ? TRUNCATE_EXISTING : OPEN_EXISTING;
}
DWORD share = 0;
DWORD share = FILE_SHARE_DELETE;
if (!(mode & fs::unread) || !(mode & fs::write))
{
share |= FILE_SHARE_READ;
@@ -993,7 +961,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
if (!(mode & (fs::lock + fs::unread)) || !(mode & fs::write))
{
share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
share |= FILE_SHARE_WRITE;
}
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -1634,6 +1602,110 @@ bool fs::remove_all(const std::string& path, bool remove_root)
return true;
}
std::string fs::escape_path(std::string_view path)
{
std::string real; real.resize(path.size());
auto get_char = [&](std::size_t& from, std::size_t& to, std::size_t count)
{
std::memcpy(&real[to], &path[from], count);
from += count, to += count;
};
std::size_t i = 0, j = -1, pos_nondelim = 0, after_delim = 0;
if (i < path.size())
{
j = 0;
}
for (; i < path.size();)
{
real[j] = path[i];
#ifdef _Win32
if (real[j] == '\\')
{
real[j] = '/';
}
#endif
// If the current character was preceeded by a delimiter special treatment is required:
// If another deleimiter is encountered, remove it (do not write it to output string)
// Otherwise test if it is a "." or ".." sequence.
if (std::exchange(after_delim, path[i] == delim[0] || path[i] == delim[1]))
{
if (!after_delim)
{
if (real[j] == '.')
{
if (i + 1 == path.size())
{
break;
}
get_char(i, j, 1);
switch (real[j])
{
case '.':
{
bool remove_element = true;
std::size_t k = 1;
for (; k + i != path.size(); k++)
{
switch (path[i + k])
{
case '.': continue;
case delim[0]: case delim[1]: break;
default: remove_element = false; break;
}
}
if (remove_element)
{
if (i == 1u)
{
j = pos_nondelim;
real[j] = '\0';// Ensure termination at this posistion
after_delim = true;
i += k;
continue;
}
}
get_char(i, j, k);
continue;
}
case '/':
{
i++;
after_delim = true;
continue;
}
default: get_char(i, j, 1); continue;
}
}
pos_nondelim = j;
get_char(i, j, 1);
}
else
{
i++;
}
}
else
{
get_char(i, j, 1);
}
}
if (j != umax && (real[j] == delim[0] || real[j] == delim[1])) j--; // Do not include a delmiter at the end
real.resize(j + 1);
return real;
}
u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
{
u64 result = 0;
+9 -2
View File
@@ -8,12 +8,15 @@
#include <vector>
#include <algorithm>
namespace fs
{
#ifdef _WIN32
static constexpr auto& delim = "/\\";
static constexpr auto& wdelim = L"/\\";
using native_handle = void*;
#else
static constexpr auto& delim = "/";
static constexpr auto& wdelim = L"/";
using native_handle = int;
#endif
@@ -498,6 +501,9 @@ namespace fs
// Get common cache directory
const std::string& get_cache_dir();
// Get real path for comparisons (TODO: investigate std::filesystem::path::compare implementation)
std::string escape_path(std::string_view path);
// Delete directory and all its contents recursively
bool remove_all(const std::string& path, bool remove_root = true);
@@ -628,7 +634,8 @@ namespace fs
template <typename... Args>
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
{
if (fs::file f{path, mode})
// Always use write flag, remove read flag
if (fs::file f{path, mode + fs::write - fs::read})
{
// Write args sequentially
(f.write(args), ...);
+130 -599
View File
@@ -82,7 +82,7 @@ static u8* add_jit_memory(std::size_t size, uint align)
if (pos == umax) [[unlikely]]
{
jit_log.warning("JIT: Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
jit_log.error("JIT: Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
return nullptr;
}
@@ -194,56 +194,78 @@ void jit_runtime::finalize() noexcept
std::memcpy(alloc(s_data_init.size(), 1, false), s_data_init.data(), s_data_init.size());
}
asmjit::JitRuntime& asmjit::get_global_runtime()
asmjit::Runtime& asmjit::get_global_runtime()
{
// 16 MiB for internal needs
static constexpr u64 size = 1024 * 1024 * 16;
struct custom_runtime final : asmjit::HostRuntime
{
custom_runtime() noexcept
{
// Search starting in first 2 GiB of memory
for (u64 addr = size;; addr += size)
{
if (auto ptr = utils::memory_reserve(size, reinterpret_cast<void*>(addr)))
{
m_pos.raw() = static_cast<std::byte*>(ptr);
break;
}
}
// Initialize "end" pointer
m_max = m_pos + size;
// Make memory writable + executable
utils::memory_commit(m_pos, size, utils::protection::wx);
}
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override
{
std::size_t codeSize = code->getCodeSize();
if (!codeSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoCodeGenerated;
}
void* p = m_pos.fetch_add(::align(codeSize, 4096));
if (!p || m_pos > m_max) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoVirtualMemory;
}
std::size_t relocSize = code->relocate(p);
if (!relocSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorInvalidState;
}
utils::memory_protect(p, ::align(codeSize, 4096), utils::protection::rx);
flush(p, relocSize);
*dst = p;
return asmjit::kErrorOk;
}
asmjit::Error _release(void* ptr) noexcept override
{
return asmjit::kErrorOk;
}
private:
atomic_t<std::byte*> m_pos{};
std::byte* m_max{};
};
// Magic static
static asmjit::JitRuntime g_rt;
static custom_runtime g_rt;
return g_rt;
}
void asmjit::build_transaction_enter(asmjit::X86Assembler& c, asmjit::Label fallback, const asmjit::X86Gp& ctr, uint less_than)
{
Label fall = c.newLabel();
Label begin = c.newLabel();
c.jmp(begin);
c.bind(fall);
if (less_than < 65)
{
c.add(ctr, 1);
c.test(x86::eax, _XABORT_RETRY);
c.jz(fallback);
}
else
{
// Don't repeat on explicit XABORT instruction (workaround)
c.test(x86::eax, _XABORT_EXPLICIT);
c.jnz(fallback);
// Count an attempt without RETRY flag as 65 normal attempts and continue
c.push(x86::rax);
c.not_(x86::eax);
c.and_(x86::eax, _XABORT_RETRY);
c.shl(x86::eax, 5);
c.add(x86::eax, 1); // eax = RETRY ? 1 : 65
c.add(ctr, x86::rax);
c.pop(x86::rax);
}
c.cmp(ctr, less_than);
c.jae(fallback);
c.align(kAlignCode, 16);
c.bind(begin);
c.xbegin(fall);
}
void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code)
{
c.db(0xc6);
c.db(0xf8);
c.db(code);
}
#ifdef LLVM_AVAILABLE
#include <unordered_map>
@@ -263,9 +285,9 @@ void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code
#endif
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#ifdef _MSC_VER
#pragma warning(pop)
@@ -279,290 +301,35 @@ void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code
#include <sys/mman.h>
#endif
class LLVMSegmentAllocator
const bool jit_initialize = []() -> bool
{
public:
// Size of virtual memory area reserved: default 512MB
static constexpr u32 DEFAULT_SEGMENT_SIZE = 0x20000000;
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
LLVMLinkInMCJIT();
return true;
}();
LLVMSegmentAllocator()
{
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
LLVMLinkInMCJIT();
// Try to reserve as much virtual memory in the first 2 GB address space beforehand, if possible.
Segment found_segs[16];
u32 num_segs = 0;
#ifdef MAP_32BIT
u64 max_size = 0x80000000u;
while (num_segs < 16)
{
auto ptr = ::mmap(nullptr, max_size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, 0);
if (ptr != reinterpret_cast<void*>(-1))
found_segs[num_segs++] = Segment(ptr, static_cast<u32>(max_size));
else if (max_size > 0x1000000)
max_size -= 0x1000000;
else
break;
}
#else
u64 start_addr = 0x10000000;
while (num_segs < 16)
{
u64 max_addr = 0;
u64 max_size = 0x1000000;
for (u64 addr = start_addr; addr <= (0x80000000u - max_size); addr += 0x1000000)
{
for (auto curr_size = max_size; (0x80000000u - curr_size) >= addr; curr_size += 0x1000000)
{
if (auto ptr = utils::memory_reserve(curr_size, reinterpret_cast<void*>(addr)))
{
if (max_addr == 0 || max_size < curr_size)
{
max_addr = addr;
max_size = curr_size;
}
utils::memory_release(ptr, curr_size);
}
else
break;
}
}
if (max_addr == 0)
break;
if (auto ptr = utils::memory_reserve(max_size, reinterpret_cast<void*>(max_addr)))
found_segs[num_segs++] = Segment(ptr, static_cast<u32>(max_size));
start_addr = max_addr + max_size;
}
#endif
if (num_segs)
{
if (num_segs > 1)
{
m_segs.resize(num_segs);
for (u32 i = 0; i < num_segs; i++)
m_segs[i] = found_segs[i];
}
else
m_curr = found_segs[0];
return;
}
if (auto ptr = utils::memory_reserve(DEFAULT_SEGMENT_SIZE))
{
m_curr.addr = static_cast<u8*>(ptr);
m_curr.size = DEFAULT_SEGMENT_SIZE;
m_curr.used = 0;
}
}
void* allocate(u32 size)
{
if (m_curr.remaining() >= size)
return m_curr.advance(size);
if (reserve(size))
return m_curr.advance(size);
return nullptr;
}
bool reserve(u32 size)
{
if (size == 0)
return true;
store_curr();
u32 best_idx = UINT_MAX;
for (u32 i = 0, segs_size = ::size32(m_segs); i < segs_size; i++)
{
const auto seg_remaining = m_segs[i].remaining();
if (seg_remaining < size)
continue;
if (best_idx == UINT_MAX || m_segs[best_idx].remaining() > seg_remaining)
best_idx = i;
}
if (best_idx == UINT_MAX)
{
const auto size_to_reserve = (size > DEFAULT_SEGMENT_SIZE) ? ::align(size+4096, 4096) : DEFAULT_SEGMENT_SIZE;
if (auto ptr = utils::memory_reserve(size_to_reserve))
{
best_idx = ::size32(m_segs);
m_segs.emplace_back(ptr, size_to_reserve);
}
else
return false;
}
const auto& best_seg = m_segs[best_idx];
if (best_seg.addr != m_curr.addr)
m_curr = best_seg;
return true;
}
std::pair<u64, u32> current_segment() const
{
return std::make_pair(reinterpret_cast<u64>(m_curr.addr), m_curr.size);
}
std::pair<u64, u32> find_segment(u64 addr) const
{
for (const auto& seg: m_segs)
{
const u64 seg_addr = reinterpret_cast<u64>(seg.addr);
if (addr < seg_addr)
continue;
const auto end_addr = seg_addr + seg.size;
if (addr < end_addr)
return std::make_pair(seg_addr, seg.size);
}
return std::make_pair(0, 0);
}
void reset()
{
if (m_segs.empty())
{
if (m_curr.addr != nullptr)
{
utils::memory_decommit(m_curr.addr, m_curr.size);
m_curr.used = 0;
}
return;
}
if (store_curr())
m_curr = Segment();
auto allocated_it = std::remove_if(m_segs.begin(), m_segs.end(), [](const Segment& seg)
{
return reinterpret_cast<u64>(seg.addr + seg.size) > 0x80000000u;
});
if (allocated_it != m_segs.end())
{
for (auto it = allocated_it; it != m_segs.end(); ++it)
utils::memory_release(it->addr, it->size);
m_segs.erase(allocated_it, m_segs.end());
}
for (auto& seg : m_segs)
{
utils::memory_decommit(seg.addr, seg.size);
seg.used = 0;
}
}
private:
bool store_curr()
{
if (m_curr.addr != nullptr)
{
const auto wanted_addr = m_curr.addr;
auto existing_it = std::find_if(m_segs.begin(), m_segs.end(), [wanted_addr](const Segment& seg) { return seg.addr == wanted_addr; });
if (existing_it != m_segs.end())
existing_it->used = m_curr.used;
else
m_segs.push_back(m_curr);
return true;
}
return false;
}
struct Segment
{
Segment() {}
Segment(void* addr, u32 size)
: addr(static_cast<u8*>(addr))
, size(size)
{}
u8* addr = nullptr;
u32 size = 0;
u32 used = 0;
u32 remaining() const
{
if (size > used)
return size - used;
return 0;
}
void* advance(u32 offset)
{
const auto prev_used = used;
used += offset;
return &addr[prev_used];
}
};
Segment m_curr;
std::vector<Segment> m_segs;
};
// Memory manager mutex
static shared_mutex s_mutex;
// LLVM Memory allocator
static LLVMSegmentAllocator s_alloc;
#ifdef _WIN32
static std::deque<std::pair<u64, std::vector<RUNTIME_FUNCTION>>> s_unwater;
static std::vector<std::vector<RUNTIME_FUNCTION>> s_unwind; // .pdata
#else
static std::deque<std::pair<u8*, std::size_t>> s_unfire;
#endif
// Reset memory manager
extern void jit_finalize()
// Simple memory manager
struct MemoryManager1 : llvm::RTDyldMemoryManager
{
#ifdef _WIN32
for (auto&& unwind : s_unwind)
{
if (!RtlDeleteFunctionTable(unwind.data()))
{
jit_log.fatal("RtlDeleteFunctionTable() failed! Error %u", GetLastError());
}
}
s_unwind.clear();
#else
for (auto&& t : s_unfire)
{
llvm::RTDyldMemoryManager::deregisterEHFramesInProcess(t.first, t.second);
}
s_unfire.clear();
#endif
s_alloc.reset();
}
// Helper class
struct MemoryManager : llvm::RTDyldMemoryManager
{
std::unordered_map<std::string, u64>& m_link;
std::array<u8, 16>* m_tramps{};
u8* m_code_addr{}; // TODO
MemoryManager(std::unordered_map<std::string, u64>& table)
: m_link(table)
// 256 MiB for code or data
static constexpr u64 c_max_size = 0x20000000 / 2;
// Allocation unit
static constexpr u64 c_page_size = 4096;
// Reserve 512 MiB
u8* const ptr = static_cast<u8*>(utils::memory_reserve(c_max_size * 2));
u64 code_ptr = 0;
u64 data_ptr = c_max_size;
MemoryManager1() = default;
~MemoryManager1() override
{
utils::memory_release(ptr, c_max_size * 2);
}
[[noreturn]] static void null()
@@ -572,185 +339,64 @@ struct MemoryManager : llvm::RTDyldMemoryManager
llvm::JITSymbol findSymbol(const std::string& name) override
{
auto& addr = m_link[name];
u64 addr = RTDyldMemoryManager::getSymbolAddress(name);
// Find function address
if (!addr)
{
addr = RTDyldMemoryManager::getSymbolAddress(name);
if (addr)
{
jit_log.warning("LLVM: Symbol requested: %s -> 0x%016llx", name, addr);
}
else
{
jit_log.error("LLVM: Linkage failed: %s", name);
addr = reinterpret_cast<u64>(null);
}
}
// Verify address for small code model
const u64 code_start = reinterpret_cast<u64>(m_code_addr);
const s64 addr_diff = addr - code_start;
if (addr_diff < INT_MIN || addr_diff > INT_MAX)
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Allocate memory for trampolines
if (m_tramps)
{
const s64 tramps_diff = reinterpret_cast<u64>(m_tramps) - code_start;
if (tramps_diff < INT_MIN || tramps_diff > INT_MAX)
m_tramps = nullptr; //previously allocated trampoline section too far away now
}
if (!m_tramps)
{
m_tramps = reinterpret_cast<decltype(m_tramps)>(s_alloc.allocate(4096));
utils::memory_commit(m_tramps, 4096, utils::protection::wx);
}
// Create a trampoline
auto& data = *m_tramps++;
data[0x0] = 0xff; // JMP [rip+2]
data[0x1] = 0x25;
data[0x2] = 0x02;
data[0x3] = 0x00;
data[0x4] = 0x00;
data[0x5] = 0x00;
data[0x6] = 0x48; // MOV rax, imm64 (not executed)
data[0x7] = 0xb8;
std::memcpy(data.data() + 8, &addr, 8);
addr = reinterpret_cast<u64>(&data);
// Reset pointer (memory page exhausted)
if ((reinterpret_cast<u64>(m_tramps) % 4096) == 0)
{
m_tramps = nullptr;
}
addr = reinterpret_cast<uptr>(&null);
}
return {addr, llvm::JITSymbolFlags::Exported};
}
bool needsToReserveAllocationSpace() override { return true; }
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize, uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) override
u8* allocate(u64& oldp, std::uintptr_t size, uint align, utils::protection prot)
{
const u32 wanted_code_size = ::align(static_cast<u32>(CodeSize), std::min(4096u, CodeAlign));
const u32 wanted_rodata_size = ::align(static_cast<u32>(RODataSize), std::min(4096u, RODataAlign));
const u32 wanted_rwdata_size = ::align(static_cast<u32>(RWDataSize), std::min(4096u, RWDataAlign));
if (align > c_page_size)
{
jit_log.fatal("JIT: Unsupported alignment (size=0x%x, align=0x%x)", size, align);
return nullptr;
}
// Lock memory manager
std::lock_guard lock(s_mutex);
const u64 olda = ::align(oldp, align);
const u64 newp = ::align(olda + size, align);
// Setup segment for current module if needed
s_alloc.reserve(wanted_code_size + wanted_rodata_size + wanted_rwdata_size);
if ((newp - 1) / c_max_size != oldp / c_max_size)
{
jit_log.fatal("JIT: Out of memory (size=0x%x, align=0x%x)", size, align);
return nullptr;
}
if ((oldp - 1) / c_page_size != (newp - 1) / c_page_size)
{
// Allocate pages on demand
const u64 pagea = ::align(oldp, c_page_size);
const u64 psize = ::align(newp - pagea, c_page_size);
utils::memory_commit(this->ptr + pagea, psize, prot);
}
// Update allocation counter
oldp = newp;
return this->ptr + olda;
}
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
void* ptr = nullptr;
const u32 wanted_size = ::align(static_cast<u32>(size), 4096);
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Simple allocation
ptr = s_alloc.allocate(wanted_size);
}
if (ptr == nullptr)
{
jit_log.fatal("LLVM: Out of memory (size=0x%llx, aligned 0x%x)", size, align);
return nullptr;
}
utils::memory_commit(ptr, size, utils::protection::wx);
m_code_addr = static_cast<u8*>(ptr);
jit_log.notice("LLVM: Code section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x)", sec_id, sec_name.data(), ptr, size, align);
return static_cast<u8*>(ptr);
return allocate(code_ptr, size, align, utils::protection::wx);
}
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
void* ptr = nullptr;
const u32 wanted_size = ::align(static_cast<u32>(size), 4096);
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Simple allocation
ptr = s_alloc.allocate(wanted_size);
}
if (ptr == nullptr)
{
jit_log.fatal("LLVM: Out of memory (size=0x%llx, aligned 0x%x)", size, align);
return nullptr;
}
if (!is_ro)
{
}
utils::memory_commit(ptr, size);
jit_log.notice("LLVM: Data section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), ptr, size, align, is_ro ? "ro" : "rw");
return static_cast<u8*>(ptr);
return allocate(data_ptr, size, align, utils::protection::rw);
}
bool finalizeMemory(std::string* = nullptr) override
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// TODO: make only read-only sections read-only
//#ifdef _WIN32
// DWORD op;
// VirtualProtect(s_memory, (u64)m_next - (u64)s_memory, PAGE_READONLY, &op);
// VirtualProtect(s_code_addr, s_code_size, PAGE_EXECUTE_READ, &op);
//#else
// ::mprotect(s_memory, (u64)m_next - (u64)s_memory, PROT_READ);
// ::mprotect(s_code_addr, s_code_size, PROT_READ | PROT_EXEC);
//#endif
return false;
}
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
{
// Lock memory manager
std::lock_guard lock(s_mutex);
#ifdef _WIN32
// Fix RUNTIME_FUNCTION records (.pdata section)
decltype(s_unwater)::value_type pdata_entry = std::move(s_unwater.front());
s_unwater.pop_front();
// Use given memory segment as a BASE, compute the difference
const u64 segment_start = pdata_entry.first;
const u64 unwind_diff = (u64)addr - segment_start;
auto& pdata = pdata_entry.second;
for (auto& rf : pdata)
{
rf.UnwindData += static_cast<DWORD>(unwind_diff);
}
// Register .xdata UNWIND_INFO structs
if (!RtlAddFunctionTable(pdata.data(), (DWORD)pdata.size(), segment_start))
{
jit_log.error("RtlAddFunctionTable() failed! Error %u", GetLastError());
}
else
{
s_unwind.emplace_back(std::move(pdata));
}
#else
s_unfire.push_front(std::make_pair(addr, size));
#endif
return RTDyldMemoryManager::registerEHFramesInProcess(addr, size);
}
void deregisterEHFrames() override
@@ -784,14 +430,6 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
{
#ifndef _WIN32
RTDyldMemoryManager::registerEHFramesInProcess(addr, size);
{
// Lock memory manager
std::lock_guard lock(s_mutex);
s_unfire.push_front(std::make_pair(addr, size));
}
#endif
}
void deregisterEHFrames() override
@@ -799,109 +437,6 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
}
};
// Simple memory manager. I promise there will be no MemoryManager4.
struct MemoryManager3 : llvm::RTDyldMemoryManager
{
std::vector<std::pair<u8*, std::size_t>> allocs;
MemoryManager3() = default;
~MemoryManager3() override
{
for (auto& a : allocs)
{
utils::memory_release(a.first, a.second);
}
}
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
u8* r = static_cast<u8*>(utils::memory_reserve(size));
utils::memory_commit(r, size, utils::protection::wx);
allocs.emplace_back(r, size);
return r;
}
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
u8* r = static_cast<u8*>(utils::memory_reserve(size));
utils::memory_commit(r, size);
allocs.emplace_back(r, size);
return r;
}
bool finalizeMemory(std::string* = nullptr) override
{
return false;
}
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
{
}
void deregisterEHFrames() override
{
}
};
// Helper class
struct EventListener : llvm::JITEventListener
{
MemoryManager& m_mem;
EventListener(MemoryManager& mem)
: m_mem(mem)
{
}
void notifyObjectLoaded(ObjectKey K, const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
{
#ifdef _WIN32
for (auto it = obj.section_begin(), end = obj.section_end(); it != end; ++it)
{
llvm::StringRef name;
name = it->getName().get();
if (name == ".pdata")
{
llvm::StringRef data;
data = it->getContents().get();
std::vector<RUNTIME_FUNCTION> rfs(data.size() / sizeof(RUNTIME_FUNCTION));
auto offsets = reinterpret_cast<DWORD*>(rfs.data());
// Initialize .pdata section using relocation info
for (auto ri = it->relocation_begin(), end = it->relocation_end(); ri != end; ++ri)
{
if (ri->getType() == 3 /*R_X86_64_GOT32*/)
{
const u64 value = *reinterpret_cast<const DWORD*>(data.data() + ri->getOffset());
offsets[ri->getOffset() / sizeof(DWORD)] = static_cast<DWORD>(value + ri->getSymbol()->getAddress().get());
}
}
// Lock memory manager
std::lock_guard lock(s_mutex);
// Use current memory segment as a BASE, compute the difference
const u64 segment_start = s_alloc.current_segment().first;
const u64 code_diff = reinterpret_cast<u64>(m_mem.m_code_addr) - segment_start;
// Fix RUNTIME_FUNCTION records (.pdata section)
for (auto& rf : rfs)
{
rf.BeginAddress += static_cast<DWORD>(code_diff);
rf.EndAddress += static_cast<DWORD>(code_diff);
}
s_unwater.emplace_back(segment_start, std::move(rfs));
}
}
#endif
}
};
// Helper class
class ObjectCache final : public llvm::ObjectCache
{
@@ -1104,20 +639,19 @@ std::string jit_compiler::cpu(const std::string& _cpu)
}
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags)
: m_link(_link)
, m_cpu(cpu(_cpu))
: m_cpu(cpu(_cpu))
{
std::string result;
auto null_mod = std::make_unique<llvm::Module> ("null_", m_context);
if (m_link.empty())
if (_link.empty())
{
std::unique_ptr<llvm::RTDyldMemoryManager> mem;
if (flags & 0x1)
{
mem = std::make_unique<MemoryManager3>();
mem = std::make_unique<MemoryManager1>();
}
else
{
@@ -1138,21 +672,18 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
else
{
// Primary JIT
auto mem = std::make_unique<MemoryManager>(m_link);
m_jit_el = std::make_unique<EventListener>(*mem);
m_engine.reset(llvm::EngineBuilder(std::move(null_mod))
.setErrorStr(&result)
.setEngineKind(llvm::EngineKind::JIT)
.setMCJITMemoryManager(std::move(mem))
.setMCJITMemoryManager(std::make_unique<MemoryManager1>())
.setOptLevel(llvm::CodeGenOpt::Aggressive)
.setCodeModel(flags & 0x2 ? llvm::CodeModel::Large : llvm::CodeModel::Small)
.setMCPU(m_cpu)
.create());
if (m_engine)
for (auto&& [name, addr] : _link)
{
m_engine->RegisterJITEventListener(m_jit_el.get());
m_engine->addGlobalMapping(name, addr);
}
}
+66 -18
View File
@@ -53,18 +53,77 @@ struct jit_runtime final : asmjit::HostRuntime
namespace asmjit
{
// Should only be used to build global functions
asmjit::JitRuntime& get_global_runtime();
asmjit::Runtime& get_global_runtime();
// Emit xbegin and adjacent loop, return label at xbegin
void build_transaction_enter(X86Assembler& c, Label fallback, const X86Gp& ctr, uint less_than);
// Emit xbegin and adjacent loop, return label at xbegin (don't use xabort please)
template <typename F>
[[nodiscard]] inline asmjit::Label build_transaction_enter(asmjit::X86Assembler& c, asmjit::Label fallback, F func)
{
Label fall = c.newLabel();
Label begin = c.newLabel();
c.jmp(begin);
c.bind(fall);
// Emit xabort
void build_transaction_abort(X86Assembler& c, unsigned char code);
// Don't repeat on zero status (may indicate syscall or interrupt)
c.test(x86::eax, x86::eax);
c.jz(fallback);
// First invoked after failure (can fallback to proceed, or jump anywhere else)
func();
// Other bad statuses are ignored regardless of repeat flag (TODO)
c.align(kAlignCode, 16);
c.bind(begin);
return fall;
// xbegin should be issued manually, allows to add more check before entering transaction
}
// Helper to spill RDX (EDX) register for RDTSC
inline void build_swap_rdx_with(asmjit::X86Assembler& c, std::array<X86Gp, 4>& args, const asmjit::X86Gp& with)
{
#ifdef _WIN32
c.xchg(args[1], with);
args[1] = with;
#else
c.xchg(args[2], with);
args[2] = with;
#endif
}
// Get full RDTSC value into chosen register (clobbers rax/rdx or saves only rax with other target)
inline void build_get_tsc(asmjit::X86Assembler& c, const asmjit::X86Gp& to = asmjit::x86::rax)
{
if (&to != &x86::rax && &to != &x86::rdx)
{
// Swap to save its contents
c.xchg(x86::rax, to);
}
c.rdtsc();
c.shl(x86::rdx, 32);
if (&to == &x86::rax)
{
c.or_(x86::rax, x86::rdx);
}
else if (&to == &x86::rdx)
{
c.or_(x86::rdx, x86::rax);
}
else
{
// Swap back, maybe there is more effective way to do it
c.xchg(x86::rax, to);
c.mov(to.r32(), to.r32());
c.or_(to.r64(), x86::rdx);
}
}
}
// Build runtime function with asmjit::X86Assembler
template <typename FT, typename F>
FT build_function_asm(F&& builder)
inline FT build_function_asm(F&& builder)
{
using namespace asmjit;
@@ -89,6 +148,7 @@ FT build_function_asm(F&& builder)
X86Assembler compiler(&code);
builder(std::ref(compiler), args);
ASSERT(compiler.getLastError() == 0);
FT result;
@@ -135,15 +195,9 @@ class jit_compiler final
// Local LLVM context
llvm::LLVMContext m_context;
// JIT Event Listener
std::unique_ptr<struct EventListener> m_jit_el;
// Execution instance
std::unique_ptr<llvm::ExecutionEngine> m_engine;
// Link table
std::unordered_map<std::string, u64> m_link;
// Arch
std::string m_cpu;
@@ -182,12 +236,6 @@ public:
// Get CPU info
static std::string cpu(const std::string& _cpu);
// Check JIT purpose
bool is_primary() const
{
return !m_link.empty();
}
};
#endif
-2
View File
@@ -2,8 +2,6 @@
#include "types.h"
#include <exception>
#include <stdexcept>
#include <string>
namespace fmt
+30 -12
View File
@@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
@@ -1230,7 +1231,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
};
if ((d_size | (d_size + addr)) >= 0x100000000ull)
if (0x1'0000'0000ull - addr < d_size)
{
sig_log.error("Invalid d_size (0x%llx)", d_size);
report_opcode();
@@ -1240,7 +1241,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
// get length of data being accessed
size_t a_size = get_x64_access_size(context, op, reg, d_size, i_size);
if ((a_size | (a_size + addr)) >= 0x100000000ull)
if (0x1'0000'0000ull - addr < a_size)
{
sig_log.error("Invalid a_size (0x%llx)", a_size);
report_opcode();
@@ -1248,22 +1249,28 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
// check if address is RawSPU MMIO register
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
do if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
{
auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET));
if (!thread)
{
return false;
break;
}
if (a_size != 4 || !d_size || !i_size)
if (!a_size || !d_size || !i_size)
{
sig_log.error("Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", +op, +reg, d_size, a_size, i_size);
report_opcode();
return false;
}
if (a_size != 4)
{
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
break;
}
switch (op)
{
case X64OP_LOAD:
@@ -1342,7 +1349,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
RIP(context) += i_size;
g_tls_fault_spu++;
return true;
}
} while (0);
if (vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size)), is_writing ? vm::page_writable : vm::page_readable))
{
@@ -1413,11 +1420,11 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
{
data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_PPU_THREAD << 32) | cpu->id;
}
else
else if (cpu->id_type() == 2)
{
const auto& spu = static_cast<spu_thread&>(*cpu);
const u64 type = spu.offset < RAW_SPU_BASE_ADDR ?
const u64 type = spu.get_type() == spu_type::threaded ?
SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD :
SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU;
@@ -1515,7 +1522,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
if (!access_violation_recovered)
{
vm_log.notice("\n%s", cpu->dump_all());
vm_log.error("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
vm_log.error("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
}
// TODO:
@@ -1552,7 +1559,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
// Do not log any further access violations in this case.
if (!access_violation_recovered)
{
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
vm_log.fatal("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
}
while (Emu.IsPaused())
@@ -1892,7 +1899,18 @@ void thread_base::initialize(void (*error_cb)(), bool(*wait_cb)(const void*))
void thread_base::notify_abort() noexcept
{
atomic_storage_futex::raw_notify(+m_state_notifier);
m_signal.try_inc();
while (auto ptr = m_state_notifier.load())
{
// Since this function is not perfectly implemented, run it in a loop
atomic_storage_futex::raw_notify(ptr);
if (m_state_notifier.load() == ptr)
{
break;
}
}
}
bool thread_base::finalize(thread_state result_state) noexcept
@@ -1953,7 +1971,7 @@ bool thread_base::finalize(thread_state result_state) noexcept
void thread_base::finalize() noexcept
{
atomic_storage_futex::set_wait_callback([](const void*){ return true; });
atomic_storage_futex::set_wait_callback(nullptr);
g_tls_log_prefix = []() -> std::string { return {}; };
thread_ctrl::g_tls_this_thread = nullptr;
}
+17 -2
View File
@@ -40,6 +40,8 @@ enum class thread_state : u32
finished // Final state, always set at the end of thread execution
};
class need_wakeup {};
template <class Context>
class named_thread;
@@ -210,6 +212,12 @@ public:
static_cast<thread_base&>(thread).notify();
}
template <typename T>
static void raw_notify(named_thread<T>& thread)
{
static_cast<thread_base&>(thread).notify_abort();
}
// Read current state
static inline thread_state state()
{
@@ -303,16 +311,18 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
if (_this->m_state >= thread_state::aborting)
{
_this->m_state_notifier.store(data);
return false;
}
_this->m_state_notifier.release(data);
if (!data)
{
_this->m_state_notifier.release(data);
return true;
}
_this->m_state_notifier.store(data);
if (_this->m_state >= thread_state::aborting)
{
_this->m_state_notifier.release(nullptr);
@@ -408,6 +418,11 @@ public:
{
thread::notify_abort();
}
if constexpr (std::is_base_of_v<need_wakeup, Context>)
{
this->wake_up();
}
}
return *this;
+25
View File
@@ -63,6 +63,17 @@ namespace utils
#ifdef _WIN32
return ::VirtualAlloc(use_addr, size, MEM_RESERVE, PAGE_NOACCESS);
#else
if (use_addr && reinterpret_cast<uptr>(use_addr) % 0x10000)
{
return nullptr;
}
if (!use_addr)
{
// Hack: Ensure aligned 64k allocations
size += 0x10000;
}
auto ptr = ::mmap(use_addr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (ptr == reinterpret_cast<void*>(-1))
@@ -76,6 +87,20 @@ namespace utils
return nullptr;
}
if (!use_addr && ptr)
{
// Continuation of the hack above
const auto misalign = reinterpret_cast<uptr>(ptr) % 0x10000;
::munmap(ptr, 0x10000 - misalign);
if (misalign)
{
::munmap(static_cast<u8*>(ptr) + size - misalign, misalign);
}
ptr = static_cast<u8*>(ptr) + (0x10000 - misalign);
}
return ptr;
#endif
}
+3
View File
@@ -81,5 +81,8 @@ namespace utils
{
return m_flags;
}
// Another userdata
u64 info = 0;
};
}
+64
View File
@@ -2,8 +2,72 @@
#include "types.h"
extern bool g_use_rtm;
extern u64 g_rtm_tx_limit1;
namespace utils
{
// Transaction helper (result = pair of success and op result, or just bool)
template <typename F, typename R = std::invoke_result_t<F>>
inline auto tx_start(F op)
{
uint status = -1;
for (auto stamp0 = __rdtsc(), stamp1 = stamp0; g_use_rtm && stamp1 - stamp0 <= g_rtm_tx_limit1; stamp1 = __rdtsc())
{
#ifndef _MSC_VER
__asm__ goto ("xbegin %l[retry];" ::: "memory" : retry);
#else
status = _xbegin();
if (status != _XBEGIN_STARTED) [[unlikely]]
{
goto retry;
}
#endif
if constexpr (std::is_void_v<R>)
{
std::invoke(op);
#ifndef _MSC_VER
__asm__ volatile ("xend;" ::: "memory");
#else
_xend();
#endif
return true;
}
else
{
auto result = std::invoke(op);
#ifndef _MSC_VER
__asm__ volatile ("xend;" ::: "memory");
#else
_xend();
#endif
return std::make_pair(true, std::move(result));
}
retry:
#ifndef _MSC_VER
__asm__ volatile ("movl %%eax, %0;" : "=r" (status) :: "memory");
#endif
if (!status) [[unlikely]]
{
break;
}
}
if constexpr (std::is_void_v<R>)
{
return false;
}
else
{
return std::make_pair(false, R());
}
};
// Rotate helpers
#if defined(__GNUG__)
+24 -24
View File
@@ -57,7 +57,7 @@ void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
patch_engine::patch_engine()
{
const std::string patches_path = fs::get_config_dir() + "patches/";
const std::string patches_path = get_patches_path();
if (!fs::create_path(patches_path))
{
@@ -73,7 +73,7 @@ std::string patch_engine::get_patch_config_path()
if (!fs::create_path(config_dir))
{
patch_log.error("Could not create path: %s", patch_path);
patch_log.error("Could not create path: %s (%s)", patch_path, fs::g_tls_error);
}
return patch_path;
@@ -89,7 +89,7 @@ std::string patch_engine::get_patches_path()
std::string patch_engine::get_imported_patch_path()
{
return fs::get_config_dir() + "patches/imported_patch.yml";
return get_patches_path() + "imported_patch.yml";
}
static void append_log_message(std::stringstream* log_messages, const std::string& message)
@@ -98,19 +98,24 @@ static void append_log_message(std::stringstream* log_messages, const std::strin
*log_messages << message << std::endl;
};
bool patch_engine::load(patch_map& patches_map, const std::string& path, bool importing, std::stringstream* log_messages)
bool patch_engine::load(patch_map& patches_map, const std::string& path, std::string content, bool importing, std::stringstream* log_messages)
{
// Load patch file
fs::file file{ path };
if (!file)
if (content.empty())
{
// Do nothing
return true;
// Load patch file
fs::file file{path};
if (!file)
{
// Do nothing
return true;
}
content = file.to_string();
}
// Interpret yaml nodes
auto [root, error] = yaml_load(file.to_string());
auto [root, error] = yaml_load(content);
if (!error.empty() || !root)
{
@@ -543,18 +548,13 @@ bool patch_engine::read_patch_node(patch_info& info, YAML::Node node, const YAML
return is_valid;
}
void patch_engine::append(const std::string& patch)
{
load(m_map, patch);
}
void patch_engine::append_global_patches()
{
// Legacy patch.yml
load(m_map, fs::get_config_dir() + "patch.yml");
// New patch.yml
load(m_map, fs::get_config_dir() + "patches/patch.yml");
load(m_map, get_patches_path() + "patch.yml");
// Imported patch.yml
load(m_map, get_imported_patch_path());
@@ -571,7 +571,7 @@ void patch_engine::append_title_patches(const std::string& title_id)
load(m_map, fs::get_config_dir() + "data/" + title_id + "/patch.yml");
// New patch.yml
load(m_map, fs::get_config_dir() + "patches/" + title_id + "_patch.yml");
load(m_map, get_patches_path() + title_id + "_patch.yml");
}
std::size_t patch_engine::apply(const std::string& name, u8* dst)
@@ -801,11 +801,11 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
if (patch.is_legacy)
{
patch_log.notice("Applied legacy patch (hash='%s')(<- %d)", patch.hash, applied);
patch_log.success("Applied legacy patch (hash='%s')(<- %d)", patch.hash, applied);
}
else
{
patch_log.notice("Applied patch (hash='%s', description='%s', author='%s', patch_version='%s', file_version='%s') (<- %d)", patch.hash, patch.description, patch.author, patch.patch_version, patch.version, applied);
patch_log.success("Applied patch (hash='%s', description='%s', author='%s', patch_version='%s', file_version='%s') (<- %d)", patch.hash, patch.description, patch.author, patch.patch_version, patch.version, applied);
}
}
@@ -820,7 +820,7 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
fs::file file(path, fs::rewrite);
if (!file)
{
patch_log.fatal("Failed to open patch config file %s", path);
patch_log.fatal("Failed to open patch config file %s (%s)", path, fs::g_tls_error);
return;
}
@@ -973,8 +973,8 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
fs::file file(path, fs::rewrite);
if (!file)
{
patch_log.fatal("save_patches: Failed to open patch file %s", path);
append_log_message(log_messages, fmt::format("Failed to open patch file %s", path));
patch_log.fatal("save_patches: Failed to open patch file %s (%s)", path, fs::g_tls_error);
append_log_message(log_messages, fmt::format("Failed to open patch file %s (%s)", path, fs::g_tls_error));
return false;
}
@@ -1059,7 +1059,7 @@ bool patch_engine::import_patches(const patch_engine::patch_map& patches, const
{
patch_engine::patch_map existing_patches;
if (load(existing_patches, path, true, log_messages))
if (load(existing_patches, path, "", true, log_messages))
{
append_patches(existing_patches, patches, count, total, log_messages);
return count == 0 || save_patches(existing_patches, path, log_messages);
+1 -4
View File
@@ -99,7 +99,7 @@ public:
static std::string get_imported_patch_path();
// Load from file and append to specified patches map
static bool load(patch_map& patches, const std::string& path, bool importing = false, std::stringstream* log_messages = nullptr);
static bool load(patch_map& patches, const std::string& path, std::string content = "", bool importing = false, std::stringstream* log_messages = nullptr);
// Read and add a patch node to the patch info
static bool read_patch_node(patch_info& info, YAML::Node node, const YAML::Node& root, std::stringstream* log_messages = nullptr);
@@ -138,9 +138,6 @@ public:
std::size_t apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
private:
// Load from file and append to member patches map
void append(const std::string& path);
// Internal: Apply patch (returns the number of entries applied)
template <bool check_local_storage>
std::size_t apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
+32
View File
@@ -0,0 +1,32 @@
#include "stdafx.h"
#include "cheat_info.h"
#include "Config.h"
#include "StrUtil.h"
LOG_CHANNEL(log_cheat, "Cheat");
bool cheat_info::from_str(const std::string& cheat_line)
{
auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false);
s64 val64 = 0;
if (cheat_vec.size() != 5 || !cfg::try_to_int64(&val64, cheat_vec[2], 0, cheat_type_max - 1))
{
log_cheat.fatal("Failed to parse cheat line");
return false;
}
game = cheat_vec[0];
description = cheat_vec[1];
type = cheat_type{::narrow<u8>(val64)};
offset = std::stoul(cheat_vec[3]);
red_script = cheat_vec[4];
return true;
}
std::string cheat_info::to_str() const
{
std::string cheat_str = game + "@@@" + description + "@@@" + std::to_string(static_cast<u8>(type)) + "@@@" + std::to_string(offset) + "@@@" + red_script + "@@@";
return cheat_str;
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "stdafx.h"
enum class cheat_type : u8
{
unsigned_8_cheat,
unsigned_16_cheat,
unsigned_32_cheat,
unsigned_64_cheat,
signed_8_cheat,
signed_16_cheat,
signed_32_cheat,
signed_64_cheat,
max
};
constexpr u8 cheat_type_max = static_cast<u8>(cheat_type::max);
struct cheat_info
{
std::string game;
std::string description;
cheat_type type = cheat_type::max;
u32 offset{};
std::string red_script;
bool from_str(const std::string& cheat_line);
std::string to_str() const;
};
+1 -1
View File
@@ -12,7 +12,7 @@ void cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
verify(HERE), _old;
// Wait with timeout
m_value.wait<c_signal_mask>(_old, atomic_wait_timeout{_timeout > max_timeout ? UINT64_MAX : _timeout * 1000});
m_value.wait(_old, c_signal_mask, atomic_wait_timeout{_timeout > max_timeout ? UINT64_MAX : _timeout * 1000});
// Cleanup
m_value.atomic_op([](u32& value)
-93
View File
@@ -39,84 +39,6 @@ void shared_mutex::imp_unlock_shared(u32 old)
}
}
void shared_mutex::imp_lock_low(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
for (int i = 0; i < 10; i++)
{
busy_wait();
if (try_lock_low())
{
return;
}
}
// Acquire writer lock and downgrade
const u32 old = m_value.fetch_add(c_one);
if (old == 0)
{
lock_downgrade();
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
imp_wait();
lock_downgrade();
}
void shared_mutex::imp_unlock_low(u32 old)
{
verify("shared_mutex underflow" HERE), old - 1 < c_err;
// Check reader count, notify the writer if necessary
if ((old - 1) % c_vip == 0)
{
imp_signal();
}
}
void shared_mutex::imp_lock_vip(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
for (int i = 0; i < 10; i++)
{
busy_wait();
if (try_lock_vip())
{
return;
}
}
// Acquire writer lock and downgrade
const u32 old = m_value.fetch_add(c_one);
if (old == 0)
{
lock_downgrade_to_vip();
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
imp_wait();
lock_downgrade_to_vip();
}
void shared_mutex::imp_unlock_vip(u32 old)
{
verify("shared_mutex underflow" HERE), old - 1 < c_err;
// Check reader count, notify the writer if necessary
if ((old - 1) % c_one / c_vip == 0)
{
imp_signal();
}
}
void shared_mutex::imp_wait()
{
while (true)
@@ -241,18 +163,3 @@ void shared_mutex::imp_lock_unlock()
imp_wait();
unlock();
}
bool shared_mutex::downgrade_unique_vip_lock_to_low_or_unlock()
{
return m_value.atomic_op([](u32& value)
{
if (value % c_one / c_vip == 1)
{
value -= c_vip - 1;
return true;
}
value -= c_vip;
return false;
});
}
+1 -117
View File
@@ -12,17 +12,12 @@ class shared_mutex final
c_one = 1u << 14, // Fixed-point 1.0 value (one writer, max_readers = c_one - 1)
c_sig = 1u << 30,
c_err = 1u << 31,
c_vip = 1u << 7,
};
atomic_t<u32> m_value{};
void imp_lock_shared(u32 val);
void imp_unlock_shared(u32 old);
void imp_lock_low(u32 val);
void imp_unlock_low(u32 old);
void imp_lock_vip(u32 val);
void imp_unlock_vip(u32 old);
void imp_wait();
void imp_signal();
void imp_lock(u32 val);
@@ -88,64 +83,6 @@ public:
}
}
bool try_lock_low()
{
const u32 value = m_value.load();
// Conditional increment
return value < c_vip - 1 && m_value.compare_and_swap_test(value, value + 1);
}
void lock_low()
{
const u32 value = m_value.load();
if (value >= c_vip - 1 || !m_value.compare_and_swap_test(value, value + 1)) [[unlikely]]
{
imp_lock_low(value);
}
}
void unlock_low()
{
// Unconditional decrement (can result in broken state)
const u32 value = m_value.fetch_sub(1);
if (value >= c_one) [[unlikely]]
{
imp_unlock_low(value);
}
}
bool try_lock_vip()
{
const u32 value = m_value.load();
// Conditional increment
return (value < c_one - 1 || value & (c_one - c_vip)) && (value % c_vip) == 0 && m_value.compare_and_swap_test(value, value + c_vip);
}
void lock_vip()
{
const u32 value = m_value.load();
if ((value >= c_one - 1 && !(value & (c_one - c_vip))) || (value % c_vip) || !m_value.compare_and_swap_test(value, value + c_vip)) [[unlikely]]
{
imp_lock_vip(value);
}
}
void unlock_vip()
{
// Unconditional decrement (can result in broken state)
const u32 value = m_value.fetch_sub(c_vip);
if (value >= c_one) [[unlikely]]
{
imp_unlock_vip(value);
}
}
bool try_lock()
{
return m_value.compare_and_swap_test(0, c_one);
@@ -214,12 +151,6 @@ public:
m_value -= c_one - 1;
}
void lock_downgrade_to_vip()
{
// Convert to vip lock (can result in broken state)
m_value -= c_one - c_vip;
}
// Optimized wait for lockability without locking, relaxed
void lock_unlock()
{
@@ -240,12 +171,9 @@ public:
{
return m_value.load() < c_one - 1;
}
// Special purpose logic
bool downgrade_unique_vip_lock_to_low_or_unlock();
};
// Simplified shared (reader) lock implementation. Mutually incompatible with low_lock and vip_lock.
// Simplified shared (reader) lock implementation.
class reader_lock final
{
shared_mutex& m_mutex;
@@ -283,47 +211,3 @@ public:
m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared();
}
};
// Special shared (reader) lock, mutually exclusive with vip locks. Mutually incompatible with normal shared (reader) lock.
class low_lock final
{
shared_mutex& m_mutex;
public:
low_lock(const low_lock&) = delete;
low_lock& operator=(const low_lock&) = delete;
explicit low_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_low();
}
~low_lock()
{
m_mutex.unlock_low();
}
};
// Special shared (reader) lock, mutually exclusive with low locks. Mutually incompatible with normal shared (reader) lock.
class vip_lock final
{
shared_mutex& m_mutex;
public:
vip_lock(const vip_lock&) = delete;
vip_lock& operator=(const vip_lock&) = delete;
explicit vip_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_vip();
}
~vip_lock()
{
m_mutex.unlock_vip();
}
};
+6
View File
@@ -28,6 +28,12 @@ DYNAMIC_IMPORT("ntdll.dll", NtWaitForKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOO
DYNAMIC_IMPORT("ntdll.dll", NtReleaseKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForSingleObject, NTSTATUS(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtDelayExecution, NTSTATUS(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForAlertByThreadId, NTSTATUS(PVOID Address, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtAlertThreadByThreadId, NTSTATUS(DWORD_PTR ThreadId));
constexpr NTSTATUS NTSTATUS_SUCCESS = 0;
constexpr NTSTATUS NTSTATUS_ALERTED = 0x101;
constexpr NTSTATUS NTSTATUS_TIMEOUT = 0x102;
#endif
#ifndef __linux__
+16 -5
View File
@@ -64,6 +64,13 @@ bool utils::has_avx512()
return g_value;
}
bool utils::has_avx512_icl()
{
// Check AVX512IFMA, AVX512VBMI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, AVX512VPCLMULQDQ, AVX512GFNI, AVX512VAES (Icelake-client level support)
static const bool g_value = has_avx512() && (get_cpuid(7, 0)[1] & 0x00200000) == 0x00200000 && (get_cpuid(7, 0)[2] & 0x00005f42) == 0x00005f42;
return g_value;
}
bool utils::has_xop()
{
static const bool g_value = has_avx() && get_cpuid(0x80000001, 0)[2] & 0x800;
@@ -145,12 +152,16 @@ std::string utils::get_system_info()
{
result += " | AVX";
if (has_avx2())
{
result += '+';
}
if (has_avx512())
{
result += "-512";
if (has_avx512_icl())
{
result += '+';
}
}
else if (has_avx2())
{
result += '+';
}
+2
View File
@@ -43,6 +43,8 @@ namespace utils
bool has_avx512();
bool has_avx512_icl();
bool has_xop();
bool has_clwb();
+43 -5
View File
@@ -18,7 +18,7 @@
#include <array>
#ifdef _MSC_VER
#ifndef __cpp_lib_bitops
#if !defined(__cpp_lib_bitops) && _MSC_VER < 1928
#define __cpp_lib_bitops
#endif
#endif
@@ -94,6 +94,11 @@ namespace std
{
static_assert(sizeof(To) == sizeof(From), "std::bit_cast<>: incompatible type size");
if constexpr ((std::is_same_v<std::remove_const_t<To>, std::remove_const_t<From>> && std::is_constructible_v<To, From>) || (std::is_integral_v<From> && std::is_integral_v<To>))
{
return static_cast<To>(from);
}
To result{};
std::memcpy(&result, &from, sizeof(From));
return result;
@@ -237,7 +242,7 @@ namespace fmt
const fmt_type_info* get_type_info();
}
template <typename T>
template <typename T, std::size_t Align>
class atomic_t;
// Extract T::simple_type if available, remove cv qualifiers
@@ -264,15 +269,21 @@ class b8
public:
b8() = default;
constexpr b8(bool value)
constexpr b8(bool value) noexcept
: m_value(value)
{
}
constexpr operator bool() const
constexpr operator bool() const noexcept
{
return m_value != 0;
}
constexpr bool set(bool value) noexcept
{
m_value = value;
return value;
}
};
#ifndef _MSC_VER
@@ -293,6 +304,11 @@ struct alignas(16) u128
{
}
constexpr explicit operator bool() const noexcept
{
return !!(lo | hi);
}
friend u128 operator+(const u128& l, const u128& r)
{
u128 value;
@@ -373,6 +389,28 @@ struct alignas(16) u128
return value;
}
u128 operator<<(u128 shift_value)
{
const u64 v0 = lo << (shift_value.lo & 63);
const u64 v1 = __shiftleft128(lo, hi, shift_value.lo);
u128 value;
value.lo = (shift_value.lo & 64) ? 0 : v0;
value.hi = (shift_value.lo & 64) ? v0 : v1;
return value;
}
u128 operator>>(u128 shift_value)
{
const u64 v0 = hi >> (shift_value.lo & 63);
const u64 v1 = __shiftright128(lo, hi, shift_value.lo);
u128 value;
value.lo = (shift_value.lo & 64) ? v0 : v1;
value.hi = (shift_value.lo & 64) ? 0 : v0;
return value;
}
u128 operator~() const
{
u128 value;
@@ -1052,4 +1090,4 @@ inline constexpr uintmax_t ceil2(T value)
return i + std::min<uintmax_t>(ispow2, 1);
}
}
}
}
+1 -1
View File
@@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>$(CmakeCLI)
@@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<PropsAbsPath>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\common_default.props'))</PropsAbsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+4
View File
@@ -96,6 +96,9 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -125,6 +128,7 @@
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>ASMJIT_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+9 -16
View File
@@ -31,13 +31,13 @@ jobs:
displayName: ccache
- bash: |
docker pull --quiet rpcs3/rpcs3-travis-xenial:1.4
docker pull --quiet rpcs3/rpcs3-travis-xenial:1.6
docker run \
-v $(pwd):/rpcs3 \
--env-file .ci/travis.env \
-v $CCACHE_DIR:/root/.ccache \
-v $BUILD_ARTIFACTSTAGINGDIRECTORY:/root/artifacts \
rpcs3/rpcs3-travis-xenial:1.4 \
rpcs3/rpcs3-travis-xenial:1.6 \
/rpcs3/.ci/build-linux.sh
displayName: Docker setup and build
@@ -51,8 +51,8 @@ jobs:
QT_VER: '5.14.2'
QT_DATE: '202003291224'
QTDIR: C:\Qt\$(QT_VER)\msvc2017_64
VULKAN_VER: '1.2.135.0'
VULKAN_SDK_SHA: '181b3353612c8b0fc5e1857b652d62140191ae42b98f2f0d532cf349cebfd8c6'
VULKAN_VER: '1.2.154.1'
VULKAN_SDK_SHA: 'b64471f3a720e649c1fae6535ea83b8c642655ebed1485bfdf15bf4d88f746d9'
VULKAN_SDK: C:\VulkanSDK\$(VULKAN_VER)
CACHE_DIR: ./cache
@@ -91,6 +91,7 @@ jobs:
maximumCpuCount: true
platform: x64
configuration: 'Release - LLVM'
msbuildArgs: '/p:VCToolsVersion=14.25.28610'
displayName: Compile RPCS3
- bash: .ci/deploy-windows.sh
@@ -100,16 +101,8 @@ jobs:
condition: succeeded()
artifact: RPCS3 for Windows
- task: GitHubRelease@1
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
inputs:
gitHubConnection: 'RPCS3-Token'
repositoryName: 'RPCS3/rpcs3-binaries-win'
releaseNotesFilePath: 'GitHubReleaseMessage.txt'
action: 'create'
target: '7d09e3be30805911226241afbb14f8cdc2eb054e'
tagSource: 'userSpecifiedTag'
tag: 'build-$(Build.SourceVersion)'
title: $(AVVER)
addChangeLog: false
- bash: .ci/github-upload-windows.sh
condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: Push build to GitHub
env:
RPCS3_TOKEN: $(RPCS3-Token)
+465
View File
@@ -0,0 +1,465 @@
/*
Nekotekina Theme for RPCS3 by GooseWing
v1.0
Based on YoRHa Theme for RPCS3
by Ani @ https://github.com/AniLeo
r1 (2018.02.27)
sorry for stealing
*/
/*
Color Scheme
- Kot Programs
8c806a
bd9d86
c1b398
eadfb1
ebe4d2
- Light
ffd785
bfa163
- Dark
705722
5c471c
4d4940
*/
/* Every widget */
QWidget {
font-family: SCE-PS3 Rodin LATIN;
font-size: 9.00pt;
color: #ffd785;
background: transparent;
alternate-background-color: transparent;
}
/* Debugger: Sets font-family to default (any invalid value could be provided) */
#debugger QListWidget, #debugger QTextEdit {
font-family: none;
}
/* Log+TTY: Use flat dark color background with default font for better readability */
#log_frame, #tty_frame {
background: rgba(52, 49, 40, 0.9);
font-size: 8.50pt;
font-family: none;
}
/* Debugger: Restore original font size */
#debugger QListWidget, #debugger QTextEdit {
font-size: 9.50pt;
}
/* LLE: Style QListWidget checkboxes (QListWidget) */
#lleList::indicator {
border: 0.05em solid #4d4940;
}
#lleList::indicator::unchecked {
background-color: #b3ac98;
}
#lleList::indicator::checked {
background-color: #4d4940;
}
#lleList::indicator::disabled {
background-color: #828790;
}
#lleList::item::selected {
color: #4d4940;
}
/* Mouse Tooltips */
QToolTip {
background-color: #705722;
color: #ffd785;
border: 0.10em solid #705722;
}
/* CG Disasm and Trophy Manager: background-image doesn't work, use static color */
QWidget#cg_disasm, QWidget#trophy_manager {
background: #6e695c;
}
/* Main Window and Dialogs */
QDialog, QMainWindow#main_window {
border-image: url("GuiConfigs/kot-bg.jpg");
}
/* Table headers */
QHeaderView::section {
text-transform: uppercase;
background: #bfa163;
color: #4d4940;
padding-left: 0.15em;
padding-top: 0.15em;
padding-bottom: 0.10em;
text-transform: uppercase;
border: none;
}
/* All other Tabs */
QTabBar {
text-transform: uppercase;
}
QTabBar::tab {
background: transparent;
padding-left: 0.50em;
padding-right: 0.50em;
padding-top: 0.25em;
padding-bottom: 0.25em;
margin-right: 0.25em;
}
QTabBar::tab::selected {
background: #705722;
color: #ffd785;
border-bottom-style: solid;
}
/* Settings Dialog: Tabs */
QTabBar#tab_bar_settings {
border-bottom: 0.05em solid #705722;
text-transform: uppercase;
}
QTabBar::tab#tab_bar_settings {
background: transparent;
width: 5.20em;
padding-left: 0.50em;
padding-right: 0.50em;
padding-top: 0.65em;
padding-bottom: 0.65em;
margin-right: 0.25em;
font-size: 10.5pt;
font-weight: 550;
}
QTabBar::tab:last#tab_bar_settings {
margin-right: 0em;
}
QTabBar::tab:!selected:hover#tab_bar_settings {
background: transparent;
color: #705722;
}
QTabBar::tab::selected#tab_bar_settings {
background: #bfa163;
color: #705722;
border-bottom-style: solid;
margin-top: 0.15em;
}
/* Checkboxes */
QCheckBox::indicator {
border-radius: 0.1em;
border: 0.05em solid #5c471c;
margin-top: 0.05em;
width: 0.8em;
height: 0.8em;
}
QCheckBox::indicator:checked {
background-color: #ffd785; /* Light */
}
QCheckBox::indicator:unchecked {
background-color: #705722; /* Dark */
}
QCheckBox::indicator::disabled {
background-color: #828790; /* Gray */
}
/* Radio Buttons */
QRadioButton::indicator {
border-radius: 0.4em;
border: 0.05em solid #5c471c;
width: 0.8em;
height: 0.8em;
}
QRadioButton::indicator:checked {
background-color: #ffd785; /* Light */
}
QRadioButton::indicator:unchecked {
background-color: #705722; /* Dark */
}
QRadioButton::indicator::disabled {
background-color: #828790; /* Gray */
}
/* Combo Boxes */
QComboBox {
background: transparent;
color: #ffd785;
border: 0.05em solid #ffd785;
border-radius: 0.15em;
padding-bottom: 0.2em;
padding-left: 0.4em;
}
QComboBox QAbstractItemView {
background: #bfa163;
color: #4d4940;
}
QComboBox::disabled {
background: #828790;
color: #4d4940;
}
/* Group Boxes (Settings Dialog) */
QGroupBox {
margin-top: 1em;
border: 0.05em solid #ffd785;
text-transform: uppercase;
font-size: 9.25pt;
background-color: rgba(41,41,41,120);
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top;
padding: 0.3em 0.5em 0.3em 0.5em;
color: #ffd785;
}
/* Buttons */
QPushButton {
background: #b89754;
color: #292929;
}
QPushButton::disabled {
background: #828790;
color: #ffffff;
}
/* QSpinBox (Settings -> Emulator -> width/height) */
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
QSpinBox, QDoubleSpinBox {
background: transparent;
/*background-color: #bfa163;*/
border: 0.05em solid #4d4940;
border-radius: 0.10em;
color: #ffd785;
}
/* Styles Sliders */
QSlider::groove:horizontal {
border: 0.10em solid #ffd785;
border-radius: 0.10em;
}
QSlider::handle:horizontal {
background: #ffd785;
width: 0.50em;
}
QSlider#sizeSlider::groove:horizontal {
border: 0.10em solid #ffd785;
border-radius: 0.10em;
height: 1.5em;
}
/* Log and Debugger borders */
QTextEdit {
border: 0.05em solid #4d4940;
}
/* For dock buttons to be visible */
QDockWidget {
background: transparent;
text-transform: uppercase;
color: #4d4940;
font-weight: 500;
}
[floating="true"] {
border-image: url("GuiConfigs/kot-bg.jpg");
}
QDockWidget::title {
background: #bfa163;
padding-top: 0.2em;
}
QDockWidget::close-button, QDockWidget::float-button {
background-color: #bfa163;
}
/* Disable ugly borders */
QTabWidget::pane {
border: 0em solid #4d4940;
}
/* Top menu bar */
QMenuBar {
height:1.50em;
text-transform: uppercase;
}
QMenuBar::item {
margin-right: 0.20em;
margin-left: 0.20em;
padding-left: 1.20em;
padding-right: 1.20em;
}
QMenuBar::item:selected {
background: #4d4940;
color: #aea993;
}
QMenu {
background: #bfa163;
color: #4d4940;
text-transform: uppercase;
}
QMenu::item {
padding-left: 1.5em;
padding-right: 0.75em;
padding-top: 0.25em;
padding-bottom: 0.25em;
}
QMenu::item:selected {
background: #4d4940;
color: #aea993;
border: 0.05em solid #4d4940;
}
QMenu::item:disabled {
background-color: #828790;
color: #4d4940;
}
/* Pad Settings: Controller Image */
QLabel#l_controller {
color: #ffd785;
}
/* Game Grid Font */
QTableWidget#game_grid {
font-weight: 600;
color: #4d4940;
text-transform: uppercase;
selection-color: #aea993;
}
QTableWidget#game_grid::item:selected:active {
selection-background-color: #4d4940;
}
QTableWidget#game_grid::item:selected:!active {
selection-background-color: #615c51;
}
/* Debug UI Settings buttons */
QLabel#color_button {
background: transparent;
}
/* Search bar on main Toolbar */
QLineEdit#mw_searchbar {
margin-left: 0.7em;
color: #4d4940;
font-size: 10.25pt;
}
/* Uniform colors in Toolbar */
QToolButton {
background: transparent;
text-transform: uppercase;
}
QToolButton::hover {
background-color: #b3ac98;
}
/* Set Theme UI colors */
QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #4d4940;
}
QLabel#log_level_always {
color: #00ffff; /* Cyan */
}
QLabel#log_level_fatal {
color: #ff00ff; /* Fuchsia */
}
QLabel#log_level_error {
color: #ff0000; /* Red */
}
QLabel#log_level_todo {
color: #ff6000; /* Orange */
}
QLabel#log_level_success {
color: #00ff00; /* Green */
}
QLabel#log_level_warning {
color: #ffff00; /* Yellow */
}
QLabel#log_level_notice {
color: #ffffff; /* White */
}
QLabel#log_level_trace {
color: #808080; /* Gray */
}
QLabel#log_stack {
color: #b3ac98; /* Light */
}
/* Set TTY colors */
#tty_frame {
color: #b3ac98; /* Light */
}
/* Memory Viewer */
QLabel#memory_viewer_address_panel {
color: #0000ff; /* Font Color: Blue */
}
QLabel#memory_viewer_hex_panel {
color: #4d4940; /* Font Color: Grey */
}
QLabel#memory_viewer_ascii_panel {
color: #4d4940; /* Font Color: Grey */
}
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000000; /* Font Color: Black */
background-color: #ffff00; /* Yellow */
}
QLabel#debugger_frame_pc {
color: #000000; /* Font Color: Black */
background-color: #00ff00; /* Green */
}
/* Trophy Notification Popup */
QWidget#trophy_notification_frame {
background-color: #b3ac98;
color: #4d4940;
}
-4
View File
@@ -460,10 +460,6 @@ QSpinBox:hover, QDoubleSpinBox:hover {
color: #FFFFFF;
}
QSpinBox::up-button, QSpinBox::down-button, QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
background: transparent;
}
QSpinBox:disabled, QDoubleSpinBox:disabled {
color: #455971;
background: #26293b;
-4
View File
@@ -482,10 +482,6 @@ QSpinBox:hover, QDoubleSpinBox:hover {
color: #455971;
}
QSpinBox::up-button, QSpinBox::down-button, QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
background: transparent;
}
QSpinBox:disabled, QDoubleSpinBox:disabled {
background-color: #b3b3b3;
color: #455971;
+18 -8
View File
@@ -71,6 +71,22 @@ QWidget {
color: #4d4940;
}
/* Style QTreeWidget checkboxes */
QTreeWidget::indicator {
border: 0.05em solid #4d4940;
}
QTreeWidget::indicator::unchecked {
background-color: #b3ac98;
}
QTreeWidget::indicator::checked {
background-color: #4d4940;
}
QTreeWidget::indicator::disabled {
background-color: #828790;
}
QTreeWidget::item::selected {
color: #4d4940;
}
/* Mouse Tooltips */
QToolTip {
@@ -80,14 +96,8 @@ QToolTip {
}
/* CG Disasm and Trophy Manager: background-image doesn't work, use static color */
QWidget#cg_disasm, QWidget#trophy_manager {
background: #b3ac98;
}
/* Main Window and Dialogs */
QDialog, QMainWindow#main_window {
/* Main Window, Dialogs and some Dialogs that are actually widgets */
QDialog, QWidget#trophy_manager, QWidget#cg_disasm, QMainWindow#main_window {
border-image: url("GuiConfigs/YoRHa-background.jpg");
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

+1 -1
Submodule llvm updated: f5679565d3...8c02f52a12
+1 -1
View File
@@ -1,7 +1,7 @@
REM You need cmake and python to update the project files
REM this script relies on CWD being the path that this script is in
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -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 -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
cmake -G "Visual Studio 16 2019 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -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_BENCHMARKS=OFF -DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_INTEL_JITEVENTS=ON -DLLVM_ENABLE_Z3_SOLVER=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=10.0 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm
RD /S /Q cmake
RD /S /Q CMakeFiles
+4 -1
View File
@@ -26,6 +26,9 @@
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
@@ -36,7 +39,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -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 -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -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 -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakePreprocessorDefinitions>
+2 -2
View File
@@ -83,7 +83,7 @@ set_target_properties(rpcs3
AUTOUIC ON)
target_link_libraries(rpcs3 rpcs3_emu rpcs3_ui)
target_link_libraries(rpcs3 3rdparty::discord-rpc 3rdparty::qt5 3rdparty::hidapi 3rdparty::libusb)
target_link_libraries(rpcs3 3rdparty::discord-rpc 3rdparty::qt5 3rdparty::hidapi 3rdparty::libusb 3rdparty::wolfssl)
target_link_libraries(rpcs3 ${ADDITIONAL_LIBS})
# Win resource file
@@ -107,7 +107,7 @@ if(UNIX)
endif()
if(WIN32)
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib Psapi.lib gdi32.lib setupapi.lib)
target_link_libraries(rpcs3 ws2_32.lib Iphlpapi.lib Winmm.lib Psapi.lib gdi32.lib setupapi.lib)
else()
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS})
endif()
+40 -12
View File
@@ -576,14 +576,32 @@ int validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *
int dev_hash_result = 0;
const s32 file_name_length = ::narrow<s32>(std::strlen(file_name), HERE);
std::unique_ptr<u8[]> buf(new u8[0x30 + file_name_length]);
const std::size_t buf_len = 0x30 + file_name_length;
std::unique_ptr<u8[]> buf(new u8[buf_len]);
std::unique_ptr<u8[]> buf_lower(new u8[buf_len]);
std::unique_ptr<u8[]> buf_upper(new u8[buf_len]);
// Build the title buffer (content_id + file_name).
memcpy(buf.get(), npd->content_id, 0x30);
memcpy(buf.get() + 0x30, file_name, file_name_length);
std::memcpy(buf.get(), npd->content_id, 0x30);
std::memcpy(buf.get() + 0x30, file_name, file_name_length);
std::memcpy(buf_lower.get(), buf.get(), buf_len);
std::memcpy(buf_upper.get(), buf.get(), buf_len);
for (std::size_t i = std::basic_string_view<u8>(buf.get() + 0x30, file_name_length).find_last_of('.'); i < buf_len; i++)
{
const u8 c = static_cast<u8>(buf[i]);
buf_upper[i] = std::toupper(c);
buf_lower[i] = std::tolower(c);
}
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf.get(), 0x30 + file_name_length, npd->title_hash, 0x10);
// Try to ignore case sensivity with file extension
title_hash_result =
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf.get(), buf_len, npd->title_hash, 0x10) ||
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf_lower.get(), buf_len, npd->title_hash, 0x10) ||
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf_upper.get(), buf_len, npd->title_hash, 0x10);
if (verbose)
{
@@ -674,7 +692,7 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
}
// Perform header validation (EDAT only).
char real_file_name[MAX_PATH];
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name, real_file_name);
if (!validate_npd_hashes(real_file_name, devklic, &NPD, verbose))
{
@@ -696,14 +714,20 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
// Make sure we don't have an empty RIF key.
if (key == v128{})
{
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file!");
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file! (local activation)");
return 1;
}
}
else if ((NPD.license & 0x1) == 0x1) // Type 1: Use network activation.
{
edat_log.error("EDAT: Network license not supported!");
return 1;
memcpy(&key, rifkey, 0x10);
// Make sure we don't have an empty RIF key.
if (key == v128{})
{
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file! (network activation)");
return 1;
}
}
if (verbose)
@@ -774,7 +798,7 @@ bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& inpu
}
// Perform header validation (EDAT only).
char real_file_name[MAX_PATH];
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name.c_str(), real_file_name);
if (!validate_npd_hashes(real_file_name, custom_klic, &NPD, false))
{
@@ -898,13 +922,17 @@ bool EDATADecrypter::ReadHeader()
if (dec_key == v128{})
{
edat_log.warning("EDAT: Empty Dec key!");
edat_log.warning("EDAT: Empty Dec key for local actívation!");
}
}
else if ((npdHeader.license & 0x1) == 0x1) // Type 1: Use network activation.
{
edat_log.error("EDAT: Network license not supported!");
return false;
dec_key = std::move(rif_key);
if (dec_key == v128{})
{
edat_log.warning("EDAT: Empty Dec key for network activation!");
}
}
}
+8 -8
View File
@@ -535,7 +535,7 @@ package_error package_reader::check_target_app_version()
const auto category = psf::get_string(psf, "CATEGORY", "");
const auto title_id = psf::get_string(psf, "TITLE_ID", "");
const auto app_ver = psf::get_string(psf, "APP_VER", "");
auto target_app_ver = psf::get_string(psf, "TARGET_APP_VER", "");
const auto target_app_ver = psf::get_string(psf, "TARGET_APP_VER", "");
if (category != "GD")
{
@@ -561,7 +561,7 @@ package_error package_reader::check_target_app_version()
return package_error::no_error;
}
const fs::file installed_sfo_file(Emu.GetHddDir() + "game/" + title_id + "/PARAM.SFO");
const fs::file installed_sfo_file(Emu.GetHddDir() + "game/" + std::string(title_id) + "/PARAM.SFO");
if (!installed_sfo_file)
{
if (!target_app_ver.empty())
@@ -587,9 +587,9 @@ package_error package_reader::check_target_app_version()
}
std::add_pointer_t<char> ev0, ev1;
const double old_version = std::strtod(installed_app_ver.c_str(), &ev0);
const double old_version = std::strtod(installed_app_ver.data(), &ev0);
if (installed_app_ver.c_str() + installed_app_ver.size() != ev0)
if (installed_app_ver.data() + installed_app_ver.size() != ev0)
{
pkg_log.error("Failed to convert the installed app version to double (%s)", installed_app_ver);
return package_error::other;
@@ -599,9 +599,9 @@ package_error package_reader::check_target_app_version()
{
// This is most likely the first patch. Let's make sure its version is high enough for the installed game.
const double new_version = std::strtod(app_ver.c_str(), &ev1);
const double new_version = std::strtod(app_ver.data(), &ev1);
if (app_ver.c_str() + app_ver.size() != ev1)
if (app_ver.data() + app_ver.size() != ev1)
{
pkg_log.error("Failed to convert the package's app version to double (%s)", app_ver);
return package_error::other;
@@ -619,9 +619,9 @@ package_error package_reader::check_target_app_version()
// Check if the installed app version matches the target app version
const double target_version = std::strtod(target_app_ver.c_str(), &ev1);
const double target_version = std::strtod(target_app_ver.data(), &ev1);
if (target_app_ver.c_str() + target_app_ver.size() != ev1)
if (target_app_ver.data() + target_app_ver.size() != ev1)
{
pkg_log.error("Failed to convert the package's target app version to double (%s)", target_app_ver);
return package_error::other;
+6 -2
View File
@@ -1112,8 +1112,12 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
if (ctrl->npdrm.license == 1) // Network license.
{
self_log.error("SELF: Can't decrypt network NPDRM!");
return false;
// Try to find a RAP file to get the key.
if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key))
{
self_log.error("SELF: Can't decrypt network NPDRM!");
return false;
}
}
else if (ctrl->npdrm.license == 2) // Local license.
{
+4 -3
View File
@@ -8,6 +8,7 @@
#include <time.h>
#include "Utilities/StrUtil.h"
#include "Utilities/span.h"
#include "Utilities/File.h"
#include <memory>
#include <string>
@@ -120,16 +121,16 @@ void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_
aes_cmac(&ctx, in_len, in, hash);
}
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH])
{
std::string_view v(file_path);
if (auto pos = v.find_last_of("/\\"); pos != umax)
if (auto pos = v.find_last_of(fs::delim); pos != umax)
{
v.remove_prefix(pos + 1);
}
gsl::span r(real_file_name, MAX_PATH);
gsl::span r(real_file_name, CRYPTO_MAX_PATH);
strcpy_trunc(r, v);
return real_file_name;
}
+4 -4
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
// Licensed under the terms of the GNU GPL, version 3
@@ -6,14 +6,14 @@
#include "../../Utilities/types.h"
#define MAX_PATH 4096
#include <stdlib.h>
#include "aes.h"
#include "sha1.h"
#include "lz.h"
#include "ec.h"
enum { CRYPTO_MAX_PATH = 4096 };
// Auxiliary functions (endian swap, xor, and file name).
inline u16 swap16(u16 i)
{
@@ -42,7 +42,7 @@ inline u64 swap64(u64 i)
#endif
}
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH]);
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH]);
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str);
+9 -6
View File
@@ -12,8 +12,7 @@ LOG_CHANNEL(OpenAL);
#define checkForAlcError(sit) do { ALCenum g_last_alc_error = alcGetError(m_device); if(g_last_alc_error != ALC_NO_ERROR) { OpenAL.error("%s: OpenALC error 0x%04x", sit, g_last_alc_error); return; }} while(0)
OpenALBackend::OpenALBackend()
: m_sampling_rate(get_sampling_rate())
, m_sample_size(get_sample_size())
: AudioBackend()
{
ALCdevice* m_device = alcOpenDevice(nullptr);
checkForAlcError("alcOpenDevice");
@@ -24,13 +23,17 @@ OpenALBackend::OpenALBackend()
alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent");
if (get_channels() == 2)
switch (m_channels)
{
case 2:
m_format = (m_sample_size == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
}
else
{
break;
case 6:
m_format = (m_sample_size == 2) ? AL_FORMAT_51CHN16 : AL_FORMAT_51CHN32;
break;
default:
m_format = (m_sample_size == 2) ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
break;
}
}
-3
View File
@@ -15,9 +15,6 @@ private:
u32 m_next_buffer = 0;
u32 m_num_unqueued = 0;
const u32 m_sampling_rate;
const u32 m_sample_size;
void unqueue_processed();
public:
+7 -6
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_ALSA
#ifndef HAVE_ALSA
#error "ALSA support disabled but still being built."
#endif
@@ -26,6 +26,7 @@ static bool check(int err, const char* reason)
}
ALSABackend::ALSABackend()
: AudioBackend()
{
}
@@ -51,14 +52,14 @@ void ALSABackend::Open(u32 num_buffers)
if (!check(snd_pcm_hw_params_set_access(tls_handle, tls_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "snd_pcm_hw_params_set_access"))
return;
if (!check(snd_pcm_hw_params_set_format(tls_handle, tls_hw_params, g_cfg.audio.convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
if (!check(snd_pcm_hw_params_set_format(tls_handle, tls_hw_params, m_convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
return;
uint rate = get_sampling_rate();
uint rate = m_sampling_rate;
if (!check(snd_pcm_hw_params_set_rate_near(tls_handle, tls_hw_params, &rate, nullptr), "snd_pcm_hw_params_set_rate_near"))
return;
if (!check(snd_pcm_hw_params_set_channels(tls_handle, tls_hw_params, get_channels()), "snd_pcm_hw_params_set_channels"))
if (!check(snd_pcm_hw_params_set_channels(tls_handle, tls_hw_params, m_channels), "snd_pcm_hw_params_set_channels"))
return;
//uint period = 5333;
@@ -92,7 +93,7 @@ void ALSABackend::Open(u32 num_buffers)
if (!check(snd_pcm_sw_params_current(tls_handle, tls_sw_params), "snd_pcm_sw_params_current"))
return;
period_frames *= g_cfg.audio.startt;
period_frames *= m_start_threshold;
if (!check(snd_pcm_sw_params_set_start_threshold(tls_handle, tls_sw_params, period_frames + 1), "snd_pcm_sw_params_set_start_threshold"))
return;
@@ -132,7 +133,7 @@ void ALSABackend::Close()
bool ALSABackend::AddData(const void* src, u32 num_samples)
{
u32 num_frames = num_samples / get_channels();
u32 num_frames = num_samples / m_channels;
int res = snd_pcm_writei(tls_handle, src, num_frames);
+50 -12
View File
@@ -2,29 +2,67 @@
#include "AudioBackend.h"
#include "Emu/system_config.h"
/*
* Helper methods
*/
u32 AudioBackend::get_sampling_rate()
AudioBackend::AudioBackend()
{
m_convert_to_u16 = static_cast<bool>(g_cfg.audio.convert_to_u16);
m_sample_size = m_convert_to_u16 ? sizeof(u16) : sizeof(float);
m_start_threshold = g_cfg.audio.start_threshold;
const u32 sampling_period_multiplier_u32 = g_cfg.audio.sampling_period_multiplier;
if (sampling_period_multiplier_u32 == 100)
return DEFAULT_AUDIO_SAMPLING_RATE;
{
m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
}
else
{
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
m_sampling_rate = static_cast<u32>(f32{ DEFAULT_AUDIO_SAMPLING_RATE } *sampling_rate_multiplier);
}
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
return static_cast<u32>(f32{DEFAULT_AUDIO_SAMPLING_RATE} * sampling_rate_multiplier);
const audio_downmix downmix = g_cfg.audio.audio_channel_downmix.get();
switch (downmix)
{
case audio_downmix::no_downmix:
m_channels = 8;
break;
case audio_downmix::downmix_to_stereo:
m_channels = 2;
break;
case audio_downmix::downmix_to_5_1:
m_channels = 6;
break;
case audio_downmix::use_application_settings:
m_channels = 2; // TODO
break;
default:
fmt::throw_exception("Unknown audio channel mode %s (%d)", downmix, static_cast<int>(downmix));
}
}
u32 AudioBackend::get_sample_size()
/*
* Helper methods
*/
u32 AudioBackend::get_sampling_rate() const
{
return g_cfg.audio.convert_to_u16 ? sizeof(u16) : sizeof(float);
return m_sampling_rate;
}
u32 AudioBackend::get_channels()
u32 AudioBackend::get_sample_size() const
{
return g_cfg.audio.downmix_to_2ch ? 2 : 8;
return m_sample_size;
}
u32 AudioBackend::get_channels() const
{
return m_channels;
}
bool AudioBackend::get_convert_to_u16() const
{
return m_convert_to_u16;
}
bool AudioBackend::has_capability(u32 cap) const
+14 -3
View File
@@ -20,6 +20,8 @@ public:
SET_FREQUENCY_RATIO = 0x8, // Implements SetFrequencyRatio
};
AudioBackend();
virtual ~AudioBackend() = default;
/*
@@ -94,13 +96,22 @@ public:
/*
* Helper methods
*/
static u32 get_sampling_rate();
u32 get_sampling_rate() const;
static u32 get_sample_size();
u32 get_sample_size() const;
static u32 get_channels();
u32 get_channels() const;
bool get_convert_to_u16() const;
bool has_capability(u32 cap) const;
void dump_capabilities(std::string& out) const;
protected:
bool m_convert_to_u16 = false;
u32 m_sample_size = sizeof(float);
u32 m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
u32 m_channels = 0;
u32 m_start_threshold = 1;
};
+10 -13
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_FAUDIO
#ifndef HAVE_FAUDIO
#error "FAudio support disabled but still being built."
#endif
@@ -10,6 +10,7 @@
LOG_CHANNEL(FAudio_, "FAudio");
FAudioBackend::FAudioBackend()
: AudioBackend()
{
u32 res;
@@ -20,7 +21,7 @@ FAudioBackend::FAudioBackend()
return;
}
res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, g_cfg.audio.downmix_to_2ch ? 2 : 8, 48000, 0, 0, nullptr);
res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, m_channels, 48000, 0, 0, nullptr);
if (res)
{
FAudio_.fatal("FAudio_CreateMasteringVoice() failed(0x%08x)", res);
@@ -102,17 +103,13 @@ void FAudioBackend::Close()
void FAudioBackend::Open(u32 /* num_buffers */)
{
const u32 sample_size = AudioBackend::get_sample_size();
const u32 channels = AudioBackend::get_channels();
const u32 sampling_rate = AudioBackend::get_sampling_rate();
FAudioWaveFormatEx waveformatex;
waveformatex.wFormatTag = g_cfg.audio.convert_to_u16 ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<u32>(sampling_rate * channels * sample_size);
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.wFormatTag = m_convert_to_u16 ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<u32>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
u32 res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex, 0, FAUDIO_DEFAULT_FREQ_RATIO, nullptr, nullptr, nullptr);
@@ -140,7 +137,7 @@ bool FAudioBackend::AddData(const void* src, u32 num_samples)
}
FAudioBuffer buffer;
buffer.AudioBytes = num_samples * AudioBackend::get_sample_size();
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = FAUDIO_NO_LOOP_REGION;
buffer.LoopCount = 0;
+24 -10
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_PULSE
#ifndef HAVE_PULSE
#error "PulseAudio support disabled but still being built."
#endif
@@ -9,6 +9,7 @@
#include <pulse/error.h>
PulseBackend::PulseBackend()
: AudioBackend()
{
}
@@ -19,7 +20,8 @@ PulseBackend::~PulseBackend()
void PulseBackend::Close()
{
if(this->connection) {
if (this->connection)
{
pa_simple_free(this->connection);
this->connection = nullptr;
}
@@ -28,20 +30,30 @@ void PulseBackend::Close()
void PulseBackend::Open(u32 /* num_buffers */)
{
pa_sample_spec ss;
ss.format = (get_sample_size() == 2) ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.rate = get_sampling_rate();
ss.format = (m_sample_size == 2) ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.rate = m_sampling_rate;
pa_channel_map channel_map;
if (get_channels() == 2)
if (m_channels == 2)
{
channel_map.channels = 2;
channel_map.channels = 2;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
}
else if (m_channels == 6)
{
channel_map.channels = 6;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
channel_map.map[3] = PA_CHANNEL_POSITION_LFE;
channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
}
else
{
channel_map.channels = 8;
channel_map.channels = 8;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
@@ -55,7 +67,8 @@ void PulseBackend::Open(u32 /* num_buffers */)
int err;
this->connection = pa_simple_new(NULL, "RPCS3", PA_STREAM_PLAYBACK, NULL, "Game", &ss, &channel_map, NULL, &err);
if(!this->connection) {
if (!this->connection)
{
fprintf(stderr, "PulseAudio: Failed to initialize audio: %s\n", pa_strerror(err));
}
}
@@ -65,10 +78,11 @@ bool PulseBackend::AddData(const void* src, u32 num_samples)
AUDIT(this->connection);
int err;
if(pa_simple_write(this->connection, src, num_samples * get_sample_size(), &err) < 0) {
if (pa_simple_write(this->connection, src, num_samples * m_sample_size, &err) < 0)
{
fprintf(stderr, "PulseAudio: Failed to write audio stream: %s\n", pa_strerror(err));
return false;
}
return true;
}
+22 -20
View File
@@ -9,26 +9,32 @@
#include "XAudio2Backend.h"
#include <Windows.h>
#include <system_error>
#pragma comment(lib, "xaudio2_9redist.lib")
LOG_CHANNEL(XAudio);
XAudio2Backend::XAudio2Backend()
: AudioBackend()
{
Microsoft::WRL::ComPtr<IXAudio2> instance;
// In order to prevent errors on CreateMasteringVoice, apparently we need CoInitializeEx according to:
// https://docs.microsoft.com/en-us/windows/win32/api/xaudio2fx/nf-xaudio2fx-xaudio2createvolumemeter
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr = XAudio2Create(instance.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr))
{
XAudio.error("XAudio2Create() failed(0x%08x)", (u32)hr);
XAudio.error("XAudio2Create() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
}
hr = instance->CreateMasteringVoice(&m_master_voice, g_cfg.audio.downmix_to_2ch ? 2 : 8, 48000);
hr = instance->CreateMasteringVoice(&m_master_voice, m_channels, 48000);
if (FAILED(hr))
{
XAudio.error("CreateMasteringVoice() failed(0x%08x)", (u32)hr);
XAudio.error("CreateMasteringVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
}
@@ -62,7 +68,7 @@ void XAudio2Backend::Play()
HRESULT hr = m_source_voice->Start();
if (FAILED(hr))
{
XAudio.error("Start() failed(0x%08x)", (u32)hr);
XAudio.error("Start() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
}
}
@@ -80,7 +86,7 @@ void XAudio2Backend::Pause()
HRESULT hr = m_source_voice->Stop();
if (FAILED(hr))
{
XAudio.error("Stop() failed(0x%08x)", (u32)hr);
XAudio.error("Stop() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
}
}
@@ -89,23 +95,19 @@ void XAudio2Backend::Open(u32 /* num_buffers */)
{
HRESULT hr;
const u32 sample_size = AudioBackend::get_sample_size();
const u32 channels = AudioBackend::get_channels();
const u32 sampling_rate = AudioBackend::get_sampling_rate();
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg.audio.convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(sampling_rate * channels * sample_size);
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.wFormatTag = m_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (FAILED(hr))
{
XAudio.error("CreateSourceVoice() failed(0x%08x)", (u32)hr);
XAudio.error("CreateSourceVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
return;
}
@@ -139,7 +141,7 @@ bool XAudio2Backend::AddData(const void* src, u32 num_samples)
XAUDIO2_BUFFER buffer;
buffer.AudioBytes = num_samples * AudioBackend::get_sample_size();
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;
@@ -152,7 +154,7 @@ bool XAudio2Backend::AddData(const void* src, u32 num_samples)
HRESULT hr = m_source_voice->SubmitSourceBuffer(&buffer);
if (FAILED(hr))
{
XAudio.error("AddData() failed(0x%08x)", (u32)hr);
XAudio.error("AddData() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
return false;
}
@@ -167,7 +169,7 @@ void XAudio2Backend::Flush()
HRESULT hr = m_source_voice->FlushSourceBuffers();
if (FAILED(hr))
{
XAudio.error("FlushSourceBuffers() failed(0x%08x)", (u32)hr);
XAudio.error("FlushSourceBuffers() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
}
}
@@ -190,7 +192,7 @@ f32 XAudio2Backend::SetFrequencyRatio(f32 new_ratio)
HRESULT hr = m_source_voice->SetFrequencyRatio(new_ratio);
if (FAILED(hr))
{
XAudio.error("SetFrequencyRatio() failed(0x%08x)", (u32)hr);
XAudio.error("SetFrequencyRatio() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
Emu.Pause();
return 1.0f;
}
+15 -6
View File
@@ -1,18 +1,23 @@
add_library(rpcs3_emu
IdManager.cpp
localized_string.cpp
System.cpp
system_config.cpp
system_config_types.cpp
VFS.cpp
GDB.cpp
title.cpp
perf_meter.cpp
)
# prevent WolfSSL from warning about not having harden options
add_compile_definitions(WC_NO_HARDEN)
target_link_libraries(rpcs3_emu
PRIVATE
3rdparty::zlib 3rdparty::yaml-cpp
PUBLIC
3rdparty::libevdev)
3rdparty::libevdev 3rdparty::flatbuffers)
find_package(Threads REQUIRED)
@@ -35,6 +40,7 @@ target_sources(rpcs3_emu PRIVATE
../util/yaml.cpp
../util/cereal.cpp
../../Utilities/bin_patch.cpp
../../Utilities/cheat_info.cpp
../../Utilities/cond.cpp
../../Utilities/Config.cpp
../../Utilities/dynamic_library.cpp
@@ -333,10 +339,6 @@ target_link_libraries(rpcs3_emu
PRIVATE
3rdparty::stblib 3rdparty::libpng)
if(CMAKE_COMPILER_IS_GNUCXX)
target_link_libraries(rpcs3_emu PUBLIC -latomic)
endif()
# CPU
target_sources(rpcs3_emu PRIVATE
@@ -350,6 +352,7 @@ target_link_libraries(rpcs3_emu
# Io
target_sources(rpcs3_emu PRIVATE
Io/interception.cpp
Io/KeyboardHandler.cpp
Io/pad_config.cpp
Io/pad_config_types.cpp
@@ -361,7 +364,12 @@ target_sources(rpcs3_emu PRIVATE
# Np
target_sources(rpcs3_emu PRIVATE
NP/fb_helpers.cpp
NP/np_handler.cpp
NP/signaling_handler.cpp
NP/np_structs_extra.cpp
NP/rpcn_client.cpp
NP/rpcn_config.cpp
)
# Memory
@@ -436,6 +444,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/VKMemAlloc.cpp
RSX/VK/VKPresent.cpp
RSX/VK/VKProgramPipeline.cpp
RSX/VK/VKQueryPool.cpp
RSX/VK/VKRenderPass.cpp
RSX/VK/VKResolveHelper.cpp
RSX/VK/VKResourceManager.cpp
@@ -451,7 +460,7 @@ target_link_libraries(rpcs3_emu
3rdparty::ffmpeg 3rdparty::cereal
3rdparty::opengl 3rdparty::stblib
3rdparty::vulkan 3rdparty::glew
3rdparty::libusb
3rdparty::libusb 3rdparty::wolfssl
PRIVATE
3rdparty::span 3rdparty::xxhash
)
+24 -1
View File
@@ -56,7 +56,30 @@ protected:
virtual u32 DisAsmBranchTarget(const s32 imm) = 0;
std::string FixOp(std::string op)
// TODO: Add builtin fmt helpper for best performance
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
static std::string SignedHex(T value)
{
const auto v = static_cast<std::make_signed_t<T>>(value);
if (v == std::numeric_limits<std::make_signed_t<T>>::min())
{
// for INTx_MIN
return fmt::format("-0x%x", v);
}
const auto av = std::abs(v);
if (av < 10)
{
// Does not need hex
return fmt::format("%d", v);
}
return fmt::format("%s%s", v < 0 ? "-" : "", av);
}
static std::string FixOp(std::string op)
{
op.resize(std::max<std::size_t>(op.length(), 10), ' ');
return op;
+391 -99
View File
@@ -8,17 +8,24 @@
#include "Emu/GDB.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/perf_meter.hpp"
#include <thread>
#include <unordered_map>
#include <numeric>
#include <map>
DECLARE(cpu_thread::g_threads_created){0};
DECLARE(cpu_thread::g_threads_deleted){0};
DECLARE(cpu_thread::g_suspend_counter){0};
LOG_CHANNEL(profiler);
LOG_CHANNEL(sys_log, "SYS");
static thread_local u64 s_tls_thread_slot = -1;
extern thread_local void(*g_tls_log_control)(const char* fmt, u64 progress);
template <>
void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
{
@@ -29,6 +36,7 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
case cpu_flag::stop: return "STOP";
case cpu_flag::exit: return "EXIT";
case cpu_flag::wait: return "w";
case cpu_flag::temp: return "t";
case cpu_flag::pause: return "p";
case cpu_flag::suspend: return "s";
case cpu_flag::ret: return "ret";
@@ -245,24 +253,31 @@ struct cpu_counter
// For synchronizing suspend_all operation
alignas(64) shared_mutex cpu_suspend_lock;
// Workload linked list
alignas(64) atomic_t<cpu_thread::suspend_work*> cpu_suspend_work{};
// Semaphore for global thread array (global counter)
alignas(64) atomic_t<u32> cpu_array_sema{0};
// Semaphore subdivision for each array slot (64 x N in total)
atomic_t<u64> cpu_array_bits[6]{};
alignas(64) atomic_t<u64> cpu_array_bits[3]{};
// Copy of array bits for internal use
alignas(64) u64 cpu_copy_bits[3]{};
// All registered threads
atomic_t<cpu_thread*> cpu_array[sizeof(cpu_array_bits) * 8]{};
u64 add(cpu_thread* _this)
u64 add(cpu_thread* _this, bool restore = false) noexcept
{
if (!cpu_array_sema.try_inc(sizeof(cpu_counter::cpu_array_bits) * 8))
{
return -1;
}
u64 array_slot = -1;
if (!restore && !cpu_array_sema.try_inc(sizeof(cpu_counter::cpu_array_bits) * 8))
{
sys_log.fatal("Too many threads.");
return array_slot;
}
for (u32 i = 0;; i = (i + 1) % ::size32(cpu_array_bits))
{
const auto [bits, ok] = cpu_array_bits[i].fetch_op([](u64& bits) -> u64
@@ -281,44 +296,92 @@ struct cpu_counter
{
// Get actual slot number
array_slot = i * 64 + std::countr_one(bits);
break;
// Register thread
if (cpu_array[array_slot].compare_and_swap_test(nullptr, _this)) [[likely]]
{
break;
}
sys_log.fatal("Unexpected slot registration failure (%u).", array_slot);
cpu_array_bits[array_slot / 64] &= ~(1ull << (array_slot % 64));
continue;
}
}
// Register and wait if necessary
verify("cpu_counter::add()" HERE), cpu_array[array_slot].exchange(_this) == nullptr;
if (!restore)
{
// First time (thread created)
_this->state += cpu_flag::wait;
cpu_suspend_lock.lock_unlock();
}
_this->state += cpu_flag::wait;
cpu_suspend_lock.lock_unlock();
return array_slot;
}
void remove(cpu_thread* _this, u64 slot)
void remove(cpu_thread* _this, u64 slot) noexcept
{
// Unregister and wait if necessary
_this->state += cpu_flag::wait;
if (cpu_array[slot].exchange(nullptr) != _this)
std::lock_guard lock(cpu_suspend_lock);
if (!cpu_array[slot].compare_and_swap_test(_this, nullptr))
{
sys_log.fatal("Inconsistency for array slot %u", slot);
return;
}
cpu_array_bits[slot / 64] &= ~(1ull << (slot % 64));
cpu_array_sema--;
cpu_suspend_lock.lock_unlock();
}
// Remove temporarily
void remove(cpu_thread* _this) noexcept
{
// Unregister temporarily (called from check_state)
const u64 index = s_tls_thread_slot;
if (index >= std::size(cpu_array))
{
sys_log.fatal("Index out of bounds (%u).", index);
return;
}
if (cpu_array[index].load() == _this && cpu_array[index].compare_and_swap_test(_this, nullptr))
{
cpu_array_bits[index / 64] &= ~(1ull << (index % 64));
return;
}
sys_log.fatal("Thread not found in cpu_array (%s).", _this->get_name());
}
};
template <typename F>
void for_all_cpu(F&& func) noexcept
template <bool UseCopy = false, typename F>
void for_all_cpu(F func) noexcept
{
auto ctr = g_fxo->get<cpu_counter>();
const auto ctr = g_fxo->get<cpu_counter>();
for (u32 i = 0; i < ::size32(ctr->cpu_array_bits); i++)
{
for (u64 bits = ctr->cpu_array_bits[i]; bits; bits &= bits - 1)
for (u64 bits = (UseCopy ? ctr->cpu_copy_bits[i] : ctr->cpu_array_bits[i].load()); bits; bits &= bits - 1)
{
const u64 index = i * 64 + std::countr_zero(bits);
if (cpu_thread* cpu = ctr->cpu_array[index].load())
{
func(cpu);
if constexpr (std::is_invocable_v<F, cpu_thread*, u64>)
{
func(cpu, index);
continue;
}
if constexpr (std::is_invocable_v<F, cpu_thread*>)
{
func(cpu);
continue;
}
}
}
}
@@ -338,7 +401,7 @@ void cpu_thread::operator()()
{
thread_ctrl::set_native_priority(-1);
}
// force input/output denormals to zero for SPU threads (FTZ/DAZ)
_mm_setcsr( _mm_getcsr() | 0x8040 );
@@ -378,23 +441,63 @@ void cpu_thread::operator()()
}
// Register thread in g_cpu_array
const u64 array_slot = g_fxo->get<cpu_counter>()->add(this);
s_tls_thread_slot = g_fxo->get<cpu_counter>()->add(this);
if (array_slot == umax)
if (s_tls_thread_slot == umax)
{
sys_log.fatal("Too many threads.");
return;
}
atomic_storage_futex::set_notify_callback([](const void*, u64 progress)
{
static thread_local bool wait_set = false;
cpu_thread* _cpu = get_current_cpu_thread();
// Wait flag isn't set asynchronously so this should be thread-safe
if (progress == 0 && !(_cpu->state & cpu_flag::wait))
{
// Operation just started and syscall is imminent
_cpu->state += cpu_flag::wait + cpu_flag::temp;
wait_set = true;
return;
}
if (progress == umax && std::exchange(wait_set, false))
{
// Operation finished: need to clean wait flag
verify(HERE), !_cpu->check_state();
return;
}
});
g_tls_log_control = [](const char* fmt, u64 progress)
{
static thread_local bool wait_set = false;
cpu_thread* _cpu = get_current_cpu_thread();
if (progress == 0 && !(_cpu->state & cpu_flag::wait))
{
_cpu->state += cpu_flag::wait + cpu_flag::temp;
wait_set = true;
return;
}
if (progress == umax && std::exchange(wait_set, false))
{
verify(HERE), !_cpu->check_state();
return;
}
};
static thread_local struct thread_cleanup_t
{
cpu_thread* _this;
u64 slot;
std::string name;
thread_cleanup_t(cpu_thread* _this, u64 slot)
thread_cleanup_t(cpu_thread* _this)
: _this(_this)
, slot(slot)
, name(thread_ctrl::get_name())
{
}
@@ -411,7 +514,11 @@ void cpu_thread::operator()()
ptr->compare_and_swap(_this, nullptr);
}
g_fxo->get<cpu_counter>()->remove(_this, slot);
atomic_storage_futex::set_notify_callback(nullptr);
g_tls_log_control = [](const char*, u64){};
g_fxo->get<cpu_counter>()->remove(_this, s_tls_thread_slot);
_this = nullptr;
}
@@ -424,7 +531,7 @@ void cpu_thread::operator()()
cleanup();
}
}
} cleanup{this, array_slot};
} cleanup{this};
// Check thread status
while (!(state & (cpu_flag::exit + cpu_flag::dbg_global_stop)) && thread_ctrl::state() != thread_state::aborting)
@@ -433,11 +540,21 @@ void cpu_thread::operator()()
if (!(state & cpu_flag::stop))
{
cpu_task();
state -= cpu_flag::ret;
if (state & cpu_flag::ret && state.test_and_reset(cpu_flag::ret))
{
cpu_return();
}
continue;
}
thread_ctrl::wait();
if (state & cpu_flag::ret && state.test_and_reset(cpu_flag::ret))
{
cpu_return();
}
}
// Complete cleanup gracefully
@@ -464,13 +581,9 @@ bool cpu_thread::check_state() noexcept
}
bool cpu_sleep_called = false;
bool cpu_flag_memory = false;
bool cpu_can_stop = true;
bool escape, retval;
if (!(state & cpu_flag::wait))
{
state += cpu_flag::wait;
}
u64 susp_ctr = -1;
while (true)
{
@@ -479,6 +592,21 @@ bool cpu_thread::check_state() noexcept
{
bool store = false;
if (flags & cpu_flag::pause && !(flags & cpu_flag::wait))
{
// Save value before state is saved and cpu_flag::wait is observed
susp_ctr = g_suspend_counter;
}
if (flags & cpu_flag::temp) [[unlikely]]
{
// Sticky flag, indicates check_state() is not allowed to return true
flags -= cpu_flag::temp;
flags -= cpu_flag::wait;
cpu_can_stop = false;
store = true;
}
if (flags & cpu_flag::signal)
{
flags -= cpu_flag::signal;
@@ -490,20 +618,20 @@ bool cpu_thread::check_state() noexcept
if (!(flags & (cpu_flag::exit + cpu_flag::dbg_global_stop + cpu_flag::ret + cpu_flag::stop)))
{
// Check pause flags which hold thread inside check_state
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause))
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause + cpu_flag::memory))
{
if (!(flags & cpu_flag::wait))
{
flags += cpu_flag::wait;
store = true;
}
escape = false;
return store;
}
if (flags & cpu_flag::memory)
if (flags & cpu_flag::wait)
{
// wait flag will be cleared later (optimization)
cpu_flag_memory = true;
}
else
{
AUDIT(!cpu_flag_memory);
flags -= cpu_flag::wait;
store = true;
}
@@ -512,12 +640,18 @@ bool cpu_thread::check_state() noexcept
}
else
{
cpu_flag_memory = false;
retval = true;
if (cpu_can_stop && !(flags & cpu_flag::wait))
{
flags += cpu_flag::wait;
store = true;
}
retval = cpu_can_stop;
}
if (flags & cpu_flag::dbg_step)
if (cpu_can_stop && flags & cpu_flag::dbg_step)
{
// Can't process dbg_step if we only paused temporarily
flags += cpu_flag::dbg_pause;
flags -= cpu_flag::dbg_step;
store = true;
@@ -529,23 +663,30 @@ bool cpu_thread::check_state() noexcept
if (escape)
{
if (cpu_flag_memory)
if (s_tls_thread_slot == umax)
{
cpu_mem();
if (state & (cpu_flag::pause + cpu_flag::memory)) [[unlikely]]
{
state += cpu_flag::wait;
continue;
}
// Restore thread in the suspend list
std::lock_guard lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
s_tls_thread_slot = g_fxo->get<cpu_counter>()->add(this, true);
}
verify(HERE), cpu_can_stop || !retval;
return retval;
}
else if (!cpu_sleep_called && state0 & cpu_flag::suspend)
if (!cpu_sleep_called && state0 & cpu_flag::suspend)
{
cpu_sleep();
cpu_sleep_called = true;
if (cpu_can_stop && s_tls_thread_slot != umax)
{
// Exclude inactive threads from the suspend list (optimization)
std::lock_guard lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
g_fxo->get<cpu_counter>()->remove(this);
s_tls_thread_slot = -1;
}
continue;
}
@@ -555,8 +696,48 @@ bool cpu_thread::check_state() noexcept
}
else
{
// If only cpu_flag::pause was set, notification won't arrive
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
if (state0 & cpu_flag::memory)
{
vm::passive_lock(*this);
continue;
}
// If only cpu_flag::pause was set, wait on suspend counter instead
if (state0 & cpu_flag::pause)
{
if (state0 & cpu_flag::wait)
{
// Otherwise, value must be reliable because cpu_flag::wait hasn't been observed yet
susp_ctr = -1;
}
// Hard way
if (susp_ctr == umax) [[unlikely]]
{
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
continue;
}
// Wait for current suspend_all operation
for (u64 i = 0;; i++)
{
if (i < 20)
{
busy_wait(300);
}
else
{
g_suspend_counter.wait(susp_ctr);
}
if (!(state & cpu_flag::pause))
{
break;
}
}
susp_ctr = -1;
}
}
}
}
@@ -627,7 +808,7 @@ std::string cpu_thread::dump_callstack() const
return {};
}
std::vector<u32> cpu_thread::dump_callstack_list() const
std::vector<std::pair<u32, u32>> cpu_thread::dump_callstack_list() const
{
return {};
}
@@ -637,68 +818,171 @@ std::string cpu_thread::dump_misc() const
return fmt::format("Type: %s\n" "State: %s\n", typeid(*this).name(), state.load());
}
cpu_thread::suspend_all::suspend_all(cpu_thread* _this) noexcept
: m_this(_this)
bool cpu_thread::suspend_work::push(cpu_thread* _this, bool cancel_if_not_suspended) noexcept
{
if (m_this)
{
m_this->state += cpu_flag::wait;
}
// Can't allow pre-set wait bit (it'd be a problem)
verify(HERE), !_this || !(_this->state & cpu_flag::wait);
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_vip();
// cpu_counter object
const auto ctr = g_fxo->get<cpu_counter>();
for_all_cpu([](cpu_thread* cpu)
// Try to push workload
auto& queue = ctr->cpu_suspend_work;
do
{
if (!(cpu->state & cpu_flag::pause))
// Load current head
next = queue.load();
if (!next && cancel_if_not_suspended) [[unlikely]]
{
cpu->state += cpu_flag::pause;
// Give up if not suspended
return false;
}
});
busy_wait(500);
if (!_this && next)
{
// If _this == nullptr, it only works if this is the first workload pushed
ctr->cpu_suspend_lock.lock_unlock();
continue;
}
}
while (!queue.compare_and_swap_test(next, this));
while (true)
if (!next)
{
bool ok = true;
// Monitor the performance only of the actual suspend processing owner
perf_meter<"SUSPEND"_u64> perf0;
// First thread to push the work to the workload list pauses all threads and processes it
std::lock_guard lock(ctr->cpu_suspend_lock);
// Try to prefetch cpu->state earlier
for_all_cpu([&](cpu_thread* cpu)
{
if (!(cpu->state & cpu_flag::wait))
if (cpu != _this)
{
ok = false;
_m_prefetchw(&cpu->state);
}
});
if (ok) [[likely]]
// Copy of thread bits
decltype(ctr->cpu_copy_bits) copy2{};
for (u32 i = 0; i < ::size32(ctr->cpu_copy_bits); i++)
{
break;
copy2[i] = ctr->cpu_copy_bits[i] = ctr->cpu_array_bits[i].load();
}
busy_wait(500);
}
}
for_all_cpu([&](cpu_thread* cpu, u64 index)
{
if (cpu == _this || cpu->state.fetch_add(cpu_flag::pause) & cpu_flag::wait)
{
// Clear bits as long as wait flag is set
ctr->cpu_copy_bits[index / 64] &= ~(1ull << (index % 64));
}
cpu_thread::suspend_all::~suspend_all()
{
// Make sure the latest thread does the cleanup and notifies others
if (g_fxo->get<cpu_counter>()->cpu_suspend_lock.downgrade_unique_vip_lock_to_low_or_unlock())
{
for_all_cpu([&](cpu_thread* cpu)
if (cpu == _this)
{
copy2[index / 64] &= ~(1ull << (index % 64));
}
});
while (true)
{
// Check only CPUs which haven't acknowledged their waiting state yet
for_all_cpu<true>([&](cpu_thread* cpu, u64 index)
{
if (cpu->state & cpu_flag::wait)
{
ctr->cpu_copy_bits[index / 64] &= ~(1ull << (index % 64));
}
});
if (!std::accumulate(std::begin(ctr->cpu_copy_bits), std::end(ctr->cpu_copy_bits), u64{0}, std::bit_or()))
{
break;
}
_mm_pause();
}
// Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?)
auto* head = queue.exchange(nullptr);
s8 min_prio = head->prio;
s8 max_prio = head->prio;
if (auto* prev = head->next)
{
head->next = nullptr;
do
{
auto* pre2 = prev->next;
prev->next = head;
head = std::exchange(prev, pre2);
// Fill priority range
min_prio = std::min<s8>(min_prio, head->prio);
max_prio = std::max<s8>(max_prio, head->prio);
}
while (prev);
}
// Execute prefetch hint(s)
for (auto work = head; work; work = work->next)
{
for (u32 i = 0; i < work->prf_size; i++)
{
_m_prefetchw(work->prf_list[0]);
}
}
for_all_cpu<true>([&](cpu_thread* cpu)
{
_m_prefetchw(&cpu->state);
});
// Execute all stored workload
for (s32 prio = max_prio; prio >= min_prio; prio--)
{
// ... according to priorities
for (auto work = head; work; work = work->next)
{
// Properly sorting single-linked list may require to optimize the loop
if (work->prio == prio)
{
work->exec(work->func_ptr, work->res_buf);
}
}
}
// Not sure if needed, may be overkill. Some workloads may execute instructions with non-temporal hint.
_mm_sfence();
// Finalization
g_suspend_counter++;
// Exact bitset for flag pause removal
std::memcpy(ctr->cpu_copy_bits, copy2, sizeof(copy2));
for_all_cpu<true>([&](cpu_thread* cpu)
{
cpu->state -= cpu_flag::pause;
});
g_fxo->get<cpu_counter>()->cpu_suspend_lock.unlock_low();
}
else
{
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
// Seems safe to set pause on self because wait flag hasn't been observed yet
_this->state += cpu_flag::pause + cpu_flag::temp;
_this->check_state();
return true;
}
if (m_this)
{
m_this->check_state();
}
g_suspend_counter.notify_all();
return true;
}
void cpu_thread::stop_all() noexcept
@@ -711,13 +995,16 @@ void cpu_thread::stop_all() noexcept
}
else
{
::vip_lock lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
std::lock_guard lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
for_all_cpu([](cpu_thread* cpu)
auto on_stop = [](u32, cpu_thread& cpu)
{
cpu->state += cpu_flag::dbg_global_stop;
cpu->abort();
});
cpu.state += cpu_flag::dbg_global_stop;
cpu.abort();
};
idm::select<named_thread<ppu_thread>>(on_stop);
idm::select<named_thread<spu_thread>>(on_stop);
}
sys_log.notice("All CPU threads have been signaled.");
@@ -727,7 +1014,12 @@ void cpu_thread::stop_all() noexcept
std::this_thread::sleep_for(10ms);
}
sys_log.notice("All CPU threads have been stopped.");
sys_log.notice("All CPU threads have been stopped. [+: %u]", +g_threads_created);
std::lock_guard lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
g_threads_deleted -= g_threads_created.load();
g_threads_created = 0;
}
void cpu_thread::flush_profilers() noexcept
+73 -19
View File
@@ -11,6 +11,7 @@ enum class cpu_flag : u32
stop, // Thread not running (HLE, initial state)
exit, // Irreversible exit
wait, // Indicates waiting state, set by the thread itself
temp, // Indicates that the thread cannot properly return after next check_state()
pause, // Thread suspended by suspend_all technique
suspend, // Thread suspended
ret, // Callback return requested
@@ -27,9 +28,6 @@ enum class cpu_flag : u32
class cpu_thread
{
// PPU cache backward compatibility hack
char dummy[sizeof(std::shared_ptr<void>) - 8];
public:
u64 block_hash = 0;
@@ -75,6 +73,11 @@ public:
return !!(state & (cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause));
}
bool has_pause_flag() const
{
return !!(state & cpu_flag::pause);
}
// Check thread type
u32 id_type() const
{
@@ -88,13 +91,13 @@ private:
public:
// Thread stats for external observation
static atomic_t<u64> g_threads_created, g_threads_deleted;
static atomic_t<u64> g_threads_created, g_threads_deleted, g_suspend_counter;
// Get thread name (as assigned to named_thread)
std::string get_name() const;
// Get CPU state dump (everything)
virtual std::string dump_all() const = 0;
virtual std::string dump_all() const;
// Get CPU register dump
virtual std::string dump_regs() const;
@@ -103,7 +106,7 @@ public:
virtual std::string dump_callstack() const;
// Get CPU call stack list
virtual std::vector<u32> dump_callstack_list() const;
virtual std::vector<std::pair<u32, u32>> dump_callstack_list() const;
// Get CPU dump of misc information
virtual std::string dump_misc() const;
@@ -114,24 +117,75 @@ public:
// Callback for cpu_flag::suspend
virtual void cpu_sleep() {}
// Callback for cpu_flag::memory
virtual void cpu_mem() {}
// Callback for cpu_flag::ret
virtual void cpu_return() {}
// Callback for vm::temporary_unlock
virtual void cpu_unmem() {}
// Thread locker
class suspend_all
// For internal use
struct suspend_work
{
cpu_thread* m_this;
// Task priority
s8 prio;
public:
suspend_all(cpu_thread* _this) noexcept;
suspend_all(const suspend_all&) = delete;
suspend_all& operator=(const suspend_all&) = delete;
~suspend_all();
// Size of prefetch list workload
u32 prf_size;
void* const* prf_list;
void* func_ptr;
void* res_buf;
// Type-erased op executor
void (*exec)(void* func, void* res);
// Next object in the linked list
suspend_work* next;
// Internal method
bool push(cpu_thread* _this, bool cancel_if_not_suspended = false) noexcept;
};
// Suspend all threads and execute op (may be executed by other thread than caller!)
template <s8 Prio = 0, typename F>
static auto suspend_all(cpu_thread* _this, std::initializer_list<void*> hints, F op)
{
if constexpr (std::is_void_v<std::invoke_result_t<F>>)
{
suspend_work work{Prio, ::size32(hints), hints.begin(), &op, nullptr, [](void* func, void*)
{
std::invoke(*static_cast<F*>(func));
}};
work.push(_this);
return;
}
else
{
std::invoke_result_t<F> result;
suspend_work work{Prio, ::size32(hints), hints.begin(), &op, &result, [](void* func, void* res_buf)
{
*static_cast<std::invoke_result_t<F>*>(res_buf) = std::invoke(*static_cast<F*>(func));
}};
work.push(_this);
return result;
}
}
// Push the workload only if threads are being suspended by suspend_all()
template <s8 Prio = 0, typename F>
static bool if_suspended(cpu_thread* _this, std::initializer_list<void*> hints, F op)
{
static_assert(std::is_void_v<std::invoke_result_t<F>>, "Unimplemented (must return void)");
{
suspend_work work{Prio, ::size32(hints), hints.begin(), &op, nullptr, [](void* func, void*)
{
std::invoke(*static_cast<F*>(func));
}};
return work.push(_this, true);
}
}
// Stop all threads with cpu_flag::dbg_global_stop
static void stop_all() noexcept;
+47 -9
View File
@@ -57,6 +57,15 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
{
m_use_fma = true;
}
// Test AVX-512_icelake features (TODO)
if (cpu == "icelake" ||
cpu == "icelake-client" ||
cpu == "icelake-server" ||
cpu == "tigerlake")
{
m_use_avx512_icl = true;
}
}
llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type)
@@ -65,9 +74,9 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type)
uint s2 = val->getType()->getScalarSizeInBits();
if (type->isVectorTy())
s1 *= type->getVectorNumElements();
s1 *= llvm::cast<llvm::VectorType>(type)->getNumElements();
if (val->getType()->isVectorTy())
s2 *= val->getType()->getVectorNumElements();
s2 *= llvm::cast<llvm::VectorType>(val->getType())->getNumElements();
if (s1 != s2)
{
@@ -83,18 +92,37 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type)
}
template <>
v128 cpu_translator::get_const_vector<v128>(llvm::Constant* c, u32 a, u32 b)
std::pair<bool, v128> cpu_translator::get_const_vector<v128>(llvm::Value* c, u32 a, u32 b)
{
v128 result{};
if (!llvm::isa<llvm::Constant>(c))
{
return {false, result};
}
const auto t = c->getType();
if (!t->isVectorTy())
{
if (const auto ci = llvm::dyn_cast<llvm::ConstantInt>(c); ci && ci->getBitWidth() == 128)
{
auto cv = ci->getValue();
for (int i = 0; i < 128; i++)
{
result._bit[i] = cv[i];
}
return {true, result};
}
fmt::throw_exception("[0x%x, %u] Not a vector" HERE, a, b);
}
if (uint sz = llvm::cast<llvm::VectorType>(t)->getBitWidth() - 128)
if (auto v = llvm::cast<llvm::VectorType>(t); v->getScalarSizeInBits() * v->getNumElements() != 128)
{
fmt::throw_exception("[0x%x, %u] Bad vector size: %u" HERE, a, b, sz + 128);
fmt::throw_exception("[0x%x, %u] Bad vector size: i%ux%u" HERE, a, b, v->getScalarSizeInBits(), v->getNumElements());
}
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
@@ -106,13 +134,17 @@ v128 cpu_translator::get_const_vector<v128>(llvm::Constant* c, u32 a, u32 b)
return {};
}
if (llvm::isa<llvm::ConstantExpr>(c))
{
// Sorry, if we cannot evaluate it we cannot use it
fmt::throw_exception("[0x%x, %u] Constant Expression!" HERE, a, b);
}
fmt::throw_exception("[0x%x, %u] Unexpected constant type" HERE, a, b);
}
const auto sct = t->getScalarType();
v128 result;
if (sct->isIntegerTy(8))
{
for (u32 i = 0; i < 16; i++)
@@ -160,13 +192,19 @@ v128 cpu_translator::get_const_vector<v128>(llvm::Constant* c, u32 a, u32 b)
fmt::throw_exception("[0x%x, %u] Unexpected vector element type" HERE, a, b);
}
return result;
return {true, result};
}
template <>
llvm::Constant* cpu_translator::make_const_vector<v128>(v128 v, llvm::Type* t)
{
verify(HERE), t->isVectorTy() && llvm::cast<llvm::VectorType>(t)->getBitWidth() == 128;
if (const auto ct = llvm::dyn_cast<llvm::IntegerType>(t); ct && ct->getBitWidth() == 128)
{
return llvm::ConstantInt::get(t, llvm::APInt(128, llvm::makeArrayRef(reinterpret_cast<const u64*>(v._bytes), 2)));
}
verify(HERE), t->isVectorTy();
verify(HERE), 128 == t->getScalarSizeInBits() * llvm::cast<llvm::VectorType>(t)->getNumElements();
const auto sct = t->getScalarType();
+87 -18
View File
@@ -363,7 +363,7 @@ struct llvm_value_t<T[N]> : llvm_value_t<std::conditional_t<(std::extent_v<T> >
}
else if constexpr (N > 1)
{
return llvm::VectorType::get(base::get_type(context), N);
return llvm::VectorType::get(base::get_type(context), N, false);
}
else
{
@@ -2283,9 +2283,11 @@ struct llvm_splat
if (auto i = llvm::dyn_cast_or_null<llvm::ShuffleVectorInst>(value))
{
if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(2)))
if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(1)) || llvm::isa<llvm::UndefValue>(i->getOperand(1)))
{
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0)))
static constexpr int zero_array[llvm_value_t<U>::is_vector]{};
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0)); j && i->getShuffleMask().equals(zero_array))
{
if (llvm::cast<llvm::ConstantInt>(j->getOperand(2))->isZero())
{
@@ -2311,7 +2313,7 @@ struct llvm_zshuffle
using type = std::remove_extent_t<T>[N];
llvm_expr_t<A1> a1;
u32 index_array[N];
int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_zshuffle<>: invalid type");
@@ -2334,7 +2336,7 @@ struct llvm_zshuffle
if (auto z = llvm::dyn_cast<llvm::ConstantAggregateZero>(i->getOperand(1)); z && z->getType() == v1->getType())
{
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2))
if (i->getShuffleMask().equals(index_array))
{
if (auto r1 = a1.match(v1); v1)
{
@@ -2356,7 +2358,7 @@ struct llvm_shuffle2
llvm_expr_t<A1> a1;
llvm_expr_t<A2> a2;
u32 index_array[N];
int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_shuffle2<>: invalid type");
@@ -2382,7 +2384,7 @@ struct llvm_shuffle2
if (v1->getType() == v2->getType() && v1->getType() == llvm_value_t<T>::get_type(v1->getContext()))
{
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2))
if (i->getShuffleMask().equals(index_array))
{
if (auto r1 = a1.match(v1); v1)
{
@@ -2423,6 +2425,9 @@ protected:
// Allow FMA
bool m_use_fma = false;
// Allow Icelake tier AVX-512
bool m_use_avx512_icl = false;
// IR builder
llvm::IRBuilder<>* m_ir;
@@ -2662,13 +2667,13 @@ public:
template <typename T, typename... Args, typename = std::enable_if_t<llvm_zshuffle<sizeof...(Args), T>::is_ok>>
static auto zshuffle(T&& v, Args... indices)
{
return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<u32>(indices)...}};
return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<int>(indices)...}};
}
template <typename T, typename U, typename... Args, typename = std::enable_if_t<llvm_shuffle2<sizeof...(Args), T, U>::is_ok>>
static auto shuffle2(T&& v1, U&& v2, Args... indices)
{
return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<u32>(indices)...}};
return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<int>(indices)...}};
}
// Average: (a + b + 1) >> 1
@@ -2682,7 +2687,7 @@ public:
const auto cast_op = result.is_sint ? llvm::Instruction::SExt : llvm::Instruction::ZExt;
llvm::Type* cast_to = m_ir->getIntNTy(result.esize * 2);
if constexpr (result.is_vector != 0)
cast_to = llvm::VectorType::get(cast_to, result.is_vector);
cast_to = llvm::VectorType::get(cast_to, result.is_vector, false);
const auto axt = m_ir->CreateCast(cast_op, a.eval(m_ir), cast_to);
const auto bxt = m_ir->CreateCast(cast_op, b.eval(m_ir), cast_to);
@@ -2744,19 +2749,83 @@ public:
}
// TODO: Support doubles
auto fre(value_t<f32[4]> a)
template <typename T, typename = std::enable_if_t<llvm_value_t<typename T::type>::esize == 32u && llvm_value_t<typename T::type>::is_float>>
auto fre(T a)
{
decltype(a) result;
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()).getCallee(), {av});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()), {av});
return result;
}
auto frsqe(value_t<f32[4]> a)
template <typename T, typename = std::enable_if_t<llvm_value_t<typename T::type>::esize == 32u && llvm_value_t<typename T::type>::is_float>>
auto frsqe(T a)
{
decltype(a) result;
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()).getCallee(), {av});
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()), {av});
return result;
}
template <typename T, typename U, typename = std::enable_if_t<std::is_same_v<typename T::type, typename U::type> && llvm_value_t<typename T::type>::esize == 32u && llvm_value_t<typename T::type>::is_float>>
auto fmax(T a, U b)
{
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.max.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result;
}
template <typename T, typename U, typename = std::enable_if_t<std::is_same_v<typename T::type, typename U::type> && llvm_value_t<typename T::type>::esize == 32u && llvm_value_t<typename T::type>::is_float>>
auto fmin(T a, U b)
{
value_t<typename T::type> result;
const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.min.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result;
}
template <typename T1, typename T2>
value_t<u8[16]> gf2p8affineqb(T1 a, T2 b, u8 c)
{
value_t<u8[16]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto immediate = (llvm_const_int<u8>{c});
const auto imm8 = immediate.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_vgf2p8affineqb_128), {data0, data1, imm8});
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u8[16]> vperm2b(T1 a, T2 b, T3 c)
{
value_t<u8[16]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto index = c.eval(m_ir);
const auto zeros = llvm::ConstantAggregateZero::get(get_type<u8[16]>());
if (auto c = llvm::dyn_cast<llvm::Constant>(index))
{
// Convert VPERM2B index back to LLVM vector shuffle mask
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
if (cv || llvm::isa<llvm::ConstantAggregateZero>(c))
{
result.value = m_ir->CreateZExt(cv, get_type<u32[16]>());
result.value = m_ir->CreateShuffleVector(data0, data1, result.value);
return result;
}
}
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpermi2var_qi_128), {data0, index, data1});
return result;
}
@@ -2837,7 +2906,7 @@ public:
}
template <typename R = v128>
R get_const_vector(llvm::Constant*, u32 a, u32 b);
std::pair<bool, R> get_const_vector(llvm::Value*, u32 a, u32 b);
template <typename T = v128>
llvm::Constant* make_const_vector(T, llvm::Type*);
@@ -2863,7 +2932,7 @@ struct fmt_unveil<llvm::TypeSize, void>
template <>
inline llvm::Type* cpu_translator::get_type<__m128i>()
{
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16);
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16, false);
}
#ifndef _MSC_VER
+2
View File
@@ -1,5 +1,7 @@
#include "stdafx.h"
#include "StaticHLE.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/PPUOpcodes.h"
LOG_CHANNEL(static_hle);
+1 -2
View File
@@ -1,8 +1,7 @@
#pragma once
#include "../../Utilities/types.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/PPUOpcodes.h"
#include "Emu/Memory/vm_ptr.h"
#include <vector>
struct shle_pattern
+1
View File
@@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_sync.h"
+165 -36
View File
@@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_process.h"
@@ -44,8 +45,43 @@ void fmt_class_string<CellAudioError>::format(std::string& out, u64 arg)
cell_audio_config::cell_audio_config()
{
raw = audio::get_raw_config();
reset();
}
void cell_audio_config::reset()
{
backend.reset();
backend = Emu.GetCallbacks().get_audio();
audio_channels = backend->get_channels();
audio_sampling_rate = backend->get_sampling_rate();
audio_block_period = AUDIO_BUFFER_SAMPLES * 1000000 / audio_sampling_rate;
audio_buffer_length = AUDIO_BUFFER_SAMPLES * audio_channels;
audio_buffer_size = audio_buffer_length * backend->get_sample_size();
desired_buffer_duration = raw.desired_buffer_duration * 1000llu;
buffering_enabled = raw.buffering_enabled && backend->has_capability(AudioBackend::PLAY_PAUSE_FLUSH | AudioBackend::IS_PLAYING);;
minimum_block_period = audio_block_period / 2;
maximum_block_period = (6 * audio_block_period) / 5;
desired_full_buffers = buffering_enabled ? static_cast<u32>(desired_buffer_duration / audio_block_period) + 3 : 2;
num_allocated_buffers = desired_full_buffers + EXTRA_AUDIO_BUFFERS;
fully_untouched_timeout = static_cast<u64>(audio_block_period) * 2;
partially_untouched_timeout = static_cast<u64>(audio_block_period) * 4;
const bool raw_time_stretching_enabled = buffering_enabled && raw.enable_time_stretching && (raw.time_stretching_threshold > 0);
time_stretching_enabled = raw_time_stretching_enabled && backend->has_capability(AudioBackend::SET_FREQUENCY_RATIO);
time_stretching_threshold = raw.time_stretching_threshold / 100.0f;
// Warn if audio backend does not support all requested features
if (raw_buffering_enabled && !buffering_enabled)
if (raw.buffering_enabled && !buffering_enabled)
{
cellAudio.error("Audio backend %s does not support buffering, this option will be ignored.", backend->GetName());
}
@@ -122,6 +158,11 @@ f32 audio_ringbuffer::set_frequency_ratio(f32 new_ratio)
return frequency_ratio;
}
u64 audio_ringbuffer::get_timestamp() const
{
return get_system_time() - Emu.GetPauseTime();
}
void audio_ringbuffer::enqueue(const float* in_buffer)
{
AUDIT(cur_pos < cfg.num_allocated_buffers);
@@ -142,7 +183,7 @@ void audio_ringbuffer::enqueue(const float* in_buffer)
}
// Enqueue audio
bool success = backend->AddData(buf, AUDIO_BUFFER_SAMPLES * cfg.audio_channels);
const bool success = backend->AddData(buf, AUDIO_BUFFER_SAMPLES * cfg.audio_channels);
if (!success)
{
cellAudio.error("Could not enqueue buffer onto audio backend. Attempting to recover...");
@@ -311,8 +352,8 @@ void audio_port::tag(s32 offset)
// We use -0.0f in case games check if the buffer is empty. -0.0f == 0.0f evaluates to true, but std::signbit can be used to distinguish them
const f32 tag = -0.0f;
const u32 tag_first_pos = num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : PORT_BUFFER_TAG_DELTA_8CH;
const u32 tag_first_pos = num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : num_channels == 6 ? PORT_BUFFER_TAG_FIRST_6CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : num_channels == 6 ? PORT_BUFFER_TAG_DELTA_6CH : PORT_BUFFER_TAG_DELTA_8CH;
for (u32 tag_pos = tag_first_pos, tag_nr = 0; tag_nr < PORT_BUFFER_TAG_COUNT; tag_pos += tag_delta, tag_nr++)
{
@@ -341,8 +382,8 @@ std::tuple<u32, u32, u32, u32> cell_audio_thread::count_port_buffer_tags()
u32 port_pos = port.position();
// Find the last tag that has been touched
const u32 tag_first_pos = port.num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = port.num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : PORT_BUFFER_TAG_DELTA_8CH;
const u32 tag_first_pos = port.num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : port.num_channels == 6 ? PORT_BUFFER_TAG_FIRST_6CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = port.num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : port.num_channels == 6 ? PORT_BUFFER_TAG_DELTA_6CH : PORT_BUFFER_TAG_DELTA_8CH;
u32 last_touched_tag_nr = port.prev_touched_tag_nr;
bool retouched = false;
@@ -500,6 +541,63 @@ void cell_audio_thread::advance(u64 timestamp, bool reset)
}
}
namespace audio
{
cell_audio_config::raw_config get_raw_config()
{
return
{
.buffering_enabled = static_cast<bool>(g_cfg.audio.enable_buffering),
.desired_buffer_duration = g_cfg.audio.desired_buffer_duration,
.enable_time_stretching = static_cast<bool>(g_cfg.audio.enable_time_stretching),
.time_stretching_threshold = g_cfg.audio.time_stretching_threshold,
.convert_to_u16 = static_cast<bool>(g_cfg.audio.convert_to_u16),
.start_threshold = static_cast<u32>(g_cfg.audio.start_threshold),
.sampling_period_multiplier = static_cast<u32>(g_cfg.audio.sampling_period_multiplier),
.downmix = g_cfg.audio.audio_channel_downmix,
.renderer = g_cfg.audio.renderer
};
}
void configure_audio()
{
if (const auto g_audio = g_fxo->get<cell_audio>())
{
// Only reboot the audio renderer if a relevant setting changed
const auto new_raw = get_raw_config();
if (const auto raw = g_audio->cfg.raw;
raw.desired_buffer_duration != new_raw.desired_buffer_duration ||
raw.buffering_enabled != new_raw.buffering_enabled ||
raw.time_stretching_threshold != new_raw.time_stretching_threshold ||
raw.enable_time_stretching != new_raw.enable_time_stretching ||
raw.convert_to_u16 != new_raw.convert_to_u16 ||
raw.start_threshold != new_raw.start_threshold ||
raw.sampling_period_multiplier != new_raw.sampling_period_multiplier ||
raw.downmix != new_raw.downmix ||
raw.renderer != new_raw.renderer)
{
g_audio->cfg.raw = new_raw;
g_audio->m_update_configuration = true;
}
}
}
}
void cell_audio_thread::update_config()
{
std::lock_guard lock(mutex);
// Clear ringbuffer
ringbuffer.reset();
// Reload config
cfg.reset();
// Allocate ringbuffer
ringbuffer.reset(new audio_ringbuffer(cfg));
}
void cell_audio_thread::operator()()
{
thread_ctrl::set_native_priority(1);
@@ -519,6 +617,12 @@ void cell_audio_thread::operator()()
// Main cellAudio loop
while (thread_ctrl::state() != thread_state::aborting)
{
if (m_update_configuration)
{
update_config();
m_update_configuration = false;
}
const u64 timestamp = ringbuffer->update();
if (Emu.IsPaused())
@@ -742,16 +846,19 @@ void cell_audio_thread::operator()()
// Mix
float *buf = ringbuffer->get_current_buffer();
if (cfg.audio_channels == 2)
{
mix<true>(buf);
}
else if (cfg.audio_channels == 8)
{
mix<false>(buf);
}
else
switch (cfg.audio_channels)
{
case 2:
mix<audio_downmix::downmix_to_stereo>(buf);
break;
case 6:
mix<audio_downmix::downmix_to_5_1>(buf);
break;
case 8:
mix<audio_downmix::no_downmix>(buf);
break;
default:
fmt::throw_exception("Unsupported number of audio channels: %u", cfg.audio_channels);
}
@@ -766,12 +873,12 @@ void cell_audio_thread::operator()()
ringbuffer.reset();
}
template <bool DownmixToStereo>
template <audio_downmix downmix>
void cell_audio_thread::mix(float *out_buffer, s32 offset)
{
AUDIT(out_buffer != nullptr);
constexpr u32 channels = DownmixToStereo ? 2 : 8;
constexpr u32 channels = downmix == audio_downmix::no_downmix ? 8 : downmix == audio_downmix::downmix_to_5_1 ? 6 : 2;
constexpr u32 out_buffer_sz = channels * AUDIO_BUFFER_SAMPLES;
bool first_mix = true;
@@ -823,14 +930,18 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
out_buffer[out + 0] = left;
out_buffer[out + 1] = right;
if constexpr (!DownmixToStereo)
if constexpr (downmix != audio_downmix::downmix_to_stereo)
{
out_buffer[out + 2] = 0.0f;
out_buffer[out + 3] = 0.0f;
out_buffer[out + 4] = 0.0f;
out_buffer[out + 5] = 0.0f;
out_buffer[out + 6] = 0.0f;
out_buffer[out + 7] = 0.0f;
if constexpr (downmix != audio_downmix::downmix_to_5_1)
{
out_buffer[out + 6] = 0.0f;
out_buffer[out + 7] = 0.0f;
}
}
}
first_mix = false;
@@ -866,12 +977,21 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
const float side_left = buf[in + 6] * m;
const float side_right = buf[in + 7] * m;
if constexpr (DownmixToStereo)
if constexpr (downmix == audio_downmix::downmix_to_stereo)
{
// Don't mix in the lfe as per dolby specification and based on documentation
const float mid = center * 0.5;
out_buffer[out + 0] = left * minus_3db + mid + side_left * 0.5 + rear_left * 0.5;
out_buffer[out + 1] = right * minus_3db + mid + side_right * 0.5 + rear_right * 0.5;
const float mid = center * 0.5f;
out_buffer[out + 0] = left * minus_3db + mid + side_left * 0.5f + rear_left * 0.5f;
out_buffer[out + 1] = right * minus_3db + mid + side_right * 0.5f + rear_right * 0.5f;
}
else if constexpr (downmix == audio_downmix::downmix_to_5_1)
{
out_buffer[out + 0] = left;
out_buffer[out + 1] = right;
out_buffer[out + 2] = center;
out_buffer[out + 3] = low_freq;
out_buffer[out + 4] = side_left + rear_left;
out_buffer[out + 5] = side_right + rear_right;
}
else
{
@@ -902,12 +1022,21 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
const float side_left = buf[in + 6] * m;
const float side_right = buf[in + 7] * m;
if constexpr (DownmixToStereo)
if constexpr (downmix == audio_downmix::downmix_to_stereo)
{
// Don't mix in the lfe as per dolby specification and based on documentation
const float mid = center * 0.5;
out_buffer[out + 0] += left * minus_3db + mid + side_left * 0.5 + rear_left * 0.5;
out_buffer[out + 1] += right * minus_3db + mid + side_right * 0.5 + rear_right * 0.5;
const float mid = center * 0.5f;
out_buffer[out + 0] += left * minus_3db + mid + side_left * 0.5f + rear_left * 0.5f;
out_buffer[out + 1] += right * minus_3db + mid + side_right * 0.5f + rear_right * 0.5f;
}
else if constexpr (downmix == audio_downmix::downmix_to_5_1)
{
out_buffer[out + 0] += left;
out_buffer[out + 1] += right;
out_buffer[out + 2] += center;
out_buffer[out + 3] += low_freq;
out_buffer[out + 4] += side_left + rear_left;
out_buffer[out + 5] += side_right + rear_right;
}
else
{
@@ -934,7 +1063,7 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
{
std::memset(out_buffer, 0, out_buffer_sz * sizeof(float));
}
else if (g_cfg.audio.convert_to_u16)
else if (cfg.backend->get_convert_to_u16())
{
// convert the data from float to u16 with clipping:
// 2x MULPS
@@ -1097,7 +1226,7 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32
{
return CELL_AUDIO_ERROR_PORT_FULL;
}
// TODO: is this necessary in any way? (Based on libaudio.prx)
//const u64 num_channels_non_0 = std::max<u64>(1, num_channels);
@@ -1368,7 +1497,7 @@ error_code cellAudioSetPortLevel(u32 portNum, float level)
return CELL_OK;
}
static error_code AudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key, u32 queue_type)
static error_code AudioCreateNotifyEventQueue(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<u64> key, u32 queue_type)
{
vm::var<sys_event_queue_attribute_t> attr;
attr->protocol = SYS_SYNC_FIFO;
@@ -1384,7 +1513,7 @@ static error_code AudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key,
// So check initialization as well
const u32 queue_depth = g_fxo->get<cell_audio>()->init && g_ps3_process_info.sdk_ver <= 0x35FFFF ? 2 : 8;
if (CellError res{sys_event_queue_create(id, attr, key_value, queue_depth) + 0u})
if (CellError res{sys_event_queue_create(ppu, id, attr, key_value, queue_depth) + 0u})
{
if (res != CELL_EEXIST)
{
@@ -1401,14 +1530,14 @@ static error_code AudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key,
return CELL_AUDIO_ERROR_EVENT_QUEUE;
}
error_code cellAudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key)
error_code cellAudioCreateNotifyEventQueue(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<u64> key)
{
cellAudio.warning("cellAudioCreateNotifyEventQueue(id=*0x%x, key=*0x%x)", id, key);
return AudioCreateNotifyEventQueue(id, key, SYS_PPU_QUEUE);
return AudioCreateNotifyEventQueue(ppu, id, key, SYS_PPU_QUEUE);
}
error_code cellAudioCreateNotifyEventQueueEx(vm::ptr<u32> id, vm::ptr<u64> key, u32 iFlags)
error_code cellAudioCreateNotifyEventQueueEx(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<u64> key, u32 iFlags)
{
cellAudio.warning("cellAudioCreateNotifyEventQueueEx(id=*0x%x, key=*0x%x, iFlags=0x%x)", id, key, iFlags);
@@ -1418,7 +1547,7 @@ error_code cellAudioCreateNotifyEventQueueEx(vm::ptr<u32> id, vm::ptr<u64> key,
}
const u32 queue_type = (iFlags & CELL_AUDIO_CREATEEVENTFLAG_SPU) ? SYS_SPU_QUEUE : SYS_PPU_QUEUE;
return AudioCreateNotifyEventQueue(id, key, queue_type);
return AudioCreateNotifyEventQueue(ppu, id, key, queue_type);
}
error_code AudioSetNotifyEventQueue(u64 key, u32 iFlags)
+58 -29
View File
@@ -5,6 +5,7 @@
#include "Emu/Memory/vm.h"
#include "Emu/Audio/AudioBackend.h"
#include "Emu/Audio/AudioDumper.h"
#include "Emu/system_config_types.h"
struct lv2_event_queue;
@@ -64,6 +65,7 @@ enum
CELL_AUDIO_PORTATTR_OUT_PERSONAL_2 = 0x0000000004000000ULL,
CELL_AUDIO_PORTATTR_OUT_PERSONAL_3 = 0x0000000008000000ULL,
CELL_AUDIO_PORTATTR_OUT_SECONDARY = 0x0000000000000001ULL,
CELL_AUDIO_PORTATTR_OUT_STREAM1 = 0x0000000000000001ULL,
CELL_AUDIO_STATUS_CLOSE = 0x1010,
CELL_AUDIO_STATUS_READY = 1,
@@ -100,6 +102,7 @@ enum : u32
MAX_AUDIO_EVENT_QUEUES = 64,
AUDIO_BLOCK_SIZE_2CH = 2 * AUDIO_BUFFER_SAMPLES,
AUDIO_BLOCK_SIZE_6CH = 6 * AUDIO_BUFFER_SAMPLES,
AUDIO_BLOCK_SIZE_8CH = 8 * AUDIO_BUFFER_SAMPLES,
PORT_BUFFER_TAG_COUNT = 6,
@@ -108,6 +111,10 @@ enum : u32
PORT_BUFFER_TAG_DELTA_2CH = PORT_BUFFER_TAG_LAST_2CH / (PORT_BUFFER_TAG_COUNT - 1),
PORT_BUFFER_TAG_FIRST_2CH = PORT_BUFFER_TAG_LAST_2CH % (PORT_BUFFER_TAG_COUNT - 1),
PORT_BUFFER_TAG_LAST_6CH = AUDIO_BLOCK_SIZE_6CH - 1,
PORT_BUFFER_TAG_DELTA_6CH = PORT_BUFFER_TAG_LAST_6CH / (PORT_BUFFER_TAG_COUNT - 1),
PORT_BUFFER_TAG_FIRST_6CH = PORT_BUFFER_TAG_LAST_6CH % (PORT_BUFFER_TAG_COUNT - 1),
PORT_BUFFER_TAG_LAST_8CH = AUDIO_BLOCK_SIZE_8CH - 1,
PORT_BUFFER_TAG_DELTA_8CH = PORT_BUFFER_TAG_LAST_8CH / (PORT_BUFFER_TAG_COUNT - 1),
PORT_BUFFER_TAG_FIRST_8CH = PORT_BUFFER_TAG_LAST_8CH % (PORT_BUFFER_TAG_COUNT - 1),
@@ -182,49 +189,59 @@ struct audio_port
struct cell_audio_config
{
const std::shared_ptr<AudioBackend> backend = Emu.GetCallbacks().get_audio();
struct raw_config
{
bool buffering_enabled = false;
s64 desired_buffer_duration = 0;
bool enable_time_stretching = false;
s64 time_stretching_threshold = 0;
bool convert_to_u16 = false;
u32 start_threshold = 0;
u32 sampling_period_multiplier = 0;
audio_downmix downmix = audio_downmix::downmix_to_stereo;
audio_renderer renderer = audio_renderer::null;
} raw;
const u32 audio_channels = AudioBackend::get_channels();
const u32 audio_sampling_rate = AudioBackend::get_sampling_rate();
const u32 audio_block_period = AUDIO_BUFFER_SAMPLES * 1000000 / audio_sampling_rate;
std::shared_ptr<AudioBackend> backend = nullptr;
const u32 audio_buffer_length = AUDIO_BUFFER_SAMPLES * audio_channels;
const u32 audio_buffer_size = audio_buffer_length * AudioBackend::get_sample_size();
u32 audio_channels = 0;
u32 audio_sampling_rate = 0;
u32 audio_block_period = 0;
u32 audio_buffer_length = 0;
u32 audio_buffer_size = 0;
/*
* Buffering
*/
const u64 desired_buffer_duration = g_cfg.audio.desired_buffer_duration * 1000llu;
private:
const bool raw_buffering_enabled = static_cast<bool>(g_cfg.audio.enable_buffering);
public:
u64 desired_buffer_duration = 0;
// We need a non-blocking backend (implementing play/pause/flush) to be able to do buffering correctly
// We also need to be able to query the current playing state
const bool buffering_enabled = raw_buffering_enabled && backend->has_capability(AudioBackend::PLAY_PAUSE_FLUSH | AudioBackend::IS_PLAYING);
bool buffering_enabled = false;
const u64 minimum_block_period = audio_block_period / 2; // the block period will not be dynamically lowered below this value (usecs)
const u64 maximum_block_period = (6 * audio_block_period) / 5; // the block period will not be dynamically increased above this value (usecs)
u64 minimum_block_period = 0; // the block period will not be dynamically lowered below this value (usecs)
u64 maximum_block_period = 0; // the block period will not be dynamically increased above this value (usecs)
const u32 desired_full_buffers = buffering_enabled ? static_cast<u32>(desired_buffer_duration / audio_block_period) + 3 : 2;
const u32 num_allocated_buffers = desired_full_buffers + EXTRA_AUDIO_BUFFERS; // number of ringbuffer buffers
u32 desired_full_buffers = 0;
u32 num_allocated_buffers = 0; // number of ringbuffer buffers
const f32 period_average_alpha = 0.02f; // alpha factor for the m_average_period rolling average
const s64 period_comparison_margin = 250; // when comparing the current period time with the desired period, if it is below this number of usecs we do not wait any longer
const u64 fully_untouched_timeout = 2 * audio_block_period; // timeout if the game has not touched any audio buffer yet
const u64 partially_untouched_timeout = 4 * audio_block_period; // timeout if the game has not touched all audio buffers yet
u64 fully_untouched_timeout = 0; // timeout if the game has not touched any audio buffer yet
u64 partially_untouched_timeout = 0; // timeout if the game has not touched all audio buffers yet
/*
* Time Stretching
*/
private:
const bool raw_time_stretching_enabled = buffering_enabled && g_cfg.audio.enable_time_stretching && (g_cfg.audio.time_stretching_threshold > 0);
public:
// We need to be able to set a dynamic frequency ratio to be able to do time stretching
const bool time_stretching_enabled = raw_time_stretching_enabled && backend->has_capability(AudioBackend::SET_FREQUENCY_RATIO);
const f32 time_stretching_threshold = g_cfg.audio.time_stretching_threshold / 100.0f; // we only apply time stretching below this buffer fill rate (adjusted for average period)
// We need to be able to set a dynamic frequency ratio to be able to do time stretching
bool time_stretching_enabled = false;
f32 time_stretching_threshold = 0.0f; // we only apply time stretching below this buffer fill rate (adjusted for average period)
const f32 time_stretching_step = 0.1f; // will only reduce/increase the frequency ratio in steps of at least this value
const f32 time_stretching_scale = 0.9f;
@@ -232,6 +249,11 @@ public:
* Constructor
*/
cell_audio_config();
/*
* Config changes
*/
void reset();
};
class audio_ringbuffer
@@ -285,10 +307,7 @@ public:
return buffer[num].get();
}
u64 get_timestamp() const
{
return get_system_time() - Emu.GetPauseTime();
}
u64 get_timestamp() const;
float* get_current_buffer() const
{
@@ -332,12 +351,13 @@ public:
class cell_audio_thread
{
private:
std::unique_ptr<audio_ringbuffer> ringbuffer;
void reset_ports(s32 offset = 0);
void advance(u64 timestamp, bool reset = true);
std::tuple<u32, u32, u32, u32> count_port_buffer_tags();
template <bool DownmixToStereo>
template <audio_downmix downmix>
void mix(float *out_buffer, s32 offset = 0);
void finish_port_volume_stepping();
@@ -346,8 +366,11 @@ class cell_audio_thread
return (time_left > 350) ? time_left - 250 : 100;
}
void update_config();
public:
cell_audio_config cfg;
atomic_t<bool> m_update_configuration = false;
shared_mutex mutex;
atomic_t<u32> init = 0;
@@ -370,7 +393,7 @@ public:
u64 m_counter = 0;
u64 m_start_time = 0;
u64 m_dynamic_period = 0;
f32 m_average_playtime;
f32 m_average_playtime = 0.0f;
void operator()();
@@ -400,3 +423,9 @@ public:
};
using cell_audio = named_thread<cell_audio_thread>;
namespace audio
{
cell_audio_config::raw_config get_raw_config();
void configure_audio();
}
+3
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "cellCamera.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_event.h"
#include "Emu/IdManager.h"
@@ -26,7 +27,9 @@ void fmt_class_string<CellCameraError>::format(std::string& out, u64 arg)
STR_CASE(CELL_CAMERA_ERROR_RESOLUTION_UNKNOWN);
STR_CASE(CELL_CAMERA_ERROR_BAD_FRAMERATE);
STR_CASE(CELL_CAMERA_ERROR_TIMEOUT);
STR_CASE(CELL_CAMERA_ERROR_BUSY);
STR_CASE(CELL_CAMERA_ERROR_FATAL);
STR_CASE(CELL_CAMERA_ERROR_MUTEX);
}
return unknown;
+36 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Utilities/Timer.h"
#include "Emu/Cell/lv2/sys_memory.h"
@@ -22,7 +22,9 @@ enum CellCameraError : u32
CELL_CAMERA_ERROR_RESOLUTION_UNKNOWN = 0x8014080b,
CELL_CAMERA_ERROR_BAD_FRAMERATE = 0x8014080c,
CELL_CAMERA_ERROR_TIMEOUT = 0x8014080d,
CELL_CAMERA_ERROR_BUSY = 0x8014080e,
CELL_CAMERA_ERROR_FATAL = 0x8014080f,
CELL_CAMERA_ERROR_MUTEX = 0x80140810,
};
// Event masks
@@ -322,6 +324,39 @@ enum
GET_DEF = 0x87,
};
enum // version
{
CELL_CAMERA_INFO_VER_100 = 0x0100,
CELL_CAMERA_INFO_VER_101 = 0x0101,
CELL_CAMERA_INFO_VER_200 = 0x0200,
CELL_CAMERA_INFO_VER = CELL_CAMERA_INFO_VER_200,
CELL_CAMERA_READ_VER_100 = 0x0100,
CELL_CAMERA_READ_VER = CELL_CAMERA_READ_VER_100,
};
// Other
enum
{
CELL_CAMERA_MAX_CAMERAS = 1
};
struct CellCameraInfo
{
// filled in by application as inputs for open
be_t<s32> format;
be_t<s32> resolution;
be_t<s32> framerate;
// filled in by open
vm::bptr<u8> buffer;
be_t<s32> bytesize;
be_t<s32> width;
be_t<s32> height;
be_t<s32> dev_num;
be_t<s32> guid;
};
struct CellCameraInfoEx
{
be_t<s32> format; // CellCameraFormat
+39 -18
View File
@@ -1,22 +1,43 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "cellDaisy.h"
LOG_CHANNEL(cellDaisy);
template <>
void fmt_class_string<CellDaisyError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](CellDaisyError value)
{
switch (value)
{
STR_CASE(CELL_DAISY_ERROR_NO_BEGIN);
STR_CASE(CELL_DAISY_ERROR_INVALID_PORT_ATTACH);
STR_CASE(CELL_DAISY_ERROR_NOT_IMPLEMENTED);
STR_CASE(CELL_DAISY_ERROR_AGAIN);
STR_CASE(CELL_DAISY_ERROR_INVAL);
STR_CASE(CELL_DAISY_ERROR_PERM);
STR_CASE(CELL_DAISY_ERROR_BUSY);
STR_CASE(CELL_DAISY_ERROR_STAT);
}
return unknown;
});
}
using LFQueue2 = struct CellDaisyLFQueue2;
using Lock = struct CellDaisyLock;
using ScatterGatherInterlock = struct CellDaisyScatterGatherInterlock;
using AtomicInterlock = volatile struct CellDaisyAtomicInterlock;
s32 cellDaisyLFQueue2GetPopPointer(vm::ptr<LFQueue2> queue, vm::ptr<s32> pPointer, u32 isBlocking)
error_code cellDaisyLFQueue2GetPopPointer(vm::ptr<LFQueue2> queue, vm::ptr<s32> pPointer, u32 isBlocking)
{
cellDaisy.todo("cellDaisyLFQueue2GetPopPointer()");
return CELL_OK;
}
s32 cellDaisyLFQueue2CompletePopPointer(vm::ptr<LFQueue2> queue, s32 pointer, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal, u32 isQueueFull)
error_code cellDaisyLFQueue2CompletePopPointer(vm::ptr<LFQueue2> queue, s32 pointer, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal, u32 isQueueFull)
{
cellDaisy.todo("cellDaisyLFQueue2CompletePopPointer()");
return CELL_OK;
@@ -27,7 +48,7 @@ void cellDaisyLFQueue2PushOpen(vm::ptr<LFQueue2> queue)
cellDaisy.todo("cellDaisyLFQueue2PushOpen()");
}
s32 cellDaisyLFQueue2PushClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
error_code cellDaisyLFQueue2PushClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
{
cellDaisy.todo("cellDaisyLFQueue2PushClose()");
return CELL_OK;
@@ -38,73 +59,73 @@ void cellDaisyLFQueue2PopOpen(vm::ptr<LFQueue2> queue)
cellDaisy.todo("cellDaisyLFQueue2PopOpen()");
}
s32 cellDaisyLFQueue2PopClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
error_code cellDaisyLFQueue2PopClose(vm::ptr<LFQueue2> queue, vm::ptr<s32(vm::ptr<void>, u32)> fpSendSignal)
{
cellDaisy.todo("cellDaisyLFQueue2PopClose()");
return CELL_OK;
}
s32 cellDaisyLFQueue2HasUnfinishedConsumer(vm::ptr<LFQueue2> queue, u32 isCancelled)
error_code cellDaisyLFQueue2HasUnfinishedConsumer(vm::ptr<LFQueue2> queue, u32 isCancelled)
{
cellDaisy.todo("cellDaisyLFQueue2HasUnfinishedConsumer()");
return CELL_OK;
}
s32 cellDaisy_snprintf(vm::ptr<char> buffer, u32 count, vm::cptr<char> fmt, ppu_va_args_t fmt_args)
error_code cellDaisy_snprintf(vm::ptr<char> buffer, u32 count, vm::cptr<char> fmt, ppu_va_args_t fmt_args)
{
cellDaisy.todo("cellDaisy_snprintf()");
return CELL_OK;
}
s32 cellDaisyLock_initialize(vm::ptr<Lock> _this, u32 depth)
error_code cellDaisyLock_initialize(vm::ptr<Lock> _this, u32 depth)
{
cellDaisy.todo("cellDaisyLock_initialize()");
return CELL_OK;
}
s32 cellDaisyLock_getNextHeadPointer(vm::ptr<Lock> _this)
error_code cellDaisyLock_getNextHeadPointer(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_getNextHeadPointer()");
return CELL_OK;
}
s32 cellDaisyLock_getNextTailPointer(vm::ptr<Lock> _this)
error_code cellDaisyLock_getNextTailPointer(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_getNextTailPointer()");
return CELL_OK;
}
s32 cellDaisyLock_completeConsume(vm::ptr<Lock> _this, u32 pointer)
error_code cellDaisyLock_completeConsume(vm::ptr<Lock> _this, u32 pointer)
{
cellDaisy.todo("cellDaisyLock_completeConsume()");
return CELL_OK;
}
s32 cellDaisyLock_completeProduce(vm::ptr<Lock> _this, u32 pointer)
error_code cellDaisyLock_completeProduce(vm::ptr<Lock> _this, u32 pointer)
{
cellDaisy.todo("cellDaisyLock_completeProduce()");
return CELL_OK;
}
s32 cellDaisyLock_pushOpen(vm::ptr<Lock> _this)
error_code cellDaisyLock_pushOpen(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_pushOpen()");
return CELL_OK;
}
s32 cellDaisyLock_pushClose(vm::ptr<Lock> _this)
error_code cellDaisyLock_pushClose(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_pushClose()");
return CELL_OK;
}
s32 cellDaisyLock_popOpen(vm::ptr<Lock> _this)
error_code cellDaisyLock_popOpen(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_popOpen()");
return CELL_OK;
}
s32 cellDaisyLock_popClose(vm::ptr<Lock> _this)
error_code cellDaisyLock_popClose(vm::ptr<Lock> _this)
{
cellDaisy.todo("cellDaisyLock_popClose()");
return CELL_OK;
@@ -125,13 +146,13 @@ void cellDaisyScatterGatherInterlock_9tor(vm::ptr<ScatterGatherInterlock> _this)
cellDaisy.todo("cellDaisyScatterGatherInterlock_9tor()");
}
s32 cellDaisyScatterGatherInterlock_probe(vm::ptr<ScatterGatherInterlock> _this, u32 isBlocking)
error_code cellDaisyScatterGatherInterlock_probe(vm::ptr<ScatterGatherInterlock> _this, u32 isBlocking)
{
cellDaisy.todo("cellDaisyScatterGatherInterlock_probe()");
return CELL_OK;
}
s32 cellDaisyScatterGatherInterlock_release(vm::ptr<ScatterGatherInterlock> _this)
error_code cellDaisyScatterGatherInterlock_release(vm::ptr<ScatterGatherInterlock> _this)
{
cellDaisy.todo("cellDaisyScatterGatherInterlock_release()");
return CELL_OK;
+2 -2
View File
@@ -1,11 +1,11 @@
#pragma once
#pragma once
// libDaisy = 0x80410501 - 0x804105ff
// Error codes
enum
enum CellDaisyError : u32
{
CELL_DAISY_ERROR_NO_BEGIN = 0x80410501,
CELL_DAISY_ERROR_INVALID_PORT_ATTACH = 0x80410502,
+40 -21
View File
@@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_sync.h"
@@ -10,6 +11,24 @@
LOG_CHANNEL(cellDmux);
template <>
void fmt_class_string<CellDmuxError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](CellDmuxError value)
{
switch (value)
{
STR_CASE(CELL_DMUX_ERROR_ARG);
STR_CASE(CELL_DMUX_ERROR_SEQ);
STR_CASE(CELL_DMUX_ERROR_BUSY);
STR_CASE(CELL_DMUX_ERROR_EMPTY);
STR_CASE(CELL_DMUX_ERROR_FATAL);
}
return unknown;
});
}
/* Demuxer Thread Classes */
enum
@@ -940,7 +959,7 @@ void dmuxQueryEsAttr(u32 info /* may be 0 */, vm::cptr<CellCodecEsFilterId> esFi
cellDmux.warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2);
}
s32 cellDmuxQueryAttr(vm::cptr<CellDmuxType> type, vm::ptr<CellDmuxAttr> attr)
error_code cellDmuxQueryAttr(vm::cptr<CellDmuxType> type, vm::ptr<CellDmuxAttr> attr)
{
cellDmux.warning("cellDmuxQueryAttr(type=*0x%x, attr=*0x%x)", type, attr);
@@ -953,7 +972,7 @@ s32 cellDmuxQueryAttr(vm::cptr<CellDmuxType> type, vm::ptr<CellDmuxAttr> attr)
return CELL_OK;
}
s32 cellDmuxQueryAttr2(vm::cptr<CellDmuxType2> type2, vm::ptr<CellDmuxAttr> attr)
error_code cellDmuxQueryAttr2(vm::cptr<CellDmuxType2> type2, vm::ptr<CellDmuxAttr> attr)
{
cellDmux.warning("cellDmuxQueryAttr2(demuxerType2=*0x%x, demuxerAttr=*0x%x)", type2, attr);
@@ -966,7 +985,7 @@ s32 cellDmuxQueryAttr2(vm::cptr<CellDmuxType2> type2, vm::ptr<CellDmuxAttr> attr
return CELL_OK;
}
s32 cellDmuxOpen(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResource> res, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
error_code cellDmuxOpen(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResource> res, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
{
cellDmux.warning("cellDmuxOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
@@ -979,7 +998,7 @@ s32 cellDmuxOpen(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResource> res, vm
fmt::throw_exception("cellDmux disabled, use LLE.");
}
s32 cellDmuxOpenEx(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> resEx, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
error_code cellDmuxOpenEx(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> resEx, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
{
cellDmux.warning("cellDmuxOpenEx(type=*0x%x, resEx=*0x%x, cb=*0x%x, handle=*0x%x)", type, resEx, cb, handle);
@@ -992,14 +1011,14 @@ s32 cellDmuxOpenEx(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> res
fmt::throw_exception("cellDmux disabled, use LLE.");
}
s32 cellDmuxOpenExt(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> resEx, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
error_code cellDmuxOpenExt(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> resEx, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
{
cellDmux.warning("cellDmuxOpenExt(type=*0x%x, resEx=*0x%x, cb=*0x%x, handle=*0x%x)", type, resEx, cb, handle);
return cellDmuxOpenEx(type, resEx, cb, handle);
}
s32 cellDmuxOpen2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellDmuxResource2> res2, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
error_code cellDmuxOpen2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellDmuxResource2> res2, vm::cptr<CellDmuxCb> cb, vm::ptr<u32> handle)
{
cellDmux.warning("cellDmuxOpen2(type2=*0x%x, res2=*0x%x, cb=*0x%x, handle=*0x%x)", type2, res2, cb, handle);
@@ -1012,7 +1031,7 @@ s32 cellDmuxOpen2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellDmuxResource2> res
fmt::throw_exception("cellDmux disabled, use LLE.");
}
s32 cellDmuxClose(u32 handle)
error_code cellDmuxClose(u32 handle)
{
cellDmux.warning("cellDmuxClose(handle=0x%x)", handle);
@@ -1041,7 +1060,7 @@ s32 cellDmuxClose(u32 handle)
return CELL_OK;
}
s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, b8 discontinuity, u64 userData)
error_code cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, b8 discontinuity, u64 userData)
{
cellDmux.trace("cellDmuxSetStream(handle=0x%x, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx)", handle, streamAddress, streamSize, discontinuity, userData);
@@ -1069,7 +1088,7 @@ s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, b8 disconti
return CELL_OK;
}
s32 cellDmuxResetStream(u32 handle)
error_code cellDmuxResetStream(u32 handle)
{
cellDmux.warning("cellDmuxResetStream(handle=0x%x)", handle);
@@ -1084,7 +1103,7 @@ s32 cellDmuxResetStream(u32 handle)
return CELL_OK;
}
s32 cellDmuxResetStreamAndWaitDone(u32 handle)
error_code cellDmuxResetStreamAndWaitDone(u32 handle)
{
cellDmux.warning("cellDmuxResetStreamAndWaitDone(handle=0x%x)", handle);
@@ -1117,7 +1136,7 @@ s32 cellDmuxResetStreamAndWaitDone(u32 handle)
return CELL_OK;
}
s32 cellDmuxQueryEsAttr(vm::cptr<CellDmuxType> type, vm::cptr<CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
error_code cellDmuxQueryEsAttr(vm::cptr<CellDmuxType> type, vm::cptr<CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
{
cellDmux.warning("cellDmuxQueryEsAttr(demuxerType=*0x%x, esFilterId=*0x%x, esSpecificInfo=*0x%x, esAttr=*0x%x)", type, esFilterId, esSpecificInfo, esAttr);
@@ -1131,7 +1150,7 @@ s32 cellDmuxQueryEsAttr(vm::cptr<CellDmuxType> type, vm::cptr<CellCodecEsFilterI
return CELL_OK;
}
s32 cellDmuxQueryEsAttr2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
error_code cellDmuxQueryEsAttr2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
{
cellDmux.warning("cellDmuxQueryEsAttr2(type2=*0x%x, esFilterId=*0x%x, esSpecificInfo=*0x%x, esAttr=*0x%x)", type2, esFilterId, esSpecificInfo, esAttr);
@@ -1145,7 +1164,7 @@ s32 cellDmuxQueryEsAttr2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellCodecEsFilt
return CELL_OK;
}
s32 cellDmuxEnableEs(u32 handle, vm::cptr<CellCodecEsFilterId> esFilterId, vm::cptr<CellDmuxEsResource> esResourceInfo, vm::cptr<CellDmuxEsCb> esCb, u32 esSpecificInfo, vm::ptr<u32> esHandle)
error_code cellDmuxEnableEs(u32 handle, vm::cptr<CellCodecEsFilterId> esFilterId, vm::cptr<CellDmuxEsResource> esResourceInfo, vm::cptr<CellDmuxEsCb> esCb, u32 esSpecificInfo, vm::ptr<u32> esHandle)
{
cellDmux.warning("cellDmuxEnableEs(handle=0x%x, esFilterId=*0x%x, esResourceInfo=*0x%x, esCb=*0x%x, esSpecificInfo=*0x%x, esHandle=*0x%x)", handle, esFilterId, esResourceInfo, esCb, esSpecificInfo, esHandle);
@@ -1175,7 +1194,7 @@ s32 cellDmuxEnableEs(u32 handle, vm::cptr<CellCodecEsFilterId> esFilterId, vm::c
return CELL_OK;
}
s32 cellDmuxDisableEs(u32 esHandle)
error_code cellDmuxDisableEs(u32 esHandle)
{
cellDmux.warning("cellDmuxDisableEs(esHandle=0x%x)", esHandle);
@@ -1194,7 +1213,7 @@ s32 cellDmuxDisableEs(u32 esHandle)
return CELL_OK;
}
s32 cellDmuxResetEs(u32 esHandle)
error_code cellDmuxResetEs(u32 esHandle)
{
cellDmux.trace("cellDmuxResetEs(esHandle=0x%x)", esHandle);
@@ -1213,7 +1232,7 @@ s32 cellDmuxResetEs(u32 esHandle)
return CELL_OK;
}
s32 cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
error_code cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
{
cellDmux.trace("cellDmuxGetAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo);
@@ -1236,7 +1255,7 @@ s32 cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo
return CELL_OK;
}
s32 cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
error_code cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
{
cellDmux.trace("cellDmuxPeekAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo);
@@ -1259,7 +1278,7 @@ s32 cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInf
return CELL_OK;
}
s32 cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
error_code cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
{
cellDmux.trace("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo);
@@ -1282,7 +1301,7 @@ s32 cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecific
return CELL_OK;
}
s32 cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
error_code cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
{
cellDmux.trace("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo);
@@ -1305,7 +1324,7 @@ s32 cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecifi
return CELL_OK;
}
s32 cellDmuxReleaseAu(u32 esHandle)
error_code cellDmuxReleaseAu(u32 esHandle)
{
cellDmux.trace("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
@@ -1323,7 +1342,7 @@ s32 cellDmuxReleaseAu(u32 esHandle)
return CELL_OK;
}
s32 cellDmuxFlushEs(u32 esHandle)
error_code cellDmuxFlushEs(u32 esHandle)
{
cellDmux.warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
+2 -2
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include "Emu/Memory/vm_ptr.h"
// Error Codes
enum
enum CellDmuxError :u32
{
CELL_DMUX_ERROR_ARG = 0x80610201,
CELL_DMUX_ERROR_SEQ = 0x80610202,
+14 -14
View File
@@ -1,81 +1,81 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellDtcpIpUtility);
s32 cellDtcpIpRead()
error_code cellDtcpIpRead()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpFinalize()
error_code cellDtcpIpFinalize()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpActivate()
error_code cellDtcpIpActivate()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpOpen()
error_code cellDtcpIpOpen()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpCheckActivation()
error_code cellDtcpIpCheckActivation()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpInitialize()
error_code cellDtcpIpInitialize()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpGetDecryptedData()
error_code cellDtcpIpGetDecryptedData()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpStopSequence()
error_code cellDtcpIpStopSequence()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpSeek()
error_code cellDtcpIpSeek()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpStartSequence()
error_code cellDtcpIpStartSequence()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpSetEncryptedData()
error_code cellDtcpIpSetEncryptedData()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpClose()
error_code cellDtcpIpClose()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
}
s32 cellDtcpIpSuspendActivationForDebug()
error_code cellDtcpIpSuspendActivationForDebug()
{
UNIMPLEMENTED_FUNC(cellDtcpIpUtility);
return CELL_OK;
+123 -86
View File
@@ -8,8 +8,46 @@
LOG_CHANNEL(cellFont);
template <>
void fmt_class_string<CellFontError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(CELL_FONT_ERROR_FATAL);
STR_CASE(CELL_FONT_ERROR_INVALID_PARAMETER);
STR_CASE(CELL_FONT_ERROR_UNINITIALIZED);
STR_CASE(CELL_FONT_ERROR_INITIALIZE_FAILED);
STR_CASE(CELL_FONT_ERROR_INVALID_CACHE_BUFFER);
STR_CASE(CELL_FONT_ERROR_ALREADY_INITIALIZED);
STR_CASE(CELL_FONT_ERROR_ALLOCATION_FAILED);
STR_CASE(CELL_FONT_ERROR_NO_SUPPORT_FONTSET);
STR_CASE(CELL_FONT_ERROR_OPEN_FAILED);
STR_CASE(CELL_FONT_ERROR_READ_FAILED);
STR_CASE(CELL_FONT_ERROR_FONT_OPEN_FAILED);
STR_CASE(CELL_FONT_ERROR_FONT_NOT_FOUND);
STR_CASE(CELL_FONT_ERROR_FONT_OPEN_MAX);
STR_CASE(CELL_FONT_ERROR_FONT_CLOSE_FAILED);
STR_CASE(CELL_FONT_ERROR_ALREADY_OPENED);
STR_CASE(CELL_FONT_ERROR_NO_SUPPORT_FUNCTION);
STR_CASE(CELL_FONT_ERROR_NO_SUPPORT_CODE);
STR_CASE(CELL_FONT_ERROR_NO_SUPPORT_GLYPH);
STR_CASE(CELL_FONT_ERROR_BUFFER_SIZE_NOT_ENOUGH);
STR_CASE(CELL_FONT_ERROR_RENDERER_ALREADY_BIND);
STR_CASE(CELL_FONT_ERROR_RENDERER_UNBIND);
STR_CASE(CELL_FONT_ERROR_RENDERER_INVALID);
STR_CASE(CELL_FONT_ERROR_RENDERER_ALLOCATION_FAILED);
STR_CASE(CELL_FONT_ERROR_ENOUGH_RENDERING_BUFFER);
STR_CASE(CELL_FONT_ERROR_NO_SUPPORT_SURFACE);
}
return unknown;
});
}
// Functions
s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> config)
error_code cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> config)
{
cellFont.warning("cellFontInitializeWithRevision(revisionFlags=0x%llx, config=*0x%x)", revisionFlags, config);
@@ -26,26 +64,26 @@ s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> co
return CELL_OK;
}
s32 cellFontGetRevisionFlags(vm::ptr<u64> revisionFlags)
error_code cellFontGetRevisionFlags(vm::ptr<u64> revisionFlags)
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontEnd()
error_code cellFontEnd()
{
cellFont.warning("cellFontEnd()");
return CELL_OK;
}
s32 cellFontSetFontsetOpenMode(u32 openMode)
error_code cellFontSetFontsetOpenMode(u32 openMode)
{
cellFont.todo("cellFontSetFontsetOpenMode(openMode=0x%x)", openMode);
return CELL_OK;
}
s32 cellFontOpenFontMemory(vm::ptr<CellFontLibrary> library, u32 fontAddr, u32 fontSize, u32 subNum, u32 uniqueId, vm::ptr<CellFont> font)
error_code cellFontOpenFontMemory(vm::ptr<CellFontLibrary> library, u32 fontAddr, u32 fontSize, u32 subNum, u32 uniqueId, vm::ptr<CellFont> font)
{
cellFont.warning("cellFontOpenFontMemory(library=*0x%x, fontAddr=0x%x, fontSize=%d, subNum=%d, uniqueId=%d, font=*0x%x)", library, fontAddr, fontSize, subNum, uniqueId, font);
@@ -61,7 +99,7 @@ s32 cellFontOpenFontMemory(vm::ptr<CellFontLibrary> library, u32 fontAddr, u32 f
return CELL_OK;
}
s32 cellFontOpenFontFile(vm::ptr<CellFontLibrary> library, vm::cptr<char> fontPath, u32 subNum, s32 uniqueId, vm::ptr<CellFont> font)
error_code cellFontOpenFontFile(vm::ptr<CellFontLibrary> library, vm::cptr<char> fontPath, u32 subNum, s32 uniqueId, vm::ptr<CellFont> font)
{
cellFont.warning("cellFontOpenFontFile(library=*0x%x, fontPath=%s, subNum=%d, uniqueId=%d, font=*0x%x)", library, fontPath, subNum, uniqueId, font);
@@ -80,7 +118,7 @@ s32 cellFontOpenFontFile(vm::ptr<CellFontLibrary> library, vm::cptr<char> fontPa
return ret;
}
s32 cellFontOpenFontset(ppu_thread& ppu, vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
error_code cellFontOpenFontset(ppu_thread& ppu, vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
{
cellFont.warning("cellFontOpenFontset(library=*0x%x, fontType=*0x%x, font=*0x%x)", library, fontType, font);
@@ -151,17 +189,16 @@ s32 cellFontOpenFontset(ppu_thread& ppu, vm::ptr<CellFontLibrary> library, vm::p
break;
default:
cellFont.warning("cellFontOpenFontset: fontType->type = %d not supported.", fontType->type);
return CELL_FONT_ERROR_NO_SUPPORT_FONTSET;
return { CELL_FONT_ERROR_NO_SUPPORT_FONTSET, fontType->type };
}
s32 ret = cellFontOpenFontFile(library, vm::make_str(file), 0, 0, font); //TODO: Find the correct values of subNum, uniqueId
error_code ret = cellFontOpenFontFile(library, vm::make_str(file), 0, 0, font); //TODO: Find the correct values of subNum, uniqueId
font->origin = CELL_FONT_OPEN_FONTSET;
return ret;
}
s32 cellFontOpenFontInstance(vm::ptr<CellFont> openedFont, vm::ptr<CellFont> font)
error_code cellFontOpenFontInstance(vm::ptr<CellFont> openedFont, vm::ptr<CellFont> font)
{
cellFont.warning("cellFontOpenFontInstance(openedFont=*0x%x, font=*0x%x)", openedFont, font);
@@ -175,17 +212,17 @@ s32 cellFontOpenFontInstance(vm::ptr<CellFont> openedFont, vm::ptr<CellFont> fon
return CELL_OK;
}
s32 cellFontSetFontOpenMode(u32 openMode)
error_code cellFontSetFontOpenMode(u32 openMode)
{
cellFont.todo("cellFontSetFontOpenMode(openMode=0x%x)", openMode);
return CELL_OK;
}
s32 cellFontCreateRenderer(vm::ptr<CellFontLibrary> library, vm::ptr<CellFontRendererConfig> config, vm::ptr<CellFontRenderer> Renderer)
error_code cellFontCreateRenderer(vm::ptr<CellFontLibrary> library, vm::ptr<CellFontRendererConfig> config, vm::ptr<CellFontRenderer> Renderer)
{
cellFont.todo("cellFontCreateRenderer(library=*0x%x, config=*0x%x, Renderer=*0x%x)", library, config, Renderer);
//Write data in Renderer
// Write data in Renderer
return CELL_OK;
}
@@ -211,7 +248,7 @@ void cellFontRenderSurfaceSetScissor(vm::ptr<CellFontRenderSurface> surface, s32
surface->sc_y1 = h;
}
s32 cellFontSetScalePixel(vm::ptr<CellFont> font, float w, float h)
error_code cellFontSetScalePixel(vm::ptr<CellFont> font, float w, float h)
{
cellFont.trace("cellFontSetScalePixel(font=*0x%x, w=%f, h=%f)", font, w, h);
@@ -221,7 +258,7 @@ s32 cellFontSetScalePixel(vm::ptr<CellFont> font, float w, float h)
return CELL_OK;
}
s32 cellFontGetHorizontalLayout(vm::ptr<CellFont> font, vm::ptr<CellFontHorizontalLayout> layout)
error_code cellFontGetHorizontalLayout(vm::ptr<CellFont> font, vm::ptr<CellFontHorizontalLayout> layout)
{
cellFont.trace("cellFontGetHorizontalLayout(font=*0x%x, layout=*0x%x)", font, layout);
@@ -236,7 +273,7 @@ s32 cellFontGetHorizontalLayout(vm::ptr<CellFont> font, vm::ptr<CellFontHorizont
return CELL_OK;
}
s32 cellFontBindRenderer(vm::ptr<CellFont> font, vm::ptr<CellFontRenderer> renderer)
error_code cellFontBindRenderer(vm::ptr<CellFont> font, vm::ptr<CellFontRenderer> renderer)
{
cellFont.warning("cellFontBindRenderer(font=*0x%x, renderer=*0x%x)", font, renderer);
@@ -250,7 +287,7 @@ s32 cellFontBindRenderer(vm::ptr<CellFont> font, vm::ptr<CellFontRenderer> rende
return CELL_OK;
}
s32 cellFontUnbindRenderer(vm::ptr<CellFont> font)
error_code cellFontUnbindRenderer(vm::ptr<CellFont> font)
{
cellFont.warning("cellFontBindRenderer(font=*0x%x)", font);
@@ -264,13 +301,13 @@ s32 cellFontUnbindRenderer(vm::ptr<CellFont> font)
return CELL_OK;
}
s32 cellFontDestroyRenderer()
error_code cellFontDestroyRenderer()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetupRenderScalePixel(vm::ptr<CellFont> font, float w, float h)
error_code cellFontSetupRenderScalePixel(vm::ptr<CellFont> font, float w, float h)
{
cellFont.todo("cellFontSetupRenderScalePixel(font=*0x%x, w=%f, h=%f)", font, w, h);
@@ -283,7 +320,7 @@ s32 cellFontSetupRenderScalePixel(vm::ptr<CellFont> font, float w, float h)
return CELL_OK;
}
s32 cellFontGetRenderCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontGlyphMetrics> metrics)
error_code cellFontGetRenderCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontGlyphMetrics> metrics)
{
cellFont.todo("cellFontGetRenderCharGlyphMetrics(font=*0x%x, code=0x%x, metrics=*0x%x)", font, code, metrics);
@@ -296,7 +333,7 @@ s32 cellFontGetRenderCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<
return CELL_OK;
}
s32 cellFontRenderCharGlyphImage(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontRenderSurface> surface, float x, float y, vm::ptr<CellFontGlyphMetrics> metrics, vm::ptr<CellFontImageTransInfo> transInfo)
error_code cellFontRenderCharGlyphImage(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontRenderSurface> surface, float x, float y, vm::ptr<CellFontGlyphMetrics> metrics, vm::ptr<CellFontImageTransInfo> transInfo)
{
cellFont.notice("cellFontRenderCharGlyphImage(font=*0x%x, code=0x%x, surface=*0x%x, x=%f, y=%f, metrics=*0x%x, trans=*0x%x)", font, code, surface, x, y, metrics, transInfo);
@@ -341,13 +378,13 @@ s32 cellFontRenderCharGlyphImage(vm::ptr<CellFont> font, u32 code, vm::ptr<CellF
return CELL_OK;
}
s32 cellFontEndLibrary()
error_code cellFontEndLibrary()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetEffectSlant(vm::ptr<CellFont> font, float slantParam)
error_code cellFontSetEffectSlant(vm::ptr<CellFont> font, float slantParam)
{
cellFont.trace("cellFontSetEffectSlant(font=*0x%x, slantParam=%f)", font, slantParam);
@@ -361,7 +398,7 @@ s32 cellFontSetEffectSlant(vm::ptr<CellFont> font, float slantParam)
return CELL_OK;
}
s32 cellFontGetEffectSlant(vm::ptr<CellFont> font, vm::ptr<float> slantParam)
error_code cellFontGetEffectSlant(vm::ptr<CellFont> font, vm::ptr<float> slantParam)
{
cellFont.warning("cellFontSetEffectSlant(font=*0x%x, slantParam=*0x%x)", font, slantParam);
@@ -370,7 +407,7 @@ s32 cellFontGetEffectSlant(vm::ptr<CellFont> font, vm::ptr<float> slantParam)
return CELL_OK;
}
s32 cellFontGetFontIdCode(vm::ptr<CellFont> font, u32 code, vm::ptr<u32> fontId, vm::ptr<u32> fontCode)
error_code cellFontGetFontIdCode(vm::ptr<CellFont> font, u32 code, vm::ptr<u32> fontId, vm::ptr<u32> fontCode)
{
cellFont.todo("cellFontGetFontIdCode(font=*0x%x, code=%d, fontId=*0x%x, fontCode=*0x%x)", font, code, fontId, fontCode);
@@ -378,7 +415,7 @@ s32 cellFontGetFontIdCode(vm::ptr<CellFont> font, u32 code, vm::ptr<u32> fontId,
return CELL_OK;
}
s32 cellFontCloseFont(vm::ptr<CellFont> font)
error_code cellFontCloseFont(vm::ptr<CellFont> font)
{
cellFont.warning("cellFontCloseFont(font=*0x%x)", font);
@@ -392,7 +429,7 @@ s32 cellFontCloseFont(vm::ptr<CellFont> font)
return CELL_OK;
}
s32 cellFontGetCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontGlyphMetrics> metrics)
error_code cellFontGetCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontGlyphMetrics> metrics)
{
cellFont.warning("cellFontGetCharGlyphMetrics(font=*0x%x, code=0x%x, metrics=*0x%x)", font, code, metrics);
@@ -415,13 +452,13 @@ s32 cellFontGetCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFo
return CELL_OK;
}
s32 cellFontGraphicsSetFontRGBA()
error_code cellFontGraphicsSetFontRGBA()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontOpenFontsetOnMemory(ppu_thread& ppu, vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
error_code cellFontOpenFontsetOnMemory(ppu_thread& ppu, vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
{
cellFont.todo("cellFontOpenFontsetOnMemory(library=*0x%x, fontType=*0x%x, font=*0x%x)", library, fontType, font);
@@ -433,109 +470,109 @@ s32 cellFontOpenFontsetOnMemory(ppu_thread& ppu, vm::ptr<CellFontLibrary> librar
return CELL_OK;
}
s32 cellFontGraphicsSetScalePixel()
error_code cellFontGraphicsSetScalePixel()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGraphicsGetScalePixel()
error_code cellFontGraphicsGetScalePixel()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetEffectWeight()
error_code cellFontSetEffectWeight()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGlyphSetupVertexesGlyph()
error_code cellFontGlyphSetupVertexesGlyph()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGetVerticalLayout()
error_code cellFontGetVerticalLayout()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGetRenderCharGlyphMetricsVertical()
error_code cellFontGetRenderCharGlyphMetricsVertical()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetScalePoint()
error_code cellFontSetScalePoint()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetupRenderEffectSlant()
error_code cellFontSetupRenderEffectSlant()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGraphicsSetLineRGBA()
error_code cellFontGraphicsSetLineRGBA()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGraphicsSetDrawType()
error_code cellFontGraphicsSetDrawType()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontEndGraphics()
error_code cellFontEndGraphics()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGraphicsSetupDrawContext()
error_code cellFontGraphicsSetupDrawContext()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetupRenderEffectWeight()
error_code cellFontSetupRenderEffectWeight()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGlyphGetOutlineControlDistance()
error_code cellFontGlyphGetOutlineControlDistance()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGlyphGetVertexesGlyphSize()
error_code cellFontGlyphGetVertexesGlyphSize()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGenerateCharGlyph()
error_code cellFontGenerateCharGlyph()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontDeleteGlyph()
error_code cellFontDeleteGlyph()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontExtend(u32 a1, u32 a2, u32 a3)
error_code cellFontExtend(u32 a1, u32 a2, u32 a3)
{
cellFont.todo("cellFontExtend(a1=0x%x, a2=0x%x, a3=0x%x)", a1, a2, a3);
//In a test I did: a1=0xcfe00000, a2=0x0, a3=(pointer to something)
@@ -555,229 +592,229 @@ s32 cellFontExtend(u32 a1, u32 a2, u32 a3)
return CELL_OK;
}
s32 cellFontRenderCharGlyphImageVertical()
error_code cellFontRenderCharGlyphImageVertical()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontSetResolutionDpi()
error_code cellFontSetResolutionDpi()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGetCharGlyphMetricsVertical()
error_code cellFontGetCharGlyphMetricsVertical()
{
UNIMPLEMENTED_FUNC(cellFont);
return CELL_OK;
}
s32 cellFontGetRenderEffectWeight()
error_code cellFontGetRenderEffectWeight()
{
cellFont.todo("cellFontGetRenderEffectWeight()");
return CELL_OK;
}
s32 cellFontGraphicsGetDrawType()
error_code cellFontGraphicsGetDrawType()
{
cellFont.todo("cellFontGraphicsGetDrawType()");
return CELL_OK;
}
s32 cellFontGetKerning()
error_code cellFontGetKerning()
{
cellFont.todo("cellFontGetKerning()");
return CELL_OK;
}
s32 cellFontGetRenderScaledKerning()
error_code cellFontGetRenderScaledKerning()
{
cellFont.todo("cellFontGetRenderScaledKerning()");
return CELL_OK;
}
s32 cellFontGetRenderScalePixel()
error_code cellFontGetRenderScalePixel()
{
cellFont.todo("cellFontGetRenderScalePixel()");
return CELL_OK;
}
s32 cellFontGlyphGetScalePixel()
error_code cellFontGlyphGetScalePixel()
{
cellFont.todo("cellFontGlyphGetScalePixel()");
return CELL_OK;
}
s32 cellFontGlyphGetHorizontalShift()
error_code cellFontGlyphGetHorizontalShift()
{
cellFont.todo("cellFontGlyphGetHorizontalShift()");
return CELL_OK;
}
s32 cellFontRenderCharGlyphImageHorizontal()
error_code cellFontRenderCharGlyphImageHorizontal()
{
cellFont.todo("cellFontRenderCharGlyphImageHorizontal()");
return CELL_OK;
}
s32 cellFontGetEffectWeight()
error_code cellFontGetEffectWeight()
{
cellFont.todo("cellFontGetEffectWeight()");
return CELL_OK;
}
s32 cellFontGetScalePixel()
error_code cellFontGetScalePixel()
{
cellFont.todo("cellFontGetScalePixel()");
return CELL_OK;
}
s32 cellFontClearFileCache()
error_code cellFontClearFileCache()
{
cellFont.todo("cellFontClearFileCache()");
return CELL_OK;
}
s32 cellFontAdjustFontScaling()
error_code cellFontAdjustFontScaling()
{
cellFont.todo("cellFontAdjustFontScaling()");
return CELL_OK;
}
s32 cellFontSetupRenderScalePoint()
error_code cellFontSetupRenderScalePoint()
{
cellFont.todo("cellFontSetupRenderScalePoint()");
return CELL_OK;
}
s32 cellFontGlyphGetVerticalShift()
error_code cellFontGlyphGetVerticalShift()
{
cellFont.todo("cellFontGlyphGetVerticalShift()");
return CELL_OK;
}
s32 cellFontGetGlyphExpandBufferInfo()
error_code cellFontGetGlyphExpandBufferInfo()
{
cellFont.todo("cellFontGetGlyphExpandBufferInfo()");
return CELL_OK;
}
s32 cellFontGetLibrary()
error_code cellFontGetLibrary()
{
cellFont.todo("cellFontGetLibrary()");
return CELL_OK;
}
s32 cellFontVertexesGlyphRelocate()
error_code cellFontVertexesGlyphRelocate()
{
cellFont.todo("cellFontVertexesGlyphRelocate()");
return CELL_OK;
}
s32 cellFontGetInitializedRevisionFlags()
error_code cellFontGetInitializedRevisionFlags()
{
cellFont.todo("cellFontGetInitializedRevisionFlags()");
return CELL_OK;
}
s32 cellFontGetResolutionDpi()
error_code cellFontGetResolutionDpi()
{
cellFont.todo("cellFontGetResolutionDpi()");
return CELL_OK;
}
s32 cellFontGlyphRenderImageVertical()
error_code cellFontGlyphRenderImageVertical()
{
cellFont.todo("cellFontGlyphRenderImageVertical()");
return CELL_OK;
}
s32 cellFontGlyphRenderImageHorizontal()
error_code cellFontGlyphRenderImageHorizontal()
{
cellFont.todo("cellFontGlyphRenderImageHorizontal()");
return CELL_OK;
}
s32 cellFontAdjustGlyphExpandBuffer()
error_code cellFontAdjustGlyphExpandBuffer()
{
cellFont.todo("cellFontAdjustGlyphExpandBuffer()");
return CELL_OK;
}
s32 cellFontGetRenderScalePoint()
error_code cellFontGetRenderScalePoint()
{
cellFont.todo("cellFontGetRenderScalePoint()");
return CELL_OK;
}
s32 cellFontGraphicsGetFontRGBA()
error_code cellFontGraphicsGetFontRGBA()
{
cellFont.todo("cellFontGraphicsGetFontRGBA()");
return CELL_OK;
}
s32 cellFontGlyphGetOutlineVertexes()
error_code cellFontGlyphGetOutlineVertexes()
{
cellFont.todo("cellFontGlyphGetOutlineVertexes()");
return CELL_OK;
}
s32 cellFontDelete()
error_code cellFontDelete()
{
cellFont.todo("cellFontDelete()");
return CELL_OK;
}
s32 cellFontPatchWorks()
error_code cellFontPatchWorks()
{
cellFont.todo("cellFontPatchWorks()");
return CELL_OK;
}
s32 cellFontGlyphRenderImage()
error_code cellFontGlyphRenderImage()
{
cellFont.todo("cellFontGlyphRenderImage()");
return CELL_OK;
}
s32 cellFontGetBindingRenderer()
error_code cellFontGetBindingRenderer()
{
cellFont.todo("cellFontGetBindingRenderer()");
return CELL_OK;
}
s32 cellFontGenerateCharGlyphVertical()
error_code cellFontGenerateCharGlyphVertical()
{
cellFont.todo("cellFontGenerateCharGlyphVertical()");
return CELL_OK;
}
s32 cellFontGetRenderEffectSlant()
error_code cellFontGetRenderEffectSlant()
{
cellFont.todo("cellFontGetRenderEffectSlant()");
return CELL_OK;
}
s32 cellFontGetScalePoint()
error_code cellFontGetScalePoint()
{
cellFont.todo("cellFontGetScalePoint()");
return CELL_OK;
}
s32 cellFontGraphicsGetLineRGBA()
error_code cellFontGraphicsGetLineRGBA()
{
cellFont.todo("cellFontGraphicsGetLineRGBA()");
return CELL_OK;
}
s32 cellFontControl()
error_code cellFontControl()
{
cellFont.todo("cellFontControl()");
return CELL_OK;
}
s32 cellFontStatic()
error_code cellFontStatic()
{
cellFont.todo("cellFontStatic()");
return CELL_OK;
+2 -2
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include "Emu/Memory/vm_ptr.h"
// Error codes
enum
enum CellFontError : u32
{
CELL_FONT_ERROR_FATAL = 0x80540001,
CELL_FONT_ERROR_INVALID_PARAMETER = 0x80540002,
+43 -43
View File
@@ -5,13 +5,13 @@
LOG_CHANNEL(cellFontFT);
s32 cellFontInitLibraryFreeType()
error_code cellFontInitLibraryFreeType()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib)
error_code cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib)
{
cellFontFT.warning("cellFontInitLibraryFreeTypeWithRevision(revisionFlags=0x%llx, config=*0x%x, lib=**0x%x)", revisionFlags, config, lib);
@@ -20,247 +20,247 @@ s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontL
return CELL_OK;
}
s32 cellFontFTGetRevisionFlags()
error_code cellFontFTGetRevisionFlags()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 cellFontFTGetInitializedRevisionFlags()
error_code cellFontFTGetInitializedRevisionFlags()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTCacheStream_CacheEnd()
error_code FTCacheStream_CacheEnd()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTCacheStream_CacheInit()
error_code FTCacheStream_CacheInit()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTCacheStream_CalcCacheIndexSize()
error_code FTCacheStream_CalcCacheIndexSize()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTCacheStream_End()
error_code FTCacheStream_End()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTCacheStream_Init()
error_code FTCacheStream_Init()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_Close()
error_code FTFaceH_Close()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_FontFamilyName()
error_code FTFaceH_FontFamilyName()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_FontStyleName()
error_code FTFaceH_FontStyleName()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetAscender()
error_code FTFaceH_GetAscender()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxHeight()
error_code FTFaceH_GetBoundingBoxHeight()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxMaxX()
error_code FTFaceH_GetBoundingBoxMaxX()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxMaxY()
error_code FTFaceH_GetBoundingBoxMaxY()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxMinX()
error_code FTFaceH_GetBoundingBoxMinX()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxMinY()
error_code FTFaceH_GetBoundingBoxMinY()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetBoundingBoxWidth()
error_code FTFaceH_GetBoundingBoxWidth()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetCompositeCodes()
error_code FTFaceH_GetCompositeCodes()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetGlyphImage()
error_code FTFaceH_GetGlyphImage()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetGlyphMetrics()
error_code FTFaceH_GetGlyphMetrics()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetKerning()
error_code FTFaceH_GetKerning()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetMaxHorizontalAdvance()
error_code FTFaceH_GetMaxHorizontalAdvance()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetMaxVerticalAdvance()
error_code FTFaceH_GetMaxVerticalAdvance()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderBufferSize()
error_code FTFaceH_GetRenderBufferSize()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderEffectSlant()
error_code FTFaceH_GetRenderEffectSlant()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderEffectWeight()
error_code FTFaceH_GetRenderEffectWeight()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderScale()
error_code FTFaceH_GetRenderScale()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderScalePixel()
error_code FTFaceH_GetRenderScalePixel()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_GetRenderScalePoint()
error_code FTFaceH_GetRenderScalePoint()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_SetCompositeCodes()
error_code FTFaceH_SetCompositeCodes()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_SetRenderEffectSlant()
error_code FTFaceH_SetRenderEffectSlant()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_SetRenderEffectWeight()
error_code FTFaceH_SetRenderEffectWeight()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_SetRenderScalePixel()
error_code FTFaceH_SetRenderScalePixel()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTFaceH_SetRenderScalePoint()
error_code FTFaceH_SetRenderScalePoint()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_CloseFace()
error_code FTManager_CloseFace()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_Done_FreeType()
error_code FTManager_Done_FreeType()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_Init_FreeType()
error_code FTManager_Init_FreeType()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_OpenFileFace()
error_code FTManager_OpenFileFace()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_OpenMemFace()
error_code FTManager_OpenMemFace()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_OpenStreamFace()
error_code FTManager_OpenStreamFace()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
}
s32 FTManager_SetFontOpenMode()
error_code FTManager_SetFontOpenMode()
{
UNIMPLEMENTED_FUNC(cellFontFT);
return CELL_OK;
+43 -14
View File
@@ -342,25 +342,54 @@ error_code cellFsGetFreeSize(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32>
{
cellFs.todo("cellFsGetFreeSize(path=%s, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count);
if (block_size)
{
*block_size = 0;
}
if (block_count)
{
*block_count = 0;
}
if (!path || !block_size || !block_count)
{
return CELL_EFAULT;
}
fs::device_stat info;
fs::statfs(vfs::get(path.get_ptr()), info);
*block_size = 4096;
*block_count = info.avail_free / 4096;
*block_size = 0;
*block_count = 0;
vm::var<lv2_file_c0000002> op;
op->_vtable = vm::cast(0xfae12000);
op->op = 0xC0000002;
op->out_code = 0x80010003;
op->path = path;
if (!std::strncmp(path.get_ptr(), "/dev_hdd0", 9))
{
sys_fs_fcntl(ppu, -1, 0xC0000002, op, sizeof(*op));
*block_count = op->out_block_count;
*block_size = op->out_block_size;
}
else
{
vm::var<u64> _block_size, avail;
if (auto err = sys_fs_disk_free(ppu, path, vm::var<u64>{}, avail))
{
if (err + 0u == CELL_EPERM)
{
return not_an_error(CELL_EINVAL);
}
return err;
}
if (!*avail)
{
return CELL_ENOTDIR;
}
if (auto err = cellFsGetBlockSize(ppu, path, vm::var<u64>{}, _block_size))
{
return err;
}
*block_count = *avail / *_block_size;
*block_size = *_block_size;
}
return CELL_OK;
}

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