Acceleration, top speed, impact speed, armor, boosts, chutes and each tool's charges, decoded from the resource file rather than transcribed. GameModel is a fixed 180-byte block: mass at +0, drag at +36, acceleration at +64, impact speed at +100. Top speed is NOT stored - it is terminal velocity, acceleration over drag, which is why it lands on the round numbers the arcade quoted: 6.0/0.060 is Mule's 360 kph, 5.5/0.060 is Bull's 330. Armor is a float in the DamageZones record past the "dz_vtv" name, at +35. Boosts and chutes come from the subsystem stream, which is now walked properly: a record is name[32], a type id, its own length, and the charge count sixteen bytes on. That replaces a regex that hunted for printable names in the float tails and guessed where each one started - the new walk matches every vehicle's declared subsystem count exactly. Neutrino's two derived figures are withheld and the card says why. Its drag is 0.008 against 0.052 on every other Lepton and its impact speed is uninitialised, so the engine would give it a 2880 kph top speed. The data is wrong, not the reading.
Regenerating the reference pages
docs/vtv-presets.html and docs/tracks.html are generated from
assets/RP411/RPL4.RES, the gauge config, and the console's RPConfig.xml.
Both are committed, so this is only needed when the resource file changes.
Both need a resource listing from the original tool, which is the authority for resource ids — the directory can be walked in file order, but the ids have holes (this file leaves 53 and 56 unassigned) so the walk has to be aligned against the listing:
Release\RPL4TOOL.exe -l assets\RP411\RPL4.RES > listing.txt # ends in _getch(); close it
python tools\pages\extract_presets.py vtv.json listing.txt
python tools\pages\build_page.py vtv.json docs\vtv-presets.html
python tools\pages\build_tracks.py listing.txt docs\tracks.html
RPL4TOOL finishes with _getch() (RP_L4/RPL4TOOL.cpp), so with stdout
redirected it writes the whole listing and then waits for a keypress —
close it once the file stops growing.
What each reads
| script | reads | writes |
|---|---|---|
extract_presets.py |
RES, L4GAUGE.CFG, tools/console-config/RPConfig.xml, listing |
vtv.json |
build_page.py |
vtv.json, GAUGE/s*.pcc silhouettes |
docs/vtv-presets.html |
build_tracks.py |
RES, listing, RPConfig.xml, RPL4FE.cpp catalogs, tracks.css/js/tpl |
docs/tracks.html |
build_tracks.py reads the front end's own kMaps / kFootballMaps arrays
so the page cannot claim a track is offered when the menu does not offer it.
Two formats worth knowing
Control mappings. A vehicle's ControlsMappings List holds the resource
ids of its L4 and Thrustmaster streams. Streams are named plainly, so
there is nothing in a stream saying whose it is — resolve by id, never by
which vehicle name sits nearest in the file. Records are 24 bytes and carry
their own mode mask; bits 3–8 are ModePreset1..6.
Map instances. 76-byte records: class id at +0, position at +48, unit quaternion at +60. A few records are longer, so resync on an unexpected class id rather than trusting the stride. The quaternion doubles as a checksum — a mis-read almost never produces a unit one.