Compare commits

...

355 Commits

Author SHA1 Message Date
Ani a8e62e1bc1 rpcs3_version: Bump to 0.0.21 2022-03-01 00:29:49 +01:00
Megamouse 42aa8f263a Qt: store pad settings state and remove max size 2022-02-28 08:19:13 +01:00
nastys af95ff5f8b Round macOS icon 2022-02-27 11:16:50 +01:00
nastys f0093375b8 Set min macOS version to 11.6 2022-02-27 11:16:50 +01:00
Ani 7d26e61d82 gui/themes: YoRHa by Ani (r2) (#10785)
- Styled Log Viewer
- Styled CG Disasm's text boxes
- Fixed list widget checkbox and row styling
- Fixed missing styling on Debugger
- Fixed text alignment on table headers
- Fixed QSpinBox buttons
- Styled disabled QSpinbox
- Styled Pad Settings tabs to look the same as Settings Dialog
- Centered Pad Settings tabs
- Separated first row from game list table headers so there's some 
spacing in between when highlighting that row
- Refactored some code to style global QT properties instead of specific 
RPCS3 elements
- Separated RPCS3 specific code from global code
2022-02-26 12:49:43 +00:00
kd-11 e035000864 vk: Do not enable passthrough DMA unconditionally (yet)
- There are still some kinks to work out. Host labels do not fix all the bugs which means I missed something.
2022-02-26 10:28:46 +03:00
kd-11 6db5d83615 Flush dma offloader on texture read sema 2022-02-25 10:53:55 +03:00
Eladash 86a04a867b Qt: show time of day in 'last played' game info, log current time when RPCS3 boots (#11220) 2022-02-23 23:40:18 +01:00
kd-11 f3823232e0 Disable passthrough DMA for proprietary intel driver 2022-02-23 21:15:08 +03:00
kd-11 6b8b23c401 vk: Drain the label queue before using the CPU fallback to avoid out-of-order signals
- This avoids crashes in some game engines which expect RSX semaphores to signal in the order they are submitted.
2022-02-23 12:57:04 +03:00
kd-11 6fd2a9b677 rsx: Remove leftover dprints 2022-02-23 12:57:04 +03:00
kd-11 da559b5568 vk/rsx: Tuning and optimization for host labels 2022-02-23 12:57:04 +03:00
kd-11 24587ab459 rsx: Add the option to the advanced tab 2022-02-23 12:57:04 +03:00
kd-11 c7e49b58a8 rsx: Implement host GPU sync labels 2022-02-23 12:57:04 +03:00
Megamouse c5680c29bd Qt: set organization name 2022-02-22 14:19:29 +01:00
Megamouse 1144121d08 shortcuts: add some logging, fix shortcut path 2022-02-22 14:19:29 +01:00
Megamouse fa6736e69d update_manager: add some logging 2022-02-22 14:19:29 +01:00
kd-11 10e6b43a2f Drop redundant declaration 2022-02-21 23:58:01 +03:00
kd-11 0809e7cf9f Fix build 2022-02-21 23:58:01 +03:00
kd-11 12fd43e1c6 vk: Remove unused variables 2022-02-21 23:58:01 +03:00
kd-11 397a795e75 vk: Remove hardcoded command buffer list length 2022-02-21 23:58:01 +03:00
kd-11 1f9ade0ab6 vk: Remove pointless function (VKGSRender::open_command_buffer)
A relic of the past, back before we wrote wrappers for raw handles.
2022-02-21 23:58:01 +03:00
kd-11 83407c386c vk: Move renderer types to a separate file
- Makes my life easier managing conflicts
2022-02-21 23:58:01 +03:00
kd-11 b791d90b35 vk: Rewrite command buffer chains 2022-02-21 23:58:01 +03:00
nastys 574e934bf3 macOS: Implement shortcuts 2022-02-21 19:11:52 +01:00
nastys b57ea3a229 Fix macOS builds 2022-02-21 19:11:52 +01:00
Megamouse 771f3c49e5 windows: fix windows shortcut paths 2022-02-21 01:14:53 +01:00
Megamouse 13e1305a76 linux: fix shortcut icon aspect ratio 2022-02-21 01:14:53 +01:00
Megamouse 9214df482e Unbreak macOS builds 2022-02-20 21:06:46 +01:00
Megamouse b1a9e87ecf cellSearch: fix cellSearchStartListSearch
Fixes listing BGM in Gundam.
The returned content was always empty.
Playback of the tracks will still require a MusicSelectionContext and cellMusic playback, which isn't implemented yet.
2022-02-20 21:06:46 +01:00
Megamouse 0a34403ef8 Qt: create rpcs3 shortcuts 2022-02-20 13:23:27 +01:00
Megamouse e5bb0ba004 Qt: properly hide metal sempahore if not apple 2022-02-20 13:23:27 +01:00
Megamouse 2147fe479c cellSearch: more logging 2022-02-20 12:29:37 +01:00
Megamouse 93e7988df7 rsx: add boost mode shortcut 2022-02-20 11:56:11 +01:00
nastys 7801e8368b Add MoltenVK Semaphore setting 2022-02-20 08:47:16 +01:00
Megamouse 91d7f28c67 cellSearch: log audio and video metadata 2022-02-19 14:27:47 +01:00
Megamouse 8171c7766c cellSearch: silence irrelevant log error 2022-02-19 14:27:47 +01:00
Megamouse 3f69ceac40 cellMusic: fix cellMusicSetVolume log messages 2022-02-19 14:27:47 +01:00
Megamouse 4be9e0d396 RSX: Fix rsx capture stop
RSX captures froze on stop, at least with Vulkan.
2022-02-16 19:50:57 +01:00
RipleyTom 6bd8a93ff4 Fixes some unchecked derefs in sceNp logging 2022-02-16 17:08:58 +01:00
Eladash e39797d860 Fix sys_fs_close FD state logging 2022-02-16 18:09:13 +03:00
kd-11 254ddcad51 vk/dma: Initialize COW DMA block contents to avoid leaks
- It is possible to lose data when uploading since the result of map_dma can change types and handles.
- Consider sync-on-exit for inherited spans

Not a problem when using passthrough DMA, but this extension does not work properly on NVIDIA + windows
2022-02-16 16:33:27 +03:00
kd-11 abd8bd6f36 Bump vulkan headers requirement 2022-02-15 22:30:59 +03:00
Eladash fd6c33980b cellSaveData: Check filename format of savedata files (#11502) 2022-02-14 22:03:40 +03:00
kd-11 2d5d5746d1 gl: Harmonize format conversion values
- Return values that are true to the PS3, not the host.
2022-02-13 15:31:39 +03:00
kd-11 314b63eebf vk: Drop unused native format ABGR8 2022-02-13 15:31:39 +03:00
kd-11 f382d54e9a gl: Remove pointless assert 2022-02-13 15:31:39 +03:00
kd-11 9581e4ff98 qt: Add translation resources 2022-02-13 14:39:42 +03:00
kd-11 b7a57ac4b0 qt: Update tooltips 2022-02-13 14:39:42 +03:00
kd-11 df5295ae85 vk: Per work-queue scratch resources
- Avoids parallel tasks from trampling over each other's data
2022-02-13 14:39:42 +03:00
kd-11 c8ad8b18bb vk: Ignore queue transfer stuff when using 'fast' mode 2022-02-13 14:39:42 +03:00
kd-11 44cc254620 Fix linux build 2022-02-13 14:39:42 +03:00
kd-11 cef512a123 vk: Spec-compliant async compute 2022-02-13 14:39:42 +03:00
Megamouse 7895d43a98 Terminate headless rpcs3 if nothing was booted 2022-02-12 12:46:07 +01:00
Megamouse 4f4a80cc04 Use RPCS3/asmjit fork 2022-02-12 02:54:00 +01:00
Megamouse d6597038ee Input: multithreaded handlers
Implements naive multithreading for input handlers.
2022-02-10 20:38:11 +01:00
kd-11 ec3e8de780 rsx: End the current frame before performing cache cleanup to release in-flight data 2022-02-10 22:20:56 +03:00
kd-11 f667b52cca vk: Rewrite resource management 2022-02-10 22:20:56 +03:00
kd-11 48b54131f6 vk: Fix up multiple resource allocation routines
- Originally part of async bringup. Imported to allow smoother transition.
2022-02-10 22:20:56 +03:00
Megamouse d172b9add6 Rename CallAfter to CallFromMainThread 2022-02-07 19:42:08 +01:00
kd-11 2d9f21a2ea rsx: Lower performance warnings to 'warn' level instead of 'error' level to avoid causing panic for users 2022-02-07 09:25:01 +03:00
kd-11 247759b75b rsx: Fix memory tagging and add some security checks 2022-02-07 09:25:01 +03:00
RipleyTom 987166f4da Fix IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP 2022-02-06 20:37:12 +01:00
kd-11 90d368ae30 vk: Speed up cached image search a bit 2022-02-06 15:49:50 +03:00
kd-11 a2d33a7d76 vk: Fix WCB crash 2022-02-06 15:49:50 +03:00
kd-11 51f9310b9f vk: Silence compiler warnings 2022-02-06 15:49:50 +03:00
kd-11 dca3d477c9 vk: Use image hot-cache for faster allocation times
- Creating new images is expensive.
- We can keep around a set of images that have been recently discarded and use them instead of creating new ones from scratch each time.
2022-02-06 15:49:50 +03:00
Megamouse 02cdf8ac63 Qt: save settings dialog window state 2022-02-06 13:02:16 +01:00
nastys 6b370e85d5 Add overlay animations 2022-02-06 12:26:34 +01:00
Megamouse 05e80aad90 Qt: make patch manager dialog resizable 2022-02-06 00:09:27 +01:00
Megamouse 4ad255b8e0 Qt: make about dialog resizable 2022-02-06 00:09:27 +01:00
Megamouse 09a60cdefa Qt: add scrollbar to settings dialog 2022-02-06 00:09:27 +01:00
Megamouse eacf5a3813 Qt: adjust wording for updates 2022-02-05 12:22:54 +01:00
Eladash e951c619c5 Implement Emulator::GracefulShutdown() 2022-02-05 11:49:29 +01:00
RipleyTom 6c5b8dc31c rpcn: add cookie impl to tickets 2022-02-03 13:25:15 +01:00
Megamouse fd0e7a4efa Qt: fix compat download abort 2022-02-01 21:21:42 +01:00
Megamouse a4c4548c3a input: add enumeration threads for each hid_pad_handler
There was a roughly 60 ms lag for each hid handler every 2 seconds. (sucks if you use all 3 hid handlers)
2022-02-01 19:28:04 +01:00
Megamouse 8efc29972d input: add missing nullptr checks for pad 2022-02-01 19:28:04 +01:00
Vestral 7977fbb9c5 Audio: prevent click at play/pause
Cubeb uses internal rate resampler and it's not being flushed during call to stream_stop.
This results in noticeable click when emulator is unpaused.
Reset last sample buffer on pause for all backends.
2022-01-31 21:20:57 +01:00
Vestral 681bab558b XAudio: fix deinitialization order 2022-01-31 21:20:57 +01:00
Vestral 107107107c SoundTouch resampler integration 2022-01-31 21:20:57 +01:00
Hyogi Sim 3a804674c9 Fix linkage error on debug build with clang-13
Debug build with clang-13 fails with "undefined references" to the
static const members in spu_channel class. This patch replaces the const
definitions with constexpr constants.
2022-01-31 17:05:18 +03:00
Malcolm Jestadt 91673f8fdc SPU LLVM: Add relaxed xfloat option
- This new setting is on by default
- It's active when approximate default is disabled
- Approximate xfloat is now exposed to the gui
2022-01-31 08:02:48 +03:00
kd-11 86919ec0e1 rsx: Validate requested images before attempting to upload them
- Do not allow dimensions of 0 to reach the backend APIs
2022-01-30 14:58:51 +03:00
kd-11 0e320d17c1 vk: Fix 'grow' behavior when we reach the size limit
- Just swap out the current heap ptr and spawn a fresh one. Chances are, we can spare 1GB of host memory.
2022-01-30 10:56:15 +03:00
kd-11 d063f0b335 vk: Fix working buffer calculation for emulated D16F operations 2022-01-30 10:56:15 +03:00
Eladash 781b2b4548 Implement fs::isfile (#11447) 2022-01-29 22:10:48 +03:00
nastys bb65e6797f macOS CI: Don't hardcode moltenVK and llvm version-specific paths 2022-01-27 11:40:32 +03:00
Megamouse b0f0641564 Windows Hotfix: Update hidapi 2022-01-26 22:02:27 +01:00
Nekotekina 16aae4eb77 Fixup creating image path 2022-01-26 15:46:16 +03:00
Nekotekina 3a1082fe0d Fix overlays::image_info constructor 2022-01-26 15:46:16 +03:00
Nekotekina dba2baba9c Implement utils::memory_map_fd (partial)
Improve JIT profiling dump format (data + name, mmap)
Improve objdump interception util (better speed, fix bugs)
Rename spu_ubertrampoline to __ub+number
2022-01-26 15:46:16 +03:00
kd-11 ffe00e8619 gl: Clean up format bitcast checks and register D32F type for FORMAT_CLASS16F
- Also hides a dangerous export for vulkan, same as GL
2022-01-26 12:08:36 +03:00
kd-11 3fa45ff994 Fix missing typeless info update 2022-01-26 12:08:36 +03:00
Eladash 73ff506b88 overlay_controls.cpp: Improve image_info ctor withstandability 2022-01-26 10:35:52 +03:00
kd-11 3a1676e558 vk: Fix float16 requirement issue 2022-01-25 21:34:21 +03:00
Nekotekina 0db9850a73 Add loop building utilities for ASMJIT
Refactor copy_data_swap_u32 a bit
2022-01-25 03:16:37 +03:00
Nekotekina 11ee1f3eb2 Improve JIT profiling on Linux
Add JIT object dumping functionality.
Add source for objdump interception utility.
2022-01-25 03:16:37 +03:00
Nekotekina 14951d8713 Fix abuse of fs::pending_file
Debug dumps don't fall into category which needs atomic rewrite.
2022-01-24 22:39:01 +03:00
Nekotekina 065ee621b8 Call avcodec_register_all in case of old ffmpeg
Apparently it's still possible to break without it.
2022-01-24 22:39:01 +03:00
Nekotekina 12c83b340d Remove built_function
With today's branch prediction techniques, it's hardly useful.
2022-01-24 22:21:41 +03:00
nastys d2897bc6a0 macOS: Fix DS3 init on Monterey 2022-01-24 20:16:57 +01:00
kd-11 5920372929 qt: Encourage users to use better ZCULL synchronization options
- From looking at logs, users are not actually changing ZCULL settings because they do not realize how slow 'Precise' mode is.
  By marking precise as the 'slowest' mode, we can get the message across that better options exist.
- Also updates the tooltips with more useful information.
2022-01-24 19:14:27 +03:00
kd-11 1fa82eec89 vk: Rework format feature validation
- Requirements have changed a lot over the years. We no longer blit Z formats around for example because they never support linear filtering
- Removing some unused requirements allows more hardware to be usable
2022-01-24 19:14:27 +03:00
RipleyTom 8c2fd50957 Add a QGroupBox in RPCN password window 2022-01-23 11:04:18 +01:00
kd-11 2f7d38bb81 rsx: Improve coverage checking logic to handle 3D and cubemap resources 2022-01-23 00:03:03 +03:00
kd-11 4f8b5849b7 rsx: Take depth into account when calculating coverage 2022-01-23 00:03:03 +03:00
kd-11 7f216f2581 rsx: Fix local slice height calculation 2022-01-23 00:03:03 +03:00
kd-11 6ffd38c393 vk: Only enable DCC workaround if the format features allow it 2022-01-22 13:16:48 +03:00
nastys 801e7f3c2f macOS: Implement texture swizzling for 16-bit formats 2022-01-22 00:17:17 +01:00
nastys c7140df5f8 Initial support for Apple GPUs 2022-01-22 00:17:17 +01:00
nastys 6b5f0957ce Disable macOS swizzling workaround 2022-01-22 00:17:17 +01:00
Jan Beich f2ed50e6b0 cellVdec: constify AVInputFormat for ffmpeg >= 5.0
rpcs3/Emu/Cell/Modules/cellAdec.cpp:326:19: error: assigning to 'AVInputFormat *' from 'const AVInputFormat *' discards qualifiers
                        input_format = av_find_input_format("oma");
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
rpcs3/Emu/Cell/Modules/cellAdec.cpp:332:19: error: assigning to 'AVInputFormat *' from 'const AVInputFormat *' discards qualifiers
                        input_format = av_find_input_format("mp3");
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
2022-01-21 21:36:17 +03:00
Jan Beich 511ca82e30 cellAVdec: constify AVCodec for ffmpeg >= 5.0
rpcs3/Emu/Cell/Modules/cellAdec.cpp:325:12: error: assigning to 'AVCodec *' from 'const AVCodec *' discards qualifiers
                        codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rpcs3/Emu/Cell/Modules/cellAdec.cpp:331:12: error: assigning to 'AVCodec *' from 'const AVCodec *' discards qualifiers
                        codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rpcs3/Emu/Cell/Modules/cellVdec.cpp:143:12: error: assigning to 'AVCodec *' from 'const AVCodec *' discards qualifiers
                        codec = avcodec_find_decoder(AV_CODEC_ID_MPEG2VIDEO);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rpcs3/Emu/Cell/Modules/cellVdec.cpp:148:12: error: assigning to 'AVCodec *' from 'const AVCodec *' discards qualifiers
                        codec = avcodec_find_decoder(AV_CODEC_ID_H264);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rpcs3/Emu/Cell/Modules/cellVdec.cpp:153:12: error: assigning to 'AVCodec *' from 'const AVCodec *' discards qualifiers
                        codec = avcodec_find_decoder(AV_CODEC_ID_MPEG4);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2022-01-21 21:36:17 +03:00
Nekotekina 00274bb4da PPU: port FP convert instructions to Aarch64 2022-01-21 16:07:48 +03:00
Nekotekina a4d94a83b9 PPU/simd.hpp: minor changes in DP instructions 2022-01-21 13:57:46 +03:00
Nekotekina 0de9960772 PPU: rewrite MFOCRF+MFCR instructions 2022-01-21 12:49:52 +03:00
Nekotekina aa7c9dd15d PPU: rewrite LVSL/LVSR instructions
Make the tables endian-agnostic.
2022-01-21 00:05:40 +03:00
Nekotekina 628354ba92 Use global variable in gv_zeroupper 2022-01-20 21:16:00 +03:00
Nekotekina 17b1a34ebf PPU: rewrite LVLX/LVRX/STVLX/STVRX instructions 2022-01-20 21:16:00 +03:00
Nekotekina 349f251d14 PPU LLVM: use masked stores for STVLX/STVRX
Drop maskmove intrinsic, not portable.
Its implicit NT hint may also hurt performance.
2022-01-20 21:16:00 +03:00
kd-11 3942a464fe vk: Avoid leaking descriptor copies 2022-01-20 19:21:24 +03:00
kd-11 2331dc3256 vk: Keep the total number of allocated samplers under control 2022-01-20 19:21:24 +03:00
Nekotekina 8c3fb3998c PPU: fix crash on SSE41 CPU in internal builder 2022-01-20 14:42:58 +03:00
Nekotekina 327c577024 PPU: print internal interpreter build error 2022-01-20 14:42:58 +03:00
Nekotekina d572d90bb7 PPU: fixup for old CPU
Abort building interpreter function when out of registers.
2022-01-20 08:31:08 +03:00
Nekotekina b42fae0989 PPU: refactor shift and splat instructions
Fix utils::rol32/64 functions.
Fix immediate clamping in splat instructions.
Other fixes.
2022-01-19 23:01:31 +03:00
Megamouse d92008abe4 Qt: fix RestoreDefaults crash
For some reason rpcs3 crashes when I restore the defaults of multiple configs one after another in the settings dialog.
Using the other signal seems to work.
I don't wanna investigate this nonsense though, so I'll just accept the fix as is.
2022-01-19 20:41:05 +01:00
Megamouse 484a3e6824 Qt: check for patch updates 2022-01-18 20:24:31 +01:00
Nekotekina 08b02efc6c ARM: don't calibrate TSC, use cntfrq_el0 info 2022-01-18 04:21:42 +03:00
Nekotekina 4728478247 PPU: improve interpreter codegen
Implement more sensible check for EVEX prefix and SSE
2022-01-18 04:20:06 +03:00
Nekotekina 4704367382 Remove unnecessary asmjit::imm_ptr 2022-01-18 00:10:32 +03:00
Nekotekina 14cca55b50 PPU: refactor vector rounding instructions
Fix: nearbyint -> roundeven
2022-01-18 00:10:32 +03:00
Nekotekina 248f9424ac PPU: refactor VPack instructions 2022-01-18 00:10:19 +03:00
Nekotekina b404d37eb0 PPU: more interpreter refactoring (VPERM)
Notably, runtime-built SSSE3 version of VPERM.
Some other instructions are refactored and vectorized.
Aarch64 impl of multiple instructions including VPERM.
2022-01-18 00:10:19 +03:00
Nekotekina 14170afe8a Fix PPU decoder settings dialog 2022-01-18 00:10:19 +03:00
RipleyTom 58fdf58150 Force close socket in sys_net_bnet_close 2022-01-17 21:27:20 +01:00
kd-11 000ec71629 Fix invalid descriptor setup if subdraw0 has broken vertex setup 2022-01-17 12:38:10 +03:00
kd-11 3e794e7fdb rsx: Optimize 8-bit rounding logic a bit
- NV hw does not like the raw use of round()
2022-01-17 10:28:23 +03:00
kd-11 c38ca21a81 rsx: Round up 8-bit ROP output on NVIDIA cards
- NV GPUs have a tendancy to be off by a very small margin, breaking rendering when greaterThan/lessThan checks are used.
- NOTE: Currently this setting is using the sRGB flag which indicates 8-bit output.
  Only one game is currently known to care about this behaviour so this is good enough for now.
2022-01-17 10:28:23 +03:00
kd-11 f923eaf09a rsx: Surface format remapping enhancements 2022-01-17 10:28:23 +03:00
Nekotekina 5b980b99a0 PPU: Rename new ppu_use_nj_bit setting to flip it back
Some mistakes were made.
2022-01-16 01:34:47 +03:00
Nekotekina 22240777aa PPU Interpreter: fix accuracy flag dispatch 2022-01-16 01:00:37 +03:00
Nekotekina f95395b351 PPU LLVM: improve accuracy of VSL/VSR
Passes tests, should now be equal to interpreter.
2022-01-15 21:13:31 +03:00
Nekotekina df24cff0b1 PPU LLVM: fix VMINFP and VMAXFP accuracy
PPU cache needs to be cleared.
2022-01-15 17:36:57 +03:00
Nekotekina 6dda047128 PPU LLVM: fix VNMSUBFP sign handling
PPU cache needs to be cleared.
2022-01-15 17:36:57 +03:00
Nekotekina e9efa73eed PPU: restore previous NJ mode handling option
Fix the divergence between PPU Interpreter and LLVM.
2022-01-15 17:36:57 +03:00
Megamouse 1c0b3fc7e0 Qt: Fix accurateXFloat enabled state in settings dialog 2022-01-15 13:48:03 +01:00
Nekotekina 580bd2b25e Initial Linux Aarch64 support
* Update asmjit dependency (aarch64 branch)
* Disable USE_DISCORD_RPC by default
* Dump some JIT objects in rpcs3 cache dir
* Add SIGILL handler for all platforms
* Fix resetting zeroing denormals in thread pool
* Refactor most v128:: utils into global gv_** functions
* Refactor PPU interpreter (incomplete), remove "precise"
* - Instruction specializations with multiple accuracy flags
* - Adjust calling convention for speed
* - Removed precise/fast setting, replaced with static
* - Started refactoring interpreters for building at runtime JIT
*   (I got tired of poor compiler optimizations)
* - Expose some accuracy settings (SAT, NJ, VNAN, FPCC)
* - Add exec_bytes PPU thread variable (akin to cycle count)
* PPU LLVM: fix VCTUXS+VCTSXS instruction NaN results
* SPU interpreter: remove "precise" for now (extremely non-portable)
* - As with PPU, settings changed to static/dynamic for interpreters.
* - Precise options will be implemented later
* Fix termination after fatal error dialog
2022-01-15 06:48:04 +03:00
kd-11 d6aa834b5f vk: Enable shading rate hack for all GPUs
- This is a hack, ideally we should be using coverage-based masking when writing the exploded texture.
- We do not have access to the fragment coverage mask and it is non-trivial to integrate it in a competent manner.
2022-01-14 10:21:38 +03:00
MSuih f526027778 Revert recent file system changes (#11370)
* Revert "FS: use std::filesystem::u8path"

This reverts commit cd016be86e.

* Revert "VFS: fix missing path deliminators"

This reverts commit 84753db574.

* Revert "Bugfix of Emulator::Load disc path searching"

This reverts commit b9179de288.

* Revert "fs: Reimplement path resolving using std::filesystem::weakly_canonical"

This reverts commit 0c4b2ff06b.
2022-01-13 07:24:04 +03:00
Malik Idrees Hasan Khan 949e93bec7 Fix typos (#11361) 2022-01-12 23:21:02 +01:00
Megamouse cd016be86e FS: use std::filesystem::u8path 2022-01-13 00:07:25 +03:00
Megamouse 84753db574 VFS: fix missing path deliminators 2022-01-13 00:07:25 +03:00
Eladash ef0bee9228 aes.cpp: Use secured memory resetting 2022-01-12 03:37:39 +03:00
Eladash a60cee6536 Update PPUTranslator::MTFSFI for its intention to be clearer 2022-01-12 03:37:39 +03:00
Eladash 108846055b shared_ptr.cpp: Remove std::swap specialization 2022-01-12 03:37:39 +03:00
Eladash b9179de288 Bugfix of Emulator::Load disc path searching
Turns out fs::file does not always fail when provding a path to a directory.
2022-01-12 03:37:39 +03:00
Eladash 0c4b2ff06b fs: Reimplement path resolving using std::filesystem::weakly_canonical 2022-01-12 03:37:39 +03:00
Silent 8c9090fd03 WolfSSL: Use a custom UTF-8 aware fopen on Windows
Fixes loading cacert.pem from Unicode directories
2022-01-12 03:35:15 +03:00
nastys ef66b002e0 Implement proper macOS version check (#11352) 2022-01-11 23:17:26 +01:00
nastys 0d1c0e72a6 macOS: Increase thread stack size to 8 MiB 2022-01-11 08:05:17 +03:00
nastys 37f24d8c1c Log maxfiles to file and stderr on *NIX 2022-01-11 08:05:17 +03:00
nastys 3571e6ef85 macOS: Set correct maxfiles (fixes shader cache and SPU LLVM) 2022-01-11 08:05:17 +03:00
nastys ed542b2cb4 macOS: Fix arrow keys 2022-01-10 22:54:06 +01:00
nastys b950651487 Update wolfssl 2022-01-10 20:34:12 +01:00
nastys 09700360f7 macOS: Warn if Vulkan is not supported 2022-01-10 19:18:49 +03:00
nastys 29a6db8960 Disable OpenGL on macOS 2022-01-10 19:18:49 +03:00
kd-11 6d737e61fd rsx: Use 32 bit integers for pitch
- RSX max pitch = 65536 which requires 17 bits
2022-01-10 12:27:30 +03:00
kd-11 d874ca5d8c cellGame: Fall back to VERSION field if APP_VER is missing from PARAM.SFO 2022-01-10 12:27:30 +03:00
Vestrel 1adc408ad7 More sys_uart packets (#11332)
* Additional sys_uart packets added
2022-01-10 03:43:54 +03:00
kd-11 83026fd263 rsx: use coverage ratio to determine when too much data is overlapping 2022-01-07 22:55:27 +03:00
kd-11 92824b6729 rsx: Rework invalidation tagging 2022-01-07 22:55:27 +03:00
kd-11 7563655221 rsx: Bump surface removal threshold values
- It is much slower to attempt surface removal than to render duplicates on the host GPU
2022-01-07 22:55:27 +03:00
kd-11 6889b48973 rsx: Add optimized version of section removal code 2022-01-07 22:55:27 +03:00
Vestral 9766d87126 cellAudio: fix enqueued samples computation 2022-01-07 09:48:51 +01:00
Eladash bba528e2ae rsx: Fix wrong fault report in initialization (#11323)
* rsx: Fix wrong fault report in initialization

* Ensure emu.isstopped() == true at RPCS3 startup

Based on zero initialization.
2022-01-05 20:41:01 +03:00
nastys 7c39c1de9b macOS CI 2022-01-04 21:23:53 +01:00
nastys 81c2fb508b Fix macOS hidapi CMakeLists 2022-01-04 21:23:53 +01:00
clienthax 350257e1a4 Fcntl 0xc0000007, 0xc0000015, 0xc000001c 2022-01-04 22:47:06 +03:00
Florin9doi 0e07d3c58f USB: Improve SingStar emulation 2022-01-04 18:03:23 +01:00
Ani 0d4543ca2a llvm: Update to latest submodule commit (#11325) 2022-01-03 02:33:20 +00:00
陈俊嘉 20cc2d7267 Add multi-config generator build support for Windows. 2022-01-02 23:59:54 +01:00
RipleyTom 39a832d07f hidapi CMakeLists.txt fix 2022-01-02 23:33:19 +01:00
Megamouse 13136ec083 Rebase hidapi to 0.11.0 2022-01-02 23:33:19 +01:00
Malcolm Jestadt 31a5a77ae5 SPU: Use REP MOVSB in do_dma_transfer
- Try to use REP MOVSB when the size of the transfer is above a certain threshold
- This threshold is determined by the ERMS and FSRM cpuid flags
- The threshold values are (roughly) taken from GLIBC
- A threshold of 0xFFFFFFFF indicates that the cpu has neither flag
2022-01-02 21:35:46 +03:00
Megamouse 1c014299eb HLE: fix some types 2022-01-02 18:18:31 +03:00
kd-11 7c47b0029c gl: Fully drop alignment restriction for compressed textures
- This is just not part of spec, there is no enforcement for multiple of block size for width or height of s3tc compressed images.
- This restriction does indeed exist for ASTC and ETC but we're not using those formats.
2022-01-02 14:29:38 +03:00
Ani 61d9852632 rpcs3_version: Bump to 0.0.20 (#11318) 2022-01-01 00:32:14 +00:00
Nekotekina cb2748ae08 Update ASMJIT (new upstream API) 2021-12-29 02:45:00 +03:00
Alex James 900d7df40f GDB: Rework to_hex/hex_to functions
macOS defines uint64 as an alias of unsigned long long. Drop the length
modifiers to resolve the warning on macOS:

rpcs3/rpcs3/Emu/GDB.cpp:107:37: warning: format specifies type 'unsigned long *' but the argument has type 'u64 *' (aka 'unsigned long long *') [-Wformat]
        sscanf_s(val.c_str(), "%" HEX_U64, &result);
                               ~~~~~~~~~~  ^~~~~~~

Also use std::from_chars to implement hex_to_{u8,u32,u64} instead of
sscanf.
2021-12-28 02:02:44 +03:00
clienthax 6837370a62 Handle SYS_NET_IPPROTO_IP get/setsockopt
Improve net logging.

Should allow latest vsh to load (Depending on windows version apparantly..)
2021-12-27 20:58:09 +03:00
Nekotekina 9cfdd8afea Fix builds on additional platforms
LLVMIntelJITEvents is awailable only Windows/Linux
2021-12-27 16:17:53 +03:00
Nekotekina 7b24df0957 Update LLVM commit 2021-12-27 02:24:28 +03:00
Nekotekina 122555fb66 Add an error check in JITAnnouncer event listener
This is a bit strange one.
2021-12-26 22:01:20 +03:00
Nekotekina d836033212 LLVM: enable some JIT events (Intel, Perf)
Made some related adjustments.
Currently incomplete.
2021-12-26 16:41:37 +03:00
Nekotekina 510041a873 rsx_methods.cpp: optimize compile time (120s to 10s)
Untemplate NV308A_COLOR
2021-12-26 14:40:21 +03:00
Nekotekina 8b4b6ba946 copy_data_swap_u32: build AVX-512 path 2021-12-26 14:40:21 +03:00
Nekotekina d36a715b24 Disable built_function on __APPLE__
Workaround for #11287
2021-12-26 14:40:21 +03:00
Nekotekina 599e00d6da BufferUtils: remove dead code (vertex streaming)
RIP. It won't be useful.
2021-12-26 14:40:21 +03:00
Nekotekina 3cd8891ab8 Re-refactor copy_data_swap_u32 again
Drop AVX2 path for now, since it usually operates on small data.
Rely on automatic SSE vectorization on recent compilers.
Side refactoring on JIT.h to workaround weird conflict issue.
2021-12-26 14:40:21 +03:00
Nekotekina e3e6fb5489 Don't use vm::preallocated flag in patch enclave allocs 2021-12-26 14:40:21 +03:00
kd-11 a9303acfdf rsx: Fix zclip w scaling 2021-12-26 12:50:31 +03:00
Josh Lay b4ec4f46b8 Fedora (35): Adjust to Pipewire adoption ++QT deps
Provided build steps didn't work on Fedora 35, these packages seem to settle things 😄
2021-12-26 09:20:56 +01:00
Eladash 6ee9d0f35f sys_rsx: Outlaw mapping sys_vm memory to RSX IO address-space 2021-12-25 02:22:49 +03:00
nastys a0040e6fb1 macOS: Implement texture converter for Metal (2) (#11289)
* macOS: Implement texture converter for Metal (2)

* Fix texture conversion formatting
2021-12-24 15:46:37 +03:00
kd-11 28d7af313b rsx: Remove noisy debug print 2021-12-24 15:13:33 +03:00
kd-11 39ef39aa4e rsx: Exercise caution when testing for overlaps in invalidated sections 2021-12-24 15:13:33 +03:00
kd-11 d9a1308624 Drop libwayland-client from official appimages 2021-12-24 11:35:50 +03:00
kd-11 56dd09f4fe rsx: Handle floating point shenanigans
- If near and far clip are too close together, the API will not distinguish between them leading to out of bounds values
2021-12-22 22:08:53 +03:00
kd-11 de495952fd rsx: Enable fallback for devices without wide integer Z buffers 2021-12-22 22:08:53 +03:00
kd-11 1ce5349199 rsx: Remove zclip hackery
- Calculates precise Z value as requested by the game
- Works properly if the underlying Z format matches the PS3 1:1 but may cause minor problems otherwise
2021-12-22 22:08:53 +03:00
Nekotekina dcd011048d Implement "built_function" utility (runtime-generated assembly)
Similar to build_function_asm, but links without indirection.
Achieved by emitting code directly into a byte array.
2021-12-22 19:27:20 +03:00
Nekotekina 12e3c9e08b Use PAUSE in vk::query_pool_manager::get_query_result 2021-12-21 23:28:09 +03:00
Nekotekina 262ff01619 Use aligned stores in write_index_array_data_to_buffer
Ensure that target buffer is cache line aligned.
Improve stx::make_single to support alignment.
2021-12-21 23:28:09 +03:00
Nekotekina 76ccaf5e6f BufferUtils: refactoring
Optimize CPU capability tests for arch-tuned builds.
Separate streaming and non-streaming utilities.
Rewritten copy_data_swap_u32(_cmp) with AVX2 path.
2021-12-21 23:28:09 +03:00
nastys 47e4a95d8f Fix remap_vector redefinition on macOS (#11271) 2021-12-21 10:36:09 +01:00
Nekotekina c0bafbc804 TSX: enable same data optimization for PUTLLC 2021-12-19 20:23:01 +03:00
Nekotekina 61c64d1060 TSX: refactoring M
Remove first stage 'optimistic' transactions.
2021-12-19 20:23:01 +03:00
Nekotekina 3e1e1a683c TSX/PPU: fix conditional store regression 2021-12-17 21:48:01 +03:00
Megamouse 18f59d3be8 Input: fix min stick input of keyboard pad handler 2021-12-17 17:21:44 +01:00
Megamouse bf739aa156 Input: implement stick multipliers for keyboard 2021-12-17 17:21:44 +01:00
RipleyTom 43b7d1fe98 Add missing virtual destructors to some base class 2021-12-15 18:05:55 +03:00
Megamouse cc21d1b3cf cellSaveData: prevent some potential crashes due to corrupt files 2021-12-14 20:30:47 +01:00
nastys 08333e0876 macOS moltenVK support and SIGBUS handling (#11252) 2021-12-12 21:35:56 +01:00
Malcolm Jestadt 2f93df480b SPU LLVM: Disable affineqb shufb paths temporarilly 2021-12-10 19:32:10 +03:00
Megamouse 56fe450959 Qt: fix screenshot path creation 2021-12-10 17:27:52 +01:00
clienthax 6f9adbd162 Debug SPRX check 2021-12-10 14:23:26 +01:00
Megamouse f48c535802 cellAudio: Recover XAudio on failed initialization 2021-12-09 01:46:44 +01:00
Megamouse 5f7e5a9844 cellAudio: relax FAudio error handling 2021-12-09 01:46:44 +01:00
Megamouse 3f3b4bc363 cellAudio: recover Cubeb on failed initialization 2021-12-09 01:46:44 +01:00
Megamouse 68466f05b6 cellAudio: move some stuff to cpp 2021-12-09 01:46:44 +01:00
Megamouse e6b4655142 cellAudio: use members instead of config values 2021-12-09 01:46:44 +01:00
xddxd f690d55045 Remove unnecessary define 2021-12-09 01:21:11 +01:00
kd-11 d523f9cc6b rsx: Avoid skipping input mask checks due to static flow control 2021-12-08 23:58:32 +03:00
kd-11 7ca15c60bb rsx: Improve image aspect tests
- Replace old format-based detection with proper aspect test.
  Explicit image aspect has been available for a long time, but older
  code was not updated.
2021-12-08 23:58:32 +03:00
Nekotekina 8abd3e8bb4 PPU LLVM: fix bitcast usage to enable constant folding 2021-12-07 15:35:51 +03:00
Nekotekina 6730dc1dc4 LLVM DSL: print some debug info in get_const_vector<v128> 2021-12-07 13:21:24 +03:00
Nekotekina 6b40d69a8f Introduce coroutine support (util/coro.hpp)
Implement coroutine types `lazy` and `generator` in stx namespace.
Implement fs::list_dir_recursively.
2021-12-07 13:04:10 +03:00
Nekotekina d6420b8803 Put std::hash specialization out of std 2021-12-07 13:04:10 +03:00
Megamouse a4ad0a9468 cellVideoOutConfigure: treat unknown aspect as AUTO 2021-12-06 20:50:57 +01:00
Void48 a09fd80905 Update README.md 2021-12-06 12:05:52 +01:00
Malcolm Jestadt 0617e9e14b SPU LLVM: Fix vgf2p8affineqb usage
- Reverse the order of the bytes in the selection masks. Previously it was assumed that byte 0 would determine the output of bit 0, but byte 7 determines the output of bit 0.
2021-12-06 12:34:11 +03:00
Eladash cb4711203b logging: Tell apart PPU access violation caused by executing unmapped memory 2021-12-05 01:22:32 +03:00
Nekotekina e3e39e8de3 PPU LLVM: rewrite and optimize saturation bit
Use vector accumulator
2021-12-03 00:14:06 +03:00
Nekotekina 209b14fbac PPU LLVM: inline remaining vector instructions 2021-12-03 00:14:06 +03:00
Nekotekina 04c9d01390 PPU LLVM: modernize most vector instructions
Rewritten VSUM instructions:
VSUMSWS, VSUM2SWS, VSUM4SBS, VSUM4SHS, VSUM4UBS
2021-12-03 00:14:06 +03:00
Nekotekina c9d8e59dbf PPU LLVM: allow to drop setting SAT flag (optimization, module-wide)
Implement ppu_attr::has_mfvscr (partially, module-wide search).
If this instruction isn't found, allow to drop setting SAT flag.
It's based on presumption that only MFVSCR can retrieve SAT flag.
2021-12-03 00:14:06 +03:00
Nekotekina 86b194014b PPU LLVM: rewrite more packing instructions
Rewritten VPKUHUM, VPKUHUS, VPKUWUM, VPKUWUS.
Decoupled saturation test from sat pack pattern.
2021-12-03 00:14:06 +03:00
Nekotekina e7c827f73b PPU LLVM: rewrite some packing instructions
Rewritten VPKSHSS, VPKSHUS, VPKSWSS, VPKSWUS.
Decoupled saturation test from sat pack pattern.
2021-12-03 00:14:06 +03:00
Nekotekina abe498f35c PPU LLVM: modernize some code with new DSL
PPU: rewritten instructions VMHADDSHS, VMHRADDSHS
PPU: added optimized path for VPERM (ra=rb)
2021-12-03 00:14:06 +03:00
DH 49c02854f5 [rsx] reduce size of config structs 2021-12-02 21:36:57 +03:00
DH cccfb89aa0 [Config] Use std::less<> for std::map<...>
Reduces amount of string copies
[Utilities] fmt::replace_all: avoid creation of temporary strings
2021-12-02 21:36:57 +03:00
DH 2981867375 sys_spu_thread: Removed unused field access 2021-12-02 21:36:57 +03:00
DH 56d922999f Fixed debug build compilation errors
const_str_t constructor without arguments shoud be constexpr for usage as default initializer in constexpr functions
2021-12-02 21:36:57 +03:00
DH 813c3298ad [Utilities] Fixed area_base operator* scalar type 2021-12-02 21:36:57 +03:00
kd-11 02832d9623 rsx: Add some sensible fallbacks (#11219)
* rsx: Add some sensible fallbacks

* Update GLPresent.cpp

* Update VKPresent.cpp

* Update rsx_utils.h

* Update rsx_utils.cpp
2021-12-02 16:02:08 +03:00
Eladash 0ab36ef44d sys_spu: Implement SPU image segment info checks (#11211) 2021-12-02 13:17:10 +03:00
kd-11 9bb46aa944 rsx: Simplify unconstrained aspect ratio conversion
- There is a reason resolutions are defined by only a height variable.
2021-12-01 21:55:53 +01:00
Megamouse 474baca6d8 rsx: default initialize RsxDisplayInfo 2021-12-01 21:55:53 +01:00
Megamouse 88d0b7d135 cellAvconfExt: add some trivial param checks 2021-12-01 21:55:53 +01:00
Megamouse aea1ec2594 avconf: Add const to fxo references 2021-12-01 21:55:53 +01:00
kd-11 22a7b026e7 rsx: Fix image scaling
- Specifically fixes a corner case where double transforms are required.
  Technically this can be made more readable using transformation matrices:
  * M1 = transform_virtual_to_physical()
  * M2 = transform_image_to_virtual()
  * M3 = M1 * M2
  * Result = Input * M3
  But we don't use a CPU-side matrix library and it is not reasonable to do this on the GPU.
2021-12-01 21:55:53 +01:00
Megamouse c8d4a0dcdc VK/GL: honor game's aspect ratio when scaling 2021-12-01 21:55:53 +01:00
Eladash f16949c292 fs::file: always use strict reading mode for large reads (#11206) 2021-12-01 19:09:07 +03:00
Jan Beich f910a152f1 CI: switch FreeBSD to Clang/libc++ 13 (#11214) 2021-11-30 16:12:37 +00:00
Megamouse 270c2e58a0 Update xxHash to version 0.8.1 2021-11-29 22:12:39 +01:00
Megamouse a586d1c529 Update glslang to version 11.7.1 2021-11-29 22:12:39 +01:00
Megamouse 09b047611b Update FAudio to version 21.11 2021-11-29 22:12:39 +01:00
Vestral e5005597fe CellAudio fixes 2021-11-29 20:43:00 +01:00
kd-11 38bfefcdfa vk: Fix incorrect mixed transfer modes for mipmapped VTC 2021-11-28 01:44:21 +03:00
kd-11 44fe6f6d39 rsx: Fix sloppy format matching test 2021-11-27 17:47:41 +03:00
RipleyTom 4fe17fcecf sys_usbd improvements (#11202) 2021-11-27 01:49:35 +00:00
RipleyTom 276ee81da8 Ignore Log subsection for config obsolete check 2021-11-25 19:42:12 +01:00
RipleyTom 5e158bd3f2 Impl sys_usbd_get_device_location 2021-11-25 00:53:00 +01:00
clienthax 2b924175aa Emulated v406 usio 2021-11-24 21:59:48 +01:00
Vestrel 37a722cc1d Audio backend improvements
Callback based audio update.
Upgraded common backend interface.
Added Cubeb backend.
Support multiple audio providers.
Dropped pulse, alsa, openal backends.
2021-11-24 19:41:05 +01:00
orbea a84223bdc6 rpcs3: Fix the DATADIR path for AppImage
Even when DATADIR is defined the other paths may still be correct.

Fixes: https://github.com/RPCS3/rpcs3/issues/11195
2021-11-24 19:14:06 +01:00
kd-11 4df1a938b1 Unused var 2021-11-24 16:02:24 +03:00
kd-11 94a3b1cfe8 rsx: Roll back some optimizations
- Just use RGB565 for all blit targets. Avoids really dumb transforms done by GPU hw.
- When X16 is used, all the channels get written to R channel alone. CmdBlit does perform format conversion!
- gl: Force image copy when blit is requested with compatible targets. Avoids format conversion issues.
2021-11-24 16:02:24 +03:00
kd-11 a21c6c4628 rsx: Fix handling of scaling requests for packed formats
- One does not simply interpolate RGB565 components as U16 data!
2021-11-24 16:02:24 +03:00
kd-11 58f0fa3ca5 gl: Enable handling of X16 blit targets 2021-11-24 16:02:24 +03:00
kd-11 97bd8f7bc1 rsx: Update sampler format class when inheriting mipmap slices/sections 2021-11-24 16:02:24 +03:00
clienthax 4c0ef37a5c Stub uvc camera init 2021-11-23 23:41:13 +01:00
AniLeo 1df8f52a9f vk: Remove lavapipe workaround
Current lavapipe version now has support for 
shaderStorageBufferArrayDynamicIndexing
2021-11-23 22:48:46 +01:00
shockdude f9434091c3 sys_usbd: make emulated turntable interrupt transfer as fast as possible
Also add missing mutex
2021-11-23 02:19:36 +00:00
orbea 59f253ba24 cmake: Use GNUInstalldirs 2021-11-22 21:45:55 +01:00
Eladash c52d447381 sys_fs: Place all path-format checks upfront, implement more checks 2021-11-22 21:03:07 +03:00
Eladash 524b065bc8 Debugger: Show PPU reservation data
Asterisk marks the offset of data that had been given to the guest PPU code.
2021-11-22 14:48:34 +03:00
Eladash f7b55ec8d4 lv2: Add missing reservation disowning in lv2_obj::yield 2021-11-22 14:48:34 +03:00
Megamouse e7fc2bfa3b Input: Log path on hid_open_path error 2021-11-22 09:41:12 +01:00
Megamouse 22e3075c64 cellSaveData: always log setList and setBuf
For debugging
2021-11-20 08:43:46 +01:00
Megamouse 09ead539a5 improvise CELL_SAVEDATA_ERRDIALOG_NOREPEAT 2021-11-20 08:43:46 +01:00
Megamouse 5272dd951b Qt: simplify callbacks.resolve_path 2021-11-20 08:43:46 +01:00
Megamouse 7eee9e7b05 overlays: simplify backup icon copy procedure 2021-11-20 08:43:46 +01:00
Eladash e5eb727110 Memory Searcher: Peek full string in log, fix case-insensitive search 2021-11-20 07:57:34 +01:00
Eladash 7352a5a495 GUI: Rename memory string searching tool to "Memory Searcher" 2021-11-20 07:57:34 +01:00
Nekotekina 3d859a7493 Update LLVM commit (fixup) 2021-11-18 18:47:54 +03:00
RipleyTom 3587cfd2df Update SpuTest to v1.1.2 2021-11-18 15:50:31 +01:00
Megamouse de2be90636 Qt: only show prefix for fatal messages
Always messages are supposed to be humanly readable
2021-11-17 22:53:20 +01:00
Artur 9f35c3f52d Properly recognize triggers and axes for evdev pads. 2021-11-17 21:29:24 +01:00
RipleyTom 22910c02a9 Implement sceNpManagerGetPsHandle (#11164) 2021-11-17 18:02:01 +00:00
Nekotekina fef8905dc2 Update LLVM commit 2021-11-16 15:13:34 +03:00
Megamouse 0f7534c755 VK: fix NVIDIA driverVersion check 2021-11-16 09:31:16 +01:00
Megamouse 4d0330bf82 rsx: fix possible segfault 2021-11-16 09:31:16 +01:00
Megamouse 026efd96b2 cellKbCnvRawCode: use proper constants
and comment out unreachable code
2021-11-16 09:31:16 +01:00
Megamouse f6af5ff13a cellRtcGetDaysInMonth: fix param check 2021-11-16 09:31:16 +01:00
Megamouse 0d7b7585a8 Some typo/warning fixes 2021-11-16 09:31:16 +01:00
Eladash 6283600b84 Qt: Fix log prefix in log_frame 2021-11-16 09:02:43 +01:00
Megamouse f6e04ffdd2 overlays: add stick input to native dialogs 2021-11-16 01:38:33 +01:00
Megamouse 44b42f68fd overlays: add R3, L3 and PS buttons
Unused at the moment
2021-11-16 01:38:33 +01:00
Megamouse 56241838c0 input: add made up CELL_PAD_CTRL_PS enum
And remove useless comment about 0x0 buttons. It's a bitmap, so 0x0 is literally useless.
2021-11-16 01:38:33 +01:00
Megamouse 26475f8f40 cellGem: add comment about hack 2021-11-16 01:38:33 +01:00
Megamouse ff5e31f396 overlays: add system sounds 2021-11-15 23:03:30 +01:00
kd-11 59b1c324a9 rsx: Properly implement immediate mode rendering
- Treat the draw commands as being consumed on-the-fly with ATTR0 as provoking attribute
- Analysing streams sent to RSX and the results implies they are consumed fully inline.
  This only makes sense if a provoking attribute is present. The 'static' register is truly the immediate register for the draw.
2021-11-15 18:14:15 +03:00
kd-11 1f627caa81 rsx: Clear some leaking register state between runs 2021-11-15 18:14:15 +03:00
Megamouse 7dc3a50ddf Fix headless mode 2021-11-14 17:07:18 +01:00
Eladash cfe08de951 Account empty EDAT (#11146)
* Improve sys_fs_open logging
2021-11-14 02:15:27 +03:00
Eladash 48ad959697 sys_event: Fix PPU queue forced uproot of waiters (#11147) 2021-11-13 20:22:54 +03:00
陈俊嘉 05881ffa62 Disable vulkan in Windows build when HAVE_VULKAN is off and other cmake build fixes. (#11118)
* Make WolfSSL build support multi-config generator.
Fix a build error in Windows when using QT's moc.
Disable vulkan in Windows build when HAVE_VULKAN is off.

* add WIN32_LEAN_AND_MEAN definition to VS project.
add HAVE_VULKAN definition to VS project.
Define NTSTATUS in main.cpp.
2021-11-13 16:11:49 +01:00
Megamouse 8b3ed7b599 Qt: fix initial pad settings dialog size and position 2021-11-11 23:06:57 +01:00
cglmrfreeman 48ad7ca3a0 Update OpenSUSE Qt5 dependencies (#11135) 2021-11-11 19:57:23 +01:00
Megamouse cbec04cd0f Curl: fix --verbose-curl option 2021-11-11 17:37:22 +01:00
Malcolm Jestadt 3fde455932 SPU LLVM: Optimize branch following ORX
- test the input of ORX directly for zeroes, instead of the result
2021-11-11 12:58:38 +03:00
RipleyTom ba727e13ae Fixes rpcn_client.h func ptr comparison warning 2021-11-11 08:11:14 +01:00
RipleyTom 2248007c9a Add HAVE_SNI definition to curl build for wolfssl 2021-11-11 07:35:59 +01:00
Megamouse 2359ba9aed curl: add verbose logging
and really verbose logging i you use --verbose-curl
2021-11-11 00:36:42 +01:00
RipleyTom b736691bde Special nullptr optParam->cbFunc case fix 2021-11-10 20:03:11 +01:00
RipleyTom 50bf528f3f NP: add signaling_handler wakeup on connect queue 2021-11-10 12:43:45 +01:00
kd-11 7e3eab9915 rsx: Fix texture state propagation between unrelated draw calls
- Older games can load all textures before a draw sequence and then swap shaders for different draws.
- Optimizations in texture state streaming make it so that only referenced data is carried forward.
2021-11-09 12:39:49 +03:00
RipleyTom dc0793b731 NP: Implement sceNpMatching2DeleteServerContext 2021-11-08 13:10:40 +03:00
RipleyTom c194804fec NP: Implement sceNpBasicGetFriendListEntry 2021-11-08 13:10:40 +03:00
RipleyTom d41e405420 NP: Cache Manager + improvements 2021-11-08 13:10:40 +03:00
RipleyTom 516cb959cb rpcn: new allocator + refactoring of np_handler 2021-11-08 13:10:40 +03:00
RipleyTom 704e74b904 rpcn: extra changes 2021-11-08 13:10:40 +03:00
Nick Renieris b70f08d850 The Velocity Improvements: RoomData/RoomMemberData commands & fixes
modules/np2: Correct some SceNpMaching2 ptr type endianness
np/handler: Use STL .contains() method
Ignore USECRYPTO & USESIGNATURE in recvfrom/sendto
Implement RoomData/RoomMemberData commands
2021-11-08 13:10:40 +03:00
Ani 53f2594983 llvm: Add AVX-512 detection for Alderlake (#11121) 2021-11-07 15:23:51 +00:00
Malcolm Jestadt 7573d7289b SPU LLVM: Hook up 128 bit spu verification
- Also fix FMA enablement for sapphirerapids
2021-11-06 21:12:12 +03:00
Megamouse f9abe40494 Qt: fix initial TSX selection 2021-11-06 13:47:43 +01:00
Megamouse 88bb26afb4 vk: make upscaler dynamic
The config option was marked as dynamic, but was never actually changed ingame
2021-11-06 01:02:54 +01:00
Megamouse dac0baac0d Qt: improve fsr tooltip area 2021-11-06 01:02:54 +01:00
kd-11 f7eacf70ec rsx: Restore shader disassembler to working state 2021-11-05 23:55:07 +03:00
Megamouse 067b35217a Qt: Consider TSX-FA in settings dialog 2021-11-04 23:34:10 +01:00
xddxd c3888f5bbb Specify the compiler for llvm_build (#11110) 2021-11-04 21:28:19 +00:00
Megamouse af3ef02ca0 fix npDrmIsAvailable 2021-11-04 21:41:07 +01:00
Eladash c49ebba648 Fixes of PS3 filesystem EDAT/SDAT handling
* Return EFSSPEIFIC if encountered corrupted EDAT or an unmatched key in sys_fs_open and sys_fs_read.
* Fix validate_dev_klic() for license-free EDAT.
* Fix EDATADecrypter::ReadData() for when size + pos > file_size but pos < file_size.
* Try to save up to 16 decryption keys. Educated guess based on NPDRM file descriptors count llimit.
* Return LICENCE_NOT_FOUND if needed RAP file is not found in sceNpDrmIsAvailable.
* Check additional sys_fs_open errors for sceNpDrmOpen. (EISDIR, ENOTMOUNTED)
2021-11-04 21:32:15 +03:00
kd-11 933d96af5f vk: Do not clip region using renderpass renderarea, we have scissor for that 2021-11-04 21:05:15 +03:00
Whatcookie bf6044fced SPU/SYSINFO: Disable TSX by default for TSX-FA cpus (#11105)
- Also detect the new RTM_ALWAYS_ABORT bit in cpuid
- This new bit indicates that RTM is disabled in the microcode
- On cpus with RTM_ALWAYS_ABORT TSX can be renabled by writing 0x4 to the msr 0x0000010F
2021-11-04 16:44:25 +00:00
Ani 1a0392bf15 CPUTranslator: Enable FMA for alderlake CPUs (#11106) 2021-11-03 19:31:46 +00:00
kd-11 ad00c44231 rsx: Configure pitch correctly for pitch-zero textures (1D) 2021-11-03 16:58:30 +03:00
Nekotekina 69f321a471 LLVM 13 2021-11-02 20:11:08 +03:00
Malcolm Jestadt 37383f4217 SPU ASMJIT: Disable 512 wide spu verification
- Apparantly this crashes every game.
2021-11-01 20:04:26 +03:00
Eladash b84e95d768 rsx: Fixate time stamp of VBLANK 2021-11-01 10:04:53 +01:00
Eladash 4369fb234e rsx: Fix typo in VBLANK processing regarding emulation pause 2021-11-01 10:04:53 +01:00
Eladash 58040d478a rsx: Implement NTSC fixup mode, improve VBLANK accuracy 2021-11-01 10:04:53 +01:00
418 changed files with 44942 additions and 20275 deletions
+10 -4
View File
@@ -7,10 +7,16 @@ git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ { print $3 }'
# Prefer newer Clang than in base system (see also .ci/install-freebsd.sh)
# libc++ isn't in llvm* packages, so download manually
fetch https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/libcxx-12.0.0.src.tar.xz
tar xf libcxx-12.0.0.src.tar.xz
export CC=clang12 CXX=clang++12
export CXXFLAGS="$CXXFLAGS -nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -isystem $PWD/libcxx-12.0.0.src/include"
fetch https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-13.0.1-rc1.tar.gz
tar xf llvm*.tar.gz
export CC=clang13 CXX=clang++13
cmake -B libcxx_build -G Ninja -S llvm*/libcxx \
-DLLVM_CCACHE_BUILD=ON \
-DCMAKE_INSTALL_PREFIX:PATH=libcxx_prefix
cmake --build libcxx_build
cmake --install libcxx_build
export CXXFLAGS="$CXXFLAGS -nostdinc++ -isystem$PWD/libcxx_prefix/include/c++/v1"
export LDFLAGS="$LDFLAGS -nostdlib++ -L$PWD/libcxx_prefix/lib -l:libc++.a -lcxxrt"
CONFIGURE_ARGS="
-DWITH_LLVM=OFF
+61 -20
View File
@@ -1,27 +1,68 @@
#!/bin/sh -ex
export CCACHE_SLOPPINESS=pch_defines,time_macros
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5/
export PATH="/usr/local/opt/ccache/libexec:$PATH"
brew update
brew install llvm@13 molten-vk vulkan-headers sdl2 nasm qt@5 ninja cmake glew git p7zip create-dmg ccache
# Setup vulkan and gfx-rs/portability
curl -sLO https://github.com/gfx-rs/portability/releases/download/latest/gfx-portability-macos-latest.zip
unzip -: gfx-portability-macos-latest.zip
curl -sLO https://github.com/KhronosGroup/Vulkan-Headers/archive/sdk-1.1.106.0.zip
unzip -: sdk-*.zip
mkdir vulkan-sdk
ln -s "${PWD}"/Vulkan-Headers*/include vulkan-sdk/include
mkdir vulkan-sdk/lib
cp target/release/libportability.dylib vulkan-sdk/lib/libVulkan.dylib
# Let macdeployqt locate and install Vulkan library
install_name_tool -id "${PWD}"/vulkan-sdk/lib/libVulkan.dylib vulkan-sdk/lib/libVulkan.dylib
export VULKAN_SDK="${PWD}/vulkan-sdk"
export CXX=clang++
export CC=clang
export Qt5_DIR="/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5"
export PATH="/usr/local/opt/llvm/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin"
export LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"
export CPPFLAGS="-I/usr/local/opt/llvm/include -msse -msse2 -mcx16 -no-pie"
export CPLUS_INCLUDE_PATH="/usr/local/opt/molten-vk/include"
export VULKAN_SDK="/usr/local/opt/molten-vk"
export VK_ICD_FILENAMES="$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json"
# Pull all the submodules except llvm
# Note: Tried to use git submodule status, but it takes over 20 seconds
# shellcheck disable=SC2046
git submodule -q update --init $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
git submodule update --init --recursive --depth 1
# 3rdparty fixes
ln -s "$VULKAN_SDK/lib/libMoltenVK.dylib" "$VULKAN_SDK/lib/libvulkan.dylib"
sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVersionNumber = 1343;/g" 3rdparty/hidapi/hidapi/mac/hid.c
cd ..
mkdir build && cd build || exit 1
cmake .. -DWITH_LLVM=OFF -DUSE_NATIVE_INSTRUCTIONS=OFF -G Ninja
cmake -DUSE_DISCORD_RPC=OFF -DUSE_VULKAN=ON -DUSE_ALSA=OFF -DUSE_PULSE=OFF -DUSE_AUDIOUNIT=ON \
-G Ninja -DLLVM_CCACHE_BUILD=OFF -DLLVM_TARGETS_TO_BUILD="X86" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF \
-DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF \
-DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_PERF=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF \
-DCMAKE_CXX_STANDARD=20 -DUSE_NATIVE_INSTRUCTIONS=OFF \
../cirrus-ci-build/
ninja
cd ../cirrus-ci-build/
COMM_TAG="$(grep 'version{.*}' rpcs3/rpcs3_version.cpp | awk -F[\{,] '{printf "%d.%d.%d", $2, $3, $4}')"
COMM_COUNT="$(git rev-list --count HEAD)"
COMM_HASH="$(git rev-parse --short=8 HEAD)"
cd ../build/bin
mkdir "rpcs3.app/Contents/lib/"
cp "/usr/local/opt/llvm/lib/libc++abi.1.0.dylib" "rpcs3.app/Contents/lib/libc++abi.1.dylib"
rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
"rpcs3.app/Contents/Frameworks/QtQml.framework" \
"rpcs3.app/Contents/Frameworks/QtQmlModels.framework" \
"rpcs3.app/Contents/Frameworks/QtQuick.framework" \
"rpcs3.app/Contents/Frameworks/QtVirtualKeyboard.framework" \
"rpcs3.app/Contents/Plugins/platforminputcontexts" \
"rpcs3.app/Contents/Plugins/virtualkeyboard"
mv rpcs3.app RPCS3_.app
mv RPCS3_.app RPCS3.app
echo "[InternetShortcut]" > Quickstart.url
echo "URL=https://rpcs3.net/quickstart" >> Quickstart.url
echo "IconIndex=0" >> Quickstart.url
create-dmg --volname RPCS3 \
--window-size 800 400 \
--icon-size 100 \
--icon rpcs3.app 200 190 \
--add-file Quickstart.url Quickstart.url 400 20 \
--hide-extension rpcs3.app \
--hide-extension Quickstart.url \
--app-drop-link 600 185 \
--skip-jenkins \
"$ARTDIR/rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_macos.dmg" \
RPCS3.app
7z a -mx9 rpcs3-v"${COMM_TAG}"-"${COMM_COUNT}"-"${COMM_HASH}"_macos.7z RPCS3.app
mv rpcs3-v"${COMM_TAG}"-"${COMM_COUNT}"-"${COMM_HASH}"_macos.7z "$ARTDIR"
+5
View File
@@ -18,6 +18,11 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
# Embed newer libstdc++ for distros that don't come with it (ubuntu 16.04)
mkdir -p appdir/usr/optional/ ; mkdir -p appdir/usr/optional/libstdc++/
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./appdir/usr/optional/libstdc++/
# Remove libwayland-client because it has platform-dependent exports and breaks other OSes
rm -f ./appdir/usr/lib/libwayland-client.so*
# Install latest appimage runner
rm ./appdir/AppRun
curl -sL https://github.com/RPCS3/AppImageKit-checkrt/releases/download/continuous2/AppRun-patched-x86_64 -o ./appdir/AppRun
chmod a+x ./appdir/AppRun
+1 -1
View File
@@ -9,7 +9,7 @@ export ASSUME_ALWAYS_YES=true
pkg info # debug
# Prefer newer Clang than in base system (see also .ci/build-freebsd.sh)
pkg install llvm12
pkg install llvm13
# Mandatory dependencies (qt5-dbus and qt5-gui are pulled via qt5-widgets)
pkg install git ccache cmake ninja qt5-qmake qt5-buildtools qt5-widgets qt5-concurrent qt5-multimedia qt5-svg glew openal-soft ffmpeg
+20
View File
@@ -111,3 +111,23 @@ freebsd_task:
folder: /tmp/ccache_dir
install_script: "sh -ex ./.ci/install-freebsd.sh"
script: "./.ci/build-freebsd.sh"
macos_task:
timeout_in: 120m
ccache_cache:
folder: /tmp/ccache_dir
matrix:
- name: Cirrus macOS
osx_instance:
image: big-sur-base
mac_script:
- mkdir artifacts
- ".ci/build-mac.sh"
env:
ARTDIR: ${CIRRUS_WORKING_DIR}/artifacts/
CCACHE_DIR: "/tmp/ccache_dir"
CCACHE_MAXSIZE: 300M
CI_HAS_ARTIFACTS: true
artifacts:
name: Artifact
path: "artifacts/rpcs3-*_macos.*"
+10 -2
View File
@@ -4,8 +4,8 @@
ignore = dirty
[submodule "asmjit"]
path = 3rdparty/asmjit/asmjit
url = ../../asmjit/asmjit.git
branch = oldstable
url = ../../RPCS3/asmjit.git
branch = aarch64
ignore = dirty
[submodule "llvm"]
path = llvm
@@ -68,3 +68,11 @@
path = 3rdparty/flatbuffers
url = ../../google/flatbuffers.git
ignore = dirty
[submodule "3rdparty/cubeb/cubeb"]
path = 3rdparty/cubeb/cubeb
url = ../../mozilla/cubeb.git
ignore = dirty
[submodule "3rdparty/SoundTouch/soundtouch"]
path = 3rdparty/SoundTouch/soundtouch
url = ../../RPCS3/soundtouch.git
ignore = dirty
+5 -33
View File
@@ -128,38 +128,11 @@ target_include_directories(3rdparty_stblib INTERFACE stblib/include)
# DiscordRPC
add_subdirectory(discord-rpc)
# Cubeb
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
# ALSA
set(ALSA_TARGET 3rdparty_dummy_lib)
if(USE_ALSA)
find_package(ALSA)
if(ALSA_FOUND)
add_library(3rdparty_alsa INTERFACE)
target_compile_definitions(3rdparty_alsa INTERFACE -DHAVE_ALSA)
target_include_directories(3rdparty_alsa SYSTEM INTERFACE ${ALSA_INCLUDE_DIRS})
target_link_libraries(3rdparty_alsa INTERFACE ${ALSA_LIBRARIES})
set(ALSA_TARGET 3rdparty_alsa)
endif()
endif()
# Pulse
set(PULSE_TARGET 3rdparty_dummy_lib)
if(USE_PULSE)
pkg_check_modules(PULSE libpulse-simple)
if(PULSE_FOUND)
add_library(3rdparty_pulse INTERFACE)
target_compile_definitions(3rdparty_pulse INTERFACE -DHAVE_PULSE)
target_include_directories(3rdparty_pulse SYSTEM
INTERFACE ${PULSE_INCLUDE_DIRS})
target_link_libraries(3rdparty_pulse INTERFACE ${PULSE_LDFLAGS})
set(PULSE_TARGET 3rdparty_pulse)
endif()
endif()
# SoundTouch
add_subdirectory(SoundTouch EXCLUDE_FROM_ALL)
# libevdev
set(LIBEVDEV_TARGET 3rdparty_dummy_lib)
@@ -334,8 +307,6 @@ add_library(3rdparty::libpng ALIAS ${LIBPNG_TARGET})
add_library(3rdparty::opengl ALIAS 3rdparty_opengl)
add_library(3rdparty::stblib ALIAS 3rdparty_stblib)
add_library(3rdparty::discordRPC ALIAS 3rdparty_discordRPC)
add_library(3rdparty::alsa ALIAS ${ALSA_TARGET})
add_library(3rdparty::pulse ALIAS ${PULSE_TARGET})
add_library(3rdparty::faudio ALIAS ${FAUDIO_TARGET})
add_library(3rdparty::libevdev ALIAS ${LIBEVDEV_TARGET})
add_library(3rdparty::vulkan ALIAS ${VULKAN_TARGET})
@@ -344,3 +315,4 @@ add_library(3rdparty::ffmpeg ALIAS 3rdparty_ffmpeg)
add_library(3rdparty::glew ALIAS 3rdparty_glew)
add_library(3rdparty::wolfssl ALIAS wolfssl)
add_library(3rdparty::libcurl ALIAS libcurl)
add_library(3rdparty::soundtouch ALIAS soundtouch)
+34
View File
@@ -0,0 +1,34 @@
add_library(soundtouch STATIC EXCLUDE_FROM_ALL
soundtouch/source/SoundTouch/AAFilter.cpp
soundtouch/source/SoundTouch/FIFOSampleBuffer.cpp
soundtouch/source/SoundTouch/FIRFilter.cpp
soundtouch/source/SoundTouch/InterpolateCubic.cpp
soundtouch/source/SoundTouch/InterpolateLinear.cpp
soundtouch/source/SoundTouch/InterpolateShannon.cpp
soundtouch/source/SoundTouch/RateTransposer.cpp
soundtouch/source/SoundTouch/SoundTouch.cpp
soundtouch/source/SoundTouch/sse_optimized.cpp
soundtouch/source/SoundTouch/TDStretch.cpp
)
target_include_directories(soundtouch PRIVATE
soundtouch/source/SoundTouch
soundtouch/include)
target_include_directories(soundtouch INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/soundtouch/include>
$<INSTALL_INTERFACE:/soundtouch/include>)
set_property(TARGET soundtouch PROPERTY FOLDER "3rdparty/")
target_compile_definitions(soundtouch PUBLIC
ST_NO_EXCEPTION_HANDLING
USE_MULTICH_ALWAYS
SOUNDTOUCH_FLOAT_SAMPLES;
)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86|amd64|AMD64|em64t|EM64T)")
target_compile_definitions(soundtouch PUBLIC
SOUNDTOUCH_ALLOW_SSE
)
endif ()
+77
View File
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="soundtouch\include\FIFOSampleBuffer.h" />
<ClInclude Include="soundtouch\include\FIFOSamplePipe.h" />
<ClInclude Include="soundtouch\include\SoundTouch.h" />
<ClInclude Include="soundtouch\include\STTypes.h" />
<ClInclude Include="soundtouch\source\SoundTouch\AAFilter.h" />
<ClInclude Include="soundtouch\source\SoundTouch\FIRFilter.h" />
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateCubic.h" />
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateLinear.h" />
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateShannon.h" />
<ClInclude Include="soundtouch\source\SoundTouch\RateTransposer.h" />
<ClInclude Include="soundtouch\source\SoundTouch\TDStretch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="soundtouch\source\SoundTouch\AAFilter.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\FIFOSampleBuffer.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\FIRFilter.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateCubic.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateLinear.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateShannon.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\RateTransposer.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\SoundTouch.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\sse_optimized.cpp" />
<ClCompile Include="soundtouch\source\SoundTouch\TDStretch.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{508c291a-3d18-49f5-b25d-f7c8db92cb21}</ProjectGuid>
<RootNamespace>soundtouch</RootNamespace>
</PropertyGroup>
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>SOUNDTOUCH_ALLOW_SSE;ST_NO_EXCEPTION_HANDLING;USE_MULTICH_ALWAYS;SOUNDTOUCH_FLOAT_SAMPLES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./soundtouch/source/SoundTouch;./soundtouch/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="soundtouch\include\FIFOSampleBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\include\FIFOSamplePipe.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\include\SoundTouch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\include\STTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\FIRFilter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateCubic.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateLinear.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\InterpolateShannon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\RateTransposer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\TDStretch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="soundtouch\source\SoundTouch\AAFilter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateLinear.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateShannon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\RateTransposer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\SoundTouch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\sse_optimized.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\TDStretch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\AAFilter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\FIFOSampleBuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\FIRFilter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="soundtouch\source\SoundTouch\InterpolateCubic.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+132 -52
View File
@@ -11,66 +11,146 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="asmjit\src\asmjit\base\arch.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codebuilder.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codecompiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codeemitter.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codeholder.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\constpool.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\cpuinfo.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\func.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\globals.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\logging.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\osutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\regalloc.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\runtime.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\string.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\vmem.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\zone.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\archtraits.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\codeholder.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\codewriter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\constpool.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\cpuinfo.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emitter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emitterutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\environment.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\errorhandler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\formatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\funcargscontext.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\func.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\globals.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\jitallocator.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\jitruntime.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\logger.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\osutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\ralocal.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\rastack.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\string.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\support.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\target.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\type.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\virtmem.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zone.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonehash.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonelist.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonestack.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonetree.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonevector.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instimpl.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86internal.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86logging.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86formatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86func.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instapi.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instdb.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86operand_regs.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86regalloc.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64instapi.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64instdb.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\armformatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\armfunc.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="asmjit\src\asmjit\base\arch.h" />
<ClInclude Include="asmjit\src\asmjit\base\assembler.h" />
<ClInclude Include="asmjit\src\asmjit\base\codebuilder.h" />
<ClInclude Include="asmjit\src\asmjit\base\codecompiler.h" />
<ClInclude Include="asmjit\src\asmjit\base\codeemitter.h" />
<ClInclude Include="asmjit\src\asmjit\base\codeholder.h" />
<ClInclude Include="asmjit\src\asmjit\base\constpool.h" />
<ClInclude Include="asmjit\src\asmjit\base\context_p.h" />
<ClInclude Include="asmjit\src\asmjit\base\cpuinfo.h" />
<ClInclude Include="asmjit\src\asmjit\base\func.h" />
<ClInclude Include="asmjit\src\asmjit\base\logging.h" />
<ClInclude Include="asmjit\src\asmjit\base\globals.h" />
<ClInclude Include="asmjit\src\asmjit\base\inst.h" />
<ClInclude Include="asmjit\src\asmjit\base\lock.h" />
<ClInclude Include="asmjit\src\asmjit\base\operand.h" />
<ClInclude Include="asmjit\src\asmjit\base\osutils.h" />
<ClInclude Include="asmjit\src\asmjit\base\regalloc_p.h" />
<ClInclude Include="asmjit\src\asmjit\base\runtime.h" />
<ClInclude Include="asmjit\src\asmjit\base\string.h" />
<ClInclude Include="asmjit\src\asmjit\base\vectypes.h" />
<ClInclude Include="asmjit\src\asmjit\base\vmem.h" />
<ClInclude Include="asmjit\src\asmjit\base\zone.h" />
<ClInclude Include="asmjit\src\asmjit\core\api-build_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\api-config.h" />
<ClInclude Include="asmjit\src\asmjit\core\archcommons.h" />
<ClInclude Include="asmjit\src\asmjit\core\archtraits.h" />
<ClInclude Include="asmjit\src\asmjit\core\assembler.h" />
<ClInclude Include="asmjit\src\asmjit\core\builder.h" />
<ClInclude Include="asmjit\src\asmjit\core\codebuffer.h" />
<ClInclude Include="asmjit\src\asmjit\core\codeholder.h" />
<ClInclude Include="asmjit\src\asmjit\core\codewriter_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\compilerdefs.h" />
<ClInclude Include="asmjit\src\asmjit\core\compiler.h" />
<ClInclude Include="asmjit\src\asmjit\core\constpool.h" />
<ClInclude Include="asmjit\src\asmjit\core\cpuinfo.h" />
<ClInclude Include="asmjit\src\asmjit\core\emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\emitter.h" />
<ClInclude Include="asmjit\src\asmjit\core\emitterutils_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\environment.h" />
<ClInclude Include="asmjit\src\asmjit\core\errorhandler.h" />
<ClInclude Include="asmjit\src\asmjit\core\formatter.h" />
<ClInclude Include="asmjit\src\asmjit\core\formatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\funcargscontext_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\func.h" />
<ClInclude Include="asmjit\src\asmjit\core\globals.h" />
<ClInclude Include="asmjit\src\asmjit\core\inst.h" />
<ClInclude Include="asmjit\src\asmjit\core\jitallocator.h" />
<ClInclude Include="asmjit\src\asmjit\core\jitruntime.h" />
<ClInclude Include="asmjit\src\asmjit\core\logger.h" />
<ClInclude Include="asmjit\src\asmjit\core\misc_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\operand.h" />
<ClInclude Include="asmjit\src\asmjit\core\osutils.h" />
<ClInclude Include="asmjit\src\asmjit\core\osutils_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\raassignment_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rabuilders_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\radefs_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\ralocal_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rastack_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\string.h" />
<ClInclude Include="asmjit\src\asmjit\core\support.h" />
<ClInclude Include="asmjit\src\asmjit\core\target.h" />
<ClInclude Include="asmjit\src\asmjit\core\type.h" />
<ClInclude Include="asmjit\src\asmjit\core\virtmem.h" />
<ClInclude Include="asmjit\src\asmjit\core\zone.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonehash.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonelist.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonestack.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonestring.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonetree.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonevector.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86archtraits_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86assembler.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86builder.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86compiler.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86inst.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instimpl_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86internal_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86logging_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86emitter.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86formatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86func_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86globals.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instapi_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instdb.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instdb_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86opcode_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86operand.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86regalloc_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64assembler.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64builder.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64compiler.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64emitter.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64globals.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instapi_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instdb.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instdb_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64operand.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64utils.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armarchtraits_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armformatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armfunc_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armglobals.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armoperand.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AC40FF01-426E-4838-A317-66354CEFAE88}</ProjectGuid>
+132 -52
View File
@@ -1,65 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="asmjit\src\asmjit\base\arch.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codebuilder.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codecompiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codeemitter.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\codeholder.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\constpool.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\cpuinfo.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\func.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\globals.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\logging.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\osutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\regalloc.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\runtime.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\string.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\vmem.cpp" />
<ClCompile Include="asmjit\src\asmjit\base\zone.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\archtraits.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\codeholder.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\codewriter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\constpool.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\cpuinfo.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emitter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\emitterutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\environment.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\errorhandler.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\formatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\funcargscontext.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\func.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\globals.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\jitallocator.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\jitruntime.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\logger.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\osutils.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\ralocal.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\rastack.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\string.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\support.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\target.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\type.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\virtmem.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zone.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonehash.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonelist.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonestack.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonetree.cpp" />
<ClCompile Include="asmjit\src\asmjit\core\zonevector.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86inst.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instimpl.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86internal.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86logging.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86formatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86func.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instapi.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86instdb.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86operand_regs.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86regalloc.cpp" />
<ClCompile Include="asmjit\src\asmjit\x86\x86rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64assembler.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64builder.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64compiler.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64emithelper.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64instapi.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64instdb.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64operand.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\a64rapass.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\armformatter.cpp" />
<ClCompile Include="asmjit\src\asmjit\arm\armfunc.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="asmjit\src\asmjit\base\arch.h" />
<ClInclude Include="asmjit\src\asmjit\base\assembler.h" />
<ClInclude Include="asmjit\src\asmjit\base\codebuilder.h" />
<ClInclude Include="asmjit\src\asmjit\base\codecompiler.h" />
<ClInclude Include="asmjit\src\asmjit\base\codeemitter.h" />
<ClInclude Include="asmjit\src\asmjit\base\codeholder.h" />
<ClInclude Include="asmjit\src\asmjit\base\constpool.h" />
<ClInclude Include="asmjit\src\asmjit\base\context_p.h" />
<ClInclude Include="asmjit\src\asmjit\base\cpuinfo.h" />
<ClInclude Include="asmjit\src\asmjit\base\func.h" />
<ClInclude Include="asmjit\src\asmjit\base\logging.h" />
<ClInclude Include="asmjit\src\asmjit\base\globals.h" />
<ClInclude Include="asmjit\src\asmjit\base\inst.h" />
<ClInclude Include="asmjit\src\asmjit\base\lock.h" />
<ClInclude Include="asmjit\src\asmjit\base\operand.h" />
<ClInclude Include="asmjit\src\asmjit\base\osutils.h" />
<ClInclude Include="asmjit\src\asmjit\base\regalloc_p.h" />
<ClInclude Include="asmjit\src\asmjit\base\runtime.h" />
<ClInclude Include="asmjit\src\asmjit\base\string.h" />
<ClInclude Include="asmjit\src\asmjit\base\vectypes.h" />
<ClInclude Include="asmjit\src\asmjit\base\vmem.h" />
<ClInclude Include="asmjit\src\asmjit\base\zone.h" />
<ClInclude Include="asmjit\src\asmjit\core\api-build_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\api-config.h" />
<ClInclude Include="asmjit\src\asmjit\core\archcommons.h" />
<ClInclude Include="asmjit\src\asmjit\core\archtraits.h" />
<ClInclude Include="asmjit\src\asmjit\core\assembler.h" />
<ClInclude Include="asmjit\src\asmjit\core\builder.h" />
<ClInclude Include="asmjit\src\asmjit\core\codebuffer.h" />
<ClInclude Include="asmjit\src\asmjit\core\codeholder.h" />
<ClInclude Include="asmjit\src\asmjit\core\codewriter_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\compilerdefs.h" />
<ClInclude Include="asmjit\src\asmjit\core\compiler.h" />
<ClInclude Include="asmjit\src\asmjit\core\constpool.h" />
<ClInclude Include="asmjit\src\asmjit\core\cpuinfo.h" />
<ClInclude Include="asmjit\src\asmjit\core\emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\emitter.h" />
<ClInclude Include="asmjit\src\asmjit\core\emitterutils_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\environment.h" />
<ClInclude Include="asmjit\src\asmjit\core\errorhandler.h" />
<ClInclude Include="asmjit\src\asmjit\core\formatter.h" />
<ClInclude Include="asmjit\src\asmjit\core\formatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\funcargscontext_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\func.h" />
<ClInclude Include="asmjit\src\asmjit\core\globals.h" />
<ClInclude Include="asmjit\src\asmjit\core\inst.h" />
<ClInclude Include="asmjit\src\asmjit\core\jitallocator.h" />
<ClInclude Include="asmjit\src\asmjit\core\jitruntime.h" />
<ClInclude Include="asmjit\src\asmjit\core\logger.h" />
<ClInclude Include="asmjit\src\asmjit\core\misc_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\operand.h" />
<ClInclude Include="asmjit\src\asmjit\core\osutils.h" />
<ClInclude Include="asmjit\src\asmjit\core\osutils_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\raassignment_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rabuilders_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\radefs_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\ralocal_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\rastack_p.h" />
<ClInclude Include="asmjit\src\asmjit\core\string.h" />
<ClInclude Include="asmjit\src\asmjit\core\support.h" />
<ClInclude Include="asmjit\src\asmjit\core\target.h" />
<ClInclude Include="asmjit\src\asmjit\core\type.h" />
<ClInclude Include="asmjit\src\asmjit\core\virtmem.h" />
<ClInclude Include="asmjit\src\asmjit\core\zone.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonehash.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonelist.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonestack.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonestring.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonetree.h" />
<ClInclude Include="asmjit\src\asmjit\core\zonevector.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86archtraits_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86assembler.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86builder.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86compiler.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86inst.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instimpl_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86internal_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86logging_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86emitter.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86formatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86func_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86globals.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instapi_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instdb.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86instdb_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86opcode_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86operand.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86regalloc_p.h" />
<ClInclude Include="asmjit\src\asmjit\x86\x86rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64assembler.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64builder.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64compiler.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64emithelper_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64emitter.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64globals.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instapi_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instdb.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64instdb_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64operand.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64rapass_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\a64utils.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armarchtraits_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armformatter_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armfunc_p.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armglobals.h" />
<ClInclude Include="asmjit\src\asmjit\arm\armoperand.h" />
</ItemGroup>
</Project>
+12
View File
@@ -0,0 +1,12 @@
# Cubeb
function(add_sanitizers ...)
endfunction(add_sanitizers)
set(BUILD_SHARED_LIBS FALSE CACHE BOOL "Don't build shared libs")
set(BUILD_TESTS FALSE CACHE BOOL "Don't build tests")
set(BUILD_RUST_LIBS FALSE CACHE BOOL "Don't build rust libs")
set(BUILD_TOOLS FALSE CACHE BOOL "Don't build tools")
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
add_library(3rdparty::cubeb ALIAS cubeb)
Vendored Submodule
+1
Submodule 3rdparty/cubeb/cubeb added at d512bfa07a
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define CUBEB_EXPORT
+87
View File
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cubeb\src\cubeb.c" />
<ClCompile Include="cubeb\src\cubeb_log.cpp" />
<ClCompile Include="cubeb\src\cubeb_mixer.cpp" />
<ClCompile Include="cubeb\src\cubeb_resampler.cpp" />
<ClCompile Include="cubeb\src\cubeb_strings.c" />
<ClCompile Include="cubeb\src\cubeb_utils.cpp" />
<ClCompile Include="cubeb\src\cubeb_wasapi.cpp" />
<ClCompile Include="cubeb\src\cubeb_winmm.c" />
<ClCompile Include="cubeb\src\speex\resample.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="cubeb\include\cubeb\cubeb.h" />
<ClInclude Include="cubeb\src\cubeb-internal.h" />
<ClInclude Include="cubeb\src\cubeb-speex-resampler.h" />
<ClInclude Include="cubeb\src\cubeb_array_queue.h" />
<ClInclude Include="cubeb\src\cubeb_assert.h" />
<ClInclude Include="cubeb\src\cubeb_log.h" />
<ClInclude Include="cubeb\src\cubeb_mixer.h" />
<ClInclude Include="cubeb\src\cubeb_resampler.h" />
<ClInclude Include="cubeb\src\cubeb_resampler_internal.h" />
<ClInclude Include="cubeb\src\cubeb_ringbuffer.h" />
<ClInclude Include="cubeb\src\cubeb_ring_array.h" />
<ClInclude Include="cubeb\src\cubeb_strings.h" />
<ClInclude Include="cubeb\src\cubeb_utils.h" />
<ClInclude Include="cubeb\src\cubeb_utils_win.h" />
<ClInclude Include="cubeb\src\speex\arch.h" />
<ClInclude Include="cubeb\src\speex\fixed_generic.h" />
<ClInclude Include="cubeb\src\speex\resample_neon.h" />
<ClInclude Include="cubeb\src\speex\resample_sse.h" />
<ClInclude Include="cubeb\src\speex\speex_config_types.h" />
<ClInclude Include="cubeb\src\speex\speex_resampler.h" />
<ClInclude Include="cubeb\src\speex\stack_alloc.h" />
<ClInclude Include="extra\cubeb_export.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{fda7b080-03b0-48c8-b24f-88118981422a}</ProjectGuid>
<RootNamespace>libcubeb</RootNamespace>
</PropertyGroup>
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>OUTSIDE_SPEEX;RANDOM_PREFIX=speex;FLOATING_POINT;EXPORT=;USE_WASAPI;USE_WINMM;CUBEB_WASAPI_USE_IAUDIOSTREAMVOLUME;_HAS_DEPRECATED_RESULT_OF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./cubeb/src/speex/;./extra/;./cubeb/src/;./cubeb/include/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+108
View File
@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="cubeb\src\speex\resample.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_winmm.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_utils.cpp">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_wasapi.cpp">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_strings.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_resampler.cpp">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_mixer.cpp">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb_log.cpp">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="cubeb\src\cubeb.c">
<Filter>Source files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="cubeb\include\cubeb\cubeb.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\arch.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_array_queue.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_assert.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="extra\cubeb_export.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_log.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_mixer.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_resampler.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_resampler_internal.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_ring_array.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_ringbuffer.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_strings.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_utils.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb_utils_win.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb-internal.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\cubeb-speex-resampler.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\fixed_generic.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\resample_neon.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\resample_sse.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\speex_config_types.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\speex_resampler.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="cubeb\src\speex\stack_alloc.h">
<Filter>Header files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Source files">
<UniqueIdentifier>{cd86de6d-e811-4c48-9653-af00c7098a45}</UniqueIdentifier>
</Filter>
<Filter Include="Header files">
<UniqueIdentifier>{566bbf3e-ca28-4390-b054-58c92a66f24e}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
+1
View File
@@ -7,6 +7,7 @@ if(USE_SYSTEM_CURL)
target_link_libraries(libcurl INTERFACE CURL::libcurl)
else()
message("-- RPCS3: building libcurl + wolfssl submodules")
add_compile_definitions(HAVE_SNI)
option(BUILD_CURL_EXE "Set to ON to build curl executable." OFF)
option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" ON)
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" ON)
+1 -1
View File
@@ -2,7 +2,7 @@
add_library(3rdparty_discordRPC INTERFACE)
# We don't want Discord Rich Presence on the BSDs and other OSes
if (USE_DISCORD_RPC AND (WIN32 OR CMAKE_SYSTEM MATCHES "Linux" OR APPLE))
if (USE_DISCORD_RPC AND (WIN32 OR CMAKE_SYSTEM MATCHES "Linux" OR APPLE) AND COMPILER_X86)
if (WIN32 AND NOT MSVC)
ExternalProject_Add(discordRPC
GIT_REPOSITORY https://github.com/discordapp/discord-rpc
+9 -14
View File
@@ -1,25 +1,20 @@
# hidapi
set(BUILD_SHARED_LIBS FALSE CACHE BOOL "Don't build shared libs")
set(HIDAPI_INSTALL_TARGETS FALSE CACHE BOOL "Don't install anything")
if(CMAKE_SYSTEM MATCHES "Linux")
set(HIDAPI_WITH_LIBUSB FALSE CACHE BOOL "Don't build with libusb for linux")
endif()
add_library(3rdparty_hidapi INTERFACE)
target_include_directories(3rdparty_hidapi INTERFACE hidapi/hidapi)
add_subdirectory(hidapi EXCLUDE_FROM_ALL)
if(APPLE)
add_subdirectory(hidapi/mac EXCLUDE_FROM_ALL)
target_include_directories(hidapi-mac PUBLIC hidapi/hidapi)
target_link_libraries(3rdparty_hidapi INTERFACE hidapi-mac "-framework CoreFoundation" "-framework IOKit")
target_link_libraries(3rdparty_hidapi INTERFACE hidapi_darwin "-framework CoreFoundation" "-framework IOKit")
elseif(CMAKE_SYSTEM MATCHES "Linux")
add_subdirectory(hidapi/linux EXCLUDE_FROM_ALL)
target_include_directories(hidapi-hidraw PUBLIC hidapi/hidapi)
target_link_libraries(3rdparty_hidapi INTERFACE hidapi-hidraw udev)
elseif(WIN32)
add_subdirectory(hidapi/windows EXCLUDE_FROM_ALL)
target_include_directories(hidapi-hid PUBLIC hidapi/hidapi)
target_link_libraries(3rdparty_hidapi INTERFACE hidapi-hid Shlwapi.lib)
else()
add_subdirectory(hidapi/libusb EXCLUDE_FROM_ALL)
target_include_directories(hidapi-libusb PUBLIC hidapi/hidapi)
target_link_libraries(3rdparty_hidapi INTERFACE hidapi-libusb usb)
endif()
+31 -4
View File
@@ -1,8 +1,10 @@
if(WITH_LLVM)
CHECK_CXX_COMPILER_FLAG("-msse -msse2 -mcx16" COMPILER_X86)
CHECK_CXX_COMPILER_FLAG("-march=armv8-a+lse" COMPILER_ARM)
if(BUILD_LLVM_SUBMODULE)
message(STATUS "LLVM will be built from the submodule.")
set(LLVM_TARGETS_TO_BUILD "X86" CACHE INTERNAL "")
option(LLVM_BUILD_RUNTIME OFF)
option(LLVM_BUILD_TOOLS OFF)
option(LLVM_INCLUDE_BENCHMARKS OFF)
@@ -13,6 +15,15 @@ if(WITH_LLVM)
option(LLVM_INCLUDE_UTILS OFF)
option(LLVM_CCACHE_BUILD ON)
if(WIN32)
set(LLVM_USE_INTEL_JITEVENTS ON)
endif()
if(CMAKE_SYSTEM MATCHES "Linux")
set(LLVM_USE_INTEL_JITEVENTS ON)
set(LLVM_USE_PERF ON)
endif()
set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS})
if (MSVC)
@@ -26,7 +37,7 @@ if(WITH_LLVM)
set(CMAKE_CXX_FLAGS ${CXX_FLAGS_OLD})
# now tries to find LLVM again
find_package(LLVM 11.0 CONFIG)
find_package(LLVM 13.0 CONFIG)
if(NOT LLVM_FOUND)
message(FATAL_ERROR "Couldn't build LLVM from the submodule. You might need to run `git submodule update --init`")
endif()
@@ -39,7 +50,7 @@ if(WITH_LLVM)
set(LLVM_DIR ${CMAKE_SOURCE_DIR}/${LLVM_DIR})
endif()
find_package(LLVM 11.0 CONFIG)
find_package(LLVM 13.0 CONFIG)
if (NOT LLVM_FOUND)
if (LLVM_VERSION AND LLVM_VERSION_MAJOR LESS 11)
@@ -52,7 +63,23 @@ if(WITH_LLVM)
endif()
endif()
set(LLVM_LIBS LLVMMCJIT LLVMX86CodeGen LLVMX86AsmParser)
set(LLVM_LIBS LLVMMCJIT)
if(COMPILER_X86)
set(LLVM_LIBS ${LLVM_LIBS} LLVMX86CodeGen LLVMX86AsmParser)
endif()
if(COMPILER_ARM)
set(LLVM_LIBS ${LLVM_LIBS} LLVMX86CodeGen LLVMX86AsmParser LLVMARMCodeGen LLVMARMAsmParser)
endif()
if(WIN32 OR CMAKE_SYSTEM MATCHES "Linux")
set(LLVM_LIBS ${LLVM_LIBS} LLVMIntelJITEvents)
endif()
if(CMAKE_SYSTEM MATCHES "Linux")
set(LLVM_LIBS ${LLVM_LIBS} LLVMPerfJITEvents)
endif()
add_library(3rdparty_llvm INTERFACE)
target_link_libraries(3rdparty_llvm INTERFACE ${LLVM_LIBS})
+1 -12
View File
@@ -27,18 +27,7 @@ else()
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
# TODO(cjj19970505@live.cn)
# This only works in single-config generator
# For a multi-config generator, we need to provide different wolfssl binaries for different config
if (GENERATOR_IS_MULTI_CONFIG)
message( FATAL_ERROR "RPCS3 can only be configured using single-config generator." )
endif()
if(MSVC)
set(WolfSSL_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/${CMAKE_BUILD_TYPE}/wolfssl.lib" CACHE INTERNAL "")
else()
set(WolfSSL_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/libwolfssl.a" CACHE INTERNAL "")
endif()
set(WolfSSL_LIBRARY "$<TARGET_FILE:wolfssl>" CACHE INTERNAL "")
# "${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/wolfssl/" provides openssl headers
# So that curl can be built on an environment where openssl headers are not provided
+74
View File
@@ -0,0 +1,74 @@
#ifndef _WIN_USER_SETTINGS_H_
#define _WIN_USER_SETTINGS_H_
/* Verify this is Windows */
#ifndef _WIN32
#error This user_settings.h header is only designed for Windows
#endif
/* Configurations */
#define WOLFSSL_DES_ECB
#define HAVE_FFDHE_2048
#define TFM_TIMING_RESISTANT
#define NO_DSA
#define TFM_ECC256
#define NO_RC4
#define NO_HC128
#define NO_RABBIT
#define WOLFSSL_SHA224
#define WOLFSSL_SHA384
#define WOLFSSL_SHA3
#define WOLFSSL_SHA512
#define WOLFSSL_SHAKE256
#define HAVE_POLY1305
#define HAVE_ONE_TIME_AUTH
#define HAVE_CHACHA
#define HAVE_HASHDRBG
#define HAVE_SNI
#define HAVE_ENCRYPT_THEN_MAC
#define NO_MD4
#define WC_NO_ASYNC_THREADING
#define WC_NO_HARDEN
#define HAVE_WRITE_DUP
#define WC_RSA_BLINDING
#define NO_MULTIBYTE_PRINT
#define OPENSSL_EXTRA
#define WOLFSSL_RIPEMD
#define NO_PSK
#define HAVE_EXTENDED_MASTER
#define WOLFSSL_SNIFFER
#define HAVE_AESGCM
#define HAVE_SUPPORTED_CURVES
#define HAVE_TLS_EXTENSIONS
#define HAVE_ECC
#define ECC_SHAMIR
#define ECC_TIMING_RESISTANT
/* UTF-8 aware filesystem functions for Windows */
#define WOLFSSL_USER_FILESYSTEM
#include <stdio.h>
#define XFILE FILE*
extern FILE* wolfSSL_fopen_utf8(const char* name, const char* mode);
#define XFOPEN wolfSSL_fopen_utf8
#define XFDOPEN fdopen
#define XFSEEK fseek
#define XFTELL ftell
#define XREWIND rewind
#define XFREAD fread
#define XFWRITE fwrite
#define XFCLOSE fclose
#define XSEEK_END SEEK_END
#define XBADFILE NULL
#define XFGETS fgets
#define XFPRINTF fprintf
#define XFFLUSH fflush
#include <sys/stat.h>
#define XSTAT _stat
#define XS_ISREG(s) (s & _S_IFREG)
#define SEPARATOR_CHAR ';'
#endif /* _WIN_USER_SETTINGS_H_ */
+7 -6
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@@ -47,8 +47,8 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;CYASSL_USER_SETTINGS;WC_NO_HARDEN;HAVE_WRITE_DUP;WC_RSA_BLINDING;NO_MULTIBYTE_PRINT;OPENSSL_EXTRA;WOLFSSL_RIPEMD;NO_PSK;HAVE_EXTENDED_MASTER;WOLFSSL_SNIFFER;HAVE_AESGCM;WOLFSSL_SHA384;WOLFSSL_SHA512;HAVE_SUPPORTED_CURVES;HAVE_TLS_EXTENSIONS;HAVE_ECC;ECC_SHAMIR;ECC_TIMING_RESISTANT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./wolfssl;./extra/win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -61,8 +61,8 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;CYASSL_USER_SETTINGS;WC_NO_HARDEN;HAVE_WRITE_DUP;WC_RSA_BLINDING;NO_MULTIBYTE_PRINT;OPENSSL_EXTRA;WOLFSSL_RIPEMD;NO_PSK;HAVE_EXTENDED_MASTER;WOLFSSL_SNIFFER;HAVE_AESGCM;WOLFSSL_SHA384;WOLFSSL_SHA512;HAVE_SUPPORTED_CURVES;HAVE_TLS_EXTENSIONS;HAVE_ECC;ECC_SHAMIR;ECC_TIMING_RESISTANT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./wolfssl;./extra/win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -105,6 +105,7 @@
<ClCompile Include="wolfssl\wolfcrypt\src\hmac.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\idea.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\integer.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\kdf.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\logging.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\md2.c" />
<ClCompile Include="wolfssl\wolfcrypt\src\md4.c" />
@@ -136,6 +137,7 @@
<ClCompile Include="wolfssl\wolfcrypt\src\wolfevent.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="extra\win32\user_settings.h" />
<ClInclude Include="wolfssl\resource.h" />
<CustomBuild Include="wolfssl\wolfcrypt\src\aes_asm.asm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
@@ -151,7 +153,6 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)%(Filename).obj</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">$(IntDir)%(Filename).obj</Outputs>
</CustomBuild>
<ClInclude Include="wolfssl\IDE\WIN\user_settings.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wolfssl\wolfssl.rc">
+7 -7
View File
@@ -11,7 +11,7 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
* [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
* [Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
* [Vulkan SDK 1.2.154+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
* [Vulkan SDK 1.2.198+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.15.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
@@ -22,18 +22,18 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst
* Clang 12+ or GCC 11+
* [CMake 3.16.9+](https://www.cmake.org/download/)
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
* [Vulkan SDK 1.2.154+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
* [Vulkan SDK 1.2.198+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
* [SDL2](https://www.libsdl.org/download-2.0.php) (for the FAudio backend)
**If you have an NVIDIA GPU, you may need to install the libglvnd package.**
#### Arch Linux
sudo pacman -S glew openal cmake vulkan-validation-layers qt5-base qt5-declarative sdl2
sudo pacman -S glew openal cmake vulkan-validation-layers qt5-base qt5-declarative sdl2 sndio jack2
#### Debian & Ubuntu
sudo apt-get install build-essential libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl2-2.0 libsdl2-dev
sudo apt-get install build-essential libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl2-2.0 libsdl2-dev libjack-dev libsndio-dev
Ubuntu is usually horrendously out of date, and some packages need to be downloaded by hand. This part is for Qt, GCC, Vulkan, and CMake
##### Qt PPA
@@ -64,7 +64,7 @@ For Ubuntu systems, it is strongly recommended to use the PPA from [LunarG](http
```
. /etc/os-release
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.154-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.154/lunarg-vulkan-1.2.154-$UBUNTU_CODENAME.list
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.198-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.198/lunarg-vulkan-1.2.198-$UBUNTU_CODENAME.list
sudo apt update
sudo apt install vulkan-sdk
```
@@ -82,11 +82,11 @@ sudo apt-get install cmake
#### Fedora
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-qtbase-devel qt5-qtbase-private-devel vulkan-devel
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-qtbase-devel qt5-qtbase-private-devel vulkan-devel pipewire-jack-audio-connection-kit-devel qt5-qtmultimedia-devel qt5-qtsvg-devel
#### OpenSUSE
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libqt5gui-private-headers-devel libevdev-devel
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libqt5-qtmultimedia-devel libqt5-qtsvg-devel libQt5Gui-private-headers-devel libevdev-devel libsndio7_1 libjack-devel
## Setup the project
+25 -22
View File
@@ -15,11 +15,9 @@ endif()
option(USE_NATIVE_INSTRUCTIONS "USE_NATIVE_INSTRUCTIONS makes rpcs3 compile with -march=native, which is useful for local builds, but not good for packages." ON)
option(WITH_LLVM "Enable usage of LLVM library" ON)
option(BUILD_LLVM_SUBMODULE "Build LLVM from git submodule" ON)
option(USE_ALSA "ALSA audio backend" ON)
option(USE_PULSE "PulseAudio audio backend" ON)
option(USE_FAUDIO "FAudio audio backend" ON)
option(USE_LIBEVDEV "libevdev-based joystick support" ON)
option(USE_DISCORD_RPC "Discord rich presence integration" ON)
option(USE_DISCORD_RPC "Discord rich presence integration" OFF)
option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON)
option(USE_VULKAN "Vulkan render backend" ON)
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
@@ -28,16 +26,17 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/buildfiles/cmake")
include(CheckCXXCompilerFlag)
# TODO(cjj19970505@live.cn)
# Currently cmake config scripts are single-config generator only.
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTI_CONFIG)
message(FATAL_ERROR "Multi-config generators are not supported.")
endif()
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
# TODO(cjj19970505@live.cn)
# Currently DicordRPC is included as a binary compiled with /MT flag.
# We need all 4 binaries(/MT /MTd /MD /MDd) or including the source instead of binary.
set(USE_DISCORD_RPC OFF CACHE BOOL "Discord RPC is only avaliable with single-config generator" FORCE)
else()
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
endif()
endif()
if(CMAKE_BUILD_TYPE MATCHES "Debug" AND NOT MSVC)
@@ -47,21 +46,23 @@ endif()
if(MSVC)
option(USE_MSVC_STATIC_CRT "Use static MSVC C runtime" OFF)
# TODO(cjj19970505@live.cno)
# TODO(cjj19970505@live.cn)
# 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(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)
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
# 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
@@ -71,18 +72,20 @@ if(MSVC)
# TODO(cjj19970505@live.cn)
# offical QT uses dynamic CRT.
# When building our lib with static CRT and debug build type
# and linking with Qt with dynmaic 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,
# and linking with Qt with dynmaic 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 AND CMAKE_BUILD_TYPE MATCHES "Debug")
message(AUTHOR_WARNING "Debug build currently can not work with static CRT.")
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()
endif()
+1 -1
View File
@@ -3,7 +3,7 @@ RPCS3
[![Azure Build Status](https://dev.azure.com/nekotekina/nekotekina/_apis/build/status/RPCS3.rpcs3?branchName=master)](https://dev.azure.com/nekotekina/nekotekina/_build?definitionId=4&branchName=master)
[![Cirrus CI - Base Branch Build Status](https://img.shields.io/cirrus/github/RPCS3/rpcs3?label=Cirrus%20CI%20(FreeBSD)&logo=cirrus-ci)](https://cirrus-ci.com/github/RPCS3/rpcs3)
[![RPCS3 discord server](https://img.shields.io/discord/272035812277878785?color=%237289DA&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.me/rpcs3)
[![RPCS3 discord server](https://img.shields.io/discord/272035812277878785?color=5865F2&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.me/rpcs3)
The world's first free and open-source PlayStation 3 emulator/debugger, written in C++ for Windows and Linux.
+24 -19
View File
@@ -19,8 +19,8 @@ namespace cfg
}
}
_base::_base(type _type, node* owner, const std::string& name, bool dynamic)
: m_type(_type), m_dynamic(dynamic), m_name(name)
_base::_base(type _type, node* owner, std::string name, bool dynamic)
: m_type(_type), m_dynamic(dynamic), m_name(std::move(name))
{
for (const auto& node : owner->m_nodes)
{
@@ -33,7 +33,7 @@ namespace cfg
owner->m_nodes.emplace_back(this);
}
bool _base::from_string(const std::string&, bool)
bool _base::from_string(std::string_view, bool)
{
cfg_log.fatal("cfg::_base::from_string() purecall");
return false;
@@ -58,7 +58,7 @@ std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
return {std::to_string(min), std::to_string(max)};
}
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
{
s64 result;
const char* start = &value.front();
@@ -104,7 +104,7 @@ std::vector<std::string> cfg::make_uint_range(u64 min, u64 max)
return {std::to_string(min), std::to_string(max)};
}
bool try_to_uint64(u64* out, const std::string& value, u64 min, u64 max)
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
{
u64 result;
const char* start = &value.front();
@@ -136,7 +136,7 @@ bool try_to_uint64(u64* out, const std::string& value, u64 min, u64 max)
return true;
}
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string& value)
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value)
{
u64 max = umax;
@@ -320,7 +320,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
return;
}
std::map<std::string, std::string> values;
map_of_type<std::string> values;
for (const auto& pair : data)
{
@@ -339,7 +339,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
return; // ???
}
std::map<std::string, logs::level> values;
map_of_type<logs::level> values;
for (const auto& pair : data)
{
@@ -377,9 +377,9 @@ std::string cfg::node::to_string() const
return {out.c_str(), out.size()};
}
bool cfg::node::from_string(const std::string& value, bool dynamic)
bool cfg::node::from_string(std::string_view value, bool dynamic)
{
auto [result, error] = yaml_load(value);
auto [result, error] = yaml_load(std::string(value));
if (error.empty())
{
@@ -414,26 +414,31 @@ void cfg::set_entry::from_default()
m_set = {};
}
std::string cfg::map_entry::get_value(const std::string& key)
std::string cfg::map_entry::get_value(std::string_view key)
{
return m_map.contains(key) ? m_map.at(key) : "";
if (auto it = m_map.find(key); it != m_map.end())
{
return it->second;
}
return {};
}
void cfg::map_entry::set_value(const std::string& key, const std::string& value)
void cfg::map_entry::set_value(std::string key, std::string value)
{
m_map[key] = value;
m_map[std::move(key)] = std::move(value);
}
void cfg::map_entry::set_map(std::map<std::string, std::string>&& map)
void cfg::map_entry::set_map(map_of_type<std::string>&& map)
{
m_map = std::move(map);
}
void cfg::map_entry::erase(const std::string& key)
void cfg::map_entry::erase(std::string_view key)
{
if (m_map.contains(key))
if (auto it = m_map.find(key); it != m_map.end())
{
m_map.erase(key);
m_map.erase(it);
}
}
@@ -442,7 +447,7 @@ void cfg::map_entry::from_default()
set_map({});
}
void cfg::log_entry::set_map(std::map<std::string, logs::level>&& map)
void cfg::log_entry::set_map(map_of_type<logs::level>&& map)
{
m_map = std::move(map);
}
+26 -23
View File
@@ -21,7 +21,7 @@ namespace cfg
std::vector<std::string> make_uint_range(u64 min, u64 max);
// Internal hack
bool try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string&);
bool try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view);
// Internal hack
std::vector<std::string> try_to_enum_list(decltype(&fmt_class_string<int>::format) func);
@@ -53,7 +53,7 @@ namespace cfg
_base(type _type);
// Owned entry constructor
_base(type _type, class node* owner, const std::string& name, bool dynamic);
_base(type _type, class node* owner, std::string name, bool dynamic);
public:
_base(const _base&) = delete;
@@ -80,7 +80,7 @@ namespace cfg
}
// Try to convert from string (optional)
virtual bool from_string(const std::string&, bool /*dynamic*/ = false);
virtual bool from_string(std::string_view, bool /*dynamic*/ = false);
// Get string list (optional)
virtual std::vector<std::string> to_list() const
@@ -107,8 +107,8 @@ namespace cfg
}
// Registered node constructor
node(node* owner, const std::string& name, bool dynamic = true)
: _base(type::node, owner, name, dynamic)
node(node* owner, std::string name, bool dynamic = true)
: _base(type::node, owner, std::move(name), dynamic)
{
}
@@ -122,7 +122,7 @@ namespace cfg
std::string to_string() const override;
// Deserialize node
bool from_string(const std::string& value, bool dynamic = false) override;
bool from_string(std::string_view value, bool dynamic = false) override;
// Set default values
void from_default() override;
@@ -135,8 +135,8 @@ namespace cfg
public:
bool def;
_bool(node* owner, const std::string& name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, name, dynamic)
_bool(node* owner, std::string name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, std::move(name), dynamic)
, m_value(def)
, def(def)
{
@@ -159,7 +159,7 @@ namespace cfg
return m_value ? "true" : "false";
}
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
if (value == "false")
m_value = false;
@@ -220,7 +220,7 @@ namespace cfg
return result; // TODO: ???
}
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
u64 result;
@@ -285,7 +285,7 @@ namespace cfg
return std::to_string(m_value);
}
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
s64 result;
if (try_to_int64(&result, value, Min, Max))
@@ -359,7 +359,7 @@ namespace cfg
return std::to_string(m_value);
}
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
u64 result;
if (try_to_uint64(&result, value, Min, Max))
@@ -430,9 +430,9 @@ namespace cfg
return *m_value.load().get();
}
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
m_value = value;
m_value = std::string(value);
return true;
}
};
@@ -474,9 +474,12 @@ namespace cfg
}
};
template<typename T>
using map_of_type = std::map<std::string, T, std::less<>>;
class map_entry final : public _base
{
std::map<std::string, std::string> m_map{};
map_of_type<std::string> m_map{};
public:
map_entry(node* owner, const std::string& name)
@@ -484,24 +487,24 @@ namespace cfg
{
}
const std::map<std::string, std::string>& get_map() const
const map_of_type<std::string>& get_map() const
{
return m_map;
}
std::string get_value(const std::string& key);
std::string get_value(std::string_view key);
void set_value(const std::string& key, const std::string& value);
void set_map(std::map<std::string, std::string>&& map);
void set_value(std::string key, std::string value);
void set_map(map_of_type<std::string>&& map);
void erase(const std::string& key);
void erase(std::string_view key);
void from_default() override;
};
class log_entry final : public _base
{
std::map<std::string, logs::level> m_map{};
map_of_type<logs::level> m_map{};
public:
log_entry(node* owner, const std::string& name)
@@ -509,12 +512,12 @@ namespace cfg
{
}
const std::map<std::string, logs::level>& get_map() const
const map_of_type<logs::level>& get_map() const
{
return m_map;
}
void set_map(std::map<std::string, logs::level>&& map);
void set_map(map_of_type<logs::level>&& map);
void from_default() override;
};
+33 -2
View File
@@ -9,6 +9,7 @@
#include <map>
#include "util/asm.hpp"
#include "util/coro.hpp"
using namespace std::literals::string_literals;
@@ -1182,7 +1183,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
for (const char* data = static_cast<const char*>(buffer); count;)
{
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
DWORD nwritten = 0;
ensure(WriteFile(m_handle, data, size, &nwritten, nullptr)); // "file::write"
@@ -1412,6 +1413,12 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
};
m_file = std::make_unique<unix_file>(fd);
if (mode & fs::isfile && !(mode & fs::write) && stat().is_directory)
{
m_file.reset();
g_tls_error = error::isdir;
}
#endif
}
@@ -1658,7 +1665,7 @@ bool fs::dir::open(const std::string& path)
bool fs::file::strict_read_check(u64 _size, u64 type_size) const
{
if (usz pos0 = pos(), size0 = size(); pos0 >= size0 || (size0 - pos0) / type_size < _size)
if (usz pos0 = pos(), size0 = size(); (pos0 >= size0 ? 0 : (size0 - pos0)) / type_size < _size)
{
fs::g_tls_error = fs::error::inval;
return false;
@@ -2039,6 +2046,30 @@ bool fs::pending_file::commit(bool overwrite)
return false;
}
stx::generator<fs::dir_entry&> fs::list_dir_recursively(std::string path)
{
for (auto& entry : fs::dir(path))
{
if (entry.name == "." || entry.name == "..")
{
continue;
}
std::string new_path = path_append(path, entry.name);
if (entry.is_directory)
{
for (auto& nested : fs::list_dir_recursively(new_path))
{
co_yield nested;
}
}
entry.name = std::move(new_path);
co_yield entry;
}
}
template<>
void fmt_class_string<fs::seek_mode>::format(std::string& out, u64 arg)
{
+44 -54
View File
@@ -32,6 +32,7 @@ namespace fs
excl,
lock,
unread,
isfile,
__bitset_enum_max
};
@@ -44,6 +45,7 @@ namespace fs
constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr auto lock = +open_mode::lock; // Prevent opening the file more than once
constexpr auto unread = +open_mode::unread; // Aggressively prevent reading the opened file (do not use)
constexpr auto isfile = +open_mode::isfile; // Ensure valid fs::file handle is not of directory
constexpr auto write_new = write + create + excl;
constexpr auto rewrite = write + create + trunc;
@@ -205,8 +207,6 @@ namespace fs
{
std::unique_ptr<file_base> m_file{};
bool strict_read_check(u64 size, u64 type_size) const;
public:
// Default constructor
file() = default;
@@ -281,6 +281,9 @@ namespace fs
return m_file->sync();
}
// Check if the handle is capable of reading (size * type_size) of bytes at the time of calling
bool strict_read_check(u64 size, u64 type_size = 1) const;
// Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count,
u32 line = __builtin_LINE(),
@@ -337,8 +340,8 @@ namespace fs
}
// Write std::basic_string unconditionally
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::basic_string<T>& str,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const std::basic_string<T>& str,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
@@ -349,8 +352,8 @@ namespace fs
}
// Write POD unconditionally
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const T& data,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const T& data,
pod_tag_t = pod_tag,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
@@ -362,8 +365,8 @@ namespace fs
}
// Write POD std::vector unconditionally
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::vector<T>& vec,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const std::vector<T>& vec,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
@@ -373,84 +376,69 @@ namespace fs
return *this;
}
// Read std::basic_string, size must be set by resize() method
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
return read(&str[0], str.size() * sizeof(T), line, col, file, func) == str.size() * sizeof(T);
}
// Read std::basic_string
template <bool IsStrict = false, typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str, usz _size,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(std::basic_string<T>& str, usz _size = umax,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
if (!m_file) xnull({line, col, file, func});
if (!_size) return true;
if constexpr (IsStrict)
if (_size != umax)
{
// If _size arg is too high std::bad_alloc may happen in resize and then we cannot error check
if (!strict_read_check(_size, sizeof(T))) return false;
// If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check
if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T)))
{
return false;
}
str.resize(_size);
}
str.resize(_size);
return read(str.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
return read(str.data(), sizeof(T) * str.size(), line, col, file, func) == sizeof(T) * str.size();
}
// Read POD, sizeof(T) is used
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(T& data,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(T& data,
pod_tag_t = pod_tag,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
return read(&data, sizeof(T), line, col, file, func) == sizeof(T);
}
// Read POD std::vector, size must be set by resize() method
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
return read(std::addressof(data), sizeof(T), line, col, file, func) == sizeof(T);
}
// Read POD std::vector
template <bool IsStrict = false, typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz _size,
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(std::vector<T>& vec, usz _size = umax,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
if (!m_file) xnull({line, col, file, func});
if (!_size) return true;
if constexpr (IsStrict)
if (_size != umax)
{
if (!strict_read_check(_size, sizeof(T))) return false;
// If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check
if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T)))
{
return false;
}
vec.resize(_size);
}
vec.resize(_size);
return read(vec.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
}
// Read POD (experimental)
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, T> read(
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
T read(
pod_tag_t = pod_tag,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
@@ -472,13 +460,13 @@ namespace fs
{
std::basic_string<T> result;
result.resize(size() / sizeof(T));
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
if (seek(0), !read(result, result.size(), file, func, line, col)) xfail({line, col, file, func});
return result;
}
// Read full file to std::vector
template<typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, std::vector<T>> to_vector(
template<typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
std::vector<T> to_vector(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
@@ -486,7 +474,7 @@ namespace fs
{
std::vector<T> result;
result.resize(size() / sizeof(T));
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
if (seek(0), !read(result, result.size(), file, func, line, col)) xfail({line, col, file, func});
return result;
}
@@ -818,4 +806,6 @@ namespace fs
}
file make_gather(std::vector<file>);
stx::generator<dir_entry&> list_dir_recursively(std::string path);
}
+194 -78
View File
@@ -16,6 +16,79 @@
LOG_CHANNEL(jit_log, "JIT");
void jit_announce(uptr func, usz size, std::string_view name)
{
if (!size)
{
jit_log.error("Empty function announced: %s (%p)", name, func);
return;
}
// If directory ASMJIT doesn't exist, nothing will be written
static constexpr u64 c_dump_size = 0x1'0000'0000;
static constexpr u64 c_index_size = c_dump_size / 16;
static atomic_t<u64> g_index_off = 0;
static atomic_t<u64> g_data_off = c_index_size;
static void* g_asm = []() -> void*
{
fs::remove_all(fs::get_cache_dir() + "/ASMJIT/", false);
fs::file objs(fmt::format("%s/ASMJIT/.objects", fs::get_cache_dir()), fs::read + fs::rewrite);
if (!objs || !objs.trunc(c_dump_size))
{
return nullptr;
}
return utils::memory_map_fd(objs.get_handle(), c_dump_size, utils::protection::rw);
}();
if (g_asm && size < c_index_size)
{
struct entry
{
u64 addr; // RPCS3 process address
u32 size; // Function size
u32 off; // Function offset
};
// Write index entry at the beginning of file, and data + NTS name at fixed offset
const u64 index_off = g_index_off.fetch_add(1);
const u64 size_all = size + name.size() + 1;
const u64 data_off = g_data_off.fetch_add(size_all);
// If either index or data area is exhausted, nothing will be written
if (index_off < c_index_size / sizeof(entry) && data_off + size_all < c_dump_size)
{
entry& index = static_cast<entry*>(g_asm)[index_off];
std::memcpy(static_cast<char*>(g_asm) + data_off, reinterpret_cast<char*>(func), size);
std::memcpy(static_cast<char*>(g_asm) + data_off + size, name.data(), name.size());
index.size = static_cast<u32>(size);
index.off = static_cast<u32>(data_off);
atomic_storage<u64>::store(index.addr, func);
}
}
if (g_asm && !name.empty() && name[0] != '_')
{
// Save some objects separately
fs::file dump(fmt::format("%s/ASMJIT/%s", fs::get_cache_dir(), name), fs::rewrite);
if (dump)
{
dump.write(reinterpret_cast<uchar*>(func), size);
}
}
#ifdef __linux__
static const fs::file s_map(fmt::format("/tmp/perf-%d.map", getpid()), fs::rewrite + fs::append);
s_map.write(fmt::format("%x %x %s\n", func, size, name));
#endif
}
static u8* get_jit_memory()
{
// Reserve 2G memory (magic static)
@@ -104,8 +177,37 @@ static u8* add_jit_memory(usz size, uint align)
return pointer + pos;
}
const asmjit::Environment& jit_runtime_base::environment() const noexcept
{
static const asmjit::Environment g_env = asmjit::Environment::host();
return g_env;
}
void* jit_runtime_base::_add(asmjit::CodeHolder* code) noexcept
{
ensure(!code->flatten());
ensure(!code->resolveUnresolvedLinks());
usz codeSize = code->codeSize();
if (!codeSize)
return nullptr;
auto p = ensure(this->_alloc(codeSize, 64));
ensure(!code->relocateToBase(uptr(p)));
{
asmjit::VirtMem::ProtectJitReadWriteScope rwScope(p, codeSize);
for (asmjit::Section* section : code->_sections)
{
std::memcpy(p + section->offset(), section->data(), section->bufferSize());
}
}
return p;
}
jit_runtime::jit_runtime()
: HostRuntime()
{
}
@@ -113,38 +215,9 @@ jit_runtime::~jit_runtime()
{
}
asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
uchar* jit_runtime::_alloc(usz size, usz align) noexcept
{
usz codeSize = code->getCodeSize();
if (!codeSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoCodeGenerated;
}
void* p = jit_runtime::alloc(codeSize, 16);
if (!p) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoVirtualMemory;
}
usz relocSize = code->relocate(p);
if (!relocSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorInvalidState;
}
flush(p, relocSize);
*dst = p;
return asmjit::kErrorOk;
}
asmjit::Error jit_runtime::_release(void*) noexcept
{
return asmjit::kErrorOk;
return jit_runtime::alloc(size, align, true);
}
u8* jit_runtime::alloc(usz size, uint align, bool exec) noexcept
@@ -191,12 +264,12 @@ void jit_runtime::finalize() noexcept
std::memcpy(alloc(s_data_init.size(), 1, false), s_data_init.data(), s_data_init.size());
}
asmjit::Runtime& asmjit::get_global_runtime()
jit_runtime_base& asmjit::get_global_runtime()
{
// 16 MiB for internal needs
static constexpr u64 size = 1024 * 1024 * 16;
struct custom_runtime final : asmjit::HostRuntime
struct custom_runtime final : jit_runtime_base
{
custom_runtime() noexcept
{
@@ -205,7 +278,7 @@ asmjit::Runtime& asmjit::get_global_runtime()
{
if (auto ptr = utils::memory_reserve(size, reinterpret_cast<void*>(addr)))
{
m_pos.raw() = static_cast<std::byte*>(ptr);
m_pos.raw() = static_cast<uchar*>(ptr);
break;
}
}
@@ -217,50 +290,26 @@ asmjit::Runtime& asmjit::get_global_runtime()
utils::memory_commit(m_pos, size, utils::protection::wx);
}
custom_runtime(const custom_runtime&) = delete;
custom_runtime& operator=(const custom_runtime&) = delete;
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override
uchar* _alloc(usz size, usz align) noexcept override
{
usz codeSize = code->getCodeSize();
if (!codeSize) [[unlikely]]
return m_pos.atomic_op([&](uchar*& pos) -> uchar*
{
*dst = nullptr;
return asmjit::kErrorNoCodeGenerated;
}
const auto r = reinterpret_cast<uchar*>(utils::align(uptr(pos), align));
void* p = m_pos.fetch_add(utils::align(codeSize, 4096));
if (!p || m_pos > m_max) [[unlikely]]
{
*dst = nullptr;
jit_log.fatal("Out of memory (static asmjit)");
return asmjit::kErrorNoVirtualMemory;
}
if (r >= pos && r + size > pos && r + size <= m_max)
{
pos = r + size;
return r;
}
usz relocSize = code->relocate(p);
if (!relocSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorInvalidState;
}
utils::memory_protect(p, utils::align(codeSize, 4096), utils::protection::rx);
flush(p, relocSize);
*dst = p;
return asmjit::kErrorOk;
}
asmjit::Error _release(void*) noexcept override
{
return asmjit::kErrorOk;
return nullptr;
});
}
private:
atomic_t<std::byte*> m_pos{};
atomic_t<uchar*> m_pos{};
std::byte* m_max{};
uchar* m_max{};
};
// Magic static
@@ -268,6 +317,24 @@ asmjit::Runtime& asmjit::get_global_runtime()
return g_rt;
}
asmjit::inline_runtime::inline_runtime(uchar* data, usz size)
: m_data(data)
, m_size(size)
{
}
uchar* asmjit::inline_runtime::_alloc(usz size, usz align) noexcept
{
ensure(align <= 4096);
return size <= m_size ? m_data : nullptr;
}
asmjit::inline_runtime::~inline_runtime()
{
utils::memory_protect(m_data, m_size, utils::protection::rx);
}
#ifdef LLVM_AVAILABLE
#include <unordered_map>
@@ -293,6 +360,9 @@ asmjit::Runtime& asmjit::get_global_runtime()
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolSize.h"
#ifdef _MSC_VER
#pragma warning(pop)
#else
@@ -348,19 +418,21 @@ static u64 make_null_function(const std::string& name)
using namespace asmjit;
// Build a "null" function that contains its name
const auto func = build_function_asm<void (*)()>([&](X86Assembler& c, auto& args)
const auto func = build_function_asm<void (*)()>("NULL", [&](native_asm& c, auto& args)
{
#if defined(ARCH_X64)
Label data = c.newLabel();
c.lea(args[0], x86::qword_ptr(data, 0));
c.jmp(imm_ptr(&null));
c.align(kAlignCode, 16);
c.jmp(Imm(&null));
c.align(AlignMode::kCode, 16);
c.bind(data);
// Copy function name bytes
for (char ch : name)
c.db(ch);
c.db(0);
c.align(kAlignData, 16);
c.align(AlignMode::kData, 16);
#endif
});
func_ptr = reinterpret_cast<u64>(func);
@@ -368,6 +440,42 @@ static u64 make_null_function(const std::string& name)
}
}
struct JITAnnouncer : llvm::JITEventListener
{
void notifyObjectLoaded(u64, const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& info) override
{
using namespace llvm;
object::OwningBinary<object::ObjectFile> debug_obj_ = info.getObjectForDebug(obj);
if (!debug_obj_.getBinary())
{
#ifdef __linux__
jit_log.error("LLVM: Failed to announce JIT events (no debug object)");
#endif
return;
}
const object::ObjectFile& debug_obj = *debug_obj_.getBinary();
for (const auto& [sym, size] : computeSymbolSizes(debug_obj))
{
Expected<object::SymbolRef::Type> type_ = sym.getType();
if (!type_ || *type_ != object::SymbolRef::ST_Function)
continue;
Expected<StringRef> name = sym.getName();
if (!name)
continue;
Expected<u64> addr = sym.getAddress();
if (!addr)
continue;
jit_announce(*addr, size, {name->data(), name->size()});
}
}
};
// Simple memory manager
struct MemoryManager1 : llvm::RTDyldMemoryManager
{
@@ -391,7 +499,8 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
~MemoryManager1() override
{
utils::memory_release(ptr, c_max_size * 2);
// Hack: don't release to prevent reuse of address space, see jit_announce
utils::memory_decommit(ptr, c_max_size * 2);
}
llvm::JITSymbol findSymbol(const std::string& name) override
@@ -725,11 +834,12 @@ std::string jit_compiler::cpu(const std::string& _cpu)
}
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags)
: m_cpu(cpu(_cpu))
: m_context(new llvm::LLVMContext)
, m_cpu(cpu(_cpu))
{
std::string result;
auto null_mod = std::make_unique<llvm::Module> ("null_", m_context);
auto null_mod = std::make_unique<llvm::Module> ("null_", *m_context);
if (_link.empty())
{
@@ -773,6 +883,12 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
}
}
if (!_link.empty() || !(flags & 0x1))
{
m_engine->RegisterJITEventListener(llvm::JITEventListener::createIntelJITEventListener());
m_engine->RegisterJITEventListener(new JITAnnouncer);
}
if (!m_engine)
{
fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result);
+180 -59
View File
@@ -1,8 +1,12 @@
#pragma once
#include "util/types.hpp"
// Include asmjit with warnings ignored
#define ASMJIT_EMBED
#define ASMJIT_DEBUG
#define ASMJIT_STATIC
#define ASMJIT_BUILD_DEBUG
#undef Bool
#ifdef _MSC_VER
#pragma warning(push, 0)
@@ -18,15 +22,41 @@
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Weffc++"
#ifndef __clang__
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wdeprecated-anon-enum-enum-conversion"
#pragma GCC diagnostic ignored "-Wcast-qual"
#else
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"
#endif
#include <asmjit/asmjit.h>
#if defined(ARCH_ARM64)
#include <asmjit/a64.h>
#endif
#pragma GCC diagnostic pop
#endif
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#if defined(ARCH_X64)
using native_asm = asmjit::x86::Assembler;
using native_args = std::array<asmjit::x86::Gp, 4>;
#elif defined(ARCH_ARM64)
using native_asm = asmjit::a64::Assembler;
using native_args = std::array<asmjit::a64::Gp, 4>;
#endif
void jit_announce(uptr func, usz size, std::string_view name);
void jit_announce(auto* func, usz size, std::string_view name)
{
jit_announce(uptr(func), size, name);
}
enum class jit_class
{
@@ -36,17 +66,27 @@ enum class jit_class
spu_data,
};
struct jit_runtime_base
{
jit_runtime_base() noexcept = default;
virtual ~jit_runtime_base() = default;
jit_runtime_base(const jit_runtime_base&) = delete;
jit_runtime_base& operator=(const jit_runtime_base&) = delete;
const asmjit::Environment& environment() const noexcept;
void* _add(asmjit::CodeHolder* code) noexcept;
virtual uchar* _alloc(usz size, usz align) noexcept = 0;
};
// ASMJIT runtime for emitting code in a single 2G region
struct jit_runtime final : asmjit::HostRuntime
struct jit_runtime final : jit_runtime_base
{
jit_runtime();
~jit_runtime() override;
// Allocate executable memory
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override;
// Do nothing (deallocation is delayed)
asmjit::Error _release(void* p) noexcept override;
uchar* _alloc(usz size, usz align) noexcept override;
// Allocate memory
static u8* alloc(usz size, uint align, bool exec = true) noexcept;
@@ -61,11 +101,25 @@ struct jit_runtime final : asmjit::HostRuntime
namespace asmjit
{
// Should only be used to build global functions
asmjit::Runtime& get_global_runtime();
jit_runtime_base& get_global_runtime();
// Don't use directly
class inline_runtime : public jit_runtime_base
{
uchar* m_data;
usz m_size;
public:
inline_runtime(uchar* data, usz size);
~inline_runtime();
uchar* _alloc(usz size, usz align) noexcept override;
};
// Emit xbegin and adjacent loop, return label at xbegin (don't use xabort please)
template <typename F>
[[nodiscard]] inline asmjit::Label build_transaction_enter(asmjit::X86Assembler& c, asmjit::Label fallback, F func)
[[nodiscard]] inline asmjit::Label build_transaction_enter(asmjit::x86::Assembler& c, asmjit::Label fallback, F func)
{
Label fall = c.newLabel();
Label begin = c.newLabel();
@@ -80,7 +134,7 @@ namespace asmjit
func();
// Other bad statuses are ignored regardless of repeat flag (TODO)
c.align(kAlignCode, 16);
c.align(AlignMode::kCode, 16);
c.bind(begin);
return fall;
@@ -88,7 +142,7 @@ namespace asmjit
}
// Helper to spill RDX (EDX) register for RDTSC
inline void build_swap_rdx_with(asmjit::X86Assembler& c, std::array<X86Gp, 4>& args, const asmjit::X86Gp& with)
inline void build_swap_rdx_with(asmjit::x86::Assembler& c, std::array<x86::Gp, 4>& args, const asmjit::x86::Gp& with)
{
#ifdef _WIN32
c.xchg(args[1], with);
@@ -100,7 +154,7 @@ namespace asmjit
}
// Get full RDTSC value into chosen register (clobbers rax/rdx or saves only rax with other target)
inline void build_get_tsc(asmjit::X86Assembler& c, const asmjit::X86Gp& to = asmjit::x86::rax)
inline void build_get_tsc(asmjit::x86::Assembler& c, const asmjit::x86::Gp& to = asmjit::x86::rax)
{
if (&to != &x86::rax && &to != &x86::rdx)
{
@@ -127,21 +181,103 @@ namespace asmjit
c.or_(to.r64(), x86::rdx);
}
}
inline void build_init_args_from_ghc(native_asm& c, native_args& args)
{
#if defined(ARCH_X64)
// TODO: handle case when args don't overlap with r13/rbp/r12/rbx
c.mov(args[0], x86::r13);
c.mov(args[1], x86::rbp);
c.mov(args[2], x86::r12);
c.mov(args[3], x86::rbx);
#else
static_cast<void>(c);
static_cast<void>(args);
#endif
}
inline void build_init_ghc_args(native_asm& c, native_args& args)
{
#if defined(ARCH_X64)
// TODO: handle case when args don't overlap with r13/rbp/r12/rbx
c.mov(x86::r13, args[0]);
c.mov(x86::rbp, args[1]);
c.mov(x86::r12, args[2]);
c.mov(x86::rbx, args[3]);
#else
static_cast<void>(c);
static_cast<void>(args);
#endif
}
#if defined(ARCH_X64)
template <uint Size>
struct native_vec;
template <>
struct native_vec<16> { using type = x86::Xmm; };
template <>
struct native_vec<32> { using type = x86::Ymm; };
template <>
struct native_vec<64> { using type = x86::Zmm; };
template <uint Size>
using native_vec_t = typename native_vec<Size>::type;
// if (count > step) { for (; ctr < (count - step); ctr += step) {...} count -= ctr; }
inline void build_incomplete_loop(native_asm& c, auto ctr, auto count, u32 step, auto&& build)
{
asmjit::Label body = c.newLabel();
asmjit::Label exit = c.newLabel();
ensure((step & (step - 1)) == 0);
c.cmp(count, step);
c.jbe(exit);
c.sub(count, step);
c.align(asmjit::AlignMode::kCode, 16);
c.bind(body);
build();
c.add(ctr, step);
c.sub(count, step);
c.ja(body);
c.add(count, step);
c.bind(exit);
}
// for (; count > 0; ctr++, count--)
inline void build_loop(native_asm& c, auto ctr, auto count, auto&& build)
{
asmjit::Label body = c.newLabel();
asmjit::Label exit = c.newLabel();
c.test(count, count);
c.jz(exit);
c.align(asmjit::AlignMode::kCode, 16);
c.bind(body);
build();
c.inc(ctr);
c.sub(count, 1);
c.ja(body);
c.bind(exit);
}
#endif
}
// Build runtime function with asmjit::X86Assembler
template <typename FT, typename F>
inline FT build_function_asm(F&& builder)
template <typename FT, typename Asm = native_asm, typename F>
inline FT build_function_asm(std::string_view name, F&& builder)
{
using namespace asmjit;
auto& rt = get_global_runtime();
CodeHolder code;
code.init(rt.getCodeInfo());
code._globalHints = asmjit::CodeEmitter::kHintOptimizedAlign;
code.init(rt.environment());
std::array<X86Gp, 4> args;
#if defined(ARCH_X64)
native_args args;
#ifdef _WIN32
args[0] = x86::rcx;
args[1] = x86::rdx;
@@ -153,60 +289,45 @@ inline FT build_function_asm(F&& builder)
args[2] = x86::rdx;
args[3] = x86::rcx;
#endif
#elif defined(ARCH_ARM64)
native_args args;
args[0] = a64::x0;
args[1] = a64::x1;
args[2] = a64::x2;
args[3] = a64::x3;
#endif
X86Assembler compiler(&code);
builder(std::ref(compiler), args);
ensure(compiler.getLastError() == 0);
FT result;
if (rt.add(&result, &code))
Asm compiler(&code);
compiler.addEncodingOptions(EncodingOptions::kOptimizedAlign);
if constexpr (std::is_invocable_r_v<bool, F, Asm&, native_args&>)
{
return nullptr;
if (!builder(compiler, args))
return nullptr;
}
else
{
builder(compiler, args);
}
return result;
const auto result = rt._add(&code);
jit_announce(result, code.codeSize(), name);
return reinterpret_cast<FT>(uptr(result));
}
#ifdef LLVM_AVAILABLE
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include "util/types.hpp"
#ifdef _MSC_VER
#pragma warning(push, 0)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wsuggest-override"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
#ifdef __clang__
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
#endif
#endif
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#ifdef _MSC_VER
#pragma warning(pop)
#else
#pragma GCC diagnostic pop
#endif
namespace llvm
{
class LLVMContext;
class ExecutionEngine;
class Module;
}
// Temporary compiler interface
class jit_compiler final
{
// Local LLVM context
llvm::LLVMContext m_context{};
std::unique_ptr<llvm::LLVMContext> m_context{};
// Execution instance
std::unique_ptr<llvm::ExecutionEngine> m_engine{};
@@ -221,7 +342,7 @@ public:
// Get LLVM context
auto& get_context()
{
return m_context;
return *m_context;
}
auto& get_engine() const
+9 -30
View File
@@ -16,43 +16,22 @@
#endif
#ifdef _WIN32
std::string wchar_to_utf8(const wchar_t *src)
std::string wchar_to_utf8(std::wstring_view src)
{
std::string utf8_string;
const auto tmp_size = WideCharToMultiByte(CP_UTF8, 0, src, -1, nullptr, 0, nullptr, nullptr);
const auto tmp_size = WideCharToMultiByte(CP_UTF8, 0, src.data(), src.size(), nullptr, 0, nullptr, nullptr);
utf8_string.resize(tmp_size);
WideCharToMultiByte(CP_UTF8, 0, src, -1, utf8_string.data(), tmp_size, nullptr, nullptr);
WideCharToMultiByte(CP_UTF8, 0, src.data(), src.size(), utf8_string.data(), tmp_size, nullptr, nullptr);
return utf8_string;
}
std::string wchar_path_to_ansi_path(const std::wstring& src)
std::wstring utf8_to_wchar(std::string_view src)
{
std::wstring buf_short;
std::string buf_final;
// Get the short path from the wide char path(short path should only contain ansi characters)
auto tmp_size = GetShortPathNameW(src.data(), nullptr, 0);
buf_short.resize(tmp_size);
GetShortPathNameW(src.data(), buf_short.data(), tmp_size);
// Convert wide char to ansi
tmp_size = WideCharToMultiByte(CP_ACP, 0, buf_short.data(), -1, nullptr, 0, nullptr, nullptr);
buf_final.resize(tmp_size);
WideCharToMultiByte(CP_ACP, 0, buf_short.data(), -1, buf_final.data(), tmp_size, nullptr, nullptr);
return buf_final;
}
std::string utf8_path_to_ansi_path(const std::string& src)
{
std::wstring buf_wide;
// Converts the utf-8 path to wide char
const auto tmp_size = MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, nullptr, 0);
buf_wide.resize(tmp_size);
MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, buf_wide.data(), tmp_size);
return wchar_path_to_ansi_path(buf_wide);
std::wstring wchar_string;
const auto tmp_size = MultiByteToWideChar(CP_UTF8, 0, src.data(), src.size(), nullptr, 0);
wchar_string.resize(tmp_size);
MultiByteToWideChar(CP_UTF8, 0, src.data(), src.size(), wchar_string.data(), tmp_size);
return wchar_string;
}
#endif
+1 -1
View File
@@ -239,7 +239,7 @@ struct fmt_class_string<T, void>
static void format(std::string& out, u64 arg)
{
const auto& obj = get_object(arg);
void format_byte_array(std::string&, const uchar*, usz);
format_byte_array(out, reinterpret_cast<const uchar*>(std::data(obj)), std::size(obj));
}
+18 -10
View File
@@ -6,10 +6,11 @@
#include <functional>
#include <string_view>
#include "util/types.hpp"
#ifdef _WIN32
std::string wchar_to_utf8(const wchar_t *src);
std::string wchar_path_to_ansi_path(const std::wstring& src);
std::string utf8_path_to_ansi_path(const std::string& src);
std::wstring utf8_to_wchar(std::string_view src);
std::string wchar_to_utf8(std::wstring_view src);
#endif
// Copy null-terminated string from a std::string or a char array to a char array with truncation
@@ -22,17 +23,17 @@ inline void strcpy_trunc(D& dst, const T& src)
}
// Convert string to signed integer
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max);
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max);
// Convert string to unsigned integer
bool try_to_uint64(u64* out, const std::string& value, u64 min, u64 max);
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max);
namespace fmt
{
std::string replace_all(std::string_view src, std::string_view from, std::string_view to, usz count = -1);
template <usz list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::string> (&list)[list_size])
std::string replace_all(std::string src, const std::pair<std::string_view, std::string> (&list)[list_size])
{
for (usz pos = 0; pos < src.length(); ++pos)
{
@@ -41,11 +42,14 @@ namespace fmt
const usz comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
{
continue;
}
if (src.substr(pos, comp_length) == list[i].first)
{
src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + src.substr(pos + comp_length);
src.erase(pos, comp_length);
src.insert(pos, list[i].second.data(), list[i].second.length());
pos += list[i].second.length() - 1;
break;
}
@@ -56,7 +60,7 @@ namespace fmt
}
template <usz list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>> (&list)[list_size])
std::string replace_all(std::string src, const std::pair<std::string_view, std::function<std::string()>> (&list)[list_size])
{
for (usz pos = 0; pos < src.length(); ++pos)
{
@@ -65,12 +69,16 @@ namespace fmt
const usz comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
{
continue;
}
if (src.substr(pos, comp_length) == list[i].first)
{
src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + src.substr(pos + comp_length);
pos += list[i].second().length() - 1;
src.erase(pos, comp_length);
auto replacement = list[i].second();
src.insert(pos, replacement);
pos += replacement.length() - 1;
break;
}
}
+89 -28
View File
@@ -77,7 +77,7 @@
#include "util/logs.hpp"
#include "util/asm.hpp"
#include "util/v128.hpp"
#include "util/v128sse.hpp"
#include "util/simd.hpp"
#include "util/sysinfo.hpp"
#include "Emu/Memory/vm_locking.h"
@@ -189,6 +189,7 @@ bool IsDebuggerPresent()
}
#endif
#if defined(ARCH_X64)
enum x64_reg_t : u32
{
X64R_RAX = 0,
@@ -839,6 +840,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
#ifdef _WIN32
typedef CONTEXT x64_context;
typedef CONTEXT ucontext_t;
#define X64REG(context, reg) (&(&(context)->Rax)[reg])
#define XMMREG(context, reg) (reinterpret_cast<v128*>(&(&(context)->Xmm0)[reg]))
@@ -1211,12 +1213,18 @@ usz get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, usz d_
return d_size;
}
#elif defined(ARCH_ARM64)
#define RIP(context) ((context)->uc_mcontext.pc)
#endif /* ARCH_ */
namespace rsx
{
extern std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
}
bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) noexcept
bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noexcept
{
g_tls_fault_all++;
@@ -1243,6 +1251,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
}
#if defined(ARCH_X64)
const u8* const code = reinterpret_cast<u8*>(RIP(context));
x64_op_t op;
@@ -1382,6 +1391,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
g_tls_fault_spu++;
return true;
} while (0);
#else
static_cast<void>(context);
#endif /* ARCH_ */
if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
{
@@ -1545,7 +1557,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
if (!g_tls_access_violation_recovered)
{
vm_log.notice("\n%s", dump_useful_thread_info());
vm_log.error("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
vm_log.error("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
}
// TODO:
@@ -1582,7 +1594,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
// Do not log any further access violations in this case.
if (!g_tls_access_violation_recovered)
{
vm_log.fatal("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (cpu && cpu->id_type() == 1 && cpu->get_pc() == addr ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
}
while (Emu.IsPaused())
@@ -1754,8 +1766,9 @@ const bool s_exception_handler_set = []() -> bool
static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
{
x64_context* context = static_cast<ucontext_t*>(uct);
ucontext_t* context = static_cast<ucontext_t*>(uct);
#if defined(ARCH_X64)
#ifdef __APPLE__
const u64 err = context->uc_mcontext->__es.__err;
#elif defined(__DragonFly__) || defined(__FreeBSD__)
@@ -1770,6 +1783,23 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
const bool is_executing = err & 0x10;
const bool is_writing = err & 0x2;
#elif defined(ARCH_ARM64)
const bool is_executing = uptr(info->si_addr) == RIP(context);
const u32 insn = is_executing ? 0 : *reinterpret_cast<u32*>(RIP(context));
const bool is_writing = (insn & 0xbfff0000) == 0x0c000000
|| (insn & 0xbfe00000) == 0x0c800000
|| (insn & 0xbfdf0000) == 0x0d000000
|| (insn & 0xbfc00000) == 0x0d800000
|| (insn & 0x3f400000) == 0x08000000
|| (insn & 0x3bc00000) == 0x39000000
|| (insn & 0x3fc00000) == 0x3d800000
|| (insn & 0x3bc00000) == 0x38000000
|| (insn & 0x3fe00000) == 0x3c800000
|| (insn & 0x3a400000) == 0x28000000;
#else
#error "signal_handler not implemented"
#endif
const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const auto cause = is_executing ? "executing" : is_writing ? "writing" : "reading";
@@ -1809,6 +1839,26 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
thread_ctrl::emergency_exit(msg);
}
static void sigill_handler(int /*sig*/, siginfo_t* info, void* /*uct*/) noexcept
{
std::string msg = fmt::format("Illegal instruction at %p (%s).\n", info->si_addr, *reinterpret_cast<be_t<u128>*>(info->si_addr));
append_thread_name(msg);
if (IsDebuggerPresent())
{
sys_log.fatal("\n%s", msg);
sys_log.notice("\n%s", dump_useful_thread_info());
// Convert to SIGTRAP
raise(SIGTRAP);
return;
}
thread_ctrl::emergency_exit(msg);
}
void sigpipe_signaling_handler(int)
{
}
@@ -1826,6 +1876,21 @@ const bool s_exception_handler_set = []() -> bool
std::abort();
}
#ifdef __APPLE__
if (::sigaction(SIGBUS, &sa, NULL) == -1)
{
std::fprintf(stderr, "sigaction(SIGBUS) failed (%d).\n", errno);
std::abort();
}
#endif
sa.sa_sigaction = sigill_handler;
if (::sigaction(SIGILL, &sa, NULL) == -1)
{
std::fprintf(stderr, "sigaction(SIGILL) failed (%d).\n", errno);
std::abort();
}
sa.sa_handler = sigpipe_signaling_handler;
if (::sigaction(SIGPIPE, &sa, NULL) == -1)
{
@@ -1844,11 +1909,7 @@ const bool s_terminate_handler_set = []() -> bool
std::set_terminate([]()
{
if (IsDebuggerPresent())
#ifdef _MSC_VER
__debugbreak();
#else
__asm("int3;");
#endif
utils::trap();
report_fatal_error("RPCS3 has abnormally terminated.");
});
@@ -1897,6 +1958,11 @@ void thread_base::start()
m_thread = ::_beginthreadex(nullptr, 0, entry_point, this, CREATE_SUSPENDED, nullptr);
ensure(m_thread);
ensure(::ResumeThread(reinterpret_cast<HANDLE>(+m_thread)) != -1);
#elif defined(__APPLE__)
pthread_attr_t stack_size_attr;
pthread_attr_init(&stack_size_attr);
pthread_attr_setstacksize(&stack_size_attr, 0x800000);
ensure(pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), &stack_size_attr, entry_point, this) == 0);
#else
ensure(pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), nullptr, entry_point, this) == 0);
#endif
@@ -1922,7 +1988,7 @@ void thread_base::initialize(void (*error_cb)())
{
if (attempts == umax)
{
g_tls_wait_time += __rdtsc() - stamp0;
g_tls_wait_time += utils::get_tsc() - stamp0;
}
else if (attempts > 1)
{
@@ -2083,6 +2149,8 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
std::fesetround(FE_TONEAREST);
gv_unset_zeroing_denormals();
static constexpr u64 s_stop_bit = 0x8000'0000'0000'0000ull;
static atomic_t<u64> s_pool_ctr = []
@@ -2182,26 +2250,27 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base))
{
return build_function_asm<native_entry>([&](asmjit::X86Assembler& c, auto& args)
return build_function_asm<native_entry>("", [&](native_asm& c, auto& args)
{
using namespace asmjit;
#if defined(ARCH_X64)
Label _ret = c.newLabel();
c.push(x86::rbp);
c.sub(x86::rsp, 0x20);
// Call entry point (TODO: support for detached threads missing?)
c.call(imm_ptr(entry));
c.call(entry);
// Call finalize, return if zero
c.mov(args[0], x86::rax);
c.call(imm_ptr<native_entry(*)(u64)>(finalize));
c.call(static_cast<native_entry(*)(u64)>(&finalize));
c.test(x86::rax, x86::rax);
c.jz(_ret);
// Otherwise, call it as an entry point with first arg = new current thread
c.mov(x86::rbp, x86::rax);
c.call(imm_ptr(thread_ctrl::get_current));
c.call(thread_ctrl::get_current);
c.mov(args[0], x86::rax);
c.add(x86::rsp, 0x28);
c.jmp(x86::rbp);
@@ -2209,6 +2278,7 @@ thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base*
c.bind(_ret);
c.add(x86::rsp, 0x28);
c.ret();
#endif
});
}
@@ -2351,7 +2421,7 @@ bool thread_base::join(bool dtor) const
// Hacked for too sleepy threads (1ms) TODO: make sure it's unneeded and remove
const auto timeout = dtor && Emu.IsStopped() ? atomic_wait_timeout{1'000'000} : atomic_wait_timeout::inf;
auto stamp0 = __rdtsc();
auto stamp0 = utils::get_tsc();
for (u64 i = 0; (m_sync & 3) <= 1; i++)
{
@@ -2364,7 +2434,7 @@ bool thread_base::join(bool dtor) const
if (i >= 16 && !(i & (i - 1)) && timeout != atomic_wait_timeout::inf)
{
sig_log.error(u8"Thread [%s] is too sleepy. Waiting for it %.3fµs already!", *m_tname.load(), (__rdtsc() - stamp0) / (utils::get_tsc_freq() / 1000000.));
sig_log.error(u8"Thread [%s] is too sleepy. Waiting for it %.3fµs already!", *m_tname.load(), (utils::get_tsc() - stamp0) / (utils::get_tsc_freq() / 1000000.));
}
}
@@ -2509,17 +2579,8 @@ void thread_base::exec()
sig_log.fatal("Thread terminated due to fatal error: %s", reason);
#ifdef _WIN32
if (IsDebuggerPresent())
{
__debugbreak();
}
#else
if (IsDebuggerPresent())
{
__asm("int3;");
}
#endif
utils::trap();
if (const auto _this = g_tls_this_thread)
{
@@ -2841,7 +2902,7 @@ void thread_ctrl::set_native_priority(int priority)
if (int err = pthread_setschedparam(pthread_self(), policy, &param))
{
sig_log.error("pthraed_setschedparam() failed: %d", err);
sig_log.error("pthread_setschedparam() failed: %d", err);
}
#endif
}
+12
View File
@@ -478,7 +478,19 @@ class named_thread final : public Context, result_storage<Context>, thread_base
return thread::finalize(thread_state::finished);
}
#if defined(ARCH_X64)
static inline thread::native_entry trampoline = thread::make_trampoline(entry_point);
#else
static void* trampoline(void* arg)
{
if (const auto next = thread_base::finalize(entry_point(static_cast<thread_base*>(arg))))
{
return next(thread_ctrl::get_current());
}
return nullptr;
}
#endif
friend class thread_ctrl;
+1 -1
View File
@@ -12,7 +12,7 @@ private:
steady_clock::time_point m_end;
public:
Timer() : m_stopped(false)
Timer() : m_stopped(false), m_start(steady_clock::now())
{
}
+1 -1
View File
@@ -576,7 +576,7 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
const u32 alloc_size = utils::align(static_cast<u32>(p.value.long_value) + alloc_at % 4096, 4096);
// Allocate map if needed, if allocated flags will indicate that bit 62 is set (unique identifier)
auto alloc_map = vm::reserve_map(vm::any, alloc_at & -0x10000, utils::align(alloc_size, 0x10000), vm::page_size_64k | vm::preallocated | (1ull << 62));
auto alloc_map = vm::reserve_map(vm::any, alloc_at & -0x10000, utils::align(alloc_size, 0x10000), vm::page_size_64k | (1ull << 62));
u64 flags = vm::alloc_unwritable;
+10 -4
View File
@@ -1,6 +1,7 @@
#pragma once
#include <cmath>
#include <type_traits>
template<typename T>
struct size2_base
@@ -670,17 +671,22 @@ struct area_base
{
return{ x1 / size.width, y1 / size.height, x2 / size.width, y2 / size.height };
}
constexpr area_base operator / (const T& value) const
template <typename U> requires (std::is_arithmetic_v<U>)
constexpr area_base operator / (const U& value) const
{
return{ x1 / value, y1 / value, x2 / value, y2 / value };
return area_base{static_cast<T>(x1 / value), static_cast<T>(y1 / value), static_cast<T>(x2 / value), static_cast<T>(y2 / value)};
}
constexpr area_base operator * (const size2_base<T>& size) const
{
return{ x1 * size.width, y1 * size.height, x2 * size.width, y2 * size.height };
}
constexpr area_base operator * (const f32& value) const
template <typename U> requires (std::is_arithmetic_v<U>)
constexpr area_base operator * (const U& value) const
{
return{ static_cast<T>(x1 * value), static_cast<T>(y1 * value), static_cast<T>(x2 * value), static_cast<T>(y2 * value) };
return area_base{static_cast<T>(x1 * value), static_cast<T>(y1 * value), static_cast<T>(x2 * value), static_cast<T>(y2 * value)};
}
template<typename NT>
+129
View File
@@ -0,0 +1,129 @@
#include "Utilities/simple_ringbuf.h"
simple_ringbuf::simple_ringbuf(u32 size)
{
set_buf_size(size);
}
simple_ringbuf::simple_ringbuf(simple_ringbuf&& other)
{
rw_ptr = other.rw_ptr.load();
buf_size = other.buf_size;
buf = std::move(other.buf);
initialized = other.initialized.observe();
other.buf_size = 0;
other.rw_ptr = 0;
other.initialized = false;
}
simple_ringbuf& simple_ringbuf::operator=(simple_ringbuf&& other)
{
if (this == &other) return *this;
rw_ptr = other.rw_ptr.load();
buf_size = other.buf_size;
buf = std::move(other.buf);
initialized = other.initialized.observe();
other.buf_size = 0;
other.rw_ptr = 0;
other.initialized = false;
return *this;
}
u32 simple_ringbuf::get_free_size() const
{
const u64 _rw_ptr = rw_ptr;
const u32 rd = static_cast<u32>(_rw_ptr);
const u32 wr = static_cast<u32>(_rw_ptr >> 32);
return wr >= rd ? buf_size - 1 - (wr - rd) : rd - wr - 1U;
}
u32 simple_ringbuf::get_used_size() const
{
return buf_size - 1 - get_free_size();
}
u32 simple_ringbuf::get_total_size() const
{
return buf_size;
}
void simple_ringbuf::set_buf_size(u32 size)
{
ensure(size);
this->buf_size = size + 1;
buf = std::make_unique<u8[]>(this->buf_size);
flush();
initialized = true;
}
void simple_ringbuf::flush()
{
rw_ptr.atomic_op([&](u64 &val)
{
val = static_cast<u32>(val >> 32) | (val & 0xFFFFFFFF'00000000);
});
}
u32 simple_ringbuf::push(const void *data, u32 size)
{
ensure(data != nullptr && initialized.observe());
const u32 old = static_cast<u32>(rw_ptr.load() >> 32);
const u32 to_push = std::min(size, get_free_size());
auto b_data = static_cast<const u8*>(data);
if (!to_push) return 0;
if (old + to_push > buf_size)
{
const auto first_write_sz = buf_size - old;
memcpy(&buf[old], b_data, first_write_sz);
memcpy(&buf[0], b_data + first_write_sz, to_push - first_write_sz);
}
else
{
memcpy(&buf[old], b_data, to_push);
}
rw_ptr.atomic_op([&](u64 &val)
{
val = static_cast<u64>((old + to_push) % buf_size) << 32 | static_cast<u32>(val);
});
return to_push;
}
u32 simple_ringbuf::pop(void *data, u32 size)
{
ensure(data != nullptr && initialized.observe());
const u32 old = static_cast<u32>(rw_ptr.load());
const u32 to_pop = std::min(size, get_used_size());
u8 *b_data = static_cast<u8*>(data);
if (!to_pop) return 0;
if (old + to_pop > buf_size)
{
const auto first_read_sz = buf_size - old;
memcpy(b_data, &buf[old], first_read_sz);
memcpy(b_data + first_read_sz, &buf[0], to_pop - first_read_sz);
}
else
{
memcpy(b_data, &buf[old], to_pop);
}
rw_ptr.atomic_op([&](u64 &val)
{
val = (old + to_pop) % buf_size | (val & 0xFFFFFFFF'00000000);
});
return to_pop;
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include "util/types.hpp"
#include "util/atomic.hpp"
// Single reader/writer simple ringbuffer.
// Counters are 32-bit.
class simple_ringbuf
{
private:
atomic_t<u64> rw_ptr = 0;
u32 buf_size = 0;
std::unique_ptr<u8[]> buf{};
atomic_t<bool> initialized = false;
public:
simple_ringbuf() {};
simple_ringbuf(u32 size);
simple_ringbuf(const simple_ringbuf&) = delete;
simple_ringbuf& operator=(const simple_ringbuf&) = delete;
simple_ringbuf(simple_ringbuf&& other);
simple_ringbuf& operator=(simple_ringbuf&& other);
u32 get_free_size() const;
u32 get_used_size() const;
u32 get_total_size() const;
// Thread unsafe functions.
void set_buf_size(u32 size);
void flush(); // Could be safely called from reader.
u32 push(const void *data, u32 size);
u32 pop(void *data, u32 size);
};
+164 -186
View File
@@ -2,6 +2,7 @@
YoRHa Theme for RPCS3
by Ani @ https://github.com/AniLeo
r1 (2018.02.27)
r2 (2021.08.28)
*/
/*
@@ -33,93 +34,85 @@ QWidget {
alternate-background-color: transparent;
}
/* Debugger: Sets font-family to default (any invalid value could be provided) */
#debugger QListWidget, #debugger QTextEdit {
font-family: none;
}
/* Log+TTY: Use flat dark color background with default font for better readability */
#log_frame, #tty_frame {
background: rgba(52, 49, 40, 0.9);
font-size: 8.50pt;
font-family: none;
}
/* Debugger: Restore original font size */
#debugger QListWidget, #debugger QTextEdit {
font-size: 9.50pt;
}
/* LLE: Style QListWidget checkboxes (QListWidget) */
#lleList::indicator {
border: 0.05em solid #4d4940;
}
#lleList::indicator::unchecked {
background-color: #b3ac98;
}
#lleList::indicator::checked {
background-color: #4d4940;
}
#lleList::indicator::disabled {
background-color: #828790;
}
#lleList::item::selected {
color: #4d4940;
}
/* Style QTreeWidget checkboxes */
QTreeWidget::indicator {
border: 0.05em solid #4d4940;
}
QTreeWidget::indicator::unchecked {
background-color: #b3ac98;
}
QTreeWidget::indicator::checked {
background-color: #4d4940;
}
QTreeWidget::indicator::disabled {
background-color: #828790;
}
QTreeWidget::item::selected {
color: #4d4940;
}
/* Mouse Tooltips */
QToolTip {
background-color: #b3ac98;
color: #4d4940;
border: 0.10em solid #4d4940;
}
/* Main Window, Dialogs and some Dialogs that are actually widgets */
QDialog, QWidget#trophy_manager, QWidget#cg_disasm, QMainWindow#main_window {
/* Every dialog */
QDialog {
border-image: url("GuiConfigs/YoRHa-background.jpg");
}
/*
QTextEdit, QPlainTextEdit: Use flat dark color background with
a solid border, smaller font size and
default font family for better readability
RPCS3: Log, TTY, Log Viewer, CG Disasm
*/
QTextEdit, QPlainTextEdit {
background: rgba(52, 49, 40, 0.9);
border: 0.05em solid #4d4940;
color: #b3ac98;
font-family: none;
font-size: 8.50pt;
}
/*
QListWidget, QTreeWidget: Style checkboxes and rows
RPCS3: LLE/HLE Selector, Debugger
*/
QListWidget::item {
margin-top: 0.05em;
margin-bottom: 0.05em;
}
QListWidget::indicator, QTreeWidget::indicator {
border: 0.05em solid #4d4940;
}
QListWidget::indicator::unchecked, QTreeWidget::indicator::unchecked {
background-color: #b3ac98;
}
QListWidget::indicator::checked, QTreeWidget::indicator::checked {
background-color: #4d4940;
}
QListWidget::indicator::disabled, QTreeWidget::indicator::disabled {
background-color: #828790;
}
QListWidget::item::selected, QTreeWidget::item::selected {
background-color: #4d4940;
}
/*
QTableView: Style selected row
RPCS3: Game List
*/
QTableView {
selection-background-color: #4d4940;
}
/*
QToolTip: Mouse Tooltips
*/
QToolTip {
background-color: #b3ac98;
border: 0.10em solid #4d4940;
color: #4d4940;
}
/* Table headers */
QHeaderView::section {
text-transform: uppercase;
background: #4d4940;
color: #b3ac98;
padding-left: 0.15em;
padding-top: 0.15em;
padding-bottom: 0.10em;
padding-left: 0.20em;
padding-top: 0.25em;
margin-bottom: 0.05em;
text-transform: uppercase;
border: none;
}
/* All other Tabs */
QTabBar {
text-transform: uppercase;
}
QTabBar::tab {
background: transparent;
padding-left: 0.50em;
@@ -134,75 +127,32 @@ QTabBar::tab::selected {
border-bottom-style: solid;
}
/* Settings Dialog: Tabs */
QTabBar#tab_bar_settings {
border-bottom: 0.05em solid #4d4940;
text-transform: uppercase;
}
QTabBar::tab#tab_bar_settings {
background: transparent;
width: 5.20em;
padding-left: 0.50em;
padding-right: 0.50em;
padding-top: 0.65em;
padding-bottom: 0.65em;
margin-right: 0.25em;
font-size: 10.5pt;
font-weight: 550;
}
QTabBar::tab:last#tab_bar_settings {
margin-right: 0em;
}
QTabBar::tab:!selected:hover#tab_bar_settings {
background: transparent;
color: #4d4940;
}
QTabBar::tab::selected#tab_bar_settings {
background: #4d4940;
color: #aea993;
border-bottom-style: solid;
margin-top: 0.15em;
}
/* Checkboxes */
QCheckBox::indicator {
border-radius: 0.1em;
border: 0.05em solid #4d4940;
margin-top: 0.05em;
width: 0.8em;
height: 0.8em;
}
QCheckBox::indicator:checked {
background-color: #4d4940; /* Dark */
}
QCheckBox::indicator:unchecked {
background-color: #b3ac98; /* Light */
}
QCheckBox::indicator::disabled {
background-color: #828790; /* Gray */
}
/* Radio Buttons */
QRadioButton::indicator {
border-radius: 0.4em;
}
/* Checkboxes and Radio Buttons */
QCheckBox::indicator, QRadioButton::indicator {
border: 0.05em solid #4d4940;
margin-top: 0.05em;
margin-bottom: 0.05em;
width: 0.8em;
height: 0.8em;
}
QRadioButton::indicator:checked {
QCheckBox::indicator:checked, QRadioButton::indicator:checked {
background-color: #4d4940; /* Dark */
}
QRadioButton::indicator:unchecked {
QCheckBox::indicator:unchecked, QRadioButton::indicator:unchecked {
background-color: #b3ac98; /* Light */
}
QRadioButton::indicator::disabled {
QCheckBox::indicator::disabled, QRadioButton::indicator::disabled {
background-color: #828790; /* Gray */
}
/* Combo Boxes */
QComboBox {
background: transparent;
@@ -220,13 +170,12 @@ QComboBox::disabled {
color: #4d4940;
}
/* Group Boxes (Settings Dialog) */
QGroupBox {
margin-top: 1em;
border: 0.05em solid #4d4940;
text-transform: uppercase;
font-size: 9.25pt;
font-size: 9.00pt;
}
QGroupBox::title {
subcontrol-origin: margin;
@@ -235,7 +184,6 @@ QGroupBox::title {
color: #4d4940;
}
/* Buttons */
QPushButton {
background: #b3ac98;
@@ -244,40 +192,28 @@ QPushButton::disabled {
background: #828790;
}
/* QSpinBox (Settings -> Emulator -> width/height) */
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
QSpinBox, QDoubleSpinBox {
/* background: transparent; - This hits a weird bug in Qt where background flickers */
background-color: #b3ac98;
border: 0.05em solid #4d4940;
border-radius: 0.10em;
}
QSpinBox::disabled, QDoubleSpinBox::disabled {
background-color: #828790;
}
/* Styles Sliders */
QSlider::groove:horizontal {
border: 0.10em solid #4d4940;
border-radius: 0.10em;
}
QSlider::handle:horizontal {
background: #4d4940;
width: 0.50em;
}
QSlider#sizeSlider::groove:horizontal {
border: 0.10em solid #4d4940;
border-radius: 0.10em;
height: 1.5em;
QSlider::disabled {
background: #828790;
}
/* Log and Debugger borders */
QTextEdit {
border: 0.05em solid #4d4940;
}
/* For dock buttons to be visible */
QDockWidget {
background: transparent;
@@ -296,13 +232,11 @@ QDockWidget::close-button, QDockWidget::float-button {
background-color: #b3ac98;
}
/* Disable ugly borders */
QTabWidget::pane {
border: 0em solid #4d4940;
}
/* Top menu bar */
QMenuBar {
height:1.50em;
@@ -319,7 +253,6 @@ QMenuBar::item:selected {
color: #aea993
}
QMenu {
background: #b3ac98;
color: #4d4940;
@@ -342,42 +275,6 @@ QMenu::item:disabled {
color: #4d4940;
}
/* Pad Settings: Controller Image */
QLabel#l_controller {
color: #4d4940;
}
/* Game Grid Font */
QTableWidget#game_grid {
font-weight: 600;
color: #4d4940;
text-transform: uppercase;
selection-color: #aea993;
}
QTableWidget#game_grid::item:selected:active {
selection-background-color: #4d4940;
}
QTableWidget#game_grid::item:selected:!active {
selection-background-color: #615c51;
}
/* Debug UI Settings buttons */
QLabel#color_button {
background: transparent;
}
/* Search bar on main Toolbar */
QLineEdit#mw_searchbar {
margin-left: 0.7em;
color: #4d4940;
font-size: 10.25pt;
}
/* Uniform colors in Toolbar */
QToolButton {
background: transparent;
@@ -388,18 +285,95 @@ QToolButton::hover {
}
/*** RPCS3 Specifics ***/
/* Main Window, Dialogs and some Dialogs that are actually widgets */
QWidget#trophy_manager, QWidget#cg_disasm, QWidget#log_viewer, QMainWindow#main_window {
border-image: url("GuiConfigs/YoRHa-background.jpg");
}
/*
#debugger: Set font-family to default (any invalid value could be provided)
Reset background, color and font size to the global values
Add solid border
*/
#debugger QListWidget, #debugger QTextEdit {
background: transparent;
border: 0.05em solid #4d4940;
color: #292929;
font-family: none;
font-size: 9.50pt;
}
/* Pad Settings, Emulator Settings Dialogs: Tabs */
#pad_settings_dialog QTabWidget::tab-bar {
alignment: center;
}
QTabBar#tab_bar_settings, #pad_settings_dialog QTabBar {
border-bottom: 0.05em solid #4d4940;
text-transform: uppercase;
}
QTabBar::tab#tab_bar_settings, #pad_settings_dialog QTabBar::tab {
background: transparent;
width: 5.20em;
padding-left: 0.50em;
padding-right: 0.50em;
padding-top: 0.65em;
padding-bottom: 0.65em;
margin-right: 0.25em;
font-size: 10.5pt;
font-weight: 550;
}
QTabBar::tab:last#tab_bar_settings, #pad_settings_dialog QTabBar::tab:last {
margin-right: 0em;
}
QTabBar::tab:!selected:hover#tab_bar_settings, #pad_settings_dialog QTabBar::tab:!selected:hover {
background: transparent;
color: #4d4940;
}
QTabBar::tab::selected#tab_bar_settings, #pad_settings_dialog QTabBar::tab::selected {
background: #4d4940;
color: #aea993;
border-bottom-style: solid;
margin-top: 0.15em;
}
/* Pad Settings: Controller Image */
QLabel#l_controller {
color: #4d4940;
}
/* Game Grid Font */
QTableWidget#game_grid {
font-weight: 600;
color: #4d4940;
text-transform: uppercase;
selection-color: #aea993;
}
/* Debug UI Settings buttons */
QLabel#color_button {
background: transparent;
}
/* Search bar on main Toolbar */
QLineEdit#mw_searchbar {
margin-left: 0.7em;
color: #4d4940;
font-size: 10.25pt;
}
/* Set Theme UI colors */
QLabel#gamelist_icon_background_color {
color: transparent;
}
/* Set Windows Taskbar Thumbnail colors */
QLabel#thumbnail_icon_color {
color: #4d4940;
}
QLabel#log_level_always {
color: #00ffff; /* Cyan */
}
@@ -433,7 +407,6 @@ QLabel#log_stack {
color: #b3ac98; /* Light */
}
/* Memory Viewer */
QLabel#memory_viewer_address_panel {
color: #0000ff; /* Font Color: Blue */
@@ -445,7 +418,6 @@ QLabel#memory_viewer_ascii_panel {
color: #4d4940; /* Font Color: Grey */
}
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000000; /* Font Color: Black */
@@ -456,9 +428,15 @@ QLabel#debugger_frame_pc {
background-color: #00ff00; /* Green */
}
/* Trophy Notification Popup */
QWidget#trophy_notification_frame {
background-color: #b3ac98;
color: #4d4940;
}
/*
#sizeSlider: Style the main window's icon size slider so it's not stretched
*/
QSlider#sizeSlider::groove:horizontal {
height: 1.5em;
}
Binary file not shown.
+13 -2
View File
@@ -20,11 +20,20 @@ else()
# Some distros have the compilers set to use PIE by default, but RPCS3 doesn't work with PIE, so we need to disable it.
CHECK_CXX_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
CHECK_CXX_COMPILER_FLAG("-msse -msse2 -mcx16" COMPILER_X86)
CHECK_CXX_COMPILER_FLAG("-march=armv8.1-a" COMPILER_ARM)
add_compile_options(-Wall)
add_compile_options(-fno-exceptions)
add_compile_options(-fstack-protector)
add_compile_options(-msse -msse2 -mcx16)
if (COMPILER_X86)
add_compile_options(-msse -msse2 -mcx16)
endif()
if (COMPILER_ARM)
add_compile_options(-march=armv8.1-a)
endif()
add_compile_options(-Werror=old-style-cast)
add_compile_options(-Werror=sign-compare)
@@ -81,7 +90,9 @@ else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
endif()
elseif(APPLE)
add_compile_options(-stdlib=libc++)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-stdlib=libc++)
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-image_base,0x10000 -Wl,-pagezero_size,0x10000")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie")
elseif(WIN32)
+2 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
@@ -61,6 +61,7 @@
LLVMBitWriter.lib;
LLVMCoroutines.lib;
LLVMObjCARCOpts.lib;
LLVMIntelJITEvents.lib;
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
+2 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
@@ -62,6 +62,7 @@
LLVMBitWriter.lib;
LLVMCoroutines.lib;
LLVMObjCARCOpts.lib;
LLVMIntelJITEvents.lib;
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
+21
View File
@@ -0,0 +1,21 @@
#import <Foundation/Foundation.h>
namespace Darwin_Version
{
NSOperatingSystemVersion osver = NSProcessInfo.processInfo.operatingSystemVersion;
int getNSmajorVersion()
{
return osver.majorVersion;
}
int getNSminorVersion()
{
return osver.minorVersion;
}
int getNSpatchVersion()
{
return osver.patchVersion;
}
}
+1 -1
Submodule llvm updated: 5836324d64...509d31ad89
+2 -2
View File
@@ -39,9 +39,9 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeReleaseCLI>call vsdevcmd.bat -arch=amd64
cmake -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="./Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeReleaseCLI>
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="./Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DLLVM_USE_INTEL_JITEVENTS=ON ../llvm</CmakeReleaseCLI>
<CmakeDebugCLI>call vsdevcmd.bat -arch=amd64
cmake -G Ninja -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_INSTALL_PREFIX="./Debug" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeDebugCLI>
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_INSTALL_PREFIX="./Debug" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DLLVM_USE_INTEL_JITEVENTS=ON ../llvm</CmakeDebugCLI>
<CmakeCleanCLI>echo Cleaning..
for /F "delims= eol=|" %%f in ('
dir /b ^| findstr /V "[^.]*\build[^.]*\.vcxproj"') do (
+2 -2
View File
@@ -39,9 +39,9 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeReleaseCLI>call vsdevcmd.bat -arch=amd64
cmake -G Ninja -DCMAKE_CXX_COMPILER="clang-cl.exe" -DCMAKE_C_COMPILER="clang-cl.exe" -DCMAKE_BUILD_TYPE="Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DCMAKE_INSTALL_PREFIX="./Release" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeReleaseCLI>
cmake -G Ninja -DCMAKE_CXX_COMPILER="clang-cl.exe" -DCMAKE_C_COMPILER="clang-cl.exe" -DCMAKE_BUILD_TYPE="Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DCMAKE_INSTALL_PREFIX="./Release" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DLLVM_USE_INTEL_JITEVENTS=ON ../llvm</CmakeReleaseCLI>
<CmakeDebugCLI>call vsdevcmd.bat -arch=amd64
cmake -G Ninja -DCMAKE_CXX_COMPILER="clang-cl.exe" -DCMAKE_C_COMPILER="clang-cl.exe" -DCMAKE_BUILD_TYPE="Debug" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DCMAKE_INSTALL_PREFIX="./Debug" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeDebugCLI>
cmake -G Ninja -DCMAKE_CXX_COMPILER="clang-cl.exe" -DCMAKE_C_COMPILER="clang-cl.exe" -DCMAKE_BUILD_TYPE="Debug" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DCMAKE_INSTALL_PREFIX="./Debug" -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DLLVM_USE_INTEL_JITEVENTS=ON ../llvm</CmakeDebugCLI>
<CmakeCleanCLI>echo Cleaning..
for /F "delims= eol=|" %%f in ('
dir /b ^| findstr /V "[^.]*\build[^.]*\.vcxproj"') do (
+211
View File
@@ -0,0 +1,211 @@
// objdump injection utility for Linux perf tools.
// Profiling JIT generated code is always problematic.
// On Linux, perf annotation tools do not automatically
// disassemble runtime-generated code.
// However, it's possible to override objdump utility
// which is used to disassemeble executables.
// This tool intercepts objdump commands, and if they
// correspond to JIT generated objects in RPCS3,
// it should be able to correctly disassemble them.
// Usage:
// 1. Make sure ~/.cache/rpcs3/ASMJIT directory exists.
// 2. Build this utility, for example:
// g++-11 objdump.cpp -o objdump
// 3. Run perf, for example:
// perf record -b -p `pgrep rpcs3`
// 4. Specify --objdump override, for example:
// perf report --objdump=./objdump --gtk
#include <cstring>
#include <cstdio>
#include <cstdint>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <string>
#include <vector>
#include <charconv>
std::string to_hex(std::uint64_t value, bool prfx = true)
{
char buf[20]{}, *ptr = buf + 19;
do *--ptr = "0123456789abcdef"[value % 16], value /= 16; while (value);
if (!prfx) return ptr;
*--ptr = 'x';
*--ptr = '0';
return ptr;
}
int main(int argc, char* argv[])
{
std::string home;
if (const char* d = ::getenv("XDG_CACHE_HOME"))
home = d;
else if (const char* d = ::getenv("XDG_CONFIG_HOME"))
home = d;
else if (const char* d = ::getenv("HOME"))
home = d, home += "/.cache";
// Get cache path
home += "/rpcs3/ASMJIT/";
// Get objects
int fd = open((home + ".objects").c_str(), O_RDONLY);
if (fd < 0)
return 1;
// Map 4GiB (full size)
const auto data = mmap(nullptr, 0x10000'0000, PROT_READ, MAP_SHARED, fd, 0);
struct entry
{
std::uint64_t addr;
std::uint32_t size;
std::uint32_t off;
};
// Index part (precedes actual data)
const auto index = static_cast<const entry*>(data);
const entry* found = nullptr;
std::string out_file;
std::vector<std::string> args;
for (int i = 0; i < argc; i++)
{
// Replace args
std::string arg = argv[i];
if (std::uintptr_t(data) != -1 && arg.find("--start-address=0x") == 0)
{
// Decode address and try to find the object
std::uint64_t addr = -1;
std::from_chars(arg.data() + strlen("--start-address=0x"), arg.data() + arg.size(), addr, 16);
for (int j = 0; j < 0x100'0000; j++)
{
if (index[j].addr == 0)
{
break;
}
if (index[j].addr == addr)
{
found = index + j;
break;
}
}
if (found)
{
// Extract object into a new file (read file name from the mapped memory)
const char* name = static_cast<char*>(data) + found->off + found->size;
if (name[0])
{
out_file = home + name;
}
else
{
out_file = "/tmp/rpcs3.objdump." + std::to_string(getpid());
unlink(out_file.c_str());
}
const int fd2 = open(out_file.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd2 > 0)
{
// Don't overwrite if exists
write(fd2, static_cast<char*>(data) + found->off, found->size);
close(fd2);
}
args.emplace_back("--adjust-vma=" + to_hex(addr));
continue;
}
}
if (found && arg.find("--stop-address=0x") == 0)
{
continue;
}
if (found && arg == "-d")
{
arg = "-D";
}
if (arg == "-l")
{
arg = "-Mintel,x86-64";
}
args.emplace_back(std::move(arg));
}
if (found)
{
args.pop_back();
args.emplace_back("-b");
args.emplace_back("binary");
args.emplace_back("-m");
args.emplace_back("i386:x86-64");
args.emplace_back(std::move(out_file));
}
args[0] = "/usr/bin/objdump";
std::vector<char*> new_argv;
for (auto& arg : args)
{
new_argv.push_back(arg.data());
}
new_argv.push_back(nullptr);
if (found)
{
int fds[2];
pipe(fds);
if (fork() > 0)
{
close(fds[1]);
char c = 0;
std::string buf;
while (read(fds[0], &c, 1) != 0)
{
if (c)
{
buf += c;
if (c == '\n')
{
write(STDOUT_FILENO, buf.data(), buf.size());
buf.clear();
}
}
c = 0;
}
return 0;
}
else
{
while ((dup2(fds[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
close(fds[1]);
close(fds[0]);
// Fallthrough
}
}
return execv(new_argv[0], new_argv.data());
}
+24 -8
View File
@@ -17,8 +17,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rpcs3.emu", "rpcs3.emu", "{
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio", "rpcs3\XAudio.vcxproj", "{78CB2F39-B809-4A06-8329-8C0A19119D3D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenAL", "rpcs3\OpenAL.vcxproj", "{30A05C4D-F5FD-421C-A864-17A64BDEAA75}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pnglibconf", "3rdparty\libpng\pnglibconf.vcxproj", "{EB33566E-DA7F-4D28-9077-88C0B7C77E35}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "3rdparty\libpng\libpng.vcxproj", "{D6973076-9317-4EF2-A0B8-B7A18AC0713E}"
@@ -47,10 +45,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
{C4A10229-4712-4BD2-B63E-50D93C67A038} = {C4A10229-4712-4BD2-B63E-50D93C67A038}
{78CB2F39-B809-4A06-8329-8C0A19119D3D} = {78CB2F39-B809-4A06-8329-8C0A19119D3D}
{3384223A-6D97-4799-9862-359F85312892} = {3384223A-6D97-4799-9862-359F85312892}
{30A05C4D-F5FD-421C-A864-17A64BDEAA75} = {30A05C4D-F5FD-421C-A864-17A64BDEAA75}
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF}
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E}
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2} = {9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}
{FDA7B080-03B0-48C8-B24F-88118981422A} = {FDA7B080-03B0-48C8-B24F-88118981422A}
{508c291a-3d18-49f5-b25d-f7c8db92cb21} = {508c291a-3d18-49f5-b25d-f7c8db92cb21}
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}
{FDC361C5-7734-493B-8CFB-037308B35122} = {FDC361C5-7734-493B-8CFB-037308B35122}
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {8F85B6CC-250F-4ACA-A617-E820A74E3E3C}
@@ -79,6 +79,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rdParty", "3rdParty", "{6C
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llvm_build_clang_cl", "llvm_build\llvm_build_clang_cl.vcxproj", "{A37E4273-85DB-4217-B775-CE971B87D9DF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cubeb", "rpcs3\Cubeb.vcxproj", "{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcubeb", "3rdparty\cubeb\libcubeb.vcxproj", "{FDA7B080-03B0-48C8-B24F-88118981422A}"
EndProject
Project("{508c291a-3d18-49f5-b25d-f7c8db92cb21}") = "soundtouch", "3rdparty\SoundTouch\soundtouch.vcxproj", "{508c291a-3d18-49f5-b25d-f7c8db92cb21}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -103,10 +109,6 @@ Global
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug|x64.Build.0 = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release|x64.ActiveCfg = Release|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release|x64.Build.0 = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug|x64.ActiveCfg = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug|x64.Build.0 = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release|x64.ActiveCfg = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release|x64.Build.0 = Release|x64
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|x64.ActiveCfg = Release|x64
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|x64.Build.0 = Release|x64
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|x64.ActiveCfg = Release|x64
@@ -161,6 +163,18 @@ Global
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Release|x64.ActiveCfg = Release|x64
{A37E4273-85DB-4217-B775-CE971B87D9DF}.Debug|x64.ActiveCfg = Debug|x64
{A37E4273-85DB-4217-B775-CE971B87D9DF}.Release|x64.ActiveCfg = Release|x64
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}.Debug|x64.ActiveCfg = Debug|x64
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}.Debug|x64.Build.0 = Debug|x64
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}.Release|x64.ActiveCfg = Release|x64
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}.Release|x64.Build.0 = Release|x64
{FDA7B080-03B0-48C8-B24F-88118981422A}.Debug|x64.ActiveCfg = Debug|x64
{FDA7B080-03B0-48C8-B24F-88118981422A}.Debug|x64.Build.0 = Debug|x64
{FDA7B080-03B0-48C8-B24F-88118981422A}.Release|x64.ActiveCfg = Release|x64
{FDA7B080-03B0-48C8-B24F-88118981422A}.Release|x64.Build.0 = Release|x64
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Debug|x64.ActiveCfg = Debug|x64
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Debug|x64.Build.0 = Debug|x64
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Release|x64.ActiveCfg = Release|x64
{508c291a-3d18-49f5-b25d-f7c8db92cb21}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -171,7 +185,6 @@ Global
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{3384223A-6D97-4799-9862-359F85312892} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{78CB2F39-B809-4A06-8329-8C0A19119D3D} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{30A05C4D-F5FD-421C-A864-17A64BDEAA75} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
@@ -186,6 +199,9 @@ Global
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{A37E4273-85DB-4217-B775-CE971B87D9DF} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{FDA7B080-03B0-48C8-B24F-88118981422A} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{508c291a-3d18-49f5-b25d-f7c8db92cb21} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
+14 -23
View File
@@ -3,6 +3,9 @@ if(USE_PRECOMPILED_HEADERS AND NOT COMMAND target_precompile_headers)
include(cotire)
endif()
# Define GNU standard installation directories
include(GNUInstallDirs)
# Generate git-version.h at build time.
include(${CMAKE_CURRENT_SOURCE_DIR}/git-version.cmake)
@@ -23,6 +26,7 @@ elseif(NOT MSVC AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
endif()
if(UNIX AND NOT APPLE)
add_definitions(-DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}/rpcs3")
# Optionally enable X11 for window management
find_package(X11)
if(X11_FOUND)
@@ -151,10 +155,6 @@ elseif(UNIX)
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/git)
elseif(WIN32)
# TODO(cjj19970505@live.cn)
# this is a single-config generator workaround
# multi-config generator will fail.
# TODO(cjj19970505@live.cn)
# offical Qt binaries are built with -MD(d) only as stated in offical wiki
# 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
@@ -175,19 +175,10 @@ elseif(WIN32)
list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../bin/")
# If Qt5 is installed from vcpkg
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../tools/qt5/debug/bin/")
else()
list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../tools/qt5/bin/")
endif()
find_program(_WINDEPLOYQT
NAMES windeployqt
PATHS ${_QT5_TOOLS_PATHS}
REQUIRED)
message("Use windeployqt in ${_WINDEPLOYQT}")
list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../tools/qt5$<$<CONFIG:Debug>:/debug>/bin/")
add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND set PATH=${_QT5_TOOLS_PATHS}$<SEMICOLON>%PATH%
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/bin" "$<TARGET_FILE_DIR:rpcs3>"
# If Qt5 is installed from vcpkg, add binary path to PATH
# otherwise windeployqt tool won't be able to locate necessary dlls
@@ -198,21 +189,21 @@ endif()
# Unix installation
if(UNIX AND NOT APPLE)
# Install the binary
install(TARGETS rpcs3 RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
install(TARGETS rpcs3 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# Install the application icon and menu item
install(FILES rpcs3.svg
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps)
install(FILES rpcs3.png
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps)
install(FILES rpcs3.desktop
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES rpcs3.metainfo.xml
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
# Install other files
install(DIRECTORY ../bin/Icons
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/rpcs3)
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
install(DIRECTORY ../bin/GuiConfigs
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/rpcs3)
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
install(DIRECTORY ../bin/git
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/rpcs3)
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
endif()
+10 -1
View File
@@ -32,6 +32,8 @@
#include "aes.h"
#include "aesni.h"
#include <algorithm>
/*
* 32-bit integer manipulation macros (little endian)
*/
@@ -459,8 +461,10 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
ctx->rk = RK = ctx->buf;
#if defined(__SSE2__) || defined(_M_X64)
if( aesni_supports( POLARSSL_AESNI_AES ) )
return( aesni_setkey_enc( reinterpret_cast<unsigned char*>(ctx->rk), key, keysize ) );
#endif
for( i = 0; i < (keysize >> 5); i++ )
{
@@ -562,12 +566,14 @@ int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int key
if( ret != 0 )
return( ret );
#if defined(__SSE2__) || defined(_M_X64)
if( aesni_supports( POLARSSL_AESNI_AES ) )
{
aesni_inverse_key( reinterpret_cast<unsigned char*>(ctx->rk),
reinterpret_cast<const unsigned char*>(cty.rk), ctx->nr );
goto done;
}
#endif
SK = cty.rk + cty.nr * 4;
@@ -593,7 +599,8 @@ int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int key
*RK++ = *SK++;
done:
memset( &cty, 0, sizeof( aes_context ) );
// Wipe the stack buffer clean
std::fill_n(reinterpret_cast<volatile char*>(&cty), sizeof(cty), 0);
return( 0 );
}
@@ -655,8 +662,10 @@ int aes_crypt_ecb( aes_context *ctx,
int i;
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
#if defined(__SSE2__) || defined(_M_X64)
if( aesni_supports( POLARSSL_AESNI_AES ) )
return( aesni_crypt_ecb( ctx, mode, input, output ) );
#endif
RK = ctx->rk;
+4
View File
@@ -1,3 +1,5 @@
#if defined(__SSE2__) || defined(_M_X64)
/*
* AES-NI support functions
*
@@ -680,3 +682,5 @@ int aesni_setkey_enc( unsigned char *rk,
return( 0 );
}
#endif
+48 -58
View File
@@ -549,6 +549,11 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
bool validate_dev_klic(const u8* klicensee, NPD_HEADER *npd)
{
if ((npd->license & 0x3) != 0x3)
{
return true;
}
unsigned char dev[0x60] = { 0 };
// Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
@@ -566,12 +571,6 @@ bool validate_dev_klic(const u8* klicensee, NPD_HEADER *npd)
u128 klic;
std::memcpy(&klic, klicensee, sizeof(klic));
if (!klic)
{
// Allow empty dev hash.
return true;
}
// Generate klicensee xor key.
u128 key = klic ^ std::bit_cast<u128>(NP_OMAC_KEY_2);
@@ -579,13 +578,19 @@ bool validate_dev_klic(const u8* klicensee, NPD_HEADER *npd)
return cmac_hash_compare(reinterpret_cast<uchar*>(&key), 0x10, dev, 0x60, npd->dev_hash, 0x10);
}
bool validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *npd, bool verbose)
bool validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *npd, EDAT_HEADER* edat, bool verbose)
{
if (!file_name)
{
fmt::throw_exception("Empty filename");
}
// Ignore header validation in DEBUG data.
if (edat->flags & EDAT_DEBUG_DATA_FLAG)
{
return true;
}
const usz file_name_length = std::strlen(file_name);
const usz buf_len = 0x30 + file_name_length;
@@ -704,14 +709,10 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
// Perform header validation (EDAT only).
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name, real_file_name);
if (!validate_npd_hashes(real_file_name, devklic, &NPD, verbose))
if (!validate_npd_hashes(real_file_name, devklic, &NPD, &EDAT, verbose))
{
// Ignore header validation in DEBUG data.
if ((EDAT.flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
{
edat_log.error("NPD hash validation failed!");
return true;
}
edat_log.error("NPD hash validation failed!");
return true;
}
// Select EDAT key.
@@ -784,7 +785,7 @@ u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file)
return rifkey;
}
bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, std::string* contentID)
bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, std::string* contentID, u32* license)
{
// Setup NPD and EDAT/SDAT structs.
NPD_HEADER NPD;
@@ -808,17 +809,17 @@ bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& inpu
// Perform header validation (EDAT only).
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name.c_str(), real_file_name);
if (!validate_npd_hashes(real_file_name, custom_klic, &NPD, false))
if (!validate_npd_hashes(real_file_name, custom_klic, &NPD, &EDAT, false))
{
// Ignore header validation in DEBUG data.
if ((EDAT.flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
{
edat_log.error("NPD hash validation failed!");
return false;
}
edat_log.error("NPD hash validation failed!");
return false;
}
*contentID = std::string(reinterpret_cast<const char*>(NPD.content_id));
std::string_view sv{NPD.content_id, std::size(NPD.content_id)};
sv = sv.substr(0, sv.find_first_of('\0'));
if (contentID) *contentID = std::string(sv);
if (license) *license = (NPD.license & 3);
return true;
}
@@ -910,33 +911,13 @@ bool EDATADecrypter::ReadHeader()
else
{
// verify key
if (!validate_dev_klic(reinterpret_cast<uchar*>(&dev_key), &npdHeader))
if (!validate_dev_klic(reinterpret_cast<uchar*>(&dec_key), &npdHeader))
{
edat_log.error("Failed validating klic");
return false;
}
// Select EDAT key.
if ((npdHeader.license & 0x3) == 0x3) // Type 3: Use supplied devklic.
dec_key = std::move(dev_key);
else if ((npdHeader.license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
{
dec_key = std::move(rif_key);
if (!dec_key)
{
edat_log.warning("Empty Dec key for local activation!");
}
}
else if ((npdHeader.license & 0x1) == 0x1) // Type 1: Use network activation.
{
dec_key = std::move(rif_key);
if (!dec_key)
{
edat_log.warning("Empty Dec key for network activation!");
}
}
// Use provided dec_key
}
edata_file.seek(0);
@@ -952,29 +933,37 @@ bool EDATADecrypter::ReadHeader()
file_size = edatHeader.file_size;
total_blocks = utils::aligned_div(edatHeader.file_size, edatHeader.block_size);
// Try decrypting the first block instead
u8 data_sample[1];
if (file_size && !ReadData(0, data_sample, 1))
{
return false;
}
return true;
}
u64 EDATADecrypter::ReadData(u64 pos, u8* data, u64 size)
{
if (pos > edatHeader.file_size)
return 0;
size = std::min<u64>(size, pos > edatHeader.file_size ? 0 : edatHeader.file_size - pos);
// now we need to offset things to account for the actual 'range' requested
const u64 startOffset = pos % edatHeader.block_size;
const u32 num_blocks = static_cast<u32>(utils::aligned_div(startOffset + size, edatHeader.block_size));
const u64 bufSize = num_blocks*edatHeader.block_size;
if (data_buf_size < (bufSize))
if (!size)
{
data_buf.reset(new u8[bufSize]);
data_buf_size = bufSize;
return 0;
}
// find and decrypt block range covering pos + size
const u32 starting_block = static_cast<u32>(pos / edatHeader.block_size);
const u32 ending_block = std::min(starting_block + num_blocks, total_blocks);
// Now we need to offset things to account for the actual 'range' requested
const u64 startOffset = pos % edatHeader.block_size;
const u64 num_blocks = utils::aligned_div(startOffset + size, edatHeader.block_size);
data_buf.resize(num_blocks * edatHeader.block_size);
// Find and decrypt block range covering pos + size
const u32 starting_block = ::narrow<u32>(pos / edatHeader.block_size);
const u32 ending_block = ::narrow<u32>(std::min<u64>(starting_block + num_blocks, total_blocks));
u64 writeOffset = 0;
for (u32 i = starting_block; i < ending_block; ++i)
{
edata_file.seek(0);
@@ -984,6 +973,7 @@ u64 EDATADecrypter::ReadData(u64 pos, u8* data, u64 size)
edat_log.error("Error Decrypting data");
return 0;
}
writeOffset += res;
}
+21 -17
View File
@@ -16,9 +16,21 @@ constexpr u32 EDAT_DEBUG_DATA_FLAG = 0x80000000;
struct loaded_npdrm_keys
{
atomic_t<u128> devKlic{};
atomic_t<u128> rifKey{};
atomic_t<u128> dec_keys[16]{};
atomic_t<u64> dec_keys_pos = 0;
atomic_t<u32> npdrm_fds{0};
void install_decryption_key(u128 key)
{
dec_keys_pos.atomic_op([&](u64& pos) { dec_keys[pos++ % std::size(dec_keys)] = key; });
}
// TODO: Check if correct for ELF files usage
u128 last_key() const
{
const usz pos = dec_keys_pos;
return pos ? dec_keys[(pos - 1) % std::size(dec_keys)].load() : u128{};
}
};
struct NPD_HEADER
@@ -45,14 +57,14 @@ struct EDAT_HEADER
// Decrypts full file, or null/empty file
extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic, bool verbose);
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, std::string* contentID);
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, std::string* contentID = nullptr, u32* license = nullptr);
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
struct EDATADecrypter final : fs::file_base
{
// file stream
const fs::file edata_file;
fs::file edata_file;
u64 file_size{0};
u32 total_blocks{0};
u64 pos{0};
@@ -61,25 +73,17 @@ struct EDATADecrypter final : fs::file_base
EDAT_HEADER edatHeader{};
// Internal data buffers.
std::unique_ptr<u8[]> data_buf{};
u64 data_buf_size{0};
std::vector<u8> data_buf{};
u128 dec_key{};
// edat usage
u128 rif_key{};
u128 dev_key{};
public:
// SdataByFd usage
EDATADecrypter(fs::file&& input)
: edata_file(std::move(input)) {}
// Edat usage
EDATADecrypter(fs::file&& input, const u128& dev_key, const u128& rif_key)
EDATADecrypter(fs::file&& input, u128 dec_key = {})
: edata_file(std::move(input))
, rif_key(rif_key)
, dev_key(dev_key) {}
, dec_key(dec_key)
{
}
~EDATADecrypter() override {}
// false if invalid
bool ReadHeader();
u64 ReadData(u64 pos, u8* data, u64 size);
+22 -1
View File
@@ -1343,6 +1343,27 @@ static bool IsSelfElf32(const fs::file& f)
return (elf_class[4] == 1);
}
static bool IsDebugSelf(const fs::file& f)
{
if (f.size() < 0x18)
{
return false;
}
// Get the key version.
f.seek(0x08);
const u16 key_version = f.read<le_t<u16>>();
// Check for DEBUG version.
if (key_version == 0x80 || key_version == 0xc0)
{
return true;
}
return false;
}
static bool CheckDebugSelf(fs::file& s)
{
if (s.size() < 0x18)
@@ -1442,7 +1463,7 @@ bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
self.seek(0);
if (self.size() >= 4 && self.read<u32>() == "SCE\0"_u32)
if (self.size() >= 4 && self.read<u32>() == "SCE\0"_u32 && !IsDebugSelf(self))
{
// Check the ELF file class (32 or 64 bit).
const bool isElf32 = IsSelfElf32(self);
+11 -20
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@@ -11,9 +11,8 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{30A05C4D-F5FD-421C-A864-17A64BDEAA75}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OpenAL</RootNamespace>
<ProjectGuid>{9610627D-20FE-4B07-8CE3-9FF68A5F1EC2}</ProjectGuid>
<RootNamespace>Cubeb</RootNamespace>
</PropertyGroup>
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -37,36 +36,28 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'" Label="PropertySheets">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_llvm.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'" Label="PropertySheets">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_llvm.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.\3rdparty\OpenAL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\3rdparty\cubeb\cubeb\include\;..\3rdparty\cubeb\extra\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Emu\Audio\AL\OpenALBackend.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Emu\Audio\AL\OpenALBackend.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="emucore.vcxproj">
<Project>{c4a10229-4712-4bd2-b63e-50d93c67a038}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Emu\Audio\Cubeb\CubebBackend.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Emu\Audio\Cubeb\CubebBackend.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<UniqueIdentifier>{F573EFFC-2BB8-43DF-AEFA-4E9EA31A817F}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Emu\Audio\AL\OpenALBackend.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Emu\Audio\AL\OpenALBackend.cpp">
<ClCompile Include="Emu\Audio\Cubeb\CubebBackend.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
<ItemGroup>
<ClInclude Include="Emu\Audio\Cubeb\CubebBackend.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
-212
View File
@@ -1,212 +0,0 @@
#include "stdafx.h"
#include "OpenALBackend.h"
#ifdef _MSC_VER
#pragma comment(lib, "OpenAL32.lib")
#endif
LOG_CHANNEL(OpenAL);
#define checkForAlError(sit) do { ALenum g_last_al_error = alGetError(); if(g_last_al_error != AL_NO_ERROR) OpenAL.error("%s: OpenAL error 0x%04x", sit, g_last_al_error); } while(0)
#define checkForAlcError(sit) do { ALCenum g_last_alc_error = alcGetError(m_device); if(g_last_alc_error != ALC_NO_ERROR) { OpenAL.error("%s: OpenALC error 0x%04x", sit, g_last_alc_error); return; }} while(0)
OpenALBackend::OpenALBackend()
: AudioBackend()
{
ALCint attribs[] = {ALC_FREQUENCY, DEFAULT_AUDIO_SAMPLING_RATE, 0, 0};
ALCdevice* m_device = alcOpenDevice(nullptr);
checkForAlcError("alcOpenDevice");
ALCcontext* m_context = alcCreateContext(m_device, attribs);
checkForAlcError("alcCreateContext");
alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent");
switch (m_channels)
{
case 2:
m_format = (m_sample_size == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
break;
case 6:
m_format = (m_sample_size == 2) ? AL_FORMAT_51CHN16 : AL_FORMAT_51CHN32;
break;
default:
m_format = (m_sample_size == 2) ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
break;
}
}
OpenALBackend::~OpenALBackend()
{
if (alIsSource(m_source))
{
Close();
}
if (ALCcontext* m_context = alcGetCurrentContext())
{
ALCdevice* m_device = alcGetContextsDevice(m_context);
alcMakeContextCurrent(nullptr);
alcDestroyContext(m_context);
alcCloseDevice(m_device);
}
}
void OpenALBackend::Play()
{
AUDIT(alIsSource(m_source));
ALint state;
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
checkForAlError("Play->alGetSourcei(AL_SOURCE_STATE)");
if (state != AL_PLAYING)
{
alSourcePlay(m_source);
checkForAlError("Play->alSourcePlay");
}
}
void OpenALBackend::Pause()
{
AUDIT(alIsSource(m_source));
alSourcePause(m_source);
checkForAlError("Pause->alSourcePause");
}
bool OpenALBackend::IsPlaying()
{
AUDIT(alIsSource(m_source));
ALint state;
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
checkForAlError("IsPlaying->alGetSourcei(AL_SOURCE_STATE)");
return state == AL_PLAYING;
}
void OpenALBackend::Open(u32 num_buffers)
{
AUDIT(!alIsSource(m_source));
// Initialize Source
alGenSources(1, &m_source);
checkForAlError("Open->alGenSources");
alSourcei(m_source, AL_LOOPING, AL_FALSE);
checkForAlError("Open->alSourcei");
// Initialize Buffers
alGenBuffers(num_buffers, m_buffers);
checkForAlError("Open->alGenBuffers");
m_num_buffers = num_buffers;
m_num_unqueued = num_buffers;
}
void OpenALBackend::Close()
{
if (alIsSource(m_source))
{
// Stop & Kill Source
Pause();
alDeleteSources(1, &m_source);
// Free Buffers
alDeleteBuffers(m_num_buffers, m_buffers);
checkForAlError("alDeleteBuffers");
}
}
bool OpenALBackend::AddData(const void* src, u32 num_samples)
{
AUDIT(alIsSource(m_source));
// Unqueue processed buffers, if any
unqueue_processed();
// Fail if there are no free buffers remaining
if (m_num_unqueued == 0)
{
OpenAL.warning("No unqueued buffers remaining");
return false;
}
// Copy data to the next available buffer
alBufferData(m_buffers[m_next_buffer], m_format, src, num_samples * m_sample_size, m_sampling_rate);
checkForAlError("AddData->alBufferData");
// Enqueue buffer
alSourceQueueBuffers(m_source, 1, &m_buffers[m_next_buffer]);
checkForAlError("AddData->alSourceQueueBuffers");
m_num_unqueued--;
m_next_buffer = (m_next_buffer + 1) % m_num_buffers;
return true;
}
void OpenALBackend::Flush()
{
AUDIT(alIsSource(m_source));
// Stop source first
alSourceStop(m_source);
checkForAlError("Flush->alSourceStop");
// Unqueue processed buffers (should now be all of them)
unqueue_processed();
}
void OpenALBackend::unqueue_processed()
{
AUDIT(alIsSource(m_source));
// Get number of buffers
ALint num_processed;
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &num_processed);
checkForAlError("Flush->alGetSourcei(AL_BUFFERS_PROCESSED)");
if (num_processed > 0)
{
// Unqueue all buffers
ALuint x[MAX_AUDIO_BUFFERS];
alSourceUnqueueBuffers(m_source, num_processed, x);
checkForAlError("Flush->alSourceUnqueueBuffers");
m_num_unqueued += num_processed;
}
}
u64 OpenALBackend::GetNumEnqueuedSamples()
{
AUDIT(alIsSource(m_source));
// Get number of buffers queued
ALint num_queued;
alGetSourcei(m_source, AL_BUFFERS_QUEUED, &num_queued);
checkForAlError("GetNumEnqueuedSamples->alGetSourcei(AL_BUFFERS_QUEUED)");
AUDIT(static_cast<u32>(num_queued) <= m_num_buffers - m_num_unqueued);
// Get sample position
ALint sample_pos;
alGetSourcei(m_source, AL_SAMPLE_OFFSET, &sample_pos);
checkForAlError("GetNumEnqueuedSamples->alGetSourcei(AL_SAMPLE_OFFSET)");
// Return
return (num_queued * AUDIO_BUFFER_SAMPLES) + (sample_pos % AUDIO_BUFFER_SAMPLES);
}
f32 OpenALBackend::SetFrequencyRatio(f32 new_ratio)
{
new_ratio = std::clamp(new_ratio, 0.5f, 2.0f);
alSourcef(m_source, AL_PITCH, new_ratio);
checkForAlError("SetFrequencyRatio->alSourcei(AL_PITCH)");
return new_ratio;
}
-40
View File
@@ -1,40 +0,0 @@
#pragma once
#include "Emu/Audio/AudioBackend.h"
#include "3rdparty/OpenAL/include/alext.h"
class OpenALBackend : public AudioBackend
{
private:
ALint m_format{};
ALuint m_source{};
ALuint m_buffers[MAX_AUDIO_BUFFERS]{};
ALsizei m_num_buffers{};
u32 m_next_buffer = 0;
u32 m_num_unqueued = 0;
void unqueue_processed();
public:
OpenALBackend();
~OpenALBackend() override;
const char* GetName() const override { return "OpenAL"; }
static const u32 capabilities = PLAY_PAUSE_FLUSH | IS_PLAYING | GET_NUM_ENQUEUED_SAMPLES | SET_FREQUENCY_RATIO;
u32 GetCapabilities() const override { return capabilities; }
void Open(u32 num_buffers) override;
void Close() override;
void Play() override;
void Pause() override;
bool IsPlaying() override;
bool AddData(const void* src, u32 num_samples) override;
void Flush() override;
u64 GetNumEnqueuedSamples() override;
f32 SetFrequencyRatio(f32 new_ratio) override;
};
-166
View File
@@ -1,166 +0,0 @@
#ifndef HAVE_ALSA
#error "ALSA support disabled but still being built."
#endif
#include "stdafx.h"
#include "Emu/system_config.h"
#include "ALSABackend.h"
LOG_CHANNEL(ALSA);
static void error(int err, const char* reason)
{
ALSA.error("ALSA: %s failed: %s\n", reason, snd_strerror(err));
}
static bool check(int err, const char* reason)
{
if (err < 0)
{
error(err, reason);
return false;
}
return true;
}
ALSABackend::ALSABackend()
: AudioBackend()
{
}
ALSABackend::~ALSABackend()
{
if (tls_sw_params || tls_hw_params || tls_handle)
{
Close();
}
}
void ALSABackend::Open(u32 num_buffers)
{
if (!check(snd_pcm_open(&tls_handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK), "snd_pcm_open"))
return;
if (!check(snd_pcm_hw_params_malloc(&tls_hw_params), "snd_pcm_hw_params_malloc"))
return;
if (!check(snd_pcm_hw_params_any(tls_handle, tls_hw_params), "snd_pcm_hw_params_any"))
return;
if (!check(snd_pcm_hw_params_set_access(tls_handle, tls_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "snd_pcm_hw_params_set_access"))
return;
if (!check(snd_pcm_hw_params_set_format(tls_handle, tls_hw_params, m_convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
return;
uint rate = m_sampling_rate;
if (!check(snd_pcm_hw_params_set_rate_near(tls_handle, tls_hw_params, &rate, nullptr), "snd_pcm_hw_params_set_rate_near"))
return;
if (!check(snd_pcm_hw_params_set_channels(tls_handle, tls_hw_params, m_channels), "snd_pcm_hw_params_set_channels"))
return;
//uint period = 5333;
//if (!check(snd_pcm_hw_params_set_period_time_near(tls_handle, tls_hw_params, &period, nullptr), "snd_pcm_hw_params_set_period_time_near"))
// return;
//if (!check(snd_pcm_hw_params_set_periods(tls_handle, tls_hw_params, 4, 0), "snd_pcm_hw_params_set_periods"))
// return;
snd_pcm_uframes_t bufsize_frames = num_buffers * AUDIO_BUFFER_SAMPLES;
snd_pcm_uframes_t period_frames = AUDIO_BUFFER_SAMPLES;
if (!check(snd_pcm_hw_params_set_buffer_size_near(tls_handle, tls_hw_params, &bufsize_frames), "snd_pcm_hw_params_set_buffer_size_near"))
return;
if (!check(snd_pcm_hw_params_set_period_size_near(tls_handle, tls_hw_params, &period_frames, 0), "snd_pcm_hw_params_set_period_size"))
return;
if (!check(snd_pcm_hw_params(tls_handle, tls_hw_params), "snd_pcm_hw_params"))
return;
if (!check(snd_pcm_hw_params_get_buffer_size(tls_hw_params, &bufsize_frames), "snd_pcm_hw_params_get_buffer_size"))
return;
if (!check(snd_pcm_hw_params_get_period_size(tls_hw_params, &period_frames, nullptr), "snd_pcm_hw_params_get_period_size"))
return;
if (!check(snd_pcm_sw_params_malloc(&tls_sw_params), "snd_pcm_sw_params_malloc"))
return;
if (!check(snd_pcm_sw_params_current(tls_handle, tls_sw_params), "snd_pcm_sw_params_current"))
return;
period_frames *= m_start_threshold;
if (!check(snd_pcm_sw_params_set_start_threshold(tls_handle, tls_sw_params, period_frames + 1), "snd_pcm_sw_params_set_start_threshold"))
return;
if (!check(snd_pcm_sw_params_set_stop_threshold(tls_handle, tls_sw_params, bufsize_frames), "snd_pcm_sw_params_set_stop_threshold"))
return;
if (!check(snd_pcm_sw_params(tls_handle, tls_sw_params), "snd_pcm_sw_params"))
return;
if (!check(snd_pcm_prepare(tls_handle), "snd_pcm_prepare"))
return;
ALSA.notice("bufsize_frames=%u, period_frames=%u", bufsize_frames, period_frames);
}
void ALSABackend::Close()
{
if (tls_sw_params)
{
snd_pcm_sw_params_free(tls_sw_params);
tls_sw_params = nullptr;
}
if (tls_hw_params)
{
snd_pcm_hw_params_free(tls_hw_params);
tls_hw_params = nullptr;
}
if (tls_handle)
{
snd_pcm_close(tls_handle);
tls_handle = nullptr;
}
}
bool ALSABackend::AddData(const void* src, u32 num_samples)
{
u32 num_frames = num_samples / m_channels;
int res = snd_pcm_writei(tls_handle, src, num_frames);
if (res == -EAGAIN)
{
ALSA.warning("EAGAIN");
return false;
}
if (res < 0)
{
res = snd_pcm_recover(tls_handle, res, 0);
if (res < 0)
{
ALSA.warning("Failed to recover (%d)", res);
return false;
}
return false;
}
if (res + 0u != num_frames)
{
ALSA.warning("Error (%d)", res);
return false;
}
return true;
}
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#ifndef HAVE_ALSA
#error "ALSA support disabled but still being built."
#endif
#include "Emu/Audio/AudioBackend.h"
#include <alsa/asoundlib.h>
class ALSABackend : public AudioBackend
{
snd_pcm_t* tls_handle{};
snd_pcm_hw_params_t* tls_hw_params{};
snd_pcm_sw_params_t* tls_sw_params{};
public:
ALSABackend();
virtual ~ALSABackend() override;
ALSABackend(const ALSABackend&) = delete;
ALSABackend& operator=(const ALSABackend&) = delete;
virtual const char* GetName() const override { return "ALSA"; }
static const u32 capabilities = 0;
virtual u32 GetCapabilities() const override { return capabilities; }
virtual void Open(u32) override;
virtual void Close() override;
virtual bool AddData(const void* src, u32 num_samples) override;
};
+9 -79
View File
@@ -2,105 +2,35 @@
#include "AudioBackend.h"
#include "Emu/system_config.h"
AudioBackend::AudioBackend()
{
m_convert_to_u16 = static_cast<bool>(g_cfg.audio.convert_to_u16);
m_sample_size = m_convert_to_u16 ? sizeof(u16) : sizeof(float);
m_start_threshold = g_cfg.audio.start_threshold;
const u32 sampling_period_multiplier_u32 = g_cfg.audio.sampling_period_multiplier;
if (sampling_period_multiplier_u32 == 100)
{
m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
}
else
{
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
m_sampling_rate = static_cast<u32>(f32{ DEFAULT_AUDIO_SAMPLING_RATE } *sampling_rate_multiplier);
}
const audio_downmix downmix = g_cfg.audio.audio_channel_downmix.get();
switch (downmix)
{
case audio_downmix::no_downmix:
m_channels = 8;
break;
case audio_downmix::downmix_to_stereo:
m_channels = 2;
break;
case audio_downmix::downmix_to_5_1:
m_channels = 6;
break;
case audio_downmix::use_application_settings:
m_channels = 2; // TODO
break;
default:
fmt::throw_exception("Unknown audio channel mode %s (%d)", downmix, static_cast<int>(downmix));
}
}
AudioBackend::AudioBackend() {}
/*
* Helper methods
*/
u32 AudioBackend::get_sampling_rate() const
{
return m_sampling_rate;
return static_cast<std::underlying_type_t<decltype(m_sampling_rate)>>(m_sampling_rate);
}
u32 AudioBackend::get_sample_size() const
{
return m_sample_size;
return static_cast<std::underlying_type_t<decltype(m_sample_size)>>(m_sample_size);
}
u32 AudioBackend::get_channels() const
{
return m_channels;
return static_cast<std::underlying_type_t<decltype(m_channels)>>(m_channels);
}
bool AudioBackend::get_convert_to_u16() const
bool AudioBackend::get_convert_to_s16() const
{
return m_convert_to_u16;
return m_sample_size == AudioSampleSize::S16;
}
bool AudioBackend::has_capability(u32 cap) const
void AudioBackend::convert_to_s16(u32 cnt, const f32* src, void* dst)
{
return (cap & GetCapabilities()) == cap;
}
void AudioBackend::dump_capabilities(std::string& out) const
{
u32 count = 0;
const u32 capabilities = GetCapabilities();
if (capabilities & PLAY_PAUSE_FLUSH)
for (usz i = 0; i < cnt; i++)
{
fmt::append(out, "PLAY_PAUSE_FLUSH");
count++;
}
if (capabilities & IS_PLAYING)
{
fmt::append(out, "%sIS_PLAYING", count > 0 ? " | " : "");
count++;
}
if (capabilities & GET_NUM_ENQUEUED_SAMPLES)
{
fmt::append(out, "%sGET_NUM_ENQUEUED_SAMPLES", count > 0 ? " | " : "");
count++;
}
if (capabilities & SET_FREQUENCY_RATIO)
{
fmt::append(out, "%sSET_FREQUENCY_RATIO", count > 0 ? " | " : "");
count++;
}
if (count == 0)
{
fmt::append(out, "NONE");
static_cast<s16 *>(dst)[i] = static_cast<s16>(std::clamp(src[i] * 32768.5f, -32768.0f, 32767.0f));
}
}
+53 -71
View File
@@ -7,20 +7,37 @@ enum : u32
{
DEFAULT_AUDIO_SAMPLING_RATE = 48000,
MAX_AUDIO_BUFFERS = 64,
AUDIO_BUFFER_SAMPLES = 256
AUDIO_BUFFER_SAMPLES = 256,
AUDIO_MAX_CHANNELS = 8,
};
enum class AudioFreq : u32
{
FREQ_32K = 32000,
FREQ_44K = 44100,
FREQ_48K = 48000,
FREQ_88K = 88200,
FREQ_96K = 96000,
FREQ_176K = 176400,
FREQ_192K = 192000,
};
enum class AudioSampleSize : u32
{
FLOAT = sizeof(float),
S16 = sizeof(s16),
};
enum class AudioChannelCnt : u32
{
STEREO = 2,
SURROUND_5_1 = 6,
SURROUND_7_1 = 8,
};
class AudioBackend
{
public:
enum Capabilities : u32
{
PLAY_PAUSE_FLUSH = 0x1, // Implements Play, Pause, Flush
IS_PLAYING = 0x2, // Implements IsPlaying
GET_NUM_ENQUEUED_SAMPLES = 0x4, // Implements GetNumEnqueuedSamples
SET_FREQUENCY_RATIO = 0x8, // Implements SetFrequencyRatio
};
AudioBackend();
virtual ~AudioBackend() = default;
@@ -28,71 +45,37 @@ public:
/*
* Pure virtual methods
*/
virtual const char* GetName() const = 0;
virtual u32 GetCapabilities() const = 0;
virtual std::string_view GetName() const = 0;
virtual void Open(u32 num_buffers) = 0;
virtual void Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt) = 0;
virtual void Close() = 0;
virtual bool AddData(const void* src, u32 num_samples) = 0;
// Sets write callback. It's called when backend requests new data to be sent
// Callback should return number of submitted bytes. Calling other backend functions from callback is unsafe
virtual void SetWriteCallback(std::function<u32(u32 /* byte_cnt */, void * /* buffer */)> cb) = 0;
// Returns length of one callback frame in seconds.
virtual f64 GetCallbackFrameLen() = 0;
// Returns true if audio is currently being played, false otherwise
virtual bool IsPlaying() = 0;
// Start playing enqueued data
virtual void Play() = 0;
// Pause playing enqueued data
virtual void Pause() = 0;
/*
* This virtual method should be reimplemented if backend can fail to be initialized under non-error conditions
* eg. when there is no audio devices attached
*/
virtual bool Initialized() const { return true; }
virtual bool Initialized() { return true; }
/*
* Virtual methods - should be implemented depending on backend capabilities
* This virtual method should be reimplemented if backend can fail during normal operation
*/
// Start playing enqueued data
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
virtual void Play()
{
fmt::throw_exception("Play() not implemented");
}
// Pause playing enqueued data
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
virtual void Pause()
{
fmt::throw_exception("Pause() not implemented");
}
// Pause audio, and unqueue all currently queued buffers
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
virtual void Flush()
{
fmt::throw_exception("Flush() not implemented");
}
// Returns true if audio is currently being played, false otherwise
// Should be implemented if capabilities & IS_PLAYING
virtual bool IsPlaying()
{
fmt::throw_exception("IsPlaying() not implemented");
}
// Returns the number of currently enqueued samples
// Should be implemented if capabilities & GET_NUM_ENQUEUED_SAMPLES
virtual u64 GetNumEnqueuedSamples()
{
fmt::throw_exception("GetNumEnqueuedSamples() not implemented");
return 0;
}
// Sets a new frequency ratio. Backend is allowed to modify the ratio value, e.g. clamping it to the allowed range
// Returns the new frequency ratio set
// Should be implemented if capabilities & SET_FREQUENCY_RATIO
virtual f32 SetFrequencyRatio(f32 /* new_ratio */) // returns the new ratio
{
fmt::throw_exception("SetFrequencyRatio() not implemented");
return 1.0f;
}
virtual bool Operational() { return true; }
/*
* Helper methods
@@ -103,16 +86,15 @@ public:
u32 get_channels() const;
bool get_convert_to_u16() const;
bool get_convert_to_s16() const;
bool has_capability(u32 cap) const;
void dump_capabilities(std::string& out) const;
/*
* Convert float buffer to s16 one. src and dst could be the same. cnt is number of buffer elements.
*/
static void convert_to_s16(u32 cnt, const f32* src, void* dst);
protected:
bool m_convert_to_u16 = false;
u32 m_sample_size = sizeof(float);
u32 m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
u32 m_channels = 0;
u32 m_start_threshold = 1;
AudioSampleSize m_sample_size = AudioSampleSize::FLOAT;
AudioFreq m_sampling_rate = AudioFreq::FREQ_48K;
AudioChannelCnt m_channels = AudioChannelCnt::STEREO;
};
+17 -4
View File
@@ -4,11 +4,22 @@
#include "Utilities/date_time.h"
#include "Emu/System.h"
AudioDumper::AudioDumper(u16 ch)
: m_header(ch)
AudioDumper::AudioDumper()
{
if (GetCh())
}
AudioDumper::~AudioDumper()
{
Close();
}
void AudioDumper::Open(u16 ch, u32 sample_rate, u32 sample_size)
{
Close();
if (ch)
{
m_header = WAVHeader(ch, sample_rate, sample_size);
std::string path = fs::get_cache_dir() + "audio_";
if (const std::string id = Emu.GetTitleID(); !id.empty())
{
@@ -20,12 +31,14 @@ AudioDumper::AudioDumper(u16 ch)
}
}
AudioDumper::~AudioDumper()
void AudioDumper::Close()
{
if (GetCh())
{
m_output.seek(0);
m_output.write(m_header); // rewrite file header
m_output.close();
m_header.FMT.NumChannels = 0;
}
}
+13 -10
View File
@@ -30,19 +30,19 @@ struct WAVHeader
u32 SampleRate; // 48000
u32 ByteRate; // SampleRate * NumChannels * BitsPerSample/8
u16 BlockAlign; // NumChannels * BitsPerSample/8
u16 BitsPerSample; // sizeof(float) * 8
u16 BitsPerSample; // SampleSize * 8
FMTHeader() = default;
FMTHeader(u16 ch)
FMTHeader(u16 ch, u32 sample_rate, u32 sample_size)
: ID("fmt "_u32)
, Size(16)
, AudioFormat(3)
, AudioFormat(sample_size == sizeof(float) ? 3 : 1)
, NumChannels(ch)
, SampleRate(48000)
, ByteRate(SampleRate * ch * sizeof(float))
, BlockAlign(ch * sizeof(float))
, BitsPerSample(sizeof(float) * 8)
, SampleRate(sample_rate)
, ByteRate(SampleRate * ch * sample_size)
, BlockAlign(ch * sample_size)
, BitsPerSample(sample_size * 8)
{
}
} FMT;
@@ -52,9 +52,9 @@ struct WAVHeader
WAVHeader() = default;
WAVHeader(u16 ch)
WAVHeader(u16 ch, u32 sample_rate, u32 sample_size)
: RIFF(sizeof(RIFFHeader) + sizeof(FMTHeader))
, FMT(ch)
, FMT(ch, sample_rate, sample_size)
, ID("data"_u32)
, Size(0)
{
@@ -67,9 +67,12 @@ class AudioDumper
fs::file m_output{};
public:
AudioDumper(u16 ch);
AudioDumper();
~AudioDumper();
void Open(u16 ch, u32 sample_rate, u32 sample_size);
void Close();
void WriteData(const void* buffer, u32 size);
u16 GetCh() const { return m_header.FMT.NumChannels; }
};
+222
View File
@@ -0,0 +1,222 @@
#include "Emu/Audio/Cubeb/CubebBackend.h"
#include <algorithm>
#include "util/logs.hpp"
#ifdef _WIN32
#include <Windows.h>
#include <system_error>
#endif
LOG_CHANNEL(Cubeb);
CubebBackend::CubebBackend()
: AudioBackend()
{
#ifdef _WIN32
// Cubeb requires COM to be initialized on the thread calling cubeb_init on Windows
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
m_com_init_success = true;
}
#endif
if (int err = cubeb_init(&m_ctx, "RPCS3", nullptr))
{
Cubeb.error("cubeb_init() failed: 0x%08x", err);
m_ctx = nullptr;
return;
}
Cubeb.notice("Using backend %s", cubeb_get_backend_id(m_ctx));
}
CubebBackend::~CubebBackend()
{
Close();
if (m_ctx)
{
cubeb_destroy(m_ctx);
}
#ifdef _WIN32
if (m_com_init_success)
{
CoUninitialize();
}
#endif
}
bool CubebBackend::Initialized()
{
return m_ctx != nullptr;
}
bool CubebBackend::Operational()
{
return m_ctx != nullptr && m_stream != nullptr && !m_reset_req.observe();
}
void CubebBackend::Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt)
{
if (m_ctx == nullptr) return;
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
m_sampling_rate = freq;
m_sample_size = sample_size;
m_channels = ch_cnt;
full_sample_size = get_channels() * get_sample_size();
cubeb_stream_params stream_param{};
stream_param.format = get_convert_to_s16() ? CUBEB_SAMPLE_S16NE : CUBEB_SAMPLE_FLOAT32NE;
stream_param.rate = get_sampling_rate();
stream_param.channels = get_channels();
stream_param.layout = [&]()
{
switch (ch_cnt)
{
case AudioChannelCnt::STEREO: return CUBEB_LAYOUT_STEREO;
case AudioChannelCnt::SURROUND_5_1: return CUBEB_LAYOUT_3F2_LFE;
case AudioChannelCnt::SURROUND_7_1: return CUBEB_LAYOUT_3F4_LFE;
default:
ensure(false);
return CUBEB_LAYOUT_UNDEFINED;
}
}();
u32 min_latency{};
if (int err = cubeb_get_min_latency(m_ctx, &stream_param, &min_latency))
{
Cubeb.error("cubeb_get_min_latency() failed: 0x%08x", err);
}
const u32 stream_latency = std::max(static_cast<u32>(AUDIO_MIN_LATENCY * get_sampling_rate()), min_latency);
if (int err = cubeb_stream_init(m_ctx, &m_stream, "Main stream", nullptr, nullptr, nullptr, &stream_param, stream_latency, data_cb, state_cb, this))
{
m_stream = nullptr;
Cubeb.error("cubeb_stream_init() failed: 0x%08x", err);
}
if (m_stream == nullptr)
{
Cubeb.error("Failed to open audio backend. Make sure that no other application is running that might block audio access (e.g. Netflix).");
CloseUnlocked();
return;
}
if (int err = cubeb_stream_set_volume(m_stream, 1.0))
{
Cubeb.error("cubeb_stream_set_volume() failed: 0x%08x", err);
}
if (int err = cubeb_stream_start(m_stream))
{
Cubeb.error("cubeb_stream_start() failed: 0x%08x", err);
}
}
void CubebBackend::CloseUnlocked()
{
if (m_stream == nullptr) return;
if (int err = cubeb_stream_stop(m_stream))
{
Cubeb.error("cubeb_stream_stop() failed: 0x%08x", err);
}
cubeb_stream_destroy(m_stream);
m_playing = false;
m_stream = nullptr;
m_last_sample.fill(0);
}
void CubebBackend::Close()
{
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
}
void CubebBackend::Play()
{
if (m_playing) return;
std::lock_guard lock(m_cb_mutex);
m_playing = true;
}
void CubebBackend::Pause()
{
std::lock_guard lock(m_cb_mutex);
m_playing = false;
m_last_sample.fill(0);
}
bool CubebBackend::IsPlaying()
{
return m_playing;
}
void CubebBackend::SetWriteCallback(std::function<u32(u32, void *)> cb)
{
std::lock_guard lock(m_cb_mutex);
m_write_callback = cb;
}
f64 CubebBackend::GetCallbackFrameLen()
{
u32 stream_latency{};
if (int err = cubeb_stream_get_latency(m_stream, &stream_latency))
{
Cubeb.error("cubeb_stream_get_latency() failed: 0x%08x", err);
}
return std::max<f64>(AUDIO_MIN_LATENCY, static_cast<f64>(stream_latency) / get_sampling_rate());
}
long CubebBackend::data_cb(cubeb_stream* /* stream */, void* user_ptr, void const* /* input_buffer */, void* output_buffer, long nframes)
{
CubebBackend* const cubeb = static_cast<CubebBackend*>(user_ptr);
std::unique_lock lock(cubeb->m_cb_mutex, std::defer_lock);
if (nframes && lock.try_lock() && cubeb->m_write_callback && cubeb->m_playing)
{
const u32 sample_size = cubeb->full_sample_size.observe();
const u32 bytes_req = nframes * sample_size;
u32 written = std::min(cubeb->m_write_callback(bytes_req, output_buffer), bytes_req);
written -= written % sample_size;
if (written >= sample_size)
{
memcpy(cubeb->m_last_sample.data(), static_cast<u8*>(output_buffer) + written - sample_size, sample_size);
}
for (u32 i = written; i < bytes_req; i += sample_size)
{
memcpy(static_cast<u8*>(output_buffer) + i, cubeb->m_last_sample.data(), sample_size);
}
}
else
{
// Stream parameters are modified only after stream_destroy. stream_destroy will return
// only after this callback returns, so it's safe to access full_sample_size here.
memset(output_buffer, 0, nframes * cubeb->full_sample_size.observe());
}
return nframes;
}
void CubebBackend::state_cb(cubeb_stream* /* stream */, void* user_ptr, cubeb_state state)
{
CubebBackend* const cubeb = static_cast<CubebBackend*>(user_ptr);
if (state == CUBEB_STATE_ERROR)
{
Cubeb.error("Stream entered error state");
cubeb->m_reset_req = true;
}
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include <memory>
#include "Utilities/mutex.h"
#include "util/atomic.hpp"
#include "Emu/Audio/AudioBackend.h"
#include "cubeb/cubeb.h"
class CubebBackend final : public AudioBackend
{
public:
CubebBackend();
~CubebBackend() override;
CubebBackend(const CubebBackend&) = delete;
CubebBackend& operator=(const CubebBackend&) = delete;
std::string_view GetName() const override { return "Cubeb"sv; }
bool Initialized() override;
bool Operational() override;
void Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt) override;
void Close() override;
void SetWriteCallback(std::function<u32(u32, void *)> cb) override;
f64 GetCallbackFrameLen() override;
void Play() override;
void Pause() override;
bool IsPlaying() override;
private:
static constexpr f64 AUDIO_MIN_LATENCY = 512.0 / 48000; // 10ms
cubeb* m_ctx = nullptr;
cubeb_stream* m_stream = nullptr;
#ifdef _WIN32
bool m_com_init_success = false;
#endif
shared_mutex m_cb_mutex{};
std::function<u32(u32, void *)> m_write_callback{};
std::array<u8, sizeof(float) * static_cast<u32>(AudioChannelCnt::SURROUND_7_1)> m_last_sample{};
atomic_t<u8> full_sample_size = 0;
bool m_playing = false;
atomic_t<bool> m_reset_req = false;
// Cubeb callbacks
static long data_cb(cubeb_stream* stream, void* user_ptr, void const* input_buffer, void* output_buffer, long nframes);
static void state_cb(cubeb_stream* stream, void* user_ptr, cubeb_state state);
void CloseUnlocked();
};
+174 -85
View File
@@ -12,28 +12,41 @@ LOG_CHANNEL(FAudio_, "FAudio");
FAudioBackend::FAudioBackend()
: AudioBackend()
{
u32 res = FAudioCreate(&m_instance, 0, FAUDIO_DEFAULT_PROCESSOR);
FAudio *instance;
u32 res = FAudioCreate(&instance, 0, FAUDIO_DEFAULT_PROCESSOR);
if (res)
{
FAudio_.fatal("FAudioCreate() failed(0x%08x)", res);
FAudio_.error("FAudioCreate() failed(0x%08x)", res);
return;
}
res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, m_channels, 48000, 0, 0, nullptr);
res = FAudio_CreateMasteringVoice(instance, &m_master_voice, FAUDIO_DEFAULT_CHANNELS, FAUDIO_DEFAULT_SAMPLERATE, 0, 0, nullptr);
if (res)
{
FAudio_.fatal("FAudio_CreateMasteringVoice() failed(0x%08x)", res);
FAudio_.error("FAudio_CreateMasteringVoice() failed(0x%08x)", res);
FAudio_StopEngine(instance);
return;
}
OnProcessingPassStart = nullptr;
OnProcessingPassEnd = nullptr;
OnCriticalError = OnCriticalError_func;
res = FAudio_RegisterForCallbacks(instance, this);
if (res)
{
// Some error recovery functionality will be lost, but otherwise backend is operational
FAudio_.error("FAudio_RegisterForCallbacks() failed(0x%08x)", res);
}
// All succeeded, "commit"
m_instance = instance;
}
FAudioBackend::~FAudioBackend()
{
if (m_source_voice != nullptr)
{
FAudioSourceVoice_Stop(m_source_voice, 0, FAUDIO_COMMIT_NOW);
FAudioVoice_DestroyVoice(m_source_voice);
}
Close();
if (m_master_voice != nullptr)
{
@@ -49,127 +62,203 @@ FAudioBackend::~FAudioBackend()
void FAudioBackend::Play()
{
AUDIT(m_source_voice != nullptr);
if (m_source_voice == nullptr)
{
FAudio_.error("Play() called uninitialized");
return;
}
if (m_playing) return;
const u32 res = FAudioSourceVoice_Start(m_source_voice, 0, FAUDIO_COMMIT_NOW);
if (res)
{
FAudio_.fatal("FAudioSourceVoice_Start() failed(0x%08x)", res);
FAudio_.error("FAudioSourceVoice_Start() failed(0x%08x)", res);
}
std::lock_guard lock(m_cb_mutex);
m_playing = true;
}
void FAudioBackend::Pause()
{
AUDIT(m_source_voice != nullptr);
if (m_source_voice)
{
u32 res = FAudioSourceVoice_Stop(m_source_voice, 0, FAUDIO_COMMIT_NOW);
if (res)
{
FAudio_.error("FAudioSourceVoice_Stop() failed(0x%08x)", res);
}
if (res = FAudioSourceVoice_FlushSourceBuffers(m_source_voice))
{
FAudio_.error("FAudioSourceVoice_FlushSourceBuffers() failed(0x%08x)", res);
}
}
else
{
FAudio_.error("Pause() called uninitialized");
}
std::lock_guard lock(m_cb_mutex);
m_playing = false;
m_last_sample.fill(0);
}
void FAudioBackend::CloseUnlocked()
{
if (m_source_voice == nullptr) return;
const u32 res = FAudioSourceVoice_Stop(m_source_voice, 0, FAUDIO_COMMIT_NOW);
if (res)
{
FAudio_.fatal("FAudioSourceVoice_Stop() failed(0x%08x)", res);
FAudio_.error("FAudioSourceVoice_Stop() failed(0x%08x)", res);
}
}
void FAudioBackend::Flush()
{
AUDIT(m_source_voice != nullptr);
const u32 res = FAudioSourceVoice_FlushSourceBuffers(m_source_voice);
if (res)
{
FAudio_.fatal("FAudioSourceVoice_FlushSourceBuffers() failed(0x%08x)", res);
}
}
bool FAudioBackend::IsPlaying()
{
AUDIT(m_source_voice != nullptr);
FAudioVoiceState state;
FAudioSourceVoice_GetState(m_source_voice, &state, FAUDIO_VOICE_NOSAMPLESPLAYED);
return state.BuffersQueued > 0 || state.pCurrentBufferContext != nullptr;
FAudioVoice_DestroyVoice(m_source_voice);
m_playing = false;
m_source_voice = nullptr;
m_data_buf = nullptr;
m_data_buf_len = 0;
m_last_sample.fill(0);
}
void FAudioBackend::Close()
{
Pause();
Flush();
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
}
void FAudioBackend::Open(u32 /* num_buffers */)
bool FAudioBackend::Initialized()
{
return m_instance != nullptr;
}
bool FAudioBackend::Operational()
{
return m_instance != nullptr && m_source_voice != nullptr && !m_reset_req.observe();
}
void FAudioBackend::Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt)
{
if (m_instance == nullptr) return;
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
m_sampling_rate = freq;
m_sample_size = sample_size;
m_channels = ch_cnt;
FAudioWaveFormatEx waveformatex;
waveformatex.wFormatTag = m_convert_to_u16 ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<u32>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
waveformatex.wFormatTag = get_convert_to_s16() ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = get_channels();
waveformatex.nSamplesPerSec = get_sampling_rate();
waveformatex.nAvgBytesPerSec = static_cast<u32>(get_sampling_rate() * get_channels() * get_sample_size());
waveformatex.nBlockAlign = get_channels() * get_sample_size();
waveformatex.wBitsPerSample = get_sample_size() * 8;
waveformatex.cbSize = 0;
const u32 res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex, 0, FAUDIO_DEFAULT_FREQ_RATIO, nullptr, nullptr, nullptr);
OnVoiceProcessingPassStart = OnVoiceProcessingPassStart_func;
OnVoiceProcessingPassEnd = nullptr;
OnStreamEnd = nullptr;
OnBufferStart = nullptr;
OnBufferEnd = nullptr;
OnLoopEnd = nullptr;
OnVoiceError = nullptr;
const u32 res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex, 0, FAUDIO_DEFAULT_FREQ_RATIO, this, nullptr, nullptr);
if (res)
{
FAudio_.fatal("FAudio_CreateSourceVoice() failed(0x%08x)", res);
FAudio_.error("FAudio_CreateSourceVoice() failed(0x%08x)", res);
}
if (m_source_voice == nullptr)
{
FAudio_.fatal("Failed to open audio backend. Make sure that no other application is running that might block audio access (e.g. Netflix).");
return;
}
AUDIT(m_source_voice != nullptr);
FAudioVoice_SetVolume(m_source_voice, 1.0f, FAUDIO_COMMIT_NOW);
m_data_buf_len = get_sampling_rate() * get_sample_size() * get_channels() * INTERNAL_BUF_SIZE_MS * static_cast<u32>(FAUDIO_DEFAULT_FREQ_RATIO) / 1000;
m_data_buf = std::make_unique<u8[]>(m_data_buf_len);
}
bool FAudioBackend::AddData(const void* src, u32 num_samples)
bool FAudioBackend::IsPlaying()
{
AUDIT(m_source_voice != nullptr);
return m_playing;
}
FAudioVoiceState state;
FAudioSourceVoice_GetState(m_source_voice, &state, FAUDIO_VOICE_NOSAMPLESPLAYED);
void FAudioBackend::SetWriteCallback(std::function<u32(u32, void *)> cb)
{
std::lock_guard lock(m_cb_mutex);
m_write_callback = cb;
}
if (state.BuffersQueued >= MAX_AUDIO_BUFFERS)
f64 FAudioBackend::GetCallbackFrameLen()
{
constexpr f64 _10ms = 0.01;
if (m_instance == nullptr)
{
FAudio_.warning("Too many buffers enqueued (%d)", state.BuffersQueued);
return false;
FAudio_.error("GetCallbackFrameLen() called uninitialized");
return _10ms;
}
FAudioBuffer buffer;
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = FAUDIO_NO_LOOP_REGION;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pAudioData = static_cast<const u8*>(src);
buffer.pContext = nullptr;
buffer.PlayBegin = 0;
buffer.PlayLength = AUDIO_BUFFER_SAMPLES;
f64 min_latency{};
const u32 res = FAudioSourceVoice_SubmitSourceBuffer(m_source_voice, &buffer, nullptr);
if (res)
u32 samples_per_q = 0, freq = 0;
FAudio_GetProcessingQuantum(m_instance, &samples_per_q, &freq);
if (freq)
{
FAudio_.fatal("FAudioSourceVoice_SubmitSourceBuffer() failed(0x%08x)", res);
return false;
min_latency = static_cast<f64>(samples_per_q) / freq;
}
return true;
return std::max<f64>(min_latency, _10ms);
}
u64 FAudioBackend::GetNumEnqueuedSamples()
void FAudioBackend::OnVoiceProcessingPassStart_func(FAudioVoiceCallback *cb_obj, u32 BytesRequired)
{
FAudioVoiceState state;
FAudioSourceVoice_GetState(m_source_voice, &state, 0);
FAudioBackend *faudio = static_cast<FAudioBackend *>(cb_obj);
// all buffers contain AUDIO_BUFFER_SAMPLES, so we can easily calculate how many samples there are remaining
return (AUDIO_BUFFER_SAMPLES - state.SamplesPlayed % AUDIO_BUFFER_SAMPLES) + (state.BuffersQueued * AUDIO_BUFFER_SAMPLES);
}
f32 FAudioBackend::SetFrequencyRatio(f32 new_ratio)
{
new_ratio = std::clamp(new_ratio, FAUDIO_MIN_FREQ_RATIO, FAUDIO_DEFAULT_FREQ_RATIO);
const u32 res = FAudioSourceVoice_SetFrequencyRatio(m_source_voice, new_ratio, FAUDIO_COMMIT_NOW);
if (res)
std::unique_lock lock(faudio->m_cb_mutex, std::defer_lock);
if (BytesRequired && lock.try_lock() && faudio->m_write_callback && faudio->m_playing)
{
FAudio_.fatal("FAudioSourceVoice_SetFrequencyRatio() failed(0x%08x)", res);
return 1.0f;
}
ensure(BytesRequired <= faudio->m_data_buf_len, "FAudio internal buffer is too small. Report to developers!");
return new_ratio;
const u32 sample_size = faudio->get_sample_size() * faudio->get_channels();
u32 written = std::min(faudio->m_write_callback(BytesRequired, faudio->m_data_buf.get()), BytesRequired);
written -= written % sample_size;
if (written >= sample_size)
{
memcpy(faudio->m_last_sample.data(), faudio->m_data_buf.get() + written - sample_size, sample_size);
}
for (u32 i = written; i < BytesRequired; i += sample_size)
{
memcpy(faudio->m_data_buf.get() + i, faudio->m_last_sample.data(), sample_size);
}
FAudioBuffer buffer{};
buffer.AudioBytes = BytesRequired;
buffer.LoopBegin = FAUDIO_NO_LOOP_REGION;
buffer.pAudioData = static_cast<const u8*>(faudio->m_data_buf.get());
const u32 res = FAudioSourceVoice_SubmitSourceBuffer(faudio->m_source_voice, &buffer, nullptr);
if (res)
{
FAudio_.error("FAudioSourceVoice_SubmitSourceBuffer() failed(0x%08x)", res);
}
}
}
void FAudioBackend::OnCriticalError_func(FAudioEngineCallback *cb_obj, u32 Error)
{
FAudio_.error("OnCriticalError() failed(0x%08x)", Error);
FAudioBackend *faudio = static_cast<FAudioBackend *>(cb_obj);
faudio->m_reset_req = true;
}
+33 -20
View File
@@ -4,16 +4,14 @@
#error "FAudio support disabled but still being built."
#endif
#include <memory>
#include "Utilities/mutex.h"
#include "Emu/Audio/AudioBackend.h"
#include "FAudio.h"
class FAudioBackend : public AudioBackend
class FAudioBackend : public AudioBackend, public FAudioVoiceCallback, public FAudioEngineCallback
{
private:
FAudio* m_instance{};
FAudioMasteringVoice* m_master_voice{};
FAudioSourceVoice* m_source_voice{};
public:
FAudioBackend();
~FAudioBackend() override;
@@ -21,27 +19,42 @@ public:
FAudioBackend(const FAudioBackend&) = delete;
FAudioBackend& operator=(const FAudioBackend&) = delete;
const char* GetName() const override
{
return "FAudio";
}
std::string_view GetName() const override { return "FAudio"sv; }
static const u32 capabilities = PLAY_PAUSE_FLUSH | IS_PLAYING | GET_NUM_ENQUEUED_SAMPLES | SET_FREQUENCY_RATIO;
u32 GetCapabilities() const override
{
return capabilities;
}
bool Initialized() override;
bool Operational() override;
void Open(u32 /* num_buffers */) override;
void Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt) override;
void Close() override;
void SetWriteCallback(std::function<u32(u32, void *)> cb) override;
f64 GetCallbackFrameLen() override;
void Play() override;
void Pause() override;
bool IsPlaying() override;
bool AddData(const void* src, u32 num_samples) override;
void Flush() override;
private:
static constexpr u32 INTERNAL_BUF_SIZE_MS = 25;
u64 GetNumEnqueuedSamples() override;
f32 SetFrequencyRatio(f32 new_ratio) override;
FAudio* m_instance{};
FAudioMasteringVoice* m_master_voice{};
FAudioSourceVoice* m_source_voice{};
shared_mutex m_cb_mutex{};
std::function<u32(u32, void *)> m_write_callback{};
std::unique_ptr<u8[]> m_data_buf{};
u64 m_data_buf_len = 0;
std::array<u8, sizeof(float) * static_cast<u32>(AudioChannelCnt::SURROUND_7_1)> m_last_sample{};
bool m_playing = false;
atomic_t<bool> m_reset_req = false;
// FAudio voice callbacks
static void OnVoiceProcessingPassStart_func(FAudioVoiceCallback *cb_obj, u32 BytesRequired);
// FAudio engine callbacks
static void OnCriticalError_func(FAudioEngineCallback *cb_obj, u32 Error);
void CloseUnlocked();
};
+11 -10
View File
@@ -6,19 +6,20 @@ class NullAudioBackend : public AudioBackend
{
public:
NullAudioBackend() {}
virtual ~NullAudioBackend() {}
~NullAudioBackend() {}
virtual const char* GetName() const override { return "Null"; }
std::string_view GetName() const override { return "Null"sv; }
static const u32 capabilities = PLAY_PAUSE_FLUSH;
virtual u32 GetCapabilities() const override { return capabilities; }
void Open(AudioFreq /* freq */, AudioSampleSize /* sample_size */, AudioChannelCnt /* ch_cnt */) override { m_playing = false; }
void Close() override { m_playing = false; }
virtual void Open(u32) override {}
virtual void Close() override {}
void SetWriteCallback(std::function<u32(u32, void *)> /* cb */) override {};
f64 GetCallbackFrameLen() override { return 0.01; };
virtual void Play() override {}
virtual void Pause() override {}
void Play() override { m_playing = true; }
void Pause() override { m_playing = false; }
bool IsPlaying() override { return m_playing; }
virtual bool AddData(const void*, u32) override { return true; }
virtual void Flush() override {}
private:
bool m_playing = false;
};
-88
View File
@@ -1,88 +0,0 @@
#ifndef HAVE_PULSE
#error "PulseAudio support disabled but still being built."
#endif
#include "Emu/System.h"
#include "PulseBackend.h"
#include <pulse/simple.h>
#include <pulse/error.h>
PulseBackend::PulseBackend()
: AudioBackend()
{
}
PulseBackend::~PulseBackend()
{
this->Close();
}
void PulseBackend::Close()
{
if (this->connection)
{
pa_simple_free(this->connection);
this->connection = nullptr;
}
}
void PulseBackend::Open(u32 /* num_buffers */)
{
pa_sample_spec ss;
ss.format = (m_sample_size == 2) ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.rate = m_sampling_rate;
pa_channel_map channel_map;
if (m_channels == 2)
{
channel_map.channels = 2;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
}
else if (m_channels == 6)
{
channel_map.channels = 6;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
channel_map.map[3] = PA_CHANNEL_POSITION_LFE;
channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
}
else
{
channel_map.channels = 8;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
channel_map.map[3] = PA_CHANNEL_POSITION_LFE;
channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
channel_map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
channel_map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
}
ss.channels = channel_map.channels;
int err;
this->connection = pa_simple_new(NULL, "RPCS3", PA_STREAM_PLAYBACK, NULL, "Game", &ss, &channel_map, NULL, &err);
if (!this->connection)
{
fprintf(stderr, "PulseAudio: Failed to initialize audio: %s\n", pa_strerror(err));
}
}
bool PulseBackend::AddData(const void* src, u32 num_samples)
{
AUDIT(this->connection);
int err;
if (pa_simple_write(this->connection, src, num_samples * m_sample_size, &err) < 0)
{
fprintf(stderr, "PulseAudio: Failed to write audio stream: %s\n", pa_strerror(err));
return false;
}
return true;
}
-31
View File
@@ -1,31 +0,0 @@
#pragma once
#ifndef HAVE_PULSE
#error "PulseAudio support disabled but still being built."
#endif
#include <pulse/simple.h>
#include "Emu/Audio/AudioBackend.h"
class PulseBackend : public AudioBackend
{
public:
PulseBackend();
virtual ~PulseBackend() override;
PulseBackend(const PulseBackend&) = delete;
PulseBackend& operator=(const PulseBackend&) = delete;
virtual const char* GetName() const override { return "Pulse"; }
static const u32 capabilities = 0;
virtual u32 GetCapabilities() const override { return capabilities; }
virtual void Open(u32) override;
virtual void Close() override;
virtual bool AddData(const void* src, u32 num_samples) override;
private:
pa_simple* connection{};
};
+194 -100
View File
@@ -22,24 +22,24 @@ XAudio2Backend::XAudio2Backend()
// In order to prevent errors on CreateMasteringVoice, apparently we need CoInitializeEx according to:
// https://docs.microsoft.com/en-us/windows/win32/api/xaudio2fx/nf-xaudio2fx-xaudio2createvolumemeter
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr) && hr != RPC_E_CHANGED_MODE)
if (SUCCEEDED(hr))
{
XAudio.error("CoInitializeEx() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
m_com_init_success = true;
}
hr = XAudio2Create(instance.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR);
hr = XAudio2Create(instance.GetAddressOf(), 0, XAUDIO2_USE_DEFAULT_PROCESSOR);
if (FAILED(hr))
{
XAudio.error("XAudio2Create() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
}
hr = instance->CreateMasteringVoice(&m_master_voice, m_channels, 48000);
hr = instance->RegisterForCallbacks(this);
if (FAILED(hr))
{
XAudio.error("CreateMasteringVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
// Some error recovery functionality will be lost, but otherwise backend is operational
XAudio.error("RegisterForCallbacks() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
// All succeeded, "commit"
@@ -47,150 +47,244 @@ XAudio2Backend::XAudio2Backend()
}
XAudio2Backend::~XAudio2Backend()
{
Close();
if (m_xaudio2_instance != nullptr)
{
m_xaudio2_instance->StopEngine();
// TODO: Enabling this might crash afterwards in ComPtr::InternalRelease.
// Maybe it's both trying to do the same thing?
//m_xaudio2_instance->Release();
}
if (m_com_init_success)
{
CoUninitialize();
}
}
bool XAudio2Backend::Initialized()
{
return m_xaudio2_instance != nullptr;
}
bool XAudio2Backend::Operational()
{
if (m_dev_listener.output_device_changed())
{
m_reset_req = true;
}
return m_xaudio2_instance != nullptr && m_source_voice != nullptr && !m_reset_req.observe();
}
void XAudio2Backend::Play()
{
if (m_source_voice == nullptr)
{
XAudio.error("Play() called uninitialized");
return;
}
if (m_playing) return;
const HRESULT hr = m_source_voice->Start();
if (FAILED(hr))
{
XAudio.error("Start() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
}
std::lock_guard lock(m_cb_mutex);
m_playing = true;
}
void XAudio2Backend::CloseUnlocked()
{
if (m_source_voice != nullptr)
{
m_source_voice->Stop();
const HRESULT hr = m_source_voice->Stop();
if (FAILED(hr))
{
XAudio.error("Stop() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
m_source_voice->DestroyVoice();
m_source_voice = nullptr;
}
if (m_master_voice != nullptr)
{
m_master_voice->DestroyVoice();
m_master_voice = nullptr;
}
if (m_xaudio2_instance != nullptr)
{
m_xaudio2_instance->StopEngine();
}
}
void XAudio2Backend::Play()
{
AUDIT(m_source_voice != nullptr);
const HRESULT hr = m_source_voice->Start();
if (FAILED(hr))
{
XAudio.fatal("Start() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
m_playing = false;
m_data_buf = nullptr;
m_data_buf_len = 0;
m_last_sample.fill(0);
}
void XAudio2Backend::Close()
{
Pause();
Flush();
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
}
void XAudio2Backend::Pause()
{
AUDIT(m_source_voice != nullptr);
const HRESULT hr = m_source_voice->Stop();
if (FAILED(hr))
if (m_source_voice)
{
XAudio.fatal("Stop() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
HRESULT hr = m_source_voice->Stop();
if (FAILED(hr))
{
XAudio.error("Stop() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
hr = m_source_voice->FlushSourceBuffers();
if (FAILED(hr))
{
XAudio.error("FlushSourceBuffers() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
}
else
{
XAudio.error("Pause() called uninitialized");
}
std::lock_guard lock(m_cb_mutex);
m_playing = false;
m_last_sample.fill(0);
}
void XAudio2Backend::Open(u32 /* num_buffers */)
void XAudio2Backend::Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt)
{
WAVEFORMATEX waveformatex{};
waveformatex.wFormatTag = m_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
std::lock_guard lock(m_cb_mutex);
CloseUnlocked();
const HRESULT hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (FAILED(hr))
if (m_xaudio2_instance == nullptr)
{
XAudio.fatal("CreateSourceVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
XAudio.error("Open() called unitiliazed");
return;
}
AUDIT(m_source_voice != nullptr);
HRESULT hr = m_xaudio2_instance->CreateMasteringVoice(&m_master_voice);
if (FAILED(hr))
{
XAudio.error("CreateMasteringVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
XAudio.error("Failed to open audio backend. Make sure that no other application is running that might block audio access (e.g. Netflix).");
m_reset_req = true;
return;
}
m_sampling_rate = freq;
m_sample_size = sample_size;
m_channels = ch_cnt;
WAVEFORMATEX waveformatex{};
waveformatex.wFormatTag = get_convert_to_s16() ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = get_channels();
waveformatex.nSamplesPerSec = get_sampling_rate();
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(get_sampling_rate() * get_channels() * get_sample_size());
waveformatex.nBlockAlign = get_channels() * get_sample_size();
waveformatex.wBitsPerSample = get_sample_size() * 8;
waveformatex.cbSize = 0;
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO, this);
if (FAILED(hr))
{
XAudio.error("CreateSourceVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return;
}
ensure(m_source_voice != nullptr);
m_source_voice->SetVolume(1.0f);
m_data_buf_len = get_sampling_rate() * get_sample_size() * get_channels() * INTERNAL_BUF_SIZE_MS * static_cast<u32>(XAUDIO2_DEFAULT_FREQ_RATIO) / 1000;
m_data_buf = std::make_unique<u8[]>(m_data_buf_len);
}
bool XAudio2Backend::IsPlaying()
{
AUDIT(m_source_voice != nullptr);
XAUDIO2_VOICE_STATE state;
m_source_voice->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
return state.BuffersQueued > 0 || state.pCurrentBufferContext != nullptr;
return m_playing;
}
bool XAudio2Backend::AddData(const void* src, u32 num_samples)
void XAudio2Backend::SetWriteCallback(std::function<u32(u32, void *)> cb)
{
AUDIT(m_source_voice != nullptr);
std::lock_guard lock(m_cb_mutex);
m_write_callback = cb;
}
XAUDIO2_VOICE_STATE state;
m_source_voice->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
f64 XAudio2Backend::GetCallbackFrameLen()
{
constexpr f64 _10ms = 0.01;
if (state.BuffersQueued >= MAX_AUDIO_BUFFERS)
if (m_source_voice == nullptr)
{
XAudio.warning("Too many buffers enqueued (%d)", state.BuffersQueued);
return false;
XAudio.error("GetCallbackFrameLen() called uninitialized");
return _10ms;
}
XAUDIO2_BUFFER buffer{};
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pAudioData = static_cast<const BYTE*>(src);
buffer.pContext = nullptr;
buffer.PlayBegin = 0;
buffer.PlayLength = AUDIO_BUFFER_SAMPLES;
void *ext;
f64 min_latency{};
const HRESULT hr = m_source_voice->SubmitSourceBuffer(&buffer);
HRESULT hr = m_xaudio2_instance->QueryInterface(IID_IXAudio2Extension, &ext);
if (FAILED(hr))
{
XAudio.fatal("AddData() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return false;
XAudio.error("QueryInterface() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
return true;
}
void XAudio2Backend::Flush()
{
AUDIT(m_source_voice != nullptr);
const HRESULT hr = m_source_voice->FlushSourceBuffers();
if (FAILED(hr))
else
{
XAudio.fatal("FlushSourceBuffers() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
u32 samples_per_q = 0, freq = 0;
static_cast<IXAudio2Extension *>(ext)->GetProcessingQuantum(&samples_per_q, &freq);
if (freq)
{
min_latency = static_cast<f64>(samples_per_q) / freq;
}
}
return std::max<f64>(min_latency, _10ms); // 10ms is the minimum for XAudio
}
u64 XAudio2Backend::GetNumEnqueuedSamples()
void XAudio2Backend::OnVoiceProcessingPassStart(UINT32 BytesRequired)
{
AUDIT(m_source_voice != nullptr);
XAUDIO2_VOICE_STATE state;
m_source_voice->GetState(&state);
// all buffers contain AUDIO_BUFFER_SAMPLES, so we can easily calculate how many samples there are remaining
return static_cast<u64>(AUDIO_BUFFER_SAMPLES - state.SamplesPlayed % AUDIO_BUFFER_SAMPLES) + (state.BuffersQueued * AUDIO_BUFFER_SAMPLES);
}
f32 XAudio2Backend::SetFrequencyRatio(f32 new_ratio)
{
new_ratio = std::clamp(new_ratio, XAUDIO2_MIN_FREQ_RATIO, XAUDIO2_DEFAULT_FREQ_RATIO);
const HRESULT hr = m_source_voice->SetFrequencyRatio(new_ratio);
if (FAILED(hr))
std::unique_lock lock(m_cb_mutex, std::defer_lock);
if (BytesRequired && lock.try_lock() && m_write_callback && m_playing)
{
XAudio.fatal("SetFrequencyRatio() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
return 1.0f;
}
ensure(BytesRequired <= m_data_buf_len, "XAudio internal buffer is too small. Report to developers!");
return new_ratio;
const u32 sample_size = get_sample_size() * get_channels();
u32 written = std::min(m_write_callback(BytesRequired, m_data_buf.get()), BytesRequired);
written -= written % sample_size;
if (written >= sample_size)
{
memcpy(m_last_sample.data(), m_data_buf.get() + written - sample_size, sample_size);
}
for (u32 i = written; i < BytesRequired; i += sample_size)
{
memcpy(m_data_buf.get() + i, m_last_sample.data(), sample_size);
}
XAUDIO2_BUFFER buffer{};
buffer.AudioBytes = BytesRequired;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.pAudioData = static_cast<const BYTE*>(m_data_buf.get());
const HRESULT hr = m_source_voice->SubmitSourceBuffer(&buffer);
if (FAILED(hr))
{
XAudio.error("SubmitSourceBuffer() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
}
}
void XAudio2Backend::OnCriticalError(HRESULT Error)
{
XAudio.error("OnCriticalError() called: %s (0x%08x)", std::system_category().message(Error), static_cast<u32>(Error));
m_reset_req = true;
}
+44 -17
View File
@@ -4,19 +4,16 @@
#error "XAudio2 can only be built on Windows."
#endif
#include <memory>
#include "Utilities/mutex.h"
#include "Emu/Audio/AudioBackend.h"
#include "Emu/Audio/audio_device_listener.h"
#include <xaudio2redist.h>
#include <wrl/client.h>
class XAudio2Backend final : public AudioBackend
class XAudio2Backend final : public AudioBackend, public IXAudio2VoiceCallback, public IXAudio2EngineCallback
{
private:
Microsoft::WRL::ComPtr<IXAudio2> m_xaudio2_instance{};
IXAudio2MasteringVoice* m_master_voice{};
IXAudio2SourceVoice* m_source_voice{};
public:
XAudio2Backend();
~XAudio2Backend() override;
@@ -24,23 +21,53 @@ public:
XAudio2Backend(const XAudio2Backend&) = delete;
XAudio2Backend& operator=(const XAudio2Backend&) = delete;
const char* GetName() const override { return "XAudio2"; }
std::string_view GetName() const override { return "XAudio2"sv; }
static const u32 capabilities = PLAY_PAUSE_FLUSH | IS_PLAYING | GET_NUM_ENQUEUED_SAMPLES | SET_FREQUENCY_RATIO;
u32 GetCapabilities() const override { return capabilities; }
bool Initialized() override;
bool Operational() override;
bool Initialized() const override { return m_xaudio2_instance != nullptr; }
void Open(u32 /* num_buffers */) override;
void Open(AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt) override;
void Close() override;
void SetWriteCallback(std::function<u32(u32, void *)> cb) override;
f64 GetCallbackFrameLen() override;
void Play() override;
void Pause() override;
bool IsPlaying() override;
bool AddData(const void* src, u32 num_samples) override;
void Flush() override;
private:
static constexpr u32 INTERNAL_BUF_SIZE_MS = 25;
u64 GetNumEnqueuedSamples() override;
f32 SetFrequencyRatio(f32 new_ratio) override;
Microsoft::WRL::ComPtr<IXAudio2> m_xaudio2_instance{};
IXAudio2MasteringVoice* m_master_voice{};
IXAudio2SourceVoice* m_source_voice{};
bool m_com_init_success = false;
shared_mutex m_cb_mutex{};
std::function<u32(u32, void *)> m_write_callback{};
std::unique_ptr<u8[]> m_data_buf{};
u64 m_data_buf_len = 0;
std::array<u8, sizeof(float) * static_cast<u32>(AudioChannelCnt::SURROUND_7_1)> m_last_sample{};
bool m_playing = false;
atomic_t<bool> m_reset_req = false;
audio_device_listener m_dev_listener{};
// XAudio voice callbacks
void OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
void OnVoiceProcessingPassEnd() override {}
void OnStreamEnd() override {}
void OnBufferStart(void* /* pBufferContext */) override {}
void OnBufferEnd(void* /* pBufferContext*/) override {}
void OnLoopEnd(void* /* pBufferContext */) override {}
void OnVoiceError(void* /* pBufferContext */, HRESULT /* Error */) override {}
// XAudio engine callbacks
void OnProcessingPassStart() override {};
void OnProcessingPassEnd() override {};
void OnCriticalError(HRESULT Error) override;
void CloseUnlocked();
};
+52 -12
View File
@@ -10,15 +10,26 @@ LOG_CHANNEL(IO);
audio_device_listener::audio_device_listener()
{
#ifdef _WIN32
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
m_com_init_success = true;
}
// Try to register a listener for device changes
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_device_enumerator));
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_device_enumerator));
if (hr != S_OK)
{
IO.error("CoCreateInstance() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
}
else if (m_device_enumerator)
{
m_device_enumerator->RegisterEndpointNotificationCallback(&m_listener);
hr = m_device_enumerator->RegisterEndpointNotificationCallback(this);
if (FAILED(hr))
{
IO.error("RegisterEndpointNotificationCallback() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
m_device_enumerator->Release();
}
}
else
{
@@ -32,11 +43,27 @@ audio_device_listener::~audio_device_listener()
#ifdef _WIN32
if (m_device_enumerator != nullptr)
{
m_device_enumerator->UnregisterEndpointNotificationCallback(this);
m_device_enumerator->Release();
}
if (m_com_init_success)
{
CoUninitialize();
}
#endif
}
bool audio_device_listener::input_device_changed()
{
return m_input_device_changed.test_and_reset();
}
bool audio_device_listener::output_device_changed()
{
return m_output_device_changed.test_and_reset();
}
#ifdef _WIN32
template <>
void fmt_class_string<ERole>::format(std::string& out, u64 arg)
@@ -70,7 +97,7 @@ void fmt_class_string<EDataFlow>::format(std::string& out, u64 arg)
});
}
HRESULT audio_device_listener::listener::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR new_default_device_id)
HRESULT audio_device_listener::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR new_default_device_id)
{
IO.notice("OnDefaultDeviceChanged(flow=%s, role=%s, new_default_device_id=0x%x)", flow, role, new_default_device_id);
@@ -80,8 +107,9 @@ HRESULT audio_device_listener::listener::OnDefaultDeviceChanged(EDataFlow flow,
return S_OK;
}
// Only listen for console and communication device changes.
if ((role != eConsole && role != eCommunications) || (flow != eRender && flow != eCapture))
// Listen only for one device role, otherwise we're going to receive more than one
// notification for flow type
if (role != eConsole)
{
IO.notice("OnDefaultDeviceChanged(): we don't care about this device");
return S_OK;
@@ -90,15 +118,27 @@ HRESULT audio_device_listener::listener::OnDefaultDeviceChanged(EDataFlow flow,
const std::wstring tmp(new_default_device_id);
const std::string new_device_id = wchar_to_utf8(tmp.c_str());
if (device_id != new_device_id)
if (flow == eRender || flow == eAll)
{
device_id = new_device_id;
IO.warning("Default device changed: new device = '%s'", device_id);
if (auto& g_audio = g_fxo->get<cell_audio>(); g_fxo->is_init<cell_audio>())
if (output_device_id != new_device_id)
{
g_audio.m_update_configuration = true;
output_device_id = new_device_id;
IO.warning("Default output device changed: new device = '%s'", output_device_id);
m_output_device_changed = true;
}
}
if (flow == eCapture || flow == eAll)
{
if (input_device_id != new_device_id)
{
input_device_id = new_device_id;
IO.warning("Default input device changed: new device = '%s'", input_device_id);
m_input_device_changed = true;
}
}
+23 -12
View File
@@ -4,28 +4,39 @@
#include <MMDeviceAPI.h>
#endif
#include "util/atomic.hpp"
#ifdef _WIN32
class audio_device_listener : public IMMNotificationClient
#else
class audio_device_listener
#endif
{
public:
audio_device_listener();
~audio_device_listener();
bool input_device_changed();
bool output_device_changed();
private:
#ifdef _WIN32
struct listener : public IMMNotificationClient
{
std::string device_id;
std::string input_device_id;
std::string output_device_id;
IFACEMETHODIMP_(ULONG) AddRef() override { return 1; };
IFACEMETHODIMP_(ULONG) Release() override { return 1; };
IFACEMETHODIMP QueryInterface(REFIID /*iid*/, void** /*object*/) override { return S_OK; };
IFACEMETHODIMP OnPropertyValueChanged(LPCWSTR /*device_id*/, const PROPERTYKEY /*key*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceAdded(LPCWSTR /*device_id*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceRemoved(LPCWSTR /*device_id*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceStateChanged(LPCWSTR /*device_id*/, DWORD /*new_state*/) override { return S_OK; };
IFACEMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR new_default_device_id) override;
} m_listener;
IFACEMETHODIMP_(ULONG) AddRef() override { return 1; };
IFACEMETHODIMP_(ULONG) Release() override { return 1; };
IFACEMETHODIMP QueryInterface(REFIID /*iid*/, void** /*object*/) override { return S_OK; };
IFACEMETHODIMP OnPropertyValueChanged(LPCWSTR /*device_id*/, const PROPERTYKEY /*key*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceAdded(LPCWSTR /*device_id*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceRemoved(LPCWSTR /*device_id*/) override { return S_OK; };
IFACEMETHODIMP OnDeviceStateChanged(LPCWSTR /*device_id*/, DWORD /*new_state*/) override { return S_OK; };
IFACEMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR new_default_device_id) override;
IMMDeviceEnumerator* m_device_enumerator = nullptr;
bool m_com_init_success = false;
#endif
atomic_t<bool> m_input_device_changed = false;
atomic_t<bool> m_output_device_changed = false;
};
+53
View File
@@ -0,0 +1,53 @@
#include "stdafx.h"
#include "Emu/Audio/audio_resampler.h"
#include <algorithm>
audio_resampler::audio_resampler()
{
resampler.setSetting(SETTING_SEQUENCE_MS, 20); // Resampler frame size (reduce latency at cost of slight sound quality degradation)
resampler.setSetting(SETTING_USE_QUICKSEEK, 1); // Use fast quick seeking algorithm (substantally reduces computation time)
}
audio_resampler::~audio_resampler()
{
}
void audio_resampler::set_params(AudioChannelCnt ch_cnt, AudioFreq freq)
{
flush();
resampler.setChannels(static_cast<u32>(ch_cnt));
resampler.setSampleRate(static_cast<u32>(freq));
}
f64 audio_resampler::set_tempo(f64 new_tempo)
{
new_tempo = std::clamp(new_tempo, RESAMPLER_MIN_FREQ_VAL, RESAMPLER_MAX_FREQ_VAL);
resampler.setTempo(new_tempo);
return new_tempo;
}
void audio_resampler::put_samples(const f32* buf, u32 sample_cnt)
{
resampler.putSamples(buf, sample_cnt);
}
std::pair<f32* /* buffer */, u32 /* samples */> audio_resampler::get_samples(u32 sample_cnt)
{
f32 *const buf = resampler.bufBegin();
return std::make_pair(buf, resampler.receiveSamples(sample_cnt));
}
u32 audio_resampler::samples_available() const
{
return resampler.numSamples();
}
f64 audio_resampler::get_resample_ratio()
{
return resampler.getInputOutputSampleRatio();
}
void audio_resampler::flush()
{
resampler.clear();
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "util/types.hpp"
#include "Emu/Audio/AudioBackend.h"
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
#include "SoundTouch.h"
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif
constexpr f64 RESAMPLER_MAX_FREQ_VAL = 1.0;
constexpr f64 RESAMPLER_MIN_FREQ_VAL = 0.1;
class audio_resampler
{
public:
audio_resampler();
~audio_resampler();
void set_params(AudioChannelCnt ch_cnt, AudioFreq freq);
f64 set_tempo(f64 new_tempo);
void put_samples(const f32* buf, u32 sample_cnt);
std::pair<f32* /* buffer */, u32 /* samples */> get_samples(u32 sample_cnt);
u32 samples_available() const;
f64 get_resample_ratio();
void flush();
private:
soundtouch::SoundTouch resampler{};
};
+23 -15
View File
@@ -1,4 +1,4 @@
add_library(rpcs3_emu
add_library(rpcs3_emu
cache_utils.cpp
IdManager.cpp
localized_string.cpp
@@ -54,10 +54,16 @@ target_sources(rpcs3_emu PRIVATE
../../Utilities/mutex.cpp
../../Utilities/rXml.cpp
../../Utilities/sema.cpp
../../Utilities/simple_ringbuf.cpp
../../Utilities/StrFmt.cpp
../../Utilities/Thread.cpp
../../Utilities/version.cpp
)
if(APPLE)
target_sources(rpcs3_emu PRIVATE
../../darwin/util/sysinfo_darwin.mm
)
endif()
target_include_directories(rpcs3_emu PUBLIC "${CMAKE_SOURCE_DIR}")
@@ -108,24 +114,12 @@ target_sources(rpcs3_emu PRIVATE
# Audio
target_sources(rpcs3_emu PRIVATE
Audio/audio_device_listener.cpp
Audio/audio_resampler.cpp
Audio/AudioDumper.cpp
Audio/AudioBackend.cpp
Audio/AL/OpenALBackend.cpp
Audio/Cubeb/CubebBackend.cpp
)
if(USE_ALSA)
find_package(ALSA)
if(ALSA_FOUND)
target_sources(rpcs3_emu PRIVATE Audio/ALSA/ALSABackend.cpp)
target_link_libraries(rpcs3_emu PUBLIC 3rdparty::alsa)
endif()
endif()
if(USE_PULSE AND PULSE_FOUND)
target_sources(rpcs3_emu PRIVATE Audio/Pulse/PulseBackend.cpp)
target_link_libraries(rpcs3_emu PUBLIC 3rdparty::pulse)
endif()
if(USE_FAUDIO)
find_package(SDL2)
if(SDL2_FOUND AND NOT SDL2_VERSION VERSION_LESS 2.0.9)
@@ -147,6 +141,13 @@ target_link_libraries(rpcs3_emu
PUBLIC
3rdparty::openal)
target_link_libraries(rpcs3_emu
PUBLIC
3rdparty::cubeb)
target_link_libraries(rpcs3_emu
PUBLIC
3rdparty::soundtouch)
# Cell
target_sources(rpcs3_emu PRIVATE
@@ -370,13 +371,19 @@ target_sources(rpcs3_emu PRIVATE
Io/GHLtar.cpp
Io/Buzz.cpp
Io/Turntable.cpp
Io/usio.cpp
)
# Np
target_sources(rpcs3_emu PRIVATE
NP/fb_helpers.cpp
NP/np_cache.cpp
NP/np_contexts.cpp
NP/np_dnshook.cpp
NP/np_handler.cpp
NP/np_helpers.cpp
NP/np_notifications.cpp
NP/np_requests.cpp
NP/signaling_handler.cpp
NP/np_structs_extra.cpp
NP/rpcn_client.cpp
@@ -396,6 +403,7 @@ target_sources(rpcs3_emu PRIVATE
RSX/GSRender.cpp
RSX/RSXFIFO.cpp
RSX/rsx_methods.cpp
RSX/rsx_vertex_data.cpp
RSX/RSXOffload.cpp
RSX/RSXTexture.cpp
RSX/RSXThread.cpp
+2 -14
View File
@@ -17,7 +17,9 @@
#include <unordered_map>
#include <map>
#if defined(ARCH_X64)
#include <emmintrin.h>
#endif
DECLARE(cpu_thread::g_threads_created){0};
DECLARE(cpu_thread::g_threads_deleted){0};
@@ -410,20 +412,6 @@ void cpu_thread::operator()()
{
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(id_type() == 1 ? thread_class::ppu : thread_class::spu));
}
if (id_type() == 2)
{
// force input/output denormals to zero for SPU threads (FTZ/DAZ)
_mm_setcsr( _mm_getcsr() | 0x8040 );
const volatile int a = 0x1fc00000;
__m128 b = _mm_castsi128_ps(_mm_set1_epi32(a));
int c = _mm_cvtsi128_si32(_mm_castps_si128(_mm_mul_ps(b,b)));
if (c != 0)
{
sys_log.fatal("Could not disable denormals.");
}
}
while (!g_fxo->is_init<cpu_profiler>())
{
+1 -1
View File
@@ -179,7 +179,7 @@ public:
// Callback for thread_ctrl::wait or RSX wait
virtual void cpu_wait(bs_t<cpu_flag> old);
// Callback for function abortion stats on Emu.Stop()
// Callback for function abortion stats on Emu.Kill()
virtual void cpu_on_stop() {}
// For internal use
+27 -13
View File
@@ -3,7 +3,7 @@
#include "CPUTranslator.h"
#include "util/v128.hpp"
#include "util/v128sse.hpp"
#include "util/simd.hpp"
llvm::LLVMContext g_llvm_ctx;
@@ -85,29 +85,35 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
m_use_ssse3 = false;
}
// Test AVX feature (TODO)
if (cpu == "sandybridge" ||
cpu == "ivybridge" ||
cpu == "bdver1")
{
m_use_avx = true;
}
// Test FMA feature (TODO)
if (cpu == "haswell" ||
cpu == "broadwell" ||
cpu == "skylake" ||
cpu == "alderlake" ||
cpu == "bdver2" ||
cpu == "bdver3" ||
cpu == "bdver4" ||
cpu.startswith("znver"))
{
m_use_fma = true;
m_use_avx = true;
}
// Test AVX-512 feature (TODO)
if (cpu == "skylake-avx512" ||
cpu == "cascadelake" ||
cpu == "cannonlake" ||
cpu == "cooperlake" ||
cpu == "icelake" ||
cpu == "icelake-client" ||
cpu == "icelake-server" ||
cpu == "tigerlake" ||
cpu == "rocketlake")
cpu == "cooperlake")
{
m_use_avx = true;
m_use_fma = true;
m_use_avx512 = true;
}
@@ -128,6 +134,9 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
cpu == "rocketlake" ||
cpu == "sapphirerapids")
{
m_use_avx = true;
m_use_fma = true;
m_use_avx512 = true;
m_use_avx512_icl = true;
m_use_vnni = true;
}
@@ -139,9 +148,9 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
uint s2 = val->getType()->getScalarSizeInBits();
if (type->isVectorTy())
s1 *= llvm::cast<llvm::VectorType>(type)->getNumElements();
s1 *= llvm::cast<llvm::FixedVectorType>(type)->getNumElements();
if (val->getType()->isVectorTy())
s2 *= llvm::cast<llvm::VectorType>(val->getType())->getNumElements();
s2 *= llvm::cast<llvm::FixedVectorType>(val->getType())->getNumElements();
if (s1 != s2)
{
@@ -183,7 +192,7 @@ std::pair<bool, v128> cpu_translator::get_const_vector<v128>(llvm::Value* c, u32
fmt::throw_exception("[0x%x, %u] Not a vector", _pos, _line);
}
if (auto v = llvm::cast<llvm::VectorType>(t); v->getScalarSizeInBits() * v->getNumElements() != 128)
if (auto v = llvm::cast<llvm::FixedVectorType>(t); v->getScalarSizeInBits() * v->getNumElements() != 128)
{
fmt::throw_exception("[0x%x, %u] Bad vector size: i%ux%u", _pos, _line, v->getScalarSizeInBits(), v->getNumElements());
}
@@ -197,13 +206,18 @@ std::pair<bool, v128> cpu_translator::get_const_vector<v128>(llvm::Value* c, u32
return {};
}
std::string result;
llvm::raw_string_ostream out(result);
c->print(out, true);
out.flush();
if (llvm::isa<llvm::ConstantExpr>(c))
{
// Sorry, if we cannot evaluate it we cannot use it
fmt::throw_exception("[0x%x, %u] Constant Expression!", _pos, _line);
fmt::throw_exception("[0x%x, %u] Constant Expression!\n%s", _pos, _line, result);
}
fmt::throw_exception("[0x%x, %u] Unexpected constant type", _pos, _line);
fmt::throw_exception("[0x%x, %u] Unexpected constant type!\n%s", _pos, _line, result);
}
const auto sct = t->getScalarType();
@@ -267,7 +281,7 @@ llvm::Constant* cpu_translator::make_const_vector<v128>(v128 v, llvm::Type* t, u
}
ensure(t->isVectorTy());
ensure(128 == t->getScalarSizeInBits() * llvm::cast<llvm::VectorType>(t)->getNumElements());
ensure(128 == t->getScalarSizeInBits() * llvm::cast<llvm::FixedVectorType>(t)->getNumElements());
const auto sct = t->getScalarType();
+36 -19
View File
@@ -15,6 +15,7 @@
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
#endif
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Target/TargetMachine.h"
@@ -43,6 +44,18 @@ enum class i4 : char
{
};
template <typename T>
concept LLVMType = (std::is_pointer_v<T>) && (std::is_base_of_v<llvm::Type, std::remove_pointer_t<T>>);
template <typename T>
concept LLVMValue = (std::is_pointer_v<T>) && (std::is_base_of_v<llvm::Value, std::remove_pointer_t<T>>);
template <typename T>
concept DSLValue = requires (T& v)
{
{ v.eval(std::declval<llvm::IRBuilder<>*>()) } -> LLVMValue;
};
template <typename T = void>
struct llvm_value_t
{
@@ -2886,6 +2899,9 @@ protected:
// Allow FMA
bool m_use_fma = false;
// Allow AVX
bool m_use_avx = false;
// Allow skylake-x tier AVX-512
bool m_use_avx512 = false;
@@ -2945,11 +2961,11 @@ public:
}
// Call external function: provide name and function pointer
template <typename RT, typename... FArgs, typename... Args>
template <typename RetT = void, typename RT, typename... FArgs, LLVMValue... Args>
llvm::CallInst* call(std::string_view lame, RT(*_func)(FArgs...), Args... args)
{
static_assert(sizeof...(FArgs) == sizeof...(Args), "spu_llvm_recompiler::call(): unexpected arg number");
const auto type = llvm::FunctionType::get(get_type<RT>(), {args->getType()...}, false);
const auto type = llvm::FunctionType::get(get_type<std::conditional_t<std::is_void_v<RetT>, RT, RetT>>(), {args->getType()...}, false);
const auto func = llvm::cast<llvm::Function>(m_module->getOrInsertFunction({lame.data(), lame.size()}, type).getCallee());
#ifdef _WIN32
func->setCallingConv(llvm::CallingConv::Win64);
@@ -2963,6 +2979,22 @@ public:
return inst;
}
template <typename RT, typename... FArgs, DSLValue... Args> requires (sizeof...(Args) != 0)
auto call(std::string_view name, RT(*_func)(FArgs...), Args&&... args)
{
llvm_value_t<RT> r;
r.value = call(name, _func, std::forward<Args>(args).eval(m_ir)...);
return r;
}
template <typename RT, DSLValue... Args>
auto call(llvm::Function* func, Args&&... args)
{
llvm_value_t<RT> r;
r.value = m_ir->CreateCall(func, {std::forward<Args>(args).eval(m_ir)...});
return r;
}
// Bitcast with immediate constant folding
llvm::Value* bitcast(llvm::Value* val, llvm::Type* type) const;
@@ -3493,10 +3525,10 @@ public:
shuffle.value = m_ir->CreateZExt(shuffle.value, get_type<u32[32]>());
intermediate.value = m_ir->CreateShuffleVector(data0, data1, shuffle.value);
// expand the shuffle index to 256 bits with zeroes
// expand the shuffle index to 256 bits with zeroes
shuffleindex.value = m_ir->CreateShuffleVector(index, zeroes, shuffle.value);
// permute
// permute
intermediate.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_permvar_qi_256), {intermediate.value, shuffleindex.value});
// convert the 256 bit vector back to 128 bits
@@ -3648,19 +3680,4 @@ struct fmt_unveil<llvm::TypeSize, void>
}
};
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
template <>
inline llvm::Type* cpu_translator::get_type<__m128i>()
{
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16, false);
}
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif
#endif
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -269,8 +269,12 @@ public:
bool just_started = false;
bool just_finished = false;
AVCodec* codec = nullptr;
const AVCodec* codec = nullptr;
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(59, 0, 0)
const AVInputFormat* input_format = nullptr;
#else
AVInputFormat* input_format = nullptr;
#endif
AVCodecContext* ctx = nullptr;
AVFormatContext* fmt = nullptr;
u8* io_buf;
+4 -4
View File
@@ -51,7 +51,7 @@ error_code cellAtracCreateDecoder(vm::ptr<CellAtracHandle> pHandle, vm::ptr<u8>
{
cellAtrac.warning("cellAtracCreateDecoder(pHandle=*0x%x, pucWorkMem=*0x%x, uiPpuThreadPriority=%d, uiSpuThreadPriority=%d)", pHandle, pucWorkMem, uiPpuThreadPriority, uiSpuThreadPriority);
pHandle->pucWorkMem = pucWorkMem;
std::memcpy(pHandle->ucWorkMem, pucWorkMem.get_ptr(), CELL_ATRAC_HANDLE_SIZE);
return CELL_OK;
}
@@ -59,7 +59,7 @@ error_code cellAtracCreateDecoderExt(vm::ptr<CellAtracHandle> pHandle, vm::ptr<u
{
cellAtrac.warning("cellAtracCreateDecoderExt(pHandle=*0x%x, pucWorkMem=*0x%x, uiPpuThreadPriority=%d, pExtRes=*0x%x)", pHandle, pucWorkMem, uiPpuThreadPriority, pExtRes);
pHandle->pucWorkMem = pucWorkMem;
std::memcpy(pHandle->ucWorkMem, pucWorkMem.get_ptr(), CELL_ATRAC_HANDLE_SIZE);
return CELL_OK;
}
@@ -84,7 +84,7 @@ error_code cellAtracGetStreamDataInfo(vm::ptr<CellAtracHandle> pHandle, vm::pptr
{
cellAtrac.warning("cellAtracGetStreamDataInfo(pHandle=*0x%x, ppucWritePointer=**0x%x, puiWritableByte=*0x%x, puiReadPosition=*0x%x)", pHandle, ppucWritePointer, puiWritableByte, puiReadPosition);
*ppucWritePointer = pHandle->pucWorkMem;
ppucWritePointer->set(pHandle.addr());
*puiWritableByte = 0x1000;
*puiReadPosition = 0;
return CELL_OK;
@@ -206,7 +206,7 @@ error_code cellAtracGetBufferInfoForResetting(vm::ptr<CellAtracHandle> pHandle,
{
cellAtrac.warning("cellAtracGetBufferInfoForResetting(pHandle=*0x%x, uiSample=0x%x, pBufferInfo=*0x%x)", pHandle, uiSample, pBufferInfo);
pBufferInfo->pucWriteAddr = pHandle->pucWorkMem;
pBufferInfo->pucWriteAddr.set(pHandle.addr());
pBufferInfo->uiWritableByte = 0x1000;
pBufferInfo->uiMinWriteByte = 0;
pBufferInfo->uiReadPosition = 0;
+3 -6
View File
@@ -43,15 +43,12 @@ enum
struct alignas(8) CellAtracHandle
{
vm::ptr<u8> pucWorkMem;
// ...
u8 ucWorkMem[CELL_ATRAC_HANDLE_SIZE];
};
CHECK_MAX_SIZE(CellAtracHandle, 512);
struct CellAtracBufferInfo
{
vm::ptr<u8> pucWriteAddr;
vm::bptr<u8> pucWriteAddr;
be_t<u32> uiWritableByte;
be_t<u32> uiMinWriteByte;
be_t<u32> uiReadPosition;
@@ -59,6 +56,6 @@ struct CellAtracBufferInfo
struct CellAtracExtRes
{
vm::ptr<struct CellSpurs> pSpurs;
vm::bptr<struct CellSpurs> pSpurs;
u8 priority[8];
};

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