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

Graphics and sound

How the Xbox-era renderer and audio got onto SDL2, OpenGL and a 5-channel float mixer, and how THUG2's music and voice streams play. All of it came over from the THUG1 port: same engine, same file formats, so THUG2 got its picture and its soundtrack on day one.

GoalSame picture and sound as THUG2's PC release, from its original data files, on a Mac.

The code here was written for the THUG1 port (the diffs are from there) and runs THUG2 unchanged, except for the few format differences the story covers: fonts, skins, animations.

1Render into a backbuffer, present it scaled

The game draws into an off-screen framebuffer at the render resolution; presenting draws that texture as one quad into the window. Everything else (resolution, letterboxing, motion blur) hangs off this.

excerptWn32/Code/Plat/Gfx/p_nx.cpp

2Decode console-flavoured textures

Xbox textures are swizzled (Morton order) and fonts are 8-bit palettized. They're unswizzled and expanded to RGBA before glTexImage2D. THUG2's 2D sprites add one more twist: their rows are stored bottom-up.

excerptWn32/Code/Plat/Gfx/nx/chars.cpp

PS2 alpha goes 0–128, because 128 means "fully opaque" on the GS. Twenty years later we're still multiplying by two.

3One mixer for everything

A single SDL audio callback at 48 kHz, 5 float channels: music and voice streams first, sound effects on top. Locks around it keep the game thread from swapping streams mid-buffer.

excerptWn32/Code/Plat/Audio/Mixer.cpp
excerptWn32/Code/Plat/Gel/SoundFX/p_sfx.cpp

4The soundtrack starts itself

THUG1's retail scripts only queue the soundtrack when running from CD, so the THUG1 port needed a script patch to switch it on. THUG2's main menu starts the playlist itself (PlaySongsRandomly in launch_main_menu; the log says shuffling random song order num_songs=53), so that patch stayed behind.

5Find the tracks: hex names and a .wad

THUG2's PC release does it the same way as THUG1's: music files named after the checksum of the track name, in hex (04df1461.bik and 136 more in streams/music), voice streams packed into streams/pcm/pcm.wad, indexed by pcm.dat.

diffWn32/Code/Plat/Gel/Music/p_music.cpp · THUG1 port

6Decode Bink audio, resample, spread over 5 channels

A built-in Bink audio decoder (binkaudio.cpp) feeds a streamer that resamples to 48 kHz (with pitch, because the game bends voice pitch) and places stereo on the 5 mixer channels the way sound effects do.

diffWn32/Code/Plat/Gel/Music/p_music.cpp · THUG1 port

(void)fPitch; is a stub's way of saying "I heard you, I just don't care". Now it cares.