Compare commits

...
262 Commits
Author SHA1 Message Date
Elad e9ad8a9219 Update SPULLVMRecompiler.cpp 2026-03-30 13:32:45 +03:00
Megamouse 6dc06b3ff5 Update Qt to 6.11.0 2026-03-30 10:58:19 +02:00
Megamouse a10390e52a Update libpng to 1.6.56 2026-03-30 10:58:19 +02:00
Megamouse 433110b4d8 Update wolfssl to 5.9.0 2026-03-30 10:58:19 +02:00
Megamouse b94e6d4864 Fix some warnings 2026-03-30 10:58:19 +02:00
Megamouse 44dc29e52b Qt: Add some some more thread names 2026-03-30 10:58:19 +02:00
Megamouse ab03d76ed6 overlays: show latching message for fatal errors 2026-03-30 10:13:05 +02:00
Megamouse bd2b2c2747 Qt: add recording settings dialog 2026-03-30 09:17:20 +02:00
Ani aa7cf5ea15 sysinfo: Implement RAM Usage stats for Linux (#18473)
Reads memory statistics from "/proc/meminfo"
2026-03-29 19:48:59 +03:00
oltolm f8fe64ff77 find_dialog: fix compiler warning 2026-03-29 14:45:53 +02:00
oltolm 1791876eda remove unused lambda captures 2026-03-29 14:45:53 +02:00
oltolm e6204d3c1d CMake: fix the case USE_SYSTEM_ZLIB=OFF and USE_SYSTEM_CURL=OFF 2026-03-29 14:45:53 +02:00
oltolm f0f9ef6f30 cmake: fix build with latest Curl 2026-03-29 14:45:53 +02:00
kd-11 51ea735cb5 rsx/vk: Try to reclaim memory aggressively when changing resolution scale 2026-03-28 20:20:12 +03:00
kd-11 069821a2e7 rsx/rtts: Fix broken optimization check
- Typo. Applying inverse res scale is really not what we want
2026-03-28 20:20:12 +03:00
kd-11 0052108e87 rsx/rtt: Fix transfer region calculation when source and destination scaling does not match 2026-03-28 20:20:12 +03:00
kd-11 64c24959cb rsx: Fix clang build 2026-03-28 20:20:12 +03:00
kd-11 b57390d3cd rsx/overlays: Add resolution scale threshold to home menu 2026-03-28 20:20:12 +03:00
kd-11 91c136b6d0 rsx/overlay: Add resolution scale slider to home menu 2026-03-28 20:20:12 +03:00
kd-11 c00fa2cc8c config: Make resolution scaling a dynamic option 2026-03-28 20:20:12 +03:00
kd-11 fe3cbde1d3 rsx: Add optimization to skip cloning surfaces whose dimensions did not change
- If only the threshold changed or the surface is below threshold anyway, nothing will change
- In those cases, just update the internal data and continue
2026-03-28 20:20:12 +03:00
kd-11 e2dff6bbf8 rsx: Implement resolution scale change handling in surface cache 2026-03-28 20:20:12 +03:00
Elad 976cd1ce66 SaveStates: Fix restart after saving 2026-03-27 22:22:40 +03:00
Elad a4523651c7 RPCS3: Notify RAM shortage, Log current and peak RAM usage 2026-03-27 20:20:29 +03:00
BehroozRezvani 2702417192 Make performance overlays use window space (#18419)
Adds a new performance overlay option to use the whole window as rather
than just framebuffer space.
2026-03-27 16:08:46 +01:00
capriots 72b872df66 cellDmuxPamf: fix freezing FMVs in some games
- Delays demuxing a bit to let the game finish initializing FMV
playback.
- Also includes the missing half of #18450 which I forgot to Commit ^^"
- Sets cellDmuxPamf to HLE by default again
2026-03-27 13:47:26 +00:00
Elad bb3e2689d4 Thread.cpp: Fix game exit on access violation
Fixes game closing in Twisted Metal.
This commit also aloows to debug such states by using cpu_flag::req_exit as a broker
2026-03-26 13:55:00 +02:00
Elad 4ced11e533 SPU Analyzer: Add pure opcode tag 2026-03-26 13:55:00 +02:00
Elad 9a0a5a1735 LLVM: Try to reuse BitCasts 2026-03-26 13:55:00 +02:00
Elad e83034624b SPU Debugger: Measure rate of block ran 2026-03-26 13:55:00 +02:00
Elad 619fe7b14e SPU LLVM: Classify SPU memory and context memory instructions 2026-03-26 13:55:00 +02:00
Elad 37a07ae545 SPU LLVM: Optimize FM, FMA and FCGT in Reduced Loop 2026-03-26 13:55:00 +02:00
Elad e1eae3ee49 Add floating ppoint hint 2026-03-26 13:55:00 +02:00
Elad 49abd6d8e5 SPU LLVM: Allow the reuse of address from LQX/STQX 2026-03-26 13:55:00 +02:00
Elad fbdbf8addf SPU LLVM: CEQHI pattern 2026-03-26 13:55:00 +02:00
Elad 2e4ee9c9b6 SPU LLVM: Implement reduced loop 2026-03-26 13:55:00 +02:00
Elad a863e94c25 SPU: Detect reduced loop 2026-03-26 13:55:00 +02:00
kd-11 9b6bc7c1b4 rsx: Make resolution scaling configuration non-global
- Paves the way for other changes.
- The main goal is to be able to switch the resolution scale and MSAA level at runtime.
2026-03-25 21:19:46 +03:00
kd-11 86b7ea6bf3 overlays/sdf: Avoid 0-height inner boxes for switch capsule
- Can introduce dfdx/dfdy discontinuities on the midline as the distance changes direction
- The seams can sometimes become visible if a border is applied on some GPUs
2026-03-25 21:19:46 +03:00
oltolm 18bd6d681e cmake: fix build with bundled zlib 2026-03-25 08:30:41 +01:00
oltolm 2dd194d381 make the code build with Clang 22 2026-03-25 08:30:41 +01:00
oltolm a8b603dd92 CMake: remove option USE_MSVC_STATIC_CRT and clean up 2026-03-25 08:30:41 +01:00
Megamouse a03d4f69f8 logs: Fix global log levels during boot and after changing log level settings 2026-03-24 19:34:06 +01:00
capriots 99bb042bea HLE modules: process PPU state after lv2 syscalls 2026-03-24 07:55:05 +02:00
Megamouse 2bcc27d581 Qt/input: Do not send gui input release events until there was at least one button press 2026-03-23 20:32:46 +01:00
Megamouse 53c33cd812 gui/input: disable stick anti deadzone in pad navigation
This is only meant to be used during emulation.
2026-03-23 19:35:01 +01:00
Megamouse 1d05cf9ce5 Qt/Input: trace gui pad navigation button presses 2026-03-23 19:35:01 +01:00
Megamouse 07f5b0aa5b Qt: Improve find dialog
Add index of current line and word.
Add case sensitivity checkbox.
2026-03-23 17:52:30 +01:00
Megamouse 36e1d664ea Qt: Smoothly start/stop audio with fade in and fade out 2026-03-23 14:47:15 +01:00
Megamouse 90e2c39015 Qt: loop SND0.AT3 audio 2026-03-23 14:47:15 +01:00
kd-11 5a90dc0059 overlays: Bump the slider label font size 2026-03-23 02:38:34 +03:00
kd-11 c19d22ce88 overlays/sdf: Clamp rounded-rect border radius to never exceed the box sides
- If the radius exceeds any half-dimension then the box-shrink subtraction yields a negative.
  That negative introduces a second transition boundary when the classification happens as it transitions back to positive.
  Normally not a big deal but when rendering borders at the transition points it can introduce artifacts.
2026-03-23 02:38:34 +03:00
kd-11 5acc263b73 gl: Properly initialize memory layout definition structs
- Also refactors the upload_texture function to be a bit more readable
2026-03-23 01:36:50 +03:00
schm1dtmac bc6e01c422 Fix GH & brew breaking macOS builds again 2026-03-22 20:36:51 +01:00
kd-11 a2eb4fec53 overlays: Restore slider handles to previous size
- Added padding to smooth out the outer edge transition made the circle too small
2026-03-22 20:11:43 +03:00
kd-11 32c9c6f515 overlays: Fixups for switch rendering
- Disallow odd numbers for the primary dimension
- Increase the size slightly in home menus
- Disable vertex snapping when rendering SDFs
2026-03-22 20:11:43 +03:00
kd-11 04f7dd02fd overlays: Fix SDF rendering when scrolling is involved 2026-03-22 20:11:43 +03:00
kd-11 35907bcfc8 overlays: Redesign switches 2026-03-22 20:11:43 +03:00
kd-11 61b1bd7ead overlays/sdf: Take element padding into account
- Helps to smooth out the outer edges of ellipses and circles
2026-03-22 20:11:43 +03:00
kd-11 2bad4f47f1 gl: Integrate SDF rendering functionality 2026-03-22 20:11:43 +03:00
kd-11 5a94adcf26 overlays: Implement SDF config transforms 2026-03-22 20:11:43 +03:00
kd-11 57e37862f4 overlays: Use ellipse SDF for circles 2026-03-22 20:11:43 +03:00
kd-11 45bae0046a vk: Add support for basic SDF rendering
- Does not support scaled coordinates yet
2026-03-22 20:11:43 +03:00
kd-11 a0c91bf96a overlays: Use SDF equations to represent curved shapes 2026-03-22 20:11:43 +03:00
Ani b607993b7b overlay: Remove redundant redeclaration
Fixes one gcc compilation warning
2026-03-22 16:40:20 +01:00
Ani 1eb72e4b71 rpcs3: Add missing #include <climits>, fix gcc-16 compilation 2026-03-22 16:40:20 +01:00
Megamouse e5840ab868 Qt: fix audio timer loop 2026-03-22 15:46:44 +01:00
BehroozRezvani 54999d1507 Add Zed config files to gitignore 2026-03-22 13:16:58 +01:00
Megamouse 51514f9dc8 Qt: start hover audio/video after a timeout 2026-03-22 06:49:43 +01:00
Megamouse 40229adb14 Qt: add gui audio volume setting 2026-03-22 06:49:43 +01:00
Megamouse 33f8deffbe Qt: add setting for disabling hover music 2026-03-22 06:49:43 +01:00
Megamouse c80e08a642 Qt: Don't check for movies if play_hover_movies is disabled
Apparently this was forgotten. The variable was already captured
2026-03-22 06:49:43 +01:00
Megamouse 62b2ffd7ca Qt/overlays: Add secondary audio output for emulation 2026-03-22 06:49:43 +01:00
Megamouse cd1d6282b4 Qt: Remove some unused code 2026-03-21 16:10:26 +01:00
kd-11 67f69bb4b3 rsx/cfg: Fix handling of instructions with literal input
- The hardware is pretty dumb about it, it just unconditionally skips the next instruction
2026-03-21 14:44:45 +01:00
RipleyTom 2ba7756c0e Add overlay notification for received messages 2026-03-20 19:51:16 +01:00
Megamouse c6407b37a5 Batch create/remove steam shortcuts 2026-03-20 17:48:11 +01:00
kd-11 410660627d overlays: Add a special message id for spinners with empty text 2026-03-20 15:33:28 +03:00
kd-11 852317a071 overlays: Shrink the shader notification popup 2026-03-20 15:33:28 +03:00
kd-11 6590f1b55d overlays: Add RSX memory tiling to settings page 2026-03-20 15:33:28 +03:00
schm1dtmac 84277f41a1 Fix mac builds (& add some failsafes) 2026-03-19 21:51:36 +01:00
Ani b73c45f1fb overlay: Add 8px left margin on the sidebar 2026-03-19 19:44:55 +01:00
kd-11 ddd226f0ea rsx/fp/cfg: Add unit test for special cond inversion 2026-03-19 19:38:17 +03:00
kd-11 3c68c36fa0 rsx/cfg: Log a warning when encountering empty IF blocks with ELSE aliasing
- Hardware tests confirm this is correct behavior, the condition just inverts
2026-03-19 19:38:17 +03:00
kd-11 d54e54b66d rsx/cfg: Handle IF-ELSE aliasing statement as inverted condition
- If there is no IF block but ELSE block exists, treat the branch as being inverted and the ELSE block as the main IF body
- Rare but seen in some games
2026-03-19 19:38:17 +03:00
RipleyTom 2f3b66985e Clean up code using mutable + const when possible 2026-03-19 14:56:48 +02:00
kd-11 43799762c7 qt: Update tooltips with new vsync behavior 2026-03-19 03:10:07 +03:00
kd-11 cb501e32ca gl: Make vsync setting dynamic 2026-03-19 03:10:07 +03:00
kd-11 7a7e25f901 overlays: Add Vsync configuration to overlays 2026-03-19 03:10:07 +03:00
kd-11 e690e7e458 gl/vk: Implement tri-state Vsync setting 2026-03-19 03:10:07 +03:00
Ani 253d4565f1 config: Enable start in fullscreen mode by default 2026-03-18 22:34:37 +01:00
Megamouse 1f2a935458 Qt: Do not close pad settings dialog if user said no in duplicate button dialog 2026-03-18 18:47:34 +01:00
Megamouse 0c27b63ab4 Qt: fix duplicate button or combo warning 2026-03-18 18:47:34 +01:00
FlexBy420 4c106960c5 Update current firmware to 4.93 2026-03-18 16:00:35 +02:00
Megamouse f076d1e1e6 Input: Fix keyboard stick handling 2026-03-18 12:10:29 +01:00
Megamouse 7b58340a60 Input: optimize keyboard button handling on release 2026-03-18 12:10:29 +01:00
Megamouse 5578edf9e4 Input: Map PS button to start+select by default 2026-03-18 12:10:29 +01:00
Megamouse 704d8764af input: refactor combos into a struct for future use
Also update some terminology in the code
2026-03-18 12:10:29 +01:00
Darkhost1999 6523afa69a overlays/home: Fix restarting games from home menu 2026-03-17 21:39:18 +01:00
Megamouse 5416f432b5 input: Fix SDL buttons 2026-03-17 20:53:46 +01:00
Megamouse 43f3a4816d Qt: Fix game list selection after Refresh(true) 2026-03-17 20:15:40 +01:00
Megamouse bc0c42b025 Automatic combo button input 2026-03-17 15:30:21 +01:00
Megamouse 9f3adb3fc7 Fix steam banners for iso files 2026-03-17 14:47:17 +01:00
Megamouse df6cba6582 Use ICON0.PNG for steam cover 2026-03-17 14:47:17 +01:00
Megamouse 8cdad0af98 Add more fallbacks to the steam banner 2026-03-17 14:47:17 +01:00
Megamouse 801a1e6c38 Qt: Move game shortcut creation logic to shortcut_utils 2026-03-17 14:47:17 +01:00
kd-11 9da088fe29 overlays: Relax vblank range to default 2026-03-17 15:42:12 +03:00
kd-11 d96f31eda4 overlays: Limit vblank setting in the UI
- Use Qt GUI or config modification if you need crazy figures
2026-03-17 15:42:12 +03:00
kd-11 a5cce58225 overlays/home: Auto-resize the sidebar in case of long translated text 2026-03-17 15:42:12 +03:00
kd-11 39e6fc5918 overlays: Left align the savestates menu
- Temporary measure, a proper dialog will be added later
2026-03-17 15:42:12 +03:00
kd-11 2ea344ce3e overlays: Allow home menu 'entries' to support different alignment options 2026-03-17 15:42:12 +03:00
kd-11 358fbb3ce3 overlays: Backing out of settings menu returns to home menu 2026-03-17 15:42:12 +03:00
kd-11 aaf441005a overlays: Fix UX issues with dropdowns
- Select button resets the value to default
- Audio cues play correctly
2026-03-17 15:42:12 +03:00
Megamouse 6e6dd603cb mmjoy: deduplicate some code 2026-03-17 13:36:25 +01:00
Megamouse 22fe14d31d input: implement button combos 2026-03-17 13:36:25 +01:00
Megamouse 2eba7da8e6 Qt: Create Steam banners as well during shortcut creation 2026-03-16 23:20:24 +01:00
kd-11 ca2b7f9b9f rsx/overlays: Fix linux build 2026-03-16 19:08:07 +03:00
kd-11 4780e7c8da rsx/overlays: Fix clang build 2026-03-16 19:08:07 +03:00
kd-11 a318384142 rsx/overlays: Fix weird spacing with reset prompt
- Just post-rebase issues
2026-03-16 19:08:07 +03:00
kd-11 53d3f49f45 overlays/gl: Fix misbehaving clip regions 2026-03-16 19:08:07 +03:00
kd-11 25581ce52f overlays/tabs: Fix crash when scrolling through tabs quickly 2026-03-16 19:08:07 +03:00
kd-11 6c0c80b7bb overlays/list-view: Use track to indicate scrolling instead of ugly highlight 2026-03-16 19:08:07 +03:00
kd-11 f9af53f215 overlays: Fix bug with list view element count calculation and selection wrap-around 2026-03-16 19:08:07 +03:00
kd-11 2fd5b1b4be overlays/home: Add icons to settings page 2026-03-16 19:08:07 +03:00
kd-11 3acf1f6470 overlays: Add some more icons 2026-03-16 19:08:07 +03:00
kd-11 37f1533dad overlays/home: Integrate the new dropdown widget 2026-03-16 19:08:07 +03:00
kd-11 bb652ed840 rsx/overlays: Implement dropdown control
- The base widget and the popup are rendered separately
- The owner is responsible for placing the widget at the desired position for rendering
2026-03-16 19:08:07 +03:00
kd-11 281706fdae overlays/utils: Add simple utility to center align a child component 2026-03-16 19:08:07 +03:00
kd-11 198fe71cc4 overlays/checkbox: Make sure backgrounds are opaque for clarity 2026-03-16 19:08:07 +03:00
kd-11 b8e2c7060b overlays: Improve slider label spacing 2026-03-16 19:08:07 +03:00
kd-11 dbb6c87a10 utils: Implement enum size computation 2026-03-16 19:08:07 +03:00
kd-11 7240cbfdab rsx/overlays: Implement arrow rendering 2026-03-16 19:08:07 +03:00
kd-11 7866c7195c rsx/overlays: Tabs - Do not touch renderer resources on the input thread! 2026-03-16 19:08:07 +03:00
kd-11 e26978e664 overlays/home: Use the new slider component 2026-03-16 19:08:07 +03:00
kd-11 63ed8881a4 rsx/overlays: Implement slider control 2026-03-16 19:08:07 +03:00
kd-11 1be7b9f983 overlays: Align switches to container end 2026-03-16 19:08:07 +03:00
kd-11 471ed347f4 overlay/settings: Use switch element instead of checkbox 2026-03-16 19:08:07 +03:00
kd-11 cff9b5b65e rsx/overlays: Implement checkbox and switch controls 2026-03-16 19:08:07 +03:00
kd-11 5d28ff5df1 overlays: Unified icon loading logic 2026-03-16 19:08:07 +03:00
kd-11 7fd0aa95fb overlays: Add icons for trophies and friends 2026-03-16 19:08:07 +03:00
kd-11 27ecfaee9c overlays/home: Add icons to the home menu 2026-03-16 19:08:07 +03:00
kd-11 ce2afa1d54 overlays: Extend list view to allow hassle-free insertion of overlay-element descendants 2026-03-16 19:08:07 +03:00
kd-11 984c562500 overlays: Fix bug in box padding calculation 2026-03-16 19:08:07 +03:00
kd-11 f880a00cba overlays: Provide home icons in different sizes 2026-03-16 19:08:07 +03:00
kd-11 6cf2cc67d3 overlays/icon: Handle some edge cases 2026-03-16 19:08:07 +03:00
kd-11 9e6fecb4ca rsx: Tighten data contract for "external" raw images 2026-03-16 19:08:07 +03:00
kd-11 3194bd3fb4 overlays/home: Add icons repository wrapper 2026-03-16 19:08:07 +03:00
kd-11 fcb5a5c5f8 overlays: Add some home menu icons from font-awesome 2026-03-16 19:08:07 +03:00
kd-11 3988eceb8d overlays: Turn the home menu into a proper sidebar 2026-03-16 19:08:07 +03:00
kd-11 2b2b13273b overlay/settings: Add missing sound effects 2026-03-16 19:08:07 +03:00
kd-11 88278ec7c9 rxs/overlays: Fix visual glitches in the tabbed settings dialogs 2026-03-16 19:08:07 +03:00
kd-11 7d92198ef0 rsx/overlays: Improvements for some containers 2026-03-16 19:08:07 +03:00
kd-11 23eb67badc rsx/overlays: Convert settings pages to a tabbed interface 2026-03-16 19:08:07 +03:00
kd-11 d5928d99d7 rsx/overlays: Replace home menu with a sidebar 2026-03-16 19:08:07 +03:00
kd-11 3c16105c3b overlays/home: Refactor to support having some home pages inside other containers 2026-03-16 19:08:07 +03:00
kd-11 5cb688f309 rsx/overlays: Implement tabbed containers 2026-03-16 19:08:07 +03:00
Megamouse 7859a5f9d2 input: log warning instead of throwing an exception when the dpad has an unknown value 2026-03-16 11:13:17 +01:00
Megamouse 8b74ea8757 Qt: Add steam shortcuts 2026-03-16 10:30:47 +01:00
Megamouse 2c2ec6e109 VS: Add missing test files
I'm having some gmock issues, so let's just exclude them for now.
2026-03-16 10:30:47 +01:00
Megamouse 6c48bd8f93 Fix callback initialization order
We need to initialize the emu callbacks before creating the main window.
Otherwise CallFromMainThread segs since call_from_main_thread is null.
The same goes for the CallFromMainThread connect in gui_application.
If we create the connection too late, we will simply never wake up the
caller and therefore softlock eventually.
2026-03-16 09:49:42 +01:00
Ani b422cb86f2 cmake: Build with SDL by default 2026-03-16 08:59:15 +01:00
Ani 1fb97734a0 cellDmuxPamf: LLE by default again
HLE implementation is crashing on a few games, see #18360, revert it back to LLE until issues with HLE are fixed
2026-03-16 06:21:01 +02:00
Ani 7221012593 config: Disable pad navigation by default
Pad navigation is currently crashing with the SDL handler, see #18362. Disable it until the issue is fixed.
2026-03-16 02:03:54 +01:00
p0yr4s 297db8713f qt: import QJsonDocument 2026-03-15 21:00:11 +01:00
p0yr4s 477ae6c6df cmake: Only use Qt6::GuiPrivate for Qt >= 6.10 2026-03-15 21:00:11 +01:00
Megamouse 74fbca8c80 input: simplify mmjoy handler 2026-03-15 20:00:05 +01:00
Megamouse 433816148a Fix iso shortcuts 2026-03-15 19:02:32 +01:00
Ani 5714eb0ba5 config/ui: Unify Shader Mode values
Have the same values between UI and Config for easing automatic configuration
2026-03-15 18:19:45 +01:00
Ani 315f88b0e4 ui: Split overlay settings, A-Z order emulator tab settings 2026-03-15 18:19:45 +01:00
AniLeo 8587fca5db ui: Move SPU Loop Detection to advanced 2026-03-15 18:19:45 +01:00
AniLeo e2a26f937f ui: Move PPU Non-Java Fixup to debug 2026-03-15 18:19:45 +01:00
AniLeo 90ebc7f319 ui: Move Accurate DFMA to debug 2026-03-15 18:19:45 +01:00
AniLeo 67a67feb68 ui: A-Z order advanced tab settings 2026-03-15 18:19:45 +01:00
AniLeo 9bdacc64aa config: Enable pad navigation by default 2026-03-15 18:19:45 +01:00
AniLeo 5a921bca46 ui: Allow toggling pad navigation on BSD 2026-03-15 18:19:45 +01:00
AniLeo 86f453f677 ui: Merge pkg/pup install dialog options 2026-03-15 18:19:45 +01:00
AniLeo 7712584bd4 ui: Merge exit/boot game dialog options 2026-03-15 18:19:45 +01:00
Ani bc58dff715 ui: Rename depth buffers to depth buffer
Removes ambiguity between config and ui
2026-03-15 18:19:45 +01:00
Ani 0bb6299e39 ui: Specify Anti-Aliasing as MSAA 2026-03-15 18:19:45 +01:00
Ani b24524fc75 config: Fix naming of SPU XFloat Accuracy
Rename from 'XFloat Accuracy' to 'SPU XFloat Accuracy'
2026-03-15 18:19:45 +01:00
Ani 60eb1ce2ec config: Fix naming of Asynchronous Texture Streaming
Rename from 'Asynchronous Texture Streaming 2' to 'Asynchronous Texture Streaming'
2026-03-15 18:19:45 +01:00
Ani 9733d8c857 config: Move FSR CAS out of Vulkan subcategory
FSR1 was already implemented for OpenGL as well, so this setting is no longer exclusive to the Vulkan render
2026-03-15 18:19:45 +01:00
jfleezy23 5274210ba8 VK: scale auto shader compiler workers on wide CPUs 2026-03-15 18:45:36 +03:00
Malcolm 1627757608 SPU LLVM: Emulate GBB with udot/sdot
Greatly simplifies GB, GBH, and GBH. Uses udot/sdot with power of two
masks to shift values and sum them in a single step, effectively
gathering them
2026-03-15 08:48:18 +02:00
Malcolm 4542020c86 SPU LLVM: ARM64: Use UDOT for emulating SUMB 2026-03-15 08:48:18 +02:00
Megamouse b734ceb2e7 overlays: allow to reset current setting 2026-03-14 17:50:22 +01:00
qurious-pixel 951d47c94c Use System Protobuf for Intel Mac 2026-03-14 09:53:24 +01:00
Megamouse 6f07e8453a Update curl to 8.19.0 2026-03-12 19:08:49 +01:00
Megamouse e6cf05cfb7 Qt: Fix log levels tooltip 2026-03-11 14:42:45 +01:00
Megamouse 6b6dd6c432 Qt: Rename Shortcuts to Keyboard Shortcuts 2026-03-11 14:42:45 +01:00
Megamouse ee01d1186f overlays: play SND0.AT3 during initialization 2026-03-11 06:45:22 +01:00
Megamouse 2934641237 overlays: support playing audio with video_view 2026-03-11 06:45:22 +01:00
Elad fecb53f86c Fix SaveStates cellDumxPamf regression 2026-03-10 20:13:29 +02:00
Elad 9811e1cc3b Debugger: Add HW PPU threads view 2026-03-10 20:13:29 +02:00
Elad 234f2b4648 Silence sys_memory_get_user_memory_size 2026-03-10 20:13:29 +02:00
Megamouse 9e573a9ff2 rpcn: set default version to 2 2026-03-10 17:41:48 +01:00
Megamouse 3803c864f7 rpcn: Fix file access error when loading rpcn.yml with version 1
The file was still in use when saving.
2026-03-10 17:41:48 +01:00
Megamouse 8afa40eaa7 rpcn: Fix segfault in rpcn_settings_dialog destructor
This will happen if m_rpcn failed to connect in the constructor.
2026-03-10 17:41:48 +01:00
kd-11 c7a576edce gl: Implement proper, sectioned DMA transfers
- Allows to transfer partial contents when needed
2026-03-10 16:25:32 +03:00
kd-11 c72d54bd6a gl: Add guards to catch invalid configuration in image transfer functions 2026-03-10 16:25:32 +03:00
kd-11 040a79ddd1 gl: Improve object annotation for renderdoc debugging 2026-03-10 16:25:32 +03:00
kd-11 aa094ca948 gl: Trace memory readback operations to debug tracking when renderdoc compat is enabled
- Renderdoc does not show these calls so we need to insert the debug message
2026-03-10 16:25:32 +03:00
kd-11 7917520633 gl: Support packing/unpacking images with padding 2026-03-10 16:25:32 +03:00
kd-11 8651875e59 gl: Add optional row length to GPU image routines 2026-03-10 16:25:32 +03:00
kd-11 ef70a6e825 gl: Move ownership of the global blitter object from texture cache to global 2026-03-10 16:25:32 +03:00
kd-11 0869ef421d gl: Silence compiler warning 2026-03-10 16:25:32 +03:00
kd-11 5f86315ae0 gl: Fix shader interpreter compilation 2026-03-10 16:25:32 +03:00
kd-11 ab72ce418e gl: Minor enhancements to blitter
- Move some functions to cpp. Makes it easier to debug failing image operations
- Add fbo validation before blit operations
2026-03-10 16:25:32 +03:00
kd-11 36cdaac327 overlays: Fix image size estimation 2026-03-10 16:25:32 +03:00
kd-11 6d52415d50 gl: Ignore range offset when doing readback operations
- OGL desperately needs a functioning DMA layer
2026-03-10 16:25:32 +03:00
Megamouse 0603d24a91 Qt: play SND0.AT3 in game lists when a movie would play 2026-03-10 12:42:56 +01:00
Megamouse 71f0d5c602 cellGem: fix RAW8 to RGBA_320x240
We were basically writing two rows into dst for each other src line.
This means we were writing 480 lines in total instead of 240,
overwriting one of the lines written in the previous iteration.
This led to writing one line out of bounds last iteration.
Let's just use a simple debayer technique which perfectly matches here.
This also applies the previously missing gain factors.

I also tried to first demosaic and then drop every other pixel.
The result was comparatively blurred and the performance worse.
2026-03-10 07:01:55 +01:00
Megamouse 763001ee91 cellGem: fix gain channels 2026-03-10 07:01:55 +01:00
Megamouse 0f92ea2578 cellGem: fix memcpy in cellGemReadExternalPortDeviceInfo
It was copying from dst to src, and the wrong size at that
2026-03-10 07:01:55 +01:00
Megamouse e0a0d736c4 cellGem: remove redundant check 2026-03-10 07:01:55 +01:00
Ani 65320446f0 vk: Add 0x13C0 NAVI2 device ID (Raphael Mendocino)
This is the iGPU on 9800X3D
2026-03-09 19:32:09 +02:00
kd-11 5f6822042d gl: Silence warnings 2026-03-09 15:18:47 +03:00
kd-11 302e87c920 rsx/vk: Improve robustness when encountering corrupted shaders 2026-03-09 15:18:47 +03:00
RipleyTom 77cbdd82ab LLVM 22 fixups
From https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html:
The alignment argument of the @llvm.masked.load, @llvm.masked.store, @llvm.masked.gather and @llvm.masked.scatter intrinsics has been removed. Instead, the align attribute should be placed on the pointer (or vector of pointers) argument.

They also changed(not in changelog for some reason):
vpdpbusd_128: [v4i32] -> [v4i32, v4i32, v4i32]
to
vpdpbusd_128: [v4i32] -> [v4i32, v16i8, v16i8]
2026-03-09 06:30:29 +02:00
Megamouse 41db06b53f cellGem: fix handle_pos calculation
The handle position depends on the sphere position and the orientation
2026-03-08 16:12:44 +01:00
Megamouse eeda9c7738 cellGem: improve quaternion rotation
rotate_vector caused wrong results for default_orientation and 0,0,x
2026-03-08 16:12:44 +01:00
Megamouse c38bf70464 cellCamera: improve error logging 2026-03-08 16:12:44 +01:00
RipleyTom 43b295892f PPUAnalyzer: Fix SLDI shift operand 2026-03-08 09:29:48 +02:00
capriots 2573cc5fd0 cellDmuxPamf: fix stream cache not being consumed in some cases 2026-03-07 21:46:07 +02:00
capriots 4828d4d2d6 cellDmuxPamf: review fixes 2026-03-07 21:46:07 +02:00
capriots c5f278ed37 cellDmuxPamf: properly handle streams smaller than 0x800 bytes 2026-03-07 21:46:07 +02:00
capriots b839d4d1a6 cellDmuxPamf: consume guest memory on SPU thread group creation 2026-03-07 21:46:07 +02:00
capriots 3616424b26 cellDmuxPamf: fix lv2 mutex + cond not being destroyed on close 2026-03-07 21:46:07 +02:00
capriots 4d6da6542e tests: enable cellDmuxPamf tests in CMakeLists 2026-03-07 21:46:07 +02:00
capriots f2aa347608 cellDmuxPamf: review fixes + improvements 2026-03-07 21:46:07 +02:00
capriots bd7d5faa9f cellDmuxPamf implementation part 2: PPU thread 2026-03-07 21:46:07 +02:00
capriots a3d09a7427 tests: cellDmuxPamf 2026-03-07 21:46:07 +02:00
capriots 7dad9663b2 cellDmuxPamf implementation part 1: SPU thread 2026-03-07 21:46:07 +02:00
kd-11 cae8ae63e3 gl: Use image dimensions to determine read buffer size 2026-03-07 16:29:11 +03:00
kd-11 728d84b1fe gl: Add debug names to some objects 2026-03-07 16:29:11 +03:00
kd-11 4a51302c58 gl: Propagate native layout from parent when creating temporary subresources 2026-03-07 16:29:11 +03:00
kd-11 0ea692e9ab gl: Use named_object<GL_TEXTURE> as the base class for images 2026-03-07 16:29:11 +03:00
kd-11 1e16b338b4 gl: Add support for named objects 2026-03-07 16:29:11 +03:00
kd-11 14789b536f gl: Clean up the awful image copy API
- Wrap everything in rsx::io_buffer and gl::buffer to avoid out of bounds issues.
- Also abstracts away nasty things like OpenGL offset pointer casts.
2026-03-07 16:29:11 +03:00
RipleyTom ac30feeddb Revert enabling PPU jump elider 2026-03-06 21:10:40 +00:00
Megamouse 0d80e300a0 Qt: add log level settings 2026-03-06 15:06:25 +01:00
Megamouse 69384d7bb4 Update codebase to SDL 3.4.0 2026-03-06 13:56:04 +01:00
Megamouse 4fd2409b8b Update FAudio to 26.03 2026-03-06 13:56:04 +01:00
Megamouse d97851376d Add stacktrace in case of exception 2026-03-06 13:56:04 +01:00
Megamouse 1c5e30e83f input/qt: fix default squircle value in text and remove duplicate comments 2026-03-06 13:56:04 +01:00
kd-11 414df8432e gl: Respect internal offsets when performing DMA transfer operations 2026-03-06 12:18:18 +03:00
kd-11 92f63ccc0b rsx/cfg: Silence GCC noise 2026-03-06 12:18:18 +03:00
kd-11 d75e8b24f7 [FIXUP] API extend 2026-03-06 12:18:18 +03:00
kd-11 a1af15b907 gl/dma: Fix range calculation when creating DMA blocks 2026-03-06 12:18:18 +03:00
kd-11 cf5eb22591 glutils: Extend buffer_object interface 2026-03-06 12:18:18 +03:00
RipleyTom 2f9f79eea2 PPU Fixes
-CallFunction empty function/jump elision was never gone through as cond was always false
-MSelf duplicate offset detection never triggered because set was reset each loop
-Rel executable memory size calculation used wrong section type
2026-03-06 10:49:59 +02:00
Megamouse c57d6110c4 rsx: add missing default to switch 2026-03-05 21:05:15 +01:00
Megamouse 2a292d1e2e rsx: fix unused parameter warning 2026-03-05 21:05:15 +01:00
Megamouse f2c8b157ef ISO: pass mode to file 2026-03-05 21:05:15 +01:00
Megamouse ec00a06caf Fix warning suppression in windows clang 2026-03-05 21:05:15 +01:00
Megamouse ae6172d86b Remove unused function 2026-03-05 21:05:15 +01:00
Megamouse 5605cf2141 Qt: Do not check return code of rpcs3 download 2026-03-05 17:25:45 +01:00
RipleyTom d46ddcee5d Fix mac build 2026-03-04 21:08:07 +03:00
Megamouse 3750fb2c1f cellGem: Fix deadlock when cellGemUpdateStart is called before cellCamera delivers images 2026-03-04 11:31:32 +01:00
kd-11 86b2773c28 rsx: Clean up after vertex cache changes 2026-03-04 03:54:39 +03:00
kd-11 11a9011510 rsx: Fix memory misalignment for temporary storage
- We create the temp storage with alignment of U but then do a type cast to u128 later. This obviously causes problems.
2026-03-04 03:54:39 +03:00
Iván Díaz Álvarez e66f1fa306 Solves render problems due to vertex data being modified before reuse
* Stores first 64bit of the vertex data to compare on retrieval as a fingerprint of if the underlying vertex data has been changed
2026-03-04 01:31:01 +03:00
365 changed files with 17638 additions and 3811 deletions
+4 -3
View File
@@ -13,15 +13,16 @@ export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
brew update
brew install -f --overwrite --quiet ccache "llvm@$LLVM_COMPILER_VER"
brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER"
if [ "$AARCH64" -eq 1 ]; then
brew install -f --overwrite --quiet googletest opencv@4 sdl3 vulkan-headers vulkan-loader molten-vk
brew unlink --quiet ffmpeg fmt qtbase qtsvg qtdeclarative protobuf
brew install -f --overwrite --quiet googletest opencv@4 sdl3 vulkan-headers vulkan-loader molten-vk
brew unlink --quiet ffmpeg fmt qtbase qtsvg qtdeclarative protobuf || true
else
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
arch -x86_64 /usr/local/bin/brew install -f --overwrite --quiet [email protected] opencv@4 "llvm@$LLVM_COMPILER_VER" sdl3 vulkan-headers vulkan-loader molten-vk
arch -x86_64 /usr/local/bin/brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative
arch -x86_64 /usr/local/bin/brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative protobuf || true
fi
export CXX=clang++
+2 -2
View File
@@ -21,7 +21,7 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
"rpcs3.app/Contents/Frameworks/QtVirtualKeyboard.framework" \
"rpcs3.app/Contents/Plugins/platforminputcontexts" \
"rpcs3.app/Contents/Plugins/virtualkeyboard" \
"rpcs3.app/Contents/Resources/git"
"rpcs3.app/Contents/Resources/git" || true
../../.ci/optimize-mac.sh rpcs3.app
@@ -49,7 +49,7 @@ QT_TRANS="$WORKDIR/qt-downloader/$QT_VER/clang_64/translations"
cp $QT_TRANS/qt_*.qm rpcs3.app/Contents/translations
cp $QT_TRANS/qtbase_*.qm rpcs3.app/Contents/translations
cp $QT_TRANS/qtmultimedia_*.qm rpcs3.app/Contents/translations
rm -f rpcs3.app/Contents/translations/qt_help_*.qm
rm -f rpcs3.app/Contents/translations/qt_help_*.qm || true
# Need to do this rename hack due to case insensitive filesystem
mv rpcs3.app RPCS3_.app
+1 -1
View File
@@ -6,7 +6,7 @@
QT_HOST="http://qt.mirror.constant.com/"
QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt${QT_VER_MAIN}_${QT_URL_VER}_${QT_VER_MSVC}_64/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_11_24H2-${QT_VER_MSVC_UP}-Windows-Windows_11_24H2-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtbase${QT_SUFFIX}"
+7 -7
View File
@@ -30,23 +30,23 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.9"
docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: clang
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.9"
docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: gcc
- os: ubuntu-24.04-arm
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.9"
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: clang
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64"
- os: ubuntu-24.04-arm
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.9"
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: gcc
name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }}
@@ -134,7 +134,7 @@ jobs:
runs-on: macos-14
env:
CCACHE_DIR: /tmp/ccache_dir
QT_VER: '6.10.2'
QT_VER: '6.11.0'
QT_VER_MAIN: '6'
LLVM_COMPILER_VER: '21'
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
@@ -213,9 +213,9 @@ jobs:
env:
COMPILER: msvc
QT_VER_MAIN: '6'
QT_VER: '6.10.2'
QT_VER: '6.11.0'
QT_VER_MSVC: 'msvc2022'
QT_DATE: '202601261212'
QT_DATE: '202603180535'
LLVM_VER: '19.1.7'
VULKAN_VER: '1.3.268.0'
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
+3
View File
@@ -69,6 +69,9 @@ CMakeSettings.json
*PVS-Studio*
PVS/*
# Zed Editor files
.zed/*
# Ignore other system generated files
x64/*
rpcs3/x64/*
-3
View File
@@ -18,9 +18,6 @@ else()
set(USE_LIBIDN2 OFF CACHE BOOL "Use libidn2 for IDN support") # Disabled because MacOS CI doesn't work otherwise
set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
option(CURL_DISABLE_INSTALL "Disable installation targets" ON)
if(USE_MSVC_STATIC_CRT)
set(CURL_STATIC_CRT ON CACHE BOOL "Use static crt to build curl")
endif()
if(WIN32)
set(ENABLE_UNICODE ON CACHE BOOL "enable Unicode")
endif()
+14 -14
View File
@@ -79,12 +79,16 @@
<ClCompile Include="curl\lib\cookie.c" />
<ClCompile Include="curl\lib\cshutdn.c" />
<ClCompile Include="curl\lib\curlx\base64.c" />
<ClCompile Include="curl\lib\curlx\basename.c" />
<ClCompile Include="curl\lib\curlx\dynbuf.c" />
<ClCompile Include="curl\lib\curlx\fopen.c" />
<ClCompile Include="curl\lib\curlx\inet_ntop.c" />
<ClCompile Include="curl\lib\curlx\inet_pton.c" />
<ClCompile Include="curl\lib\curlx\multibyte.c" />
<ClCompile Include="curl\lib\curlx\nonblock.c" />
<ClCompile Include="curl\lib\curlx\snprintf.c" />
<ClCompile Include="curl\lib\curlx\strcopy.c" />
<ClCompile Include="curl\lib\curlx\strdup.c" />
<ClCompile Include="curl\lib\curlx\strerr.c" />
<ClCompile Include="curl\lib\curlx\strparse.c" />
<ClCompile Include="curl\lib\curlx\timediff.c" />
@@ -106,6 +110,7 @@
<ClCompile Include="curl\lib\curl_rtmp.c" />
<ClCompile Include="curl\lib\curl_sasl.c" />
<ClCompile Include="curl\lib\curl_sha512_256.c" />
<ClCompile Include="curl\lib\curl_share.c" />
<ClCompile Include="curl\lib\curl_sspi.c" />
<ClCompile Include="curl\lib\curl_threads.c" />
<ClCompile Include="curl\lib\curl_trc.c" />
@@ -169,14 +174,13 @@
<ClCompile Include="curl\lib\progress.c" />
<ClCompile Include="curl\lib\psl.c" />
<ClCompile Include="curl\lib\rand.c" />
<ClCompile Include="curl\lib\rename.c" />
<ClCompile Include="curl\lib\ratelimit.c" />
<ClCompile Include="curl\lib\request.c" />
<ClCompile Include="curl\lib\rtsp.c" />
<ClCompile Include="curl\lib\select.c" />
<ClCompile Include="curl\lib\sendf.c" />
<ClCompile Include="curl\lib\setopt.c" />
<ClCompile Include="curl\lib\sha256.c" />
<ClCompile Include="curl\lib\share.c" />
<ClCompile Include="curl\lib\slist.c" />
<ClCompile Include="curl\lib\smb.c" />
<ClCompile Include="curl\lib\smtp.c" />
@@ -184,10 +188,8 @@
<ClCompile Include="curl\lib\socks.c" />
<ClCompile Include="curl\lib\socks_gssapi.c" />
<ClCompile Include="curl\lib\socks_sspi.c" />
<ClCompile Include="curl\lib\speedcheck.c" />
<ClCompile Include="curl\lib\splay.c" />
<ClCompile Include="curl\lib\strcase.c" />
<ClCompile Include="curl\lib\strdup.c" />
<ClCompile Include="curl\lib\strequal.c" />
<ClCompile Include="curl\lib\strerror.c" />
<ClCompile Include="curl\lib\system_win32.c" />
@@ -204,6 +206,7 @@
<ClCompile Include="curl\lib\version.c" />
<ClCompile Include="curl\lib\vquic\curl_ngtcp2.c" />
<ClCompile Include="curl\lib\vquic\curl_quiche.c" />
<ClCompile Include="curl\lib\vssh\vssh.c" />
<ClCompile Include="curl\lib\vtls\apple.c" />
<ClCompile Include="curl\lib\vtls\cipher_suite.c" />
<ClCompile Include="curl\lib\vtls\hostcheck.c" />
@@ -224,13 +227,11 @@
<ClCompile Include="curl\lib\vauth\spnego_sspi.c" />
<ClCompile Include="curl\lib\vauth\vauth.c" />
<ClCompile Include="curl\lib\vquic\vquic.c" />
<ClCompile Include="curl\lib\vssh\curl_path.c" />
<ClCompile Include="curl\lib\vssh\libssh.c" />
<ClCompile Include="curl\lib\vssh\libssh2.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\openssl.c" />
<ClCompile Include="curl\lib\vtls\schannel.c" />
<ClCompile Include="curl\lib\vtls\schannel_verify.c" />
@@ -272,6 +273,7 @@
<ClInclude Include="curl\lib\cookie.h" />
<ClInclude Include="curl\lib\cshutdn.h" />
<ClInclude Include="curl\lib\curlx\base64.h" />
<ClInclude Include="curl\lib\curlx\basename.h" />
<ClInclude Include="curl\lib\curlx\binmode.h" />
<ClInclude Include="curl\lib\curlx\curlx.h" />
<ClInclude Include="curl\lib\curlx\dynbuf.h" />
@@ -280,6 +282,9 @@
<ClInclude Include="curl\lib\curlx\inet_pton.h" />
<ClInclude Include="curl\lib\curlx\multibyte.h" />
<ClInclude Include="curl\lib\curlx\nonblock.h" />
<ClInclude Include="curl\lib\curlx\snprintf.h" />
<ClInclude Include="curl\lib\curlx\strcopy.h" />
<ClInclude Include="curl\lib\curlx\strdup.h" />
<ClInclude Include="curl\lib\curlx\strerr.h" />
<ClInclude Include="curl\lib\curlx\strparse.h" />
<ClInclude Include="curl\lib\curlx\timediff.h" />
@@ -300,9 +305,7 @@
<ClInclude Include="curl\lib\curl_ldap.h" />
<ClInclude Include="curl\lib\curl_md4.h" />
<ClInclude Include="curl\lib\curl_md5.h" />
<ClInclude Include="curl\lib\curl_memory.h" />
<ClInclude Include="curl\lib\curl_memrchr.h" />
<ClInclude Include="curl\lib\curl_mem_undef.h" />
<ClInclude Include="curl\lib\curl_ntlm_core.h" />
<ClInclude Include="curl\lib\curl_printf.h" />
<ClInclude Include="curl\lib\curl_range.h" />
@@ -312,6 +315,7 @@
<ClInclude Include="curl\lib\curl_setup_once.h" />
<ClInclude Include="curl\lib\curl_sha256.h" />
<ClInclude Include="curl\lib\curl_sha512_256.h" />
<ClInclude Include="curl\lib\curl_share.h" />
<ClInclude Include="curl\lib\curl_sspi.h" />
<ClInclude Include="curl\lib\curl_threads.h" />
<ClInclude Include="curl\lib\curl_trc.h" />
@@ -352,7 +356,6 @@
<ClInclude Include="curl\lib\imap.h" />
<ClInclude Include="curl\lib\llist.h" />
<ClInclude Include="curl\lib\macos.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" />
@@ -367,7 +370,7 @@
<ClInclude Include="curl\lib\progress.h" />
<ClInclude Include="curl\lib\psl.h" />
<ClInclude Include="curl\lib\rand.h" />
<ClInclude Include="curl\lib\rename.h" />
<ClInclude Include="curl\lib\ratelimit.h" />
<ClInclude Include="curl\lib\request.h" />
<ClInclude Include="curl\lib\rtsp.h" />
<ClInclude Include="curl\lib\select.h" />
@@ -376,7 +379,6 @@
<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" />
<ClInclude Include="curl\lib\smb.h" />
@@ -384,7 +386,6 @@
<ClInclude Include="curl\lib\sockaddr.h" />
<ClInclude Include="curl\lib\socketpair.h" />
<ClInclude Include="curl\lib\socks.h" />
<ClInclude Include="curl\lib\speedcheck.h" />
<ClInclude Include="curl\lib\splay.h" />
<ClInclude Include="curl\lib\strcase.h" />
<ClInclude Include="curl\lib\strdup.h" />
@@ -405,6 +406,7 @@
<ClInclude Include="curl\lib\vquic\curl_ngtcp2.h" />
<ClInclude Include="curl\lib\vquic\curl_quiche.h" />
<ClInclude Include="curl\lib\vquic\vquic_int.h" />
<ClInclude Include="curl\lib\vssh\vssh.h" />
<ClInclude Include="curl\lib\vtls\apple.h" />
<ClInclude Include="curl\lib\vtls\cipher_suite.h" />
<ClInclude Include="curl\lib\vtls\hostcheck.h" />
@@ -418,12 +420,10 @@
<ClInclude Include="curl\lib\vauth\ntlm.h" />
<ClInclude Include="curl\lib\vauth\vauth.h" />
<ClInclude Include="curl\lib\vquic\vquic.h" />
<ClInclude Include="curl\lib\vssh\curl_path.h" />
<ClInclude Include="curl\lib\vssh\ssh.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\openssl.h" />
<ClInclude Include="curl\lib\vtls\schannel.h" />
<ClInclude Include="curl\lib\vtls\vtls.h" />
+42 -42
View File
@@ -204,9 +204,6 @@
<ClCompile Include="curl\lib\rand.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\rename.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\rtsp.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -222,9 +219,6 @@
<ClCompile Include="curl\lib\sha256.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\share.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\slist.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -246,18 +240,12 @@
<ClCompile Include="curl\lib\socks_sspi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\speedcheck.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\splay.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strcase.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strdup.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strerror.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -318,9 +306,6 @@
<ClCompile Include="curl\lib\vauth\vauth.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\curl_path.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\libssh.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -333,9 +318,6 @@
<ClCompile Include="curl\lib\vtls\mbedtls.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vtls\mbedtls_threadlock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vtls\openssl.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -549,6 +531,27 @@
<ClCompile Include="curl\lib\curlx\strerr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\strcopy.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\vssh.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curl_share.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\ratelimit.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\basename.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\snprintf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\strdup.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="curl\include\curl\curl.h">
@@ -653,9 +656,6 @@
<ClInclude Include="curl\lib\curl_md5.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_memrchr.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -758,9 +758,6 @@
<ClInclude Include="curl\lib\llist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\memdebug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\mime.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -791,9 +788,6 @@
<ClInclude Include="curl\lib\rand.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\rename.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\rtsp.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -812,9 +806,6 @@
<ClInclude Include="curl\lib\setup-vms.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\share.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\sigpipe.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -836,9 +827,6 @@
<ClInclude Include="curl\lib\socks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\speedcheck.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\splay.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -887,9 +875,6 @@
<ClInclude Include="curl\lib\vauth\vauth.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\curl_path.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\ssh.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -899,9 +884,6 @@
<ClInclude Include="curl\lib\vtls\mbedtls.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vtls\mbedtls_threadlock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vtls\openssl.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1103,9 +1085,6 @@
<ClInclude Include="curl\lib\cf-ip-happy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_mem_undef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_fopen.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1121,6 +1100,27 @@
<ClInclude Include="curl\lib\curlx\strerr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\snprintf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\strcopy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\vssh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_share.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\ratelimit.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\basename.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\strdup.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="curl\lib\libcurl.rc">
+2
View File
@@ -20,6 +20,8 @@ else()
option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF)
option(protobuf_FORCE_FETCH_DEPENDENCIES "Force all dependencies to be downloaded from GitHub. Local installations will be ignored." OFF)
option(protobuf_LOCAL_DEPENDENCIES_ONLY "Prevent downloading any dependencies from GitHub. If this option is set, the dependency must be available locally as an installed package." OFF)
option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" OFF)
add_subdirectory(protobuf EXCLUDE_FROM_ALL)
target_include_directories(3rdparty_protobuf SYSTEM INTERFACE protobuf/src)
+10 -3
View File
@@ -6,15 +6,22 @@ find_package(Qt6 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia M
if(WIN32)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
else()
set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui GuiPrivate)
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui)
if(Qt6_VERSION VERSION_GREATER_EQUAL "6.10.0")
set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 ${QT_MIN_VER} COMPONENTS GuiPrivate)
endif()
if(Qt6DBus_FOUND)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS)
else()
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
endif()
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
if(Qt6_VERSION VERSION_GREATER_EQUAL "6.10.0")
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
else()
target_include_directories(3rdparty_qt6 INTERFACE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
endif()
endif()
if(Qt6Widgets_FOUND)
+2 -1
View File
@@ -6,7 +6,8 @@ if (USE_SYSTEM_ZLIB)
target_link_libraries(3rdparty_zlib INTERFACE ZLIB::ZLIB)
target_compile_definitions(3rdparty_zlib INTERFACE -DZLIB_CONST=1)
else()
option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" OFF)
option(ZLIB_BUILD_TESTING "Enable Zlib Examples as tests" OFF)
option(ZLIB_BUILD_SHARED "Enable building zlib shared library" OFF)
message(STATUS "RPCS3: Using builtin ZLIB")
set(SKIP_INSTALL_ALL ON)
add_subdirectory(zlib EXCLUDE_FROM_ALL)
+5 -5
View File
@@ -20,26 +20,26 @@ The following tools are required to build RPCS3 on Windows 10 or later:
with standalone **CMake** tool.
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
- [Qt 6.10.2](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Qt 6.11.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.10.2\msvc2022_64\`
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.11.0\msvc2022_64\`
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.10.2\msvc2022_64\`
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.11.0\msvc2022_64\`
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
- Clang 17+ or GCC 13+
- [CMake 3.28.0+](https://www.cmake.org/download/)
- [Qt 6.10.2](https://www.qt.io/download-qt-installer)
- [Qt 6.11.0](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
@@ -123,7 +123,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
##### Configuring the Qt Plugin (if used)
1) go to `Extensions->Qt VS Tools->Qt Versions`
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.10.2\msvc2022_64`, version will fill in automatically
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.11.0\msvc2022_64`, version will fill in automatically
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
+3 -50
View File
@@ -37,7 +37,7 @@ option(USE_LIBEVDEV "libevdev-based joystick support" ON)
option(USE_DISCORD_RPC "Discord rich presence integration" OFF)
option(USE_VULKAN "Vulkan render backend" ON)
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
option(USE_SDL "Enables SDL input handler" OFF)
option(USE_SDL "Enables SDL input handler" ON)
option(USE_SYSTEM_CUBEB "Prefer system cubeb instead of the builtin one" OFF)
option(USE_SYSTEM_CURL "Prefer system Curl instead of the prebuild one" ON)
option(USE_SYSTEM_FAUDIO "Prefer system FAudio instead of the builtin one" OFF)
@@ -86,50 +86,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug" AND NOT MSVC)
endif()
if(MSVC)
option(USE_MSVC_STATIC_CRT "Use static MSVC C runtime" OFF)
# TODO([email protected])
# DiscordRPC binary in 3rdparty is compiled /MT
# So theoretically we should enable DiscordRPC in Release and static CRT build
# since we might encounter some rumtime issues when more than one CRT version are presented.
# https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160#what-problems-exist-if-an-application-uses-more-than-one-crt-version
# Add other DiscordRPC binaries(compiled with /MTd, /MD, /MDd) or compile it from source may address this issue.
if(NOT IS_MULTI_CONFIG)
if(NOT(CMAKE_BUILD_TYPE MATCHES "Release" AND USE_MSVC_STATIC_CRT))
set(USE_DISCORD_RPC OFF CACHE BOOL "Discord RPC is only available in Release and static CRT build." FORCE)
endif()
endif()
if(USE_MSVC_STATIC_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
else()
# though doc ( https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html )
# says if that property is not set then CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL
# to select a MSVC runtime library.
# But yaml-cpp set /MT(d) if CMAKE_MSVC_RUNTIME_LIBRARY is undefined
# So we have to define it explicitly
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
# TODO([email protected])
# offical QT uses dynamic CRT.
# When building our lib with static CRT and debug build type
# and linking with Qt with dynamic CRT and debug build,
# error is encountered in runtime (which is expected).
# But building our lib with static CRT and release build type,
# and linking with Qt with dynamic CRT and release build seems to be working,
# which is the same config with VS solution.
# (though technically it might still have some hidden errors).
# So we allow static CRT in both relase and debug build, but prompt warning in debug build.
# For more info:
# https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160#what-problems-exist-if-an-application-uses-more-than-one-crt-version
# https://wiki.qt.io/Technical_FAQ#Why_does_a_statically_built_Qt_use_the_dynamic_Visual_Studio_runtime_libraries_.3F_Do_I_need_to_deploy_those_with_my_application_.3F
if(USE_MSVC_STATIC_CRT)
if(IS_MULTI_CONFIG OR CMAKE_BUILD_TYPE MATCHES "Debug")
message(AUTHOR_WARNING "Debug build currently can not work with static CRT.")
endif()
endif()
add_compile_options(/MP)
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:/MP>")
endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -142,7 +99,7 @@ if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
endif()
if(MSVC)
add_compile_options(/wd4530 /utf-8) # C++ exception handler used, but unwind semantics are not enabled
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:/wd4530;/utf-8>") # C++ exception handler used, but unwind semantics are not enabled
endif()
add_subdirectory(3rdparty)
@@ -161,10 +118,6 @@ if (NOT FOUND_LTO EQUAL -1)
message(FATAL_ERROR "RPCS3 doesn't support building with LTO, use -DDISABLE_LTO=TRUE to force-disable it")
endif()
if(NOT WIN32)
add_compile_options(-pthread)
endif()
## Look for Gamemode if its installed on Linux
if(LINUX)
## User chooses whether to Enable GameMode features or not
+22 -1
View File
@@ -362,6 +362,27 @@ std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::
return result;
}
size_t cfg::try_to_enum_size(decltype(&fmt_class_string<int>::format) func)
{
size_t result = 0;
for (u64 i = 0;; i++)
{
std::string var;
func(var, i);
std::string hex;
fmt_class_string<u64>::format(hex, i);
if (var == hex)
{
break;
}
result++;
}
return result;
}
void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
{
switch (rhs.get_type())
@@ -416,7 +437,7 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
out << YAML::BeginMap;
for (const auto& np : static_cast<const log_entry&>(rhs).get_map())
{
if (np.second == logs::level::notice) continue;
if (np.second == logs::level::_default) continue;
out << YAML::Key << np.first;
out << YAML::Value << fmt::format("%s", np.second);
}
+11 -3
View File
@@ -30,6 +30,9 @@ namespace cfg
// Internal hack
std::vector<std::string> try_to_enum_list(decltype(&fmt_class_string<int>::format) func);
// Internal hack
size_t try_to_enum_size(decltype(&fmt_class_string<int>::format) func);
// Config tree entry type.
enum class type : unsigned
{
@@ -312,6 +315,11 @@ namespace cfg
{
return try_to_enum_list(&fmt_class_string<T>::format);
}
size_t size() const
{
return try_to_enum_size(&fmt_class_string<T>::format);
}
};
// Signed 32/64-bit integer entry with custom Min/Max range.
@@ -385,7 +393,7 @@ namespace cfg
void set(const s64& value)
{
ensure(value >= Min && value <= Max);
if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast<int_type>(value);
}
@@ -476,7 +484,7 @@ namespace cfg
void set(const f64& value)
{
ensure(value >= Min && value <= Max);
if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast<float_type>(value);
}
@@ -563,7 +571,7 @@ namespace cfg
void set(const u64& value)
{
ensure(value >= Min && value <= Max);
if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast<int_type>(value);
}
+4 -4
View File
@@ -16,12 +16,12 @@
#include <errno.h>
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996)
#elif defined(__clang__)
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+93 -19
View File
@@ -14,6 +14,11 @@
#include "Emu/CPU/Backends/AArch64/AArch64Signal.h"
#endif
#ifdef __cpp_lib_stacktrace
#include "rpcs3_version.h"
#include <stacktrace>
#endif
#ifdef _WIN32
#include <Windows.h>
#include <Psapi.h>
@@ -102,7 +107,7 @@ thread_local u64 g_tls_fault_rsx = 0;
thread_local u64 g_tls_fault_spu = 0;
thread_local u64 g_tls_wait_time = 0;
thread_local u64 g_tls_wait_fail = 0;
thread_local bool g_tls_access_violation_recovered = false;
thread_local u64 g_tls_access_violation_recovered = umax;
extern thread_local std::string(*g_tls_log_prefix)();
namespace stx
@@ -1264,7 +1269,7 @@ namespace rsx
extern std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
}
bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noexcept
bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t* context) noexcept
{
g_tls_fault_all++;
@@ -1300,7 +1305,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
}
} spu_protection{cpu};
if (addr < RAW_SPU_BASE_ADDR && vm::check_addr(addr) && rsx::g_access_violation_handler)
if (!is_exec && addr < RAW_SPU_BASE_ADDR && vm::check_addr(addr) && rsx::g_access_violation_handler)
{
bool state_changed = false;
@@ -1366,7 +1371,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
{
auto thread = idm::get_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET));
if (!thread)
if (!thread || is_exec)
{
break;
}
@@ -1498,7 +1503,9 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
static_cast<void>(context);
#endif /* ARCH_ */
if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
const auto required_page_perms = (is_writing ? vm::page_writable : vm::page_readable) + (is_exec ? vm::page_executable : 0);
if (vm::check_addr(addr, required_page_perms))
{
return true;
}
@@ -1506,9 +1513,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
// Hack: allocate memory in case the emulator is stopping
const auto hack_alloc = [&]()
{
g_tls_access_violation_recovered = true;
if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
if (vm::check_addr(addr, required_page_perms))
{
return true;
}
@@ -1520,17 +1525,45 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
return false;
}
extern void ppu_register_range(u32 addr, u32 size);
bool reprotected = false;
if (vm::writer_lock mlock; area->flags & vm::preallocated || vm::check_addr(addr, 0))
{
// For allocated memory with protection lower than required (such as protection::no or read-only while writing to it)
utils::memory_protect(vm::base(addr & -0x1000), 0x1000, utils::protection::rw);
reprotected = true;
}
if (reprotected)
{
if (is_exec && !vm::check_addr(addr, vm::page_executable))
{
ppu_register_range(addr & -0x10000, 0x10000);
}
g_tls_access_violation_recovered = addr;
return true;
}
return area->falloc(addr & -0x10000, 0x10000) || vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable);
const bool allocated = area->falloc(addr & -0x10000, 0x10000);
if (allocated)
{
if (is_exec && !vm::check_addr(addr, vm::page_executable))
{
ppu_register_range(addr & -0x10000, 0x10000);
}
g_tls_access_violation_recovered = addr;
return true;
}
return false;
};
if (cpu && (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu))
if (cpu && (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu) && !is_exec)
{
vm::temporary_unlock(*cpu);
u32 pf_port_id = 0;
@@ -1673,7 +1706,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
if (cpu->get_class() == thread_class::spu)
{
if (!g_tls_access_violation_recovered)
if (g_tls_access_violation_recovered != addr)
{
vm_log.notice("\n%s", dump_useful_thread_info());
vm_log.always()("[%s] Access violation %s location 0x%x (%s)", cpu->get_name(), is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
@@ -1709,10 +1742,10 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
// Note: a thread may access violate more than once after hack_alloc recovery
// Do not log any further access violations in this case.
if (!g_tls_access_violation_recovered)
if (g_tls_access_violation_recovered != addr)
{
vm_log.notice("\n%s", dump_useful_thread_info());
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (cpu && cpu->get_class() == thread_class::ppu && cpu->get_pc() == addr ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (is_exec ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
}
while (Emu.IsPausedOrReady())
@@ -1761,8 +1794,13 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
}
}
if (Emu.IsStopped() && !hack_alloc())
if (Emu.IsStopped())
{
while (!hack_alloc())
{
thread_ctrl::wait_for(1000);
}
return false;
}
@@ -1801,6 +1839,7 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && !is_executing)
{
u32 addr = 0;
bool is_exec = false;
if (auto [addr0, ok] = vm::try_get_addr(ptr); ok)
{
@@ -1808,14 +1847,21 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
}
else if (const usz exec64 = (ptr - vm::g_exec_addr) / 2; exec64 <= u32{umax})
{
is_exec = true;
addr = static_cast<u32>(exec64);
}
else
else if (const usz exec64 = (ptr - vm::g_exec_addr - vm::g_exec_addr_seg_offset); exec64 <= u32{umax})
{
is_exec = true;
addr = static_cast<u32>(exec64);
}
else
{
std::this_thread::sleep_for(1ms);
return EXCEPTION_CONTINUE_SEARCH;
}
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, pExp->ContextRecord))
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, is_exec, pExp->ContextRecord))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
@@ -2022,12 +2068,13 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
#endif
const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const u64 exec64_2 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) - vm::g_exec_addr_seg_offset;
const auto cause = is_executing ? "executing" : is_writing ? "writing" : "reading";
if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok && !is_executing)
{
// Try to process access violation
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, context))
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, false, context))
{
return;
}
@@ -2035,7 +2082,14 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
if (exec64 < 0x100000000ull && !is_executing)
{
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(exec64), is_writing, context))
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(exec64), is_writing, true, context))
{
return;
}
}
else if (exec64_2 < 0x100000000ull && !is_executing)
{
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(exec64_2), is_writing, true, context))
{
return;
}
@@ -2354,7 +2408,7 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
g_tls_fault_spu = 0;
g_tls_wait_time = 0;
g_tls_wait_fail = 0;
g_tls_access_violation_recovered = false;
g_tls_access_violation_recovered = umax;
g_tls_log_prefix = []() -> std::string { return {}; };
@@ -2800,6 +2854,16 @@ void thread_base::exec()
[[noreturn]] void thread_ctrl::emergency_exit(std::string_view reason)
{
// Print stacktrace
#ifdef __cpp_lib_stacktrace
if (rpcs3::is_local_build())
{
std::ostringstream oss;
oss << std::stacktrace::current();
sys_log.notice("StackTrace\n\n%s\n", oss.str());
}
#endif
if (const std::string info = dump_useful_thread_info(); !info.empty())
{
sys_log.notice("\n%s", info);
@@ -2815,6 +2879,16 @@ void thread_base::exec()
}
}
if (auto [total, current] = utils::get_memory_usage(); total - current <= 256 * 1024 * 1024)
{
if (reason_buf.empty())
{
reason_buf = std::string{reason};
}
fmt::append(reason_buf, " (Possible RAM deficiency: free RAM: %dMB)", (total - current) / (1024 * 1024));
}
if (!reason_buf.empty())
{
reason = reason_buf;
-4
View File
@@ -37,10 +37,6 @@ QSlider#sizeSlider::handle:horizontal {
QLabel#toolbar_icon_color {
color: rgba(64,64,64,255);
}
/* thumbnail icon color stylesheet */
QLabel#thumbnail_icon_color {
color: rgba(0,100,231,255);
}
/* gamelist icon color stylesheet */
QLabel#gamelist_icon_background_color {
color: rgba(209,209,209,255);
@@ -237,11 +237,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #262626;
}
/* Set Log colors */
QPlainTextEdit#log_frame {
background-color: #000; /* Black */
-5
View File
@@ -573,11 +573,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #23262d;
}
/* Log colors */
QPlainTextEdit#log_frame {
background-color: #23262d;
-5
View File
@@ -265,11 +265,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #444444;
}
/* Memory Viewer */
QLabel#memory_viewer_address_panel {
color: #00cbff; /* Font Color: Blue */
@@ -244,11 +244,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #262626;
}
/* Set Log colors */
QPlainTextEdit#log_frame {
background-color: #181d24; /* Black */
@@ -397,12 +397,6 @@ QLabel#gamelist_icon_background_color {
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #ffd785;
}
QLabel#log_level_always {
color: #00ffff; /* Cyan */
}
-5
View File
@@ -656,11 +656,6 @@ QLabel#color_button {
background: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #370048;
}
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000; /* Font Color: Black */
-5
View File
@@ -664,11 +664,6 @@ QLabel#color_button {
background: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #8500ae;
}
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000; /* Font Color: Black */
-5
View File
@@ -379,11 +379,6 @@ 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 */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

