FCare / Kronos

Kronos is a Sega Saturn emulator.
http://fcare.github.io
235 stars 23 forks source link

Input lag discussion #375

Closed Tatsuya79 closed 1 year ago

Tatsuya79 commented 5 years ago

I wanted to link that commit made by Retrowertz in VBAM to go through layers and get the fastest response for controls. Perhaps that can help finding a way for Kronos?

https://github.com/libretro/vbam-libretro/commit/3031dc53aa5799db40c5207de09160fc3960bf7f

FCare commented 5 years ago

On saturn, the gamepad input is updated using a dedicated intback spcm command. This is happening at VBlank-in, which is executed at the end of the frame.

We are doing like this currently in the loop:

This means that if you press the gamepad during the frame, it is taken into account at next frame. I think the issue is coming from here

I tried

But it does not look to save any frame on the libretro port.

On the standalone Qt version, we are using the Qt input mechanism which is based on events, so once the spcm is retrieving the gamepad status, we are sure to have the up-to-date status.

The issue is that on the standalone version, we do not have a way to do a frame by frame step, so it is complicated to test and compare.

Le ven. 30 nov. 2018 à 14:46, Tatsuya79 notifications@github.com a écrit :

I wanted to link that commit made by Retrowertz in VBAM to go through layers and get the fastest response for controls. Perhaps that can help finding a way for Kronos?

libretro/vbam-libretro@3031dc5 https://github.com/libretro/vbam-libretro/commit/3031dc53aa5799db40c5207de09160fc3960bf7f

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/FCare/Kronos/issues/375, or mute the thread https://github.com/notifications/unsubscribe-auth/ANl7CNU0R6gQ8gsim9EHn4zX2XH1LhrSks5u0Ta-gaJpZM4Y7svI .

barbudreadmon commented 5 years ago

I tried Simulate the frame Update gamepad control = > State1 At VBlank, spcm udpate the gamepad control (We retrun the state1)

If that's what is done when executing YabauseExec() and if Update gamepad control = > State1 means execute HandleEvents from percore, the libretro port shouldn't add any extra input lag i think.

Btw, i noticed beetle-saturn is executing 2 smpc functions at 2 different timings in its vdp2 code :

Tatsuya79 commented 5 years ago

To test the QT version input lag you can record a video, launch a game with Kronos, pause from the emulator, push down a direction, unpause. You can then count the frames in the video player with frame steps.

I wanted to do that but as soon as I launch OBS here on win7 x64, Kronos slows down and the sync seems lost.

FCare commented 5 years ago

on qt the handleEvent is doing nothing except launching the yabauseExec. PORTDATA1 and PORTDATA2 are updated on event based.

Le ven. 30 nov. 2018 à 16:31, Tatsuya79 notifications@github.com a écrit :

To test the QT version input lag you can record a video, launch a game with Kronos, pause from the emulator, push down a direction, unpause. You can then count the frames in the video player with frame steps.

I wanted to do that but as soon as I launch OBS here on win7 x64, Kronos slows down and the sync seems lost.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/FCare/Kronos/issues/375#issuecomment-443238054, or mute the thread https://github.com/notifications/unsubscribe-auth/ANl7CAF310pdvrGOGom-IvXMzY5ZpATTks5u0U8_gaJpZM4Y7svI .

barbudreadmon commented 5 years ago

on qt the handleEvent is doing nothing except launching the yabauseExec.

Actually it's doing nothing at all since https://github.com/FCare/Kronos/commit/49d773c08640826c160ba0684ef8e64f8c6b018c ;)

So i tried adding some printf :

smpc : INTBACK Start Read SMPC[0x21] = 0xf1 Read SMPC[0x23] = 0x2 Read SMPC[0x25] = 0xf7 Read SMPC[0x27] = 0xff Read SMPC[0x29] = 0xf1 Read SMPC[0x2b] = 0x2 Read SMPC[0x2d] = 0xff Read SMPC[0x2f] = 0xff Read SMPC[0x31] = 0x0 Read SMPC[0x33] = 0xc Read SMPC[0x35] = 0x74 Read SMPC[0x37] = 0x0 Read SMPC[0x39] = 0x0 Read SMPC[0x3b] = 0x0 Read SMPC[0x3d] = 0x0 Read SMPC[0x3f] = 0x0 Read SMPC[0x61] = 0x80 Frame rendered Read SMPC[0x63] 0x0 Write SMPC[0x63] = 0x1 Write SMPC[0x1] = 0x1 Write SMPC[0x3] = 0x8 Write SMPC[0x5] = 0xf0 Write SMPC[0x1f] = 0x10 smpc : INTBACK

I enabled SMPCLOG, so Start is when i pressed start, and i also added a printf("Frame rendered\n") at the end of YuiSwapBuffers. Correct me if i'm wrong, Read SMPC is when it's reading from the SMPC bus, and Write SMPC is when it's writing to the SMPC bus (so when it's sending the input state ?), if i'm not wrong, this output shows than the input state is sent to SMPC after the frame is rendered, which could explain this 1 frame lag ?

FCare commented 5 years ago

Yes, but the game looks to be done like this. 1: The vdp1 drawing frame, aka 0, rendering is required in the first lines of a frame (drawcommands execution) 2: SMPC intback is required just after until some time before VBlankin. (line 4 to line 207 => generate the sampling of the pad. Line 4 is generated by the game) 3: At Vblankin, the VDP2 starts to render with the vdp1 readframe, aka 1. (the game did not requested yet a vdp1 framechange) 4: During the Vblank time (between in and out), vdp1 command table is updated and vdp1 frame is changed (frame 0 become frame 1 and frame 1 become frame 0). 5: And it loops.

This means that there is one frame delay between read SMPC and effective vdp2 framebuffer change. I tried to optimize by swapping the vdp1 frame before the vdp2 rendering (which use vdp1 readframe as input) but it generates some regression on Alone in the Dark.

I am stuck there and all looks ok in terms of timing so I will just keep this discussion in background.