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:
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:
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.
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.
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.
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:
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.
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.
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.