github alondero/automobililamborghini-recomp v0.5.0
Automobili Lamborghini Recompiled v0.5.0

one month ago

Pre-release quality. Built from main for early testing and feedback. Expect rough
edges — crashes, audio glitches, and missing native translations are still the rule, not
the exception. Please open issues rather than running off the latest commit silently.

⚠️ You must supply your own ROM

This release contains no game assets or code from the original cartridge. It ships
only the recompiled executable. To play, you must obtain a legal copy of
Automobili Lamborghini (USA).z64 (the North American release is the only one
supported) and place it next to the executable before launching. See BUILDING.md
for the full instructions; in brief:

  1. Extract the archive for your platform into its own folder.
  2. Drop Automobili Lamborghini (USA).z64 into that folder.
  3. Launch the binary.

Game saves go alongside the ROM (or under %LOCALAPPDATA%\LamborghiniRecomp on
Windows / ~/.config/LamborghiniRecomp elsewhere — see README.md).

What's working

Game is playable, with upscaled resolution, high FPS, and widescreen (including HUD)
support across all race modes, plus N64 Rumble Pak support. The headline of this release
is distance pop-in is gone: a four-PR series (#119#122#123#124) traced the
remaining world pop-in to two mechanisms the earlier audits missed — the per-circuit
N64 fill-rate radius cull (worst on the city track: a whole city block popping in at the
35000-unit edge) and a camera-segment visibility list that silently dropped entries
past the first -1 hole. New graphics.json knobs let you tune the radius (draw_distance,
default 1.5× authored; draw_distance_circuit[6] per-track multiplier), the per-track
synth (no_lod_circuit[6], with pro tracks shipping off by default to preserve the
N64-authored look), and fog density (fog_scale, fog_scale_circuit). There's still
glitches so please report issues you find.

Closed since v0.4.2:

Distance pop-in (no_lod series)

  • #87 follow-up / PR #119 — The remaining city-track distance pop-in is fixed. The
    scene builder func_8000A6C0 was distance-culling every PVS entry against a
    per-circuit radius table at 0x80088FD0 — the city track's 35000-unit budget was
    authored shortest, so segment 31 sat ~51k units down a long street and popped in at
    the edge. A per-frame [[patches.hook]] on 0x8000CD3C rewrites the 30 radii to
    1e9 (per-frame because savestate restore brings the ROM values back). Authored
    visibility lists are untouched — segments the game already streamed just stop being
    hidden. New offline audit: tools/pvs_distance_audit.py (replays the builder's exact
    test arithmetic from a LAMBO_RACE_DL_DUMP snapshot).
  • PR #122 — Even with the radii lifted, segments not in the camera's authored
    10-slot visibility row never drew. Two data-model fixes: PVS rows are 10 fixed slots
    with -1 holes (not terminators), and the segment count is (header+0x8 − header+0x4) / 20 — circuit 5 has 55 segments, not 42. Three patches.hooks widen
    the existing walk to synthesise an all-segments row (authored entries first). New
    fog_scale / fog_scale_circuit ride the existing #83 fog DL-walker to scale fog
    alpha without moving its authored onset distance.
  • PR #123draw_distance becomes a dial, not a switch. Default is 1.5× the
    authored per-circuit radii (the worst measured pop needs ≥1.46×); 0 reverts to
    the old unlimited behaviour, 1.0 reproduces N64 distances. Per-circuit
    draw_distance_circuit[6] multiplies with the global. Multiplier-not-absolute
    preserves the authored per-mode budget ratios (1P radii stay longer than 2-4P).
    LAMBO_DRAW_DISTANCE env override for capture.
  • PR #124 — Ship-safe default: no_lod_circuit[6] adds a per-circuit PVS-synth
    gate. Pro tracks (3-5) ship with the synth off to preserve N64-authored back-
    of-buildings / floating geometry the radius cull was hiding; basic tracks (0-2)
    ship with the modern pop-in fix. Radius cull and 2P+ scenery sub-DL stay gated on
    the global no_lod() so distance culling and 2P scenery work on all 6 tracks.
    New docs/TRACK_INDEX.md is the authoritative 0-based / 1-based / F-key / basic-
    pro map.

Stability

  • PR #118 — Pit-stop flicker is fixed, and so is the related cold-load crash from
    LAMBO_STATE_LOAD straight into a pit-stop savestate. The widescreen HUD bracket
    reset hooks sat on recompiled branch labels that run on every incoming path;
    the pit-stop screen bnes straight past the draw and its pin, so every pit frame
    emitted an unpaired G_EX_POPSCISSOR (scissor-stack corruption) and ran the matrix
    walker over a stale span (needle/arrow shift toggled shifted/unshifted per frame —
    the flicker). Cold-load with bracket_start=0 crashed patch_load_mtx_dx 8/8.
    One module-wide bracket flag now arms on every pin and disarms on every reset; the
    quad-text bracket pair (pin_leftquad_text_end) keeps its existing pairing.
    Covered by tests/test_hud_bracket_pairing.c (cold-start reset no-op, paired
    needle shift still exact, pit-path unpaired resets leave scene matrices untouched).
  • #116 / PR #117 — The Championship-standings "Done" button and the second
    button of the pak/records confirm dialogs are no longer dead. The menu system
    dispatches per-screen actions via function pointers in static per-screen element
    tables (0x801EB320, handler at record+0x4); because they're never jal'd, splat
    truncations produced silent no-ops instead of build errors. Whole-ROM sweep for
    data pointers landing on empty-bodied recompiled functions found exactly these
    two — the class is now closed. Standard SPLIT_MERGES + UNSTUB fix (func_80041538
    and func_8004EF0C); absorbed tails have zero independent jal/data callers. PR
    also fixed a generator-sync drift: PATCH_BLOCKS and NATIVE_OVERRIDES now carry the
    hand-edits to lamborghini.us.toml so regeneration is byte-clean (the #78 quad-
    HUD hooks + the PR #108 rumble ignored entries).

Developer tooling

  • PR #120 — Default boot is silent. The same lines that used to print one per
    VI heartbeat (and several on each transition) now only emit when the binary is
    started with --lambo-debug. 99 fprintf sites converted across 7 files behind
    a lambo_log_enabled bool in src/lambo_log.h; the [rt64] and [gfx]
    heartbeats wrap their whole if-blocks so the VI-reg read + interpolatedMutex
    lock also short-circuit on a default boot (not just the inner fprintf). Crash
    dumps ([crash] tag) and the opt-in env-var features (LAMBO_PAK_TRACE,
    LAMBO_DL_INSPECT, ...) are NOT routed through the gate — they were already
    opt-in via env var or only fire on actual signal/SEH. In a 1800-VI headless run:
    default boot = 2 lines, --lambo-debug = 69 lines. main.cpp skips argv entries
    starting with - when finding the ROM path so lamborghini_modern --lambo-debug path/to/rom.z64 works.
  • PR #115 — A new /release slash command (.claude/skills/release/)
    captures the tag → dispatch → wait → verify → ship-notes flow with five
    deterministic bash scripts (list-changes, tag-and-dispatch, wait-for-build,
    verify-release, update-notes) and three reference docs (gotchas, prior-release-
    format, release-notes-template). disable-model-invocation: true keeps the agent
    from auto-triggering — releases stay deliberate.

CI / build

  • PR #121 — Fresh CMake configures were failing during the directx-headers
    FetchContent step (git.exe: add_item failed, errno 1; Git_VERSION=''). Root
    cause: devkitPro's MSYS2 git.exe sat ahead of Git for Windows on PATH and its
    Cygwin heap can fatal outside its own shell. build.ps1's toolchain-PATH step
    now auto-discovers native Git for Windows and prepends it; verifies git.exe
    in the [tools] check and warns if git still resolves to MSYS/Cygwin.

What's not done yet

This is still pre-1.0 — plenty of force_stub.txt still includes real game primitives
rather than no-ops. The tracker is the canonical "what's next" list.

Known follow-ups carried over from prior releases:

  • #26 epic / Widescreen HUD residual gaps — quad-mode skybox / fog / minimap
    pinning is solid in 2P-4P; a few residual cases (the needle/arrow scale keyed off
    the effective rect-pin aspect can over-scale at extreme ultrawide) are tracked.
  • #88 / #91 — lights-match in 3P+ viewports still open from the no_lod audit;
    pop-in is gone but 3P+ scene lighting doesn't always match the 1P baseline.
  • Texture tooling PRs (#99, #66) still open — xBRZ HD-pack batch tooling and
    font upscale / vector re-render tools are staged but not yet merged.

If you find a crash, please open an issue with lamborghini_crash style notes:

  • Output window text (or the crash-*.txt dump if the native handler caught it)
  • Commit / build provenance (below)
  • Approximate in-game location (title screen / car-select / race lap 2 / etc.)

How to run

Linux

unzip lamborghini-recomp-linux-x64.zip -d lamborghini-recomp
cp "Automobili Lamborghini (USA).z64" lamborghini-recomp/
./lamborghini-recomp/lamborghini_modern

Requires libsdl2-2.0-0 and a Vulkan-capable GPU + driver at runtime. Most
desktop distros ship these already.

Windows

Extract lamborghini-recomp-windows-x64.zip anywhere, drop your ROM in the same
folder, and double-click lamborghini_modern.exe. The bundled SDL2.dll,
dxcompiler.dll, and dxil.dll must stay alongside the EXE.

F11 / Alt+Enter toggles fullscreen (and remembers the choice next launch).

For the new pop-in / fog knobs: edit graphics.json (created on first run) and look
for draw_distance, draw_distance_circuit, no_lod_circuit, fog_scale,
fog_scale_circuit. The shipped defaults match what this release was verified
against (1.5× authored radii, pro tracks off for no_lod_circuit, 1.0 fog).

Build provenance

  • Commit: 2446cb3 (main, 2026-07-23)
  • Workflow run: #30075475921 (Build & Release, dispatch from this SHA)
  • Toolchain: Linux build on ubuntu-latest with gcc / cmake / ninja /
    libsdl2-dev / libvulkan-dev. Windows build on windows-latest with
    MinGW-w64 GCC + Ninja (PowerShell, not MSYS bash) per the project's toolchain
    notes.

If you'd rather build it yourself from source instead of running a pre-built
binary, see BUILDING.md. For graphics settings, see README.md.

Don't miss a new automobililamborghini-recomp release

NewReleases is sending notifications on new releases.