If there are two Ruby objects, A and B, that are both no longer used
(i.e. they're able to be freed by the Ruby garbage collector), and A
references B, then it's possible for the Ruby garbage collector to free
B but not also free A in the same garbage collection cycle.
The pointer unswizzling algorithm currently crashes when the garbage
collector does this because the object A will still be in
`sb()->objects` but B will not be, and so save state serialization will
still try to serialize A. When the pointer unswizzling algorithm tries
to serialize all the other objects A references and cannot find the
referenced object B, the program crashes.
Libretro provides a way to detect when the OpenGL context is destroyed,
like on Android and possibly also iOS when switching between apps. This
commit implements reinitializing all OpenGL objects when this happens so
that the graphics continue to function in this case.
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.
Any relative paths that the game tries to access in libretro builds will
now be relative to whatever is the current working directory in the Ruby
sandbox, which will also now be initialized to the game directory during
initialization. Before, all of the bindings that took paths were
hardcoded to prepend the path with the game directory.
I'd already removed the SDL static libraries from libretro builds for
portability, but kept the headers to make it easier to port the codebase
to libretro. Eventually it was time to stop using the SDL headers as a
crutch.
Since I got rid of SDL in libretro builds, I can't use SDL_ttf, so I
have to implement text rendering somewhat more manually. I'm still
getting the hang of it.