Added RAII wrapper around the the JITPageWriteEnableExecuteDisable() and
JITPageWriteDisableExecuteEnable() to make it so that it is harder to forget to
pair the calls in all code branches as suggested by leoetlino.
In MacOS 11.2 mprotect can no longer change the access protection settings of
pages that were previously marked as executable to anything but PROT_NONE. This
commit works around this new restriction by bypassing the mprotect based write
protection and instead relying on the write protection provided by MAP_JIT.
Analytics:
- Incorporated fix to allow the full set of analytics that was recommended by
spotlightishere
BuildMacOSUniversalBinary:
- The x86_64 slice for a universal binary is now built for 10.12
- The universal binary build script now can be configured though command line
options instead of modifying the script itself.
- os.system calls were replaced with equivalent subprocess calls
- Formatting was reworked to be more PEP 8 compliant
- The script was refactored to make it more modular
- The com.apple.security.cs.disable-library-validation entitlement was removed
Memory Management:
- Changed the JITPageWrite*Execute*() functions to incorporate support for
nesting
Other:
- Fixed several small lint errors
- Fixed doc and formatting mistakes
- Several small refactors to make things clearer
This commit adds support for compiling Dolphin for ARM on MacOS so that it can
run natively on the M1 processors without running through Rosseta2 emulation
providing a 30-50% performance speedup and less hitches from Rosseta2.
It consists of several key changes:
- Adding support for W^X allocation(MAP_JIT) for the ARM JIT
- Adding the machine context and config info to identify the M1 processor
- Additions to the build system and docs to support building universal binaries
- Adding code signing entitlements to access the MAP_JIT functionality
- Updating the MoltenVK libvulkan.dylib to a newer version with M1 support
Any file which includes scmrev.h must be rebuilt when scmrev.h
is regenerated. By not including scmrev.h from any file other
than Version.cpp, incremental builds become a little faster.
The STL has everything we need nowadays.
I have tried to not alter any behavior or semantics with this
change wherever possible. In particular, WriteLow and WriteHigh
in CommandProcessor retain the ability to accidentally undo
another thread's write to the upper half or lower half
respectively. If that should be fixed, it should be done in a
separate commit for clarity. One thing did change: The places
where we were using += on a volatile variable (not an atomic
operation) are now using fetch_add (actually an atomic operation).
Tested with single core and dual core on x86-64 and AArch64.
The control expression editor allows line breaks, but the serialization was
losing anything after the first line break (/r /n).
Instead of opting to encode them and decode them on serialization
(which I tried but was not safe, as it would lose /n written in the string by users),
I opted to replace them with a space.
If we can prove that FCVT will provide a correct conversion,
we can use FCVT. This makes the common case a bit faster
and the less likely cases (unfortunately including zero,
which FCVT actually can convert correctly) a bit slower.
Fixes https://bugs.dolphin-emu.org/issues/12388. Might also fix
other games that have problems with float/paired instructions
in JitArm64, but I haven't tested any.
texture serialization and deserialization used to involve many memory
allocations and deallocations, along with many copies to and from
those allocations. avoid those by reserving a memory region inside the
output and writing there directly, skipping the allocation and copy to
an intermediate buffer entirely.
This adds a CMake option (DOLPHIN_DEFAULT_UPDATE_TRACK) to allow
configuring SCM_UPDATE_TRACK_STR. This is needed to enable auto-updates
in Windows CMake builds by default.
If we know at compile time that the PPC carry flag definitely
has a certain value, we can bake that value into the emitted code
and skip having to read from PPCState.
DualShock UDP Client is the only place in the code that assumed OnConfigChanged()
is called at least once on startup or it won't load up the setting, so I took care of that
More or less a complete rewrite of the function which aims
to be equally good or better for each given input, without
relying on special cases like the old implementation did.
In particular, we now have more extensive support for
MOVN, as mentioned in a TODO comment.
I don't really see the use of this. (Maybe in the past it
was used for when we need a constant number of instructions
for backpatching? But we don't use MOVI2R for that now.)
PR 9262 added a bunch of Jit64 optimizations, some of
which were already in JitArm64 and some which weren't.
This change ports the latter ones to JitArm64.
At least on some CPUs (I found out about this from the
Arm Cortex-A76 Software Optimization Guide), using X30
with BLR is one cycle slower than using another register.
Previously, eaddr would only be partially initialized in the ipv6 case.
Even if there's no support for it, we may as well ensure that the
variable always has deterministic initialization.
While we're at it, we can make the parameter a const reference, given no
members are modified.
EmulationActivity has an instance of Settings. If you go to
SettingsActivity from EmulationActivity and change some settings,
the changes get saved to disk, but EmulationActivity's Settings
instance still contains the old settings in its map of all
settings (assuming the EmulationActivity was not killed by the
system to save memory). Then, once you're done playing your
game and exit EmulationActivity, EmulationActivity calls
Settings.saveSettings. This call to saveSettings first overwrites
the entire INI file with its map of all settings (which is
outdated) in order to save any legacy settings that have changed
(which they haven't, since the GUI doesn't let you change legacy
settings while a game is running). Then, it asks the new config
system to write the most up-to-date values available for non-legacy
settings, which should make all the settings be up-to-date again.
The problem here is that the new config system would skip writing
to disk if no settings changes had been made since the last time
we asked it to write to disk (i.e. since SettingsActivity exited).
NB: Calling Settings.loadSettings in EmulationActivity.onResume
is not a working solution. I assume this is because
SettingsActivity saves its settings in onStop and not onPause.
The config version should always be incremented whenever config is
changed, regardless of callbacks being suppressed or not.
Otherwise, getters can return stale data until another config change
(with callbacks enabled) happens.
An unfortunately large single commit that deglobalizes the DSP code.
(which I'm very sorry about).
This would have otherwise been extremely difficult to separate due to
extensive use of the globals in very coupling ways that would result in
more scaffolding to work around than is worth it.
Aside from the video code, I believe only the DSP code is the hairiest
to deal with in terms of globals, so I guess it's best to get this dealt
with right off the bat.
A summary of what this commit does:
- Turns the DSPInterpreter into its own class
This is the most involved portion of this change.
The bulk of the changes are turning non-member functions into member
functions that would be situated into the Interpreter class.
- Eliminates all usages to globals within DSPCore.
This generally involves turning a lot of non-member functions into
member functions that are either situated within SDSP or DSPCore.
- Discards DSPDebugInterface (it wasn't hooked up to anything,
and for the sake of eliminating global state, I'd rather get rid of
it than think up ways for this class to be integrated with
everything else.
- Readjusts the DSP JIT to handle calling out to member functions.
In most cases, this just means wrapping respective member function
calles into thunk functions.
Surprisingly, this doesn't even make use of the introduced System class.
It was possible all along to do this without it. We can house everything
within the DSPLLE class, which is quite nice =)
The enumerated LOG_TYPE "OSREPORT" is currently used in both EXI_DeviceIPL.cpp and HLE_OS.cpp. In many games, the multitude of game functions detected by HLE_OS.cpp for OSREPORT logging results in poor log readability. This Pull Request remedies that by adding a new enumerated LOG_TYPE "OSREPORT_HLE" for log usage in HLE_OS.cpp.
In the future, further changing how logging in HLE_OS.cpp works may be desirable. As it is, game functions are detected that send a single character to the log. This is a major source of poor readability.
Adds a flag to File::Delete and File::DeleteDir functions to control
whether a console warning is emitted when the file or directory doesn't
exist. The flag is optional and true by default to match current behavior.
Makes File::DeleteDir return true when attempting to delete a
nonexistent path.
The purpose of DeleteDir is to ensure the path doesn't exist after the
call, which is better reflected by the new return value. Additionally,
none of the current callers actually check the return value so this
won't break any existing code.
On Windows, when the Rename function fails to replace an existing file
it will now retry the operation multiple times with increasingly long
delays between attempts. This fixes transient rename failures.
I've been getting sporadic yet annoyingly frequent errors saying:
'IOS_FS: Failed to rename temporary FST file'
These typically appear on startup but I've also gotten them randomly.
Investigation shows this happens when the Windows ReplaceFile function
returns the error ERROR_UNABLE_TO_REMOVE_REPLACED. That happens in the
context of using ReplaceFile to perform an atomic file overwrite, which
is required when saving updates to a file to avoid corruption. The
error mainly happens with the /Wii/fst.bin file but I've seen it
happen with multiple other files as well.
I haven't been able to definitively pin down why the error occurs,
though online discussions suggest antivirus scanning may be a major
culprit. That said, I've excluded the Dolphin folder from Windows
Defender scans to no avail and don't have any other antivirus running,
so this is likely to be a problem others are experiencing as well.
The number and duration of retry delays is arbitrary but I feel like a
combined second or so in the worst case is an acceptable tradeoff for
the reduction (actually elimination in my experience) of those errors.
This is even more true when you consider the time it takes to read and
dismiss the error dialogs.
The way Config::Get works in master, it first calls
Config::GetActiveLayerForConfig which searches for the
setting in all layers, and then calls Config::Layer::Get
which searches for the same setting again within the given
layer. We can remove this second search by combining the
logic of Config::GetActiveLayerForConfig and
Config::Layer::Get into one function.
Unfortunately, {fmt} allows passing too many arguments to a format call
without raising any runtime or compile-time error [1].
As this is a common source of bugs since we started migrating to {fmt},
this commit adds some custom logic to validate the number of
replacement fields in format strings in addition to {fmt}'s own checks.
[1] https://github.com/fmtlib/fmt/issues/492
Adds an interface that uses fmt under the hood, which is much more
flexible than printf, particularly for localization purposes, given fmt
supports positional formatters in a cross-platform manner out of the box
with no configuration necessary.
Noticed missing include as a build failure on gcc-11:
```
[ 15%] Building CXX object Source/Core/Common/CMakeFiles/common.dir/Config/Config.cpp.o
Source/Core/Common/Config/Config.cpp:23:24:
error: 'unique_lock' in namespace 'std' does not name a template type
23 | using WriteLock = std::unique_lock<std::shared_mutex>;
| ^~~~~~~~~~~
Source/Core/Common/Config/Config.cpp:11:1:
note: 'std::unique_lock' is defined in header '<mutex>';
did you forget to '#include <mutex>'?
```
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Much of these classes are operating on integral types and are pretty
standard behavior as far as vectors go. Some member functions can be
made constexpr to make them more flexible and allow them to be used in
constexpr contexts.
Provides a basic extension to the interface to begin migration off of
the printf-based logging system.
Everything will go through macros with the same style naming as the old
logging system, except the macros will have the _FMT suffix, while the
migration is in process.
This allows for peacemeal migration over time instead of pulling
everything out and replacing it all in a single pull request, which
makes for much easier reviewing.
Common shouldn't be depending on APIs in Core (in this, case depending
on the PowerPC namespace). Because of the poor separation here, this
moves OSThread functionality into core, so that it resolves the implicit
dependency on core.
CommandLineParse expects UTF-8 strings. (QApplication, on the
other hand, seems to be designed so that you can pass in the
char** argv untouched on Windows and get proper Unicode handling.)
Fixes a critical regression where 95945a0 made us unable to
start emulation on Android 10 and newer. Android is restricting
direct access to /dev/ashmem starting with the new SDK version,
but we can use the new (and simpler) ASharedMemory API instead.
We have to keep using the /dev/ashmem approach on old versions
of Android, though.
The functions with "UTF" in the name use "modified UTF-8" rather
than the standard UTF-8 which Dolphin uses, at least according
to Oracle's documentation, so it is incorrect for us to use them.
This change fixes the problem by converting between UTF-8 and
UTF-16 manually instead of letting JNI do it for us.
This function does *not* always convert from UTF-16. It converts
from UTF-16 on Windows and UTF-32 on other operating systems.
Also renaming UTF8ToUTF16 for consistency, even though it
technically doesn't have the same problem since it only was
implemented on Windows.
Also added a IsRunning function as it was impossible to know whether it had been started or not (I will use it in later PRs but it should be there anyway)
`std::abs(x - y)` where x and y are unsigned integers fails to compile
with an "call of overloaded 'abs(unsigned int)' is ambiguous" error
on GCC, and even if it did compile, that expression still wouldn't
give the correct result since `x - y` is unsigned.
Without included header build fails on gcc-10 as:
```
[ 13%] Building CXX object Source/Core/AudioCommon/CMakeFiles/audiocommon.dir/CubebUtils.cpp.o
In file included from ../../../../Source/Core/AudioCommon/CubebUtils.cpp:13:
../../../../Source/Core/Common/StringUtil.h: In function 'bool TryParse(const string&, T*)':
../../../../Source/Core/Common/StringUtil.h:84:20: error: 'numeric_limits' is not a member of 'std'
84 | if (value < std::numeric_limits<LimitsType>::min() ||
| ^~~~~~~~~~~~~~
```
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
So far in all our uses of ScopeGuard, the type of the callable is
usually just a lambda or a function pointer, so there is no need
to rely on std::function's type erasure.
While the cost of using std::function is probably negligible, it still
causes some unnecessary overhead that can be avoided by making
ScopeGuard a templated class. Thanks to class template argument
deduction in C++17 most existing usages do not even need to be changed.
See https://godbolt.org/z/KcoPni for a comparison between
a ScopeGuard that uses std::function and one that doesn't
Add a function that safely returns whether a character is printable
i.e. whether 0x20 <= c <= 0x7e is true.
This is done in several places in our codebase and it's easy to run
into undefined behaviour if the C version defined in <cctype>
is used instead of this one, since its behaviour is undefined
if the character is not representable as an unsigned char.
This fixes MemoryViewWidget.
Due to the way the ModRM encoding works on x86, memory addressing
combinations involving RBP or R13 need an additional byte for an 8-bit
displacement of zero.
However, this was also applied in cases where it is unnecessary,
effectively wasting a byte.
- MatR with RSP or R12
8B 44 24 00 mov eax,dword ptr [rsp]
8B 04 24 mov eax,dword ptr [rsp]
- MRegSum with base != RBP or R13
46 8D 7C 37 00 lea r15d,[rdi+r14]
46 8D 3C 37 lea r15d,[rdi+r14]
- MComplex without offset
8B 4C CA 00 mov ecx,dword ptr [rdx+rcx*8]
8B 0C CA mov ecx,dword ptr [rdx+rcx*8]
A small, nonexhaustive set of warning fixes. The DiscIO Volume change
is a workaround for a GCC bug [1] that causes returning an unengaged
std::optional to emit annoying -Wmaybe-uninitialized warnings.
This last change alone fixes pages upon pages of warnings since
Volume.h is included from several files.
-Wstringop-truncation is another irrelevant warning for us, but
unfortunately there seems to be no way to disable it without
adding ugly pragmas wherever the warning appears.
Removed conditional use of std::mutex instead of std::shared_mutex on MacOS.
Because MacOS < 10.12 did not support std::shared_mutex, a previous commit
naïvely substituted std::mutex, which does not have the same behavior.
Reverses PR #8273, which substitues std::mutex for std::shared_mutex on
macOS, and results in several bugs that seem to only affect MacOS
- https://bugs.dolphin-emu.org/issues/11919
- https://bugs.dolphin-emu.org/issues/11842
- https://bugs.dolphin-emu.org/issues/11845
This change eliminates conditional code for MacOS in the core configuration
layer code and enables the use of modern language features that are more
secure and thread-safe.
Previously the logging was a in a little bit of a disarray. Some things
were in namespaces, and other things were not.
Given this code will feature a bit of restructuring during the
transition over to fmt, this is a good time to unify it under a single
namespace and also remove functions and types from the global namespace.
Now, all functions and types are under the Common::Log namespace. The
only outliers being, of course, the preprocessor macros.
This is done by:
1) Implementing said protocol in a new controller input class CemuHookUDPServer.
2) Adding functionality in the WiimoteEmu class for pushing that motion input to the emulated Wiimote and MotionPlus.
3) Suitably modifying the UI for configuring an Emulated Wii Remote.
- Do not use a lambda for std::thread as invoke constructor exists
- Use simpler std::lock_guard wherever possible
- Do not require T to be default constructible
- Move T out of the queue instead of copying
- Fixed a bug where pushing items over queue's size left it in a corrupted state
- For non-trivial types, have clear() and pop() run destructors
- Added emplace(args...)
- Added empty()
FixedSizeQueue has semantics of a circular buffer,
so pushing items continuously is expected to keep overwriting oldest elements gracefully.
Tests have been updated to verify correctness of a previously bugged behaviour
and to verify correctness of destructing non-trivial types
API has been made stricter, layers are now managed with shared pointers,
so using them temporarily increased their reference counters.
Additionally, any s_layers map has been guarded by a read/write lock,
as concurrent write/reads to it were possible.
At its only usage point, its return value is stored into a u32, and the
default implementation returns 0xFFFFFFFF (-1), which would be an
unsigned integer. Given all of the bits are used to determine a color,
it makes slightly more sense to treat this as an unsigned value as
opposed to a signed one.
We're allowed (by the standard) to forward declare types within
std::vector, so we can replace direct includes with forward declarations
and then include the types where they're directly needed.
While we're at it, we can remove an unused inclusion of <cstring>, given
nothing in the header uses anything from it. This also revealed an
indirect inclusion, which this also resolves.
Previously u32 was being used for part of the interface and unsigned int
was being used for other parts. This makes the interface fully consistent by
using only one type.
We opt for u32 here given they communicate the same thing (for platforms
we care about where int is 32-bit), while also being less to read.
While we're at it, we can also default the constructor and destructor of
inheriting classes in their respective cpp file to prevent the
construction and destruction of non-trivial types being inlined into
other regions of code.
Previously these functions were declared without the static specifier,
giving them external linkage, which isn't really ideal.
Instead, we can place these functions up by the relevant file-scope
variables and place them inside an anonymous namespace with said variables,
giving them internal linkage.
Avoids the use of the null pointer to represent an empty string.
Instead, we can simply pass an empty string_view instance. Using
std::string_view enforces this invariant at the API level.
Due to the lack of cast here, this will actually print out the ascii
value, rather than the character itself, due to promoting to integral
values. Instead, we can eliminate the use of character operands and just
print the value itself directly, given it's equivalent behavior with
less code.
Allows these arrays to be placed within the read-only segment (and
enforces the immutability in the code itself). While we're at it, we can
make use of std::array here.
Now that the std::map less-than comparitor is capable of being used with
heterogenous lookup, we're able to convert many of the querying
functions that took std::string references over to std::string_view.
Now these functions may be used without potentially allocating a
std::string instance unnecessarily.
Previously, when performing find() operations or indexing operations on
the section map, it would need to operate on a std::string key.
This means cases like:
map.find(some_string_view)
aren't usable, which kind of sucks, especially given for most cases, we
use regular string literals to perform operations in calling code.
However, since C++14, it's possible to use heterogenous lookup to avoid
needing to construct exact key types. In otherwords, we can perform the
above or use string literals without constructing a std::string instance
around them implicitly.
We simply need to specify a member type within our comparison struct
named is_transparent, to allow std::map to perform automatic type
deduction.
We also slightly alter the algorithm to an equivalent compatible with
std::string_view (which need not be null-terminated), as strcasecmp
requires null-terminated strings.
While we're at it, we can also provide a helper function to the struct
for comparing string equality rather than only less than. This allows
removing other usages of strcasecmp in other functions, allowing for the
transition of them to std::string_view.
fmt diverges from printf in that '.' as a precision specifier may only
be used for floating-point values (makes sense, given it's indicating
precision after the decimal point).
Begins the transition to using fmt for string formatting where
applicable. Given fmt supports formatting std::string instances out of
the box, we can remove now-unnecessary calls to .c_str() and .data().
Note that this change does not touch the actual logging subsystem aside
from converting the final StringFromFormat call in the process over to
fmt::format. Given our logging system is heavily used throughout the
entire codebase, and converting that over will be quite a large change
by itself, this will be tackled near the end of the conversion process.
Avoids dragging in IniFile, EXI device and SI device headers in this header which is
quite widely used throughout the codebase.
This also uncovered a few cases where indirect inclusions were being
relied upon, which this also fixes.
Allows for both string types to be non-allocating. We can't remove the
const char* overload in this case due to the fact that pointers can
implicitly convert to bool, so if we removed the overload all const
char arrays passed in would begin executing the bool overload instead of
the string_view overload, which is definitely not what we want to occur.
Since C++17, non-member std::size() is present in the standard library
which also operates on regular C arrays. Given that, we can just replace
usages of ArraySize with that where applicable.
In many cases, we can just change the actual C array ArraySize() was
called on into a std::array and just use its .size() member function
instead.
In some other cases, we can collapse the loops they were used in, into a
ranged-for loop, eliminating the need for en explicit bounds query.
Prior to this commit, the emitter would emit a 7-byte instruction when
loading a 32-bit immediate to a 64-bit register.
0: 48 c7 c0 ff ff ff 7f mov rax,0x7fffffff
With this change, it will check if it can instead emit a load to a
32-bit register, which takes only 5 or 6 bytes.
0: b8 ff ff ff 7f mov eax,0x7fffffff
std::call_once is guaranteed to execute the given callable object
exactly once. This guarantee holds even if the function is called
concurrently from several threads.
Given that, we can replace the mutex and boolean flag with
std::call_once and a std::once_flag to perform the same behavior.
Previously, every entry pair within the map would be copied. The reason
for this is subtle.
A std::map's internal entry type is defined as:
std::pair<const Key, Value>
but the loop was declaring it as:
std::pair<Key, Value>
These two types aren't synonymous with one another and so the compiler
is required to always perform a copy.
Using structured bindings avoids this (as would plain auto or correcting
the explicit type), while also allowing the use of more appropriate
names compared to first and second.
std::function is allowed to heap allocate in order to hold any necessary
bound data in order to execute properly (e.g. lambdas with captures), so
this avoids unnecessary reallocating.
While current usages of ParseLine aren't problematic, this is still a
public function that can be used for other purposes. Essentially makes
the function handle potential external inputs a little nicer.
We can just utilize map's insert_or_assign() function and check the
return value to determine whether or not we need to insert the key into
the keys_order vector.
All supported platforms now have easy access to a compiler with C++17
support.
C++17 potentially allows for some nice cleanups and removes the need
for standard library backports (optional/variant).
See discussion at https://dolp.in/pr6264#discussion_r158134178
Different address spaces can be chosen in the memory view panel.
* Effective (or virtual): Probably the view people mostly want. Address
translation goes through MMU.
* Auxiliary: ARAM address space. Does not display anything in Wii mode.
* Physical: Physical address space. Only supports mem1 and mem2 (wii
mode) so far.
MemoryWatcher only works on Linux and affects emulation determinism due
to scheduling additional events, which causes NetPlay to desync.
Considering that this interface is a rather specialized use case, the
communication with it is kinda crappy *and* it's affecting emulation, I
think it's best to just axe it and come up with a better implementation
of the functionality.
* The high half of regOp is immediately overwritten so the value in it is irrelevant.
* MOVSD produces an unnecessary dependency on the high half of regOp.
* MOVAPS is implemented as a register rename on modern microarchitectures.
There is no reason to use MOVAPD over MOVAPS, for two reasons:
* There has never been a microarchitecture with separate single and double domains.
* MOVAPD is one byte longer than MOVAPS
This sends arbitrary packets in chunks to be reassembled at the other
end, allowing large data transfers to be speed-limited and interleaved
with other packets being sent. It also enables tracking the progress of
large data transfers.
Switch to using additional overloads of sf::Packet, so we can eliminate
some of the messy code and just use the normal syntax for
BigEndianValue.
We can't avoid helper functions with u64 due to SFML's non-standard way
of defining 64-bit integer types.
Prior to this commit, the emitter would unconditionally emit a 10-byte
instruction known as MOVABS when loading a 64-bit immediate to a
register.
0: 48 b8 ef be ad de 00 movabs rax,0xdeadbeef
7: 00 00 00
With this change, it will instead rely on the fact that on x64 writes to
32-bit registers are automatically zero extended to 64-bits, allowing
us to emit a 5 or 6-bytes instruction with the same effect for certain
immediates.
0: b8 ef be ad de mov eax,0xdeadbeef
Prior to this commit, the emitter would unconditionally emit a 10-byte
instruction known as MOVABS when loading a 64-bit immediate to a
register.
0: 48 b8 ef be ad de ff movabs rax,0xffffffffdeadbeef
7: ff ff ff
With this change, it will instead emit a 7-byte instruction when it is
possible to express the 64-bit immediate using a signed 32-bit value.
0: 48 c7 c0 ef be ad de mov rax,0xffffffffdeadbeef
The LogManager code had trouble detecting the "/Source/Core/" substring
for two reasons, neither of which seemed to happen a few years ago:
1. __FILE__ is in lowercase on MSVC
2. __FILE__ uses backslash as the directory separator on MSVC
Fixes https://bugs.dolphin-emu.org/issues/11366
Similar in nature to e28d063539 in which
this same change was applied to the x64 emitter.
There's no real requirement to make this const, and this should also
be decided by the calling code, considering we had places that would
simply cast away the const and carry on
Added an option in General config to enable/disable usage statistics. Added a popup on first open if
the user would like to engage in reporting. Clicking cancel or out of the box opts out. Only
clicking 'Ok' will enable reporting. Also added a new android specific values to report.
Type punning like this is undefined behavior. Instead, we use std::memcpy to
copy the necessary data over, which is well defined (as it treats both
the source and destination as unsigned char).
This adds the functionality of sending the host's save data (raw memory
cards, as well as GCI files and Wii saves with a matching GameID) to
all other clients. The data is compressed using LZO1X to greatly reduce
its size while keeping compression/decompression fast. Save
synchronization is enabled by default, and toggleable with a checkbox
in the NetPlay dialog.
On clicking start, if the option is enabled, game boot will be delayed
until all players have received the save data sent by the host. If any
player fails to receive it properly, boot will be cancelled to prevent
desyncs.
Previously these were required to be built into the executable so that
the JIT portion of the DSP code would build properly, as the
x86-64-specifics were tightly coupled to the DSP common code. As this is
no longer the case, this is no longer necessary.