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

Screen settings

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

GoalPick a mode and resolution in a menu that looks like THUG2 made it, hit Apply, and have it stick.

1Read config.ini before the window exists

diffWn32/Code/Plat/Gfx/nx/nx_init.cpp · THUG1 port

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 · THUG1 port
new fileWn32/Code/Plat/Gfx/nx/display.cpp

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

THUG2's scripts come compiled and packed in pre/qb_scripts.prx, and the port never edits them. 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 · THUG1 port
diffCode/Sk/Scripting/gs_file.cpp · THUG1 port

The patches are QScript source in Scripts/patches/, compiled for THUG2 by qb when the game is built (see Scripts):

excerptstage_data.sh

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 · THUG1 port
diffCode/Sk/Scripting/ftables.cpp · THUG1 port

5Build the menu in QScript

Two patches. levels/mainmenu/mainmenu_options.q rewrites the wheel's Game Options to add Screen, Graphics, Keyboard and Gamepad after Load Game; scripts/game/menu/gamemenu_options.q does the same for the pause menu's Options and holds the menus themselves, built from THUG2's own menu pieces (the round bars, the road sign on the right). Chapter 4 has the story.

excerptScripts/patches/scripts/game/menu/gamemenu_options.q

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 · THUG1 port
diffCode/Sk/Objects/manual.cpp · THUG1 port
diffWn32/Code/Plat/Gfx/p_nx.cpp · THUG1 port

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

7The result

configGame/config.ini