Keep up the good work, luckily the source code is available so we can apply these kinds of improvements ourselves.
It would be very interesting to apply the same to bsnes mercury when we figure out how.
Keep up the good work, luckily the source code is available so we can apply these kinds of improvements ourselves.
It would be very interesting to apply the same to bsnes mercury when we figure out how.
They tested input lag over and over again… with higan/bsnes/snes9x standalone.
Perhaps Retroarch and GPU hard sync play a role in the results we get. I mean, perhaps something like you did was considered “not enough to bother with” on those emulators that have more input lag. (or that breaks stuff and they could say clearly what)
Because in the end… that’s working here and I’m enjoying Super Aleste with lower lag than ever before.
I tried several methods with bsnes like doing the input polling after the frame rendering but perhaps that’s completely wrong. (moved some function calls from CPU to PPU…) I mean it compiles and works but the input lag is unchanged.
I’m not an expert on this though that’s for sure! just tweaking and testing.
Does the improvement show in camera-based testing, as well? If so, there’s not really much to deny.
Despite the comments on byuu’s forum, it shouldn’t have anything to do with which scanline you’re rendering on, but if you want to test an interlaced game, R.P.M. Racing is interlaced all the time, even in menus (which is probably where you’ll need to test).
Input lag has been the only factor that caused me to step away from the RPi as an emulation platform and emulation in general. When I saw this thread pop up I created an account on these forums just to post in this thread. I compiled the Snes9x-Next core with the fix on my RPi and compiled the latest version of RetroArch with the dispmanx bilinear filtering fix and it has renewed my interest in emulation. Even being just a couple of frames it makes a huge difference to someone like me that is very sensitive to latency. Just wanted to say thanks for the work you’re doing on this matter.
[QUOTE=larskj;41476]Keep up the good work, luckily the source code is available so we can apply these kinds of improvements ourselves.
It would be very interesting to apply the same to bsnes mercury when we figure out how.[/QUOTE] Yep. I’ll see if I can have a look, but I will probably be in over my head…
[QUOTE=Tatsuya79;41479]They tested input lag over and over again… with higan/bsnes/snes9x standalone.
Perhaps Retroarch and GPU hard sync play a role in the results we get.
I mean, perhaps something like you did was considered “not enough to bother with” on those emulators that have more input lag.
(or that breaks stuff and they could say clearly what)[/quote]
Yeah, it could well be that this doesn’t apply outside of RetroArch. I never claimed I was sure that it would, so I’d expect a little less arrogance. Can’t say I’m surprised, though. I work as an engineer in electrical and software engineering and it’s not the first time I’ve run into big egos and buckets of arrogance in this world. I don’t take it personal, though. I’ll just save myself some time and stop posting over there.
[QUOTE=Tatsuya79;41479]I tried several methods with bsnes like doing the input polling after the frame rendering but perhaps that’s completely wrong. (moved some function calls from CPU to PPU…) I mean it compiles and works but the input lag is unchanged.
I’m not an expert on this though that’s for sure! just tweaking and testing.[/QUOTE] Keep looking at it! If the solution can’t be applied to bsnes, we should try to understand what differs in the implementaiton.
Yep, it does. That’s what makes the denial so bizarre…
Thanks for the tip. I’ll give it a try.
Great to hear and you’re welcome!
Just tried R.P.M racing OMG…
This game feels like it has 1s lag on any emulator anyway!
A bit unrelated but I was playing “Kat’s Run - Zen-Nihon K-Car Senshuken” a mode7 racing game (that feels like and indie game really). The sound bugs completely on snes9x, it’s OK on Next but with some graphical glitches in the demo. Bsnes is perfect.
Not the 1st time snes9x has some bugs that are worse than Next while it should be the opposite.
There’s probably more issues like this on obscure games, which make bsnes a better all-around bet.
edit: removed, doesn’t work.
I only had time to do a very quick test with the snes9x cores and… wow, what a difference! It is absolutely and definitely crystal clear to me that there’s an improvement in responsiveness. It’s really great.
Super Mario World is way more playable now: just doing quick jumps here and there feels much closer to the immediacy of real hardware and I have a CRT setup with the actual cartridge and SNES to compare. I have also perceived that, by disabling Audio Sync in Retroarch, you get even better latency, although that might be a mere placebo effect on my part.
Now, the only problem with snes9x is that, as many have noted, it has a few quirks that affect the overall result. One of these has to do with audio latency: while I can bring this value down to 30-32ms on bsnes (with the xaudio driver) with no repercussions whatsoever, on both snes9x cores this leads to very choppy audio playback forcing the user to keep a relatively high value (64ms)
Ideally we would need a WASAPI / ASIO driver on Windows to achieve exclusive bit-perfect playback and get very low audio latency, which in turn would lead to an even better sensation of responsiveness. I have already posted this on github: https://github.com/libretro/RetroArch/issues/2771
Thank you Brunnis and everyone involved! Keep up the good work, I hope bsnes can be likewise modified.
[QUOTE=Tatsuya79;41490]Think I found a way:
bsnes_mercury_balanced_libretro (Brunnis test input lag fix)
Tell me if that works for you as sometimes I get tired and I’m not sure of my eyes any more!
That’s one line change.
edit: and it’s causing issues.
Random button activation can happen or worse depending on games.[/QUOTE]
I actually had a look as well. To be honest, it doesn’t look like bsnes has exactly the same issue as snes9x. Here’s the code that exits the main loop:
if(cpu.vcounter() == 241) scheduler.exit(Scheduler::ExitReason::FrameEvent);
It suggest that bsnes actually does exit the main loop right after (or close to right after) a frame has been generated. Snes9x exited at the last line of the vblank interval. The line of code you modified suggests that bsnes polls right before a frame is generated (at V=240), before exiting:
if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) {
The polling seems to be made repeatedly, once every 256 cycles of the SNES CPU, though. The strange thing is that I haven’t been able to get any improvent OR regression by moving around the polling to different places within the frame… The fact remains, though, that bsnes reacts 1 frame slower than snes9x with my fix. Maybe bsnes actually reacts like real hardware and snes9x with my fix is “too fast”? Sounds a bit far fetched…
I’ll try to measure this somehow later on, but no, neither standalone bsnes/higan nor its libretro core appear to have the same input responsiveness as real hardware.
Okay, thanks.
And I agree. I just realized the likely reason for why the change doesn’t have any effect on bsnes. It’s one of the things that byuu alluded to in my thread over at his forum:
So, for games with 225 lines, the following might happen:
We will then have to wait until the next run of the main loop before the emulator actually runs the remaining part of the vblank interval (where game logic is run) and outputs the frame. We have introduced a full 16.67 ms delay. Snes9x with my fix doesn’t have this problem. It exits the main loop at the very moment a frame has been finished, be it at line 225 or line 240.
So, what we should try to do is to rewrite bsnes to exit the main loop at different points depending on if the game has 225 or 240 scanlines. Anyone up for the challenge?
EDIT: This is what byuu wrote:
HOWEVER, the SNES gets a bit shafted here. The SNES can run with or without overscan. And you can even toggle this setting mid-frame. So I have to output the frame at V=241,H=0. Whereas input is polled at V=225,H=256+.
I’m still not sure why we couldn’t vary the exit point dynamically, depending on game, if overscan is used or not, etc. We should at least try and see what happens.
Yeah what I did was random and not working.
Too many stuff I ignore there, can’t do much I think.
Made a pull request for Next:
Will be easier to review as I added just the new lines for clarity.
Thanks for this, it really explains a lot. Thanks specially for the modifies snes9x-next
Any chance of getting a similar tweak for Nestopia? Or is that an entirely different case?
Can’t rewrite bsnes but I can get rid of the overscan in bsnes-mercury\sfc\system\system.cpp line 285:
if(cpu.vcounter() == 241) scheduler.exit(Scheduler::ExitReason::FrameEvent);
force 225 to test it.
(I think that’s slightly faster but not as much as snes9x next)
edit: between slightly and none… …none?
Built your updated snes9x-next-libretro binary with the input lag “fix” for 32-bit Windows. I haven’t run objective tests, but I can’t discern any input lag in this snes emulator with the latest 32-bit Retroarch at default settings. I also tested in d3d mode, but have not re-read the thread to determine any effect of the fix among different video modes in Windows (sdl2, d3d, gl).
[QUOTE=Tatsuya79;41525]Made a pull request for Next:
Will be easier to review as I added just the new lines for clarity.[/QUOTE]
Great, thanks! Looks like it’s going to be committed.
[QUOTE=spinningacorn;41536]Thanks for this, it really explains a lot. Thanks specially for the modifies snes9x-next
Any chance of getting a similar tweak for Nestopia? Or is that an entirely different case?[/QUOTE]
You’re welcome! I’m planning to give Nestopia a go next week.
[QUOTE=Tatsuya79;41540]Can’t rewrite bsnes but I can get rid of the overscan in bsnes-mercury\sfc\system\system.cpp line 285:
if(cpu.vcounter() == 241) scheduler.exit(Scheduler::ExitReason::FrameEvent);
force 225 to test it.
(I think that’s slightly faster but not as much as snes9x next)
edit: between slightly and none… …none?[/QUOTE] Actually, you’re almost there. I just looked some more at the code and finally managed to achieve the same 1 frame reduction in input lag. Here’s how:
bsnes-mercury\sfc\system\system.cpp line 285:
if(cpu.vcounter() == 226) scheduler.exit(Scheduler::ExitReason::FrameEvent);
bsnes-mercury\sfc\cpu iming\joypad.cpp line 5:
if(vcounter() >= (ppu.overscan() == false ? 227 : 242)) {
This hack makes it so that the frame is always output after line 225. The emulator loop then exits. The next time the main loop is called, it enters at line 227 and proceeds to poll input and finally render the frame. The reason it didn’t work for you is that the emulator has already polled just before exiting the loop. Give this a try and see what you think.
Important: This is just a hack! Always outputting the frame at line 226 will not work in all cases, since some games have 240 lines. The interesting thing here is that snes9x seems to handle this by determining if the game renders 225 or 240 scanlines and outputs the frame as soon as it’s ready. That’s what made the fix so easy to implement on snes9x, i.e. it already output the frame at the correct place, we just needed to make sure it also left the main loop right after that point.
So, the question is: why doesn’t bsnes detect this in the same way? As it is now, it’s hard coded to exit at line 241 and output the frame. Maybe this has something to do with how overscan needs to be handled for maximum accuracy and snes9x foregoes such accuracy? Then again, byuu actually uses a check for overscan in the polling code (see second code block above)… Why not just add the following code to the first code block above and be done with it:
if(cpu.vcounter() == (ppu.overscan() == false ? 226 : 241)) scheduler.exit(Scheduler::ExitReason::FrameEvent);
I could see this as having a side effect if the game changes the overscan value between line 226 and 241. Then we’d get another main loop exit when we reach line 241, which is not what we want. I don’t know if that can happen, though. I’ll compile it anyway and give it a go. Any particular games you recommend to test the 225 vs 240 scanline handling?
Good to hear. The fix will be equally effective, regardless of video mode.
Nice gonna test that!
edit: Yes that’s obviously better! Nice work! Gonna use this as I use crop overscan anyway for the SNES (if I remember right there’s rarely interesting stuff there unlike on the Pc-Engine).
Did you measure the input lag against snes9X or Next?
[QUOTE=Brunnis;41566] So, the question is: why doesn’t bsnes detect this in the same way?[/QUOTE] Blind guess: this is how the real SNES works. I can understand that as that’s what made bsnes so accurate.
[QUOTE=Tatsuya79;41568]Nice gonna test that!
edit: Yes that’s obviously better! Nice work! Gonna use this as I use crop overscan anyway for the SNES (if I remember right there’s rarely interesting stuff there unlike on the Pc-Engine). [/QUOTE]
Would it be possible to have a DLL of Bsnes-mercury-balanced modified with this new code? Unfortunately I don’t have the means to compile it myself right now.
Thanks in advance, much appreciated.
[QUOTE=Geomancer;41569]Would it be possible to have a DLL of Bsnes-mercury-balanced modified with this new code? [/QUOTE]
Here it is:
edit: updated in a further post.