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.


1Read config.ini before the window exists
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.
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.
Patches compile like any script, from a list in CMake:
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.
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.
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.
At 120 fps the manual balance drifted twice as fast. The skater was fine. My thumbs were not.