• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

Completed Game Engine Lag Display/Debugging

Fizzi

Smash Ace
Joined
Feb 14, 2008
Messages
802
Location
Brooklyn, NY
Slippi.gg
FIZZI#36
Intro

Console gameplay is returning after a long quarantine. There has been a lot of discussions about monitors and lag reduction codes to compensate for monitor lag. This code is designed to display game-side latency information on screen. The reason I wrote this code is the following:

Screenshot

Dolphin_Ar7ZCzbbm8.png


Video


This video was recorded under vanilla conditions. This means that polling drift was present. You can visibly see it as POLL-FETCH drifts every frame and the total game lag changes throughout the game, eventually stabilizing and cycling between 3 different values.

Details

Here is how the code works:
  1. A polling callback is registered at the start of a game. This callback fires after the console hardware polls the controllers and writes the pad information to memory (this happens twice per frame in vanilla)
  2. At the point where polling callbacks are about to fire, we store the current time to use as a reference time in the following steps
  3. The game reads polled inputs once per frame to use for gameplay logic. When this happens, we store the latest poll time and map it to a key that can be referenced in order to link together the lifecycle of this input all the way to the frame being scanned out (displayed). We write this key to player 1's inputs in the form of d-pad inputs (0-15).
  4. The game engine eventually picks up on the player inputs and acts on them (making character's move, etc). At the start of this happening, we extract the key from the d-pad inputs and forward the key to the frame by drawing a specific shade of gray to the top left of the screen. We also clear the d-pad inputs before the game uses them (to prevent taunting)
  5. The game will at some point have the GPU render the frame and write it to memory. (I'm simplifying this a bit)
  6. When preparing to draw a new frame on screen, the game points the hardware to where the frame data is stored. At this point (right before the frame is drawn to the screen), we extract the color of the top-left pixels of the frame, grab the key, load the reference time, and compare it to the current time. This gives us the total time spent between the hardware polling the controllers to the game preparing to draw the corresponding frame on screen (total game lag).
  7. Next frame, we draw the most recent results.
Hopefully that made some sense. Given all this, there are a few things to note:
  • This DOES NOT describe total lag experienced by the player
    • A player can press a button up to 8.3 ms (half a frame) before the controller state is polled
    • Only one poll is used per fetch, so there is always a worst case +16.7 ms of additional lag from when a button is physically pressed
    • Monitor/screen latency is not included. A monitor will add additional latency that is not "game side"
  • Because of the previous point, this code is only really suitable for testing different lag reduction codes or seeing how the game performs in terms of latency under different load conditions.
  • The code does not work on Ishiiruka (which includes Slippi Dolphin), the polling callbacks do not seem to work correctly there.
  • This code DOES work in mainline Dolphin as long as you uncheck Store XFB Copies to Texture Only under Graphics -> Hacks. That said, it may not be representative of true lag given that Dolphin's rendering strategy is different than console's.
Anyway I hope people find this useful and that it makes development and QA for lag reduction codes simpler.

Source


Code (Last updated 9/14/2023)

Code:
$Debug Game-Side Latency (v3) [Fizzi]
*Shows latency information on screen while in-game
C216E774 00000093 #External/Debug Inputs/InitOnGameStart.asm
48000410 4E800021
00000000 43480000
41C80000 000000FF
000000B4 E2E2E2FF
41200000 41880000
546F7461 6C204761
6D65204C 61673A20
25752075 730A0A00
506F6C6C 20436F75
6E743A20 25750A00
4D696E20 506F6C6C
20446966 663A2025
75207573 0A004D61
7820506F 6C6C2044
6966663A 20257520
75730A00 46657463
682D4665 7463683A
20257520 75730A00
506F6C6C 2D466574
63683A20 25752075
730A0050 6F6C6C2D
456E6769 6E653A20
25752075 730A0000
4E800021 4E800020
4E800021 7C0802A6
90010004 9421FF20
BE8100B0 4BFFFF31
7FE802A6 83DF0000
83BE0006 887E0000
2C030001 40820128
7FA3EB78 3D808030
618C2BB0 7D8903A6
4E800421 7FA3EB78
38800000 38A00000
3D808030 618C2A3C
7D8903A6 4E800421
7FA3EB78 389F0020
80BE0056 3D808030
618C2D4C 7D8903A6
4E800421 7FA3EB78
389F0038 80BE006E
3D808030 618C2D4C
7D8903A6 4E800421
7FA3EB78 389F0048
80BE005A 3D808030
618C2D4C 7D8903A6
4E800421 7FA3EB78
389F005E 80BE005E
3D808030 618C2D4C
7D8903A6 4E800421
7FA3EB78 389F0074
80BE0062 3D808030
618C2D4C 7D8903A6
4E800421 7FA3EB78
389F0088 80BE0066
3D808030 618C2D4C
7D8903A6 4E800421
7FA3EB78 389F009B
80BE006A 3D808030
618C2D4C 7D8903A6
4E800421 3C608046
6063B6A0 88630008
2C030000 41820020
807E0012 3D808034
618C9CBC 7D8903A6
4E800421 38600002
987E0000 BA8100B0
800100E4 382100E0
7C0803A6 4E800020
7C0802A6 90010004
9421FF20 BE8100B0
4BFFFDCD 7FE802A6
38600020 3D808037
618CF1E4 7D8903A6
4E800421 7C681B78
3860001E 3880FF2E
38A0FFD8 38C00001
38E00001 3D808030
618C2834 7D8903A6
4E800421 7C7E1B78
806DB77C 7FC4F378
3D808030 618C2810
7D8903A6 4E800421
38600000 987E0026
7FC3F378 389F000C
3D808030 618C2B90
7D8903A6 4E800421
C03F0004 D03E0008
C03F0008 D03E000C
807F0000 93C30002
BA8100B0 800100E4
382100E0 7C0803A6
4E800020 7C0802A6
90010004 9421FF20
BE8100B0 4BFFFD11
7FE802A6 386003E8
3D808037 618CF1E4
7D8903A6 4E800421
7C681B78 3860001F
38800000 38A00000
38C0001D 38E00009
3D808030 618C2834
7D8903A6 4E800421
7C7E1B78 806DB77C
7FC4F378 3D808030
618C2810 7D8903A6
4E800421 38600000
987E0026 7FC3F378
389F0010 3D808030
618C2B90 7D8903A6
4E800421 7FC3F378
C03F0018 C05F001C
3D808030 618C2B10
7D8903A6 4E800421
7FC3F378 389F0014
3D808030 618C2B64
7D8903A6 4E800421
7FC3F378 3D808030
618C2AF0 7D8903A6
4E800421 807F0000
93C30006 38600013
38800014 38A00000
3D808039 618C01F0
7D8903A6 4E800421
4BFFFCE1 7C8802A6
38A00007 3D808038
618CFD54 7D8903A6
4E800421 BA8100B0
800100E4 382100E0
7C0803A6 4E800020
7C0802A6 90010004
9421FF20 BE8100B0
38600072 3D808037
618CF1E4 7D8903A6
4E800421 4BFFFBD1
7C8802A6 90640000
7C7E1B78 38800072
3D808000 618CC160
7D8903A6 4E800421
4BFFFDD1 4BFFFE89
4BFFFC59 7C6802A6
907E0012 3D808034
618C9BF0 7D8903A6
4E800421 BA8100B0
800100E4 382100E0
7C0803A6 C022A8C8
60000000 00000000
C21A4DEC 00000027 #External/Debug Inputs/LogEngineTime.asm
3C608048 80639D30
5463443E 2C030202
4082011C 3C608048
80639D60 2C030000
4081010C 7C0802A6
90010004 9421FF20
BE8100B0 3D808034
618C7364 7D8903A6
4E800421 7C7E1B78
3C608016 6063E774
80830000 5485302E
38800040 7C8523D6
7C632214 83E30008
887F0000 2C030000
41820098 3C80804C
60841FAC 80640000
547C073E 54630036
90640000 3D808034
618CC408 7D8903A6
4E800421 1C9C0004
38840016 7C9F202E
7C641850 1C63000C
3C808000 608400FC
80840000 38A003E8
7C842B96 7C842B96
7C632396 7C7D1B78
93BF006A 807F0002
9B810008 9B810009
9B81000A 80810008
54842026 608400FF
90810008 38810008
3D808030 618C2B90
7D8903A6 4E800421
7FC3F378 3D808034
618C738C 7D8903A6
4E800421 BA8100B0
800100E4 382100E0
7C0803A6 800D9368
60000000 00000000
C2376A88 0000002C #External/Debug Inputs/LogFetchTime.asm
3C608048 80639D30
5463443E 2C030202
40820148 3C608047
60639D64 80630000
2C030000 40820134
7C0802A6 90010004
9421FF20 BE8100B0
3D808034 618C7364
7D8903A6 4E800421
7C7E1B78 3C608016
6063E774 80830000
5485302E 38800040
7C8523D6 7C632214
83E30008 8061010C
54638036 889F0001
7C632378 5463803E
9061010C 807F000A
889F0001 1C840004
38840016 7C7F212E
887F0001 38630001
2C030010 41800008
38600000 987F0001
887F0000 2C030000
4082000C 38600001
987F0000 3D808034
618CC408 7D8903A6
4E800421 7C7D1B78
809F000E 93BF000E
7C64E850 1C63000C
3C808000 608400FC
80840000 38A003E8
7C842B96 7C842B96
7C632396 907F0062
807F000A 7C63E850
1C63000C 3C808000
608400FC 80840000
38A003E8 7C842B96
7C842B96 7C632396
907F0066 7FC3F378
3D808034 618C738C
7D8903A6 4E800421
BA8100B0 800100E4
382100E0 7C0803A6
881F0002 00000000
C2349A28 00000024 #External/Debug Inputs/LogPollTime.asm
3C608048 80639D30
5463443E 2C030202
40820104 3C608047
60639D64 80630000
2C030000 408200F0
7C0802A6 90010004
9421FF20 BE8100B0
3D808034 618C7364
7D8903A6 4E800421
7C7E1B78 3C608016
6063E774 80830000
5485302E 38800040
7C8523D6 7C632214
83E30008 807F006E
38630001 907F006E
3D808034 618CC408
7D8903A6 4E800421
809F000A 907F000A
7C641850 1C63000C
3C808000 608400FC
80840000 38A003E8
7C842B96 7C842B96
7C632396 7C7D1B78
807F006E 5463063F
41820028 807F005A
7C1D1800 40800008
93BF005A 807F005E
7C1D1800 40810008
93BF005E 4800000C
93BF005A 93BF005E
7FC3F378 3D808034
618C738C 7D8903A6
4E800421 BA8100B0
800100E4 382100E0
7C0803A6 80B80000
60000000 00000000
C2375C14 0000002B #External/Debug Inputs/LogScanoutTime.asm
48000034 5464C63E
5463463E 7C032000
4182000C 3860FFFF
48000018 3863FFF1
1C630006 38800005
7C632396 5463E73E
4E800020 3C608048
80639D30 5463443E
2C030202 40820108
3C608047 60639D64
80630000 2C030000
408200F4 7C0802A6
90010004 9421FF20
BE8100B0 3D808034
618C7364 7D8903A6
4E800421 7C7E1B78
3C608016 6063E774
80830000 5485302E
38800040 7C8523D6
7C632214 83E30008
887F0000 2C030000
41820080 3C60804A
60638B10 80630000
38800000 7C0323AC
7C0004AC 4C00012C
83430000 7F43D378
4BFFFF35 2C030000
41800050 7C7C1B78
3D808034 618CC408
7D8903A6 4E800421
1C9C0004 38840016
7C9F202E 7C641850
1C63000C 3C808000
608400FC 80840000
38A003E8 7C842B96
7C842B96 7C632396
7C7D1B78 93BF0056
7FC3F378 3D808034
618C738C 7D8903A6
4E800421 BA8100B0
800100E4 382100E0
7C0803A6 80010024
60000000 00000000
Change Log

9/14/2023 (v3)
  • Fix bug where if injection was placed in 0x81 memory location, the code would crash. This seemed to happen when using name entry exploit to inject code.
 
Last edited:

jmlee337

Smash Journeyman
Joined
May 8, 2008
Messages
303
Slippi.gg
LEE#337
Lacking ability to run Gamecube homebrew, I tried to test this with Dios Mios (which uses only the Gamecube mode of the Wii). However, Dios Mios does not have perfect compatibility and this definitely calls the following results into question:

Full frame video lag reduction + Poll drift fix [tauKhan]
https://gfycat.com/greenshinygrebe
This appears to indeed have performance issues as feared. You can see higher than vanilla latency when the game is starting as well as for a couple frames sometimes when characters are hit

Half frame video lag reduction + poll drift fix BETA [tauKhan]
https://gfycat.com/fearlessoblongagama
This one seems to work as far as I can tell! I didn't detect any issues

Increase Input Timing Accuracy [Dan Salvato]
https://gfycat.com/possiblepaledassie
Remember when I said Dios Mios has compatibility issues? As this is the polling fix used in Multimod Launcher, I think someone would have noticed if the whole game (including menus!) ran faster on GC

Ultimately someone is going to have to verify these codes on real GC hardware, either using homebrew or a memory card mod.


bonus findings
  • Gecko OS will not apply codes to Gamecube games, you need Gecko OS Mod for that
  • Both are limited to 256 lines by default (the testing code alone is over that)
  • I was unable to find or make an appropriate gameconfig.txt to increase the limit
 
Top Bottom