Skip to content

Audio Video and Input

LordBlacksun edited this page Sep 9, 2026 · 1 revision

Audio, Video & Input

All facts [verified] by reading the decompilation unless marked otherwise.

Audio — Miles Sound System (mss32, AIL_*)

Audio data is streamed from in-memory HOG blobs, never from loose files.

Addr Role
0x0042DAB0 Audio-options screen. INI [Sound] keys: 3DProvider, Fxvolume, Musicvolume, Speechvolume, Mastervolume. Applies live via AIL_set_stream_volume/AIL_set_sample_volume. Provider index DAT_005D5630.
0x00481900 3D-provider enum/open. switch: 0 = Miles Fast 2D Positional, 1 = Aureal A3D, 2 = Creative EAX, 3 = RAD RSX (+ Dolby Surround flag). AIL_open_3D_provider; max samples queried and clamped to 64; allocates a 64-voice table at DAT_00563F60 (stride 0x44).
0x0049D160 EAX environment: AIL_set_3D_room_type + AIL_set_3D_provider_preference("EAX damping"/"EAX effect volume"/"EAX decay time").
0x00481F80 + 0x004826A0 HOGSND sample playback. The worker computes an in-RAM pointer = HOG base + entry offset and calls AIL_set_sample_file(handle, ptr, -1) — confirming samples play from the in-memory archive. Voice pool DAT_00565080.
0x00482160 positional 2D pan/volume accumulator (mix table DAT_00565340).
0x00482A80 music streaming via AIL_open_stream (handle DAT_00565300); default rate 22050 Hz.

Video — Bink (binkw32)

Audio is routed to Miles via BinkSetSoundSystem(BinkOpenMiles, …). Movies live inside the HOG.

Addr Role
0x004C83F0 HOG movie locator (bigfile.cpp): walks the archive directory, strcmps the name, SetFilePointers the HOG handle to the entry offset → hands a positioned spec to BinkOpen.
0x004AB850 play from a filename (clear screen).
0x004AB9D0 no-clear, resourcedBinkSetFrameRate(15,1), opens with flag 0x800000 (RAM-resident).
0x004ABB80 resourced + clear.
0x004ABDE0 chapter/cutscene sequencer (chains clips; also landing movies).
0x004AC510 per-frame core: BinkDoFrame → lock back-surface → BinkCopyToBuffer → unlock → BinkNextFrame. Movies are centred on the surface (dest = (surf − movie) >> 1), not letterbox-scaled.
0x00439FB0 front-end / "VR-room" host: decodes into a 640×480×16 software buffer (0x96000, pitch 0x500=1280) used as the animated UI background.
0x004362F0 medal-display screen (rel_locklup.bik/locklidup.bik; loads rmedal%d.spr/rbar%d.spr). This is the path tied to the project's known medal-case crash — scrutinise its sprite-load loop.

Skipping the startup logo movies (the blank.bik fix)

The three startup branding logos are a consecutive string-table group (0x50A2E8), opened from the CD HOG (BinkOpen(resource, 0x800000), not loose files) at process start: warty_.bik (Warthog), new_dalogo_fs_uncmpr.bik (Digital Anvil), new_nms.bik (Microsoft Game Studios) — followed by the splash to mm.bik transition; the campaign intro is new_intro.bik. (0x004ABDE0 is the related per-chapter intro/landing sequencer, not the logo player.) The shared play loop (0x004AC510) tolerates a missing or zero-frame movieBinkOpen returns NULL (logged, not fatal) or the end flag trips on frame 0 — so the engine just moves on; each frame also polls input (0x004BD570), so any keypress already aborts a playing clip. Replacing the logo entries with a minimal zero-frame Bink therefore skips them. The repo tool tools/blank_boot_videos.py blanks the three logos by default (the splash + intro are opt-in), part of the broader modern-fixes catalogue (docs/modern-fixes.md). (Verify in-game yourself — the project never launches the binary.)

Input — DirectInput 7 + force feedback

Addr Role
0x004BCD90 DirectInputCreateEx(…,0x700,…) (DI7); creates keyboard + joystick devices; loads the WinVFX vfx.dll FF runtime; FF-present flag DAT_0050E1A4.
0x004BD490 / 0x004BD300 / 0x004BD3A0 poll keyboard (GetDeviceState(0x100,…)) / joystick (DIJOYSTATE, 0x50) / mouse; auto-Acquire on input-lost.
0x004BD570 the engine's "was this action triggered?" edge query used by every menu/movie loop.
0x0042CAA0 / 0x0042C800 / 0x0042C630 bind table DAT_004E2380 (stride 0x4E). Defaults from %sdefault.txt, user binds from INI; sections [KeyConfig] / [JoyConfig]; tokens JOY_BUTTON, SHIFT, CONTROL, ALT.
0x0042B690 rebind UI; toggles ForceFeedback, JoystickInvert, HatEnable, TwistEnable, controller.
0x004BD800 FF effect-table loader — .frc files (pc/mb/prc/gl/tc/np/cg/gp/vb/nc/Missile/Shake) under forces\.
0x004BDB10 loads a .frc via COM (CoCreateInstance) — these are Immersion Studio force-resource files, not parsed inline.
0x0047BDB0 plays an FF effect (guarded by FF-present && FF-enabled && is-player-ship).

Frame timing (FPS-cap relevance)

  • Master clock = GetTickCount (1 ms). A single global frame timestamp DAT_00565064 is refreshed each frame; ~141 gameplay timers are expressed as DAT_00565064 + delay_ms — i.e. wall-clock, not frame-count, which is favourable for raising/removing an FPS cap. [verified]
  • timeBeginPeriod(1)/timeEndPeriod(1) set 1 ms timer resolution; WinMM multimedia-timer callbacks drive a periodic task list with catch-up capped at 50 iterations per pass. [verified]
  • QueryPerformanceCounter is used only by a developer profiling stack, not the gameplay clock.
  • Bink playback is forced to 15 fps and gated on BinkWait, so movies are decoupled from the engine frame loop. No per-frame Sleep/spin frame-limiter was found in these subsystems. [verified]

Clone this wiki locally