Input Lag Compensation to compensate for game's internal lag?



hmm, i’m not so sure trying to document what value to use for each game is such a good idea. not only is what value works best going to be somewhat subjective, it would also need to be defined per emulator core as certain factors, such as when vblank is emulated in the frame slice, can cause it to vary between cores. and while the latter isn’t so much of an issue anymore, thanks to the efforts of people like Brunnis and the libretro maintainers who reorganized many of the emulator cores to address this, i imagine there are other factors, like perhaps differences in timings that, while not likely, could potentially also affect the results.


Not to mention, display latency.

Some displays are laggier than others, so some people may use bigger RunAhead values for those laggier displays. Also, if you enable interpolation on your television, RunAhead can also compensate for interpolation lag. Also, people using low-Hz (125Hz) cordless USB gamepads, combined with a laggier display, may sometimes choose 1 or 2 extra RunAhead frame over people using wired 1000Hz gamepads.

So there are external latency-varying factors, and RunAhead is capable of “compensating” for these external latency causes – RunAhead techniques is one of the only ways to successfully do so.

So there will always be reasons (e.g. display lag, enabling Sony Motionflow, etc) to increase RunAhead counts on a system-by-system basis.

At least for situations where backticking artifacts from larger-RunAhead isn’t a problem.


One other issue with Mednafen PSX is that its savestates are saving and restoring data chunks of size 4 (one word large), with the full name of the variable (bigger than 4 bytes large) specified as the chunk name.

Then the code which seeks through the names to find the correct name has a N^2 complexity, so it’s basically checking 932 chunks against 932 names, getting slow as it is closer to the bottom of the savestate.


Can’t thank you enough for looking into this. I would be overjoyed to actually be able to use Runahead with the software renderer of Beetle PSX.

Do you think the savestate system in this core can be feasibly made faster?


I just got the savestates performing much better. When it does a Fast Savestate, it excludes all text labels from every variable now. I also fixed the N^2 complexity bug.


  • Saving State: 1.787 frames worth of time
  • Loading State: 0.667 frames worth of time


  • Loading State: 0.186 frames worth of time
  • Saving State: 0.144 frames worth of time

(edited post, changed units to make it more clear)


In terms of what it does in a frame (just at the title screen and menu of Dragon Warrior 7), some rough estimates of performance:

  • Sound: 13.94%
  • Cpu: 47.03%
  • Video: 33.23%

Now the hard part is eliminating Sound and Video, and enabling the JIT for CPU. Yes, that will be hard to do.

edit: submitted pull request for the savestate fixes, and was accepted. This should show up in nightlies soon.


Display lag, controller, and smooth motion should have no effect on results derived from the pause + “k” frame advance.


Snes9x needed a patch called “lagfix” to make the snes9x core have one less frame of input lag, so yes, the selected core can indeed add lag.


Some cores that exhibit an additional frame of lag compared to their stand-alone versions or other faster cores are: all Mame cores, VBAM (next is fine), Picodrive.

Also new higan/nside because how vsync works vs stand-alone method.


silentq15 started documenting some here:


That’s correct, such things have no impact on the game’s internal lag, but they do impact your system’s lag, which is stacked on top of the internal lag.

His point is that you can reduce the game’s internal lag to compensate for your system’s lag, so that the total lag is as close to the original hardware as possible.


That’s quite true! The ability to adjust towards that ballpark (fathful lag reproduction). Others users want less lag than original hardware, and maximize RunAhead (lag advantage). A user preference.

@Dwedit, 10 times faster savestates? – That’s a very impressive coding optimization job!


Hey @Dwedit, I have just tested the updated Beetle PSX core and the improvements are absolutely noticeable! I can now use Secondary Instance smoothly on my system with Hard GPU Sync ON with most content, provided that I keep Frame Delay at 0 and Audio Latency at 64ms.

Symphony of the Night has never been this responsive and, given that it’s one of my favourite titles of all times, this is really exciting. :slight_smile: Hopefully you can manage to eliminate Sound and Video like you said, so it can get even faster in the future.

I imagine also that, when and if a dynarec is created for this core, the improvements will be once again massive.


@Tatsuya79 try this is you have the time and see if input response is better…


Not sure if this has been mentioned, but I came across a funny glitch while testing this on RPI3 using lr-fbalpha and SF2HF (Street Fighter 2 Turbo: Hyper Fighting). With 1 lookahead, the opponent will occasionally switch to your character for several frames. Didn’t try with other settings.

SF2HF is known to be problematic in terms of speed on some emulators due to inaccurate 68k wait state emulation.


Runahead feature is not responsible for savestate bugs in the cores themselves. :slight_smile:

Does using the secondary core feature change the results?


In an older post I said I got no picture with Beetle PSX HW, but I was wrong : it’s only the hardware renderer that does not work ; the core runs fine with runahead on software mode.


I haven’t tried running a secondary core for this game. This feature is quite resource intensive on the Pi. I’ll give a go later.


It crashes at launch. It’s for win x64?



thats strange… file works fine here. im modifying it for gba atm

EDIT: here’s another version, that does the same thing but with less modification. note: this is not a final version, only tested on super mario advance 4, if it still crashes then i dunno why since it works in new released 1.7.2


It’s working fine now and it reacts in 2 frames, good work!

I had to kill
input_libretro_device_p3 = “0”
input_libretro_device_p16 = “0”
that were in my retroarch.cfg.

If only they could never come back again…
I cleaned that already for a problem like that.