-5
View File
@@ -96,11 +96,6 @@ else()
# This hides our LLVM from mesa's LLVM, otherwise we get some unresolvable conflicts.
add_link_options(-Wl,--exclude-libs,ALL)
elseif(WIN32)
add_compile_definitions(__STDC_FORMAT_MACROS=1)
# Workaround for mingw64 (MSYS2)
add_link_options(-Wl,--allow-multiple-definition)
# Increase stack limit to 8 MB
add_link_options(-Wl,--stack -Wl,8388608)
endif()
+2 -3
View File
@@ -1,4 +1,3 @@
set(WOLFSSL_LIBRARY ON)
set(WOLFSSL_INCLUDE_DIR ON)
set(WOLFSSL_LIBRARIES wolfssl)
set(WOLFSSL_LIBRARY wolfssl)
set(WOLFSSL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/wolfssl)
set(WOLFSSL_FOUND TRUE)
+2 -2
View File
@@ -3,9 +3,9 @@ if(USE_SYSTEM_ZLIB)
find_package(ZLIB)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
else()
add_library(ZLIB::ZLIB INTERFACE IMPORTED)
add_library(ZLIB::ZLIB STATIC IMPORTED)
set_target_properties(ZLIB::ZLIB PROPERTIES
INTERFACE_LINK_LIBRARIES zlibstatic
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/3rdparty/zlib/zlib/libzlibstatic.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/zlib/zlib;${CMAKE_BINARY_DIR}/3rdparty/zlib/zlib")
set(ZLIB_FOUND TRUE)
endif()
+2 -6
View File
@@ -87,12 +87,6 @@ if (NOT ANDROID)
message(FATAL_ERROR "RPCS3 requires either X11 or Wayland (or both) for Vulkan.")
endif()
if(UNIX)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
target_link_libraries(rpcs3_lib PRIVATE Threads::Threads)
endif()
if(WIN32)
target_link_libraries(rpcs3_lib PRIVATE ws2_32 Iphlpapi Winmm Psapi gdi32 setupapi)
else()
@@ -195,6 +189,7 @@ if(BUILD_RPCS3_TESTS)
tests/test_address_range.cpp
tests/test_rsx_cfg.cpp
tests/test_rsx_fp_asm.cpp
tests/test_dmux_pamf.cpp
)
target_link_libraries(rpcs3_test
@@ -202,6 +197,7 @@ if(BUILD_RPCS3_TESTS)
rpcs3_lib
rpcs3_emu
GTest::gtest
GTest::gmock
)
target_include_directories(rpcs3_test
+9
View File
@@ -487,6 +487,7 @@ target_sources(rpcs3_emu PRIVATE
RSX/NV47/HW/nv406e.cpp
RSX/NV47/HW/nv4097.cpp
RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp
RSX/Overlays/HomeMenu/overlay_home_icons.cpp
RSX/Overlays/HomeMenu/overlay_home_menu.cpp
RSX/Overlays/HomeMenu/overlay_home_menu_components.cpp
RSX/Overlays/HomeMenu/overlay_home_menu_main_menu.cpp
@@ -500,6 +501,8 @@ target_sources(rpcs3_emu PRIVATE
RSX/Overlays/overlays.cpp
RSX/Overlays/overlay_animated_icon.cpp
RSX/Overlays/overlay_animation.cpp
RSX/Overlays/overlay_audio.cpp
RSX/Overlays/overlay_checkbox.cpp
RSX/Overlays/overlay_compile_notification.cpp
RSX/Overlays/overlay_controls.cpp
RSX/Overlays/overlay_cursor.cpp
@@ -516,6 +519,9 @@ target_sources(rpcs3_emu PRIVATE
RSX/Overlays/overlay_perf_metrics.cpp
RSX/Overlays/overlay_progress_bar.cpp
RSX/Overlays/overlay_save_dialog.cpp
RSX/Overlays/overlay_select.cpp
RSX/Overlays/overlay_slider.cpp
RSX/Overlays/overlay_tabs.cpp
RSX/Overlays/overlay_trophy_notification.cpp
RSX/Overlays/overlay_user_list_dialog.cpp
RSX/Overlays/overlay_utils.cpp
@@ -639,6 +645,9 @@ if(TARGET 3rdparty_vulkan)
endif()
endif()
if(NOT WIN32)
set(THREADS_PREFER_PTHREAD_FLAG ON)
endif()
find_package(Threads REQUIRED)
target_link_libraries(rpcs3_emu
@@ -20,19 +20,19 @@ namespace aarch64
sp
};
static const char* gpr_names[] =
[[maybe_unused]] static const char* gpr_names[] =
{
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19",
"x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30"
};
static const char* spr_names[] =
[[maybe_unused]] static const char* spr_names[] =
{
"xzr", "pc", "sp"
};
static const char* spr_asm_names[] =
[[maybe_unused]] static const char* spr_asm_names[] =
{
"xzr", ".", "sp"
};
+14 -5
View File
@@ -888,6 +888,14 @@ bool cpu_thread::check_state() noexcept
store = true;
}
if (flags & cpu_flag::req_exit)
{
// A request for the thread to quit has been made
flags -= cpu_flag::req_exit;
flags += cpu_flag::exit;
store = true;
}
// Can't process dbg_step if we only paused temporarily
if (cpu_can_stop && flags & cpu_flag::dbg_step)
{
@@ -1157,13 +1165,13 @@ void cpu_thread::notify()
cpu_thread& cpu_thread::operator=(thread_state)
{
if (state & cpu_flag::exit)
if (state & (cpu_flag::exit + cpu_flag::req_exit))
{
// Must be notified elsewhere or self-raised
return *this;
}
const auto old = state.fetch_add(cpu_flag::exit);
const auto old = state.fetch_add(cpu_flag::req_exit);
if (old & cpu_flag::wait && old.none_of(cpu_flag::again + cpu_flag::exit))
{
@@ -1322,8 +1330,9 @@ extern std::shared_ptr<CPUDisAsm> make_disasm(const cpu_thread* cpu, shared_ptr<
void cpu_thread::dump_all(std::string& ret) const
{
std::any func_data;
std::any misc_data;
ret += dump_misc();
dump_misc(ret, misc_data);
ret += '\n';
dump_regs(ret, func_data);
ret += '\n';
@@ -1371,9 +1380,9 @@ std::vector<std::pair<u32, u32>> cpu_thread::dump_callstack_list() const
return {};
}
std::string cpu_thread::dump_misc() const
void cpu_thread::dump_misc(std::string& ret, std::any& /*custom_data*/) const
{
return fmt::format("Type: %s; State: %s\n", get_class() == thread_class::ppu ? "PPU" : get_class() == thread_class::spu ? "SPU" : "RSX", state.load());
fmt::append(ret, "%s[0x%x]; State: %s\n", get_class() == thread_class::ppu ? "PPU" : get_class() == thread_class::spu ? "SPU" : "RSX", id, state.load());
}
bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
+3 -2
View File
@@ -29,6 +29,7 @@ enum class cpu_flag : u32
yield, // Thread is being requested to yield its execution time if it's running
preempt, // Thread is being requested to preempt the execution of all CPU threads
req_exit, // Request the thread to exit
dbg_global_pause, // Emulation paused
dbg_pause, // Thread paused
dbg_step, // Thread forced to pause after one step (one instruction, etc)
@@ -39,7 +40,7 @@ enum class cpu_flag : u32
// Test stopped state
constexpr bool is_stopped(bs_t<cpu_flag> state)
{
return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::again));
return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::again + cpu_flag::req_exit));
}
// Test paused state
@@ -176,7 +177,7 @@ public:
virtual std::vector<std::pair<u32, u32>> dump_callstack_list() const;
// Get CPU dump of misc information
virtual std::string dump_misc() const;
virtual void dump_misc(std::string& ret, std::any& /*custom_data*/) const;
// Thread entry point function
virtual void cpu_task() = 0;
+63 -2
View File
@@ -201,6 +201,13 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
m_use_vnni = true;
m_use_gfni = true;
}
#ifdef ARCH_ARM64
if (utils::has_dotprod())
{
m_use_dotprod = true;
}
#endif
}
llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
@@ -218,12 +225,66 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)", s1, s2);
}
if (const auto c1 = llvm::dyn_cast<llvm::Constant>(val))
if (val->getType() == type)
{
return val;
}
llvm::CastInst* i;
llvm::Value* source_val = val;
// Try to reuse older bitcasts
while ((i = llvm::dyn_cast_or_null<llvm::CastInst>(source_val)) && i->getOpcode() == llvm::Instruction::BitCast)
{
source_val = i->getOperand(0);
if (source_val->getType() == type)
{
return source_val;
}
}
for (auto it = source_val->use_begin(); it != source_val->use_end(); ++it)
{
llvm::Value* it_val = *it;
if (!it_val)
{
continue;
}
llvm::CastInst* bci = llvm::dyn_cast_or_null<llvm::CastInst>(it_val);
// Walk through bitcasts
while (bci && bci->getOpcode() == llvm::Instruction::BitCast)
{
if (bci->getParent() != m_ir->GetInsertBlock())
{
break;
}
if (bci->getType() == type)
{
return bci;
}
if (bci->use_begin() == bci->use_end())
{
break;
}
bci = llvm::dyn_cast_or_null<llvm::CastInst>(*bci->use_begin());
}
}
// Do bitcast on the source
if (const auto c1 = llvm::dyn_cast<llvm::Constant>(source_val))
{
return ensure(llvm::ConstantFoldCastOperand(llvm::Instruction::BitCast, c1, type, m_module->getDataLayout()));
}
return m_ir->CreateBitCast(val, type);
return m_ir->CreateBitCast(source_val, type);
}
template <>
+93
View File
@@ -567,6 +567,32 @@ struct llvm_placeholder_t
}
};
template <typename T, typename U = llvm_common_t<llvm_value_t<T>>>
struct llvm_place_stealer_t
{
// TODO: placeholder extracting actual constant values (u64, f64, vector, etc)
using type = T;
static constexpr bool is_ok = true;
llvm::Value* eval(llvm::IRBuilder<>*) const
{
return nullptr;
}
std::tuple<> match(llvm::Value*& value, llvm::Module*) const
{
if (value && value->getType() == llvm_value_t<T>::get_type(value->getContext()))
{
return {};
}
value = nullptr;
return {};
}
};
template <typename T, bool ForceSigned = false>
struct llvm_const_int
{
@@ -3090,6 +3116,9 @@ protected:
// For now, setting this flag will speed up SPU verification
// but I will remove this later with explicit parralelism - Whatcookie
bool m_use_avx = true;
// ARMv8 SDOT/UDOT
bool m_use_dotprod = false;
#else
// Allow FMA
bool m_use_fma = false;
@@ -3224,6 +3253,12 @@ public:
return {};
}
template <typename T>
static llvm_place_stealer_t<T> match_stealer()
{
return {};
}
template <typename T>
requires requires { typename llvm_common_t<T>; }
static auto match_expr(llvm::Value* v, llvm::Module* _m, T&& expr)
@@ -3647,10 +3682,59 @@ public:
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
#if LLVM_VERSION_MAJOR >= 22
// LLVM 22+ changed the intrinsic signature from v4i32 to v16i8 for operands 2 and 3
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpdpbusd_128),
{data0, m_ir->CreateBitCast(data1, get_type<u8[16]>()), m_ir->CreateBitCast(data2, get_type<u8[16]>())});
#else
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpdpbusd_128), {data0, data1, data2});
#endif
return result;
}
#ifdef ARCH_ARM64
template <typename T1, typename T2, typename T3>
value_t<u32[4]> udot(T1 a, T2 b, T3 c)
{
value_t<u32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_udot), {data0, data1, data2});
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u32[4]> sdot(T1 a, T2 b, T3 c)
{
value_t<u32[4]> result;
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
result.value = m_ir->CreateCall(get_intrinsic<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_sdot), {data0, data1, data2});
return result;
}
template <typename T1, typename T2>
auto addp(T1 a, T2 b)
{
using T_vector = typename is_llvm_expr<T1>::type;
const auto data1 = a.eval(m_ir);
const auto data2 = b.eval(m_ir);
const auto func = get_intrinsic<T_vector>(llvm::Intrinsic::aarch64_neon_addp);
value_t<T_vector> result;
result.value = m_ir->CreateCall(func, {data1, data2});
return result;
}
#endif
template <typename T1, typename T2>
value_t<u8[16]> vpermb(T1 a, T2 b)
{
@@ -3899,6 +3983,15 @@ public:
erase_stores({args.value...});
}
// Debug breakpoint
void debugtrap()
{
const auto _rty = llvm::Type::getVoidTy(m_context);
const auto type = llvm::FunctionType::get(_rty, {}, false);
const auto func = llvm::cast<llvm::Function>(m_ir->GetInsertBlock()->getParent()->getParent()->getOrInsertFunction("llvm.debugtrap", type).getCallee());
m_ir->CreateCall(func);
}
template <typename T, typename U>
static auto pshufb(T&& a, U&& b)
{
+54 -54
View File
@@ -261,7 +261,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::waiting_for_output_mutex_lock;
output_mutex_lock:
error_occurred |= static_cast<u32>(sys_mutex_lock(ppu, output_mutex, 0) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_lock>(ppu, output_mutex, 0) != CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -273,7 +273,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::waiting_for_output_cond_wait;
output_cond_wait:
ensure(sys_cond_wait(ppu, output_consumed, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_cond_wait>(ppu, output_consumed, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again)
{
@@ -287,7 +287,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::queue_mutex_lock;
queue_mutex_lock:
ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, queue_mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again)
{
@@ -296,7 +296,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
cmd_queue.pop(cmd);
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK); // Error code isn't checked on LLE
cellAdec.trace("Command type: %d", static_cast<u32>(cmd.type.get()));
@@ -307,7 +307,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
{
case LpcmDecCmdType::start_seq:
// LLE sends a command to the SPU thread. The SPU thread consumes the command without doing anything, however
error_occurred |= static_cast<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) != CELL_OK);
break;
case LpcmDecCmdType::end_seq:
@@ -324,11 +324,11 @@ void LpcmDecContext::exec(ppu_thread& ppu)
// Doesn't do anything else
notify_seq_done.cbFunc(ppu, notify_seq_done.cbArg);
error_occurred |= static_cast<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) != CELL_OK);
break;
}
case LpcmDecCmdType::close:
ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) == CELL_OK); // Error code isn't checked on LLE
return;
case LpcmDecCmdType::decode_au:
@@ -685,7 +685,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
notify_au_done.cbFunc(ppu, cmd.pcm_handle, notify_au_done.cbArg);
output_locked = true;
error_occurred |= static_cast<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) != CELL_OK);
const vm::var<CellAdecLpcmInfo> bsi_info{{ lpcm_param->channelNumber, lpcm_param->sampleRate, static_cast<u32>(output_size) }};
@@ -703,14 +703,14 @@ error_code LpcmDecContext::send_command(ppu_thread& ppu, auto&&... args)
{
ppu.state += cpu_flag::wait;
if (error_code ret = sys_mutex_lock(ppu, queue_size_mutex, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, queue_size_mutex, 0); ret != CELL_OK)
{
return ret;
}
if (cmd_queue.full())
{
ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_BUSY;
}
@@ -720,39 +720,39 @@ error_code LpcmDecContext::send_command(ppu_thread& ppu, auto&&... args)
*lpcm_param = { args... };
}
if (error_code ret = sys_mutex_lock(ppu, queue_mutex, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, queue_mutex, 0); ret != CELL_OK)
{
ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
cmd_queue.emplace(type, std::forward<decltype(args)>(args)...);
if (error_code ret = sys_mutex_unlock(ppu, queue_mutex); ret != CELL_OK
if (error_code ret = lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex); ret != CELL_OK
|| (ret = cmd_available.release(ppu)) != CELL_OK)
{
ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
return sys_mutex_unlock(ppu, queue_size_mutex);
return lv2_syscall<sys_mutex_unlock>(ppu, queue_size_mutex);
}
inline error_code LpcmDecContext::release_output(ppu_thread& ppu)
{
if (error_code ret = sys_mutex_lock(ppu, output_mutex, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, output_mutex, 0); ret != CELL_OK)
{
return ret;
}
output_locked = false;
if (error_code ret = sys_cond_signal(ppu, output_consumed); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_cond_signal>(ppu, output_consumed); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
return sys_mutex_unlock(ppu, output_mutex);
return lv2_syscall<sys_mutex_unlock>(ppu, output_mutex);
}
void lpcmDecEntry(ppu_thread& ppu, vm::ptr<LpcmDecContext> lpcm_dec)
@@ -820,13 +820,13 @@ error_code _CellAdecCoreOpOpenExt_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext>
const vm::var<sys_mutex_attribute_t> queue_mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem06"_u64 } }};
const vm::var<sys_cond_attribute_t> cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec03"_u64 } }};
error_code ret = sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::queue_size_mutex), mutex_attr);
ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::queue_size_cond), handle->queue_size_mutex, cond_attr);
ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::unk_mutex), mutex_attr);
ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::unk_cond), handle->unk_mutex, cond_attr);
ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::output_mutex), output_mutex_attr);
ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::output_consumed), handle->output_mutex, cond_attr);
ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::queue_mutex), queue_mutex_attr);
error_code ret = lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::queue_size_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::queue_size_cond), handle->queue_size_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::unk_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::unk_cond), handle->unk_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::output_mutex), output_mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::output_consumed), handle->output_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::queue_mutex), queue_mutex_attr);
ret = ret ? ret : handle->release_output(ppu);
ret = ret ? ret : handle->cmd_available.init(ppu, handle.ptr(&LpcmDecContext::cmd_available), 0);
ret = ret ? ret : handle->reserved2.init(ppu, handle.ptr(&LpcmDecContext::reserved2), 0);
@@ -844,8 +844,8 @@ error_code _CellAdecCoreOpOpenExt_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext>
const auto entry = g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(lpcmDecEntry));
ret = ppu_execute<&sys_ppu_thread_create>(ppu, handle.ptr(&LpcmDecContext::thread_id), entry, handle.addr(), +res->ppuThreadPriority, +res->ppuThreadStackSize, SYS_PPU_THREAD_CREATE_JOINABLE, +_name);
ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::spurs_queue_pop_mutex), mutex_attr);
ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::spurs_queue_push_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::spurs_queue_pop_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::spurs_queue_push_mutex), mutex_attr);
return ret;
}
@@ -865,8 +865,8 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext> ha
cellAdec.notice("_CellAdecCoreOpClose_lpcm(handle=*0x%x)", handle);
if (error_code ret = sys_mutex_lock(ppu, handle->queue_size_mutex, 0); ret != CELL_OK
|| (ret = sys_mutex_lock(ppu, handle->queue_mutex, 0)) != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, handle->queue_size_mutex, 0); ret != CELL_OK
|| (ret = lv2_syscall<sys_mutex_lock>(ppu, handle->queue_mutex, 0)) != CELL_OK)
{
return ret;
}
@@ -875,14 +875,14 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext> ha
{
handle->cmd_queue.emplace(LpcmDecCmdType::close);
if (error_code ret = sys_mutex_unlock(ppu, handle->queue_mutex); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_unlock>(ppu, handle->queue_mutex); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the queue size mutex
}
if (error_code ret = handle->cmd_available.release(ppu); ret != CELL_OK)
{
ensure(sys_mutex_unlock(ppu, handle->queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
}
@@ -893,29 +893,29 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext> ha
cmd.type = LpcmDecCmdType::close;
}
if (error_code ret = sys_mutex_unlock(ppu, handle->queue_mutex); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_unlock>(ppu, handle->queue_mutex); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the queue size mutex
}
}
error_code ret = sys_mutex_unlock(ppu, handle->queue_size_mutex);
error_code ret = lv2_syscall<sys_mutex_unlock>(ppu, handle->queue_size_mutex);
ret = ret ? ret : handle->release_output(ppu);
vm::var<u64> thread_ret;
ret = ret ? ret : sys_ppu_thread_join(ppu, static_cast<u32>(handle->thread_id), +thread_ret);
ret = ret ? ret : lv2_syscall<sys_ppu_thread_join>(ppu, static_cast<u32>(handle->thread_id), +thread_ret);
ret = ret ? ret : sys_cond_destroy(ppu, handle->queue_size_cond);
ret = ret ? ret : sys_cond_destroy(ppu, handle->unk_cond);
ret = ret ? ret : sys_cond_destroy(ppu, handle->output_consumed);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_size_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->unk_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->output_mutex);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->queue_size_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->unk_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->output_consumed);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_size_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->unk_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->output_mutex);
ret = ret ? ret : handle->cmd_available.finalize(ppu);
ret = ret ? ret : handle->reserved2.finalize(ppu);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->spurs_queue_pop_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->spurs_queue_push_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->spurs_queue_pop_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->spurs_queue_push_mutex);
return ret;
}
@@ -1091,11 +1091,11 @@ error_code AdecContext::set_pcm_item(s32 pcm_handle, vm::ptr<void> pcm_addr, u32
error_code AdecContext::link_frame(ppu_thread& ppu, s32 pcm_handle)
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast<s32>(CELL_ADEC_ERROR_FATAL))
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1115,27 +1115,27 @@ error_code AdecContext::link_frame(ppu_thread& ppu, s32 pcm_handle)
}
else
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast<s32>(CELL_ADEC_ERROR_FATAL))
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
if (frames_head == -1 || frames_tail == -1)
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1146,7 +1146,7 @@ error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
{
if (pcm_handle != frames_tail)
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1171,7 +1171,7 @@ error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
frames[prev].next = next;
}
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
@@ -1557,7 +1557,7 @@ error_code adecOpen(ppu_thread& ppu, vm::ptr<CellAdecType> type, vm::cptr<CellAd
frames[i].prev = 0;
}
ensure(sys_mutex_create(ppu, _this.ptr(&AdecContext::mutex), _this.ptr(&AdecContext::mutex_attribute)) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_create>(ppu, _this.ptr(&AdecContext::mutex), _this.ptr(&AdecContext::mutex_attribute)) == CELL_OK); // Error code isn't checked on LLE
*handle = _this;
@@ -1626,7 +1626,7 @@ error_code cellAdecClose(ppu_thread& ppu, vm::ptr<AdecContext> handle)
return ret;
}
if (error_code ret = sys_mutex_destroy(ppu, handle->mutex); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_destroy>(ppu, handle->mutex); ret != CELL_OK)
{
return ret;
}
+35 -22
View File
@@ -485,6 +485,19 @@ struct AdecFrame
CHECK_SIZE(AdecFrame, 0x68);
template <auto Syscall>
static auto lv2_syscall(ppu_thread& ppu, auto&&... args)
{
const auto ret = Syscall(ppu, std::forward<decltype(args)>(args)...);
if (ppu.test_stopped())
{
ppu.state += cpu_flag::again;
}
return ret;
}
class AdecOutputQueue
{
struct entry
@@ -511,10 +524,10 @@ public:
this->size = 0;
const vm::var<sys_mutex_attribute_t> mutex_attr = {{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem07"_u64 } }};
ensure(sys_mutex_create(ppu, _this.ptr(&AdecOutputQueue::mutex), mutex_attr) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_create>(ppu, _this.ptr(&AdecOutputQueue::mutex), mutex_attr) == CELL_OK); // Error code isn't checked on LLE
const vm::var<sys_cond_attribute_t> cond_attr = {{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec05"_u64 } }};
ensure(sys_cond_create(ppu, _this.ptr(&AdecOutputQueue::cond), mutex, cond_attr) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_cond_create>(ppu, _this.ptr(&AdecOutputQueue::cond), mutex, cond_attr) == CELL_OK); // Error code isn't checked on LLE
for (s32 i = 0; i < 4; i++)
{
@@ -524,12 +537,12 @@ public:
error_code finalize(ppu_thread& ppu) const
{
if (error_code ret = sys_cond_destroy(ppu, cond); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_cond_destroy>(ppu, cond); ret != CELL_OK)
{
return ret;
}
if (error_code ret = sys_mutex_destroy(ppu, mutex); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_destroy>(ppu, mutex); ret != CELL_OK)
{
return ret;
}
@@ -539,11 +552,11 @@ public:
error_code push(ppu_thread& ppu, vm::ptr<CellAdecPcmItem> pcm_item, s32 pcm_handle)
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (entries[back].state != 0xff)
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return true; // LLE returns the result of the comparison above
}
@@ -554,13 +567,13 @@ public:
back = (back + 1) & 3;
size++;
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
const entry* pop(ppu_thread& ppu)
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again) // Savestate was created while waiting on the mutex
{
@@ -569,7 +582,7 @@ public:
if (entries[front].state == 0xff)
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return nullptr;
}
@@ -581,15 +594,15 @@ public:
front = (front + 1) & 3;
size--;
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
const entry& peek(ppu_thread& ppu) const
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
const entry& ret = entries[front];
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
};
@@ -708,39 +721,39 @@ public:
const vm::var<sys_mutex_attribute_t> mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem01"_u64 } }};
const vm::var<sys_cond_attribute_t> cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec01"_u64 } }};
if (error_code ret = sys_mutex_create(ppu, _this.ptr(&LpcmDecSemaphore::mutex), mutex_attr); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_create>(ppu, _this.ptr(&LpcmDecSemaphore::mutex), mutex_attr); ret != CELL_OK)
{
return ret;
}
return sys_cond_create(ppu, _this.ptr(&LpcmDecSemaphore::cond), mutex, cond_attr);
return lv2_syscall<sys_cond_create>(ppu, _this.ptr(&LpcmDecSemaphore::cond), mutex, cond_attr);
}
error_code finalize(ppu_thread& ppu) const
{
if (error_code ret = sys_cond_destroy(ppu, cond); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_cond_destroy>(ppu, cond); ret != CELL_OK)
{
return ret;
}
return sys_mutex_destroy(ppu, mutex);
return lv2_syscall<sys_mutex_destroy>(ppu, mutex);
}
error_code release(ppu_thread& ppu)
{
if (error_code ret = sys_mutex_lock(ppu, mutex, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, mutex, 0); ret != CELL_OK)
{
return ret;
}
value++;
if (error_code ret = sys_cond_signal(ppu, cond); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_cond_signal>(ppu, cond); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
return sys_mutex_unlock(ppu, mutex);
return lv2_syscall<sys_mutex_unlock>(ppu, mutex);
}
error_code acquire(ppu_thread& ppu, lpcm_dec_state& savestate)
@@ -752,7 +765,7 @@ public:
savestate = lpcm_dec_state::waiting_for_cmd_mutex_lock;
if (error_code ret = sys_mutex_lock(ppu, mutex, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_lock>(ppu, mutex, 0); ret != CELL_OK)
{
return ret;
}
@@ -767,7 +780,7 @@ public:
savestate = lpcm_dec_state::waiting_for_cmd_cond_wait;
cond_wait:
if (error_code ret = sys_cond_wait(ppu, cond, 0); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_cond_wait>(ppu, cond, 0); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
@@ -780,7 +793,7 @@ public:
value--;
return sys_mutex_unlock(ppu, mutex);
return lv2_syscall<sys_mutex_unlock>(ppu, mutex);
}
};
+43 -43
View File
@@ -295,7 +295,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
{
savestate = atracxdec_state::initial;
ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, queue_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -310,24 +310,24 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::waiting_for_cmd;
label1_wait_for_cmd_state:
ensure(sys_cond_wait(ppu, queue_not_empty, 0) == CELL_OK);
ensure(lv2_syscall<sys_cond_wait>(ppu, queue_not_empty, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
return;
}
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
}
cmd_queue.pop(cmd);
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
savestate = atracxdec_state::checking_run_thread_1;
label2_check_run_thread_1_state:
ensure(sys_mutex_lock(ppu, run_thread_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, run_thread_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -336,11 +336,11 @@ void AtracXdecContext::exec(ppu_thread& ppu)
if (!run_thread)
{
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
return;
}
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
savestate = atracxdec_state::executing_cmd;
label3_execute_cmd_state:
@@ -392,7 +392,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
cellAtracXdec.trace("Waiting for output to be consumed...");
ensure(sys_mutex_lock(ppu, output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, output_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -404,7 +404,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::waiting_for_output;
label4_wait_for_output_state:
ensure(sys_cond_wait(ppu, output_consumed, 0) == CELL_OK);
ensure(lv2_syscall<sys_cond_wait>(ppu, output_consumed, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -417,7 +417,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::checking_run_thread_2;
label5_check_run_thread_2_state:
ensure(sys_mutex_lock(ppu, run_thread_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, run_thread_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -426,12 +426,12 @@ void AtracXdecContext::exec(ppu_thread& ppu)
if (!run_thread)
{
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) == CELL_OK);
return;
}
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
savestate = atracxdec_state::decoding;
label6_decode_state:
@@ -645,7 +645,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
notify_au_done.cbFunc(ppu, cmd.pcm_handle, notify_au_done.cbArg);
output_locked = true;
ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) == CELL_OK);
const u32 output_size = decoded_samples_num * (decoder.bw_pcm & 0x7fu) * decoder.nch_out;
@@ -680,7 +680,7 @@ error_code AtracXdecContext::send_command(ppu_thread& ppu, auto&&... args)
if (!signal)
{
ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, queue_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -692,23 +692,23 @@ error_code AtracXdecContext::send_command(ppu_thread& ppu, auto&&... args)
// Close command is only sent if the queue is empty on LLE
if (!cmd_queue.empty())
{
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
return {};
}
}
if (cmd_queue.full())
{
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
return CELL_ADEC_ERROR_ATX_BUSY;
}
cmd_queue.emplace(std::forward<AtracXdecCmdType>(type), std::forward<decltype(args)>(args)...);
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
}
ensure(sys_cond_signal(ppu, queue_not_empty) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, queue_not_empty) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -779,25 +779,25 @@ error_code _CellAdecCoreOpOpenExt_atracx(ppu_thread& ppu, vm::ptr<AtracXdecConte
const vm::var<sys_mutex_attribute_t> mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_atd001"_u64 } }};
const vm::var<sys_cond_attribute_t> cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_atd002"_u64 } }};
ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::queue_mutex), mutex_attr) == CELL_OK);
ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::queue_not_empty), handle->queue_mutex, cond_attr) == CELL_OK);
ensure(lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::queue_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(ppu, handle.ptr(&AtracXdecContext::queue_not_empty), handle->queue_mutex, cond_attr) == CELL_OK);
mutex_attr->name_u64 = "_atd003"_u64;
cond_attr->name_u64 = "_atd004"_u64;
ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::run_thread_mutex), mutex_attr) == CELL_OK);
ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::run_thread_cond), handle->run_thread_mutex, cond_attr) == CELL_OK);
ensure(lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::run_thread_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(ppu, handle.ptr(&AtracXdecContext::run_thread_cond), handle->run_thread_mutex, cond_attr) == CELL_OK);
mutex_attr->name_u64 = "_atd005"_u64;
cond_attr->name_u64 = "_atd006"_u64;
ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::output_mutex), mutex_attr) == CELL_OK);
ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::output_consumed), handle->output_mutex, cond_attr) == CELL_OK);
ensure(lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::output_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(ppu, handle.ptr(&AtracXdecContext::output_consumed), handle->output_mutex, cond_attr) == CELL_OK);
ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, handle->output_mutex, 0) == CELL_OK);
handle->output_locked = false;
ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
const vm::var<char[]> _name = vm::make_str("HLE ATRAC3plus decoder");
const auto entry = g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(atracXdecEntry));
@@ -829,26 +829,26 @@ error_code _CellAdecCoreOpClose_atracx(ppu_thread& ppu, vm::ptr<AtracXdecContext
ensure(!!handle); // Not checked on LLE
ensure(sys_mutex_lock(ppu, handle->run_thread_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, handle->run_thread_mutex, 0) == CELL_OK);
handle->run_thread = false;
ensure(sys_mutex_unlock(ppu, handle->run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->run_thread_mutex) == CELL_OK);
handle->send_command<AtracXdecCmdType::close>(ppu);
ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, handle->output_mutex, 0) == CELL_OK);
handle->output_locked = false;
ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
vm::var<u64> thread_ret;
ensure(sys_ppu_thread_join(ppu, static_cast<u32>(handle->thread_id), +thread_ret) == CELL_OK);
ensure(lv2_syscall<sys_ppu_thread_join>(ppu, static_cast<u32>(handle->thread_id), +thread_ret) == CELL_OK);
error_code ret = sys_cond_destroy(ppu, handle->queue_not_empty);
ret = ret ? ret : sys_cond_destroy(ppu, handle->run_thread_cond);
ret = ret ? ret : sys_cond_destroy(ppu, handle->output_consumed);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->run_thread_mutex);
ret = ret ? ret : sys_mutex_destroy(ppu, handle->output_mutex);
error_code ret = lv2_syscall<sys_cond_destroy>(ppu, handle->queue_not_empty);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->run_thread_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->output_consumed);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->run_thread_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->output_mutex);
return ret != CELL_OK ? static_cast<error_code>(CELL_ADEC_ERROR_FATAL) : CELL_OK;
}
@@ -921,7 +921,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptr<AtracXdecCo
if (!signal)
{
ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(ppu, handle->output_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -931,7 +931,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptr<AtracXdecCo
handle->output_locked = false;
}
ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -939,7 +939,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptr<AtracXdecCo
return {};
}
ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
return CELL_OK;
}
+5 -5
View File
@@ -919,7 +919,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "dev_num=%d", dev_num };
}
if (g_cfg.io.camera == camera_handler::null)
@@ -935,7 +935,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm
if (!arg1)
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "arg1=null" };
}
if (error_code error = check_resolution(dev_num))
@@ -952,7 +952,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm
if (!attr_name) // invalid attributes don't have a name
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "attrib=0x%x", attrib };
}
if (arg1)
@@ -983,7 +983,7 @@ error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "dev_num=%d", dev_num };
}
if (g_cfg.io.camera == camera_handler::null)
@@ -1004,7 +1004,7 @@ error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
if (!attr_name) // invalid attributes don't have a name
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "attrib=0x%x", attrib };
}
g_camera.set_attr(attrib, arg1, arg2);
+21 -21
View File
@@ -169,18 +169,18 @@ public:
static const u32 id_count = 1023;
SAVESTATE_INIT_POS(34);
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);
ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec);
Demuxer* dmux;
const u32 id = idm::last_id();
const u32 memAddr;
const vm::ptr<void> memAddr;
const u32 memSize;
const u32 fidMajor;
const u32 fidMinor;
const u32 sup1;
const u32 sup2;
const vm::ptr<CellDmuxCbEsMsg> cbFunc;
const u32 cbArg;
const vm::ptr<void> cbArg;
const u32 spec; //addr
std::vector<u8> raw_data; // demultiplexed data stream (managed by demuxer thread)
@@ -208,13 +208,13 @@ public:
const u32 memAddr;
const u32 memSize;
const vm::ptr<CellDmuxCbMsg> cbFunc;
const u32 cbArg;
const vm::ptr<void> cbArg;
volatile bool is_finished = false;
volatile bool is_closed = false;
atomic_t<bool> is_running = false;
atomic_t<bool> is_working = false;
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, u32 arg)
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, vm::ptr<void> arg)
: ppu_thread({}, "", 0)
, memAddr(addr)
, memSize(size)
@@ -755,11 +755,11 @@ PesHeader::PesHeader(DemuxerStream& stream)
is_ok = true;
}
ElementaryStream::ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec)
: put(utils::align(addr, 128))
ElementaryStream::ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec)
: put(utils::align(addr.addr(), 128))
, dmux(dmux)
, memAddr(utils::align(addr, 128))
, memSize(size - (addr - memAddr))
, memAddr(vm::ptr<void>::make(utils::align(addr.addr(), 128)))
, memSize(size - (addr.addr() - memAddr.addr()))
, fidMajor(fidMajor)
, fidMinor(fidMinor)
, sup1(sup1)
@@ -788,9 +788,9 @@ bool ElementaryStream::is_full(u32 space)
{
return first - put < space + 128;
}
else if (put + space + 128 > memAddr + memSize)
else if (put + space + 128 > memAddr.addr() + memSize)
{
return first - memAddr < space + 128;
return first - memAddr.addr() < space + 128;
}
else
{
@@ -816,35 +816,35 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
std::lock_guard lock(m_mutex);
ensure(!is_full(size));
if (put + size + 128 > memAddr + memSize)
if (put + size + 128 > memAddr.addr() + memSize)
{
put = memAddr;
put = memAddr.addr();
}
std::memcpy(vm::base(put + 128), raw_data.data(), size);
raw_data.erase(raw_data.begin(), raw_data.begin() + size);
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
info->auAddr = put + 128;
info->auAddr.set(put + 128);
info->auSize = size;
info->dts.lower = static_cast<u32>(dts);
info->dts.upper = static_cast<u32>(dts >> 32);
info->pts.lower = static_cast<u32>(pts);
info->pts.upper = static_cast<u32>(pts >> 32);
info->isRap = rap;
info->reserved = 0;
info->auMaxSize = 0;
info->userData = userdata;
auto spec = vm::ptr<u32>::make(put + u32{sizeof(CellDmuxAuInfoEx)});
*spec = specific;
auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64);
inf->auAddr = put + 128;
inf->auAddr.set(put + 128);
inf->auSize = size;
inf->dtsLower = static_cast<u32>(dts);
inf->dtsUpper = static_cast<u32>(dts >> 32);
inf->ptsLower = static_cast<u32>(pts);
inf->ptsUpper = static_cast<u32>(pts >> 32);
inf->dts.lower = static_cast<u32>(dts);
inf->dts.upper = static_cast<u32>(dts >> 32);
inf->pts.lower = static_cast<u32>(pts);
inf->pts.upper = static_cast<u32>(pts >> 32);
inf->auMaxSize = 0; // ?????
inf->userData = userdata;
@@ -927,7 +927,7 @@ bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool updat
void ElementaryStream::reset()
{
std::lock_guard lock(m_mutex);
put = memAddr;
put = memAddr.addr();
entries.clear();
put_count = 0;
got_count = 0;
+31 -141
View File
@@ -33,118 +33,6 @@ enum CellDmuxEsMsgType : s32
CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE = 1,
};
enum CellDmuxPamfM2vLevel : s32
{
CELL_DMUX_PAMF_M2V_MP_LL = 0,
CELL_DMUX_PAMF_M2V_MP_ML,
CELL_DMUX_PAMF_M2V_MP_H14,
CELL_DMUX_PAMF_M2V_MP_HL,
};
enum CellDmuxPamfAvcLevel : s32
{
CELL_DMUX_PAMF_AVC_LEVEL_2P1 = 21,
CELL_DMUX_PAMF_AVC_LEVEL_3P0 = 30,
CELL_DMUX_PAMF_AVC_LEVEL_3P1 = 31,
CELL_DMUX_PAMF_AVC_LEVEL_3P2 = 32,
CELL_DMUX_PAMF_AVC_LEVEL_4P1 = 41,
CELL_DMUX_PAMF_AVC_LEVEL_4P2 = 42,
};
struct CellDmuxPamfAuSpecificInfoM2v
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAvc
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoLpcm
{
u8 channelAssignmentInfo;
u8 samplingFreqInfo;
u8 bitsPerSample;
};
struct CellDmuxPamfAuSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoUserData
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoM2v
{
be_t<u32> profileLevel;
};
struct CellDmuxPamfEsSpecificInfoAvc
{
be_t<u32> level;
};
struct CellDmuxPamfEsSpecificInfoLpcm
{
be_t<u32> samplingFreq;
be_t<u32> numOfChannels;
be_t<u32> bitsPerSample;
};
struct CellDmuxPamfEsSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoUserData
{
be_t<u32> reserved1;
};
enum CellDmuxPamfSamplingFrequency : s32
{
CELL_DMUX_PAMF_FS_48K = 48000,
};
enum CellDmuxPamfBitsPerSample : s32
{
CELL_DMUX_PAMF_BITS_PER_SAMPLE_16 = 16,
CELL_DMUX_PAMF_BITS_PER_SAMPLE_24 = 24,
};
enum CellDmuxPamfLpcmChannelAssignmentInfo : s32
{
CELL_DMUX_PAMF_LPCM_CH_M1 = 1,
CELL_DMUX_PAMF_LPCM_CH_LR = 3,
CELL_DMUX_PAMF_LPCM_CH_LRCLSRSLFE = 9,
CELL_DMUX_PAMF_LPCM_CH_LRCLSCS1CS2RSLFE = 11,
};
enum CellDmuxPamfLpcmFs : s32
{
CELL_DMUX_PAMF_LPCM_FS_48K = 1,
};
enum CellDmuxPamfLpcmBitsPerSamples : s32
{
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_16 = 1,
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_24 = 3,
};
struct CellDmuxMsg
{
be_t<s32> msgType; // CellDmuxMsgType
@@ -163,12 +51,6 @@ struct CellDmuxType
be_t<u32> reserved[2];
};
struct CellDmuxPamfSpecificInfo
{
be_t<u32> thisSize;
b8 programEndCodeCb;
};
struct CellDmuxType2
{
be_t<s32> streamType; // CellDmuxStreamType
@@ -177,7 +59,7 @@ struct CellDmuxType2
struct CellDmuxResource
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
@@ -187,7 +69,7 @@ struct CellDmuxResource
struct CellDmuxResourceEx
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
@@ -227,16 +109,16 @@ struct CellDmuxResource2
be_t<u32> shit[4];
};
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg);
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg);
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
// Used for internal callbacks as well
template <typename F>
struct DmuxCb
{
vm::bptr<F> cbFunc;
be_t<u32> cbArg;
vm::bptr<void> cbArg;
};
using CellDmuxCb = DmuxCb<CellDmuxCbMsg>;
@@ -250,42 +132,50 @@ struct CellDmuxAttr
be_t<u32> demuxerVerLower;
};
struct CellDmuxPamfAttr
{
be_t<u32> maxEnabledEsNum;
be_t<u32> version;
be_t<u32> memSize;
};
struct CellDmuxEsAttr
{
be_t<u32> memSize;
};
struct CellDmuxPamfEsAttr
{
be_t<u32> auQueueMaxSize;
be_t<u32> memSize;
be_t<u32> specificInfoSize;
};
struct CellDmuxEsResource
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
};
struct CellDmuxAuInfo
{
be_t<u32> auAddr;
vm::bptr<void> auAddr;
be_t<u32> auSize;
be_t<u32> auMaxSize;
be_t<u64> userData;
be_t<u32> ptsUpper;
be_t<u32> ptsLower;
be_t<u32> dtsUpper;
be_t<u32> dtsLower;
};
struct CellDmuxAuInfoEx
{
be_t<u32> auAddr;
be_t<u32> auSize;
be_t<u32> reserved;
b8 isRap;
be_t<u64> userData;
CellCodecTimeStamp pts;
CellCodecTimeStamp dts;
};
struct CellDmuxPamfAttr;
struct CellDmuxPamfEsAttr;
using CellDmuxAuInfoEx = CellDmuxAuInfo;
struct DmuxAuInfo
{
CellDmuxAuInfo info;
vm::bptr<void> specific_info;
be_t<u32> specific_info_size;
};
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);
@@ -301,7 +191,7 @@ using CellDmuxCoreOpResetStream = error_code(vm::ptr<void>);
using CellDmuxCoreOpCreateThread = error_code(vm::ptr<void>);
using CellDmuxCoreOpJoinThread = error_code(vm::ptr<void>);
using CellDmuxCoreOpSetStream = error_code(vm::ptr<void>, vm::cptr<void>, u32, b8, u64);
using CellDmuxCoreOpFreeMemory = error_code(vm::ptr<void>, vm::ptr<void>, u32);
using CellDmuxCoreOpReleaseAu = error_code(vm::ptr<void>, vm::ptr<void>, u32);
using CellDmuxCoreOpQueryEsAttr = error_code(vm::cptr<void>, vm::cptr<void>, vm::ptr<CellDmuxPamfEsAttr>);
using CellDmuxCoreOpEnableEs = error_code(vm::ptr<void>, vm::cptr<void>, vm::cptr<CellDmuxEsResource>, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>>, vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>>, vm::cptr<void>, vm::pptr<void>);
using CellDmuxCoreOpDisableEs = u32(vm::ptr<void>);
@@ -318,7 +208,7 @@ struct CellDmuxCoreOps
vm::bptr<CellDmuxCoreOpCreateThread> createThread;
vm::bptr<CellDmuxCoreOpJoinThread> joinThread;
vm::bptr<CellDmuxCoreOpSetStream> setStream;
vm::bptr<CellDmuxCoreOpFreeMemory> freeMemory;
vm::bptr<CellDmuxCoreOpReleaseAu> releaseAu;
vm::bptr<CellDmuxCoreOpQueryEsAttr> queryEsAttr;
vm::bptr<CellDmuxCoreOpEnableEs> enableEs;
vm::bptr<CellDmuxCoreOpDisableEs> disableEs;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+102 -67
View File
@@ -770,8 +770,8 @@ namespace gem
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
@@ -822,8 +822,8 @@ namespace gem
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
@@ -845,6 +845,53 @@ namespace gem
debayer_raw8_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
template <bool use_gain>
static inline void debayer_raw8_downscale_impl(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
constexpr u32 in_pitch = 640;
constexpr u32 out_pitch = 320 * 4;
// Simple debayer
for (s32 y = 0; y < 240; y++)
{
const u8* src0 = src + y * 2 * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = dst + y * out_pitch;
for (s32 x = 0; x < 320; x++, dst0 += 4, src0 += 2, src1 += 2)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 g = (g0 + g1) >> 1;
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
dst0[0] = r;
dst0[1] = g;
dst0[2] = b;
}
dst0[3] = alpha;
}
}
}
static void debayer_raw8_downscale(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
if (gain_r != 1.0f || gain_g != 1.0f || gain_b != 1.0f)
debayer_raw8_downscale_impl<true>(src, dst, alpha, gain_r, gain_g, gain_b);
else
debayer_raw8_downscale_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
bool convert_image_format(CellCameraFormat input_format, const CellGemVideoConvertAttribute& vc,
const std::vector<u8>& video_data_in, u32 width, u32 height,
u8* video_data_out, u32 video_data_out_size, u8* buffer_memory,
@@ -881,9 +928,9 @@ namespace gem
const u8* src_data = video_data_in.data();
const u8 alpha = vc.alpha;
const f32 gain_r = vc.gain * vc.blue_gain;
const f32 gain_r = vc.gain * vc.red_gain;
const f32 gain_g = vc.gain * vc.green_gain;
const f32 gain_b = vc.gain * vc.red_gain;
const f32 gain_b = vc.gain * vc.blue_gain;
// Only RAW8 should be relevant for cellGem unless I'm mistaken
if (input_format == CELL_CAMERA_RAW8)
@@ -1183,34 +1230,7 @@ namespace gem
{
case CELL_CAMERA_RAW8:
{
const u32 in_pitch = width;
const u32 out_pitch = width * 4 / 2;
for (u32 y = 0; y < height - 1; y += 2)
{
const u8* src0 = src_data + y * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = video_data_out + (y / 2) * out_pitch;
u8* dst1 = dst0 + out_pitch;
for (u32 x = 0; x < width - 1; x += 2, src0 += 2, src1 += 2, dst0 += 4, dst1 += 4)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 top[4] = { r, g0, b, alpha };
const u8 bottom[4] = { r, g1, b, alpha };
// Top-Left
std::memcpy(dst0, top, 4);
// Bottom-Left Pixel
std::memcpy(dst1, bottom, 4);
}
}
debayer_raw8_downscale(src_data, video_data_out, alpha, gain_r, gain_g, gain_b);
break;
}
case CELL_CAMERA_RGBA:
@@ -1609,13 +1629,8 @@ public:
return false;
}
if (!m_camera_info.bytesize)
{
cellGem.error("gem_tracker: unexpected image size: %d", m_camera_info.bytesize);
return false;
}
m_tracker.set_image_data(m_camera_info.buffer.get_ptr(), m_camera_info.bytesize, m_camera_info.width, m_camera_info.height, m_camera_info.format);
m_framenumber++; // using framenumber instead of timestamp since the timestamp could be identical
return true;
}
@@ -1648,6 +1663,7 @@ public:
}
auto& gem = g_fxo->get<gem_config>();
u64 last_framenumber = 0;
while (thread_ctrl::state() != thread_state::aborting)
{
@@ -1663,6 +1679,13 @@ public:
}
}
if (std::exchange(last_framenumber, m_framenumber.load()) == last_framenumber)
{
cellGem.warning("Tracker woke up without new frame. Skipping processing (framenumber=%d)", last_framenumber);
tracker_done();
continue;
}
m_busy.release(true);
// Update PS Move LED colors
@@ -1751,9 +1774,16 @@ public:
shared_mutex mutex;
gem_tracker& operator=(thread_state) noexcept
{
wake_up_tracker();
return *this;
}
private:
atomic_t<u32> m_wake_up_tracker = 0;
atomic_t<u32> m_tracker_done = 0;
atomic_t<u64> m_framenumber = 0;
atomic_t<bool> m_busy = false;
ps_move_tracker<false> m_tracker{};
CellCameraInfoEx m_camera_info{};
@@ -1873,21 +1903,10 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
gem_state->pos[2] = controller.distance_mm;
gem_state->pos[3] = 0.f;
// TODO: calculate handle position based on our world coordinate and the angles
gem_state->handle_pos[0] = camera_x;
gem_state->handle_pos[1] = camera_y;
gem_state->handle_pos[2] = controller.distance_mm + 10.0f;
gem_state->handle_pos[3] = 0.f;
// Calculate orientation
if (g_cfg.io.move == move_handler::real || (g_cfg.io.move == move_handler::fake && move_data.orientation_enabled))
{
gem_state->quat[0] = move_data.quaternion.x();
gem_state->quat[1] = move_data.quaternion.y();
gem_state->quat[2] = move_data.quaternion.z();
gem_state->quat[3] = move_data.quaternion.w();
}
else
ps_move_data::vect<4> quat = move_data.quaternion;
if (g_cfg.io.move != move_handler::real && !(g_cfg.io.move == move_handler::fake && move_data.orientation_enabled))
{
const f32 max_angle_per_side_h = g_cfg.io.fake_move_rotation_cone_h / 2.0f;
const f32 max_angle_per_side_v = g_cfg.io.fake_move_rotation_cone_v / 2.0f;
@@ -1901,17 +1920,27 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
const f32 cy = std::cos(yaw * 0.5f);
const f32 sy = std::sin(yaw * 0.5f);
const f32 q_x = sr * cp * cy - cr * sp * sy;
const f32 q_y = cr * sp * cy + sr * cp * sy;
const f32 q_z = cr * cp * sy - sr * sp * cy;
const f32 q_w = cr * cp * cy + sr * sp * sy;
gem_state->quat[0] = q_x;
gem_state->quat[1] = q_y;
gem_state->quat[2] = q_z;
gem_state->quat[3] = q_w;
quat.x() = sr * cp * cy - cr * sp * sy;
quat.y() = cr * sp * cy + sr * cp * sy;
quat.z() = cr * cp * sy - sr * sp * cy;
quat.w() = cr * cp * cy + sr * sp * sy;
}
gem_state->quat[0] = quat.x();
gem_state->quat[1] = quat.y();
gem_state->quat[2] = quat.z();
gem_state->quat[3] = quat.w();
// Calculate handle position based on our world coordinate and the current orientation
constexpr ps_move_data::vect<3> offset_local_mm({0.f, 0.f, -45.f}); // handle is ~45 mm below sphere
const ps_move_data::vect<3> offset_world = ps_move_data::rotate_vector(quat, offset_local_mm);
gem_state->handle_pos[0] = gem_state->pos[0] - offset_world.x(); // Flip x offset
gem_state->handle_pos[1] = gem_state->pos[1] - offset_world.y(); // Flip y offset
gem_state->handle_pos[2] = gem_state->pos[2] + offset_world.z();
gem_state->handle_pos[3] = 0.f;
// Calculate velocity
if constexpr (!ps_move_data::use_imu_for_velocity)
{
move_data.update_velocity(shared_data.frame_timestamp_us, gem_state->pos);
@@ -1920,6 +1949,10 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
{
gem_state->vel[i] = move_data.vel_world[i];
gem_state->accel[i] = move_data.accel_world[i];
// TODO: maybe this also needs to be adjusted depending on the orientation
gem_state->handle_vel[i] = gem_state->vel[i];
gem_state->handle_accel[i] = gem_state->accel[i];
}
}
@@ -3612,7 +3645,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr<u32> ext_id, v
if (!pad->move_data.external_device_read_requested)
{
*ext_id = controller.ext_id = pad->move_data.external_device_id;
std::memcpy(pad->move_data.external_device_read.data(), ext_info.get_ptr(), CELL_GEM_EXTERNAL_PORT_OUTPUT_SIZE);
std::memcpy(ext_info.get_ptr(), pad->move_data.external_device_read.data(), CELL_GEM_EXTERNAL_PORT_DEVICE_INFO_SIZE);
break;
}
}
@@ -3876,13 +3909,15 @@ error_code cellGemUpdateStart(vm::cptr<void> camera_frame, u64 timestamp)
gem.camera_frame = camera_frame.addr();
if (!tracker.set_image(gem.camera_frame))
const bool image_set = tracker.set_image(gem.camera_frame);
tracker.wake_up_tracker();
if (!image_set)
{
return not_an_error(CELL_GEM_NO_VIDEO);
}
tracker.wake_up_tracker();
return CELL_OK;
}
+1
View File
@@ -1,5 +1,6 @@
#pragma once
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Memory/vm_ptr.h"
// Error Codes
+20
View File
@@ -1267,6 +1267,11 @@ struct SceNpOnlineId
{
char data[SCE_NET_NP_ONLINEID_MAX_LENGTH + 1]; // char term;
char dummy[3];
bool operator<(const SceNpOnlineId& other) const
{
return memcmp(data, other.data, sizeof(data)) < 0;
}
};
// NP ID structure
@@ -1283,6 +1288,11 @@ struct SceNpId
};
u8 reserved[8];
bool operator<(const SceNpId& other) const
{
return handle < other.handle;
}
};
CHECK_SIZE_ALIGN(SceNpId, 0x24, 1);
@@ -1689,12 +1699,22 @@ struct SceNpLobbyId
{
u8 opt[28];
u8 reserved[8];
bool operator<(const SceNpLobbyId& other) const
{
return memcmp(opt, other.opt, sizeof(opt)) < 0;
}
};
struct SceNpRoomId
{
u8 opt[28];
u8 reserved[8];
bool operator<(const SceNpRoomId& other) const
{
return memcmp(opt, other.opt, sizeof(opt)) < 0;
}
};
struct SceNpMatchingAttr
+1 -1
View File
@@ -2535,7 +2535,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
// SLDI mnemonic
reg_state_t rs = get_reg(op.rs);
if (!rs.shift_left(op.sh32, reg_tag_allocator))
if (!rs.shift_left(sh, reg_tag_allocator))
{
unmap_reg(op.ra);
}
+3 -3
View File
@@ -1004,7 +1004,7 @@ static import_result_t ppu_load_imports(const ppu_module<lv2_obj>& _module, std:
// Check address
// TODO: The address of use should be extracted from analyser instead
if (fstub && fstub >= _module.segs[0].addr && fstub <= _module.segs[0].addr + _module.segs[0].size)
if (fstub && fstub >= _module.segs[0].addr && fstub < _module.segs[0].addr + _module.segs[0].size)
{
nid_to_use_addr.emplace(fnid, fstub);
}
@@ -1895,7 +1895,7 @@ shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, bool virtual_load, c
}
else
{
ppu_loader.error("Library %s: PRX library info not found");
ppu_loader.error("Library: PRX library info not found");
}
prx->start.set(prx->specials[0xbc9a0086]);
@@ -3192,7 +3192,7 @@ bool ppu_load_rel_exec(const ppu_rel_object& elf)
for (const auto& s : elf.shdrs)
{
if (s.sh_type != sec_type::sht_progbits)
if (s.sh_type == sec_type::sht_progbits)
{
memsize = utils::align<u32>(memsize + vm::cast(s.sh_size), 128);
}
+5 -8
View File
@@ -1364,9 +1364,7 @@ void ppu_thread::dump_regs(std::string& ret, std::any& custom_data) const
u32 preferred_cr_field_index = 7;
};
dump_registers_data_t* func_data = nullptr;
func_data = std::any_cast<dump_registers_data_t>(&custom_data);
dump_registers_data_t* func_data = std::any_cast<dump_registers_data_t>(&custom_data);
if (!func_data)
{
@@ -2039,9 +2037,9 @@ std::vector<std::pair<u32, u32>> ppu_thread::dump_callstack_list() const
return call_stack_list;
}
std::string ppu_thread::dump_misc() const
void ppu_thread::dump_misc(std::string& ret, std::any& custom_data) const
{
std::string ret = cpu_thread::dump_misc();
cpu_thread::dump_misc(ret, custom_data);
if (ack_suspend)
{
@@ -2096,7 +2094,6 @@ std::string ppu_thread::dump_misc() const
{
ret += '\n';
}
return ret;
}
void ppu_thread::dump_all(std::string& ret) const
@@ -3867,12 +3864,12 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
if (mself.read(hdr) && hdr.get_count(mself.size()))
{
std::set<u64> offs;
for (u32 j = 0; j < hdr.count; j++)
{
mself_record rec{};
std::set<u64> offs;
if (mself.read(rec) && rec.get_pos(mself.size()))
{
if (rec.size <= 0x20)
+1 -1
View File
@@ -145,7 +145,7 @@ public:
virtual void dump_regs(std::string&, std::any& custom_data) const override;
virtual std::string dump_callstack() const override;
virtual std::vector<std::pair<u32, u32>> dump_callstack_list() const override;
virtual std::string dump_misc() const override;
virtual void dump_misc(std::string& ret, std::any& custom_data) const override;
virtual void dump_all(std::string&) const override;
virtual void cpu_task() override final;
virtual void cpu_sleep() override;
+6 -9
View File
@@ -550,11 +550,12 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
else if (_target >= caddr && _target <= cend)
{
u32 target_last = static_cast<u32>(_target);
std::unordered_set<u32> passed_targets{target_last};
// Try to follow unconditional branches as long as there is no infinite loop
while (target_last != _target)
// !! Triggers compilation issues in Asura's Wrath in other parts of the code
// !! See https://github.com/RPCS3/rpcs3/issues/18287
while (false)
{
const ppu_opcode_t op{*ensure(m_info.get_ptr<u32>(target_last))};
const ppu_itype::type itype = g_ppu_itype.decode(op.opcode);
@@ -1304,7 +1305,7 @@ void PPUTranslator::VMADDFP(ppu_opcode_t op)
if (!m_use_fma && data == v128{})
{
set_vr(op.vd, vec_handle_result(a * c + fsplat<f32[4]>(0.f)));
ppu_log.notice("LLVM: VMADDFP with -0 addend at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0));
ppu_log.notice("LLVM: VMADDFP with +0 addend at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0));
return;
}
}
@@ -3680,9 +3681,7 @@ void PPUTranslator::STVLX(ppu_opcode_t op)
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
const auto mask = bitcast<bool[16]>(splat<u16>(0xffff) << trunc<u16>(value<u64>(addr) & 0xf));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
const auto align = splat<u32>(16);
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
m_ir->CreateMaskedStore(data.eval(m_ir), GetMemory(m_ir->CreateAnd(addr, ~0xfull)), llvm::Align(16), mask.eval(m_ir));
}
void PPUTranslator::STDBRX(ppu_opcode_t op)
@@ -3710,9 +3709,7 @@ void PPUTranslator::STVRX(ppu_opcode_t op)
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
const auto mask = bitcast<bool[16]>(trunc<u16>(splat<u64>(0xffff) << (value<u64>(addr) & 0xf) >> 16));
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
const auto align = splat<u32>(16);
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
m_ir->CreateMaskedStore(data.eval(m_ir), GetMemory(m_ir->CreateAnd(addr, ~0xfull)), llvm::Align(16), mask.eval(m_ir));
}
void PPUTranslator::STFSUX(ppu_opcode_t op)
+23 -12
View File
@@ -13,6 +13,7 @@ struct spu_itype
static constexpr struct quadrop_tag{} _quadrop{}; // 4-op Instructions
static constexpr struct xfloat_tag{} xfloat{}; // Instructions producing xfloat values
static constexpr struct zregmod_tag{} zregmod{}; // Instructions not modifying any GPR
static constexpr struct pure_tag{} pure{}; // Instructions that always produce the same values as long as arguments are equal
enum class type : unsigned char
{
@@ -158,6 +159,15 @@ struct spu_itype
CUFLT,
FRDS, // xfloat_tag last
CFLTS,
CFLTU,
FCEQ,
FCMEQ,
FCGT,
FCMGT, // floating_tag last
FSCRWR,
FSCRRD,
DFA,
DFS,
DFM,
@@ -167,20 +177,11 @@ struct spu_itype
DFNMA,
FESD,
CFLTS,
CFLTU,
FCEQ,
FCMEQ,
FCGT,
FCMGT,
FSCRWR,
FSCRRD,
DFCEQ,
DFCMEQ,
DFCGT,
DFCMGT,
DFTSV, // floating_tag last
DFTSV,
SHLH, // shiftrot_tag first
SHLHI,
@@ -248,10 +249,10 @@ struct spu_itype
return value >= BR && value <= BISL;
}
// Test for floating point instruction
// Test for floating point instruction (32-bit float)
friend constexpr bool operator &(type value, floating_tag)
{
return value >= FMA && value <= DFTSV;
return value >= FMA && value <= FCMGT;
}
// Test for 4-op instruction
@@ -301,8 +302,16 @@ struct spu_itype
{
return (value >= HEQ && value <= STQR) || (value >= BR && value <= BIHNZ);
}
// Test for instructions which always produce the same values as long as arguments and immediate values are equal
friend constexpr bool operator &(type value, pure_tag)
{
return (value >= ILH && value <= CLGTI);
}
};
using spu_itype_t = spu_itype::type;
struct spu_iflag
{
enum
@@ -528,6 +537,8 @@ struct spu_iflag
}
};
using spu_iflag_t = spu_iflag::flag;
#define NAME(x) static constexpr const char& x = *#x
struct spu_iname
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+15
View File
@@ -24,6 +24,20 @@ union spu_opcode_t
bf_t<u32, 7, 16> i16; // 9..24
bf_t<s32, 7, 16> si16; // 9..24, signed
bf_t<u32, 7, 18> i18; // 7..24
// For 16-bit instructions in the context of 32-bits
u32 duplicate_si10() const
{
const u32 _16 = static_cast<u16>(static_cast<s16>(si10));
return (_16 << 16) | _16;
}
// For 8-bit instructions in the context of 32-bits
u32 duplicate_duplicate_si10() const
{
const u32 _8 = static_cast<u8>(si10 & 0xff);
return (_8 << 24) | (_8 << 16) | (_8 << 8) | _8;
}
};
constexpr u32 spu_branch_target(u32 pc, u32 imm = 0)
@@ -42,6 +56,7 @@ constexpr u32 spu_decode(u32 inst)
}
std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op);
std::tuple<u32, std::array<u32, 3>, u32> op_register_targets(u32 /*pc*/, spu_opcode_t op);
// SPU decoder object. D provides functions. T is function pointer type returned.
template <typename D, typename T = decltype(&D::UNK)>
+440 -6
View File
@@ -4,12 +4,23 @@
#include "Utilities/lockless.h"
#include "Utilities/address_range.h"
#include "SPUThread.h"
#include "SPUAnalyser.h"
#include <vector>
#include <bitset>
#include <memory>
#include <string>
#include <deque>
// std::bitset
template <typename CT, typename T>
requires requires(CT&& x, T&& y) { x.count(); x.test(y); x.flip(y); }
[[nodiscard]] constexpr bool at32(CT&& container, T&& index, std::source_location src_loc = std::source_location::current())
{
if (container.size() >= std::forward<T>(index)) [[unlikely]]
fmt::raw_range_error(src_loc, format_object_simplified(index), csv);
return container[std::forward<T>(index)];
}
// Helper class
class spu_cache
{
@@ -201,6 +212,25 @@ public:
__bitset_enum_max
};
enum compare_direction : u32
{
CMP_TURNAROUND_FLAG = 0x1,
CMP_NEGATE_FLAG = 0x100,
CMP_SLESS = 0,
CMP_SGREATER = CMP_SLESS | CMP_TURNAROUND_FLAG,
CMP_EQUAL,
CMP_EQUAL2 = CMP_EQUAL | CMP_TURNAROUND_FLAG,
CMP_LLESS,
CMP_LGREATER = CMP_LLESS | CMP_TURNAROUND_FLAG,
CMP_SGREATER_EQUAL = CMP_SLESS | CMP_NEGATE_FLAG,
CMP_SLOWER_EQUAL = CMP_SGREATER | CMP_NEGATE_FLAG,
CMP_NOT_EQUAL = CMP_EQUAL | CMP_NEGATE_FLAG,
CMP_NOT_EQUAL2 = CMP_NOT_EQUAL | CMP_TURNAROUND_FLAG,
CMP_LGREATER_EQUAL = CMP_LLESS | CMP_NEGATE_FLAG,
CMP_LLOWER_EQUAL = CMP_LGREATER | CMP_NEGATE_FLAG,
CMP_UNKNOWN,
};
struct reg_state_t
{
bs_t<vf> flag{+vf::is_null};
@@ -273,6 +303,399 @@ public:
static u32 alloc_tag(bool reset = false) noexcept;
};
struct reduced_loop_t
{
bool active = false; // Single block loop detected
bool failed = false;
u32 loop_pc = SPU_LS_SIZE;
u32 loop_end = SPU_LS_SIZE;
// False: single-block loop
// True: loop with a trailing block of aftermath (iteration update) stuff (like for (u32 i = 0; i < 10; /*update*/ i++))
bool is_two_block_loop = false;
bool has_cond_state = false;
// Loop stay-in state requirement
u64 cond_val_mask = umax;
u64 cond_val_min = 0;
u64 cond_val_size = 0;
compare_direction cond_val_compare{};
u64 cond_val_incr = 0;
bool cond_val_incr_is_immediate = false;
u64 cond_val_register_argument_idx = umax;
u64 cond_val_register_idx = umax;
bool cond_val_incr_before_cond = false;
bool cond_val_incr_before_cond_taken_in_account = false;
bool cond_val_is_immediate = false;
// Loop attributes
bool is_constant_expression = false;
bool is_secret = false;
struct supplemental_condition_t
{
u64 immediate_value = umax;
u64 type_size = 0;
compare_direction val_compare{};
};
// Supplemental loop condition:
// Inner conditions that depend on extrnal values (not produced inside the loop)
// all should evaluate to false in order for the optimization to work (at the moment)
// So succeeding can be treated linearly
u64 expected_sup_conds = 0;
u64 current_sup_conds_index = 0;
std::vector<supplemental_condition_t> sup_conds;
void take_cond_val_incr_before_cond_into_account()
{
if (cond_val_is_immediate && cond_val_incr_before_cond_taken_in_account && !cond_val_incr_before_cond_taken_in_account)
{
cond_val_min -= cond_val_incr;
cond_val_min &= cond_val_mask;
cond_val_incr_before_cond_taken_in_account = true;
}
}
std::bitset<s_reg_max> loop_args;
std::bitset<s_reg_max> loop_dicts;
std::bitset<s_reg_max> loop_writes;
struct origin_t
{
std::bitset<s_reg_max> regs{};
u32 modified = 0;
spu_itype_t mod1_type = spu_itype::UNK;
spu_itype_t mod2_type = spu_itype::UNK;
spu_itype_t mod3_type = spu_itype::UNK;
u32 IMM = 0;
private:
// Internal, please access using fixed order
spu_itype_t access_type(u32 i) const
{
if (i > modified)
{
return spu_itype::UNK;
}
switch (i)
{
case 1: return mod1_type;
case 2: return mod2_type;
case 3: return mod3_type;
default: return spu_itype::UNK;
}
return spu_itype::UNK;
}
public:
spu_itype_t reverse1_type()
{
return access_type(modified);
}
spu_itype_t reverse2_type()
{
return access_type(modified - 1);
}
spu_itype_t reverse3_type()
{
return access_type(modified - 2);
}
origin_t& join_with_this(const origin_t& rhs)
{
regs |= rhs.regs;
return *this;
}
origin_t& join_with_this(u32 rhs)
{
regs.set(rhs);
return *this;
}
origin_t& add_register_origin(u32 reg_val)
{
regs.set(reg_val);
return *this;
}
bool is_single_reg_access(u32 reg_val) const
{
if (!modified)
{
return true;
}
return regs.count() == 1 && ::at32(regs, reg_val);
}
bool is_loop_dictator(u32 reg_val, bool test_predictable = false, bool should_predictable = true) const
{
if (!modified)
{
return false;
}
if (regs.count() >= 1 && ::at32(regs, reg_val))
{
if (!test_predictable)
{
return true;
}
if (modified > 1)
{
return should_predictable ^ true;
}
switch (mod1_type)
{
case spu_itype::A:
{
if (regs.count() == 2)
{
return should_predictable;
}
return should_predictable ^ true;
}
case spu_itype::AI:
case spu_itype::AHI:
{
if (IMM && regs.count() == 1)
{
return should_predictable;
}
return should_predictable ^ true;
}
default: break;
}
return should_predictable ^ true;
}
return false;
}
bool is_predictable_loop_dictator(u32 reg_val) const
{
return is_loop_dictator(reg_val, true, true);
}
bool is_non_predictable_loop_dictator(u32 reg_val) const
{
return is_loop_dictator(reg_val, true, false);
}
bool is_null(u32 reg_val) const noexcept
{
if (modified)
{
return false;
}
if (regs.count() - (::at32(regs, reg_val) ? 1 : 0))
{
return false;
}
return true;
}
origin_t& add_instruction_modifier(spu_itype_t inst_type, u32 imm = 0)
{
if (inst_type == spu_itype::UNK)
{
mod1_type = spu_itype::UNK;
mod2_type = spu_itype::UNK;
mod3_type = spu_itype::UNK;
IMM = umax;
modified = 1;
return *this;
}
if (modified == 1)
{
if (modified == 3)
{
mod1_type = spu_itype::UNK;
mod2_type = spu_itype::UNK;
mod3_type = spu_itype::UNK;
IMM = umax;
modified = 1;
return *this;
}
bool is_ok = false;
switch (inst_type)
{
case spu_itype::XSBH:
{
const auto prev_type = modified == 1 ? mod1_type : mod2_type;
is_ok &= mod1_type == spu_itype::CEQB || mod1_type == spu_itype::CEQBI || mod1_type == spu_itype::CGTB || mod1_type == spu_itype::CGTBI || mod1_type == spu_itype::CLGTB || mod1_type == spu_itype::CLGTBI;
break;
}
case spu_itype::ANDI:
{
const auto prev_type = modified == 1 ? mod1_type : mod2_type;
is_ok &= mod1_type == spu_itype::CEQB || mod1_type == spu_itype::CEQBI || mod1_type == spu_itype::CGTB || mod1_type == spu_itype::CGTBI || mod1_type == spu_itype::CLGTB || mod1_type == spu_itype::CLGTBI;
is_ok &= (spu_opcode_t{imm}.si10 & 0xff) == 0xff;
break;
}
case spu_itype::CEQ:
case spu_itype::CEQH:
case spu_itype::CEQB:
case spu_itype::CGT:
case spu_itype::CGTH:
case spu_itype::CGTB:
case spu_itype::CLGT:
case spu_itype::CLGTH:
case spu_itype::CLGTB:
{
is_ok = modified == 1 && (mod1_type == spu_itype::AI || mod1_type == spu_itype::AHI);
IMM = imm;
break;
}
case spu_itype::CEQI:
case spu_itype::CEQHI:
case spu_itype::CEQBI:
case spu_itype::CGTI:
case spu_itype::CGTHI:
case spu_itype::CGTBI:
case spu_itype::CLGTI:
case spu_itype::CLGTHI:
case spu_itype::CLGTBI:
{
is_ok = modified == 1 && (mod1_type == spu_itype::AI || mod1_type == spu_itype::AHI);
IMM = spu_opcode_t{imm}.si10;
break;
}
}
if (!is_ok)
{
mod1_type = spu_itype::UNK;
mod2_type = spu_itype::UNK;
mod3_type = spu_itype::UNK;
IMM = umax;
modified = 1;
return *this;
}
(modified == 1 ? mod2_type : mod3_type) = inst_type;
modified++;
return *this;
}
mod1_type = inst_type;
modified = 1;
switch (inst_type)
{
case spu_itype::AHI:
{
IMM = spu_opcode_t{imm}.duplicate_si10();
return *this;
}
case spu_itype::AI:
case spu_itype::ORI:
case spu_itype::XORI:
case spu_itype::ANDI:
case spu_itype::CEQI:
case spu_itype::CEQHI:
case spu_itype::CEQBI:
case spu_itype::CGTI:
case spu_itype::CGTHI:
case spu_itype::CGTBI:
case spu_itype::CLGTI:
case spu_itype::CLGTHI:
case spu_itype::CLGTBI:
{
IMM = spu_opcode_t{imm}.si10;
return *this;
}
case spu_itype::ILA:
{
IMM = spu_opcode_t{imm}.i18;
return *this;
}
case spu_itype::IOHL:
case spu_itype::ILH:
case spu_itype::ILHU:
{
IMM = spu_opcode_t{imm}.i16;
return *this;
}
default:
{
IMM = imm;
break;
}
}
return *this;
}
};
static origin_t make_reg(u32 reg_val) noexcept
{
origin_t org{};
org.add_register_origin(reg_val);
return org;
}
const origin_t* find_reg(u32 reg_val) const noexcept
{
for (auto& pair : regs)
{
if (pair.first == reg_val)
{
return &pair.second;
}
}
return nullptr;
}
origin_t* find_reg(u32 reg_val) noexcept
{
return const_cast<origin_t*>(std::as_const(*this).find_reg(reg_val));
}
bool is_reg_null(u32 reg_val) const noexcept
{
if (const auto reg_found = find_reg(reg_val))
{
return reg_found->is_null(reg_val);
}
return true;
}
origin_t get_reg(u32 reg_val) noexcept
{
const auto org = find_reg(reg_val);
return org ? *org : regs.emplace_back(reg_val, std::remove_reference_t<decltype(*org)>{}).second;
}
std::vector<std::pair<u8, origin_t>> regs;
// Return old state for error reporting
reduced_loop_t discard()
{
const reduced_loop_t old = *this;
*this = reduced_loop_t{};
return old;
}
};
protected:
spu_runtime* m_spurt{};
@@ -326,8 +749,14 @@ protected:
// Set if the initial register value in this block may be xfloat
std::bitset<s_reg_max> reg_maybe_xf{};
// Bit mask of the registers used (before modified)
std::bitset<s_reg_max> reg_use{};
// Set if register is used in floating pont instruction
std::bitset<s_reg_max> reg_maybe_float{};
// Set if register is used as shuffle mask
std::bitset<s_reg_max> reg_maybe_shuffle_mask{};
// Number of times registers are used (before modified)
std::array<u32, s_reg_max> reg_use{};
// Bit mask of the trivial (u32 x 4) constant value resulting in this block
std::bitset<s_reg_max> reg_const{};
@@ -391,18 +820,23 @@ protected:
putllc16,
putllc0,
rchcnt_loop,
reduced_loop,
};
std::vector<inst_attr> m_inst_attrs;
struct pattern_info
{
u64 info;
// Info via integral
u64 info{};
// Info via additional erased-typed pointer
std::shared_ptr<void> info_ptr;
};
std::unordered_map<u32, pattern_info> m_patterns;
std::map<u32, pattern_info> m_patterns;
void add_pattern(inst_attr attr, u32 start, u64 info);
void add_pattern(inst_attr attr, u32 start, u64 info, std::shared_ptr<void> info_ptr = nullptr);
private:
// For private use
@@ -435,7 +869,7 @@ public:
spu_program analyse(const be_t<u32>* ls, u32 entry_point, std::map<u32, std::vector<u32>>* out_target_list = nullptr);
// Print analyser internal state
void dump(const spu_program& result, std::string& out);
void dump(const spu_program& result, std::string& out, u32 block_min = 0, u32 block_max = SPU_LS_SIZE);
// Get SPU Runtime
spu_runtime& get_runtime()
+109 -11
View File
@@ -495,7 +495,8 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write);
extern thread_local u64 g_tls_fault_spu;
const spu_decoder<spu_itype> s_spu_itype;
const extern spu_decoder<spu_itype> g_spu_itype;
const extern spu_decoder<spu_iflag> g_spu_iflag;
namespace vm
{
@@ -598,7 +599,7 @@ std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op)
{
std::array<u32, 2> res{spu_branch_target(pc + 4), umax};
switch (const auto type = s_spu_itype.decode(op.opcode))
switch (const auto type = g_spu_itype.decode(op.opcode))
{
case spu_itype::BR:
case spu_itype::BRA:
@@ -639,6 +640,54 @@ std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op)
return res;
}
std::tuple<u32, std::array<u32, 3>, u32> op_register_targets(u32 /*pc*/, spu_opcode_t op)
{
std::tuple<u32, std::array<u32, 3>, u32> result{u32{umax}, std::array<u32, 3>{128, 128, 128}, op.opcode};
const auto type = g_spu_itype.decode(op.opcode);
if (type & spu_itype::zregmod)
{
std::get<2>(result) = 0;
return result;
}
std::get<0>(result) = type & spu_itype::_quadrop ? op.rt4 : op.rt;
spu_opcode_t op_masked = op;
if (type & spu_itype::_quadrop)
{
op_masked.rt4 = 0;
}
else
{
op_masked.rt = 0;
}
std::get<2>(result) = op_masked.opcode;
if (auto iflags = g_spu_iflag.decode(op.opcode))
{
if (+iflags & +spu_iflag::use_ra)
{
std::get<1>(result)[0] = op.ra;
}
if (+iflags & +spu_iflag::use_rb)
{
std::get<1>(result)[1] = op.rb;
}
if (+iflags & +spu_iflag::use_rc)
{
std::get<1>(result)[2] = op.rc;
}
}
return result;
}
void spu_int_ctrl_t::set(u64 ints)
{
// leave only enabled interrupts
@@ -988,7 +1037,7 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
passed[i / 4] = true;
const spu_opcode_t op{_ref<u32>(i)};
const auto type = s_spu_itype.decode(op.opcode);
const auto type = g_spu_itype.decode(op.opcode);
if (start == 0 && type == spu_itype::STQD && op.ra == 1u && op.rt == 0u)
{
@@ -1090,11 +1139,62 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
return call_stack_list;
}
std::string spu_thread::dump_misc() const
void spu_thread::dump_misc(std::string& ret, std::any& custom_data) const
{
std::string ret = cpu_thread::dump_misc();
cpu_thread::dump_misc(ret, custom_data);
fmt::append(ret, "Block Weight: %u (Retreats: %u)", block_counter, block_failure);
struct dump_misc_data_t
{
u32 cpu_id = umax;
u64 last_read_time = umax;
u64 last_block_counter = umax;
u64 update_count = 0;
std::pair<u64, u64> update(u64 current_block_counter, u64 current_timestamp = get_system_time())
{
const u64 diff_time = current_timestamp <= last_read_time ? 0 : current_timestamp - last_read_time;
const u64 diff_block = current_block_counter <= last_block_counter ? 0 : current_block_counter - last_block_counter;
if (last_read_time == umax || update_count >= 1000)
{
last_read_time = current_timestamp;
last_block_counter = current_block_counter;
update_count = 0;
}
else if (diff_time >= 100000 && diff_block >= 100)
{
// Update values to measure rate (but not fully so rate can be measured later)
last_read_time += diff_time / 10 * 9;
last_block_counter += diff_block / 10 * 9;
update_count++;
}
return {diff_time, diff_block};
}
};
dump_misc_data_t* func_data = std::any_cast<dump_misc_data_t>(&custom_data);
if (!func_data)
{
custom_data.reset();
custom_data = std::make_any<dump_misc_data_t>();
func_data = ensure(std::any_cast<dump_misc_data_t>(&custom_data));
}
if (func_data->cpu_id != this->id)
{
*func_data = {};
func_data->cpu_id = this->id;
}
const u64 current_block_counter = atomic_storage<u64>::load(block_counter);
const auto [diff_time, diff_block] = func_data->update(current_block_counter);
const u64 rate_of_diff = diff_block ? std::max<u64>(1, utils::rational_mul<u64>(diff_block, 1'000'000, std::max<u64>(diff_time, 1))) : 0;
fmt::append(ret, "Block Weight: log10(%u/second): %.1f (Retreats: %u)", rate_of_diff, std::log10(std::max<u64>(rate_of_diff, 10)), block_failure);
if (u64 hash = atomic_storage<u64>::load(block_hash))
{
@@ -1145,8 +1245,6 @@ std::string spu_thread::dump_misc() const
break;
}
}
return ret;
}
void spu_thread::cpu_on_stop()
@@ -3761,7 +3859,7 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
const u32 addr0 = spu_branch_target(addr);
const spu_opcode_t op{read_from_ptr<be_t<u32>>(ls_ptr, addr0 - base_addr)};
const auto type = s_spu_itype.decode(op.opcode);
const auto type = g_spu_itype.decode(op.opcode);
if (type == spu_itype::UNK || !op.opcode)
{
@@ -3907,7 +4005,7 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
// Test the validity of a single instruction of the optional target
// This function can't be too slow and is unlikely to improve results by a great deal
const u32 op0 = read_from_ptr<be_t<u32>>(ls_ptr, route_pc - base_addr);
const spu_itype::type type0 = s_spu_itype.decode(op0);
const spu_itype::type type0 = g_spu_itype.decode(op0);
if (type0 == spu_itype::UNK || !op0)
{
@@ -6878,7 +6976,7 @@ spu_exec_object spu_thread::capture_memory_as_elf(std::span<spu_memory_segment_d
const u32 op = read_from_ptr<be_t<u32>>(all_data, pc0 - 4);
// Try to find function entry (if they are placed sequentially search for BI $LR of previous function)
if (!op || op == 0x35000000u || s_spu_itype.decode(op) == spu_itype::UNK)
if (!op || op == 0x35000000u || g_spu_itype.decode(op) == spu_itype::UNK)
{
if (is_exec_code(pc0, { all_data.data(), SPU_LS_SIZE }))
break;

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