libretro / snes9x2010

Snes9x 2010. Port of Snes9x 1.52+ to Libretro (previously called SNES9x Next). Rewritten in C and several optimizations and speedhacks.
Other
99 stars 71 forks source link

One unnecessary frame of input lag is added to all games #74

Closed Brunnis closed 8 years ago

Brunnis commented 8 years ago

Due to how the main emulator loop is written, there will currently (in the ideal case, with no game induced lag) always be two frames of lag until the emulator can produce a frame corresponding to a certain input. This is due to the fact that each call to the main loop starts at V=0, by rendering what was calculated in the previous frame. After the frame has been produced, the emulator reads input and runs additional logic in the vertical blanking interval (at least this is how I've interpreted it).

If the emulator main loop instead was to start right before reading the input and run until right after a frame has been generated, we'd be able to read the input and generate the corresponding frame in the same call to the main loop, i.e. we'd shave off a whole frame of lag.

Here's a simple sketch I made:

input-fix-sketch-s

I have already tested this theory by making a few crude changes to the main loop. It took less than 20 lines of code in cpuexec.c. Here is a link to the modified source code file:

http://pastebin.com/5TfgnzLG

Below are some test results with the new code (taken from this post: http://libretro.com/forums/showthread.php?t=5428&p=41376&viewfull=1#post41376):

The chart below compares the unmodified snes9x-next and bsnes-mercury-balanced cores (the first six bars) to the snes9x-next core with my fix. The test was made with an LED rigged controller and 240 FPS camera. snes-input-lag-yoshis-island-fix

I also tested the new core using the frame advance method (i.e. pausing emulation, applying input and advancing frame-by-frame). Test result for the newly compiled core is to the right. emulator-input-lag-fix

Please see this post for a detailed description of the test methodology: http://libretro.com/forums/showthread.php?t=5428&p=36549&viewfull=1#post36549

I have not found any issues with my changes yet. However, I don't have any previous experience with this code or emulators in general, so I can't vouch for it. That's where I hope some of the more experienced developers may chime in. If the changes make sense, I don't see why they shouldn't make it into the master branch. Wasting a whole frame for nothing seems, well, wasteful. I realize the code I wrote isn't the nicest looking, so please feel free to rewrite it into something more fit to be committed to the master.