* Fixed a bug where frames are still duped when the frontend is
fast-forwarding
* Fixed a bug where manual frame duping (without
`RETRO_ENVIRONMENT_GET_CAN_DUPE`) causes screen flickering during a
`Graphics.transition` call
Apparently we're not supposed to use
`RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO` to change the FPS. The core
should be running at the display refresh rate and resampling the game's
video output.
When not using the threaded audio driver, the frontend is supposed to
block until enough audio samples have been rendered for one frame, so
the frontend throttles the frame rate automatically if the core's frame
rate is slower than the display frame rate.
However, when using the threaded audio driver, there's no more
throttling, so we have to do it ourselves.
This adds a new driver for audio in libretro builds for devices with
multithreading support that defers audio rendering to a worker thread
provided by the libretro frontend.
The threaded driver has the advantage that video lag will not also cause
the audio to lag, which is very noticeable since it manifests in the
form of audio crackling when it happens.
This fixes a number of issues with the audio in libretro builds, such as
a problem where the ME stream resumes from its previous position when
played instead of starting from the beginning.
The copy constructors are causing problems when the `fiber.stack` vector
gets reallocated when its capacity is full, since when vectors are
reallocated, the elements are moved (or copied if there's no usable move
constructor) to the reallocated memory and then the original elements
are destroyed.
This premature calling of destructors leads to double-free and
use-after-free errors.
I fixed it by deleting the copy constructors and explicitly defining
move constructors.
Not sure why, but this fixes crashes when calling variadic functions in
the Ruby API in libretro builds when Ruby is built without `-DNDEBUG`.
Maybe the previous way of calling varargs functions was undefined
behaviour somehow.
`rb_rescue` only catches `StandardError`s, which doesn't include things
like Ruby syntax errors that we'd like to catch. We need to explicitly
use `rb_rescue2` to catch `Exception` in order to catch everything.