Compare commits

...

695 Commits

Author SHA1 Message Date
Ani 2b8eb8deb6 rpcs3_version: Bump to 0.0.14 2020-12-31 23:15:54 +03:00
Megamouse 7262f3d0b7 VK: make static chip_family_tables const 2020-12-31 22:57:17 +03:00
Megamouse 6f80fd0063 VK: move static chip_family_tables to cpp 2020-12-31 22:57:17 +03:00
Megamouse 7a51b7a019 VK: move helpers to vkutils 2020-12-31 22:57:17 +03:00
Megamouse d9eb31000d VK: refactoring part 1 2020-12-31 22:57:17 +03:00
Chris f8589de476 Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support

This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.

Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.

For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.

The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.

This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.

A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY

Next steps:
 - Utilize sortKey in cellSearchStartContentSearchInList()
 - Eliminate TODOs
 - Implement the missing other functions
 - Test on more games - I do not own many that support custom soundtracks

Signed-off-by: gladiac1337 <gladiac@gmail.com>

Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 22:47:09 +03:00
Florin9doi f1c61067bc Buzz! emulated controller (#9504)
* Buzz emulated controller
Co-authored-by: Florin9doi <Florin9doi@users.noreply.github.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 21:02:03 +03:00
Nekotekina 8a5620592b Implement util/fifo_mutex.hpp
Prototype. Uses 2 bytes.
Added minor fix to slow_mutex.hpp as well.
2020-12-31 20:07:50 +03:00
Nekotekina 5227e65808 vm: implement vm::atomic_op, fetch_op helpers
Can help to reduce lambda depth hell a little.
2020-12-30 20:11:02 +03:00
Eladash c4c6dc19a5 memory viewer: Implement SPU mode, fix address GOTO 2020-12-30 15:42:56 +03:00
Eladash 7fc26b1fab rsx: Implement Texture LOD Bias addend setting 2020-12-30 15:37:21 +03:00
Eladash c0e121abef rsx: Fix RSXTexture.h spacing 2020-12-30 15:37:21 +03:00
Eladash 7db13fdeff rsx: Move Anisotropic Filter Override to RSX state 2020-12-30 15:37:21 +03:00
JohnHolmesII e68027b464 Format: Update clang format
Old clang format file was extremely broken, causing issues when viewing
code on github, and also featuring stale values.

- Fix indentation information
- Force wrapping on lambdas
2020-12-30 15:24:43 +03:00
JohnHolmesII 220b69058c Docs: Update BUILDING.md 2020-12-30 09:03:24 +03:00
JohnHolmesII 9c3e55787e CMake: Update required Qt version 2020-12-30 09:03:24 +03:00
Malcolm Jestadt c952e99f3e SPU LLVM: Fix edgecase in icelake codegen 2020-12-29 22:01:11 +03:00
Nekotekina 35322b5d14 Remove deprecated _bit accessor from v128
Complicated (a lot of code), confusing (ambiguous)
2020-12-29 21:04:28 +03:00
Nekotekina 6b96807112 Reimplement utils::popcnt64
Implement utils::popcnt128
2020-12-29 15:28:02 +03:00
JohnHolmesII 57621d1c4e Types: Use nullptr over 0 2020-12-29 14:17:34 +03:00
JohnHolmesII e04b2eebc3 Warnings: Silence false warnings about fatal code paths 2020-12-29 14:17:34 +03:00
JohnHolmesII 02b684b810 Warnings: Warnings use kebab case, Mr. Kot 2020-12-29 14:17:34 +03:00
JohnHolmesII 76b1acf99d Warnings: Ensure death functions are all marked noreturn 2020-12-29 14:17:34 +03:00
kd-11 18c120ab9f rsx: Revert an accidental deletion 2020-12-28 21:49:11 +03:00
kd-11 f87dd91b52 rsx: Allow attempted fetch of non-existent surface 2020-12-28 21:49:11 +03:00
RipleyTom 4a8a161a43 Improve skylander portal emulator 2020-12-27 22:20:58 +01:00
Nekotekina e3dec420a2 vm_native.cpp: conditionally define c_madv_free 2020-12-27 12:19:50 +03:00
Nekotekina 1e32311a65 Use MAP_NORESERVE when available in mmap (Linux)
Used in: memory_reserve, memory_decommit (vm_native.cpp)
2020-12-27 10:20:42 +03:00
Marin Baron 92e5bb88e8 Remove std typeinfo 2020-12-27 00:30:16 +03:00
Eladash 66581d115b vm: Fix access violations on super memory, support super memory in vm::get_addr 2020-12-26 17:56:49 +03:00
RipleyTom 4399324955 Disables precompiled headers by default (#9499) 2020-12-25 20:41:49 +00:00
Florin9doi 733f31f90e Allow USB passthrough for THQ uDraw GameTablet 2020-12-25 14:27:24 +03:00
RipleyTom bef2c50b03 Remove bom in Utilities dir 2020-12-25 10:07:40 +03:00
kd-11 a96b4412d3 rsx: Do not rely on program env state, instead, always use program ucode analysis results when doing codegen
- Some things can be present in program env but not ucode state
  e.g A texture can be active and bound in a redirected manner but not actually be used in ucode
  In such a case, only the ucode analysis or decompilation can decide whether to inject decoding routines
2020-12-25 02:39:08 +03:00
kd-11 bee76fc8d1 rsx: Refactor shader codegen and fix shadow sampling on depth-float 2020-12-25 02:39:08 +03:00
kd-11 d9cb1a6319 vk: Fix more spec violations 2020-12-25 02:39:08 +03:00
Nekotekina 567d23d856 Implement util/auto_typemap.hpp
Used in vm::block_t as an example.
2020-12-24 14:55:25 +03:00
Eladash c94a98e15a Fix minor typo 2020-12-23 20:50:33 +03:00
Eladash 72e6e87d82 Fix SPU ELF loader 2020-12-23 20:50:33 +03:00
Eladash 0055d84bd6 Partial revert of 43c87e99b0 2020-12-23 08:25:56 +03:00
Eladash d17d22139e SPU Debugger: Print reservation data 2020-12-23 08:25:56 +03:00
Eladash 87b6284275 memory viewer: Only allow "words" steps in powers of 2 2020-12-23 08:25:56 +03:00
Eladash 2c6b974f24 Fixup memory viewer SPU headers for RawSPU 2020-12-23 08:25:56 +03:00
Eladash 020acc8235 GUI: Rewrite GOTO address tools in debugger tools 2020-12-23 08:25:56 +03:00
Nekotekina a8e0d261b7 types.hpp: more cleanup
Also fix compilation.
2020-12-22 19:08:09 +03:00
Nekotekina 6357b9a04f perf_meter.cpp: register only named threads
Can workaround some possible problems.
2020-12-22 14:32:30 +03:00
Nekotekina 43a58df8a0 Butcher narrow cast a little (don't print value).
Also remove some forward declarations from util/types.hpp
If they don't work properly, it's easier to remove them.
2020-12-22 14:32:30 +03:00
Nekotekina b7bf316c1a Don't randomly include "stdafx.h"
It's file for precompiled headers.
Include what is used, don't rely on transitive includes.
2020-12-22 14:32:30 +03:00
Nekotekina 41ee792f95 MSVC: remove MemLeak build support
There are better memleak detection tools.
1) Requires to guard placement new and external libs
2) Doesn't work thoroughly
2020-12-22 14:32:30 +03:00
Bird Egop 6c1b6c1704 Add PR-BUILD.md and Pull Request Template 2020-12-22 14:31:44 +03:00
Fro Zen acadaeed3a Change skylander variants to use hex 2020-12-22 08:58:36 +01:00
Jan Beich 96bde3df81 atomic.hpp: revert Clang < 11 workaround for u128 2020-12-22 09:00:34 +03:00
Jan Beich 5cb70ddbd5 CMake: bump minimum Clang to 11 2020-12-22 09:00:34 +03:00
Jan Beich b9b9a0465f CI: switch FreeBSD to Clang 11 (similar to e2303f3378) 2020-12-22 09:00:34 +03:00
Nekotekina bd269bccaf types.hpp: remove intrinsic includes
Replace v128 with u128 in some places.
Removed some unused files.
2020-12-21 21:11:25 +03:00
Nekotekina 5f618814f6 atomic.hpp: use u128 as storage for masks/values 2020-12-21 13:51:23 +03:00
Eladash 43c87e99b0 Debugger: Switch from NoThread when the emulation is running
And fix UpdateUnitList() when the emulation is stopped at initial startup.
2020-12-21 13:46:26 +03:00
Eladash 74a09a6338 PPU memory must be exec memory when using debugger's "Next Instruction" feature 2020-12-21 13:46:26 +03:00
Eladash 2b9c407dc3 Mask PC in debugger_frame::keyPressEvent for SPU
SPU only has 256kb of memory, need to work with this.
2020-12-21 13:46:26 +03:00
Eladash 59ed222205 Disasm: read instruction contents only once
Memory is volatile and may be changed by guest threads, ensure the decoded instruction matches with the data.
2020-12-21 13:46:26 +03:00
Eladash 2c06043617 Debugger: correctness fixes and cleanup
* Remove m_current_choice, it's not correct to rely on thread name entry. In extreme corner cases a newly thread can be created, old destroyed with the same entry name. (reoccuring LV2 SPU/PPU ID)
* Remove m_no_thread_selected, can be easily replaced with std::weak_ptr expired() function and is more accurate this way.
* In HandleBreakpointRequest: only remove breakpoint on valid PPU thread and not any thread! also fix potential nullptr deref if thread has recently been destroyed.
2020-12-21 13:46:26 +03:00
Eladash ef884642e4 Cleanup disasm classes a bit 2020-12-21 13:46:26 +03:00
kd-11 e449111c33 vk: Fixup for renderpass issues 2020-12-19 12:58:44 +03:00
Megamouse 066e53da55 minor cleanup 2020-12-19 08:33:53 +01:00
Eladash c74b2cb085 memory viewer: Fix resizing down 2020-12-18 21:00:09 +01:00
Nekotekina eec11bfba9 Move align helpers to util/asm.hpp
Also add some files:
GLTextureCache.cpp
VKTextureCache.cpp
2020-12-18 18:07:42 +03:00
Nekotekina d254a5736b Fix bug with vector arg alignment in BIND_FUNC and callbacks. 2020-12-18 18:07:42 +03:00
Megamouse b655e4aa47 Emu: implement on_exit callback 2020-12-18 16:05:40 +01:00
Nekotekina 1adec3d8e5 Hotfix: Emu.Quit after Emu.Stop 2020-12-18 13:37:14 +03:00
Nekotekina db9b7db531 Cleanup and move sysinfo.h -> util/sysinfo.hpp 2020-12-18 12:55:54 +03:00
Nekotekina 05099e2ae1 Replace uint64_t with u64 2020-12-18 12:23:53 +03:00
Nekotekina 77352a2a86 Replace uint32_t with u32 2020-12-18 12:23:53 +03:00
Nekotekina ae633292c0 Replace int32_t with s32 2020-12-18 12:23:53 +03:00
Nekotekina d6042cf891 Replace uint16_t with u16 2020-12-18 12:23:53 +03:00
Nekotekina 534c63bf57 Replace uint8_t with u8 2020-12-18 12:23:53 +03:00
Nekotekina fb29933d3d Add usz alias for std::size_t 2020-12-18 12:23:53 +03:00
Nekotekina 360c4d1554 Simplify f16 type 2020-12-18 12:23:53 +03:00
Nekotekina 4cfa9b11f3 Move busy_wait() to asm.hpp 2020-12-18 12:23:53 +03:00
Megamouse 908465b274 memory viewer: improve layout and resize 2020-12-18 09:58:12 +01:00
Megamouse a7f10d142e fix warning 2020-12-18 09:58:12 +01:00
Megamouse e855673802 memory viewer: check width and height in image viewer 2020-12-18 09:58:12 +01:00
Megamouse 112ac7bd13 memory viewer: fix RGB Image viewer crash 2020-12-18 09:58:12 +01:00
Megamouse ec7963df3d memory viewer: use enum for color formats 2020-12-18 09:58:12 +01:00
Megamouse 343d006ae2 memory viewer: more cleanup 2020-12-18 09:58:12 +01:00
Megamouse ed8e5498d1 memory viewer: fix horrible overflow that freezes rpcs3 2020-12-18 09:58:12 +01:00
Megamouse 3cfead4ca6 memory viewer cleanup 2020-12-18 09:58:12 +01:00
Eladash c8947eee6a GUI: Make memory viewer address edit accept 0x/0X prefixes
Max length is 10, added regexp validator accordinally.
2020-12-17 22:57:13 +01:00
Eladash 6c1ca7d797 GUI: Polish the memory viewer 2020-12-17 22:57:13 +01:00
Eladash 2172974db9 Link the memory viewer with the debugger 2020-12-17 19:36:35 +01:00
Eladash ba03df8511 GUI: Improve PS3 decryption tool 2020-12-17 18:49:04 +01:00
kd-11 fb47d1f788 vk: Register ampere GPU PCI IDs 2020-12-17 19:56:48 +03:00
Nekotekina 3c86e14ea4 Fix hexadecimal line numbers in error reports 2020-12-17 17:00:06 +03:00
Nekotekina c16fb61bea fixed_typemap.hpp: Fix assignment operator for g_ptr
Maybe RPCS3 hangs will finally be gone.
2020-12-17 16:47:25 +03:00
Nekotekina 2acead357b Update LLVM commit (minor fixups) 2020-12-17 16:47:25 +03:00
kd-11 235db57f0e rsx: Do not reset vertex program texture mask when updating ucode analysis
- Fixes incorrect texture type detection in some games after program env/ucode separation
2020-12-17 09:36:20 +03:00
kd-11 cfbde005fb vk: Force ampere GPUs to use the slower but spec-compliant depth-color resize route
- TODO: More investigation and optimizations
2020-12-17 09:36:20 +03:00
kd-11 0a865bd9dc vk: Workaround for validation layers bug 2020-12-17 09:36:20 +03:00
Nekotekina 6b3f722ff0 Hotfix: useless error 2020-12-16 11:57:29 +03:00
Fro Zen 3dbecada4e Almost all Skylander variants (#9443)
* Update skylander_dialog.cpp

* Fix formatting, sorted

* Support for skylanders variant

* Remove duplicate Legendary Hand of Fate

* Removed accidental Series 2 Dark Spyro

There is no series 2 dark spyro, also im removing these as im finding them so sorry if theres tons of commits

* Add LightCore Hex

* Remove Vehicle tag

* Add Big Bang Trigger Happy

Co-authored-by: RipleyTom <RipleyTom@users.noreply.github.com>
2020-12-16 11:02:59 +03:00
Megamouse d21f87af5d Fix unresponsive UI during SPU compilation 2020-12-16 11:01:51 +03:00
Megamouse 0bfec59af8 Fix stop during shader compilation 2020-12-16 11:01:51 +03:00
kd-11 035a76f26d Fix build 2020-12-16 10:10:06 +03:00
kd-11 42f4e831a2 vk: Clean up some leftovers from shader decompiler rewrites 2020-12-16 10:10:06 +03:00
kd-11 d3686dbb75 rsx: Add some texture upload statistics to the texture cache 2020-12-16 10:10:06 +03:00
kd-11 fb1c790350 rsx: Make debug overlay dynamic 2020-12-16 10:10:06 +03:00
kd-11 0ef5743261 rsx: Fix sampler descriptor updates for framebuffer resources
- Each desc manages its own lifetime now instead of relying on global timestamp check
- Fixes situation where same object remains active without update for long
2020-12-16 10:10:06 +03:00
Nekotekina e82bef425f vm: fix warnings and add narrow cast for u64 ptrs 2020-12-15 20:10:16 +03:00
Nekotekina 24c246a9f6 Fix potential thread_pool crash on exit
Minor issue.
2020-12-15 20:01:26 +03:00
Nekotekina e39348ad96 Make lf_queue<> compatible with atomic_wait 2020-12-15 19:19:36 +03:00
Nekotekina ca5f0444bf shared_ptr.hpp: add wait support for atomic_ptr<>
As well as default mask and value transformation function overload.
2020-12-15 12:52:21 +03:00
Nekotekina 4a883ba6ea atomic.hpp: use SFINAE for waitable atomic detection
Add default_mask<> variable.
Refactor get_value<>().
2020-12-15 12:50:44 +03:00
Eladash bfe1a8673a PPU: Allow HLE execution from pure instruction decoder type interpreter 2020-12-15 11:18:51 +03:00
Eladash 0445ef393f FW SPRX install: Fix IDM ID's leak 2020-12-15 11:16:45 +03:00
Eladash 7eb16e13bb PRX loader: Fix libfs_155.sprx loading
Fix relocations' segments referencing when there are "empty" (memsize=0) LOAD segments.
2020-12-15 11:16:45 +03:00
Megamouse 03ad5c6830 Salvaging code (#9432)
* Minor input refactoring

* fix sys_config_unregister_io_error_listener log message

* Remove unused variables in RepaintTextColors

Co-authored-by: GermanAizek <GermanAizek@yandex.ru>
2020-12-14 14:33:43 +01:00
Megamouse ab23e5ca0e Minor tooltip grammar fix 2020-12-14 09:01:07 +03:00
Megamouse 35ecd00559 Remove BOM from new files 2020-12-14 09:01:07 +03:00
Eladash e5603fec1e Firmware libraries settings overhaul 2020-12-13 21:52:24 +03:00
Nekotekina e321765c54 Split BEType.h to util/v128.hpp and util/to_endian.hpp 2020-12-13 16:34:45 +03:00
Nekotekina 62fdcf50ea vm: initialize g_pages at vm::init
Can reduce compile time/overhead.
2020-12-13 15:39:36 +03:00
Nekotekina 09d293592e shared_ptr.hpp: fix is_same_ptr<>() trait
Implemented as constexpr function.
2020-12-13 15:39:36 +03:00
kd-11 f83c2f0b6b rsx: Restructure and simplify some header include chains 2020-12-13 15:38:35 +03:00
kd-11 d775c8dc73 rsx: Move shader analysis+prefetch to the end of the draw call 2020-12-13 15:38:35 +03:00
Fro Zen 8e07b19bc7 Add variant support for Skylanders (#9424)
* Update skylander_dialog.cpp

Co-authored-by: RipleyTom <RipleyTom@users.noreply.github.com>
2020-12-13 14:30:38 +03:00
Luke Barr cb8ef46ec7 Initial DualSense Support (#9308)
* Initial DualSense Support

* Add Vibration Support

* Add CRC32 Validation to Incoming Bluetooth Packets
Cleanup report sizes

* Consistency, remove button comments, add two buttons.

Co-authored-by: Ani <ani-leo@outlook.com>
2020-12-13 00:00:45 +01:00
Fro Zen ee814cfd0c Update skylander_dialog.cpp (#9419) 2020-12-12 19:16:15 +03:00
Nekotekina a6a5292cd7 Use uptr (std::uintptr_t alias) 2020-12-12 16:29:55 +03:00
Nekotekina b59f142d4e Move types.h to util/types.hpp 2020-12-12 15:12:01 +03:00
Nekotekina 666a18f5e5 Remove ceil2/floor2 from types.h 2020-12-12 15:12:01 +03:00
Nekotekina dff4392c10 Move error_code to ErrorCodes.h 2020-12-12 15:12:01 +03:00
Nekotekina b09b7c1184 Remove any_pod<> from types.h
Add simplified any32 to GCM.h
Add simplified cmd64 to PPUThread.h
2020-12-12 13:12:39 +03:00
Nekotekina 6e05dcadb6 Reduce std::numeric_limits dependency
Please, stop pretending...
You need these templates for generic code.
In other words, in another templates.
Stop increasing compilation time for no reason.
2020-12-12 12:35:18 +03:00
Nekotekina bc7acf9f7a RSX: remove overly long integer sequence (opcode_list)
Convert to constexpr array and move to gcm_printing.cpp
2020-12-12 11:38:35 +03:00
Nekotekina cb19316a17 Fix u128 constructors (MSVC) 2020-12-12 09:54:39 +03:00
Nekotekina 33c3977036 endian.hpp: minor simplification
And stop pretending...
2020-12-11 22:00:26 +03:00
Nekotekina 7a015b6fc0 VKMemAlloc.cpp: use shared_mutex in vk_mem_alloc.h
Because it allows to use custom implementation.
Also fix compilation.
2020-12-11 19:05:11 +03:00
Nekotekina aa3aef4beb std::chrono cleanup: always use steady_clock 2020-12-11 19:01:56 +03:00
Nekotekina 12a48fc6d1 Fixup for fs::file::read 2020-12-11 07:33:15 +03:00
Nekotekina 72284b4530 Use atomic_t<> in VKMemAlloc 2020-12-10 18:58:11 +03:00
Nekotekina 65c04e4ddd Remove constexpr from ppu/spu decoders.
We don't need them at compile time (yet).
But can reduce compile time and complexity.
2020-12-10 15:06:01 +03:00
Nekotekina b382d3b3e9 Remove ASSUME macro
It's dangerous and sometimes bluntly misused feature.
Its optimization potential is near-zero.
2020-12-10 14:08:02 +03:00
Nekotekina 61b882b2a6 Always print system error code on 'throwing' errors.
Print system error code in src_loc fmt.
Error code may be irrelevant though.
2020-12-10 12:43:49 +03:00
Nekotekina 36c8654fb8 Remove HERE macro
Some cleanup.
Add location to some functions.
2020-12-10 12:30:22 +03:00
kd-11 d25c401aec vk: Validate image creation inputs
- Should avoid things like res scaling breaking when very large scaling is in use
2020-12-09 21:30:08 +03:00
kd-11 aac874a842 vk: Add even more D32_SFLOAT missing locations 2020-12-09 21:30:08 +03:00
Nekotekina 5d934c8759 Improve narrow() and size32() with src_loc detection 2020-12-09 16:26:20 +03:00
Nekotekina e055d16b2c Replace verify() with ensure() with auto src location.
Expression ensure(x) returns x.
Using comma operator removed.
2020-12-09 15:43:38 +03:00
Nekotekina 38745e5782 SPU ASMJIT: fixup mfence replacement 2020-12-09 11:15:40 +03:00
RipleyTom d0c271e534 Simplify g_pages
This was done because otherwise msvc runs out of heap space on azure.
2020-12-09 11:15:08 +03:00
RipleyTom 33635c5723 Set msvc toolkit back to mainline 2020-12-09 11:15:08 +03:00
kd-11 f8d2830ac7 vk: Properly register D32_SFLOAT as a depth-stencil format (#9396) 2020-12-09 02:06:27 +00:00
Megamouse a7e5c255b4 Qt 5.15.2 (#8867)
* Qt15: replace deprecated stuff

* Use Qt 5.15.1

* Move windows to Qt 5.15.2

* Move Ubuntu to Qt 5.15.2
2020-12-08 22:22:08 +01:00
Nekotekina 062c605eb1 atomic.hpp: fixup (rsp addressing) 2020-12-08 08:51:27 +03:00
Eladash 2602be426f Allow emulation to work without firmware (#9367)
* Allow emulation to work without firmware
* Fix HLE prx path detection.
* Fix manual list loading bugs.
* Fix HLE gcm
* GUI: Fix fonts search
* GUI: Hardcode sprx list
Do not depend on /dev_flash/sys/external/ contents.
2020-12-07 20:10:34 +03:00
RipleyTom 51dcb4a79d Remove bom from .hpp files 2020-12-07 20:03:44 +03:00
Nekotekina 24e4e329ed atomic.hpp: add atomic_t<bool> specialization
May be required in future, plus adds/hides some methods.
2020-12-07 17:13:12 +03:00
Nekotekina eb66302907 atomic.hpp: replace std::atomic with atomic_t
Dual dependency is nothing good.
2020-12-07 17:13:12 +03:00
Nekotekina b16cc618b5 atomic.hpp: add some features and optimizations
Add atomic_t<>::observe() (relaxed load)
Add atomic_fence_XXX() (barrier functions)
Get rid of MFENCE instruction, replace with no-op LOCK OR on stack.
Remove <atomic> dependence from stdafx.h and relevant headers.
2020-12-07 17:13:12 +03:00
Nekotekina 77aa9e58f2 shared_ptr.hpp: add trivial conversion for shared/single types
These conversions don't exist in std::shared_ptr-alike types.
But I don't want to bother with == operators until we have proper C++20.
Removed trivial conversion for atomic_ptr because it's heavyweight.
2020-12-07 15:33:28 +03:00
kd-11 3a0b3a85a5 rsx: Separate program environment state from program ucode state
- Allows for conservative texture uploads
- Allows to update a program object without running full ucode analysis for no reason
2020-12-07 00:45:27 +03:00
Eladash 15a12afe25 Debugger: Implement code flow tracking 2020-12-06 15:32:13 +03:00
Eladash 427cf91447 Debugger: rewrite GetPc() 2020-12-06 15:32:13 +03:00
RipleyTom af8c661a64 Remove BOM markers 2020-12-06 15:30:12 +03:00
RipleyTom 7b694ebeb4 Set default to utf-8 for MSVC 2020-12-06 15:30:12 +03:00
Nekotekina d1e7837422 atomic_t: cleanup type requirements
Add C++17 requirements.
Remove alignment requirements (auto-align type).
What's missing is to detect padding and forbid it.
2020-12-04 19:11:36 +03:00
Nekotekina 8efc22bd45 atomic.hpp: simplify and unify bit test instructions
Also make them available on all platform.
Rename some rare methods.
2020-12-04 14:33:38 +03:00
Nekotekina 983439076b shared_ptr.hpp: fixups and updates
Fix atomic_ptr load() edge case.
Implement atomic_ptr::peek_op() to make possible to reduce load() overhead.
Implement atomic_ptr::compare_exchange() and friends.
Implement null_ptr constant, remove nullptr_t assignment/construction.
2020-12-04 14:10:53 +03:00
Nekotekina 019f566239 atomic.cpp: more phase splitting in notify_all() 2020-12-04 14:10:53 +03:00
Nekotekina 332410d20b shared_ptr.hpp: improve atomic_ptr methods 2020-12-04 14:10:53 +03:00
JoãoPaulo c2a85bde08 Update FW 4.87 Latest Version (#9366)
Updates the latest FW version according to: https://www.playstation.com/en-us/support/system-updates/ps3/
List of changes:
・ Updated blu-ray keys for new movie releases
・ Minor security fix
2020-12-03 18:16:38 +01:00
Nekotekina 13a0b88755 atomic.cpp: improve hashtable access
Simplified, tried to use all ptr bits.
Try to prevent self-collisions (bug).
Hashtable size doubled (to 8 MiB).
2020-12-01 10:19:31 +03:00
Nekotekina 32f39fec1c Make cpu_counter::remove() async
Remove both mutex and assertion from it.
2020-12-01 10:18:41 +03:00
Nekotekina cad3a6c547 sceNp.cpp: fix some UTF-8 string mismatch 2020-11-30 03:21:34 +03:00
kd-11 2aa5c437e8 rsx: Fix upscaled image reconstruction
- Base the upscaling on the real source and not the "attr" parameter.
- In case of reconstruction, the source is much larger than the subslice in "attr"
2020-11-30 01:20:17 +03:00
kd-11 67f48ce21c rsx: Fix uncaught depth-func changes
- Depth func of always or never usually disqualifies depth testing.
  Invalidate contested surfaces when depth func is changed.
2020-11-30 00:46:36 +03:00
kd-11 845a7d9968 Fix RSX replay thread lifecycle 2020-11-29 22:39:52 +03:00
Dylan Fenn 924774d3ef Add missing Fedora dependancy to BUILDING.md 2020-11-29 21:41:03 +03:00
Nekotekina e0635cf65c Remove unneeded non-ASCII character (unedat.cpp) 2020-11-29 16:18:22 +03:00
Nekotekina 3b8e3a9714 stdafx.h: remove BOM from custom included headers
Also add warnings about adding them.
2020-11-29 15:35:05 +03:00
Nekotekina 2bee096246 Try to set 2-3 GiB working space and show error if it's failed (Windows) 2020-11-27 14:49:07 +03:00
Nekotekina 872655369a shared_ptr.hpp: fix critical bugs
Fix array initialization.
Fix reference counting.
Fix offset to refctr.
Add some features.
2020-11-27 14:32:41 +03:00
Nekotekina 0892758994 Minor debugging enhancement
Use raise(SIGTRAP) in failed SIGSEGV handling and return.
2020-11-26 20:11:26 +03:00
Nekotekina 22a24446c1 Threads: fix minor race
Has already been in "fixed" state in past...
2020-11-26 20:11:26 +03:00
Nekotekina b5d498ffda Homebrew atomic_ptr rewritten (util/shared_ptr.hpp)
It's analogous to C++20 atomic std::shared_ptr

The following things brought into global namespace:
single_ptr
shared_ptr
atomic_ptr
make_single
2020-11-26 20:11:26 +03:00
Nekotekina bd90e3e37f atomic.cpp: shrink and simplify main hashtable
Reduce collision detection to 1 or 0 for now.
I think it should be offloaded to notifiers.
2020-11-26 20:11:26 +03:00
Nekotekina 8b6d615aa6 atomic.hpp: remove/deprecate incomplete notify features
Notification with "phantom value" could be useful in theory.
As an alternative way of sending signal from the notifier.
But current implementation is just useless.
Also fixed slow_mutex (not used anywhere).
2020-11-26 06:31:36 +03:00
Megamouse 9e352da052 Handle some undefined behavior regarding null pads 2020-11-26 00:45:49 +01:00
Nekotekina ca9898e838 JIT: increase likeliness of allocating 2M large pages
On top of enabled transparent hugepages hint (Linux).
2020-11-25 10:41:17 +03:00
Nekotekina 95b8467a76 perf_meter.hpp: move logic to noinline function
May improve performance if perf meter is disabled.
2020-11-25 10:41:17 +03:00
Nekotekina 2b674d4d8c utils::shm: allow 2M hugepages on demand 2020-11-25 10:41:17 +03:00
Nekotekina 487b572aa6 Linux: remove assertions on MADV_HUGEPAGE
It's a hint and is allowed to fail.
2020-11-25 10:41:17 +03:00
Nekotekina 600c0ea5ba atomic.cpp: fix windows/std path
Always check condition after rearming internal semaphore.
2020-11-25 10:41:17 +03:00
Nekotekina 00e64920c8 Implement "slow mutex" without spin-waiting.
Benefits: only 1 byte.
Testing atomic wait.
2020-11-25 10:41:17 +03:00
Megamouse 9efedbe76a Minor changes related to Emu.Stop() 2020-11-25 00:11:07 +01:00
Nekotekina d8e9382573 asm.hpp: constexpr refactoring
Removed asm (what an irony), made many functions constexpr.
Removed some unused function, readding them should be trivial.
2020-11-24 13:20:40 +03:00
Nekotekina ab248e170c vm_native.cpp: add MADV_HUGEPAGE
It enables Transparend Huge Pages for some regions on Linux.
Although it can't be actively useful, it seems to do something.
Maybe it's even harmful for recompilers.
2020-11-24 12:31:11 +03:00
Nekotekina 27097cbcfe atomic.hpp: alter atomic_storage<>::store a bit
Always fallback to exchange. May improve codegen on gcc.
2020-11-24 12:31:11 +03:00
Nekotekina 43952e18e2 Implement prefetch_write() and prefetch_exec() wrappers
Do some refactoring to prefetch_read() in util/asm.hpp as well.
Make all these function constexpr because they are no-ops.
2020-11-24 12:31:11 +03:00
Megamouse 5076da8f77 Fix auto exit
- Don't quit on stop if force boot was set
- Don't stop the emulator on gs_frame close when it was already stopped. This would remove the force boot flag by mistake.
2020-11-24 11:17:03 +03:00
kd-11 8228a4adcd gl: Disable depth test before rendering text to the backbuffer which does have a Z buffer 2020-11-24 11:10:43 +03:00
Nekotekina 721883f64e Azure: attempt to produce clang artifact 2020-11-24 08:11:45 +03:00
Nekotekina b55c759f71 Remove any mentions of scam CI 2020-11-24 08:11:45 +03:00
Eladash 3f028fbb83 Fix SPU LS MMIO 2020-11-24 03:44:30 +03:00
Nekotekina f0cba1371c vm: adjustments
Increase max range lock size (less than 512 MiB)
Remove "range_executable" flag, make it reserved.
2020-11-24 01:09:04 +03:00
Nekotekina 14fa96fdef atomic.cpp: don't use empty notify callback
Instead, allow setting it to null and check for null.
Similar could be done for wait cb, but it's set for all named threads.
2020-11-24 01:09:04 +03:00
Nekotekina b954a41f2a Threads: minor simplification 2020-11-24 01:09:04 +03:00
kd-11 f1c65dcefc vk: Improve support for RDNA
- Add support for RDNA2
- Add RDNA MSAA workaround
2020-11-23 19:20:00 +03:00
Nekotekina d4c17ecda5 Simplify communication with thread pool
Add "entry_point" member to "thread_base".
Don't use "m_thread" to exchange values.
2020-11-23 11:32:34 +03:00
Nekotekina a4458e2c8c Clean thread pool at exit.
Execute TLS destructors.
Test atomic wait list.
2020-11-23 10:20:42 +03:00
Nekotekina 16cc88dd0e atomic.hpp: fix atomic_wait::list regression
Typo-regressions. Also improve static asserts.
2020-11-23 09:26:25 +03:00
Nekotekina 280f5f0b54 atomic.hpp: redefine op::ne to actually mean "not equal"
WTF is "native endianness", it's native by default.
2020-11-23 09:24:16 +03:00
Nekotekina e38eaa7cd7 Remove old travis badge (kill it with fire) 2020-11-23 09:22:51 +03:00
Zion Nimchuk a27bd2275c Pushing master AppImage Artifacts to GitHub Releases via Azure 2020-11-23 06:50:27 +03:00
Nekotekina 7d00c69a4f Attempt 2: Try to make Azure push linux builds 2020-11-22 19:24:54 +03:00
Nekotekina a2c189b45a Azure: try to deploy GCC artifact (upload to github) 2020-11-22 18:29:46 +03:00
Nekotekina 41320688b7 Removed .travis.yml
Non-functional CI
2020-11-22 17:03:35 +03:00
Nekotekina f85c8584b0 Attempt to fix #9316 2020-11-22 12:57:50 +03:00
Nekotekina 6cf50f8f6c Second attempt to fix hanging RPCS3 process
Now fix exit logic a bit.
Remove Init() call from Stop().
Remove Stop() call from Quit().
2020-11-22 12:45:19 +03:00
Nekotekina d70ab11477 atomic.cpp: remove redundant constexpr
Static initialization is all-zeros anyway.
But constexpr was killing my intellisense.
And probably also affected compile time.

Also make some internal structures hidden ("static").
2020-11-22 12:07:49 +03:00
kd-11 cab4c78b7b rsx: Some shader compiler threads tuning
- Allow more threads for wide CPUs
- Simplify 'auto' selection a bit
2020-11-21 20:43:15 +03:00
kd-11 14358d5e84 qt: Add shader compiler threads to GUI 2020-11-21 20:43:15 +03:00
kd-11 7553429130 gl: Thread shader source compilation dispatch
- glCompileShader is in itself much slower than anticipated
2020-11-21 20:43:15 +03:00
kd-11 3ddfa288cf rsx: Use multithreaded shader compiler backend 2020-11-21 20:43:15 +03:00
Nekotekina e89a568765 Attempt to fix Emu.Quit()
There was some kind of "initialization order fiasco" of g_fxo.
Not only should it be used after main, but also destroyed before exit.
2020-11-21 18:27:16 +03:00
Nekotekina 71f1021648 Fix thread pool entry point and get_cycles()
Fix possible race between thread handle availability.
Don't treat zero thread as invalid one.
Now entry point is full is assembly.
Attempt to fix #9282
Also fix some TLS.
2020-11-21 17:18:42 +03:00
Nekotekina 60cff6f3d4 Attempt to fix #9271 2020-11-21 07:09:48 +03:00
Nekotekina 5f010c2f4c atomic.cpp: optimize "cond" allocation with TLS
Billions of events can reduce to thousands, saving CPU time a few s.
Only 4 slots are available (arbitrarily), and only 1 is usually used.
Other slots are used only for waiting on multiple atomics.
2020-11-20 19:13:22 +03:00
Nekotekina c0f3d1f06d Basic constexpr support for u128 (MSVC)
Added explicit conversion op to u64.
Added constexpr path for +,-,>>,<< ops.
Make almost all methods constexpr.
Removed a lot of redundancy.
2020-11-20 15:04:17 +03:00
Nekotekina 6c18e00977 atomic.cpp: use deterministic "cond" allocation
Takes ~80 ns instead of ~40 ns, same about deallocation.
Loops don't exist here, only 4-level semaphore tree.
Worst case only happens with concurrence, not from looping.
This optimization is not really necessary at current state of RPCS3.
This is more like to test C++ compilers and MSVC u128 implementation.
2020-11-20 15:04:17 +03:00
Nekotekina 72ac1aa537 atomic.cpp: use some actual hash for hashtable (std::minstd_rand)
Should only take about 5ns for initialization.
Should also make collisions almost impossible.

I also suspect I fixed some bad bug in process...
2020-11-20 15:04:17 +03:00
Nekotekina 5bcaa25c02 CPU: remove descheduled threads from suspend_all list 2020-11-20 13:53:34 +03:00
Eladash 85880ffded SPU: Log STOP full opcode (#9292)
Co-authored-by: Ani <ani-leo@outlook.com>
2020-11-20 13:53:16 +03:00
Megamouse 5b207c3b95 hotfix for infinite loop when booting game data 2020-11-19 23:53:10 +01:00
Megamouse 3087f15dd8 Update disc boot detection and hope it works 2020-11-19 21:55:06 +01:00
Nekotekina 36f1193497 Fix u128 type on MSVC (subtraction, minus)
All subtraction operations were broken.
2020-11-19 16:38:06 +03:00
Nekotekina 292af1e4cd CPU: use u128 in bit counter
Apparently, u64 was not enough.
2020-11-19 16:05:08 +03:00
Nekotekina d4d5dc99f3 Fix perf_meter<> after adding thread pool.
Print and reset sorted information after emulation stop/pause.
Print useless average value.
2020-11-19 14:44:58 +03:00
Nekotekina 3e1344e4e4 vm.cpp: minor optimization for filling stack guards
Use REP STOSQ on all compilers.
2020-11-19 14:44:58 +03:00
Nekotekina 6d37bc62a5 CPU: remove cpu_counter from g_fxo
Convert it to a namespace, simplify add/remove functions.
Don't add() threads just creates, they are trapped in check_state() anyway.
Don't add() threads which are leaving check_state() because stopped.
2020-11-19 09:46:22 +03:00
Nekotekina e9f7c100a0 CPU: update suspend interface (dummy) 2020-11-18 19:15:56 +03:00
Nekotekina 190676c982 CPU: Fix g_suspend_counter waiting logic 2020-11-18 14:38:01 +03:00
Eladash 28cbba5a7d SPU LLVM: fix AND instruction family (#9290)
Incorrect immediate test (looks like copypasta)
2020-11-18 14:36:26 +03:00
kd-11 0e7a705254 rsx: Resolution scaling overhaul
- Enforce square pixels instead of per-axis scaling
2020-11-18 09:29:34 +03:00
Nekotekina 68931b4c43 Debugger: fill stack guard with STACKGRD 2020-11-17 16:32:59 +03:00
Nekotekina a4e28df9cf Update hidapi 2020-11-17 15:40:09 +03:00
Nekotekina 65c81c5e83 Fix memory viewer for SPU LS 2020-11-17 15:22:04 +03:00
Nekotekina ccd0d2046d SPU: increase max SPU count
According to max SPU TG count.
2020-11-17 15:22:04 +03:00
Nekotekina 0fec99e75b SPU: absolutely unacceptable hack for SPU LS
Make normal threads inaccessible in PS3 memory.
2020-11-17 15:22:04 +03:00
Nekotekina f8d1f070f5 sys_memory: HORRIBLE HACK for sys_memory_get_page_attributes 2020-11-17 15:22:04 +03:00
Nekotekina 3dd48a24ce atomic.cpp: remove tiny redundancy 2020-11-17 15:22:04 +03:00
Nekotekina 984e97cbdc Potential fix for Linux compilation 2020-11-17 15:22:04 +03:00
Eladash 50ea1a12c9 Debugger: Fix scrolling in first registers panel 2020-11-17 09:39:39 +01:00
Eladash 992a372fc7 cellGame fixes 2020-11-17 09:04:35 +01:00
Nekotekina d789250976 Add thread_ctrl::get_thread_stack
Returns addr and size of current thread's stack.
2020-11-17 05:33:46 +03:00
Nekotekina d7e1cf7dd2 vm: respect initial protection for allocation mapping
Unused yet.
2020-11-17 05:33:46 +03:00
Nekotekina ea5f5aea5f vm: memory locking rewritten
Added vm::lock_sudo method (wrapper for utils::memory_lock).
Put locking outside of vm::g_mutex scope.
Prelock sudo memory for RSX, vm::stack, vm::main.
Prelock sudo memory for shared memory objects.
Don't check for TSX path.
2020-11-16 12:46:15 +03:00
Nekotekina eaf0bbc108 SPU: don't allocate SPU LS in vm::main
Create its own shared memory object.
Use vm::spu to allocate all SPU types.
Use vm::writer_lock for shm::map_critical.
2020-11-16 12:46:15 +03:00
Eladash b1710bb712 SPU Debugger: Implement float registers view + General debugger fixes (#9265)
* SPU Debugger: Fix try_get_insert_mask_info
* Debugger: Always update thread state on context's data change
No longer needing to press on thread's instructions for actions to work!
2020-11-15 08:45:28 +03:00
Nekotekina dfae7bd073 SPU: Fix some stat printing 2020-11-15 04:41:16 +03:00
Nekotekina 333fe9a561 atomic.cpp: fix notification on windows 2020-11-15 04:40:44 +03:00
Nekotekina badb3dc2dd atomic.cpp/threads: remove old wait callback
Add new wait callback which simply collects statistics.
Shift workarounds towards actual problem detection.
2020-11-14 18:16:27 +03:00
Nekotekina 3ac819ee70 atomic.cpp: fix waiting on multiple variables
Silly bugs are so silly...
2020-11-14 17:25:02 +03:00
Nekotekina 00f877e812 atomic.cpp: fix rare overload scenario
If slot allocation fails, increase reference counter in every slot.
This prevents search routine from "losing" some slots.
2020-11-14 13:56:23 +03:00
Nekotekina 1e269751bf Temporarily disable memory locking if TSX is not used
It's a very heavy operation that could cause some problem under mutex lock.
2020-11-14 11:12:58 +03:00
Nekotekina 5b69eda39a Fix suspend_all bug (TSX, TSX-FA)
Could cause freezes.
2020-11-14 10:56:05 +03:00
Nekotekina 71ca413067 Don't add lonely cpu_flag::memory on TSX path (bug) 2020-11-14 09:03:33 +03:00
Nekotekina 0c7f9458c0 Fix thread pool resource management.
Make sure no tail call happens (change ret address to a trampoline).
Make sure thread handles don't leak if the pool is full.
2020-11-13 17:17:45 +03:00
Nekotekina ab365fe494 Fixed thread pool a bit
Use 128-bit allocator instead of queue.
When pool is full (128), threads just terminate as before.
2020-11-13 13:32:44 +03:00
Nekotekina e48f160a29 atomic.cpp: continuation of fixing all-ones masks
Also added missing const noexcept.
2020-11-13 12:40:02 +03:00
Nekotekina cfda4d0ade atomic.cpp: optimize raw_notify() for unspecified pointer mode
Remove unnecessary optimization from cond_alloc().
Optimistic case was absolutely dominating anyway.
Although the whole function is a dirty hack.
Now scanning through all threads is faster.
2020-11-13 07:05:33 +03:00
RipleyTom debfae06a8 Improve disconnected state handling of dns queries 2020-11-13 07:05:06 +03:00
RipleyTom e6f2f8ad0d Add some error checking in sceNp2.cpp 2020-11-13 05:28:00 +03:00
Nekotekina 67785a918c Implement simple thread pool 2020-11-13 03:32:24 +03:00
Nekotekina 50d80c64fa Add .gdbinit config file
Set to ignore SIGSEGV and SIGPIPE signals.
2020-11-12 23:43:38 +03:00
RipleyTom 1378645413 Adds SIGPIPE to ignored exceptions(unix) 2020-11-12 07:08:59 +03:00
Nekotekina 3888b0429c atomic.cpp: print some stats on stop 2020-11-12 05:52:22 +03:00
Nekotekina 70761a4ef0 atomic.cpp: fix notification bug from few commits before
Make sure forced notification ignores mask comparison.
Also fix masks provided by smaller types to correct ones.
2020-11-12 05:01:44 +03:00
Nekotekina e37df998e9 atomic.cpp: minor optimization
Silly MSVC emits unnecessary initialize-on-first-use code guards.
Didn't check other compiler. But workaround just works anyway.
2020-11-12 03:41:19 +03:00
Nekotekina c30cdfb3a7 atomic.cpp: merge more atomic variables for simplicity
Compress 16-bit ref counter and two 48+64 bit slot allocators.
This allowed to remove some weird unnecessary logic paths.
Adjust hashtable size to keep it the same.
2020-11-12 03:39:05 +03:00
Nekotekina 350b704cd7 atomic.cpp: combine two atomics (ref ctr and wait ptr)
Should fit into cache line perfectly.
Also makes ptr check more robust.
2020-11-12 01:06:12 +03:00
Nekotekina ad013d59f4 atomic.cpp: don't load actual memory on empty mask
It's not an optimization. It just allows some tricks safely.
2020-11-11 23:59:09 +03:00
Nekotekina d391133524 atomic.cpp: minor notification improvement
Check mask before locking the reference.
Can help to not bother non-eligible waiters.
2020-11-11 23:51:41 +03:00
Nekotekina 4b823469f7 atomic.cpp: restore notify_all() behaviour
Restore batch notification with non-blocking attempts.
2020-11-11 22:43:13 +03:00
Nekotekina 7cd1e767be atomic.cpp: implement some atomic wait operations.
Instead of plain waiting while equal to some value,
it can be something like less, or greater, or even bitcount.
But it's a draft and untested. Hopefully doesn't break anything.
2020-11-11 20:46:37 +03:00
Eladash 829a697c39 Fix vm::check_addr calls in Thread.cpp 2020-11-11 17:40:46 +03:00
Eladash fefab50e06 Fix vm::range_lock, imporve vm::check_addr 2020-11-11 10:30:09 +03:00
Eladash 6e27ab60ca Registers Editor: Implement SPU/PPU register value broadcast 2020-11-11 10:27:45 +03:00
Eladash 74274f6d77 Debugger: Improve SPU/PPU vector registers 2020-11-11 10:27:45 +03:00
RipleyTom 908b2703f3 Fix missing controller mapping 2020-11-11 07:16:45 +03:00
Nekotekina c047ab6147 atomic.cpp: waitable atomics got brutally rewritten
Hashtable increased and flatten, tree-alike extensions removed.
Some things simplified, so it can actually decrease perf a bit.
But most platforms shouldn't be affected.
Removed limit of 56 waiters per pointer.
Real limit now is about 65535.
2020-11-11 05:35:27 +03:00
Eladash 52fa69d93d SPU Debugger: Improve registers panel 2020-11-10 22:51:52 +03:00
RipleyTom a83df01bfd rpcn 0.3.5 (#9227) 2020-11-10 08:55:49 +00:00
Eladash b32d989a10 Fix PPU stack contents on allocation 2020-11-10 06:30:35 +03:00
Nekotekina d1ee7c651f Make memory locking optional (mlock, VirtualLock).
Fix desired locking operation (to fix "sudo" memory).
It was discovered that some systems have outdated configuration.
With too tight limit, it's almost impossible to lock anything in memory.
2020-11-10 06:05:37 +03:00
Nekotekina dcbe8ef5f4 Import VirtualAlloc2 if available (Win10+)
Import MapViewOfFile3 as well.
Unused, this crap is tricky.
2020-11-10 03:04:38 +03:00
Nekotekina bd5253047b Improve DYNAMIC_IMPORT
Don't call get_proc_address every time if if failed.
Also rename Utilities/dynamic_library.h to util/dyn_lib.hpp
2020-11-10 01:44:31 +03:00
Nekotekina cdaa8cb5c4 CPU: Improve suspend_all g_suspend_counter handling
Increase in two stages, giving more chances to use it.
Second stage is when all wait flags have been seen.
2020-11-09 23:54:36 +03:00
Nekotekina 083397a555 vm: lock memory under "sudo" addr
Remove memory touching from transactions.
2020-11-09 23:54:36 +03:00
Nekotekina e98eb4659e Implement utils::memory_lock 2020-11-09 22:57:36 +03:00
Nekotekina d1988d384c vm: remove unnecessary memset() on stop 2020-11-09 22:57:36 +03:00
Nekotekina bc61835d97 CPU: use unsigned (u8) priority in suspend_all 2020-11-09 22:57:36 +03:00
RipleyTom 8a50880613 Fix path not being saved on install pkgs 2020-11-09 14:23:54 +03:00
Nekotekina b05d12df0e Hotfix for shm->map_self()
Make sure mmap returns 64K-aligned results, as on Windows.
2020-11-08 22:15:59 +03:00
Nekotekina 733b46d51a sys_semaphore: add state check to sys_semaphore_get_value
Also to sys_semaphore_create, although we don't do it.
2020-11-08 19:03:41 +03:00
Nekotekina 8bc9868c1f SPU/vm: Improve vm::range_lock a bit
Use some prefetching
Use optimistic locking
2020-11-08 17:23:17 +03:00
Nekotekina 3507cd0a37 SPU: improve spu_thread::reservation_check
Use optimistic locking and optimistic loop (expecting 1 iteration).
2020-11-08 16:43:15 +03:00
Nekotekina 21ec32b465 vm: implement g_shmem for range locks
Renamed from g_shareable. Contains pointers instead of bits.
Used in range locks to prevent any "collision" between memory.
2020-11-08 16:43:15 +03:00
Nekotekina 1c99a2e7fb vm: add map_self() method to utils::shm
Add complementary unmap_self() method.
Move VirtualMemory to util/vm.hpp
Minor associated include cleanup.
Move asm.h to util/asm.hpp
2020-11-08 16:43:15 +03:00
Nekotekina b68bdafadc vm: refactor vm::range_lock again
Move bits to the highest, set RWX order.
Use only one reserved value (W = locked).
Assume lock size 128 for range_locked.
Add new "Size" template argument that replaces normal argument.
2020-11-08 16:43:15 +03:00
Eladash bacfa9be19 Debugger fixups (#9226)
Fix logic error in callstacks handling code, always set first to false after first iteration.
 Add explicit check for zero return addresses. Current code validity checks may not check for it properly when it sits on interrupt handler entry point (which may contain valid code).
 Do not allow 0x3FFF0 to be a back chain address because it needs space for LR save area, only 0x3FFE0 and below satisfy this criteria.
2020-11-08 16:42:20 +03:00
Eladash 5265eb81e0 kernel-explorer: Add basic process info 2020-11-08 09:17:13 +03:00
Eladash 516da4ecdd Debugger: Improve SPU/PPU callstack handling 2020-11-08 09:17:13 +03:00
Megamouse 6fcc68699a unify patch log 2020-11-07 19:22:40 +01:00
Eladash 3cb5fd8ebc Debugger: Implement SPU callstack, fix PPU callstack 2020-11-07 20:45:57 +03:00
Nekotekina fd7ea82965 atomic.cpp: fix 3-arg notify functions
Third arg forces comparison with itself, and possibly forced wakeup.
2020-11-07 19:18:14 +03:00
Nekotekina 0bd989b118 atomic.cpp: allow waiting on multiple variables simultaneously
Arbitrary maximum set to 8, but really we need 2, maybe 3.
Added atomic_wait::list object for multi-waiting.
Added atomic_wait::get_unique_tsc just in case.
2020-11-07 18:18:02 +03:00
Nekotekina bd0b292b39 atomic.cpp: adjust assumed pointer mask
Increase waiter mask (allow 65535 waiters).
Assume 47-bit pointers instead of 48-bit.
2020-11-07 15:08:46 +03:00
Nekotekina 31f0a0c064 atomic.cpp: add minor safety check 2020-11-07 15:08:46 +03:00
Nekotekina 3e445eff8e atomic.cpp: maintenance of wait() function
Move hashtable allocation into another function.
2020-11-07 15:08:46 +03:00
Eladash 6dcd482dd0 SPU reservations: Do not illegally dereference reservation data 2020-11-07 14:03:09 +03:00
Morgan Creekmore a28ab0a408 Set AccountAge to 18 to fix age restriction checks, fix incorrect logged function name (#9218) 2020-11-07 09:47:44 +00:00
Megamouse a3eb5c2d63 More Header cleanup 2020-11-06 22:14:05 +01:00
Jan Beich e2303f3378 CI/FreeBSD: switch TravisCI to Clang 11 2020-11-06 18:20:23 +00:00
Jan Beich acb17b0298 CI/FreeBSD: enable on TravisCI as ccache works nowadays 2020-11-06 18:20:23 +00:00
Jan Beich fde7cf1fab CI/FreeBSD: switch CirrusCI to 12.2-RELEASE 2020-11-06 18:20:23 +00:00
Jan Beich c2cb7e1004 CI/FreeBSD: avoid downloading commit history in submodules 2020-11-06 18:20:23 +00:00
Jan Beich 4075f5c497 CI/FreeBSD: clear ccache stats, so new hits are easier to notice 2020-11-06 18:20:23 +00:00
Jan Beich debd44fa9b CI/FreeBSD: stop forcing ccache after f528aada24 2020-11-06 18:20:23 +00:00
Nekotekina 0a5742587a atomic.cpp: upgrade raw_notify()
Now it searches all semaphores if data arg is nullptr.
Also it tries to wake up all threads if thread_id is 0.
2020-11-06 17:15:40 +03:00
Nekotekina ad4df2d946 atomic.cpp: refactor native signaling functions
Add native_alert() and try_native_alert()
2020-11-06 17:15:40 +03:00
Nekotekina bfe9580551 atomic.cpp: fix cond_handle data structures
Fix a critical bug with possible id out of range.
2020-11-06 16:56:59 +03:00
Nekotekina 1e45437498 Remove unused atomic with lock bit 2020-11-06 16:48:43 +03:00
Ani f9c8f78000 llvm: Update submodule (Zen3 workaround) (#9212) 2020-11-06 11:41:51 +00:00
RipleyTom 4554eedd19 Extend timeout on travis 2020-11-06 13:54:59 +03:00
Nekotekina 557f0c5a8a atomic.cpp: remove load() from notify functions
Only compare masks for overlap for second overload (with mask provided).
Explicit "new value" can be provided in new 3-arg overloads.
Also rename atomic_storage_futex -> atomic_wait_engine.
2020-11-06 04:44:31 +03:00
Nekotekina 9fb8d449fe atomic.cpp: more improvements
Add ref counters for internal semaphores for concurrent notifying.
Lack of them could result in loss of notification.
2020-11-06 00:14:53 +03:00
Nekotekina 1bb7c74c93 atomic.cpp: various cleanups and fixes
Add pointer comparison to notifiers (to prevent spurious wakeups).
Fix a bug with a possible double notification in raw_notify().
Fix a bug with incorrect allocatin bit slots for cond_handle.
Add a semaphore counter to track max allowed number of threads.
Use #define for some constants to STRINGIZE them in errors.
Add some error messages when certain limits are reached.
Fix a bug with a wrong check simply throwing std::abort.
Use "special" notify_all patch with batch processing for every arch.
Fix Win7 bug who no one probably noticed.
2020-11-06 00:10:16 +03:00
Nekotekina cc07e5306e Improve shared_mutex
Wait/notify only on c_sig, should reduce spurious wakeup noise.
2020-11-06 00:10:16 +03:00
Nekotekina 34fa010601 Improve cond_var notifiers
But nobody uses it anyway, so clean up includes.
2020-11-06 00:10:16 +03:00
Nekotekina 7d56069243 Fix HAS_OVERCOMMIT usage in JIT.cpp 2020-11-05 18:50:19 +03:00
Nekotekina fc77fb9b4c Update LLVM commit id 2020-11-05 06:45:43 +03:00
Nekotekina ebdf93e5dc Fix 1 warning in MSVC 2020-11-05 06:45:01 +03:00
Nekotekina 5248240e10 atomic.cpp: improvements.
Reduced static memory amount for waitable atomics.
Allow notifier to skip notifications if wait/notify masks don't overlap.
Improve raw_notify to wake up the thread by its id, add thread_id arg.
Add optional mask argument to notify_one() and notify_all().
2020-11-05 05:51:43 +03:00
Nekotekina b66628baca Improve low-level mmap utilities (Linux/BSD)
Add madvise (MADV_WILLNEED) on utils::memory_commit
Add madvise (MADV_FREE or MADV_DONTNEED) on utils::memory_decommit
Improve shm_open pseudo-random name (not used on Linux)
2020-11-04 14:59:26 +03:00
Nekotekina ba5ed5f380 Fix vm::lock_range wrong check
Minor header refactoring.
2020-11-04 14:59:26 +03:00
Nekotekina 8d5e119582 Improve cpu_flag::temp handling
Ignore cpu_flag::suspend
Ignore cpu_flag::signal
2020-11-04 14:59:26 +03:00
Nekotekina d022e7cd27 sys_prx: add cpu_flag::wait 2020-11-04 14:59:26 +03:00
Nekotekina 5d7acda80e vm: minor refactoring
Renamed internal main range locking method.
2020-11-04 14:59:25 +03:00
Nekotekina 9b595c68a5 Fix some switch warnings 2020-11-04 14:59:25 +03:00
Nekotekina 2d38d8a639 Fix NEVER_INLINE attribute
Similarly to FORCE_INLINE, it doesn't imply inline on some compilers.
2020-11-04 14:59:25 +03:00
Nekotekina dea8aa675a Optimize cpu check_state() a bit
Move cpu_flag::dbg_pause check from the start.
To the moment before it actually goes to sleep.
2020-11-04 14:59:25 +03:00
Megamouse 027eba2b59 Add Quadro to fast version of VK get_driver_vendor 2020-11-04 12:13:56 +01:00
Megamouse 91b8e7504e Set some things to log level always 2020-11-04 12:13:56 +01:00
Megamouse 088931525d Add option to log qDebug 2020-11-03 06:42:51 +01:00
Megamouse ef9638e094 Log Qt version 2020-11-03 06:42:51 +01:00
Ani 09a9d08466 rpcs3_version: Bump to 0.0.13 (#9192) 2020-11-02 20:20:12 +00:00
Nekotekina 1b8bf081b5 Upgrade to LLVM 11 Stable 2020-11-02 21:23:25 +03:00
Nekotekina 06ecc2ae68 vm::range_lock cleanup and minor optimization
Removed unused arg.
Linearized some branches.
2020-11-01 23:29:33 +03:00
Nekotekina 46d3066c62 Optimize vm::range_lock
Only test address on `range_locked`
Don't check current transaction
Remove vm::clear_range_locks completely
2020-11-01 16:46:06 +03:00
Nekotekina 8d12816001 TSX: fix transaction limit settings 2020-11-01 14:58:04 +03:00
Nekotekina fe03b55046 TSX: tiny optimization of transaction functions
Because new memory manager puts them in first 2G.
2020-11-01 14:44:59 +03:00
Nekotekina ca57f25f26 Fix vm::page_protect and range flags
Should fix assertion in vm.cpp
Minor refactoring of internal locking
2020-11-01 02:30:10 +03:00
Eladash 3c639ff8e1 SPU: Fix Accurate DMA edge case 2020-11-01 00:35:48 +03:00
Nekotekina 78c986b5dd Improve vm::range_lock
Not sure how it ever worked
Clear redundant vm::clear_range_lock usage
2020-10-31 23:53:14 +03:00
Megamouse a42663b09b Qt: Pass events to dialog when not remapping 2020-10-31 20:44:09 +01:00
Megamouse 36149fd986 overlays: kinda fix performance graph margins (#9181) 2020-10-31 16:32:31 +00:00
Eladash c2c559f8d9 Disasm: do not allow to access previous instructions in non-interpreter mode 2020-10-31 17:15:47 +03:00
Eladash 5e8419af0d SPU Debugger: SHUFB insertion patterns 2020-10-31 17:15:47 +03:00
Nekotekina 86fc842c89 TSX: new fallback method (time-based)
Basically, using timestamp counter.
Rewritten vm::reservation_op with the same principle.
Rewritten another transaction helper.
Add two new settings for configuring fallbacks.
Two limits are specified in nanoseconds (first and second).
Fix PUTLLC reload logic (prevent reusing garbage).
2020-10-31 15:34:14 +03:00
Nekotekina 80530e8aef vm: rename g_addr_lock to g_range_lock
Reduce size to 29 bits and use 3 bits to communicate some information.
This information can be used to to a very cheap lock-free access tests.
2020-10-31 15:08:49 +03:00
Nekotekina ba26e16411 Rename vm::reservation_light_op -> light_op
Rename vm::reservation_peek_op -> peek_op
Also remove overkill assertion for cpu_flag::temp.
2020-10-31 15:08:49 +03:00
Megamouse 2cee26c3e7 Cleanup some includes 2020-10-31 11:53:46 +01:00
Megamouse 5d55e509ec cellSubDisplay: Add some constants (#9178) 2020-10-31 01:40:38 +00:00
Megamouse 4984e87776 implement interception for cellKb and cellMouse
this needs to be tested
2020-10-31 02:11:27 +03:00
Megamouse c65b7d0aea HLE: Add some constants 2020-10-31 02:11:27 +03:00
Megamouse 54fd224fd8 Add License Area Setting 2020-10-31 02:10:30 +03:00
Megamouse 5ca2b1200d Qt: Fix Resolution combobox default value 2020-10-31 02:08:42 +03:00
Eladash b5014d56ab rsx: Fix transform contants load 2020-10-31 02:08:03 +03:00
Nekotekina c4e89f8bb4 Actually start rsx replay thread 2020-10-30 22:25:33 +03:00
Nekotekina 7dd85b207f vm: optimize range lock slot allocations
Doesn't seem to need a barrier.
2020-10-30 22:20:20 +03:00
Nekotekina cb0431d960 sys_fs/sys_usbd: add cpu_flag::wait 2020-10-30 20:14:32 +03:00
Nekotekina 58adb6a1aa sys_ppu_thread: add cpu_flag::wait 2020-10-30 18:27:15 +03:00
Nekotekina 13c564f2af sys_memory: add cpu_flag::wait 2020-10-30 18:09:30 +03:00
Nekotekina 95aeebe4b5 sys_rsx: add cpu_flag::wait 2020-10-30 18:00:25 +03:00
Nekotekina 605d57c541 sys_event: cleanup (replace vm::temporary_unlock)
Also made minor changes in sys_rsx.cpp.
Removed unused exception std headers.
2020-10-30 17:49:07 +03:00
Nekotekina f972fa26a4 Derive RSX Replay thread from cpu_thread
Its id is set to 0, so fix some id_type() usages.
2020-10-30 17:36:11 +03:00
Nekotekina 150e18539c Allow cpu_thread& arg passed to the syscalls
Minor cleanup. cpu_mem(), cpu_unmem() removed.
2020-10-30 17:03:32 +03:00
Eladash f03d4cf8fd PPU: Optimize reservation load for success 2020-10-30 10:49:47 +02:00
Nekotekina 3419d15878 vm: add extern clear_range_locks function
Allows to wait for range locks to clear for specified range.
vm::range_lock now monitors specified reservation lock as well.
2020-10-30 07:58:16 +03:00
Nekotekina 0da24f21d6 CPU: improve cpu_thread::suspend_all for cache efficiency (TSX)
Add prefetch hint list parameter.
Workloads may be executed by another thread on another CPU core.
It means they may benefit from directly prefetching the data as hinted.
Also implement mov_rdata_nt, for "streaming" data from such workloads.
2020-10-30 05:22:09 +03:00
Nekotekina e794109a67 perf_meter.hpp: fix double rdtsc bug, add restart() method 2020-10-30 03:19:13 +03:00
Nekotekina 006c783aba SPU: make do_dma_transfer() static with _this arg
Instead of this, nullptr will be passed from another thread.
MMIO via MMIO is disabled if it even possible.
2020-10-30 02:58:39 +03:00
Nekotekina 4378a09867 PPU: reload old data on STCX failure
In 128-byte reservation mode, it can reload the whole cache line.
2020-10-30 02:58:39 +03:00
Nekotekina fb24b06a5d PPU: add LARX perf counter
Also refactor ppu_store_reservation a bit.
2020-10-30 02:58:39 +03:00
Nekotekina 425fce5070 SPU: load previous data on PUTLLC failure
Since it will most likely execute GETLLAR to load it again.
Only implemented for TSX at moment.
2020-10-30 02:58:39 +03:00
Nekotekina d5667a859a CPU: improve cpu_thread::suspend_all (TSX)
Try to make more clever busy-waiting on cpu_flag::pause.
2020-10-30 02:58:39 +03:00
Nekotekina 95dbcf2fd7 Logs: add callback for cpu_thread to set cpu_flag::wait
May improve waiting time in critical suspend_all ops.
2020-10-29 18:57:57 +03:00
Nekotekina 8ce0819b42 SPU: add stx/ftx counters
Just count pure transaction successes and failures.
2020-10-29 18:57:57 +03:00
Nekotekina 688a456642 TSX tweaks
Allow to do more in first-chance transactions.
Give PUTLLC +1 priority (minor change).
2020-10-29 18:57:57 +03:00
Megamouse 59b3a3d26b Qt: Add "Configure Game Patches" to game list (#9154) 2020-10-29 06:02:05 +00:00
Ani ea1cdbfdd8 ci: Update docker to 1.6
Bumps Windows VulkanSDK version to 1.2.154.1 to stay synchronised with
docker
2020-10-29 03:57:39 +00:00
Ani 3641926333 ci: Use system cURL on Linux build 2020-10-29 03:57:39 +00:00
Nekotekina 280958ee74 Revert "TSX: adjust transaction logic"
This reverts commit ff550b5c3c.
2020-10-28 21:59:12 +03:00
Bevan Weiss f4070731a8 NET: Add SO_RCVBUF / SO_SNDBUF defaults to .._bnet_socket
The OS defaults for SO_RCVBUF / SO_SNDBUF may not match what the defaults for the PS3 are.
And the code may be happy with the PS3 defaults, so may not set this explicitly.
So we'll do it when we establish the socket.
It also looks like the Windows recv behaviour is different for the MSG_PEEK option (and possibly in all situations where a smaller buffer is provided). I believe other platforms will return the size of the data received into the socket buffer, even if the supplied user buffer is smaller. Windows returns WSAEMSGSIZE instead. For the length of '1' MSG_PEEK request that is currently seen, we just mask this and return the full size of the buffer. This might need to be the case in all situations, I assume there will be applications that will supply an artificially small buffer and resize it as necessary based on the size of the received packet.
Add some additional translations from native->PS3 error codes

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

- Fixes driver crash on intel

* vk: Add NVIDIA driver version check

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

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

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

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

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

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

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

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

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

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

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

Added plurality handling for multiple PPU caches created.

Added plurality handling for multiple items deleted in save manager.

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

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

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

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

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

A few notes:
1. it changes the current behaviour of the 'Fullscreen cursor'.  Currently it defaults to be captive.  This changes it so that it defaults to NOT being captive, but can be made captive with the CTRL+L key combination.
2. There are situations when in windowed mode it's possible to escape the captivity (it's like a minigame if you will).  This requires the mouse movement to exceed the bounds of the window in a single event scan.  It will just show up as a temporary visibility of the cursor when outside of the window bounds.  It's not too difficult to 'fix', but might not be a likely enough scenario to warrant either.
3. There currently isn't an ability to change what this keyboard combo maps to, but it's inline with a collection of other similar keyboard mappings.  I think adding such a more generic keyboard mapping system (not for just keypad items, but system items.. e.g. so that Emulator stop could be mapped to something other than CTRL+S etc) is a bit out-of-scope of this particular PR.
2020-09-02 14:22:00 +02:00
875 changed files with 39223 additions and 25625 deletions
+9 -15
View File
@@ -1,25 +1,18 @@
#!/bin/sh -ex
ccache -s # debug
# 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 -q update --init --depth 1 $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
# XXX Drop after Travis upgrades FreeBSD to 12.2 (see also .ci/install-freebsd.sh)
case $(${CXX:-c++} --version) in
*version\ 8.0.*)
fetch https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/libcxx-10.0.0.src.tar.xz
tar xf libcxx-10.0.0.src.tar.xz
export CC=clang10 CXX=clang++10
export CXXFLAGS="$CXXFLAGS -nostdinc++ -isystem $PWD/libcxx-10.0.0.src/include"
;;
esac
# 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-11.0.0/libcxx-11.0.0.src.tar.xz
tar xf libcxx-11.0.0.src.tar.xz
export CC=clang11 CXX=clang++11
export CXXFLAGS="$CXXFLAGS -nostdinc++ -isystem $PWD/libcxx-11.0.0.src/include"
CONFIGURE_ARGS="
-DCMAKE_C_COMPILER_LAUNCHER=ccache
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
-DWITH_LLVM=OFF
-DUSE_PRECOMPILED_HEADERS=OFF
-DUSE_NATIVE_INSTRUCTIONS=OFF
@@ -32,4 +25,5 @@ CONFIGURE_ARGS="
cmake -B build -G Ninja $CONFIGURE_ARGS
cmake --build build
ccache -s # debug
ccache --show-stats
ccache --zero-stats
+4 -5
View File
@@ -48,17 +48,16 @@ cmake .. \
-DCMAKE_CXX_FLAGS="$CFLAGS" \
-DCMAKE_AR="$AR" \
-DCMAKE_RANLIB="$RANLIB" \
-DUSE_SYSTEM_CURL=ON \
-G Ninja
ninja; build_status=$?;
cd ..
# If it compiled succesfully let's deploy depending on the build pipeline (Travis, Azure Pipelines).
# Travis only deploys on master, and it publishes to GitHub releases. Azure publishes PRs as artifacts
# only.
{ [ "$IS_AZURE" = "true" ] ||
{ [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; };
# If it compiled succesfully let's deploy depending on the build pipeline (Azure Pipelines).
# Azure publishes PRs as artifacts only.
{ [ "$IS_AZURE" = "true" ];
} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false"
if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then
+3 -11
View File
@@ -41,7 +41,6 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
COMM_HASH="$(git rev-parse --short=8 HEAD)"
RPCS3_APPIMAGE="rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_linux64.AppImage"
curl -sLO https://github.com/hcorion/uploadtool/raw/master/upload.sh
mv ./RPCS3*.AppImage "$RPCS3_APPIMAGE"
# If we're building using Azure Pipelines, let's copy over the AppImage artifact
@@ -50,16 +49,9 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
fi
FILESIZE=$(stat -c %s ./rpcs3*.AppImage)
SHA256SUM=$(sha256sum ./rpcs3*.AppImage)
if [ -n "$GITHUB_TOKEN" ]; then
unset TRAVIS_REPO_SLUG
REPO_SLUG=RPCS3/rpcs3-binaries-linux \
UPLOADTOOL_BODY="$SHA256SUM;${FILESIZE}B"\
RELEASE_NAME=build-${TRAVIS_COMMIT}\
RELEASE_TITLE=${COMM_TAG}-${COMM_COUNT}\
REPO_COMMIT=d812f1254a1157c80fd402f94446310560f54e5f\
bash upload.sh rpcs3*.AppImage
fi
SHA256SUM=$(sha256sum ./rpcs3*.AppImage | awk '{ print $1 }')
echo "${SHA256SUM};${FILESIZE}B" > /rpcs3/GitHubReleaseMessage.txt
fi
if [ "$DEPLOY_PPA" = "true" ]; then
+2 -6
View File
@@ -1,7 +1,3 @@
# Variables set by Travis CI
TRAVIS_PULL_REQUEST
TRAVIS_BRANCH
TRAVIS_COMMIT
# Variables set by Azure Pipelines
IS_AZURE
BUILD_REASON
@@ -9,8 +5,8 @@ BUILD_SOURCEVERSION
BUILD_ARTIFACTSTAGINGDIRECTORY
BUILD_REPOSITORY_NAME
BUILD_SOURCEBRANCHNAME
# Variables for Travis build matrix
# Variables for build matrix
COMPILER
DEPLOY_APPIMAGE
# Private Travis CI variables
# Private variables
GITHUB_TOKEN
+3 -5
View File
@@ -7,7 +7,7 @@ generate_post_data()
cat <<EOF
{
"tag_name": "build-${BUILD_SOURCEVERSION}",
"target_commitish": "7d09e3be30805911226241afbb14f8cdc2eb054e",
"target_commitish": "${UPLOAD_COMMIT_HASH}",
"name": "${AVVER}",
"body": "$body",
"draft": false,
@@ -16,12 +16,10 @@ generate_post_data()
EOF
}
repo_full_name="RPCS3/rpcs3-binaries-win"
curl -s \
-H "Authorization: token ${RPCS3_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
--data "$(generate_post_data)" "https://api.github.com/repos/$repo_full_name/releases" >> release.json
--data "$(generate_post_data)" "https://api.github.com/repos/$UPLOAD_REPO_FULL_NAME/releases" >> release.json
cat release.json
id=$(grep '"id"' release.json | cut -d ':' -f2 | head -n1 | awk '{$1=$1;print}')
@@ -35,7 +33,7 @@ upload_file()
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/octet-stream" \
--data-binary @"$2"/"$3" \
"https://uploads.github.com/repos/$repo_full_name/releases/$1/assets?name=$3"
"https://uploads.github.com/repos/$UPLOAD_REPO_FULL_NAME/releases/$1/assets?name=$3"
}
for file in "$ARTIFACT_DIR"/*; do
+2 -6
View File
@@ -8,12 +8,8 @@ sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
export ASSUME_ALWAYS_YES=true
pkg info # debug
# XXX Drop after Travis upgrades FreeBSD to 12.2 (see also .ci/build-freebsd.sh)
case $(${CXX:-c++} --version) in
*version\ 8.0.*)
pkg install llvm10
;;
esac
# Prefer newer Clang than in base system (see also .ci/build-freebsd.sh)
pkg install llvm11
# 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 glew openal-soft ffmpeg
+6 -7
View File
@@ -10,16 +10,16 @@ PR_NUMBER="$SYSTEM_PULLREQUEST_PULLREQUESTID"
QT_HOST="http://mirrors.ocf.berkeley.edu/qt/"
#QT_HOST="http://qt.mirror.constant.com/"
QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt5_${QT_URL_VER}/qt.qt5.${QT_URL_VER}.win64_msvc2017_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z"
QT_VER_MSVC_UP=$(echo ${QT_VER_MSVC} | tr '[:lower:]' '[:upper:]')
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}.win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_10-${QT_VER_MSVC_UP}-Windows-Windows_10-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}qtbase${QT_SUFFIX}"
QT_WINE_URL="${QT_HOST}${QT_PREFIX}qtwinextras${QT_SUFFIX}"
QT_DECL_URL="${QT_HOST}${QT_PREFIX}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}qttools${QT_SUFFIX}"
LLVMLIBS_URL='https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win/llvmlibs_mt.7z'
#GLSLANG_URL='https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z' <- Temporarily disabled auto-builds
GLSLANG_URL='https://www.dropbox.com/s/cg48qr4zmnn066v/glslanglibs_mt.7z'
VULKAN_SDK_URL="https://www.dropbox.com/s/adanclixregbp2x/VulkanSDK-${VULKAN_VER}-Installer.exe"
GLSLANG_URL='https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z'
VULKAN_SDK_URL="https://www.dropbox.com/s/kn005de7gsv5whe/VulkanSDK-1.2.154.1-Installer.exe"
DEP_URLS=" \
$QT_BASE_URL \
@@ -76,8 +76,7 @@ for url in $DEP_URLS; do
case "$url" in
*qt*) checksum=$(curl -L "${url}.sha1"); algo="sha1"; outDir='C:\Qt\' ;;
*llvm*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="." ;;
#*glslang*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="./lib/Release - LLVM-x64" ;; <- Temporarily disabled auto-build
*glslang*) checksum=$(curl -L 'https://www.dropbox.com/s/hwnatk68n70jap0/glslanglibs_mt.7z.sha256'); algo="sha256"; outDir="./lib/Release - LLVM-x64" ;;
*glslang*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="./lib/Release - LLVM-x64" ;;
*Vulkan*)
# Vulkan setup needs to be run in batch environment
# Need to subshell this or else it doesn't wait
+2 -2
View File
@@ -3,9 +3,9 @@ env:
freebsd_task:
matrix:
- name: FreeBSD 12.2 (snapshot)
- name: FreeBSD 12.2
freebsd_instance:
image_family: freebsd-12-1-snap
image_family: freebsd-12-2
cpu: 8
memory: 8G
env:
+11 -11
View File
@@ -1,20 +1,20 @@
Standard: Cpp11
Standard: c++20
UseTab: ForIndentation
TabWidth: 1
IndentWidth: 1
AccessModifierOffset: -1
TabWidth: 4
IndentWidth: 4
AccessModifierOffset: -4
PointerAlignment: Left
NamespaceIndentation: All
ColumnLimit: 200
ColumnLimit: 0
BreakBeforeBraces: Allman
BreakConstructorInitializersBeforeComma: true
BreakBeforeBinaryOperators: false
BreakConstructorInitializers: BeforeColon
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: false
AlwaysBreakTemplateDeclarations: true
AllowShortIfStatementsOnASingleLine: false
AllowShortBlocksOnASingleLine: false
AlwaysBreakTemplateDeclarations: Yes
AllowShortIfStatementsOnASingleLine: Never
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
Cpp11BracedListStyle: true
IndentCaseLabels: false
+1 -1
View File
@@ -1,7 +1,7 @@
root = true
[*.{h,cpp,hpp}]
charset = utf-8-bom
charset = utf-8
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
+2
View File
@@ -0,0 +1,2 @@
handle SIGSEGV nostop noprint
handle SIGPIPE nostop noprint
+20
View File
@@ -0,0 +1,20 @@
## How to test a PR build
Please take into account, that RPCS3 build usually takes some time (about 20 min), so you can't access a build, if a PR was just submitted.
- Open a PR you want to test
- Scroll to the very bottom and locate "Checks" section
- Expand all checks
You are supposed to see something like this
![image](https://user-images.githubusercontent.com/44116740/102790039-f98f6d00-43b5-11eb-9134-2359b732508d.png)
- Click on **Linux_Build** or **Windows_Build** __Details__
- Click **View more details on Azure Pipelines** at the very bottom
![image](https://user-images.githubusercontent.com/44116740/102790281-45daad00-43b6-11eb-90e7-0fa8c37c31c6.png)
- Click on *1 artifact produced*
![image](https://user-images.githubusercontent.com/44116740/102790526-9a7e2800-43b6-11eb-9925-be1ea1c8bdad.png)
- Select a build for your OS and click three dots on the right, Click **Download artifacts**
![image](https://user-images.githubusercontent.com/44116740/102790636-c9949980-43b6-11eb-9692-1e3ba567b9be.png)
- Congratulations! You are now downloading RPCS3 build for specific PR.
Please note, that PR builds are not supposed to be stable, because they contain new changesets.
@@ -0,0 +1,3 @@
<!-- Please include a summary of the change and which issue is fixed. -->
[How to test this PR](.github/PR-BUILD.md)
+2 -2
View File
@@ -65,11 +65,11 @@
ignore = dirty
[submodule "3rdparty/curl"]
path = 3rdparty/curl
url = https://github.com/RipleyTom/curl.git
url = https://github.com/curl/curl.git
ignore = dirty
[submodule "3rdparty/wolfssl"]
path = 3rdparty/wolfssl
url = https://github.com/RipleyTom/wolfssl.git
url = https://github.com/wolfSSL/wolfssl.git
ignore = dirty
[submodule "3rdparty/flatbuffers"]
path = 3rdparty/flatbuffers
-46
View File
@@ -1,46 +0,0 @@
language: cpp
jobs:
include:
- os: linux
dist: xenial
env:
- NAME="Linux build"
- COMPILER="gcc"
- DEPLOY_APPIMAGE="true"
services: docker
cache: ccache
compiler: gcc
install: "docker pull rpcs3/rpcs3-travis-xenial:1.5"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.5 /rpcs3/.ci/build-linux.sh'
- os: linux
dist: xenial
env:
- NAME="Linux build"
- COMPILER="clang"
services: docker
cache: ccache
compiler: clang
install: "docker pull rpcs3/rpcs3-travis-xenial:1.5"
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.5 /rpcs3/.ci/build-linux.sh'
# - os: freebsd
# compiler: clang
# cache: ccache
# install: "./.ci/install-freebsd.sh"
# script: "./.ci/build-freebsd.sh"
# - os: osx
# osx_image: xcode11.3
# addons:
# homebrew:
# packages:
# - ccache
# - glew
# - ninja
# - qt
# script: "/bin/bash -ex .ci/build-mac.sh"
# cache: ccache
allow_failures:
- os: osx
git:
depth: false # Unshallow clone to obtain proper GIT_VERSION
submodules: false
+67 -17
View File
@@ -106,6 +106,36 @@ endif()
add_subdirectory(pugixml EXCLUDE_FROM_ALL)
# libusb
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0>=1.0 )
CMAKE_DEPENDENT_OPTION( USE_SYS_LIBUSB "Use system libusb-1.0 as shared library" ON
"LIBUSB_FOUND" OFF)
else()
pkg_check_modules(LIBUSB IMPORTED_TARGET libusb-1.0>=1.0 )
CMAKE_DEPENDENT_OPTION( USE_SYS_LIBUSB "Use system libusb-1.0 as shared library" OFF
"LIBUSB_FOUND" OFF)
endif()
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
# Always use system libusb as reference implementation isn't supported
add_library(usb-1.0-shared INTERFACE)
target_link_libraries(usb-1.0-shared INTERFACE PkgConfig::LIBUSB)
elseif(MSVC)
# Windows time.h defines timespec but doesn't add any flag for it, which makes libusb attempt to define it again
add_definitions(-DHAVE_STRUCT_TIMESPEC=1)
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
else()
if(USE_SYS_LIBUSB)
# we have the system libusb and have selected to use it
add_library(usb-1.0-shared INTERFACE)
target_link_libraries(usb-1.0-shared INTERFACE PkgConfig::LIBUSB)
else()
# we don't have the system libusb, so we compile from submodule
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
endif()
endif()
# hidapi
add_library(3rdparty_hidapi INTERFACE)
target_include_directories(3rdparty_hidapi INTERFACE hidapi/hidapi)
@@ -133,24 +163,11 @@ else()
endif()
# libusb
if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
# Always use system libusb as reference implementation isn't supported
add_library(usb-1.0-static INTERFACE)
target_link_libraries(usb-1.0-static INTERFACE usb)
elseif(MSVC)
# Windows time.h defines timespec but doesn't add any flag for it, which makes libusb attempt to define it again
add_definitions(-DHAVE_STRUCT_TIMESPEC=1)
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
else()
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
endif()
# yaml-cpp
# We don't want to install yaml-cpp but its cmake file doesn't have option
# to disable it...
# So we just install it to a different directory
set(YAML_CPP_INSTALL OFF CACHE BOOL "Don't install YAML")
set(CMAKE_INSTALL_PREFIX_OLD ${CMAKE_INSTALL_PREFIX})
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/yaml-cpp_install)
@@ -164,6 +181,7 @@ set(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX_OLD})
# xxHash
set(XXHASH_BUNDLED_MODE ON)
set(XXHASH_BUILD_XXHSUM OFF)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Make xxHash build static libs")
add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL)
target_include_directories(xxhash INTERFACE xxHash)
@@ -417,7 +435,30 @@ endif()
include(llvm.cmake)
# WOLFSSL
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
if(USE_SYSTEM_WOLFSSL)
message("-- RPCS3: using shared wolfssl")
find_package(WolfSSL REQUIRED)
add_library(wolfssl INTERFACE)
target_link_libraries(wolfssl INTERFACE WolfSSL_LIBRARIES)
target_include_directories(wolfssl INTERFACE WolfSSL_INCLUDE_DIRS)
else()
SET(BUILD_TESTS NO CACHE BOOL "Build test applications")
add_compile_definitions(HAVE_FFDHE_2048 TFM_TIMING_RESISTANT ECC_TIMING_RESISTANT
WC_RSA_BLINDING HAVE_AESGCM WOLFSSL_SHA512 WOLFSSL_SHA384 NO_DSA HAVE_ECC TFM_ECC256 ECC_SHAMIR
NO_RC4 NO_HC128 NO_RABBIT WOLFSSL_SHA224 WOLFSSL_SHA3 WOLFSSL_SHAKE256 HAVE_POLY1305
HAVE_ONE_TIME_AUTH HAVE_CHACHA HAVE_HASHDRBG HAVE_TLS_EXTENSIONS HAVE_SNI HAVE_SUPPORTED_CURVES
HAVE_EXTENDED_MASTER NO_RC4 HAVE_ENCRYPT_THEN_MAC NO_PSK NO_MD4
WC_NO_ASYNC_THREADING OPENSSL_EXTRA WOLFSSL_DES_ECB WC_NO_HARDEN)
set(ENABLED_HARDEN OFF CACHE BOOL "Disable Harden")
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
target_include_directories(wolfssl INTERFACE "wolfssl/")
# This is needed for CURL
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/wolfssl/options.h.in ${CMAKE_CURRENT_BINARY_DIR}/wolfssl/wolfssl/options.h)
set(WolfSSL_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/libwolfssl.a")
set(WolfSSL_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/libwolfssl.a")
set(WolfSSL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/" "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/")
set(WolfSSL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/" "${CMAKE_CURRENT_BINARY_DIR}/wolfssl/")
endif()
# CURL
if(USE_SYSTEM_CURL)
@@ -427,11 +468,20 @@ if(USE_SYSTEM_CURL)
target_link_libraries(libcurl INTERFACE CURL::libcurl)
else()
message("-- RPCS3: building libcurl + wolfssl submodules")
option(BUILD_CURL_EXE "Set to ON to build curl executable." OFF)
option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" ON)
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" ON)
option(CURL_ZLIB "Set to ON to enable building curl with zlib support." OFF)
set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
add_subdirectory(curl EXCLUDE_FROM_ALL)
endif()
# add nice ALIAS targets for ease of use
add_library(3rdparty::libusb ALIAS usb-1.0-static)
if(USE_SYS_LIBUSB)
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
else()
add_library(3rdparty::libusb ALIAS usb-1.0-static)
endif()
add_library(3rdparty::zlib ALIAS 3rdparty_zlib)
add_library(3rdparty::7z ALIAS 3rdparty_7z)
add_library(3rdparty::flatbuffers ALIAS 3rdparty_flatbuffers)
@@ -453,5 +503,5 @@ add_library(3rdparty::vulkan ALIAS ${VULKAN_TARGET})
add_library(3rdparty::openal ALIAS 3rdparty_openal)
add_library(3rdparty::ffmpeg ALIAS 3rdparty_ffmpeg)
add_library(3rdparty::glew ALIAS 3rdparty_glew)
add_library(3rdparty::wolfssl ALIAS wolfssl-3-static)
add_library(3rdparty::wolfssl ALIAS wolfssl)
add_library(3rdparty::libcurl ALIAS libcurl)
+1 -1
+40
View File
@@ -0,0 +1,40 @@
/* options.h.in
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* default blank options for autoconf */
#ifndef WOLFSSL_OPTIONS_H
#define WOLFSSL_OPTIONS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_OPTIONS_H */
+13 -2
View File
@@ -51,8 +51,8 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>curl\include;curl\lib;wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_SNI;NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>curl\include;curl\lib;curl_extra;wolfssl;wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_SNI;NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;SIZEOF_LONG=4;SIZEOF_LONG_LONG=8;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
@@ -97,6 +97,7 @@
<ClCompile Include="curl\lib\dict.c" />
<ClCompile Include="curl\lib\doh.c" />
<ClCompile Include="curl\lib\dotdot.c" />
<ClCompile Include="curl\lib\dynbuf.c" />
<ClCompile Include="curl\lib\easy.c" />
<ClCompile Include="curl\lib\escape.c" />
<ClCompile Include="curl\lib\file.c" />
@@ -135,6 +136,7 @@
<ClCompile Include="curl\lib\memdebug.c" />
<ClCompile Include="curl\lib\mime.c" />
<ClCompile Include="curl\lib\mprintf.c" />
<ClCompile Include="curl\lib\mqtt.c" />
<ClCompile Include="curl\lib\multi.c" />
<ClCompile Include="curl\lib\netrc.c" />
<ClCompile Include="curl\lib\non-ascii.c" />
@@ -178,6 +180,7 @@
<ClCompile Include="curl\lib\url.c" />
<ClCompile Include="curl\lib\urlapi.c" />
<ClCompile Include="curl\lib\version.c" />
<ClCompile Include="curl\lib\version_win32.c" />
<ClCompile Include="curl\lib\warnless.c" />
<ClCompile Include="curl\lib\wildcard.c" />
<ClCompile Include="curl\lib\x509asn1.c" />
@@ -195,12 +198,14 @@
<ClCompile Include="curl\lib\vauth\vauth.c" />
<ClCompile Include="curl\lib\vquic\ngtcp2.c" />
<ClCompile Include="curl\lib\vquic\quiche.c" />
<ClCompile Include="curl\lib\vquic\vquic.c" />
<ClCompile Include="curl\lib\vssh\libssh.c" />
<ClCompile Include="curl\lib\vssh\libssh2.c" />
<ClCompile Include="curl\lib\vssh\wolfssh.c" />
<ClCompile Include="curl\lib\vtls\bearssl.c" />
<ClCompile Include="curl\lib\vtls\gskit.c" />
<ClCompile Include="curl\lib\vtls\gtls.c" />
<ClCompile Include="curl\lib\vtls\keylog.c" />
<ClCompile Include="curl\lib\vtls\mbedtls.c" />
<ClCompile Include="curl\lib\vtls\mbedtls_threadlock.c" />
<ClCompile Include="curl\lib\vtls\mesalink.c" />
@@ -274,6 +279,7 @@
<ClInclude Include="curl\lib\dict.h" />
<ClInclude Include="curl\lib\doh.h" />
<ClInclude Include="curl\lib\dotdot.h" />
<ClInclude Include="curl\lib\dynbuf.h" />
<ClInclude Include="curl\lib\easyif.h" />
<ClInclude Include="curl\lib\escape.h" />
<ClInclude Include="curl\lib\file.h" />
@@ -300,6 +306,7 @@
<ClInclude Include="curl\lib\llist.h" />
<ClInclude Include="curl\lib\memdebug.h" />
<ClInclude Include="curl\lib\mime.h" />
<ClInclude Include="curl\lib\mqtt.h" />
<ClInclude Include="curl\lib\multihandle.h" />
<ClInclude Include="curl\lib\multiif.h" />
<ClInclude Include="curl\lib\netrc.h" />
@@ -319,6 +326,7 @@
<ClInclude Include="curl\lib\setopt.h" />
<ClInclude Include="curl\lib\setup-os400.h" />
<ClInclude Include="curl\lib\setup-vms.h" />
<ClInclude Include="curl\lib\setup-win32.h" />
<ClInclude Include="curl\lib\share.h" />
<ClInclude Include="curl\lib\sigpipe.h" />
<ClInclude Include="curl\lib\slist.h" />
@@ -342,6 +350,7 @@
<ClInclude Include="curl\lib\url.h" />
<ClInclude Include="curl\lib\urlapi-int.h" />
<ClInclude Include="curl\lib\urldata.h" />
<ClInclude Include="curl\lib\version_win32.h" />
<ClInclude Include="curl\lib\warnless.h" />
<ClInclude Include="curl\lib\wildcard.h" />
<ClInclude Include="curl\lib\x509asn1.h" />
@@ -350,11 +359,13 @@
<ClInclude Include="curl\lib\vauth\vauth.h" />
<ClInclude Include="curl\lib\vquic\ngtcp2.h" />
<ClInclude Include="curl\lib\vquic\quiche.h" />
<ClInclude Include="curl\lib\vquic\vquic.h" />
<ClInclude Include="curl\lib\vssh\ssh.h" />
<ClInclude Include="curl\lib\vssh\wolfssh.h" />
<ClInclude Include="curl\lib\vtls\bearssl.h" />
<ClInclude Include="curl\lib\vtls\gskit.h" />
<ClInclude Include="curl\lib\vtls\gtls.h" />
<ClInclude Include="curl\lib\vtls\keylog.h" />
<ClInclude Include="curl\lib\vtls\mbedtls.h" />
<ClInclude Include="curl\lib\vtls\mbedtls_threadlock.h" />
<ClInclude Include="curl\lib\vtls\mesalink.h" />
+7 -4
View File
@@ -6,6 +6,7 @@ if (CMAKE_USE_PTHREADS_INIT)
endif()
if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
add_compile_definitions(PLATFORM_WINDOWS=1)
set(OS_WINDOWS 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
# Enable MingW support for RC language (for CMake pre-2.8)
@@ -22,9 +23,9 @@ if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
endif()
list(APPEND PLATFORM_SRC
poll_windows.c
events_windows.c
windows_usbdk.c
windows_nt_common.c
windows_common.c
windows_winusb.c
threads_windows.c
)
@@ -36,13 +37,14 @@ if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
endif()
elseif (APPLE)
# Apple != OSX alone
add_compile_definitions(PLATFORM_POSIX=1 HAVE_CLOCK_GETTIME)
set(OS_DARWIN 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(PLATFORM_SRC
darwin_usb.c
threads_posix.c
poll_posix.c
events_posix.c
)
find_package(IOKit REQUIRED)
@@ -72,6 +74,7 @@ int main()
endif()
elseif (UNIX)
# Unix is for all *NIX systems including OSX
add_compile_definitions(PLATFORM_POSIX=1 HAVE_CLOCK_GETTIME)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(OS_LINUX 1 CACHE INTERNAL "controls config.h macro definition" FORCE)
@@ -79,7 +82,7 @@ elseif (UNIX)
linux_usbfs.c
linux_netlink.c
threads_posix.c
poll_posix.c
events_posix.c
)
list(APPEND LIBUSB_LIBRARIES rt)
+5 -6
View File
@@ -41,8 +41,9 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>libusb\msvc;libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WINVER=0x0600;_WIN32_WINNT=0x0600;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
@@ -64,11 +65,11 @@
<ClCompile Include="libusb\libusb\descriptor.c" />
<ClCompile Include="libusb\libusb\hotplug.c" />
<ClCompile Include="libusb\libusb\io.c" />
<ClCompile Include="libusb\libusb\os\poll_windows.c" />
<ClCompile Include="libusb\libusb\os\events_windows.c" />
<ClCompile Include="libusb\libusb\strerror.c" />
<ClCompile Include="libusb\libusb\sync.c" />
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
<ClCompile Include="libusb\libusb\os\windows_nt_common.c" />
<ClCompile Include="libusb\libusb\os\windows_common.c" />
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
</ItemGroup>
@@ -77,13 +78,11 @@
<ClInclude Include="libusb\libusb\hotplug.h" />
<ClInclude Include="libusb\libusb\libusb.h" />
<ClInclude Include="libusb\libusb\libusbi.h" />
<ClInclude Include="libusb\libusb\os\poll_windows.h" />
<ClInclude Include="libusb\libusb\os\events_windows.h" />
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
<ClInclude Include="libusb\libusb\version.h" />
<ClInclude Include="libusb\libusb\version_nano.h" />
<ClInclude Include="libusb\libusb\os\windows_common.h" />
<ClInclude Include="libusb\libusb\os\windows_nt_common.h" />
<ClInclude Include="libusb\libusb\os\windows_nt_shared_types.h" />
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
</ItemGroup>
-1
View File
@@ -11,7 +11,6 @@ if(WITH_LLVM)
option(LLVM_INCLUDE_TESTS OFF)
option(LLVM_INCLUDE_TOOLS OFF)
option(LLVM_INCLUDE_UTILS OFF)
option(WITH_POLLY OFF)
option(LLVM_CCACHE_BUILD ON)
set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS})
+9 -11
View File
@@ -1,11 +1,13 @@
add_library(3rdparty_qt5 INTERFACE)
find_package(Qt5 5.14 CONFIG COMPONENTS Widgets Concurrent)
set(QT_MIN_VER 5.15.2)
find_package(Qt5 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent)
if(WIN32)
find_package(Qt5 5.14 COMPONENTS WinExtras REQUIRED)
find_package(Qt5 ${QT_MIN_VER} COMPONENTS WinExtras REQUIRED)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::WinExtras Qt5::Concurrent)
else()
find_package(Qt5 5.14 COMPONENTS DBus Gui)
find_package(Qt5 ${QT_MIN_VER} COMPONENTS DBus Gui)
if(Qt5DBus_FOUND)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::DBus Qt5::Concurrent)
target_compile_definitions(3rdparty_qt5 INTERFACE -DHAVE_QTDBUS)
@@ -16,16 +18,12 @@ else()
endif()
if(NOT Qt5Widgets_FOUND)
if(Qt5Widgets_VERSION VERSION_LESS 5.14.0)
message("Minimum supported Qt5 version is 5.14.0! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
if(Qt5Widgets_VERSION VERSION_LESS ${QT_MIN_VER})
message("Minimum supported Qt5 version is ${QT_MIN_VER}! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
if(CMAKE_SYSTEM MATCHES "Linux")
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install one of the latest qt5 versions.
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.14.1-bionic
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.14.1-xenial
just make sure to run
source /opt/qt514/bin/qt514-env.sh
before re-running cmake")
Find the correct ppa at https://launchpad.net/~beineri and follow the instructions.")
elseif(WIN32)
message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/")
else()
@@ -35,7 +33,7 @@ before re-running cmake")
message("CMake was unable to find Qt5!")
if(WIN32)
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.14.1\\msvc2017_64\\)
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2019_64\\)
You can also try setting the Qt5_DIR preprocessor definiton.")
elseif(CMAKE_SYSTEM MATCHES "Linux")
message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
+2 -2
View File
@@ -48,7 +48,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;ECC_TIMING_RESISTANT;WC_RSA_BLINDING;HAVE_AESGCM;WOLFSSL_SHA512;WOLFSSL_SHA384;NO_DSA;HAVE_ECC;TFM_ECC256;ECC_SHAMIR;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_TLS_EXTENSIONS;HAVE_SNI;HAVE_SUPPORTED_CURVES;HAVE_EXTENDED_MASTER;NO_RC4;HAVE_ENCRYPT_THEN_MAC;NO_PSK;NO_MD4;WC_NO_ASYNC_THREADING;OPENSSL_EXTRA;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -62,7 +62,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WC_NO_HARDEN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
+15 -15
View File
@@ -9,19 +9,19 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
* [CMake 3.14.1+](https://www.cmake.org/download/) (add to PATH)
* [Python 3.3+](https://www.python.org/downloads/) (add to PATH)
* [Qt 5.14.2](https://www.qt.io/download-qt-installer)
* [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.1.126+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.14.2\msvc2017_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools-19123)**
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.15.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager.
* Clang 9+ or GCC 9+
* Clang 11+ or GCC 9+
* [CMake 3.14.1+](https://www.cmake.org/download/)
* [Qt 5.14.2](https://www.qt.io/download-qt-installer)
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
* [Vulkan SDK 1.1.126+](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)
@@ -40,11 +40,11 @@ Ubuntu is usually horrendously out of date, and some packages need to be downloa
Ubuntu usually does not have a new enough Qt package to suit rpcs3's needs. There is a PPA available to work around this. Run the following:
```
ucodename=$(lsb_release -sc)
sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-$ucodename
. /etc/os-release
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-$UBUNTU_CODENAME
sudo apt-get update
. /opt/qt514/bin/qt514-env.sh >/dev/null 2>&1
sudo apt-get install qt514-meta-minimal qt514svg
sudo apt-get install qt515-meta-minimal qt515svg
. /opt/qt515/bin/qt515-env.sh >/dev/null 2>&1
```
##### GCC 9.x installation
@@ -62,27 +62,27 @@ You can either use `update-alternatives` to setup `gcc-9`/`g++-9` as your defaul
For Ubuntu systems, it is strongly recommended to use the PPA from [LunarG](https://packages.lunarg.com/) which will provide a compatible Vulkan SDK to compile RPCS3. If your Vulkan SDK is older, it can lead to compilation errors.
```
ucodename=$(lsb_release -sc)
wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.1.126-$ucodename.list http://packages.lunarg.com/vulkan/1.1.126/lunarg-vulkan-1.1.126-$ucodename.list
. /etc/os-release
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.148/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list
sudo apt update
sudo apt install vulkan-sdk
```
##### CMake
```
. /etc/os-release
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add -
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -sc) main"
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $UBUNTU_CODENAME main"
sudo apt-get update
sudo apt-get install kitware-archive-keyring
sudo apt-key --keyring /etc/apt/trusted.gpg del C1F34CDD40CD72DA
sudo apt-get install cmake
```
#### Fedora
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-devel vulkan-devel
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-devel qt5-qtbase-private-devel vulkan-devel
#### OpenSUSE
@@ -103,7 +103,7 @@ git submodule update --init
#### Configuring the Qt plugin (if used)
1) Go to the Qt5 menu and edit Qt5 options.
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\5.14.2\msvc2017_64`.
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\5.15.2\msvc2019_64`.
3) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
#### Building the projects
+4 -4
View File
@@ -7,8 +7,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
message(FATAL_ERROR "RPCS3 requires at least gcc-9.")
endif()
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
message(FATAL_ERROR "RPCS3 requires at least clang-9.0.")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0)
message(FATAL_ERROR "RPCS3 requires at least clang-11.0.")
endif()
endif()
@@ -22,7 +22,7 @@ option(USE_LIBEVDEV "libevdev-based joystick support" ON)
option(USE_DISCORD_RPC "Discord rich presence integration" ON)
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" ON)
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/rpcs3/cmake_modules")
@@ -64,7 +64,7 @@ set(CMAKE_C_FLAGS -w)
set(LLVM_ENABLE_WARNINGS OFF CACHE BOOL "")
if(MSVC)
add_compile_options(/wd4530) # C++ exception handler used, but unwind semantics are not enabled
add_compile_options(/wd4530 /utf-8) # C++ exception handler used, but unwind semantics are not enabled
endif()
add_subdirectory(Vulkan EXCLUDE_FROM_ALL)
-1
View File
@@ -1,7 +1,6 @@
RPCS3
=====
[![Travis (.org) branch](https://img.shields.io/travis/RPCS3/rpcs3/master?label=Travis%20CI&logo=travis)](https://travis-ci.org/RPCS3/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)
-511
View File
@@ -1,511 +0,0 @@
#ifndef BETYPE_H_GUARD
#define BETYPE_H_GUARD
#include "types.h"
#include "util/endian.hpp"
#include <cstring>
#include <cmath>
#if __has_include(<bit>)
#include <bit>
#else
#include <type_traits>
#endif
// 128-bit vector type and also se_storage<> storage type
union alignas(16) v128
{
uchar _bytes[16];
char _chars[16];
template <typename T, std::size_t N, std::size_t M>
struct masked_array_t // array type accessed as (index ^ M)
{
char m_data[16];
public:
T& operator[](std::size_t index)
{
return reinterpret_cast<T*>(m_data)[index ^ M];
}
const T& operator[](std::size_t index) const
{
return reinterpret_cast<const T*>(m_data)[index ^ M];
}
};
template <typename T, std::size_t N = 16 / sizeof(T)>
using normal_array_t = masked_array_t<T, N, std::endian::little == std::endian::native ? 0 : N - 1>;
template <typename T, std::size_t N = 16 / sizeof(T)>
using reversed_array_t = masked_array_t<T, N, std::endian::little == std::endian::native ? N - 1 : 0>;
normal_array_t<u64> _u64;
normal_array_t<s64> _s64;
reversed_array_t<u64> u64r;
reversed_array_t<s64> s64r;
normal_array_t<u32> _u32;
normal_array_t<s32> _s32;
reversed_array_t<u32> u32r;
reversed_array_t<s32> s32r;
normal_array_t<u16> _u16;
normal_array_t<s16> _s16;
reversed_array_t<u16> u16r;
reversed_array_t<s16> s16r;
normal_array_t<u8> _u8;
normal_array_t<s8> _s8;
reversed_array_t<u8> u8r;
reversed_array_t<s8> s8r;
normal_array_t<f32> _f;
normal_array_t<f64> _d;
reversed_array_t<f32> fr;
reversed_array_t<f64> dr;
__m128 vf;
__m128i vi;
__m128d vd;
struct bit_array_128
{
char m_data[16];
public:
class bit_element
{
u64& data;
const u64 mask;
public:
bit_element(u64& data, const u64 mask)
: data(data)
, mask(mask)
{
}
operator bool() const
{
return (data & mask) != 0;
}
bit_element& operator=(const bool right)
{
if (right)
{
data |= mask;
}
else
{
data &= ~mask;
}
return *this;
}
bit_element& operator=(const bit_element& right)
{
if (right)
{
data |= mask;
}
else
{
data &= ~mask;
}
return *this;
}
};
// Index 0 returns the MSB and index 127 returns the LSB
bit_element operator[](u32 index)
{
const auto data_ptr = reinterpret_cast<u64*>(m_data);
if constexpr (std::endian::little == std::endian::native)
{
return bit_element(data_ptr[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F));
}
else
{
return bit_element(data_ptr[index >> 6], 0x8000000000000000ull >> (index & 0x3F));
}
}
// Index 0 returns the MSB and index 127 returns the LSB
bool operator[](u32 index) const
{
const auto data_ptr = reinterpret_cast<const u64*>(m_data);
if constexpr (std::endian::little == std::endian::native)
{
return (data_ptr[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
}
else
{
return (data_ptr[index >> 6] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
}
}
} _bit;
static v128 from64(u64 _0, u64 _1 = 0)
{
v128 ret;
ret._u64[0] = _0;
ret._u64[1] = _1;
return ret;
}
static v128 from64r(u64 _1, u64 _0 = 0)
{
return from64(_0, _1);
}
static v128 from32(u32 _0, u32 _1 = 0, u32 _2 = 0, u32 _3 = 0)
{
v128 ret;
ret._u32[0] = _0;
ret._u32[1] = _1;
ret._u32[2] = _2;
ret._u32[3] = _3;
return ret;
}
static v128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0)
{
return from32(_0, _1, _2, _3);
}
static v128 from32p(u32 value)
{
v128 ret;
ret.vi = _mm_set1_epi32(static_cast<s32>(value));
return ret;
}
static v128 from16p(u16 value)
{
v128 ret;
ret.vi = _mm_set1_epi16(static_cast<s16>(value));
return ret;
}
static v128 from8p(u8 value)
{
v128 ret;
ret.vi = _mm_set1_epi8(static_cast<s8>(value));
return ret;
}
static v128 fromBit(u32 bit)
{
v128 ret = {};
ret._bit[bit] = true;
return ret;
}
static v128 fromV(__m128i value)
{
v128 ret;
ret.vi = value;
return ret;
}
static v128 fromF(__m128 value)
{
v128 ret;
ret.vf = value;
return ret;
}
static v128 fromD(__m128d value)
{
v128 ret;
ret.vd = value;
return ret;
}
// Unaligned load with optional index offset
static v128 loadu(const void* ptr, std::size_t index = 0)
{
v128 ret;
std::memcpy(&ret, static_cast<const u8*>(ptr) + index * sizeof(v128), sizeof(v128));
return ret;
}
// Unaligned store with optional index offset
static void storeu(v128 value, void* ptr, std::size_t index = 0)
{
std::memcpy(static_cast<u8*>(ptr) + index * sizeof(v128), &value, sizeof(v128));
}
static inline v128 add8(const v128& left, const v128& right)
{
return fromV(_mm_add_epi8(left.vi, right.vi));
}
static inline v128 add16(const v128& left, const v128& right)
{
return fromV(_mm_add_epi16(left.vi, right.vi));
}
static inline v128 add32(const v128& left, const v128& right)
{
return fromV(_mm_add_epi32(left.vi, right.vi));
}
static inline v128 addfs(const v128& left, const v128& right)
{
return fromF(_mm_add_ps(left.vf, right.vf));
}
static inline v128 addfd(const v128& left, const v128& right)
{
return fromD(_mm_add_pd(left.vd, right.vd));
}
static inline v128 sub8(const v128& left, const v128& right)
{
return fromV(_mm_sub_epi8(left.vi, right.vi));
}
static inline v128 sub16(const v128& left, const v128& right)
{
return fromV(_mm_sub_epi16(left.vi, right.vi));
}
static inline v128 sub32(const v128& left, const v128& right)
{
return fromV(_mm_sub_epi32(left.vi, right.vi));
}
static inline v128 subfs(const v128& left, const v128& right)
{
return fromF(_mm_sub_ps(left.vf, right.vf));
}
static inline v128 subfd(const v128& left, const v128& right)
{
return fromD(_mm_sub_pd(left.vd, right.vd));
}
static inline v128 maxu8(const v128& left, const v128& right)
{
return fromV(_mm_max_epu8(left.vi, right.vi));
}
static inline v128 minu8(const v128& left, const v128& right)
{
return fromV(_mm_min_epu8(left.vi, right.vi));
}
static inline v128 eq8(const v128& left, const v128& right)
{
return fromV(_mm_cmpeq_epi8(left.vi, right.vi));
}
static inline v128 eq16(const v128& left, const v128& right)
{
return fromV(_mm_cmpeq_epi16(left.vi, right.vi));
}
static inline v128 eq32(const v128& left, const v128& right)
{
return fromV(_mm_cmpeq_epi32(left.vi, right.vi));
}
static inline v128 eq32f(const v128& left, const v128& right)
{
return fromF(_mm_cmpeq_ps(left.vf, right.vf));
}
static inline v128 eq64f(const v128& left, const v128& right)
{
return fromD(_mm_cmpeq_pd(left.vd, right.vd));
}
static inline bool use_fma = false;
static inline v128 fma32f(v128 a, const v128& b, const v128& c)
{
#ifndef __FMA__
if (use_fma) [[likely]]
{
#ifdef _MSC_VER
a.vf = _mm_fmadd_ps(a.vf, b.vf, c.vf);
return a;
#else
__asm__("vfmadd213ps %[c], %[b], %[a]"
: [a] "+x" (a.vf)
: [b] "x" (b.vf)
, [c] "x" (c.vf));
return a;
#endif
}
for (int i = 0; i < 4; i++)
{
a._f[i] = std::fmaf(a._f[i], b._f[i], c._f[i]);
}
return a;
#else
a.vf = _mm_fmadd_ps(a.vf, b.vf, c.vf);
return a;
#endif
}
bool operator==(const v128& right) const
{
return _mm_movemask_epi8(v128::eq32(*this, right).vi) == 0xffff;
}
bool operator!=(const v128& right) const
{
return !operator==(right);
}
// result = (~left) & (right)
static inline v128 andnot(const v128& left, const v128& right)
{
return fromV(_mm_andnot_si128(left.vi, right.vi));
}
void clear()
{
*this = {};
}
};
template <typename T, std::size_t N, std::size_t M>
struct offset32_array<v128::masked_array_t<T, N, M>>
{
template <typename Arg>
static inline u32 index32(const Arg& arg)
{
return u32{sizeof(T)} * (static_cast<u32>(arg) ^ static_cast<u32>(M));
}
};
inline v128 operator|(const v128& left, const v128& right)
{
return v128::fromV(_mm_or_si128(left.vi, right.vi));
}
inline v128 operator&(const v128& left, const v128& right)
{
return v128::fromV(_mm_and_si128(left.vi, right.vi));
}
inline v128 operator^(const v128& left, const v128& right)
{
return v128::fromV(_mm_xor_si128(left.vi, right.vi));
}
inline v128 operator~(const v128& other)
{
return other ^ v128::from32p(UINT32_MAX); // XOR with ones
}
using stx::se_t;
using stx::se_storage;
// se_t<> with native endianness
template <typename T, std::size_t Align = alignof(T)>
using nse_t = se_t<T, false, Align>;
template <typename T, std::size_t Align = alignof(T)>
using be_t = se_t<T, std::endian::little == std::endian::native, Align>;
template <typename T, std::size_t Align = alignof(T)>
using le_t = se_t<T, std::endian::big == std::endian::native, Align>;
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
template <typename T, bool Se, typename = void>
struct to_se
{
template <typename T2, typename = void>
struct to_se_
{
using type = T2;
};
template <typename T2>
struct to_se_<T2, std::enable_if_t<std::is_arithmetic<T2>::value || std::is_enum<T2>::value>>
{
using type = std::conditional_t<(sizeof(T2) > 1), se_t<T2, Se>, T2>;
};
// Convert arithmetic and enum types
using type = typename to_se_<T>::type;
};
template <bool Se>
struct to_se<v128, Se>
{
using type = se_t<v128, Se>;
};
template <bool Se>
struct to_se<u128, Se>
{
using type = se_t<u128, Se>;
};
template <bool Se>
struct to_se<s128, Se>
{
using type = se_t<s128, Se>;
};
template <typename T, bool Se>
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
{
// Move const qualifier
using type = const typename to_se<T, Se>::type;
};
template <typename T, bool Se>
struct to_se<volatile T, Se, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>>
{
// Move volatile qualifier
using type = volatile typename to_se<T, Se>::type;
};
template <typename T, bool Se>
struct to_se<T[], Se>
{
// Move array qualifier
using type = typename to_se<T, Se>::type[];
};
template <typename T, bool Se, std::size_t N>
struct to_se<T[N], Se>
{
// Move array qualifier
using type = typename to_se<T, Se>::type[N];
};
// BE/LE aliases for to_se<>
template <typename T>
using to_be_t = typename to_se<T, std::endian::little == std::endian::native>::type;
template <typename T>
using to_le_t = typename to_se<T, std::endian::big == std::endian::native>::type;
// BE/LE aliases for atomic_t
template <typename T>
using atomic_be_t = atomic_t<be_t<T>>;
template <typename T>
using atomic_le_t = atomic_t<le_t<T>>;
template <typename T, bool Se, std::size_t Align>
struct fmt_unveil<se_t<T, Se, Align>, void>
{
using type = typename fmt_unveil<T>::type;
static inline auto get(const se_t<T, Se, Align>& arg)
{
return fmt_unveil<T>::get(arg);
}
};
#endif // BETYPE_H_GUARD
+4 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#pragma once
#include "types.h"
#include "util/types.hpp"
#include "Utilities/StrFmt.h"
template<typename T, uint N>
struct bf_base
@@ -147,7 +148,7 @@ struct bf_t : bf_base<T, N>
bf_t& operator &=(vtype right)
{
this->m_data &= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
this->m_data &= static_cast<vtype>(((static_cast<utype>(right) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos));
return *this;
}
+3 -3
View File
@@ -1,6 +1,6 @@
#pragma once
#include <Utilities/types.h>
#include "util/types.hpp"
#ifdef _WIN32
#include "windows.h"
@@ -176,7 +176,7 @@ public:
};
u_int miblen = std::size(mib);
struct kinfo_proc info;
size_t size = sizeof(info);
usz size = sizeof(info);
if (sysctl(mib, miblen, &info, &size, NULL, 0))
{
return 0;
@@ -194,7 +194,7 @@ public:
u_int miblen = std::size(mib);
// get number of structs
size_t size;
usz size;
if (sysctl(mib, miblen, NULL, &size, NULL, 0))
{
return 0;
+11 -13
View File
@@ -1,14 +1,12 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Config.h"
#include "Utilities/types.h"
#include "util/types.hpp"
#include "util/yaml.hpp"
#include <typeinfo>
#include <charconv>
[[noreturn]] void report_fatal_error(const std::string&);
LOG_CHANNEL(cfg_log, "CFG");
namespace cfg
@@ -18,7 +16,7 @@ namespace cfg
{
if (_type != type::node)
{
cfg_log.fatal("Invalid root node" HERE);
cfg_log.fatal("Invalid root node");
}
}
@@ -29,7 +27,7 @@ namespace cfg
{
if (pair.first == name)
{
cfg_log.fatal("Node already exists: %s" HERE, name);
cfg_log.fatal("Node already exists: %s", name);
}
}
@@ -38,12 +36,12 @@ namespace cfg
bool _base::from_string(const std::string&, bool)
{
report_fatal_error("from_string() purecall" HERE);
fmt::throw_exception("from_string() purecall");
}
bool _base::from_list(std::vector<std::string>&&)
{
report_fatal_error("from_list() purecall" HERE);
fmt::throw_exception("from_list() purecall");
}
// Emit YAML
@@ -84,7 +82,7 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
{
if (out) cfg_log.error("cfg::try_to_int('%s'): invalid integer", value);
if (out) cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value);
return false;
}
@@ -92,7 +90,7 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
if (result < min || result > max)
{
if (out) cfg_log.error("cfg::try_to_int('%s'): out of bounds (%d..%d)", value, min, max);
if (out) cfg_log.error("cfg::try_to_int64('%s'): out of bounds (%d..%d)", value, min, max);
return false;
}
@@ -123,13 +121,13 @@ bool cfg::try_to_uint64(u64* out, const std::string& value, u64 min, u64 max)
if (ret.ec != std::errc() || ret.ptr != end)
{
if (out) cfg_log.error("cfg::try_to_int('%s'): invalid integer", value);
if (out) cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value);
return false;
}
if (result < min || result > max)
{
if (out) cfg_log.error("cfg::try_to_int('%s'): out of bounds (%u..%u)", value, min, max);
if (out) cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (%u..%u)", value, min, max);
return false;
}
@@ -380,7 +378,7 @@ void cfg::_bool::from_default()
void cfg::string::from_default()
{
m_value = m_value.make(def);
m_value = def;
}
void cfg::set_entry::from_default()
+12 -7
View File
@@ -1,10 +1,10 @@
#pragma once
#pragma once
#include "Utilities/types.h"
#include "util/types.hpp"
#include "Utilities/StrFmt.h"
#include "util/logs.hpp"
#include "util/atomic.hpp"
#include "util/shared_cptr.hpp"
#include "util/shared_ptr.hpp"
#include <utility>
#include <string>
@@ -203,6 +203,11 @@ namespace cfg
return m_value;
}
void set(T value)
{
m_value = value;
}
void from_default() override
{
m_value = def;
@@ -388,7 +393,7 @@ namespace cfg
{
const std::string m_name;
stx::atomic_cptr<std::string> m_value;
atomic_ptr<std::string> m_value;
public:
std::string def;
@@ -396,7 +401,7 @@ namespace cfg
string(node* owner, std::string name, std::string def = {}, bool dynamic = false)
: _base(type::string, owner, name, dynamic)
, m_name(std::move(name))
, m_value(m_value.make(def))
, m_value(def)
, def(std::move(def))
{
}
@@ -406,7 +411,7 @@ namespace cfg
return *m_value.load().get();
}
std::pair<const std::string&, stx::shared_cptr<std::string>> get() const
std::pair<const std::string&, shared_ptr<std::string>> get() const
{
auto v = m_value.load();
@@ -435,7 +440,7 @@ namespace cfg
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{
m_value = m_value.make(value);
m_value = value;
return true;
}
};
+234 -161
View File
@@ -1,7 +1,6 @@
#include "File.h"
#include "File.h"
#include "mutex.h"
#include "StrFmt.h"
#include "BEType.h"
#include "Crypto/sha1.h"
#include <unordered_map>
@@ -11,6 +10,8 @@
#include <typeinfo>
#include <map>
#include "util/asm.hpp"
using namespace std::literals::string_literals;
#ifdef _WIN32
@@ -21,10 +22,10 @@ using namespace std::literals::string_literals;
static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
{
// String size + null terminator
const std::size_t buf_size = source.size() + 1;
const usz buf_size = source.size() + 1;
// Safe size
const int size = narrow<int>(buf_size, "to_wchar" HERE);
const int size = narrow<int>(buf_size);
// Buffer for max possible output length
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size + 8 + 32768]);
@@ -41,10 +42,10 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
std::memcpy(buffer.get() + 32768 + 4, L"UNC\\", 4 * sizeof(wchar_t));
}
verify("to_wchar" HERE), MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get() + 32768 + (unc ? 8 : 4), size);
ensure(MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get() + 32768 + (unc ? 8 : 4), size)); // "to_wchar"
// Canonicalize wide path (replace '/', ".", "..", \\ repetitions, etc)
verify("to_wchar" HERE), GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1;
ensure(GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1); // "to_wchar"
return buffer;
}
@@ -52,10 +53,10 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
static void to_utf8(std::string& out, const wchar_t* source)
{
// String size
const std::size_t length = std::wcslen(source);
const usz length = std::wcslen(source);
// Safe buffer size for max possible output length (including null terminator)
const int buf_size = narrow<int>(length * 3 + 1, "to_utf8" HERE);
const int buf_size = narrow<int>(length * 3 + 1);
// Resize buffer
out.resize(buf_size - 1);
@@ -63,7 +64,7 @@ static void to_utf8(std::string& out, const wchar_t* source)
const int result = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &out.front(), buf_size, NULL, NULL);
// Fix the size
out.resize(verify("to_utf8" HERE, result) - 1);
out.resize(ensure(result) - 1);
}
static time_t to_time(const ULARGE_INTEGER& ft)
@@ -182,7 +183,7 @@ static std::string path_append(std::string_view path, std::string_view more)
{
std::string result;
if (const size_t src_slash_pos = path.find_last_not_of('/'); src_slash_pos != path.npos)
if (const usz src_slash_pos = path.find_last_not_of('/'); src_slash_pos != path.npos)
{
path.remove_suffix(path.length() - src_slash_pos - 1);
result = path;
@@ -190,7 +191,7 @@ static std::string path_append(std::string_view path, std::string_view more)
result.push_back('/');
if (const size_t dst_slash_pos = more.find_first_not_of('/'); dst_slash_pos != more.npos)
if (const usz dst_slash_pos = more.find_first_not_of('/'); dst_slash_pos != more.npos)
{
more.remove_prefix(dst_slash_pos);
result.append(more);
@@ -315,33 +316,19 @@ std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device)
{
verify(HERE), name.starts_with("//"), name[2] != '/';
ensure(name.starts_with("//") && name[2] != '/');
return get_device_manager().set_device(name, device);
}
std::string fs::get_parent_dir(const std::string& path)
{
// Search upper bound (set to the last character, npos for empty string)
auto last = path.size() - 1;
// Get (basically) processed path
const auto real_path = fs::escape_path(path);
#ifdef _WIN32
const auto& delim = "/\\";
#else
const auto& delim = "/";
#endif
const auto pos = real_path.find_last_of(delim);
while (true)
{
const auto pos = path.find_last_of(delim, last, sizeof(delim) - 1);
// Contiguous slashes are ignored at the end
if (std::exchange(last, pos - 1) != pos)
{
// Return empty string if the path doesn't contain at least 2 elements
return path.substr(0, pos != umax && path.find_last_not_of(delim, pos, sizeof(delim) - 1) != umax ? pos : 0);
}
}
return real_path.substr(0, pos == umax ? 0 : pos);
}
bool fs::stat(const std::string& path, stat_t& info)
@@ -352,16 +339,83 @@ bool fs::stat(const std::string& path, stat_t& info)
}
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
std::string_view epath = path;
// '/' and '\\' Not allowed by FindFirstFileExW at the end of path but we should allow it
if (auto not_del = epath.find_last_not_of(delim); not_del != umax && not_del != epath.size() - 1)
{
epath.remove_suffix(epath.size() - 1 - not_del);
}
// Handle drives specially
if (epath.find_first_of(delim) == umax && epath.ends_with(':'))
{
WIN32_FILE_ATTRIBUTE_DATA attrs;
// Must end with a delimiter
if (!GetFileAttributesExW(to_wchar(std::string(epath) + '/').get(), GetFileExInfoStandard, &attrs))
{
g_tls_error = to_error(GetLastError());
return false;
}
info.is_directory = true; // Handle drives as directories
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = attrs.nFileSizeLow | (u64{attrs.nFileSizeHigh} << 32);
info.atime = to_time(attrs.ftLastAccessTime);
info.mtime = to_time(attrs.ftLastWriteTime);
info.ctime = info.mtime;
if (info.atime < info.mtime)
info.atime = info.mtime;
return true;
}
WIN32_FIND_DATA attrs;
// Allowed by FindFirstFileExW but we should not allow it
if (epath.ends_with("*"))
{
g_tls_error = fs::error::noent;
return false;
}
const auto wchar_ptr = to_wchar(std::string(epath));
const std::wstring_view wpath_view = wchar_ptr.get();
const HANDLE handle = FindFirstFileExW(wpath_view.data(), FindExInfoStandard, &attrs, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_CASE_SENSITIVE);
if (handle == INVALID_HANDLE_VALUE)
{
g_tls_error = to_error(GetLastError());
return false;
}
struct close_t
{
HANDLE handle;
~close_t() { FindClose(handle); }
};
for (close_t find_manage{handle}; attrs.cFileName != wpath_view.substr(wpath_view.find_last_of(wdelim) + 1);)
{
if (!FindNextFileW(handle, &attrs))
{
if (const DWORD err = GetLastError(); err != ERROR_NO_MORE_FILES)
{
g_tls_error = to_error(err);
return false;
}
g_tls_error = fs::error::noent;
return false;
}
}
info.is_directory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = (u64)attrs.nFileSizeLow | ((u64)attrs.nFileSizeHigh << 32);
info.size = attrs.nFileSizeLow | (u64{attrs.nFileSizeHigh} << 32);
info.atime = to_time(attrs.ftLastAccessTime);
info.mtime = to_time(attrs.ftLastWriteTime);
info.ctime = info.mtime;
@@ -389,73 +443,19 @@ bool fs::stat(const std::string& path, stat_t& info)
bool fs::exists(const std::string& path)
{
if (auto device = get_virtual_device(path))
{
stat_t info;
return device->stat(path, info);
}
#ifdef _WIN32
if (GetFileAttributesW(to_wchar(path).get()) == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
return true;
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
return true;
#endif
fs::stat_t info{};
return fs::stat(path, info);
}
bool fs::is_file(const std::string& path)
{
if (auto device = get_virtual_device(path))
fs::stat_t info{};
if (!fs::stat(path, info))
{
stat_t info;
if (!device->stat(path, info))
{
return false;
}
if (info.is_directory)
{
g_tls_error = error::exist;
return false;
}
return true;
}
#ifdef _WIN32
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
#endif
// TODO: correct file type check
#ifdef _WIN32
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)
#else
if (S_ISDIR(file_info.st_mode))
#endif
if (info.is_directory)
{
g_tls_error = error::exist;
return false;
@@ -466,44 +466,13 @@ bool fs::is_file(const std::string& path)
bool fs::is_dir(const std::string& path)
{
if (auto device = get_virtual_device(path))
fs::stat_t info{};
if (!fs::stat(path, info))
{
stat_t info;
if (!device->stat(path, info))
{
return false;
}
if (info.is_directory == false)
{
g_tls_error = error::exist;
return false;
}
return true;
}
#ifdef _WIN32
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
g_tls_error = to_error(errno);
return false;
}
#endif
#ifdef _WIN32
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
#else
if (!S_ISDIR(file_info.st_mode))
#endif
if (!info.is_directory)
{
g_tls_error = error::exist;
return false;
@@ -538,7 +507,7 @@ bool fs::statfs(const std::string& path, fs::device_stat& info)
// Keep cutting path from right until it's short enough
while (str.size() > 256)
{
if (std::size_t x = str.find_last_of('\\') + 1)
if (usz x = str.find_last_of('\\') + 1)
str.resize(x - 1);
else
break;
@@ -781,7 +750,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
// sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytes_copied = 0;
struct ::stat fileinfo = { 0 };
if (::fstat(input, &fileinfo) || ::sendfile(output, input, &bytes_copied, fileinfo.st_size))
if (::fstat(input, &fileinfo) == -1 || ::sendfile(output, input, &bytes_copied, fileinfo.st_size) == -1)
#else
#error "Native file copy implementation is missing"
#endif
@@ -899,7 +868,7 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
#ifdef _WIN32
// Open the file
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
g_tls_error = to_error(GetLastError());
@@ -932,14 +901,19 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
#endif
}
void fs::file::xnull() const
[[noreturn]] void fs::xnull(const src_loc& loc)
{
fmt::throw_exception("fs::file is null");
fmt::throw_exception("Null object.%s", loc);
}
void fs::file::xfail() const
[[noreturn]] void fs::xfail(const src_loc& loc)
{
fmt::throw_exception("Unexpected fs::error %s", g_tls_error);
fmt::throw_exception("Unexpected fs::error %s%s", g_tls_error, loc);
}
[[noreturn]] void fs::xovfl()
{
fmt::throw_exception("Stream overflow.");
}
fs::file::file(const std::string& path, bs_t<open_mode> mode)
@@ -985,7 +959,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
disp = mode & fs::trunc ? TRUNCATE_EXISTING : OPEN_EXISTING;
}
DWORD share = 0;
DWORD share = FILE_SHARE_DELETE;
if (!(mode & fs::unread) || !(mode & fs::write))
{
share |= FILE_SHARE_READ;
@@ -993,7 +967,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
if (!(mode & (fs::lock + fs::unread)) || !(mode & fs::write))
{
share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
share |= FILE_SHARE_WRITE;
}
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -1022,7 +996,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
stat_t stat() override
{
FILE_BASIC_INFO basic_info;
verify("file::stat" HERE), GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
ensure(GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO))); // "file::stat"
stat_t info;
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
@@ -1040,7 +1014,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
void sync() override
{
verify("file::sync" HERE), FlushFileBuffers(m_handle);
ensure(FlushFileBuffers(m_handle)); // "file::sync"
}
bool trunc(u64 length) override
@@ -1060,10 +1034,10 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 read(void* buffer, u64 count) override
{
// TODO (call ReadFile multiple times if count is too big)
const int size = narrow<int>(count, "file::read" HERE);
const int size = narrow<int>(count);
DWORD nread;
verify("file::read" HERE), ReadFile(m_handle, buffer, size, &nread, NULL);
ensure(ReadFile(m_handle, buffer, size, &nread, NULL)); // "file::read"
return nread;
}
@@ -1071,10 +1045,10 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override
{
// TODO (call WriteFile multiple times if count is too big)
const int size = narrow<int>(count, "file::write" HERE);
const int size = narrow<int>(count);
DWORD nwritten;
verify("file::write" HERE), WriteFile(m_handle, buffer, size, &nwritten, NULL);
ensure(WriteFile(m_handle, buffer, size, &nwritten, NULL)); // "file::write"
return nwritten;
}
@@ -1088,7 +1062,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
whence == seek_set ? FILE_BEGIN :
whence == seek_cur ? FILE_CURRENT :
whence == seek_end ? FILE_END :
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
(fmt::throw_exception("Invalid whence (0x%x)", whence), 0);
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
{
@@ -1102,7 +1076,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 size() override
{
LARGE_INTEGER size;
verify("file::size" HERE), GetFileSizeEx(m_handle, &size);
ensure(GetFileSizeEx(m_handle, &size)); // "file::size"
return size.QuadPart;
}
@@ -1151,7 +1125,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
if (mode & fs::trunc && mode & (fs::lock + fs::unread) && mode & fs::write)
{
// Postpone truncation in order to avoid using O_TRUNC on a locked file
verify(HERE), ::ftruncate(fd, 0) == 0;
ensure(::ftruncate(fd, 0) == 0);
}
class unix_file final : public file_base
@@ -1172,7 +1146,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
stat_t stat() override
{
struct ::stat file_info;
verify("file::stat" HERE), ::fstat(m_fd, &file_info) == 0;
ensure(::fstat(m_fd, &file_info) == 0); // "file::stat"
stat_t info;
info.is_directory = S_ISDIR(file_info.st_mode);
@@ -1190,7 +1164,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
void sync() override
{
verify("file::sync" HERE), ::fsync(m_fd) == 0;
ensure(::fsync(m_fd) == 0); // "file::sync"
}
bool trunc(u64 length) override
@@ -1207,7 +1181,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 read(void* buffer, u64 count) override
{
const auto result = ::read(m_fd, buffer, count);
verify("file::read" HERE), result != -1;
ensure(result != -1); // "file::read"
return result;
}
@@ -1215,7 +1189,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override
{
const auto result = ::write(m_fd, buffer, count);
verify("file::write" HERE), result != -1;
ensure(result != -1); // "file::write"
return result;
}
@@ -1226,7 +1200,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
whence == seek_set ? SEEK_SET :
whence == seek_cur ? SEEK_CUR :
whence == seek_end ? SEEK_END :
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
(fmt::throw_exception("Invalid whence (0x%x)", whence), 0);
const auto result = ::lseek(m_fd, offset, mode);
@@ -1242,7 +1216,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 size() override
{
struct ::stat file_info;
verify("file::size" HERE), ::fstat(m_fd, &file_info) == 0;
ensure(::fstat(m_fd, &file_info) == 0); // "file::size"
return file_info.st_size;
}
@@ -1258,7 +1232,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
static_assert(offsetof(iovec, iov_len) == offsetof(iovec_clone, iov_len), "Weird iovec::iov_len offset");
const auto result = ::writev(m_fd, reinterpret_cast<const iovec*>(buffers), buf_count);
verify("file::write_gather" HERE), result != -1;
ensure(result != -1); // "file::write_gather"
return result;
}
@@ -1268,7 +1242,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
#endif
}
fs::file::file(const void* ptr, std::size_t size)
fs::file::file(const void* ptr, usz size)
{
class memory_stream : public file_base
{
@@ -1350,11 +1324,6 @@ fs::native_handle fs::file::get_handle() const
#endif
}
void fs::dir::xnull() const
{
fmt::throw_exception("fs::dir is null");
}
bool fs::dir::open(const std::string& path)
{
if (path.empty())
@@ -1388,7 +1357,7 @@ bool fs::dir::open(const std::string& path)
class windows_dir final : public dir_base
{
std::vector<dir_entry> m_entries;
std::size_t m_pos = 0;
usz m_pos = 0;
void add_entry(const WIN32_FIND_DATAW& found)
{
@@ -1418,7 +1387,7 @@ bool fs::dir::open(const std::string& path)
add_entry(found);
}
verify("dir::read" HERE), ERROR_NO_MORE_FILES == GetLastError();
ensure(ERROR_NO_MORE_FILES == GetLastError()); // "dir::read"
FindClose(handle);
}
@@ -1634,6 +1603,110 @@ bool fs::remove_all(const std::string& path, bool remove_root)
return true;
}
std::string fs::escape_path(std::string_view path)
{
std::string real; real.resize(path.size());
auto get_char = [&](usz& from, usz& to, usz count)
{
std::memcpy(&real[to], &path[from], count);
from += count, to += count;
};
usz i = 0, j = -1, pos_nondelim = 0, after_delim = 0;
if (i < path.size())
{
j = 0;
}
for (; i < path.size();)
{
real[j] = path[i];
#ifdef _Win32
if (real[j] == '\\')
{
real[j] = '/';
}
#endif
// If the current character was preceeded by a delimiter special treatment is required:
// If another deleimiter is encountered, remove it (do not write it to output string)
// Otherwise test if it is a "." or ".." sequence.
if (std::exchange(after_delim, path[i] == delim[0] || path[i] == delim[1]))
{
if (!after_delim)
{
if (real[j] == '.')
{
if (i + 1 == path.size())
{
break;
}
get_char(i, j, 1);
switch (real[j])
{
case '.':
{
bool remove_element = true;
usz k = 1;
for (; k + i != path.size(); k++)
{
switch (path[i + k])
{
case '.': continue;
case delim[0]: case delim[1]: break;
default: remove_element = false; break;
}
}
if (remove_element)
{
if (i == 1u)
{
j = pos_nondelim;
real[j] = '\0';// Ensure termination at this posistion
after_delim = true;
i += k;
continue;
}
}
get_char(i, j, k);
continue;
}
case '/':
{
i++;
after_delim = true;
continue;
}
default: get_char(i, j, 1); continue;
}
}
pos_nondelim = j;
get_char(i, j, 1);
}
else
{
i++;
}
}
else
{
get_char(i, j, 1);
}
}
if (j != umax && (real[j] == delim[0] || real[j] == delim[1])) j--; // Do not include a delmiter at the end
real.resize(j + 1);
return real;
}
u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
{
u64 result = 0;
@@ -1642,7 +1715,7 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
if (!root_dir)
{
return static_cast<u64>(umax);
return -1;
}
for (const auto& entry : root_dir)
@@ -1654,7 +1727,7 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
if (!entry.is_directory)
{
result += ::align(entry.size, rounding_alignment);
result += utils::align(entry.size, rounding_alignment);
}
else
{
+165 -62
View File
@@ -1,6 +1,6 @@
#pragma once
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
#include "types.h"
#include "util/types.hpp"
#include "bit_set.h"
#include <memory>
@@ -8,12 +8,15 @@
#include <vector>
#include <algorithm>
namespace fs
{
#ifdef _WIN32
static constexpr auto& delim = "/\\";
static constexpr auto& wdelim = L"/\\";
using native_handle = void*;
#else
static constexpr auto& delim = "/";
static constexpr auto& wdelim = L"/";
using native_handle = int;
#endif
@@ -70,7 +73,7 @@ namespace fs
struct iovec_clone
{
const void* iov_base;
std::size_t iov_len;
usz iov_len;
};
// File handle base
@@ -131,6 +134,12 @@ namespace fs
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
};
[[noreturn]] void xnull(const src_loc&);
[[noreturn]] void xfail(const src_loc&);
[[noreturn]] void xovfl();
constexpr struct pod_tag_t{} pod_tag;
// Get virtual device for specified path (nullptr for real path)
std::shared_ptr<device_base> get_virtual_device(const std::string& path);
@@ -183,9 +192,6 @@ namespace fs
{
std::unique_ptr<file_base> m_file;
[[noreturn]] void xnull() const;
[[noreturn]] void xfail() const;
public:
// Default constructor
file() = default;
@@ -194,7 +200,7 @@ namespace fs
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read);
// Open memory for read
explicit file(const void* ptr, std::size_t size);
explicit file(const void* ptr, usz size);
// Open file with specified args (forward to constructor)
template <typename... Args>
@@ -227,144 +233,227 @@ namespace fs
}
// Change file size (possibly appending zero bytes)
bool trunc(u64 length) const
bool trunc(u64 length,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->trunc(length);
}
// Get file information
stat_t stat() const
stat_t stat(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->stat();
}
// Sync file buffers
void sync() const
void sync(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->sync();
}
// Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count) const
u64 read(void* buffer, u64 count,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->read(buffer, count);
}
// Write the data to the file and return the amount of data actually written
u64 write(const void* buffer, u64 count) const
u64 write(const void* buffer, u64 count,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->write(buffer, count);
}
// Change current position, returns resulting position
u64 seek(s64 offset, seek_mode whence = seek_set) const
u64 seek(s64 offset, seek_mode whence = seek_set,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->seek(offset, whence);
}
// Get file size
u64 size() const
u64 size(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->size();
}
// Get current position
u64 pos() const
u64 pos(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->seek(0, seek_cur);
}
// Write std::string unconditionally
const file& write(const std::string& str) const
// 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,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (write(str.data(), str.size()) != str.size()) xfail();
if (write(str.data(), str.size() * sizeof(T), line, col, file, func) != str.size() * sizeof(T)) xfail({line, col, file, func});
return *this;
}
// 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) const
std::enable_if_t<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(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (write(std::addressof(data), sizeof(T)) != sizeof(T)) xfail();
if (write(std::addressof(data), sizeof(T), line, col, file, func) != sizeof(T)) xfail({line, col, file, func});
return *this;
}
// 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) const
std::enable_if_t<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(),
const char* func = __builtin_FUNCTION()) const
{
if (write(vec.data(), vec.size() * sizeof(T)) != vec.size() * sizeof(T)) xfail();
if (write(vec.data(), vec.size() * sizeof(T), line, col, file, func) != vec.size() * sizeof(T)) xfail({line, col, file, func});
return *this;
}
// Read std::string, size must be set by resize() method
bool read(std::string& str) const
// 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()) == str.size();
return read(&str[0], str.size() * sizeof(T), line, col, file, func) == str.size() * sizeof(T);
}
// Read std::string
bool read(std::string& str, std::size_t size) const
// Read std::basic_string
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, usz size,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
str.resize(size);
return read(&str[0], size) == size;
return read(&str[0], size * sizeof(T), line, col, file, func) == size * sizeof(T);
}
// 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) const
std::enable_if_t<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)) == sizeof(T);
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
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()) == sizeof(T) * vec.size();
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
}
// Read POD std::vector
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, std::size_t size) const
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz size,
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN()) const
{
vec.resize(size);
return read(vec.data(), sizeof(T) * size) == sizeof(T) * size;
return read(vec.data(), sizeof(T) * size, line, col, file, func) == sizeof(T) * size;
}
// Read POD (experimental)
template <typename T>
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, T> read() const
std::enable_if_t<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(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
T result;
if (!read(result)) xfail();
if (!read(result, pod_tag, line, col, file, func)) xfail({line, col, file, func});
return result;
}
// Read full file to std::string
std::string to_string() const
// Read full file to std::basic_string
template <typename T = char>
std::basic_string<T> to_string(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
std::string result;
result.resize(size());
if (seek(0), !read(result)) xfail();
std::basic_string<T> result;
result.resize(size() / sizeof(T));
if (seek(0), !read(result, 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() const
std::enable_if_t<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(),
const char* func = __builtin_FUNCTION()) const
{
std::vector<T> result;
result.resize(size() / sizeof(T));
if (seek(0), !read(result)) xfail();
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
return result;
}
@@ -372,9 +461,13 @@ namespace fs
native_handle get_handle() const;
// Gathered write
u64 write_gather(const iovec_clone* buffers, u64 buf_count) const
u64 write_gather(const iovec_clone* buffers, u64 buf_count,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_file) xnull();
if (!m_file) xnull({line, col, file, func});
return m_file->write_gather(buffers, buf_count);
}
};
@@ -383,8 +476,6 @@ namespace fs
{
std::unique_ptr<dir_base> m_dir;
[[noreturn]] void xnull() const;
public:
dir() = default;
@@ -420,16 +511,24 @@ namespace fs
}
// Get next directory entry
bool read(dir_entry& out) const
bool read(dir_entry& out,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_dir) xnull();
if (!m_dir) xnull({line, col, file, func});
return m_dir->read(out);
}
// Reset to the beginning
void rewind() const
void rewind(
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) const
{
if (!m_dir) xnull();
if (!m_dir) xnull({line, col, file, func});
return m_dir->rewind();
}
@@ -498,6 +597,9 @@ namespace fs
// Get common cache directory
const std::string& get_cache_dir();
// Get real path for comparisons (TODO: investigate std::filesystem::path::compare implementation)
std::string escape_path(std::string_view path);
// Delete directory and all its contents recursively
bool remove_all(const std::string& path, bool remove_root = true);
@@ -572,7 +674,7 @@ namespace fs
if (old_size + size < old_size)
{
fmt::raw_error("fs::container_stream<>::write(): overflow");
xovfl();
}
if (pos > old_size)
@@ -628,7 +730,8 @@ namespace fs
template <typename... Args>
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
{
if (fs::file f{path, mode})
// Always use write flag, remove read flag
if (fs::file f{path, mode + fs::write - fs::read})
{
// Write args sequentially
(f.write(args), ...);
+150 -624
View File
@@ -1,16 +1,16 @@
#include "types.h"
#include "util/types.hpp"
#include "util/sysinfo.hpp"
#include "JIT.h"
#include "StrFmt.h"
#include "File.h"
#include "util/logs.hpp"
#include "mutex.h"
#include "sysinfo.h"
#include "VirtualMemory.h"
#include "util/vm.hpp"
#include "util/asm.hpp"
#include <immintrin.h>
#include <zlib.h>
#ifdef __linux__
#include <sys/mman.h>
#define CAN_OVERCOMMIT
#endif
@@ -22,11 +22,8 @@ static u8* get_jit_memory()
static void* const s_memory2 = []() -> void*
{
void* ptr = utils::memory_reserve(0x80000000);
#ifdef CAN_OVERCOMMIT
utils::memory_commit(ptr, 0x80000000);
utils::memory_protect(ptr, 0x40000000, utils::protection::wx);
#endif
return ptr;
}();
@@ -40,7 +37,7 @@ static atomic_t<u64> s_code_pos{0}, s_data_pos{0};
static std::vector<u8> s_code_init, s_data_init;
template <atomic_t<u64>& Ctr, uint Off, utils::protection Prot>
static u8* add_jit_memory(std::size_t size, uint align)
static u8* add_jit_memory(usz size, uint align)
{
// Select subrange
u8* pointer = get_jit_memory() + Off;
@@ -56,8 +53,8 @@ static u8* add_jit_memory(std::size_t size, uint align)
// Simple allocation by incrementing pointer to the next free data
const u64 pos = Ctr.atomic_op([&](u64& ctr) -> u64
{
const u64 _pos = ::align(ctr & 0xffff'ffff, align);
const u64 _new = ::align(_pos + size, align);
const u64 _pos = utils::align(ctr & 0xffff'ffff, align);
const u64 _new = utils::align(_pos + size, align);
if (_new > 0x40000000) [[unlikely]]
{
@@ -73,7 +70,7 @@ static u8* add_jit_memory(std::size_t size, uint align)
// Check the necessity to commit more memory
if (_new > olda) [[unlikely]]
{
newa = ::align(_new, 0x100000);
newa = utils::align(_new, 0x200000);
}
ctr += _new - (ctr & 0xffff'ffff);
@@ -82,15 +79,13 @@ static u8* add_jit_memory(std::size_t size, uint align)
if (pos == umax) [[unlikely]]
{
jit_log.warning("JIT: Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
jit_log.error("JIT: Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
return nullptr;
}
if (olda != newa) [[unlikely]]
{
#ifdef CAN_OVERCOMMIT
madvise(pointer + olda, newa - olda, MADV_WILLNEED);
#else
#ifndef CAN_OVERCOMMIT
// Commit more memory
utils::memory_commit(pointer + olda, newa - olda, Prot);
#endif
@@ -118,7 +113,7 @@ jit_runtime::~jit_runtime()
asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
{
std::size_t codeSize = code->getCodeSize();
usz codeSize = code->getCodeSize();
if (!codeSize) [[unlikely]]
{
*dst = nullptr;
@@ -132,7 +127,7 @@ asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
return asmjit::kErrorNoVirtualMemory;
}
std::size_t relocSize = code->relocate(p);
usz relocSize = code->relocate(p);
if (!relocSize) [[unlikely]]
{
*dst = nullptr;
@@ -150,7 +145,7 @@ asmjit::Error jit_runtime::_release(void* ptr) noexcept
return asmjit::kErrorOk;
}
u8* jit_runtime::alloc(std::size_t size, uint align, bool exec) noexcept
u8* jit_runtime::alloc(usz size, uint align, bool exec) noexcept
{
if (exec)
{
@@ -194,56 +189,78 @@ void jit_runtime::finalize() noexcept
std::memcpy(alloc(s_data_init.size(), 1, false), s_data_init.data(), s_data_init.size());
}
asmjit::JitRuntime& asmjit::get_global_runtime()
asmjit::Runtime& asmjit::get_global_runtime()
{
// 16 MiB for internal needs
static constexpr u64 size = 1024 * 1024 * 16;
struct custom_runtime final : asmjit::HostRuntime
{
custom_runtime() noexcept
{
// Search starting in first 2 GiB of memory
for (u64 addr = size;; addr += size)
{
if (auto ptr = utils::memory_reserve(size, reinterpret_cast<void*>(addr)))
{
m_pos.raw() = static_cast<std::byte*>(ptr);
break;
}
}
// Initialize "end" pointer
m_max = m_pos + size;
// Make memory writable + executable
utils::memory_commit(m_pos, size, utils::protection::wx);
}
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override
{
usz codeSize = code->getCodeSize();
if (!codeSize) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoCodeGenerated;
}
void* p = m_pos.fetch_add(utils::align(codeSize, 4096));
if (!p || m_pos > m_max) [[unlikely]]
{
*dst = nullptr;
return asmjit::kErrorNoVirtualMemory;
}
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* ptr) noexcept override
{
return asmjit::kErrorOk;
}
private:
atomic_t<std::byte*> m_pos{};
std::byte* m_max{};
};
// Magic static
static asmjit::JitRuntime g_rt;
static custom_runtime g_rt;
return g_rt;
}
void asmjit::build_transaction_enter(asmjit::X86Assembler& c, asmjit::Label fallback, const asmjit::X86Gp& ctr, uint less_than)
{
Label fall = c.newLabel();
Label begin = c.newLabel();
c.jmp(begin);
c.bind(fall);
if (less_than < 65)
{
c.add(ctr, 1);
c.test(x86::eax, _XABORT_RETRY);
c.jz(fallback);
}
else
{
// Don't repeat on explicit XABORT instruction (workaround)
c.test(x86::eax, _XABORT_EXPLICIT);
c.jnz(fallback);
// Count an attempt without RETRY flag as 65 normal attempts and continue
c.push(x86::rax);
c.not_(x86::eax);
c.and_(x86::eax, _XABORT_RETRY);
c.shl(x86::eax, 5);
c.add(x86::eax, 1); // eax = RETRY ? 1 : 65
c.add(ctr, x86::rax);
c.pop(x86::rax);
}
c.cmp(ctr, less_than);
c.jae(fallback);
c.align(kAlignCode, 16);
c.bind(begin);
c.xbegin(fall);
}
void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code)
{
c.db(0xc6);
c.db(0xf8);
c.db(code);
}
#ifdef LLVM_AVAILABLE
#include <unordered_map>
@@ -263,9 +280,9 @@ void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code
#endif
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#ifdef _MSC_VER
#pragma warning(pop)
@@ -279,478 +296,102 @@ void asmjit::build_transaction_abort(asmjit::X86Assembler& c, unsigned char code
#include <sys/mman.h>
#endif
class LLVMSegmentAllocator
const bool jit_initialize = []() -> bool
{
public:
// Size of virtual memory area reserved: default 512MB
static constexpr u32 DEFAULT_SEGMENT_SIZE = 0x20000000;
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
LLVMLinkInMCJIT();
return true;
}();
LLVMSegmentAllocator()
{
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
LLVMLinkInMCJIT();
// Try to reserve as much virtual memory in the first 2 GB address space beforehand, if possible.
Segment found_segs[16];
u32 num_segs = 0;
#ifdef MAP_32BIT
u64 max_size = 0x80000000u;
while (num_segs < 16)
{
auto ptr = ::mmap(nullptr, max_size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, 0);
if (ptr != reinterpret_cast<void*>(-1))
found_segs[num_segs++] = Segment(ptr, static_cast<u32>(max_size));
else if (max_size > 0x1000000)
max_size -= 0x1000000;
else
break;
}
#else
u64 start_addr = 0x10000000;
while (num_segs < 16)
{
u64 max_addr = 0;
u64 max_size = 0x1000000;
for (u64 addr = start_addr; addr <= (0x80000000u - max_size); addr += 0x1000000)
{
for (auto curr_size = max_size; (0x80000000u - curr_size) >= addr; curr_size += 0x1000000)
{
if (auto ptr = utils::memory_reserve(curr_size, reinterpret_cast<void*>(addr)))
{
if (max_addr == 0 || max_size < curr_size)
{
max_addr = addr;
max_size = curr_size;
}
utils::memory_release(ptr, curr_size);
}
else
break;
}
}
if (max_addr == 0)
break;
if (auto ptr = utils::memory_reserve(max_size, reinterpret_cast<void*>(max_addr)))
found_segs[num_segs++] = Segment(ptr, static_cast<u32>(max_size));
start_addr = max_addr + max_size;
}
#endif
if (num_segs)
{
if (num_segs > 1)
{
m_segs.resize(num_segs);
for (u32 i = 0; i < num_segs; i++)
m_segs[i] = found_segs[i];
}
else
m_curr = found_segs[0];
return;
}
if (auto ptr = utils::memory_reserve(DEFAULT_SEGMENT_SIZE))
{
m_curr.addr = static_cast<u8*>(ptr);
m_curr.size = DEFAULT_SEGMENT_SIZE;
m_curr.used = 0;
}
}
void* allocate(u32 size)
{
if (m_curr.remaining() >= size)
return m_curr.advance(size);
if (reserve(size))
return m_curr.advance(size);
return nullptr;
}
bool reserve(u32 size)
{
if (size == 0)
return true;
store_curr();
u32 best_idx = UINT_MAX;
for (u32 i = 0, segs_size = ::size32(m_segs); i < segs_size; i++)
{
const auto seg_remaining = m_segs[i].remaining();
if (seg_remaining < size)
continue;
if (best_idx == UINT_MAX || m_segs[best_idx].remaining() > seg_remaining)
best_idx = i;
}
if (best_idx == UINT_MAX)
{
const auto size_to_reserve = (size > DEFAULT_SEGMENT_SIZE) ? ::align(size+4096, 4096) : DEFAULT_SEGMENT_SIZE;
if (auto ptr = utils::memory_reserve(size_to_reserve))
{
best_idx = ::size32(m_segs);
m_segs.emplace_back(ptr, size_to_reserve);
}
else
return false;
}
const auto& best_seg = m_segs[best_idx];
if (best_seg.addr != m_curr.addr)
m_curr = best_seg;
return true;
}
std::pair<u64, u32> current_segment() const
{
return std::make_pair(reinterpret_cast<u64>(m_curr.addr), m_curr.size);
}
std::pair<u64, u32> find_segment(u64 addr) const
{
for (const auto& seg: m_segs)
{
const u64 seg_addr = reinterpret_cast<u64>(seg.addr);
if (addr < seg_addr)
continue;
const auto end_addr = seg_addr + seg.size;
if (addr < end_addr)
return std::make_pair(seg_addr, seg.size);
}
return std::make_pair(0, 0);
}
void reset()
{
if (m_segs.empty())
{
if (m_curr.addr != nullptr)
{
utils::memory_decommit(m_curr.addr, m_curr.size);
m_curr.used = 0;
}
return;
}
if (store_curr())
m_curr = Segment();
auto allocated_it = std::remove_if(m_segs.begin(), m_segs.end(), [](const Segment& seg)
{
return reinterpret_cast<u64>(seg.addr + seg.size) > 0x80000000u;
});
if (allocated_it != m_segs.end())
{
for (auto it = allocated_it; it != m_segs.end(); ++it)
utils::memory_release(it->addr, it->size);
m_segs.erase(allocated_it, m_segs.end());
}
for (auto& seg : m_segs)
{
utils::memory_decommit(seg.addr, seg.size);
seg.used = 0;
}
}
private:
bool store_curr()
{
if (m_curr.addr != nullptr)
{
const auto wanted_addr = m_curr.addr;
auto existing_it = std::find_if(m_segs.begin(), m_segs.end(), [wanted_addr](const Segment& seg) { return seg.addr == wanted_addr; });
if (existing_it != m_segs.end())
existing_it->used = m_curr.used;
else
m_segs.push_back(m_curr);
return true;
}
return false;
}
struct Segment
{
Segment() {}
Segment(void* addr, u32 size)
: addr(static_cast<u8*>(addr))
, size(size)
{}
u8* addr = nullptr;
u32 size = 0;
u32 used = 0;
u32 remaining() const
{
if (size > used)
return size - used;
return 0;
}
void* advance(u32 offset)
{
const auto prev_used = used;
used += offset;
return &addr[prev_used];
}
};
Segment m_curr;
std::vector<Segment> m_segs;
};
// Memory manager mutex
static shared_mutex s_mutex;
// LLVM Memory allocator
static LLVMSegmentAllocator s_alloc;
#ifdef _WIN32
static std::deque<std::pair<u64, std::vector<RUNTIME_FUNCTION>>> s_unwater;
static std::vector<std::vector<RUNTIME_FUNCTION>> s_unwind; // .pdata
#else
static std::deque<std::pair<u8*, std::size_t>> s_unfire;
#endif
// Reset memory manager
extern void jit_finalize()
// Simple memory manager
struct MemoryManager1 : llvm::RTDyldMemoryManager
{
#ifdef _WIN32
for (auto&& unwind : s_unwind)
{
if (!RtlDeleteFunctionTable(unwind.data()))
{
jit_log.fatal("RtlDeleteFunctionTable() failed! Error %u", GetLastError());
}
}
s_unwind.clear();
#else
for (auto&& t : s_unfire)
{
llvm::RTDyldMemoryManager::deregisterEHFramesInProcess(t.first, t.second);
}
s_unfire.clear();
#endif
s_alloc.reset();
}
// Helper class
struct MemoryManager : llvm::RTDyldMemoryManager
{
std::unordered_map<std::string, u64>& m_link;
std::array<u8, 16>* m_tramps{};
u8* m_code_addr{}; // TODO
MemoryManager(std::unordered_map<std::string, u64>& table)
: m_link(table)
// 256 MiB for code or data
static constexpr u64 c_max_size = 0x20000000 / 2;
// Allocation unit (2M)
static constexpr u64 c_page_size = 2 * 1024 * 1024;
// Reserve 512 MiB
u8* const ptr = static_cast<u8*>(utils::memory_reserve(c_max_size * 2));
u64 code_ptr = 0;
u64 data_ptr = c_max_size;
MemoryManager1() = default;
~MemoryManager1() override
{
utils::memory_release(ptr, c_max_size * 2);
}
[[noreturn]] static void null()
{
fmt::throw_exception("Null function" HERE);
fmt::throw_exception("Null function");
}
llvm::JITSymbol findSymbol(const std::string& name) override
{
auto& addr = m_link[name];
u64 addr = RTDyldMemoryManager::getSymbolAddress(name);
// Find function address
if (!addr)
{
addr = RTDyldMemoryManager::getSymbolAddress(name);
if (addr)
{
jit_log.warning("LLVM: Symbol requested: %s -> 0x%016llx", name, addr);
}
else
{
jit_log.error("LLVM: Linkage failed: %s", name);
addr = reinterpret_cast<u64>(null);
}
}
// Verify address for small code model
const u64 code_start = reinterpret_cast<u64>(m_code_addr);
const s64 addr_diff = addr - code_start;
if (addr_diff < INT_MIN || addr_diff > INT_MAX)
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Allocate memory for trampolines
if (m_tramps)
{
const s64 tramps_diff = reinterpret_cast<u64>(m_tramps) - code_start;
if (tramps_diff < INT_MIN || tramps_diff > INT_MAX)
m_tramps = nullptr; //previously allocated trampoline section too far away now
}
if (!m_tramps)
{
m_tramps = reinterpret_cast<decltype(m_tramps)>(s_alloc.allocate(4096));
utils::memory_commit(m_tramps, 4096, utils::protection::wx);
}
// Create a trampoline
auto& data = *m_tramps++;
data[0x0] = 0xff; // JMP [rip+2]
data[0x1] = 0x25;
data[0x2] = 0x02;
data[0x3] = 0x00;
data[0x4] = 0x00;
data[0x5] = 0x00;
data[0x6] = 0x48; // MOV rax, imm64 (not executed)
data[0x7] = 0xb8;
std::memcpy(data.data() + 8, &addr, 8);
addr = reinterpret_cast<u64>(&data);
// Reset pointer (memory page exhausted)
if ((reinterpret_cast<u64>(m_tramps) % 4096) == 0)
{
m_tramps = nullptr;
}
addr = reinterpret_cast<uptr>(&null);
}
return {addr, llvm::JITSymbolFlags::Exported};
}
bool needsToReserveAllocationSpace() override { return true; }
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize, uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) override
u8* allocate(u64& oldp, uptr size, uint align, utils::protection prot)
{
const u32 wanted_code_size = ::align(static_cast<u32>(CodeSize), std::min(4096u, CodeAlign));
const u32 wanted_rodata_size = ::align(static_cast<u32>(RODataSize), std::min(4096u, RODataAlign));
const u32 wanted_rwdata_size = ::align(static_cast<u32>(RWDataSize), std::min(4096u, RWDataAlign));
// Lock memory manager
std::lock_guard lock(s_mutex);
// Setup segment for current module if needed
s_alloc.reserve(wanted_code_size + wanted_rodata_size + wanted_rwdata_size);
}
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
void* ptr = nullptr;
const u32 wanted_size = ::align(static_cast<u32>(size), 4096);
if (align > c_page_size)
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Simple allocation
ptr = s_alloc.allocate(wanted_size);
}
if (ptr == nullptr)
{
jit_log.fatal("LLVM: Out of memory (size=0x%llx, aligned 0x%x)", size, align);
return nullptr;
}
utils::memory_commit(ptr, size, utils::protection::wx);
m_code_addr = static_cast<u8*>(ptr);
jit_log.notice("LLVM: Code section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x)", sec_id, sec_name.data(), ptr, size, align);
return static_cast<u8*>(ptr);
}
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
void* ptr = nullptr;
const u32 wanted_size = ::align(static_cast<u32>(size), 4096);
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// Simple allocation
ptr = s_alloc.allocate(wanted_size);
}
if (ptr == nullptr)
{
jit_log.fatal("LLVM: Out of memory (size=0x%llx, aligned 0x%x)", size, align);
jit_log.fatal("JIT: Unsupported alignment (size=0x%x, align=0x%x)", size, align);
return nullptr;
}
if (!is_ro)
const u64 olda = utils::align(oldp, align);
const u64 newp = utils::align(olda + size, align);
if ((newp - 1) / c_max_size != oldp / c_max_size)
{
jit_log.fatal("JIT: Out of memory (size=0x%x, align=0x%x)", size, align);
return nullptr;
}
utils::memory_commit(ptr, size);
if ((oldp - 1) / c_page_size != (newp - 1) / c_page_size)
{
// Allocate pages on demand
const u64 pagea = utils::align(oldp, c_page_size);
const u64 psize = utils::align(newp - pagea, c_page_size);
utils::memory_commit(this->ptr + pagea, psize, prot);
}
jit_log.notice("LLVM: Data section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), ptr, size, align, is_ro ? "ro" : "rw");
return static_cast<u8*>(ptr);
// Update allocation counter
oldp = newp;
return this->ptr + olda;
}
u8* allocateCodeSection(uptr size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
return allocate(code_ptr, size, align, utils::protection::wx);
}
u8* allocateDataSection(uptr size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
return allocate(data_ptr, size, align, utils::protection::rw);
}
bool finalizeMemory(std::string* = nullptr) override
{
// Lock memory manager
std::lock_guard lock(s_mutex);
// TODO: make only read-only sections read-only
//#ifdef _WIN32
// DWORD op;
// VirtualProtect(s_memory, (u64)m_next - (u64)s_memory, PAGE_READONLY, &op);
// VirtualProtect(s_code_addr, s_code_size, PAGE_EXECUTE_READ, &op);
//#else
// ::mprotect(s_memory, (u64)m_next - (u64)s_memory, PROT_READ);
// ::mprotect(s_code_addr, s_code_size, PROT_READ | PROT_EXEC);
//#endif
return false;
}
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
void registerEHFrames(u8* addr, u64 load_addr, usz size) override
{
// Lock memory manager
std::lock_guard lock(s_mutex);
#ifdef _WIN32
// Fix RUNTIME_FUNCTION records (.pdata section)
decltype(s_unwater)::value_type pdata_entry = std::move(s_unwater.front());
s_unwater.pop_front();
// Use given memory segment as a BASE, compute the difference
const u64 segment_start = pdata_entry.first;
const u64 unwind_diff = (u64)addr - segment_start;
auto& pdata = pdata_entry.second;
for (auto& rf : pdata)
{
rf.UnwindData += static_cast<DWORD>(unwind_diff);
}
// Register .xdata UNWIND_INFO structs
if (!RtlAddFunctionTable(pdata.data(), (DWORD)pdata.size(), segment_start))
{
jit_log.error("RtlAddFunctionTable() failed! Error %u", GetLastError());
}
else
{
s_unwind.emplace_back(std::move(pdata));
}
#else
s_unfire.push_front(std::make_pair(addr, size));
#endif
return RTDyldMemoryManager::registerEHFramesInProcess(addr, size);
}
void deregisterEHFrames() override
@@ -767,12 +408,12 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
{
}
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
u8* allocateCodeSection(uptr size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
return jit_runtime::alloc(size, align, true);
}
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
u8* allocateDataSection(uptr size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
return jit_runtime::alloc(size, align, false);
}
@@ -782,60 +423,7 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
return false;
}
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
{
#ifndef _WIN32
RTDyldMemoryManager::registerEHFramesInProcess(addr, size);
{
// Lock memory manager
std::lock_guard lock(s_mutex);
s_unfire.push_front(std::make_pair(addr, size));
}
#endif
}
void deregisterEHFrames() override
{
}
};
// Simple memory manager. I promise there will be no MemoryManager4.
struct MemoryManager3 : llvm::RTDyldMemoryManager
{
std::vector<std::pair<u8*, std::size_t>> allocs;
MemoryManager3() = default;
~MemoryManager3() override
{
for (auto& a : allocs)
{
utils::memory_release(a.first, a.second);
}
}
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
{
u8* r = static_cast<u8*>(utils::memory_reserve(size));
utils::memory_commit(r, size, utils::protection::wx);
allocs.emplace_back(r, size);
return r;
}
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
{
u8* r = static_cast<u8*>(utils::memory_reserve(size));
utils::memory_commit(r, size);
allocs.emplace_back(r, size);
return r;
}
bool finalizeMemory(std::string* = nullptr) override
{
return false;
}
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
void registerEHFrames(u8* addr, u64 load_addr, usz size) override
{
}
@@ -844,64 +432,6 @@ struct MemoryManager3 : llvm::RTDyldMemoryManager
}
};
// Helper class
struct EventListener : llvm::JITEventListener
{
MemoryManager& m_mem;
EventListener(MemoryManager& mem)
: m_mem(mem)
{
}
void notifyObjectLoaded(ObjectKey K, const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
{
#ifdef _WIN32
for (auto it = obj.section_begin(), end = obj.section_end(); it != end; ++it)
{
llvm::StringRef name;
name = it->getName().get();
if (name == ".pdata")
{
llvm::StringRef data;
data = it->getContents().get();
std::vector<RUNTIME_FUNCTION> rfs(data.size() / sizeof(RUNTIME_FUNCTION));
auto offsets = reinterpret_cast<DWORD*>(rfs.data());
// Initialize .pdata section using relocation info
for (auto ri = it->relocation_begin(), end = it->relocation_end(); ri != end; ++ri)
{
if (ri->getType() == 3 /*R_X86_64_GOT32*/)
{
const u64 value = *reinterpret_cast<const DWORD*>(data.data() + ri->getOffset());
offsets[ri->getOffset() / sizeof(DWORD)] = static_cast<DWORD>(value + ri->getSymbol()->getAddress().get());
}
}
// Lock memory manager
std::lock_guard lock(s_mutex);
// Use current memory segment as a BASE, compute the difference
const u64 segment_start = s_alloc.current_segment().first;
const u64 code_diff = reinterpret_cast<u64>(m_mem.m_code_addr) - segment_start;
// Fix RUNTIME_FUNCTION records (.pdata section)
for (auto& rf : rfs)
{
rf.BeginAddress += static_cast<DWORD>(code_diff);
rf.EndAddress += static_cast<DWORD>(code_diff);
}
s_unwater.emplace_back(segment_start, std::move(rfs));
}
}
#endif
}
};
// Helper class
class ObjectCache final : public llvm::ObjectCache
{
@@ -923,7 +453,7 @@ public:
name.append(".gz");
z_stream zs{};
uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize(), HERE)) + 256;
uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize())) + 256;
auto zbuf = std::make_unique<uchar[]>(zsz);
#ifndef _MSC_VER
#pragma GCC diagnostic push
@@ -1104,20 +634,19 @@ std::string jit_compiler::cpu(const std::string& _cpu)
}
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags)
: m_link(_link)
, m_cpu(cpu(_cpu))
: m_cpu(cpu(_cpu))
{
std::string result;
auto null_mod = std::make_unique<llvm::Module> ("null_", m_context);
if (m_link.empty())
if (_link.empty())
{
std::unique_ptr<llvm::RTDyldMemoryManager> mem;
if (flags & 0x1)
{
mem = std::make_unique<MemoryManager3>();
mem = std::make_unique<MemoryManager1>();
}
else
{
@@ -1138,21 +667,18 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
else
{
// Primary JIT
auto mem = std::make_unique<MemoryManager>(m_link);
m_jit_el = std::make_unique<EventListener>(*mem);
m_engine.reset(llvm::EngineBuilder(std::move(null_mod))
.setErrorStr(&result)
.setEngineKind(llvm::EngineKind::JIT)
.setMCJITMemoryManager(std::move(mem))
.setMCJITMemoryManager(std::make_unique<MemoryManager1>())
.setOptLevel(llvm::CodeGenOpt::Aggressive)
.setCodeModel(flags & 0x2 ? llvm::CodeModel::Large : llvm::CodeModel::Small)
.setMCPU(m_cpu)
.create());
if (m_engine)
for (auto&& [name, addr] : _link)
{
m_engine->RegisterJITEventListener(m_jit_el.get());
m_engine->addGlobalMapping(name, addr);
}
}
+68 -22
View File
@@ -41,7 +41,7 @@ struct jit_runtime final : asmjit::HostRuntime
asmjit::Error _release(void* p) noexcept override;
// Allocate memory
static u8* alloc(std::size_t size, uint align, bool exec = true) noexcept;
static u8* alloc(usz size, uint align, bool exec = true) noexcept;
// Should be called at least once after global initialization
static void initialize();
@@ -53,18 +53,77 @@ struct jit_runtime final : asmjit::HostRuntime
namespace asmjit
{
// Should only be used to build global functions
asmjit::JitRuntime& get_global_runtime();
asmjit::Runtime& get_global_runtime();
// Emit xbegin and adjacent loop, return label at xbegin
void build_transaction_enter(X86Assembler& c, Label fallback, const X86Gp& ctr, uint less_than);
// Emit xbegin and adjacent loop, return label at xbegin (don't use xabort please)
template <typename F>
[[nodiscard]] inline asmjit::Label build_transaction_enter(asmjit::X86Assembler& c, asmjit::Label fallback, F func)
{
Label fall = c.newLabel();
Label begin = c.newLabel();
c.jmp(begin);
c.bind(fall);
// Emit xabort
void build_transaction_abort(X86Assembler& c, unsigned char code);
// Don't repeat on zero status (may indicate syscall or interrupt)
c.test(x86::eax, x86::eax);
c.jz(fallback);
// First invoked after failure (can fallback to proceed, or jump anywhere else)
func();
// Other bad statuses are ignored regardless of repeat flag (TODO)
c.align(kAlignCode, 16);
c.bind(begin);
return fall;
// xbegin should be issued manually, allows to add more check before entering transaction
}
// Helper to spill RDX (EDX) register for RDTSC
inline void build_swap_rdx_with(asmjit::X86Assembler& c, std::array<X86Gp, 4>& args, const asmjit::X86Gp& with)
{
#ifdef _WIN32
c.xchg(args[1], with);
args[1] = with;
#else
c.xchg(args[2], with);
args[2] = with;
#endif
}
// Get full RDTSC value into chosen register (clobbers rax/rdx or saves only rax with other target)
inline void build_get_tsc(asmjit::X86Assembler& c, const asmjit::X86Gp& to = asmjit::x86::rax)
{
if (&to != &x86::rax && &to != &x86::rdx)
{
// Swap to save its contents
c.xchg(x86::rax, to);
}
c.rdtsc();
c.shl(x86::rdx, 32);
if (&to == &x86::rax)
{
c.or_(x86::rax, x86::rdx);
}
else if (&to == &x86::rdx)
{
c.or_(x86::rdx, x86::rax);
}
else
{
// Swap back, maybe there is more effective way to do it
c.xchg(x86::rax, to);
c.mov(to.r32(), to.r32());
c.or_(to.r64(), x86::rdx);
}
}
}
// Build runtime function with asmjit::X86Assembler
template <typename FT, typename F>
FT build_function_asm(F&& builder)
inline FT build_function_asm(F&& builder)
{
using namespace asmjit;
@@ -89,6 +148,7 @@ FT build_function_asm(F&& builder)
X86Assembler compiler(&code);
builder(std::ref(compiler), args);
ensure(compiler.getLastError() == 0);
FT result;
@@ -107,10 +167,9 @@ FT build_function_asm(F&& builder)
#include <string_view>
#include <unordered_map>
#include "types.h"
#include "util/types.hpp"
#include "mutex.h"
#include "restore_new.h"
#ifdef _MSC_VER
#pragma warning(push, 0)
#else
@@ -127,7 +186,6 @@ FT build_function_asm(F&& builder)
#else
#pragma GCC diagnostic pop
#endif
#include "define_new_memleakdetect.h"
// Temporary compiler interface
class jit_compiler final
@@ -135,15 +193,9 @@ class jit_compiler final
// Local LLVM context
llvm::LLVMContext m_context;
// JIT Event Listener
std::unique_ptr<struct EventListener> m_jit_el;
// Execution instance
std::unique_ptr<llvm::ExecutionEngine> m_engine;
// Link table
std::unordered_map<std::string, u64> m_link;
// Arch
std::string m_cpu;
@@ -182,12 +234,6 @@ public:
// Get CPU info
static std::string cpu(const std::string& _cpu);
// Check JIT purpose
bool is_primary() const
{
return !m_link.empty();
}
};
#endif
+86 -73
View File
@@ -1,8 +1,9 @@
#include "StrFmt.h"
#include "BEType.h"
#include "StrFmt.h"
#include "StrUtil.h"
#include "cfmt.h"
#include "util/endian.hpp"
#include "util/logs.hpp"
#include "util/v128.hpp"
#include <algorithm>
#include <string_view>
@@ -78,14 +79,14 @@ void fmt_class_string<fmt::base57>::format(std::string& out, u64 arg)
static constexpr u8 s_tail[8] = {0, 2, 3, 5, 6, 7, 9, 10};
// Get full output size
const std::size_t out_size = _arg.size / 8 * 11 + s_tail[_arg.size % 8];
const usz out_size = _arg.size / 8 * 11 + s_tail[_arg.size % 8];
out.resize(out.size() + out_size);
const auto ptr = &out.front() + (out.size() - out_size);
// Each 8 bytes of input data produce 11 bytes of base57 output
for (std::size_t i = 0, p = 0; i < _arg.size; i += 8, p += 11)
for (usz i = 0, p = 0; i < _arg.size; i += 8, p += 11)
{
// Load up to 8 bytes
be_t<u64> be_value;
@@ -235,6 +236,12 @@ void fmt_class_string<bool>::format(std::string& out, u64 arg)
out += arg ? "true" : "false";
}
template <>
void fmt_class_string<b8>::format(std::string& out, u64 arg)
{
out += get_object(arg) ? "true" : "false";
}
template <>
void fmt_class_string<v128>::format(std::string& out, u64 arg)
{
@@ -242,70 +249,76 @@ void fmt_class_string<v128>::format(std::string& out, u64 arg)
fmt::append(out, "0x%016llx%016llx", vec._u64[1], vec._u64[0]);
}
template <>
void fmt_class_string<u128>::format(std::string& out, u64 arg)
{
// TODO: it should be supported as full-fledged integral type (with %u, %d, etc, fmt)
const u128& num = get_object(arg);
#ifdef _MSC_VER
fmt::append(out, "0x%016llx%016llx", num.hi, num.lo);
#else
fmt::append(out, "0x%016llx%016llx", static_cast<u64>(num >> 64), static_cast<u64>(num));
#endif
}
template <>
void fmt_class_string<src_loc>::format(std::string& out, u64 arg)
{
const src_loc& loc = get_object(arg);
if (loc.col != umax)
{
fmt::append(out, "\n(in file %s:%u[:%u]", loc.file, loc.line, loc.col);
}
else
{
fmt::append(out, "\n(in file %s:%u", loc.file, loc.line);
}
if (loc.func && *loc.func)
{
fmt::append(out, ", in function %s)", loc.func);
}
else
{
out += ')';
}
// Print error code (may be irrelevant)
#ifdef _WIN32
if (DWORD error = GetLastError())
{
fmt::append(out, " (e=0x%08x[%u])", error, error);
}
#else
if (int error = errno)
{
fmt::append(out, " (errno=%d)", error);
}
#endif
}
namespace fmt
{
void raw_error(const char* msg)
{
thread_ctrl::emergency_exit(msg);
}
void raw_verify_error(const char* msg, const fmt_type_info* sup, u64 arg)
[[noreturn]] void raw_verify_error(const src_loc& loc)
{
std::string out{"Verification failed"};
// Print error code (may be irrelevant)
#ifdef _WIN32
if (DWORD error = GetLastError())
{
fmt::append(out, " (e=%#x)", error);
}
#else
if (int error = errno)
{
fmt::append(out, " (e=%d)", error);
}
#endif
if (sup)
{
out += " (";
sup->fmt_string(out, arg); // Print value
out += ")";
}
if (msg)
{
out += ": ";
out += msg;
}
fmt::append(out, "%s", loc);
thread_ctrl::emergency_exit(out);
}
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg)
[[noreturn]] void raw_narrow_error(const src_loc& loc)
{
std::string out{"Narrow error"};
if (sup)
{
out += " (";
sup->fmt_string(out, arg); // Print value
out += ")";
}
if (msg)
{
out += ": ";
out += msg;
}
std::string out{"Narrowing error"};
fmt::append(out, "%s", loc);
thread_ctrl::emergency_exit(out);
}
void raw_throw_exception(const char* fmt, const fmt_type_info* sup, const u64* args)
[[noreturn]] void raw_throw_exception(const src_loc& loc, const char* fmt, const fmt_type_info* sup, const u64* args)
{
std::string out;
raw_append(out, fmt, sup, args);
fmt::append(out, "%s", loc);
thread_ctrl::emergency_exit(out);
}
@@ -318,7 +331,7 @@ struct fmt::cfmt_src
const fmt_type_info* sup;
const u64* args;
bool test(std::size_t index) const
bool test(usz index) const
{
if (!sup[index].fmt_string)
{
@@ -329,26 +342,26 @@ struct fmt::cfmt_src
}
template <typename T>
T get(std::size_t index) const
T get(usz index) const
{
return *reinterpret_cast<const T*>(reinterpret_cast<const u8*>(args + index));
}
void skip(std::size_t extra)
void skip(usz extra)
{
sup += extra + 1;
args += extra + 1;
}
std::size_t fmt_string(std::string& out, std::size_t extra) const
usz fmt_string(std::string& out, usz extra) const
{
const std::size_t start = out.size();
const usz start = out.size();
sup[extra].fmt_string(out, args[extra]);
return out.size() - start;
}
// Returns type size (0 if unknown, pointer, unsigned, assumed max)
std::size_t type(std::size_t extra) const
usz type(usz extra) const
{
// Hack: use known function pointers to determine type
#define TYPE(type) \
@@ -366,14 +379,14 @@ struct fmt::cfmt_src
return 0;
}
static constexpr std::size_t size_char = 1;
static constexpr std::size_t size_short = 2;
static constexpr std::size_t size_int = 0;
static constexpr std::size_t size_long = sizeof(ulong);
static constexpr std::size_t size_llong = sizeof(ullong);
static constexpr std::size_t size_size = sizeof(std::size_t);
static constexpr std::size_t size_max = sizeof(std::uintmax_t);
static constexpr std::size_t size_diff = sizeof(std::ptrdiff_t);
static constexpr usz size_char = 1;
static constexpr usz size_short = 2;
static constexpr usz size_int = 0;
static constexpr usz size_long = sizeof(ulong);
static constexpr usz size_llong = sizeof(ullong);
static constexpr usz size_size = sizeof(usz);
static constexpr usz size_max = sizeof(std::uintmax_t);
static constexpr usz size_diff = sizeof(std::ptrdiff_t);
};
void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept
@@ -409,9 +422,9 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
{
std::vector<std::string> result;
size_t cursor_begin = 0;
usz cursor_begin = 0;
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
for (usz cursor_end = 0; cursor_end < source.length(); ++cursor_end)
{
for (auto& separator : separators)
{
@@ -438,7 +451,7 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
std::string fmt::trim(const std::string& source, const std::string& values)
{
std::size_t begin = source.find_first_not_of(values);
usz begin = source.find_first_not_of(values);
if (begin == source.npos)
return {};
@@ -464,7 +477,7 @@ std::string fmt::to_lower(const std::string& string)
bool fmt::match(const std::string& source, const std::string& mask)
{
std::size_t source_position = 0, mask_position = 0;
usz source_position = 0, mask_position = 0;
for (; source_position < source.size() && mask_position < mask.size(); ++mask_position, ++source_position)
{
@@ -473,7 +486,7 @@ bool fmt::match(const std::string& source, const std::string& mask)
case '?': break;
case '*':
for (std::size_t test_source_position = source_position; test_source_position < source.size(); ++test_source_position)
for (usz test_source_position = source_position; test_source_position < source.size(); ++test_source_position)
{
if (match(source.substr(test_source_position), mask.substr(mask_position + 1)))
{
+38 -38
View File
@@ -1,18 +1,16 @@
#pragma once
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
#include "types.h"
#include "util/types.hpp"
#include <exception>
#include <stdexcept>
#include <string>
namespace fmt
{
template <typename CharT, std::size_t N, typename... Args>
template <typename CharT, usz N, typename... Args>
static std::string format(const CharT(&)[N], const Args&...);
}
template <typename T, typename>
template <typename T, typename = void>
struct fmt_unveil
{
static_assert(sizeof(T) > 0, "fmt_unveil<> error: incomplete type");
@@ -21,7 +19,7 @@ struct fmt_unveil
static inline u64 get(const T& arg)
{
return reinterpret_cast<std::uintptr_t>(&arg);
return reinterpret_cast<uptr>(&arg);
}
// Temporary value container (can possibly be created by other fmt_unveil<> specializations)
@@ -32,7 +30,7 @@ struct fmt_unveil
// Allow implicit conversion
operator u64() const
{
return reinterpret_cast<std::uintptr_t>(&arg);
return reinterpret_cast<uptr>(&arg);
}
};
@@ -66,17 +64,6 @@ struct fmt_unveil<T, std::enable_if_t<std::is_floating_point<T>::value && sizeof
}
};
template <>
struct fmt_unveil<f16, void>
{
using type = f16;
static inline u64 get(const f16& arg)
{
return fmt_unveil<f64>::get(arg.operator float());
}
};
template <typename T>
struct fmt_unveil<T, std::enable_if_t<std::is_enum<T>::value>>
{
@@ -95,29 +82,29 @@ struct fmt_unveil<T*, void>
static inline u64 get(type arg)
{
return reinterpret_cast<std::uintptr_t>(arg);
return reinterpret_cast<uptr>(arg);
}
};
template <typename T, std::size_t N>
template <typename T, usz N>
struct fmt_unveil<T[N], void>
{
using type = std::add_const_t<T>*;
static inline u64 get(type arg)
{
return reinterpret_cast<std::uintptr_t>(arg);
return reinterpret_cast<uptr>(arg);
}
};
template <>
struct fmt_unveil<b8, void>
template <typename T, bool Se, usz Align>
struct fmt_unveil<se_t<T, Se, Align>, void>
{
using type = bool;
using type = typename fmt_unveil<T>::type;
static inline u64 get(const b8& value)
static inline auto get(const se_t<T, Se, Align>& arg)
{
return fmt_unveil<bool>::get(value);
return fmt_unveil<T>::get(arg);
}
};
@@ -134,7 +121,7 @@ struct fmt_class_string
// Helper function (converts arg to object reference)
static SAFE_BUFFERS FORCE_INLINE const T& get_object(u64 arg)
{
return *reinterpret_cast<const T*>(static_cast<std::uintptr_t>(arg));
return *reinterpret_cast<const T*>(static_cast<uptr>(arg));
}
// Enum -> string function type
@@ -236,13 +223,16 @@ struct fmt_type_info
template <typename... Args>
using fmt_args_t = const u64(&&)[sizeof...(Args) + 1];
template <typename Arg>
using fmt_unveil_t = typename fmt_unveil<Arg>::type;
namespace fmt
{
// Base-57 format helper
struct base57
{
const uchar* data;
std::size_t size;
usz size;
template <typename T>
base57(const T& arg)
@@ -251,7 +241,7 @@ namespace fmt
{
}
base57(const uchar* data, std::size_t size)
base57(const uchar* data, usz size)
: data(data)
, size(size)
{
@@ -274,7 +264,7 @@ namespace fmt
void raw_append(std::string& out, const char*, const fmt_type_info*, const u64*) noexcept;
// Formatting function
template <typename CharT, std::size_t N, typename... Args>
template <typename CharT, usz N, typename... Args>
SAFE_BUFFERS FORCE_INLINE void append(std::string& out, const CharT(&fmt)[N], const Args&... args)
{
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
@@ -282,7 +272,7 @@ namespace fmt
}
// Formatting function
template <typename CharT, std::size_t N, typename... Args>
template <typename CharT, usz N, typename... Args>
SAFE_BUFFERS FORCE_INLINE std::string format(const CharT(&fmt)[N], const Args&... args)
{
std::string result;
@@ -291,13 +281,23 @@ namespace fmt
}
// Internal exception message formatting template, must be explicitly specialized or instantiated in cpp to minimize code bloat
[[noreturn]] void raw_throw_exception(const char*, const fmt_type_info*, const u64*);
[[noreturn]] void raw_throw_exception(const src_loc&, const char*, const fmt_type_info*, const u64*);
// Throw exception with formatting
template <typename... Args>
[[noreturn]] SAFE_BUFFERS FORCE_INLINE void throw_exception(const char* fmt, const Args&... args)
template <typename CharT, usz N, typename... Args>
struct throw_exception
{
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
raw_throw_exception(fmt, type_list, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
}
[[noreturn]] SAFE_BUFFERS FORCE_INLINE throw_exception(const CharT(&fmt)[N], const Args&... args,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION())
{
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
raw_throw_exception({line, col, file, func}, reinterpret_cast<const char*>(fmt), type_list, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
}
};
template <typename CharT, usz N, typename... Args>
throw_exception(const CharT(&)[N], const Args&...) -> throw_exception<CharT, N, Args...>;
}
+9 -9
View File
@@ -17,7 +17,7 @@ std::string utf8_path_to_ansi_path(const std::string& src);
template <typename D, typename T>
inline void strcpy_trunc(D& dst, const T& src)
{
const std::size_t count = std::size(src) >= std::size(dst) ? std::size(dst) - 1 : std::size(src);
const usz count = std::size(src) >= std::size(dst) ? std::size(dst) - 1 : std::size(src);
std::memcpy(std::data(dst), std::data(src), count);
std::memset(std::data(dst) + count, 0, std::size(dst) - count);
}
@@ -27,14 +27,14 @@ namespace fmt
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
std::string replace_all(const std::string& src, const std::string& from, const std::string& to);
template <size_t list_size>
template <usz list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::string> (&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
for (usz pos = 0; pos < src.length(); ++pos)
{
for (size_t i = 0; i < list_size; ++i)
for (usz i = 0; i < list_size; ++i)
{
const size_t comp_length = list[i].first.length();
const usz comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
continue;
@@ -51,14 +51,14 @@ namespace fmt
return src;
}
template <size_t list_size>
template <usz list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>> (&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
for (usz pos = 0; pos < src.length(); ++pos)
{
for (size_t i = 0; i < list_size; ++i)
for (usz i = 0; i < list_size; ++i)
{
const size_t comp_length = list[i].first.length();
const usz comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
continue;
+419 -113
View File
@@ -1,11 +1,12 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/Cell/lv2/sys_mmapper.h"
#include "Emu/Cell/lv2/sys_event.h"
#include "Thread.h"
#include "sysinfo.h"
#include "Utilities/JIT.h"
#include <typeinfo>
#include <thread>
#include <sstream>
@@ -38,6 +39,7 @@
#endif
#ifdef __linux__
#include <sys/timerfd.h>
#include <unistd.h>
#endif
#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
@@ -71,8 +73,13 @@
# endif
#endif
#include "sync.h"
#include "util/vm.hpp"
#include "util/logs.hpp"
#include "util/asm.hpp"
#include "util/v128.hpp"
#include "util/v128sse.hpp"
#include "util/sysinfo.hpp"
#include "Emu/Memory/vm_locking.h"
LOG_CHANNEL(sig_log, "SIG");
LOG_CHANNEL(sys_log, "SYS");
@@ -81,8 +88,14 @@ LOG_CHANNEL(vm_log, "VM");
thread_local u64 g_tls_fault_all = 0;
thread_local u64 g_tls_fault_rsx = 0;
thread_local u64 g_tls_fault_spu = 0;
thread_local u64 g_tls_wait_time = 0;
thread_local u64 g_tls_wait_fail = 0;
thread_local bool g_tls_access_violation_recovered = false;
extern thread_local std::string(*g_tls_log_prefix)();
// Report error and call std::abort(), defined in main.cpp
[[noreturn]] void report_fatal_error(const std::string&);
template <>
void fmt_class_string<std::thread::id>::format(std::string& out, u64 arg)
{
@@ -107,7 +120,7 @@ bool IsDebuggerPresent()
};
u_int miblen = std::size(mib);
struct kinfo_proc info;
size_t size = sizeof(info);
usz size = sizeof(info);
if (sysctl(mib, miblen, &info, &size, NULL, 0))
{
@@ -248,7 +261,7 @@ enum x64_op_t : u32
X64OP_SBB, // lock sbb [mem], ...
};
void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, size_t& out_size, size_t& out_length)
void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz& out_size, usz& out_length)
{
// simple analysis of x64 code allows to reinterpret MOV or other instructions in any desired way
out_length = 0;
@@ -374,12 +387,12 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
return x64_reg_t{((*code & 0x38) >> 3) + X64R_AL};
};
auto get_op_size = [](const u8 rex, const bool oso) -> size_t
auto get_op_size = [](const u8 rex, const bool oso) -> usz
{
return rex & 8 ? 8 : (oso ? 2 : 4);
};
auto get_modRM_size = [](const u8* code) -> size_t
auto get_modRM_size = [](const u8* code) -> usz
{
switch (*code >> 6) // check Mod
{
@@ -822,7 +835,7 @@ typedef ucontext_t x64_context;
#define XMMREG(context, reg) (reinterpret_cast<v128*>(&(context)->uc_mcontext->__fs.__fpu_xmm0.__xmm_reg[reg]))
#define EFLAGS(context) ((context)->uc_mcontext->__ss.__rflags)
uint64_t* darwin_x64reg(x64_context *context, int reg)
u64* darwin_x64reg(x64_context *context, int reg)
{
auto *state = &context->uc_mcontext->__ss;
switch(reg)
@@ -965,7 +978,7 @@ static const int reg_table[] =
#define RDI(c) (*X64REG((c), 7))
#define RIP(c) (*X64REG((c), 16))
bool get_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, size_t i_size, u64& out_value)
bool get_x64_reg_value(x64_context* context, x64_reg_t reg, usz d_size, usz i_size, u64& out_value)
{
// get x64 reg value (for store operations)
if (reg - X64R_RAX < 16)
@@ -1056,7 +1069,7 @@ bool get_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, size_
return false;
}
bool put_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, u64 value)
bool put_x64_reg_value(x64_context* context, x64_reg_t reg, usz d_size, u64 value)
{
// save x64 reg value (for load operations)
if (reg - X64R_RAX < 16)
@@ -1075,7 +1088,7 @@ bool put_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, u64 v
return false;
}
bool set_x64_cmp_flags(x64_context* context, size_t d_size, u64 x, u64 y, bool carry = true)
bool set_x64_cmp_flags(x64_context* context, usz d_size, u64 x, u64 y, bool carry = true)
{
switch (d_size)
{
@@ -1151,7 +1164,7 @@ bool set_x64_cmp_flags(x64_context* context, size_t d_size, u64 x, u64 y, bool c
return true;
}
size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, size_t d_size, size_t i_size)
usz get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, usz d_size, usz i_size)
{
if (op == X64OP_MOVS || op == X64OP_STOS)
{
@@ -1216,8 +1229,8 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
x64_op_t op;
x64_reg_t reg;
size_t d_size;
size_t i_size;
usz d_size;
usz i_size;
// decode single x64 instruction that causes memory access
decode_x64_reg_op(code, op, reg, d_size, i_size);
@@ -1230,7 +1243,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
};
if ((d_size | (d_size + addr)) >= 0x100000000ull)
if (0x1'0000'0000ull - addr < d_size)
{
sig_log.error("Invalid d_size (0x%llx)", d_size);
report_opcode();
@@ -1238,9 +1251,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
// get length of data being accessed
size_t a_size = get_x64_access_size(context, op, reg, d_size, i_size);
usz a_size = get_x64_access_size(context, op, reg, d_size, i_size);
if ((a_size | (a_size + addr)) >= 0x100000000ull)
if (0x1'0000'0000ull - addr < a_size)
{
sig_log.error("Invalid a_size (0x%llx)", a_size);
report_opcode();
@@ -1248,22 +1261,28 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
// check if address is RawSPU MMIO register
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
do if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
{
auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET));
if (!thread)
{
return false;
break;
}
if (a_size != 4 || !d_size || !i_size)
if (!a_size || !d_size || !i_size)
{
sig_log.error("Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", +op, +reg, d_size, a_size, i_size);
report_opcode();
return false;
}
if (a_size != 4)
{
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
break;
}
switch (op)
{
case X64OP_LOAD:
@@ -1279,7 +1298,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
if (op != X64OP_LOAD_BE)
{
value = se_storage<u32>::swap(value);
value = stx::se_storage<u32>::swap(value);
}
if (op == X64OP_LOAD_CMP)
@@ -1321,7 +1340,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
u32 val32 = static_cast<u32>(reg_value);
if (!thread->write_reg(addr, op == X64OP_STORE ? se_storage<u32>::swap(val32) : val32))
if (!thread->write_reg(addr, op == X64OP_STORE ? stx::se_storage<u32>::swap(val32) : val32))
{
return false;
}
@@ -1342,9 +1361,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
RIP(context) += i_size;
g_tls_fault_spu++;
return true;
}
} while (0);
if (vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size)), is_writing ? vm::page_writable : vm::page_readable))
if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
{
if (cpu && cpu->test_stopped())
{
@@ -1354,13 +1373,11 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
return true;
}
thread_local bool access_violation_recovered = false;
// Hack: allocate memory in case the emulator is stopping
const auto hack_alloc = [&]()
{
// If failed the value remains true and std::terminate should be called
access_violation_recovered = true;
g_tls_access_violation_recovered = true;
const auto area = vm::reserve_map(vm::any, addr & -0x10000, 0x10000);
@@ -1369,7 +1386,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
return false;
}
if (area->flags & 0x100 || (is_writing && vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size)))))
if (area->flags & 0x100 || (is_writing && vm::check_addr(addr)))
{
// For 4kb pages or read only memory
utils::memory_protect(vm::base(addr & -0x1000), 0x1000, utils::protection::rw);
@@ -1377,7 +1394,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
}
area->falloc(addr & -0x10000, 0x10000);
return vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size)), is_writing ? vm::page_writable : vm::page_readable);
return vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable);
};
if (cpu)
@@ -1389,7 +1406,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
{
if (auto mem = vm::get(vm::any, addr))
{
std::shared_lock lock(pf_entries->mutex);
reader_lock lock(pf_entries->mutex);
for (const auto& entry : pf_entries->entries)
{
@@ -1413,7 +1430,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
{
data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_PPU_THREAD << 32) | cpu->id;
}
else
else if (cpu->id_type() == 2)
{
const auto& spu = static_cast<spu_thread&>(*cpu);
@@ -1427,12 +1444,12 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
u64 data3;
{
vm::reader_lock rlock;
if (vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size)), is_writing ? vm::page_writable : vm::page_readable))
if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
{
// Memory was allocated inbetween, retry
return true;
}
else if (vm::check_addr(addr, std::max(1u, ::narrow<u32>(d_size))))
else if (vm::check_addr(addr))
{
data3 = SYS_MEMORY_PAGE_FAULT_CAUSE_READ_ONLY; // TODO
}
@@ -1512,10 +1529,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
if (cpu->id_type() != 1)
{
if (!access_violation_recovered)
if (!g_tls_access_violation_recovered)
{
vm_log.notice("\n%s", cpu->dump_all());
vm_log.error("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
vm_log.error("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
}
// TODO:
@@ -1543,16 +1560,16 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
Emu.Pause();
if (cpu && !access_violation_recovered)
if (cpu && !g_tls_access_violation_recovered)
{
vm_log.notice("\n%s", cpu->dump_all());
}
// Note: a thread may access violate more than once after hack_alloc recovery
// Do not log any further access violations in this case.
if (!access_violation_recovered)
if (!g_tls_access_violation_recovered)
{
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
vm_log.fatal("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
}
while (Emu.IsPaused())
@@ -1577,21 +1594,27 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
return EXCEPTION_CONTINUE_SEARCH;
}
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - reinterpret_cast<u64>(vm::g_base_addr);
const u64 exec64 = (pExp->ExceptionRecord->ExceptionInformation[1] - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const auto ptr = reinterpret_cast<u8*>(pExp->ExceptionRecord->ExceptionInformation[1]);
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull)
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(addr64), is_writing, pExp->ContextRecord))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
}
u32 addr = 0;
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exec64 < 0x100000000ull)
{
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(exec64), is_writing, pExp->ContextRecord))
if (auto [addr0, ok] = vm::try_get_addr(ptr); ok)
{
addr = addr0;
}
else if (const usz exec64 = (ptr - vm::g_exec_addr) / 2; exec64 <= UINT32_MAX)
{
addr = static_cast<u32>(exec64);
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, pExp->ContextRecord))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
@@ -1732,14 +1755,13 @@ static void signal_handler(int sig, siginfo_t* info, void* uct) noexcept
const bool is_writing = context->uc_mcontext.gregs[REG_ERR] & 0x2;
#endif
const u64 addr64 = reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_base_addr);
const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const auto cause = is_writing ? "writing" : "reading";
if (addr64 < 0x100000000ull)
if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok)
{
// Try to process access violation
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(addr64), is_writing, context))
if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, context))
{
return;
}
@@ -1774,12 +1796,18 @@ static void signal_handler(int sig, siginfo_t* info, void* uct) noexcept
if (IsDebuggerPresent())
{
__asm("int3;");
// Convert to SIGTRAP
raise(SIGTRAP);
return;
}
report_fatal_error(msg);
}
void sigpipe_signaling_handler(int)
{
}
const bool s_exception_handler_set = []() -> bool
{
struct ::sigaction sa;
@@ -1793,6 +1821,13 @@ const bool s_exception_handler_set = []() -> bool
std::abort();
}
sa.sa_handler = sigpipe_signaling_handler;
if (::sigaction(SIGPIPE, &sa, NULL) == -1)
{
std::fprintf(stderr, "sigaction(SIGPIPE) failed (%d).\n", errno);
std::abort();
}
std::printf("Debugger: %d\n", +IsDebuggerPresent());
return true;
}();
@@ -1822,33 +1857,81 @@ thread_local DECLARE(thread_ctrl::g_tls_error_callback) = nullptr;
DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined };
void thread_base::start(native_entry entry)
static atomic_t<u128, 64> s_thread_bits{0};
static atomic_t<thread_base**> s_thread_pool[128]{};
void thread_base::start()
{
for (u128 bits = s_thread_bits.load(); bits; bits &= bits - 1)
{
const u32 pos = utils::ctz128(bits);
if (!s_thread_pool[pos])
{
continue;
}
thread_base** tls = s_thread_pool[pos].exchange(nullptr);
if (!tls)
{
continue;
}
// Receive "that" native thread handle, sent "this" thread_base
const u64 _self = reinterpret_cast<u64>(atomic_storage<thread_base*>::load(*tls));
m_thread.release(_self);
ensure(_self != reinterpret_cast<u64>(this));
atomic_storage<thread_base*>::store(*tls, this);
s_thread_pool[pos].notify_one();
return;
}
#ifdef _WIN32
m_thread = ::_beginthreadex(nullptr, 0, entry, this, CREATE_SUSPENDED, nullptr);
verify("thread_ctrl::start" HERE), m_thread, ::ResumeThread(reinterpret_cast<HANDLE>(+m_thread)) != -1;
m_thread = ::_beginthreadex(nullptr, 0, entry_point, this, CREATE_SUSPENDED, nullptr);
ensure(m_thread);
ensure(::ResumeThread(reinterpret_cast<HANDLE>(+m_thread)) != -1);
#else
verify("thread_ctrl::start" HERE), pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), nullptr, entry, this) == 0;
ensure(pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), nullptr, entry_point, this) == 0);
#endif
}
void thread_base::initialize(void (*error_cb)(), bool(*wait_cb)(const void*))
void thread_base::initialize(void (*error_cb)())
{
#ifndef _WIN32
m_thread.release(reinterpret_cast<u64>(pthread_self()));
#endif
// Initialize TLS variables
thread_ctrl::g_tls_this_thread = this;
thread_ctrl::g_tls_error_callback = error_cb;
// Initialize atomic wait callback
atomic_storage_futex::set_wait_callback(wait_cb);
g_tls_log_prefix = []
{
return thread_ctrl::get_name_cached();
};
std::string name = thread_ctrl::get_name_cached();
atomic_wait_engine::set_wait_callback([](const void*, u64 attempts, u64 stamp0) -> bool
{
if (attempts == umax)
{
g_tls_wait_time += __rdtsc() - stamp0;
}
else if (attempts > 1)
{
g_tls_wait_fail += attempts - 1;
}
return true;
});
set_name(thread_ctrl::get_name_cached());
}
void thread_base::set_name(std::string name)
{
#ifdef _MSC_VER
struct THREADNAME_INFO
{
@@ -1878,25 +1961,19 @@ void thread_base::initialize(void (*error_cb)(), bool(*wait_cb)(const void*))
#endif
#if defined(__APPLE__)
name.resize(std::min<std::size_t>(15, name.size()));
name.resize(std::min<usz>(15, name.size()));
pthread_setname_np(name.c_str());
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
pthread_set_name_np(pthread_self(), name.c_str());
#elif defined(__NetBSD__)
pthread_setname_np(pthread_self(), "%s", name.data());
#elif !defined(_WIN32)
name.resize(std::min<std::size_t>(15, name.size()));
name.resize(std::min<usz>(15, name.size()));
pthread_setname_np(pthread_self(), name.c_str());
#endif
}
void thread_base::notify_abort() noexcept
{
m_signal.try_inc();
atomic_storage_futex::raw_notify(+m_state_notifier);
}
bool thread_base::finalize(thread_state result_state) noexcept
u64 thread_base::finalize(thread_state result_state) noexcept
{
// Report pending errors
error_code::error_report(0, 0, 0, 0);
@@ -1934,29 +2011,183 @@ bool thread_base::finalize(thread_state result_state) noexcept
return thread_ctrl::get_name_cached();
};
sig_log.notice("Thread time: %fs (%fGc); Faults: %u [rsx:%u, spu:%u]; [soft:%u hard:%u]; Switches:[vol:%u unvol:%u]",
sig_log.notice("Thread time: %fs (%fGc); Faults: %u [rsx:%u, spu:%u]; [soft:%u hard:%u]; Switches:[vol:%u unvol:%u]; Wait:[%.3fs, spur:%u]",
time / 1000000000.,
cycles / 1000000000.,
g_tls_fault_all,
g_tls_fault_rsx,
g_tls_fault_spu,
fsoft, fhard, ctxvol, ctxinv);
fsoft, fhard, ctxvol, ctxinv,
g_tls_wait_time / (utils::get_tsc_freq() / 1.),
g_tls_wait_fail);
// Return true if need to delete thread object
const bool ok = m_state.exchange(result_state) <= thread_state::aborting;
atomic_wait_engine::set_wait_callback(nullptr);
// Avoid race with the destructor
const u64 _self = m_thread;
// Set result state (errored or finalized)
const bool ok = 0 == (3 & ~m_sync.fetch_op([&](u64& v)
{
v &= -4;
v |= static_cast<u32>(result_state);
}));
// Signal waiting threads
m_state.notify_all();
m_sync.notify_all(2);
// No detached thread supported atm
return !ok;
return _self;
}
void thread_base::finalize() noexcept
thread_base::native_entry thread_base::finalize(u64 _self) noexcept
{
atomic_storage_futex::set_wait_callback([](const void*){ return true; });
g_tls_fault_all = 0;
g_tls_fault_rsx = 0;
g_tls_fault_spu = 0;
g_tls_wait_time = 0;
g_tls_wait_fail = 0;
g_tls_access_violation_recovered = false;
const auto fake_self = reinterpret_cast<thread_base*>(_self);
g_tls_log_prefix = []() -> std::string { return {}; };
thread_ctrl::g_tls_this_thread = nullptr;
thread_ctrl::g_tls_this_thread = fake_self;
if (!_self)
{
return nullptr;
}
// Try to add self to thread pool
set_name("..pool");
static constexpr u64 s_stop_bit = 0x8000'0000'0000'0000ull;
static atomic_t<u64> s_pool_ctr = []
{
std::atexit([]
{
s_pool_ctr |= s_stop_bit;
while (u64 remains = s_pool_ctr & ~s_stop_bit)
{
for (u32 i = 0; i < std::size(s_thread_pool); i++)
{
if (thread_base** ptls = s_thread_pool[i].exchange(nullptr))
{
// Extract thread handle
const u64 _self = reinterpret_cast<u64>(*ptls);
// Wake up a thread and make sure it's joined
s_thread_pool[i].notify_one();
#ifdef _WIN32
const HANDLE handle = reinterpret_cast<HANDLE>(_self);
WaitForSingleObject(handle, INFINITE);
CloseHandle(handle);
#else
pthread_join(reinterpret_cast<pthread_t>(_self), nullptr);
#endif
}
}
}
});
return 0;
}();
s_pool_ctr++;
u32 pos = -1;
while (true)
{
const auto [bits, ok] = s_thread_bits.fetch_op([](u128& bits)
{
if (~bits) [[likely]]
{
// Set lowest clear bit
bits |= bits + 1;
return true;
}
return false;
});
if (ok) [[likely]]
{
pos = utils::ctz128(~bits);
break;
}
s_thread_bits.wait(bits);
}
const auto tls = &thread_ctrl::g_tls_this_thread;
s_thread_pool[pos] = tls;
atomic_wait::list<2> list{};
list.set<0>(s_pool_ctr, 0, s_stop_bit);
list.set<1>(s_thread_pool[pos], tls);
while (s_thread_pool[pos] == tls || atomic_storage<thread_base*>::load(*tls) == fake_self)
{
list.wait();
if (s_pool_ctr & s_stop_bit)
{
break;
}
}
// Free thread pool slot
s_thread_bits.atomic_op([pos](u128& val)
{
val &= ~(u128(1) << pos);
});
s_thread_bits.notify_one();
if (--s_pool_ctr & s_stop_bit)
{
return nullptr;
}
// Return new entry point
utils::prefetch_exec((*tls)->entry_point);
return (*tls)->entry_point;
}
thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base))
{
return build_function_asm<native_entry>([&](asmjit::X86Assembler& c, auto& args)
{
using namespace asmjit;
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));
// Call finalize, return if zero
c.mov(args[0], x86::rax);
c.call(imm_ptr<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.mov(args[0], x86::rax);
c.add(x86::rsp, 0x28);
c.jmp(x86::rbp);
c.bind(_ret);
c.add(x86::rsp, 0x28);
c.ret();
});
}
void thread_ctrl::_wait_for(u64 usec, bool alert /* true */)
@@ -2008,12 +2239,13 @@ void thread_ctrl::_wait_for(u64 usec, bool alert /* true */)
}
#endif
if (_this->m_signal && _this->m_signal.exchange(0))
if (_this->m_sync.bit_test_reset(2))
{
return;
}
_this->m_signal.wait(0, atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
// Wait for signal and thread state abort
_this->m_sync.wait(0, 4 + 1, atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
}
std::string thread_ctrl::get_name_cached()
@@ -2025,63 +2257,110 @@ std::string thread_ctrl::get_name_cached()
return {};
}
static thread_local stx::shared_cptr<std::string> name_cache;
static thread_local shared_ptr<std::string> name_cache;
if (!_this->m_tname.is_equal(name_cache)) [[unlikely]]
{
name_cache = _this->m_tname.load();
_this->m_tname.peek_op([&](const shared_ptr<std::string>& ptr)
{
if (ptr != name_cache)
{
name_cache = ptr;
}
});
}
return *name_cache;
}
thread_base::thread_base(std::string_view name)
: m_tname(stx::shared_cptr<std::string>::make(name))
thread_base::thread_base(native_entry entry, std::string_view name)
: entry_point(entry)
, m_tname(make_single<std::string>(name))
{
}
thread_base::~thread_base()
{
if (m_thread)
// Only cleanup on errored status
if ((m_sync & 3) == 2)
{
#ifdef _WIN32
CloseHandle(reinterpret_cast<HANDLE>(m_thread.raw()));
const HANDLE handle0 = reinterpret_cast<HANDLE>(m_thread.load());
WaitForSingleObject(handle0, INFINITE);
CloseHandle(handle0);
#else
pthread_detach(reinterpret_cast<pthread_t>(m_thread.raw()));
pthread_join(reinterpret_cast<pthread_t>(m_thread.load()), nullptr);
#endif
}
}
bool thread_base::join() const
bool thread_base::join(bool dtor) const
{
for (auto state = m_state.load(); state != thread_state::finished && state != thread_state::errored;)
// Check if already finished
if (m_sync & 2)
{
m_state.wait(state);
state = m_state;
return (m_sync & 3) == 3;
}
return m_state.load() == thread_state::finished;
// 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;
bool warn = false;
auto stamp0 = __rdtsc();
for (u64 i = 0; (m_sync & 3) <= 1; i++)
{
m_sync.wait(0, 2, timeout);
if (m_sync & 2)
{
break;
}
if (i > 20 && Emu.IsStopped())
{
stamp0 = __rdtsc();
atomic_wait_engine::raw_notify(0, get_native_id());
stamp0 = __rdtsc() - stamp0;
warn = true;
}
}
if (warn)
{
sig_log.error(u8"Thread [%s] is too sleepy. Took %.3fµs to wake it up!", *m_tname.load(), stamp0 / (utils::get_tsc_freq() / 1000000.));
}
return (m_sync & 3) == 3;
}
void thread_base::notify()
{
// Increment with saturation
if (m_signal.try_inc())
{
// Considered impossible to have a situation when not notified
m_signal.notify_all();
}
// Set notification
m_sync |= 4;
m_sync.notify_one(4);
}
u64 thread_base::get_native_id() const
{
#ifdef _WIN32
return GetThreadId(reinterpret_cast<HANDLE>(m_thread.load()));
#else
return m_thread.load();
#endif
}
u64 thread_base::get_cycles()
{
u64 cycles;
u64 cycles = 0;
const u64 handle = m_thread;
#ifdef _WIN32
if (QueryThreadCycleTime(reinterpret_cast<HANDLE>(m_thread.load()), &cycles))
if (QueryThreadCycleTime(reinterpret_cast<HANDLE>(handle), &cycles))
{
#elif __APPLE__
mach_port_name_t port = pthread_mach_thread_np(reinterpret_cast<pthread_t>(m_thread.load()));
mach_port_name_t port = pthread_mach_thread_np(reinterpret_cast<pthread_t>(handle));
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
thread_basic_info_data_t info;
kern_return_t ret = thread_info(port, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &count);
@@ -2092,11 +2371,11 @@ u64 thread_base::get_cycles()
#else
clockid_t _clock;
struct timespec thread_time;
if (!pthread_getcpuclockid(reinterpret_cast<pthread_t>(m_thread.load()), &_clock) && !clock_gettime(_clock, &thread_time))
if (!pthread_getcpuclockid(reinterpret_cast<pthread_t>(handle), &_clock) && !clock_gettime(_clock, &thread_time))
{
cycles = static_cast<u64>(thread_time.tv_sec) * 1'000'000'000 + thread_time.tv_nsec;
#endif
if (const u64 old_cycles = m_cycles.exchange(cycles))
if (const u64 old_cycles = m_sync.fetch_op([&](u64& v){ v &= 7; v |= (cycles << 3); }) >> 3)
{
return cycles - old_cycles;
}
@@ -2106,11 +2385,11 @@ u64 thread_base::get_cycles()
}
else
{
return m_cycles;
return m_sync >> 3;
}
}
void thread_ctrl::emergency_exit(std::string_view reason)
[[noreturn]] void thread_ctrl::emergency_exit(std::string_view reason)
{
sig_log.fatal("Thread terminated due to fatal error: %s", reason);
@@ -2133,17 +2412,20 @@ void thread_ctrl::emergency_exit(std::string_view reason)
{
g_tls_error_callback();
if (_this->finalize(thread_state::errored))
u64 _self = _this->finalize(thread_state::errored);
if (!_self)
{
// Unused, detached thread support remnant
delete _this;
}
thread_base::finalize();
thread_base::finalize(0);
#ifdef _WIN32
_endthreadex(0);
#else
pthread_exit(0);
pthread_exit(nullptr);
#endif
}
@@ -2190,8 +2472,8 @@ void thread_ctrl::detect_cpu_layout()
else
{
// Iterate through the buffer until a core with hyperthreading is found
auto ptr = reinterpret_cast<std::uintptr_t>(buffer.data());
const std::uintptr_t end = ptr + buffer_size;
auto ptr = reinterpret_cast<uptr>(buffer.data());
const uptr end = ptr + buffer_size;
while (ptr < end)
{
@@ -2515,3 +2797,27 @@ u64 thread_ctrl::get_thread_affinity_mask()
return -1;
#endif
}
std::pair<void*, usz> thread_ctrl::get_thread_stack()
{
#ifdef _WIN32
ULONG_PTR _min = 0;
ULONG_PTR _max = 0;
GetCurrentThreadStackLimits(&_min, &_max);
const usz ssize = _max - _min;
const auto saddr = reinterpret_cast<void*>(_min);
#else
void* saddr = 0;
usz ssize = 0;
pthread_attr_t attr;
#ifdef __linux__
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &saddr, &ssize);
#else
pthread_attr_get_np(pthread_self(), &attr);
pthread_attr_getstackaddr(&attr, &saddr);
pthread_attr_getstacksize(&attr, &ssize);
#endif
#endif
return {saddr, ssize};
}
+62 -93
View File
@@ -1,20 +1,16 @@
#pragma once
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include "util/shared_cptr.hpp"
#include "util/shared_ptr.hpp"
#include <string>
#include <memory>
#include <string_view>
#include "mutex.h"
#include "cond.h"
#include "lockless.h"
// Report error and call std::abort(), defined in main.cpp
[[noreturn]] void report_fatal_error(const std::string&);
// Hardware core layout
enum class native_core_arrangement : u32
{
@@ -34,12 +30,15 @@ enum class thread_class : u32
enum class thread_state : u32
{
created, // Initial state
aborting, // The thread has been joined in the destructor or explicitly aborted
errored, // Set after the emergency_exit call
finished // Final state, always set at the end of thread execution
created = 0, // Initial state
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
errored = 2, // Set after the emergency_exit call
finished = 3, // Final state, always set at the end of thread execution
mask = 3
};
class need_wakeup {};
template <class Context>
class named_thread;
@@ -90,6 +89,7 @@ struct thread_thread_name<T, std::void_t<decltype(named_thread<T>::thread_name)>
// Thread base class
class thread_base
{
public:
// Native thread entry point function type
#ifdef _WIN32
using native_entry = uint(__stdcall*)(void* arg);
@@ -97,38 +97,35 @@ class thread_base
using native_entry = void*(*)(void* arg);
#endif
const native_entry entry_point;
private:
// Thread handle (platform-specific)
atomic_t<std::uintptr_t> m_thread{0};
atomic_t<u64> m_thread{0};
// Thread playtoy, that shouldn't be used
atomic_t<u32> m_signal{0};
// Thread state
atomic_t<thread_state> m_state = thread_state::created;
// Thread state notification info
atomic_t<const void*> m_state_notifier{nullptr};
// Thread state and cycles
atomic_t<u64> m_sync{0};
// Thread name
stx::atomic_cptr<std::string> m_tname;
//
atomic_t<u64> m_cycles = 0;
atomic_ptr<std::string> m_tname;
// Start thread
void start(native_entry);
void start();
// Called at the thread start
void initialize(void (*error_cb)(), bool(*wait_cb)(const void*));
void initialize(void (*error_cb)());
// May be called in destructor
void notify_abort() noexcept;
// Called at the thread end, returns true if needs destruction
bool finalize(thread_state result) noexcept;
// Called at the thread end, returns self handle
u64 finalize(thread_state result) noexcept;
// Cleanup after possibly deleting the thread instance
static void finalize() noexcept;
static native_entry finalize(u64 _self) noexcept;
// Set name for debugger
static void set_name(std::string);
// Make entry point
static native_entry make_trampoline(u64(*)(thread_base*));
friend class thread_ctrl;
@@ -136,7 +133,7 @@ class thread_base
friend class named_thread;
protected:
thread_base(std::string_view name);
thread_base(native_entry, std::string_view name);
~thread_base();
@@ -145,10 +142,13 @@ public:
u64 get_cycles();
// Wait for the thread (it does NOT change thread state, and can be called from multiple threads)
bool join() const;
bool join(bool dtor = false) const;
// Notify the thread
void notify();
// Get thread id
u64 get_native_id() const;
};
// Collection of global function for current thread
@@ -188,14 +188,14 @@ public:
// Set current thread name (not recommended)
static void set_name(std::string_view name)
{
g_tls_this_thread->m_tname.store(stx::shared_cptr<std::string>::make(name));
g_tls_this_thread->m_tname.store(make_single<std::string>(name));
}
// Set thread name (not recommended)
template <typename T>
static void set_name(named_thread<T>& thread, std::string_view name)
{
static_cast<thread_base&>(thread).m_tname.store(stx::shared_cptr<std::string>::make(name));
static_cast<thread_base&>(thread).m_tname.store(make_single<std::string>(name));
}
template <typename T>
@@ -211,15 +211,15 @@ public:
}
template <typename T>
static void raw_notify(named_thread<T>& thread)
static u64 get_native_id(named_thread<T>& thread)
{
static_cast<thread_base&>(thread).notify_abort();
return static_cast<thread_base&>(thread).get_native_id();
}
// Read current state
static inline thread_state state()
{
return g_tls_this_thread->m_state;
return static_cast<thread_state>(g_tls_this_thread->m_sync & 3);
}
// Wait once with timeout. May spuriously return false.
@@ -261,6 +261,9 @@ public:
// Miscellaneous
static u64 get_thread_affinity_mask();
// Get current thread stack addr and size
static std::pair<void*, usz> get_thread_stack();
private:
// Miscellaneous
static const u64 process_affinity_mask;
@@ -273,59 +276,20 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
using result = result_storage_t<Context>;
using thread = thread_base;
// Type-erased thread entry point
#ifdef _WIN32
static inline uint __stdcall entry_point(void* arg)
#else
static inline void* entry_point(void* arg)
#endif
static u64 entry_point(thread_base* _base)
{
const auto _this = static_cast<named_thread*>(static_cast<thread*>(arg));
// Perform self-cleanup if necessary
if (_this->entry_point())
{
delete _this;
}
thread::finalize();
return 0;
return static_cast<named_thread*>(_base)->entry_point2();
}
bool entry_point()
u64 entry_point2()
{
auto tls_error_cb = []()
thread::initialize([]()
{
if constexpr (!result::empty)
{
// Construct using default constructor in the case of failure
new (static_cast<result*>(static_cast<named_thread*>(thread_ctrl::get_current()))->get()) typename result::type();
}
};
thread::initialize(tls_error_cb, [](const void* data)
{
const auto _this = thread_ctrl::get_current();
if (_this->m_state >= thread_state::aborting)
{
return false;
}
_this->m_state_notifier.release(data);
if (!data)
{
return true;
}
if (_this->m_state >= thread_state::aborting)
{
_this->m_state_notifier.release(nullptr);
return false;
}
return true;
});
if constexpr (result::empty)
@@ -342,6 +306,8 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
return thread::finalize(thread_state::finished);
}
static inline thread::native_entry trampoline = thread::make_trampoline(entry_point);
friend class thread_ctrl;
public:
@@ -349,26 +315,26 @@ public:
template <bool Valid = std::is_default_constructible_v<Context> && thread_thread_name<Context>(), typename = std::enable_if_t<Valid>>
named_thread()
: Context()
, thread(Context::thread_name)
, thread(trampoline, Context::thread_name)
{
thread::start(&named_thread::entry_point);
thread::start();
}
// Normal forwarding constructor
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>>
named_thread(std::string_view name, Args&&... args)
: Context(std::forward<Args>(args)...)
, thread(name)
, thread(trampoline, name)
{
thread::start(&named_thread::entry_point);
thread::start();
}
// Lambda constructor, also the implicit deduction guide candidate
named_thread(std::string_view name, Context&& f)
: Context(std::forward<Context>(f))
, thread(name)
, thread(trampoline, name)
{
thread::start(&named_thread::entry_point);
thread::start();
}
named_thread(const named_thread&) = delete;
@@ -400,19 +366,22 @@ public:
// Access thread state
operator thread_state() const
{
return thread::m_state.load();
return static_cast<thread_state>(thread::m_sync.load() & 3);
}
// Try to abort by assigning thread_state::aborting (UB if assigning different state)
named_thread& operator=(thread_state s)
{
ASSUME(s == thread_state::aborting);
if (s == thread_state::aborting && thread::m_state.compare_and_swap_test(thread_state::created, s))
if (s == thread_state::aborting && thread::m_sync.fetch_op([](u64& v){ return !(v & 3) && (v |= 1); }).second)
{
if (s == thread_state::aborting)
{
thread::notify_abort();
thread::m_sync.notify_one(1);
}
if constexpr (std::is_base_of_v<need_wakeup, Context>)
{
this->wake_up();
}
}
@@ -424,7 +393,7 @@ public:
{
// Assign aborting state forcefully
operator=(thread_state::aborting);
thread::join();
thread::join(true);
if constexpr (!result::empty)
{
+9 -9
View File
@@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include "util/types.hpp"
#include <chrono>
@@ -8,8 +8,8 @@ class Timer
{
private:
bool m_stopped;
std::chrono::steady_clock::time_point m_start;
std::chrono::steady_clock::time_point m_end;
steady_clock::time_point m_start;
steady_clock::time_point m_end;
public:
Timer() : m_stopped(false)
@@ -19,13 +19,13 @@ public:
void Start()
{
m_stopped = false;
m_start = std::chrono::steady_clock::now();
m_start = steady_clock::now();
}
void Stop()
{
m_stopped = true;
m_end = std::chrono::steady_clock::now();
m_end = steady_clock::now();
}
double GetElapsedTimeInSec() const
@@ -40,21 +40,21 @@ public:
u64 GetElapsedTimeInMicroSec() const
{
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(now - m_start).count();
}
u64 GetElapsedTimeInNanoSec() const
{
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(now - m_start).count();
}
u64 GetMsSince(std::chrono::steady_clock::time_point timestamp)
u64 GetMsSince(steady_clock::time_point timestamp)
{
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(now - timestamp).count();
}
+11 -11
View File
@@ -1,6 +1,6 @@
#pragma once
#pragma once
#include "types.h"
#include "util/types.hpp"
#include "StrFmt.h"
#include <vector>
@@ -92,7 +92,7 @@ namespace utils
void set_length(const u32 new_length)
{
end = start + new_length - 1;
ASSERT(valid());
ensure(valid());
}
u32 next_address() const
@@ -282,7 +282,7 @@ namespace utils
public:
// Wrapped functions
inline void reserve(size_t nr) { data.reserve(nr); }
inline void reserve(usz nr) { data.reserve(nr); }
inline void clear() { data.clear(); }
inline size_type size() const { return data.size(); }
inline bool empty() const { return data.empty(); }
@@ -456,9 +456,9 @@ namespace utils
// Will fail if ranges within the vector overlap our touch each-other
bool check_consistency() const
{
size_t _size = data.size();
usz _size = data.size();
for (size_t i = 0; i < _size; ++i)
for (usz i = 0; i < _size; ++i)
{
const auto &r1 = data[i];
if (!r1.valid())
@@ -466,7 +466,7 @@ namespace utils
continue;
}
for (size_t j = i + 1; j < _size; ++j)
for (usz j = i + 1; j < _size; ++j)
{
const auto &r2 = data[j];
if (!r2.valid())
@@ -582,15 +582,15 @@ namespace utils
namespace std
{
static_assert(sizeof(size_t) >= 2 * sizeof(u32), "size_t must be at least twice the size of u32");
static_assert(sizeof(usz) >= 2 * sizeof(u32), "usz must be at least twice the size of u32");
template <>
struct hash<utils::address_range>
{
std::size_t operator()(const utils::address_range& k) const
usz operator()(const utils::address_range& k) const
{
// we can guarantee a unique hash since our type is 64 bits and size_t as well
return (size_t{ k.start } << 32) | size_t{ k.end };
// we can guarantee a unique hash since our type is 64 bits and usz as well
return (usz{ k.start } << 32) | usz{ k.end };
}
};
}
-215
View File
@@ -1,215 +0,0 @@
#pragma once
#include "types.h"
namespace utils
{
// Rotate helpers
#if defined(__GNUG__)
inline u8 rol8(u8 x, u8 n)
{
#if __has_builtin(__builtin_rotateleft8)
return __builtin_rotateleft8(x, n);
#else
u8 result = x;
__asm__("rolb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u8 ror8(u8 x, u8 n)
{
#if __has_builtin(__builtin_rotateright8)
return __builtin_rotateright8(x, n);
#else
u8 result = x;
__asm__("rorb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u16 rol16(u16 x, u16 n)
{
#if __has_builtin(__builtin_rotateleft16)
return __builtin_rotateleft16(x, n);
#else
u16 result = x;
__asm__("rolw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u16 ror16(u16 x, u16 n)
{
#if __has_builtin(__builtin_rotateright16)
return __builtin_rotateright16(x, n);
#else
u16 result = x;
__asm__("rorw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u32 rol32(u32 x, u32 n)
{
#if __has_builtin(__builtin_rotateleft32)
return __builtin_rotateleft32(x, n);
#else
u32 result = x;
__asm__("roll %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u32 ror32(u32 x, u32 n)
{
#if __has_builtin(__builtin_rotateright32)
return __builtin_rotateright32(x, n);
#else
u32 result = x;
__asm__("rorl %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u64 rol64(u64 x, u64 n)
{
#if __has_builtin(__builtin_rotateleft64)
return __builtin_rotateleft64(x, n);
#else
u64 result = x;
__asm__("rolq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u64 ror64(u64 x, u64 n)
{
#if __has_builtin(__builtin_rotateright64)
return __builtin_rotateright64(x, n);
#else
u64 result = x;
__asm__("rorq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
constexpr u64 umulh64(u64 a, u64 b)
{
const __uint128_t x = a;
const __uint128_t y = b;
return (x * y) >> 64;
}
constexpr s64 mulh64(s64 a, s64 b)
{
const __int128_t x = a;
const __int128_t y = b;
return (x * y) >> 64;
}
constexpr s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
{
const __int128_t x = (__uint128_t{u64(high)} << 64) | u64(low);
const __int128_t r = x / divisor;
if (remainder)
{
*remainder = x % divisor;
}
return r;
}
constexpr u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
{
const __uint128_t x = (__uint128_t{high} << 64) | low;
const __uint128_t r = x / divisor;
if (remainder)
{
*remainder = x % divisor;
}
return r;
}
#elif defined(_MSC_VER)
inline u8 rol8(u8 x, u8 n)
{
return _rotl8(x, n);
}
inline u8 ror8(u8 x, u8 n)
{
return _rotr8(x, n);
}
inline u16 rol16(u16 x, u16 n)
{
return _rotl16(x, (u8)n);
}
inline u16 ror16(u16 x, u16 n)
{
return _rotr16(x, (u8)n);
}
inline u32 rol32(u32 x, u32 n)
{
return _rotl(x, (int)n);
}
inline u32 ror32(u32 x, u32 n)
{
return _rotr(x, (int)n);
}
inline u64 rol64(u64 x, u64 n)
{
return _rotl64(x, (int)n);
}
inline u64 ror64(u64 x, u64 n)
{
return _rotr64(x, (int)n);
}
inline u64 umulh64(u64 x, u64 y)
{
return __umulh(x, y);
}
inline s64 mulh64(s64 x, s64 y)
{
return __mulh(x, y);
}
inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
{
s64 rem;
s64 r = _div128(high, low, divisor, &rem);
if (remainder)
{
*remainder = rem;
}
return r;
}
inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
{
u64 rem;
u64 r = _udiv128(high, low, divisor, &rem);
if (remainder)
{
*remainder = rem;
}
return r;
}
#endif
} // namespace utils
+34 -31
View File
@@ -1,10 +1,13 @@
#include "bin_patch.h"
#include "bin_patch.h"
#include "File.h"
#include "Config.h"
#include "version.h"
#include "Emu/System.h"
LOG_CHANNEL(patch_log);
#include "util/types.hpp"
#include "util/endian.hpp"
LOG_CHANNEL(patch_log, "PAT");
namespace config_key
{
@@ -73,7 +76,7 @@ std::string patch_engine::get_patch_config_path()
if (!fs::create_path(config_dir))
{
patch_log.error("Could not create path: %s", patch_path);
patch_log.error("Could not create path: %s (%s)", patch_path, fs::g_tls_error);
}
return patch_path;
@@ -98,19 +101,24 @@ static void append_log_message(std::stringstream* log_messages, const std::strin
*log_messages << message << std::endl;
};
bool patch_engine::load(patch_map& patches_map, const std::string& path, bool importing, std::stringstream* log_messages)
bool patch_engine::load(patch_map& patches_map, const std::string& path, std::string content, bool importing, std::stringstream* log_messages)
{
// Load patch file
fs::file file{ path };
if (!file)
if (content.empty())
{
// Do nothing
return true;
// Load patch file
fs::file file{path};
if (!file)
{
// Do nothing
return true;
}
content = file.to_string();
}
// Interpret yaml nodes
auto [root, error] = yaml_load(file.to_string());
auto [root, error] = yaml_load(content);
if (!error.empty() || !root)
{
@@ -519,7 +527,7 @@ bool patch_engine::read_patch_node(patch_info& info, YAML::Node node, const YAML
if (!node)
{
append_log_message(log_messages, fmt::format("Skipping invalid patch node %s. (key: %s)", info.description, info.hash));
patch_log.error("Skipping invalid patch node %s. (key: %s)" HERE, info.description, info.hash);
patch_log.error("Skipping invalid patch node %s. (key: %s)", info.description, info.hash);
return false;
}
@@ -543,11 +551,6 @@ bool patch_engine::read_patch_node(patch_info& info, YAML::Node node, const YAML
return is_valid;
}
void patch_engine::append(const std::string& patch)
{
load(m_map, patch);
}
void patch_engine::append_global_patches()
{
// Legacy patch.yml
@@ -574,20 +577,20 @@ void patch_engine::append_title_patches(const std::string& title_id)
load(m_map, get_patches_path() + title_id + "_patch.yml");
}
std::size_t patch_engine::apply(const std::string& name, u8* dst)
usz patch_engine::apply(const std::string& name, u8* dst)
{
return apply_patch<false>(name, dst, 0, 0);
}
std::size_t patch_engine::apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
usz patch_engine::apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
{
return apply_patch<true>(name, dst, filesz, ls_addr);
}
template <bool check_local_storage>
static std::size_t apply_modification(const patch_engine::patch_info& patch, u8* dst, u32 filesz, u32 ls_addr)
static usz apply_modification(const patch_engine::patch_info& patch, u8* dst, u32 filesz, u32 ls_addr)
{
size_t applied = 0;
usz applied = 0;
for (const auto& p : patch.data_list)
{
@@ -600,7 +603,7 @@ static std::size_t apply_modification(const patch_engine::patch_info& patch, u8*
// This patch is out of range for this segment
continue;
}
offset -= ls_addr;
}
@@ -678,14 +681,14 @@ static std::size_t apply_modification(const patch_engine::patch_info& patch, u8*
}
template <bool check_local_storage>
std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
usz patch_engine::apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
{
if (m_map.find(name) == m_map.cend())
{
return 0;
}
size_t applied_total = 0;
usz applied_total = 0;
const auto& container = m_map.at(name);
const auto serial = Emu.GetTitleID();
const auto app_version = Emu.GetAppVersion();
@@ -796,7 +799,7 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
m_applied_groups.insert(patch.patch_group);
}
const size_t applied = apply_modification<check_local_storage>(patch, dst, filesz, ls_addr);
const usz applied = apply_modification<check_local_storage>(patch, dst, filesz, ls_addr);
applied_total += applied;
if (patch.is_legacy)
@@ -820,7 +823,7 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
fs::file file(path, fs::rewrite);
if (!file)
{
patch_log.fatal("Failed to open patch config file %s", path);
patch_log.fatal("Failed to open patch config file %s (%s)", path, fs::g_tls_error);
return;
}
@@ -903,7 +906,7 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
file.write(out.c_str(), out.size());
}
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches, size_t& count, size_t& total, std::stringstream* log_messages)
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches, usz& count, usz& total, std::stringstream* log_messages)
{
for (const auto& [hash, new_container] : new_patches)
{
@@ -973,8 +976,8 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
fs::file file(path, fs::rewrite);
if (!file)
{
patch_log.fatal("save_patches: Failed to open patch file %s", path);
append_log_message(log_messages, fmt::format("Failed to open patch file %s", path));
patch_log.fatal("save_patches: Failed to open patch file %s (%s)", path, fs::g_tls_error);
append_log_message(log_messages, fmt::format("Failed to open patch file %s (%s)", path, fs::g_tls_error));
return false;
}
@@ -1055,11 +1058,11 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
return true;
}
bool patch_engine::import_patches(const patch_engine::patch_map& patches, const std::string& path, size_t& count, size_t& total, std::stringstream* log_messages)
bool patch_engine::import_patches(const patch_engine::patch_map& patches, const std::string& path, usz& count, usz& total, std::stringstream* log_messages)
{
patch_engine::patch_map existing_patches;
if (load(existing_patches, path, true, log_messages))
if (load(existing_patches, path, "", true, log_messages))
{
append_patches(existing_patches, patches, count, total, log_messages);
return count == 0 || save_patches(existing_patches, path, log_messages);
+8 -11
View File
@@ -1,10 +1,10 @@
#pragma once
#pragma once
#include "BEType.h"
#include <vector>
#include <string>
#include <unordered_map>
#include "util/types.hpp"
#include "util/yaml.hpp"
namespace patch_key
@@ -53,7 +53,7 @@ public:
f64 double_value;
} value { 0 };
};
using patch_app_versions = std::unordered_map<std::string /*app_version*/, bool /*enabled*/>;
using patch_serials = std::unordered_map<std::string /*serial*/, patch_app_versions>;
using patch_titles = std::unordered_map<std::string /*serial*/, patch_serials>;
@@ -99,7 +99,7 @@ public:
static std::string get_imported_patch_path();
// Load from file and append to specified patches map
static bool load(patch_map& patches, const std::string& path, bool importing = false, std::stringstream* log_messages = nullptr);
static bool load(patch_map& patches, const std::string& path, std::string content = "", bool importing = false, std::stringstream* log_messages = nullptr);
// Read and add a patch node to the patch info
static bool read_patch_node(patch_info& info, YAML::Node node, const YAML::Node& root, std::stringstream* log_messages = nullptr);
@@ -117,7 +117,7 @@ public:
static bool save_patches(const patch_map& patches, const std::string& path, std::stringstream* log_messages = nullptr);
// Create or append patches to a file
static bool import_patches(const patch_map& patches, const std::string& path, size_t& count, size_t& total, std::stringstream* log_messages = nullptr);
static bool import_patches(const patch_map& patches, const std::string& path, usz& count, usz& total, std::stringstream* log_messages = nullptr);
// Remove a patch from a file
static bool remove_patch(const patch_info& info);
@@ -132,18 +132,15 @@ public:
void append_title_patches(const std::string& title_id);
// Apply patch (returns the number of entries applied)
std::size_t apply(const std::string& name, u8* dst);
usz apply(const std::string& name, u8* dst);
// Apply patch with a check that the address exists in SPU local storage
std::size_t apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
usz apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
private:
// Load from file and append to member patches map
void append(const std::string& path);
// Internal: Apply patch (returns the number of entries applied)
template <bool check_local_storage>
std::size_t apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
usz apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
// Database
patch_map m_map;
+10 -10
View File
@@ -21,8 +21,9 @@ Examples:
Intersection (&) and symmetric difference (^) is also available.
*/
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include "Utilities/StrFmt.h"
template <typename T>
class atomic_bs_t;
@@ -48,8 +49,8 @@ private:
}
public:
static constexpr std::size_t bitmax = sizeof(T) * 8;
static constexpr std::size_t bitsize = static_cast<under>(T::__bitset_enum_max);
static constexpr usz bitmax = sizeof(T) * 8;
static constexpr usz bitsize = static_cast<under>(T::__bitset_enum_max);
static_assert(std::is_enum<T>::value, "bs_t<> error: invalid type (must be enum)");
static_assert(bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max");
@@ -205,7 +206,7 @@ constexpr bs_t<T> operator ^(T lhs, T rhs)
// Atomic bitset specialization with optimized operations
template <typename T>
class atomic_bs_t : public atomic_t<::bs_t<T>> // TODO: true specialization
class atomic_bs_t : public atomic_t<::bs_t<T>>
{
// Corresponding bitset type
using bs_t = ::bs_t<T>;
@@ -379,11 +380,6 @@ public:
return lhs.m_data != rhs.load().m_data;
}
bool test(const bs_t& rhs)
{
return base::load().test(rhs);
}
bool test_and_set(T rhs)
{
return atomic_storage<under>::bts(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
@@ -394,10 +390,14 @@ public:
return atomic_storage<under>::btr(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
}
bool test_and_complement(T rhs)
bool test_and_invert(T rhs)
{
return atomic_storage<under>::btc(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
}
bool bit_test_set(uint bit) = delete;
bool bit_test_reset(uint bit) = delete;
bool bit_test_invert(uint bit) = delete;
};
template <typename T>
+22 -22
View File
@@ -1,12 +1,12 @@
#pragma once
#include "types.h"
#include "util/types.hpp"
#include <climits>
#include <string>
#include <vector>
#include <algorithm>
static const size_t size_dropped = std::numeric_limits<size_t>::max();
static const usz size_dropped = -1;
/*
C-style format parser. Appends formatted string to `out`, returns number of characters written.
@@ -15,13 +15,13 @@ C-style format parser. Appends formatted string to `out`, returns number of char
`src`: rvalue reference to argument provider.
*/
template<typename Dst, typename Char, typename Src>
std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
{
const std::size_t start_pos = out.size();
const usz start_pos = out.size();
struct cfmt_context
{
std::size_t size; // Size of current format sequence
usz size; // Size of current format sequence
u8 args; // Number of extra args used
u8 type; // Integral type bytesize
@@ -80,7 +80,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const auto write_decimal = [&](u64 value, s64 min_size)
{
const std::size_t start = out.size();
const usz start = out.size();
do
{
@@ -90,7 +90,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
while (0 < --min_size || value);
// Revert written characters
for (std::size_t i = start, j = out.size() - 1; i < j; i++, j--)
for (usz i = start, j = out.size() - 1; i < j; i++, j--)
{
std::swap(out[i], out[j]);
}
@@ -285,7 +285,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}
const std::size_t start = out.size();
const usz start = out.size();
out.push_back(src.template get<Char>(ctx.args));
if (1 < ctx.width)
@@ -307,8 +307,8 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}
const std::size_t start = out.size();
const std::size_t size1 = src.fmt_string(out, ctx.args);
const usz start = out.size();
const usz size1 = src.fmt_string(out, ctx.args);
if (ctx.dot && size1 > ctx.prec)
{
@@ -316,7 +316,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
out.resize(start + ctx.prec);
}
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -352,7 +352,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const u64 val = src.template get<u64>(ctx.args);
const bool negative = ctx.type && static_cast<s64>(val) < 0;
const std::size_t start = out.size();
const usz start = out.size();
if (!ctx.dot || ctx.prec)
{
@@ -372,7 +372,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
write_decimal(negative ? 0 - val : val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -419,7 +419,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
const usz start = out.size();
if (ctx.alter)
{
@@ -435,7 +435,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
write_octal(val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -476,7 +476,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
const usz start = out.size();
if (ctx.alter)
{
@@ -493,7 +493,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
write_hex(val, ch == 'X', ctx.prec);
}
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -540,14 +540,14 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
const usz start = out.size();
if (!ctx.dot || ctx.prec)
{
write_decimal(val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -570,11 +570,11 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const u64 val = src.template get<u64>(ctx.args);
const std::size_t start = out.size();
const usz start = out.size();
write_hex(val, false, sizeof(void*) * 2);
const std::size_t size2 = out.size() - start;
const usz size2 = out.size() - start;
if (size2 < ctx.width)
{
@@ -610,7 +610,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const u64 arg1 = ctx.args >= 1 ? src.template get<u64>(1) : 0;
const u64 arg2 = ctx.args >= 2 ? src.template get<u64>(2) : 0;
if (const std::size_t _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2))
if (const usz _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2))
{
out.resize(out.size() + _size);
std::snprintf(&out.front() + out.size() - _size, _size + 1, _fmt.c_str(), arg0, arg1, arg2);
+1 -1
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "cheat_info.h"
#include "Config.h"
#include "StrUtil.h"
+4 -2
View File
@@ -1,6 +1,8 @@
#pragma once
#pragma once
#include "stdafx.h"
#include "util/types.hpp"
#include <string>
enum class cheat_type : u8
{
+5 -5
View File
@@ -1,4 +1,4 @@
#include "cond.h"
#include "cond.h"
#include "sync.h"
#include "lockless.h"
@@ -9,10 +9,10 @@
void cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
{
// Not supposed to fail
verify(HERE), _old;
ensure(_old);
// Wait with timeout
m_value.wait<c_signal_mask>(_old, atomic_wait_timeout{_timeout > max_timeout ? UINT64_MAX : _timeout * 1000});
m_value.wait(_old, c_signal_mask, atomic_wait_timeout{_timeout > max_timeout ? UINT64_MAX : _timeout * 1000});
// Cleanup
m_value.atomic_op([](u32& value)
@@ -50,10 +50,10 @@ void cond_variable::imp_wake(u32 _count) noexcept
if (_count > 1 || ((_old + (c_signal_mask & (0 - c_signal_mask))) & c_signal_mask) == c_signal_mask)
{
// Resort to notify_all if signal count reached max
m_value.notify_all();
m_value.notify_all(c_signal_mask);
}
else
{
m_value.notify_one();
m_value.notify_one(c_signal_mask);
}
}
+1 -2
View File
@@ -1,8 +1,7 @@
#pragma once
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include <shared_mutex>
// Lightweight condition variable
class cond_variable
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <cmath>
+7 -7
View File
@@ -1,23 +1,23 @@
#pragma once
#include "Utilities/types.h"
#include "util/types.hpp"
namespace rpcs3
{
template<typename T>
static size_t hash_base(T value)
static usz hash_base(T value)
{
return static_cast<size_t>(value);
return static_cast<usz>(value);
}
template<typename T, typename U>
static size_t hash_struct_base(const T& value)
static usz hash_struct_base(const T& value)
{
// FNV 64-bit
size_t result = 14695981039346656037ull;
usz result = 14695981039346656037ull;
const U *bits = reinterpret_cast<const U*>(&value);
for (size_t n = 0; n < (sizeof(T) / sizeof(U)); ++n)
for (usz n = 0; n < (sizeof(T) / sizeof(U)); ++n)
{
result ^= bits[n];
result *= 1099511628211ull;
@@ -27,7 +27,7 @@ namespace rpcs3
}
template<typename T>
static size_t hash_struct(const T& value)
static usz hash_struct(const T& value)
{
static constexpr auto block_sz = sizeof(T);
+20 -9
View File
@@ -1,6 +1,6 @@
#pragma once
#pragma once
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
@@ -8,7 +8,7 @@
//!
//! T is the type of elements. Currently, default constructor of T shall be constexpr.
//! N is initial element count, available without any memory allocation and only stored contiguously.
template <typename T, std::size_t N>
template <typename T, usz N>
class lf_array
{
// Data (default-initialized)
@@ -28,7 +28,7 @@ public:
}
}
T& operator [](std::size_t index)
T& operator [](usz index)
{
if (index < N) [[likely]]
{
@@ -51,7 +51,7 @@ public:
//! Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters.
//! There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own.
template<typename T, std::size_t N>
template<typename T, usz N>
class lf_fifo : public lf_array<T, N>
{
// LSB 32-bit: push, MSB 32-bit: pop
@@ -307,14 +307,25 @@ public:
delete m_head.load();
}
void wait() noexcept
template <atomic_wait::op Flags = atomic_wait::op::eq>
void wait(std::nullptr_t null = nullptr) noexcept
{
if (m_head == nullptr)
{
m_head.wait(nullptr);
m_head.template wait<Flags>(nullptr);
}
}
const volatile void* observe() const noexcept
{
return m_head.load();
}
explicit operator bool() const noexcept
{
return m_head != nullptr;
}
template <typename... Args>
void push(Args&&... args)
{
@@ -343,9 +354,9 @@ public:
// Apply func(data) to each element, return the total length
template <typename F>
std::size_t apply(F func)
usz apply(F func)
{
std::size_t count = 0;
usz count = 0;
for (auto slice = pop_all(); slice; slice.pop_front())
{
+11 -102
View File
@@ -1,8 +1,10 @@
#include "mutex.h"
#include "util/asm.hpp"
void shared_mutex::imp_lock_shared(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
ensure(val < c_err); // "shared_mutex underflow"
for (int i = 0; i < 10; i++)
{
@@ -23,14 +25,14 @@ void shared_mutex::imp_lock_shared(u32 val)
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
ensure((old % c_sig) + c_one < c_sig); // "shared_mutex overflow"
imp_wait();
lock_downgrade();
}
void shared_mutex::imp_unlock_shared(u32 old)
{
verify("shared_mutex underflow" HERE), old - 1 < c_err;
ensure(old - 1 < c_err); // "shared_mutex underflow"
// Check reader count, notify the writer if necessary
if ((old - 1) % c_one == 0)
@@ -39,84 +41,6 @@ void shared_mutex::imp_unlock_shared(u32 old)
}
}
void shared_mutex::imp_lock_low(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
for (int i = 0; i < 10; i++)
{
busy_wait();
if (try_lock_low())
{
return;
}
}
// Acquire writer lock and downgrade
const u32 old = m_value.fetch_add(c_one);
if (old == 0)
{
lock_downgrade();
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
imp_wait();
lock_downgrade();
}
void shared_mutex::imp_unlock_low(u32 old)
{
verify("shared_mutex underflow" HERE), old - 1 < c_err;
// Check reader count, notify the writer if necessary
if ((old - 1) % c_vip == 0)
{
imp_signal();
}
}
void shared_mutex::imp_lock_vip(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
for (int i = 0; i < 10; i++)
{
busy_wait();
if (try_lock_vip())
{
return;
}
}
// Acquire writer lock and downgrade
const u32 old = m_value.fetch_add(c_one);
if (old == 0)
{
lock_downgrade_to_vip();
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
imp_wait();
lock_downgrade_to_vip();
}
void shared_mutex::imp_unlock_vip(u32 old)
{
verify("shared_mutex underflow" HERE), old - 1 < c_err;
// Check reader count, notify the writer if necessary
if ((old - 1) % c_one / c_vip == 0)
{
imp_signal();
}
}
void shared_mutex::imp_wait()
{
while (true)
@@ -137,19 +61,19 @@ void shared_mutex::imp_wait()
break;
}
m_value.wait(old);
m_value.wait(old, c_sig);
}
}
void shared_mutex::imp_signal()
{
m_value += c_sig;
m_value.notify_one();
m_value.notify_one(c_sig);
}
void shared_mutex::imp_lock(u32 val)
{
verify("shared_mutex underflow" HERE), val < c_err;
ensure(val < c_err); // "shared_mutex underflow"
for (int i = 0; i < 10; i++)
{
@@ -168,13 +92,13 @@ void shared_mutex::imp_lock(u32 val)
return;
}
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
ensure((old % c_sig) + c_one < c_sig); // "shared_mutex overflow"
imp_wait();
}
void shared_mutex::imp_unlock(u32 old)
{
verify("shared_mutex underflow" HERE), old - c_one < c_err;
ensure(old - c_one < c_err); // "shared_mutex underflow"
// 1) Notify the next writer if necessary
// 2) Notify all readers otherwise if necessary (currently indistinguishable from writers)
@@ -199,7 +123,7 @@ void shared_mutex::imp_lock_upgrade()
// Convert to writer lock
const u32 old = m_value.fetch_add(c_one - 1);
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one - 1 < c_sig;
ensure((old % c_sig) + c_one - 1 < c_sig); // "shared_mutex overflow"
if (old % c_one == 1)
{
@@ -241,18 +165,3 @@ void shared_mutex::imp_lock_unlock()
imp_wait();
unlock();
}
bool shared_mutex::downgrade_unique_vip_lock_to_low_or_unlock()
{
return m_value.atomic_op([](u32& value)
{
if (value % c_one / c_vip == 1)
{
value -= c_vip - 1;
return true;
}
value -= c_vip;
return false;
});
}
+2 -118
View File
@@ -1,7 +1,7 @@
#pragma once
#include <mutex>
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
// Shared mutex with small size (u32).
@@ -12,17 +12,12 @@ class shared_mutex final
c_one = 1u << 14, // Fixed-point 1.0 value (one writer, max_readers = c_one - 1)
c_sig = 1u << 30,
c_err = 1u << 31,
c_vip = 1u << 7,
};
atomic_t<u32> m_value{};
void imp_lock_shared(u32 val);
void imp_unlock_shared(u32 old);
void imp_lock_low(u32 val);
void imp_unlock_low(u32 old);
void imp_lock_vip(u32 val);
void imp_unlock_vip(u32 old);
void imp_wait();
void imp_signal();
void imp_lock(u32 val);
@@ -88,64 +83,6 @@ public:
}
}
bool try_lock_low()
{
const u32 value = m_value.load();
// Conditional increment
return value < c_vip - 1 && m_value.compare_and_swap_test(value, value + 1);
}
void lock_low()
{
const u32 value = m_value.load();
if (value >= c_vip - 1 || !m_value.compare_and_swap_test(value, value + 1)) [[unlikely]]
{
imp_lock_low(value);
}
}
void unlock_low()
{
// Unconditional decrement (can result in broken state)
const u32 value = m_value.fetch_sub(1);
if (value >= c_one) [[unlikely]]
{
imp_unlock_low(value);
}
}
bool try_lock_vip()
{
const u32 value = m_value.load();
// Conditional increment
return (value < c_one - 1 || value & (c_one - c_vip)) && (value % c_vip) == 0 && m_value.compare_and_swap_test(value, value + c_vip);
}
void lock_vip()
{
const u32 value = m_value.load();
if ((value >= c_one - 1 && !(value & (c_one - c_vip))) || (value % c_vip) || !m_value.compare_and_swap_test(value, value + c_vip)) [[unlikely]]
{
imp_lock_vip(value);
}
}
void unlock_vip()
{
// Unconditional decrement (can result in broken state)
const u32 value = m_value.fetch_sub(c_vip);
if (value >= c_one) [[unlikely]]
{
imp_unlock_vip(value);
}
}
bool try_lock()
{
return m_value.compare_and_swap_test(0, c_one);
@@ -214,12 +151,6 @@ public:
m_value -= c_one - 1;
}
void lock_downgrade_to_vip()
{
// Convert to vip lock (can result in broken state)
m_value -= c_one - c_vip;
}
// Optimized wait for lockability without locking, relaxed
void lock_unlock()
{
@@ -240,12 +171,9 @@ public:
{
return m_value.load() < c_one - 1;
}
// Special purpose logic
bool downgrade_unique_vip_lock_to_low_or_unlock();
};
// Simplified shared (reader) lock implementation. Mutually incompatible with low_lock and vip_lock.
// Simplified shared (reader) lock implementation.
class reader_lock final
{
shared_mutex& m_mutex;
@@ -283,47 +211,3 @@ public:
m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared();
}
};
// Special shared (reader) lock, mutually exclusive with vip locks. Mutually incompatible with normal shared (reader) lock.
class low_lock final
{
shared_mutex& m_mutex;
public:
low_lock(const low_lock&) = delete;
low_lock& operator=(const low_lock&) = delete;
explicit low_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_low();
}
~low_lock()
{
m_mutex.unlock_low();
}
};
// Special shared (reader) lock, mutually exclusive with low locks. Mutually incompatible with normal shared (reader) lock.
class vip_lock final
{
shared_mutex& m_mutex;
public:
vip_lock(const vip_lock&) = delete;
vip_lock& operator=(const vip_lock&) = delete;
explicit vip_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_vip();
}
~vip_lock()
{
m_mutex.unlock_vip();
}
};
+1 -4
View File
@@ -1,7 +1,5 @@
#include "stdafx.h"
#include "restore_new.h"
#include "Utilities/rXml.h"
#include "define_new_memleakdetect.h"
rXmlNode::rXmlNode() : handle()
{
@@ -54,7 +52,7 @@ std::string rXmlNode::GetAttribute(const std::string &name)
std::string rXmlNode::GetNodeContent()
{
return handle.text().get();
return handle.text().get();
}
rXmlDocument::rXmlDocument() : handle()
@@ -70,4 +68,3 @@ std::shared_ptr<rXmlNode> rXmlDocument::GetRoot()
{
return std::make_shared<rXmlNode>(handle.root());
}
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <pugixml.hpp>
#include <memory>
+3 -1
View File
@@ -1,5 +1,7 @@
#include "sema.h"
#include "util/asm.hpp"
void semaphore_base::imp_wait()
{
for (int i = 0; i < 10; i++)
@@ -52,7 +54,7 @@ void semaphore_base::imp_wait()
void semaphore_base::imp_post(s32 _old)
{
verify("semaphore_base: overflow" HERE), _old < 0;
ensure(_old < 0); // "semaphore_base: overflow"
m_value.notify_one();
}
+1 -1
View File
@@ -1,7 +1,7 @@
#pragma once
#include <mutex>
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
// Lightweight semaphore helper class
+13 -3
View File
@@ -2,11 +2,14 @@
/* For internal use. Don't include. */
#include "types.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include "dynamic_library.h"
#include "util/dyn_lib.hpp"
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#include <time.h>
#elif __linux__
@@ -15,6 +18,7 @@
#include <linux/futex.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include <algorithm>
#include <ctime>
@@ -28,6 +32,12 @@ DYNAMIC_IMPORT("ntdll.dll", NtWaitForKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOO
DYNAMIC_IMPORT("ntdll.dll", NtReleaseKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForSingleObject, NTSTATUS(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtDelayExecution, NTSTATUS(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForAlertByThreadId, NTSTATUS(PVOID Address, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtAlertThreadByThreadId, NTSTATUS(DWORD_PTR ThreadId));
constexpr NTSTATUS NTSTATUS_SUCCESS = 0;
constexpr NTSTATUS NTSTATUS_ALERTED = 0x101;
constexpr NTSTATUS NTSTATUS_TIMEOUT = 0x102;
#endif
#ifndef __linux__
@@ -61,7 +71,7 @@ inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* t
};
std::mutex mutex;
std::unordered_multimap<volatile void*, waiter*, pointer_hash<volatile void, alignof(int)>> map;
std::unordered_multimap<volatile void*, waiter*> map;
int operator()(volatile void* uaddr, int futex_op, uint val, const timespec* timeout, uint mask)
{
-1046
View File
File diff suppressed because it is too large Load Diff
-1060
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -67,7 +67,7 @@ namespace utils
int vnum2 = 0;
// Loop until both strings are processed
for (size_t i = 0, j = 0; (i < v1.length() || j < v2.length());)
for (usz i = 0, j = 0; (i < v1.length() || j < v2.length());)
{
// Storing numeric part of version 1 in vnum1
while (i < v1.length() && v1[i] != '.')
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include "util/types.hpp"
#include <string>
namespace utils
+1 -1
View File
@@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>$(CmakeCLI)
@@ -38,7 +38,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<PropsAbsPath>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\common_default.props'))</PropsAbsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-8
View File
@@ -5,10 +5,6 @@
<Configuration>Debug - LLVM</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug - MemLeak|x64">
<Configuration>Debug - MemLeak</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
@@ -108,10 +104,6 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="..\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'" Label="PropertySheets">
<Import Project="..\rpcs3_debug.props" />
<Import Project="..\rpcs3_memleak.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'" Label="PropertySheets">
<Import Project="..\rpcs3_debug.props" />
<Import Project="..\rpcs3_llvm.props" />
+24 -13
View File
@@ -17,10 +17,12 @@ jobs:
COMPILER: clang
GCC:
COMPILER: gcc
DEPLOY_APPIMAGE: true
variables:
CCACHE_DIR: $(Pipeline.Workspace)/ccache
IS_AZURE: true
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-linux"
DEPLOY_APPIMAGE: true
pool:
vmImage: 'ubuntu-latest'
steps:
@@ -31,30 +33,40 @@ jobs:
displayName: ccache
- bash: |
docker pull --quiet rpcs3/rpcs3-travis-xenial:1.5
docker pull --quiet rpcs3/rpcs3-travis-xenial:1.7
docker run \
-v $(pwd):/rpcs3 \
--env-file .ci/travis.env \
--env-file .ci/docker.env \
-v $CCACHE_DIR:/root/.ccache \
-v $BUILD_ARTIFACTSTAGINGDIRECTORY:/root/artifacts \
rpcs3/rpcs3-travis-xenial:1.5 \
rpcs3/rpcs3-travis-xenial:1.7 \
/rpcs3/.ci/build-linux.sh
displayName: Docker setup and build
- publish: $(Build.ArtifactStagingDirectory)
condition: and(succeeded(), eq(variables['COMPILER'], 'gcc'))
artifact: RPCS3 for Linux
condition: succeeded()
artifact: RPCS3 for Linux ($(COMPILER))
- bash: .ci/github-upload.sh
condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['COMPILER'], 'gcc'))
displayName: Push build to GitHub
env:
RPCS3_TOKEN: $(RPCS3-Token)
- job: Windows_Build
variables:
COMPILER: msvc
QT_VER: '5.14.2'
QT_DATE: '202003291224'
QTDIR: C:\Qt\$(QT_VER)\msvc2017_64
VULKAN_VER: '1.2.148.1'
VULKAN_SDK_SHA: '5dbeafbc75c334811720fb50bd6ed7c9afd42afd31cad6be0b84cd8383aa9472'
QT_VER_MAIN: '5'
QT_VER: '5.15.2'
QT_VER_MSVC: 'msvc2019'
QT_DATE: '202011130602'
QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64
VULKAN_VER: '1.2.154.1'
VULKAN_SDK_SHA: 'b64471f3a720e649c1fae6535ea83b8c642655ebed1485bfdf15bf4d88f746d9'
VULKAN_SDK: C:\VulkanSDK\$(VULKAN_VER)
CACHE_DIR: ./cache
UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e
UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-win"
pool:
vmImage: "windows-latest"
@@ -91,7 +103,6 @@ jobs:
maximumCpuCount: true
platform: x64
configuration: 'Release - LLVM'
msbuildArgs: '/p:VCToolsVersion=14.25.28610'
displayName: Compile RPCS3
- bash: .ci/deploy-windows.sh
@@ -101,7 +112,7 @@ jobs:
condition: succeeded()
artifact: RPCS3 for Windows
- bash: .ci/github-upload-windows.sh
- bash: .ci/github-upload.sh
condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: Push build to GitHub
env:
+1 -1
Submodule llvm updated: f5679565d3...cb7748dfa0
+1 -1
View File
@@ -1,7 +1,7 @@
REM You need cmake and python to update the project files
REM this script relies on CWD being the path that this script is in
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
cmake -G "Visual Studio 16 2019 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_INTEL_JITEVENTS=ON -DLLVM_ENABLE_Z3_SOLVER=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=10.0 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm
RD /S /Q cmake
RD /S /Q CMakeFiles
+1 -1
View File
@@ -39,7 +39,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakePreprocessorDefinitions>
-38
View File
@@ -98,7 +98,6 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - LLVM|x64 = Debug - LLVM|x64
Debug - MemLeak|x64 = Debug - MemLeak|x64
Debug|x64 = Debug|x64
Release - LLVM|x64 = Release - LLVM|x64
Release|x64 = Release|x64
@@ -106,8 +105,6 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -116,8 +113,6 @@ Global
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.Build.0 = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.ActiveCfg = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.Build.0 = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -125,14 +120,11 @@ Global
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.ActiveCfg = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.Build.0 = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release - LLVM|x64.ActiveCfg = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release|x64.ActiveCfg = Release|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug|x64.ActiveCfg = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug|x64.Build.0 = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -141,8 +133,6 @@ Global
{3384223A-6D97-4799-9862-359F85312892}.Release|x64.Build.0 = Release|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug|x64.ActiveCfg = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug|x64.Build.0 = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -151,8 +141,6 @@ Global
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release|x64.Build.0 = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|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 - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -160,8 +148,6 @@ Global
{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 - LLVM|x64.ActiveCfg = Release|x64
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug - MemLeak|x64.ActiveCfg = Release|x64
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug - MemLeak|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 - LLVM|x64.ActiveCfg = Release|x64
@@ -170,8 +156,6 @@ Global
{EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|x64.Build.0 = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - LLVM|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - LLVM|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - MemLeak|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - MemLeak|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release - LLVM|x64.ActiveCfg = Release Library|x64
@@ -180,8 +164,6 @@ Global
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|x64.Build.0 = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - LLVM|x64.Build.0 = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - MemLeak|x64.Build.0 = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.ActiveCfg = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.Build.0 = Debug|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -189,14 +171,11 @@ Global
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.ActiveCfg = Release|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.Build.0 = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release - LLVM|x64.ActiveCfg = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release|x64.ActiveCfg = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug|x64.ActiveCfg = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug|x64.Build.0 = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -205,8 +184,6 @@ Global
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release|x64.Build.0 = Release|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - LLVM|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - MemLeak|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -215,8 +192,6 @@ Global
{FDC361C5-7734-493B-8CFB-037308B35122}.Release|x64.Build.0 = Release|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.Build.0 = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.ActiveCfg = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.Build.0 = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -225,8 +200,6 @@ Global
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.Build.0 = Release|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug - LLVM|x64.Build.0 = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug - MemLeak|x64.Build.0 = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.ActiveCfg = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -235,8 +208,6 @@ Global
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug - LLVM|x64.Build.0 = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug - MemLeak|x64.Build.0 = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.ActiveCfg = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.Build.0 = Debug|x64
{939FE206-1182-ABC3-1234-FEAB88E98404}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -245,8 +216,6 @@ Global
{939FE206-1182-ABC3-1234-FEAB88E98404}.Release|x64.Build.0 = Release|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug - LLVM|x64.Build.0 = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug - MemLeak|x64.Build.0 = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -255,8 +224,6 @@ Global
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug - LLVM|x64.Build.0 = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug - MemLeak|x64.Build.0 = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug|x64.ActiveCfg = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Debug|x64.Build.0 = Debug|x64
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -265,8 +232,6 @@ Global
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}.Release|x64.Build.0 = Release|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug - LLVM|x64.Build.0 = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug - MemLeak|x64.Build.0 = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Release - LLVM|x64.ActiveCfg = Release|x64
@@ -275,8 +240,6 @@ Global
{73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug - MemLeak|x64.Build.0 = Debug|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug|x64.ActiveCfg = Debug|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Debug|x64.Build.0 = Debug|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
@@ -284,7 +247,6 @@ Global
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Release|x64.ActiveCfg = Release|x64
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.Release|x64.Build.0 = Release|x64
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Debug|x64.ActiveCfg = Debug|x64
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Release - LLVM|x64.ActiveCfg = Release|x64
{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}.Release|x64.ActiveCfg = Release|x64
+2 -1
View File
@@ -58,6 +58,7 @@ set(RPCS3_SRC
Input/basic_mouse_handler.cpp
Input/ds3_pad_handler.cpp
Input/ds4_pad_handler.cpp
Input/dualsense_pad_handler.cpp
Input/evdev_joystick_handler.cpp
Input/keyboard_pad_handler.cpp
Input/mm_joystick_handler.cpp
@@ -107,7 +108,7 @@ if(UNIX)
endif()
if(WIN32)
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib Psapi.lib gdi32.lib setupapi.lib)
target_link_libraries(rpcs3 ws2_32.lib Iphlpapi.lib Winmm.lib Psapi.lib gdi32.lib setupapi.lib)
else()
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS})
endif()
+1 -1
View File
@@ -1,4 +1,4 @@
#include "utils.h"
#include "utils.h"
#include "aes.h"
#include "key_vault.h"
#include "util/logs.hpp"
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#pragma once
#include "Utilities/types.h"
#include "util/types.hpp"
#include <string>
#include <vector>
+75 -44
View File
@@ -1,10 +1,12 @@
#include "stdafx.h"
#include "stdafx.h"
#include "key_vault.h"
#include "unedat.h"
#include "Utilities/mutex.h"
#include <cmath>
#include "util/asm.hpp"
LOG_CHANNEL(edat_log, "EDAT");
// Static variables are being modified concurrently in ec.cpp, for now use a mutex
@@ -135,15 +137,15 @@ std::tuple<u64, s32, s32> dec_section(unsigned char* metadata)
return std::make_tuple(offset, length, compression_end);
}
v128 get_block_key(int block, NPD_HEADER *npd)
u128 get_block_key(int block, NPD_HEADER *npd)
{
unsigned char empty_key[0x10] = {};
unsigned char *src_key = (npd->version <= 1) ? empty_key : npd->dev_hash;
v128 dest_key{};
memcpy(dest_key._bytes, src_key, 0xC);
u128 dest_key{};
std::memcpy(&dest_key, src_key, 0xC);
s32 swappedBlock = swap32(block);
memcpy(&dest_key._bytes[0xC], &swappedBlock, sizeof(swappedBlock));
std::memcpy(reinterpret_cast<uchar*>(&dest_key) + 0xC, &swappedBlock, sizeof(swappedBlock));
return dest_key;
}
@@ -248,7 +250,7 @@ s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER *edat, NPD_HEADER *np
auto b_key = get_block_key(block_num, npd);
// Encrypt the block key with the crypto key.
aesecb128_encrypt(crypt_key, b_key._bytes, key_result);
aesecb128_encrypt(crypt_key, reinterpret_cast<uchar*>(&b_key), key_result);
if ((edat->flags & EDAT_FLAG_0x10) != 0)
aesecb128_encrypt(crypt_key, key_result, hash); // If FLAG 0x10 is set, encrypt again to get the final hash.
else
@@ -553,9 +555,10 @@ int validate_dev_klic(const u8* klicensee, NPD_HEADER *npd)
memcpy(dev + 0xC, &type, 4);
// Check for an empty dev_hash (can't validate if devklic is NULL);
auto klic = v128::loadu(klicensee);
u128 klic;
std::memcpy(&klic, klicensee, sizeof(klic));
if (klic == v128{})
if (!klic)
{
// Allow empty dev hash.
return 1;
@@ -563,10 +566,10 @@ int validate_dev_klic(const u8* klicensee, NPD_HEADER *npd)
else
{
// Generate klicensee xor key.
auto key = klic ^ std::bit_cast<v128>(NP_OMAC_KEY_2);
u128 key = klic ^ std::bit_cast<u128>(NP_OMAC_KEY_2);
// Hash with generated key and compare with dev_hash.
return cmac_hash_compare(key._bytes, 0x10, dev, 0x60, npd->dev_hash, 0x10);
return cmac_hash_compare(reinterpret_cast<uchar*>(&key), 0x10, dev, 0x60, npd->dev_hash, 0x10);
}
}
@@ -575,15 +578,33 @@ int validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *
int title_hash_result = 0;
int dev_hash_result = 0;
const s32 file_name_length = ::narrow<s32>(std::strlen(file_name), HERE);
std::unique_ptr<u8[]> buf(new u8[0x30 + file_name_length]);
const s32 file_name_length = ::narrow<s32>(std::strlen(file_name));
const usz buf_len = 0x30 + file_name_length;
std::unique_ptr<u8[]> buf(new u8[buf_len]);
std::unique_ptr<u8[]> buf_lower(new u8[buf_len]);
std::unique_ptr<u8[]> buf_upper(new u8[buf_len]);
// Build the title buffer (content_id + file_name).
memcpy(buf.get(), npd->content_id, 0x30);
memcpy(buf.get() + 0x30, file_name, file_name_length);
std::memcpy(buf.get(), npd->content_id, 0x30);
std::memcpy(buf.get() + 0x30, file_name, file_name_length);
std::memcpy(buf_lower.get(), buf.get(), buf_len);
std::memcpy(buf_upper.get(), buf.get(), buf_len);
for (usz i = std::basic_string_view<u8>(buf.get() + 0x30, file_name_length).find_last_of('.'); i < buf_len; i++)
{
const u8 c = static_cast<u8>(buf[i]);
buf_upper[i] = std::toupper(c);
buf_lower[i] = std::tolower(c);
}
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf.get(), 0x30 + file_name_length, npd->title_hash, 0x10);
// Try to ignore case sensivity with file extension
title_hash_result =
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf.get(), buf_len, npd->title_hash, 0x10) ||
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf_lower.get(), buf_len, npd->title_hash, 0x10) ||
cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf_upper.get(), buf_len, npd->title_hash, 0x10);
if (verbose)
{
@@ -647,7 +668,7 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
}
// Set decryption key.
v128 key{};
u128 key{};
// Check EDAT/SDAT flag.
if ((EDAT.flags & SDAT_FLAG) == SDAT_FLAG)
@@ -661,7 +682,7 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
}
// Generate SDAT key.
key = std::bit_cast<v128>(NPD.dev_hash) ^ std::bit_cast<v128>(SDAT_KEY);
key = std::bit_cast<u128>(NPD.dev_hash) ^ std::bit_cast<u128>(SDAT_KEY);
}
else
{
@@ -674,7 +695,7 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
}
// Perform header validation (EDAT only).
char real_file_name[MAX_PATH];
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name, real_file_name);
if (!validate_npd_hashes(real_file_name, devklic, &NPD, verbose))
{
@@ -694,21 +715,27 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
memcpy(&key, rifkey, 0x10);
// Make sure we don't have an empty RIF key.
if (key == v128{})
if (!key)
{
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file!");
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file! (local activation)");
return 1;
}
}
else if ((NPD.license & 0x1) == 0x1) // Type 1: Use network activation.
{
edat_log.error("EDAT: Network license not supported!");
return 1;
memcpy(&key, rifkey, 0x10);
// Make sure we don't have an empty RIF key.
if (!key)
{
edat_log.error("EDAT: A valid RAP file is needed for this EDAT file! (network activation)");
return 1;
}
}
if (verbose)
{
be_t<v128> data;
be_t<u128> data;
std::memcpy(&data, devklic, sizeof(data));
edat_log.notice("DEVKLIC: %s", data);
@@ -719,18 +746,18 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
if (verbose)
{
edat_log.notice("DECRYPTION KEY: %s", std::bit_cast<be_t<v128>>(key));
edat_log.notice("DECRYPTION KEY: %s", std::bit_cast<be_t<u128>>(key));
}
input->seek(0);
if (check_data(key._bytes, &EDAT, &NPD, input, verbose))
if (check_data(reinterpret_cast<uchar*>(&key), &EDAT, &NPD, input, verbose))
{
edat_log.error("EDAT: Data parsing failed!");
return 1;
}
input->seek(0);
if (decrypt_data(input, output, &EDAT, &NPD, key._bytes, verbose))
if (decrypt_data(input, output, &EDAT, &NPD, reinterpret_cast<uchar*>(&key), verbose))
{
edat_log.error("EDAT: Data decryption failed!");
return 1;
@@ -739,14 +766,14 @@ bool extract_all_data(const fs::file* input, const fs::file* output, const char*
return 0;
}
v128 GetEdatRifKeyFromRapFile(const fs::file& rap_file)
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file)
{
v128 rapkey{};
v128 rifkey{};
u128 rapkey{};
u128 rifkey{};
rap_file.read<v128>(rapkey);
rap_file.read<u128>(rapkey);
rap_to_rif(rapkey._bytes, rifkey._bytes);
rap_to_rif(reinterpret_cast<uchar*>(&rapkey), reinterpret_cast<uchar*>(&rifkey));
return rifkey;
}
@@ -774,7 +801,7 @@ bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& inpu
}
// Perform header validation (EDAT only).
char real_file_name[MAX_PATH];
char real_file_name[CRYPTO_MAX_PATH];
extract_file_name(input_file_name.c_str(), real_file_name);
if (!validate_npd_hashes(real_file_name, custom_klic, &NPD, false))
{
@@ -797,8 +824,8 @@ fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name,
input.seek(0);
// Set keys (RIF and DEVKLIC).
v128 rifKey{};
v128 devklic{};
u128 rifKey{};
u128 devklic{};
// Select the EDAT key mode.
switch (mode)
@@ -852,7 +879,7 @@ fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name,
// Delete the bad output file if any errors arise.
fs::file output = fs::make_stream<std::vector<u8>>();
if (extract_all_data(&input, &output, input_file_name.c_str(), devklic._bytes, rifKey._bytes, verbose))
if (extract_all_data(&input, &output, input_file_name.c_str(), reinterpret_cast<uchar*>(&devklic), reinterpret_cast<uchar*>(&rifKey), verbose))
{
output.release();
return fs::file{};
@@ -878,12 +905,12 @@ bool EDATADecrypter::ReadHeader()
if ((edatHeader.flags & SDAT_FLAG) == SDAT_FLAG)
{
// Generate SDAT key.
dec_key = std::bit_cast<v128>(npdHeader.dev_hash) ^ std::bit_cast<v128>(SDAT_KEY);
dec_key = std::bit_cast<u128>(npdHeader.dev_hash) ^ std::bit_cast<u128>(SDAT_KEY);
}
else
{
// verify key
if (validate_dev_klic(dev_key._bytes, &npdHeader) == 0)
if (validate_dev_klic(reinterpret_cast<uchar*>(&dev_key), &npdHeader) == 0)
{
edat_log.error("EDAT: Failed validating klic");
return false;
@@ -896,15 +923,19 @@ bool EDATADecrypter::ReadHeader()
{
dec_key = std::move(rif_key);
if (dec_key == v128{})
if (!dec_key)
{
edat_log.warning("EDAT: Empty Dec key!");
edat_log.warning("EDAT: Empty Dec key for local activation!");
}
}
else if ((npdHeader.license & 0x1) == 0x1) // Type 1: Use network activation.
{
edat_log.error("EDAT: Network license not supported!");
return false;
dec_key = std::move(rif_key);
if (!dec_key)
{
edat_log.warning("EDAT: Empty Dec key for network activation!");
}
}
}
@@ -919,7 +950,7 @@ bool EDATADecrypter::ReadHeader()
}*/
file_size = edatHeader.file_size;
total_blocks = ::aligned_div(edatHeader.file_size, edatHeader.block_size);
total_blocks = utils::aligned_div(edatHeader.file_size, edatHeader.block_size);
return true;
}
@@ -932,7 +963,7 @@ u64 EDATADecrypter::ReadData(u64 pos, u8* data, u64 size)
// 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>(::aligned_div(startOffset + size, 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))
{
@@ -947,7 +978,7 @@ u64 EDATADecrypter::ReadData(u64 pos, u8* data, u64 size)
for (u32 i = starting_block; i < ending_block; ++i)
{
edata_file.seek(0);
u64 res = decrypt_block(&edata_file, &data_buf[writeOffset], &edatHeader, &npdHeader, dec_key._bytes, i, total_blocks, edatHeader.file_size);
u64 res = decrypt_block(&edata_file, &data_buf[writeOffset], &edatHeader, &npdHeader, reinterpret_cast<uchar*>(&dec_key), i, total_blocks, edatHeader.file_size);
if (res == umax)
{
edat_log.error("Error Decrypting data");
+10 -9
View File
@@ -4,7 +4,6 @@
#include "utils.h"
#include "Utilities/BEType.h"
#include "Utilities/File.h"
constexpr u32 SDAT_FLAG = 0x01000000;
@@ -17,8 +16,8 @@ constexpr u32 EDAT_DEBUG_DATA_FLAG = 0x80000000;
struct loaded_npdrm_keys
{
atomic_t<v128> devKlic{};
atomic_t<v128> rifKey{};
atomic_t<u128> devKlic{};
atomic_t<u128> rifKey{};
atomic_t<u32> npdrm_fds{0};
};
@@ -48,7 +47,7 @@ extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, std::string* contentID);
v128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
struct EDATADecrypter final : fs::file_base
{
@@ -65,18 +64,20 @@ struct EDATADecrypter final : fs::file_base
std::unique_ptr<u8[]> data_buf;
u64 data_buf_size{0};
v128 dec_key{};
u128 dec_key{};
// edat usage
v128 rif_key{};
v128 dev_key{};
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 v128& dev_key, const v128& rif_key)
: edata_file(std::move(input)), rif_key(rif_key), dev_key(dev_key) {}
EDATADecrypter(fs::file&& input, const u128& dev_key, const u128& rif_key)
: edata_file(std::move(input))
, rif_key(rif_key)
, dev_key(dev_key) {}
~EDATADecrypter() override {}
// false if invalid
+5 -5
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "aes.h"
#include "sha1.h"
#include "key_vault.h"
@@ -502,7 +502,7 @@ package_error package_reader::check_target_app_version()
const std::string name{ reinterpret_cast<char*>(buf.get()), entry.name_size };
// We're looking for the PARAM.SFO file, if there is any
// We're looking for the PARAM.SFO file, if there is any
if (name != "PARAM.SFO")
{
continue;
@@ -697,7 +697,7 @@ bool package_reader::extract_data(atomic_t<double>& sync)
return false;
}
size_t num_failures = 0;
usz num_failures = 0;
std::vector<PKGEntry> entries(header.file_count);
@@ -857,7 +857,7 @@ void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damo
cur_offset += new_offset;
u64 _offset = 0;
for (size_t i = 0; i < filelist.size(); i++)
for (usz i = 0; i < filelist.size(); i++)
{
if (cur_offset < (_offset + filelist[i].size()))
{
@@ -872,7 +872,7 @@ void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damo
u64 package_reader::archive_read(void* data_ptr, const u64 num_bytes)
{
ASSERT(filelist.size() > cur_file && filelist[cur_file]);
ensure(filelist.size() > cur_file && filelist[cur_file]);
const u64 num_bytes_left = filelist[cur_file].size() - cur_file_offset;
+6 -7
View File
@@ -1,6 +1,5 @@
#pragma once
#include "Utilities/BEType.h"
#include <sstream>
#include <iomanip>
@@ -96,7 +95,7 @@ struct PKGExtHeader
be_t<u32> ext_hdr_size; // Extended header size. ex: 0x40
be_t<u32> ext_data_size; // ex: 0x180
be_t<u32> main_and_ext_headers_hmac_offset; // ex: 0x100
be_t<u32> metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490
be_t<u32> metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490
be_t<u64> tail_offset; // tail size seams to be always 0x1A0
be_t<u32> padding1;
be_t<u32> pkg_key_id; // Id of the AES key used for decryption. PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004
@@ -118,16 +117,16 @@ struct PKGEntry
struct PKGMetaData
{
private:
static std::string to_hex_string(u8 buf[], size_t size)
static std::string to_hex_string(u8 buf[], usz size)
{
std::stringstream sstream;
for (size_t i = 0; i < size; i++)
for (usz i = 0; i < size; i++)
{
sstream << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(buf[i]);
}
return sstream.str();
}
static std::string to_hex_string(u8 buf[], size_t size, size_t dotpos)
static std::string to_hex_string(u8 buf[], usz size, usz dotpos)
{
std::string result = to_hex_string(buf, size);
if (result.size() > dotpos)
@@ -313,14 +312,14 @@ private:
u64 archive_read(void* data_ptr, const u64 num_bytes);
u64 decrypt(u64 offset, u64 size, const uchar* key);
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
const usz BUF_SIZE = 8192 * 1024; // 8 MB
bool m_is_valid = false;
std::string m_path;
std::string install_dir;
std::vector<fs::file> filelist;
size_t cur_file = 0;
usz cur_file = 0;
u64 cur_offset = 0;
u64 cur_file_offset = 0;
std::unique_ptr<u128[]> buf;
+20 -17
View File
@@ -1,9 +1,8 @@
#include "stdafx.h"
#include "stdafx.h"
#include "aes.h"
#include "sha1.h"
#include "utils.h"
#include "unself.h"
#include "Utilities/BEType.h"
#include "Emu/VFS.h"
#include "Emu/System.h"
@@ -714,7 +713,7 @@ bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
}
// Perform AES-CTR encryption on the metadata headers.
size_t ctr_nc_off = 0;
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
aes_setkey_enc(&aes, meta_info.key, 128);
aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get());
@@ -745,7 +744,7 @@ bool SCEDecrypter::DecryptData()
// Calculate the total data size.
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
}
// Allocate a buffer to store decrypted data.
@@ -757,7 +756,7 @@ bool SCEDecrypter::DecryptData()
// Parse the metadata section headers to find the offsets of encrypted data.
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
size_t ctr_nc_off = 0;
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
u8 data_key[0x10];
u8 data_iv[0x10];
@@ -799,7 +798,7 @@ bool SCEDecrypter::DecryptData()
}
// Advance the buffer's offset.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
}
return true;
@@ -823,13 +822,13 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
// Decompress if necessary.
if (meta_shdr[i].compressed == 2)
{
const size_t BUFSIZE = 32 * 1024;
const usz BUFSIZE = 32 * 1024;
u8 tempbuf[BUFSIZE];
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = ::narrow<uInt>(meta_shdr[i].data_size, HERE);
strm.avail_in = ::narrow<uInt>(meta_shdr[i].data_size);
strm.avail_out = BUFSIZE;
strm.next_in = data_buf.get()+data_buf_offset;
strm.next_out = tempbuf;
@@ -874,7 +873,7 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
}
// Advance the data buffer offset by data size.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
if (out_f.pos() != out_f.size())
fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size());
@@ -1112,8 +1111,12 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
if (ctrl->npdrm.license == 1) // Network license.
{
self_log.error("SELF: Can't decrypt network NPDRM!");
return false;
// Try to find a RAP file to get the key.
if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key))
{
self_log.error("SELF: Can't decrypt network NPDRM!");
return false;
}
}
else if (ctrl->npdrm.license == 2) // Local license.
{
@@ -1205,7 +1208,7 @@ bool SELFDecrypter::LoadMetadata(u8* klic_key)
}
// Perform AES-CTR encryption on the metadata headers.
size_t ctr_nc_off = 0;
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
aes_setkey_enc(&aes, meta_info.key, 128);
aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get());
@@ -1239,7 +1242,7 @@ bool SELFDecrypter::DecryptData()
if (meta_shdr[i].encrypted == 3)
{
if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
}
}
@@ -1252,7 +1255,7 @@ bool SELFDecrypter::DecryptData()
// Parse the metadata section headers to find the offsets of encrypted data.
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
size_t ctr_nc_off = 0;
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
u8 data_key[0x10];
u8 data_iv[0x10];
@@ -1285,7 +1288,7 @@ bool SELFDecrypter::DecryptData()
memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
// Advance the buffer's offset.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
}
}
}
@@ -1484,7 +1487,7 @@ bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
return true;
}
v128 get_default_self_klic()
u128 get_default_self_klic()
{
return std::bit_cast<v128>(NP_KLIC_FREE);
return std::bit_cast<u128>(NP_KLIC_FREE);
}
+4 -5
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include "key_vault.h"
#include "zlib.h"
#include "Utilities/types.h"
#include "util/types.hpp"
#include "Utilities/File.h"
#include "util/logs.hpp"
@@ -489,7 +489,7 @@ private:
}
// Advance the data buffer offset by data size.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE);
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
}
}
@@ -509,5 +509,4 @@ private:
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr, SelfAdditionalInfo* additional_info = nullptr);
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr);
union v128;
v128 get_default_self_klic();
u128 get_default_self_klic();
+4 -3
View File
@@ -8,6 +8,7 @@
#include <time.h>
#include "Utilities/StrUtil.h"
#include "Utilities/span.h"
#include "Utilities/File.h"
#include <memory>
#include <string>
@@ -120,16 +121,16 @@ void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_
aes_cmac(&ctx, in_len, in, hash);
}
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH])
{
std::string_view v(file_path);
if (auto pos = v.find_last_of("/\\"); pos != umax)
if (auto pos = v.find_last_of(fs::delim); pos != umax)
{
v.remove_prefix(pos + 1);
}
gsl::span r(real_file_name, MAX_PATH);
gsl::span r(real_file_name, CRYPTO_MAX_PATH);
strcpy_trunc(r, v);
return real_file_name;
}
+4 -4
View File
@@ -4,9 +4,7 @@
// Licensed under the terms of the GNU GPL, version 3
// http://www.gnu.org/licenses/gpl-3.0.txt
#include "../../Utilities/types.h"
#define MAX_PATH 4096
#include "util/types.hpp"
#include <stdlib.h>
#include "aes.h"
@@ -14,6 +12,8 @@
#include "lz.h"
#include "ec.h"
enum { CRYPTO_MAX_PATH = 4096 };
// Auxiliary functions (endian swap, xor, and file name).
inline u16 swap16(u16 i)
{
@@ -42,7 +42,7 @@ inline u64 swap64(u64 i)
#endif
}
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH]);
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH]);
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str);
+1 -1
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "OpenALBackend.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Emu/Audio/AudioBackend.h"
#include "3rdparty/OpenAL/include/alext.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_ALSA
#ifndef HAVE_ALSA
#error "ALSA support disabled but still being built."
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "AudioBackend.h"
#include "Emu/system_config.h"
+4 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#pragma once
#include "Utilities/types.h"
#include "util/types.hpp"
#include "Utilities/StrFmt.h"
enum : u32
{
@@ -101,7 +102,7 @@ public:
u32 get_sample_size() const;
u32 get_channels() const;
bool get_convert_to_u16() const;
bool has_capability(u32 cap) const;
+3 -2
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "AudioDumper.h"
#include "Utilities/date_time.h"
@@ -33,7 +33,8 @@ void AudioDumper::WriteData(const void* buffer, u32 size)
{
if (GetCh())
{
verify(HERE), size, m_output.write(buffer, size) == size;
ensure(size);
ensure(m_output.write(buffer, size) == size);
m_header.Size += size;
m_header.RIFF.Size += size;
}
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include "Utilities/types.h"
#include "util/types.hpp"
#include "Utilities/File.h"
struct WAVHeader
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_FAUDIO
#ifndef HAVE_FAUDIO
#error "FAudio support disabled but still being built."
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Emu/Audio/AudioBackend.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef HAVE_PULSE
#ifndef HAVE_PULSE
#error "PulseAudio support disabled but still being built."
#endif
+2 -1
View File
@@ -1,7 +1,8 @@
#ifndef _WIN32
#ifndef _WIN32
#error "XAudio2 can only be built on Windows."
#endif
#include <algorithm>
#include "util/logs.hpp"
#include "Utilities/StrFmt.h"
#include "Emu/System.h"

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