Beetle PSX Dynarec Update – Switch alpha port plus runahead support – lower latency than original hardware!


As an addendum to our earlier Beetle PSX dynarec post, a lot has changed in a couple of days:

  • Several important bugfixes have been pushed for ARM v7/AArch64. This should benefit Android users and ARM Linux SBC users.
  • Runahead support is finally working
  • Alpha release Switch version now available

Runahead support – lower latency than original hardware

Runahead is one of RetroArch’s crowning features as a frontend ever since we debuted this revolutionary feature in 2018.

Most systems more complex than the Atari 2600 will display a reaction to input after one or two frames have already been shown. For example, Super Mario Bros on the NES always has one frame of input latency on real hardware. Super Mario World on SNES has two frames of latency.

Runahead allows RetroArch to “remove” this baked-in latency by running multiple instances of a core simultaneously, and quickly emulating multiple frames at a time if input changes. This strategy has some analogs to frame rollback, similar to how GGPO handles high-lag connections. For it to work reliably, you need to figure out the amount of lag frames a game has, and then set Runahead frame count to that value. When done correctly, not only can you eliminate any perceptible lag, you can actually achieve latency that is quantifiably lower than when played on the original hardware [yes, with a CRT]. Surely that is the stuff of miracles on display technologies that have inherent far higher latency than any CRT screen, plus all the added additional latency of modern day PC OSes on top of the typical overhead brought about by emulators.

So up until now, runahead was not possible on Beetle PSX. Why not? For one, runahead relies on savestates. If serialization and savestates are well implemented, runahead can be used on a libretro core. Second, for runahead to run at fullspeed at any amount of frames, your hardware has to meet the demands of running a game at well above fullspeed. So the lower the FPS, the less conducive that core will be for runahead purposes even IF savestates are well implemented.

A couple of days ago, runahead would not work with the dynarec. This required some modifications. Zach Cook has since managed to fix these issues, and now we can use runahead just fine.

How to use it

First, make sure that you set Hardware Renderer to ‘Software’. Unless you are using a very high end CPU from the last two years, we recommend you leave Internal GPU Resolution at 1x. Combining the dynarec with runahead is a very CPU intensive task. You need all the headroom you can get.

To tinker with runahead settings, go to Quick Menu -> Latency.

Enable ‘Run-Ahead To Reduce Latency’, and set ‘Number of Frames To Run Ahead’ to a value of your choosing. For runahead to run as intended, this value shold match the amount of lag frames of the game.

NOTE: ‘Runahead Use Second Instance’ can give a big performance improvement. Consider always enabling it unless you have reason not to (for instance, some game related issue requires you disable it for whatever reason)

Alpha Switch version available

m4xw has done a quick port of Beetle PSX with the dynarec to the Switch port. He has already uploaded a build that you can try – you’ll have to pass the time with this core until we start deploying this on the buildbot properly.

To use this, extract the contents of this archive into /retroarch/cores/ (assuming RetroArch is already installed).

Performance has dramatically improved over interpreter before – just as an indication, Pepsi Man reportedly runs at fullspeed at 2x software rendering. But be sure to put this build through its paces yourself!