For education purposes only · no game files included · bring your own THUG
Guide 04

Screen settings

How to add Options › Screen: window or fullscreen, a render resolution, and a 60 / 120 fps limit, saved to config.ini. Also: how to patch the game's menus at all.

GoalPick a mode and resolution in a native-looking THUG menu, hit Apply, and have it stick.

1Read config.ini before the window exists

diffWn32/Code/Plat/Gfx/nx/nx_init.cpp · 5660c56

No Spaces, no swoosh animation. Fullscreen is just a borderless window that happens to be very large.

2Render at the chosen size, letterbox the rest

The render resolution no longer follows the window. The present pass fits the backbuffer into the drawable, keeping its aspect ratio, and clears the bars to black.

diffWn32/Code/Plat/Gfx/p_nx.cpp · 5660c56
new fileWn32/Code/Plat/Gfx/nx/display.cpp

3Patch the retail scripts (the trick behind every menu here)

The retail qb.pre takes priority over compiled scripts, so editing Scripts/*.q does nothing. Instead, after any .qb loads, a matching scripts/patches/<path> is parsed on top. Its symbols are registered under the original file name, so level unloads take the patch with them and reloads re-apply it.

diffCode/Gel/Scripting/file.cpp · 5660c56
diffCode/Sk/Scripting/gs_file.cpp · 5660c56

Patches compile like any script, from a list in CMake:

diffCMakeLists.txt · 5660c56 + 28ef9a3

4Expose C++ to the menu

Three script functions: read the settings, list resolutions that fit the screen, apply. Registered in ftables.cpp like the retail ones.

diffCode/Sk/Scripting/cfuncs.cpp · 5660c56 + c46ec33
diffCode/Sk/Scripting/ftables.cpp · 5660c56

5Build the menu in QScript

The options menu is copied whole into the patch with one more item; the Screen menu reuses the theme's scrolling menu and adds a check mark sprite as each item's 5th child.

diffScripts/patches/levels/mainmenu/mainmenu_scripts.q · 5660c56

fullscreen = screen_menu_fullscreen passes a global by name, and CStruct::GetInteger quietly resolves it. QScript is weird. QScript is wonderful.

660 or 120 fps without breaking the physics

The limiter uses the high-resolution counter, sleeps while there's time and spins for the last 2 ms. Game logic already scales by frame time, except for two spots that assumed 60.

diffWn32/Code/Plat/Gfx/nx/nx_init.cpp · c46ec33
diffCode/Sk/Objects/manual.cpp · c46ec33
diffWn32/Code/Plat/Gfx/p_nx.cpp · c46ec33

At 120 fps the manual balance drifted twice as fast. The skater was fine. My thumbs were not.

7The result

configGame/config.ini