The libretro buildbot uses Xenial for its GNU/Linux images, but with GCC
9 instead of the default GCC 5 that's available in the Xenial
repositories. I've changed our libretro autobuilds to do the same.
Pinning an old distribution for the libretro GNU/Linux autobuilds allows
for compatibility with devices with old versions of glibc, like some
Linux-based handheld console OSes.
The libretro Emscripten build really doesn't like exceptions, and
neither does the PlayStation 4 homebrew toolchain. I'll have to get rid
of all exceptions elsewhere as well.
In big-endian libretro builds, the WebAssembly memory is reversed, so no
byte-swapping is required to read from/write to WebAssembly memory
(which is little-endian).
However, that means the ways to get and set values in WebAssembly memory
are endianness-dependent, so I've added the correct such ways for
big-endian platforms.
In C, variables defined as `const` have external linkage.
In C++, variables defined as `const` have internal linkage, and we need
to define them as `extern const` for them to have external linkage like
in C.
However, in C, defining a variable as `extern const` throws a compiler
error, so we need to add `extern` only for C++ files.
* BGM track streams should be locked while `extPaused` is being modified
* All BGM track streams should be locked in the `BgmFadingOut` phase
since we need to query the states of all tracks in the middle of the
loop
* BGM tracks should have `extPaused` set to false if the ME ends in the
middle of the `BgmFadingOut` phase
The binding coroutines in libretro builds are constructed on the VM
stack, so reallocating the VM memory would corrupt the memory of any
currently existing coroutines.
I've changed it so that the coroutines are no longer constructed on the
VM stack so that they're unaffected by VM memory reallocations, and
added a "slot" mechanism for storing variables on the VM stack. (Any
Ruby `VALUE`s used by a coroutine have to be stored on the VM stack so
that the Ruby garbage collector doesn't free them while they're being
used, which is why the slot mechanism is necessary.)
Before, if the game tried to create a save file, missing parent
directories would always be created because they could possibly exist
only in the game directory and not in the save directory, and we
wouldn't know due to the union mounting of the save and game
directories. But this is inconsistent with the behaviour of file
creation, where it should fail if parent directories don't exist.
The behaviour has been changed to only create parent directories if the
parent directories already exist. I know that sounds strange, but if the
parent directories exist, it could be that they only exist in the game
directory but not the save directory due to the union mounting, so we
need to create the parent directories, which will be created in the save
directory due to it being set as the write directory in PhysFS.