This repository is the orchestration workspace for reverse-engineering Burnout 5 / Burnout Paradise. It is not the decompilation source tree itself. It holds the analysis databases, reference material, work ledger, and automation that let agents reconstruct the Xbox 360 build as compilable PC C++.
Recovered C++ lives in the b5-decomp submodule. This repo answers:
- which functions exist in the X360 target build;
- which translation unit owns each function;
- what reference evidence is available for each unit;
- which units are todo, in progress, compiled, reviewed, blocked, or done;
- how to claim, reconstruct, verify, review, and coordinate work.
For reconstruction work, read these in order:
AGENTS.md- the operating guide for every agent and maintainer.STRATEGY.md- the technical plan and rules of evidence.progress/README.md- the ledger andworkCLI reference.
CLAUDE.md exists only as a redirect for Claude Code. The canonical instructions are
shared in AGENTS.md so all agents follow the same process.
No single binary contains enough information. The workflow triangulates:
| Build or artifact | Role |
|---|---|
BURNOUT_X360_ARTIST.XEX |
Target/spine. Its symbols, pseudocode, asm, and xrefs define what is reconstructed. |
Burnout_External_PS3.ELF |
Symbol-rich PS3 corroboration for names and behavior. |
DecFIGS_Burnout_Internal_PS3.ELF |
DWARF source/file attribution plus declaration, type, enum, global, signature, and local-variable hints. |
BurnoutPR.exe and TUB_Burnout_PC_External.exe |
Stripped PC references, consulted selectively for platform-specific code paths. |
rwcore.lib / rwcore.pdb / rwcore_master.obj |
RenderWare core type and layout evidence. |
references/Feb-2007/ |
A real source-code slice used as the highest-fidelity template where it overlaps. |
references/Wiki/ |
burnout.wiki-derived type tables. Use names/types/semantics, never offsets. |
The canonical identity is a normalized qualified function name, not an address. Addresses are build-local and must not be treated as stable across binaries.
| Path | What it is |
|---|---|
AGENTS.md |
Tool-agnostic operating guide: resume behavior, work loop, server coordination, reconstruction rules, review policy, and "don't" rules. |
STRATEGY.md |
Design document for the workflow: target, build roles, identity model, TU model, stubs, verification, goals, and phase status. |
IDA Files/ |
IDA Pro databases and RenderWare library/PDB inputs. Some large .i64 files are intentionally git-ignored and must be supplied locally. |
.ida-exports/ |
Generated per-function JSON exports from IDA: names, prototypes, locals, pseudocode, asm, callers, and callees. Git-ignored. |
references/ |
Non-disassembly evidence: Feb-2007 source slice, DecFIGS DWARF artifacts, BPR module map, wiki index, and naming conventions. |
tools/ |
Domain-organized IDA, build, asset, RenderWare, diagnostic, and tools/work/ ledger/reconstruction tooling. |
progress/ |
Shared ledger inputs and outputs: identity, TU index, dependencies, status mirror, goals, verification/review configs, and generated review packets. |
b5-decomp/ |
Submodule containing recovered C++, vendor libraries, RenderWare headers, and CMake project files. |
build/ |
Local build tree for b5-decomp; not source of truth. |
.env.example |
Optional work-server configuration template. Copy to .env only if a maintainer gives you a worker id. |
Generated review packets under progress/reviews/ and vendor Markdown under
b5-decomp/vendor/ are artifacts/upstream documentation, not primary workflow docs.
Required for normal ledger work:
- Python 3
- Git
- PowerShell on Windows
- initialized submodules under
b5-decomp/vendor/
Required for the compile gate:
- Visual Studio/MSVC
progress/verify.config.jsonpointing at a realvcvars64.bat
If vcvars is missing, work submit reports a skipped compile gate and continues;
that is useful for bookkeeping but does not catch compiler errors.
Required only for regenerating analysis exports or generating new skeletons from IDA:
-
IDA Pro with Hex-Rays (
idat.exe) -
The relevant
.i64databases underIDA Files/ -
Generated
.ida-exports/for the target databases. If they are missing or stale, run the IDA export script before doing reconstruction work:tools/export_db.ps1
Large or licensed local inputs are intentionally not all committed. At minimum, local work that regenerates exports may need the git-ignored PS3/PC IDBs and the Feb-2007 source tree documented in the reference READMEs.
For a new local workspace:
-
Clone this repository without submodules:
git clone --no-recurse-submodules https://github.com/BurnoutDecomp/BP-Decomp_Workflow cd BP-Decomp_Workflow
-
Download the archive from Google Drive and extract it directly into the repository root.
-
Bootstrap the workspace:
work bootstrap
-
Generate the IDA export cache:
tools/export_db.ps1
After that, open an AI coding agent such as Codex or Claude Code in the repository and give it a normal work instruction, for example:
Continue with the next 5 [or any number you want]
The agent will read AGENTS.md, claim the next ready translation units, reconstruct the
code under b5-decomp/src/<mirrored path>, run the compile/parity gates, and record the
review verdicts.
Server coordination is optional. If you want your claims and completed work to be sent
to the shared work server, ask a maintainer for a worker id, then copy .env.example to
.env and set WORK_AGENT. Without that token setup, the workflow still works locally.
work status # ledger counts and active goal
work next -n 5 # preview ready work; reserves nothing
work claim [-n N] # claim next ready TU(s)
work claim <tu> [<tu> ...] # claim specific TU(s)
work show <tu> --full [--asm] # reconstruction dossier
work stubs <tu> --list # unresolved callees and owning headers
work submit <tu> [--files path ...] # compile gate, parity, reviewer packet
work parity <tu> # standalone deterministic parity check
work review <tu> --verdict pass # mark done after review/self-check
work review <tu> --verdict fail # return to in_progress with notes
work block <tu> "reason" # stop it being reclaimed
work reset-tu <tu> # delete produced files and return TU/functions to todo locally and server-sideThe compile gate is per translation unit (cl /c, no link). The target is semantic
parity with the X360 build expressed as source-like PC C++, not byte matching.
The authoritative inventory of repo tools is tools/README.md.
At a glance:
| Tool area | Entry points |
|---|---|
| Day-to-day ledger work | work bootstrap, work status, work next, work claim, work show, work submit, work parity, work review, work block, work reset-tu |
| Goal scoping and traces | work goal ..., work goal import-trace, tools/work/trace_import.py |
| IDA export pipeline | tools/export_db.ps1, tools/ida/export_all.py, tools/ida/export_lineinfo.py, tools/ida/decompile.py |
| Derived ledger builders | tools/work/build_identity.py, tools/work/build_tu_index.py, tools/work/build_type_deps.py, work seed --deps |
| Reconstruction helpers | tools/work/dossier.py, tools/work/gen_stubs.py, tools/work/gen_skeleton.py, tools/work/auto_draft.py |
| Verification/review | tools/work/verify.py, tools/work/parity.py, progress/verify.config.json, progress/review.config.json |
| Reference and maintenance | tools/work/wiki_index.py, tools/work/check_vendor_lib.py, tools/work/reconcile_from_files.py, tools/work/find_local_redefs.py, tools/renderware/generate_headers.py |
| Optional server coordination | work sync, work server-sync, work server-update, work resolve-class-homes, work server-reset, work worker-add, work worker-list, work worker-revoke |
By default work next ranks the whole program leaf-first. A goal scopes the queue to a
membership set, either hand-authored globs or an execution-derived Xenia trace:
work goal
work goal show boot-trace
work goal set boot-trace
work goal clear
work goal import-trace <name> [--trace-dir .trace/funcdata]Goals live in progress/goals.json. The full schema and Xenia
trace procedure are documented in references/GOAL_SCOPING.md.
The default mode is local: the ledger and git are the only state. If a maintainer gives
you a server URL and worker id, copy .env.example to .env and set:
WORK_SERVER=https://...
WORK_AGENT=<server-issued-worker-id>
WORK_LEASE_SECONDS=7200
With a server configured, work claim is atomic across agents and live claims live on
the server. Durable states tied to committed code (done, blocked) still sync through
progress/status.json.
A configured server that is down does not break the work loop — the CLI degrades gracefully and self-heals on reconnect, so agents never have to manage outages.
- Connection failure vs. rejection. A server that can't be reached is treated as a
recoverable outage; a server that answers with an error (HTTP) is a real decision.
Only a genuine auth rejection (missing/invalid
WORK_AGENT) still stops a command — that's a config error, not an outage. - Degrade locally. While the server is unreachable, reads (
work next,work status) fall back to the local leaf-first ranking and counts; writes (work claim,work submit→ compiled,work review,work block/unblock) apply to the local ledger and are recorded in an offline outbox (apending_optable in the git-ignored ledger cache). - Self-heal on reconnect. The outbox replays automatically before the next
server-mode command, or on demand with
work sync.work statusshows the queued-op count and whether it is reporting the server or the local ledger. - Nothing finished is ever lost.
done/blockedare durable in git (progress/status.json), so even after a long outage they reconcile into the server viawork server-sync. Only the ephemeral claim layer can drift offline (a lease may lapse on the server, or an offline claim may collide with another agent). Such conflicts are reported during sync — never silently dropped, never overwriting local state.
work sync # flush queued offline ops (auto-runs otherwise)Maintainer commands:
work server-sync [--branch <branch>] # tell the server to pull + re-import (preserves live claims/events)
work server-update [--reconcile] [--no-push]
# one-shot: refresh class homes (+status), push, re-import on the server
work resolve-class-homes [--apply] # map class TUs to their real committed home files (progress/class_homes.json)
work reconcile-from-files [--apply] [--no-demote]
# re-anchor local ledger/status.json from committed b5-decomp files
work server-reset [--to <ref>] # local reset + server reseed
work worker-add "Name" [--admin]
work worker-list
work worker-revoke <worker-id>Because every claim/submit/review is mirrored to the server, the committed
progress/status.json is a derived view of the server's durable state, not an
independent source. A GitHub Action keeps git in step with the server automatically, so
the people doing the decompilation only ever push to b5-decomp — they need no write
access to this workflow repo and never hand-edit status.json.
It runs once per b5-decomp commit. The notifier workflow
b5-decomp/.github/workflows/notify-workflow.yml
fires on every push to b5-decomp's dev branch and sends a repository_dispatch (carrying
the new commit SHA) to .github/workflows/reconcile-status.yml
in this repo, which then:
- regenerates
progress/status.jsonfrom the server'sGET /export/status. The server is the only full authority: a files-only reconcile can recoverdone(its file exists) but notblocked(a blocked TU leaves no file), so the durable set is pulled straight from the server; - advances the
b5-decompsubmodule pointer to the commit that triggered the run; - cross-checks the server's
doneset against the committed b5-decomp files withreconcile_from_files.py(non-blocking — it only emits a warning if the server marks a TUdonewhose committed file is missing or still a trap-stub/partial); - commits and pushes the regenerated
status.json+ bumped pointer under a bot identity.
Setup (one-time): the notifier needs a WORKFLOW_DISPATCH_TOKEN secret on the
b5-decomp repo — a token that can send repository_dispatch to
BurnoutDecomp/BP-Decomp_Workflow. For a fine-grained PAT, select the
BurnoutDecomp organization as its resource owner, grant access to
BP-Decomp_Workflow, and grant repository Contents write permission. A classic PAT
needs repo scope and any organization authorization required by GitHub. Without the
secret the notifier no-ops (so nothing breaks), but the automatic reconcile won't fire.
The reconcile Action also has a manual workflow_dispatch trigger (optionally pin a
specific b5_sha) for backfills.
You can refresh the committed mirror manually too:
python tools/work/fetch_server_status.py # rewrite status.json from the server
python tools/work/fetch_server_status.py --check # report drift, write nothing (exit 1 if stale)If commits reached b5-decomp without going through the server's normal claim/submit
flow, update the server so its dashboard reflects the committed state:
work server-update # refresh class homes, push, re-import on the server
work server-update --reconcile # also reconcile status.json from committed files (promote-only)This is the supported path. There is no event-reconstruction command: the old
server-reconcile-events synthesised review_pass events from git history with
commit-date timestamps — fabricated activity — and has been removed. Per-contributor
credit on the dashboard is now derived purely from Git attribution (surviving-line
authorship of each TU's committed files):
class:TUs carry no source path, sotools/work/resolve_class_homes.pymaps each to its real committed home file and writesprogress/class_homes.json, which the server reads on import.work server-updaterefreshes it for you; run it standalone withwork resolve-class-homes [--apply].- A class whose home cannot be identified unambiguously is left unmapped (shown as unattributed) rather than guessed — the map only ever points at a real file that contains the class.
Two operational notes:
- The server is now a durable store for
blocked.doneis always recoverable from the committed files, but a blocked TU's state and reason live only on the server — so back up its DB (/var/lib/bp-work-server). The bot-committedstatus.jsondoubles as a backup of thedone/blockedset. - The Action pushes to the default branch. If it is protected against direct pushes, point the Action at a side branch with an auto-PR instead of allowing the bot to push.
These helpers are optional. They do not replace manual reconstruction:
work auto --scan # find fully mechanical TUs
work auto --run [-n N] # draft/gate safe forwarder/thunk-only TUs
work reconcile-from-files [--apply] [--no-demote]
python tools/work/find_local_redefs.py [--summary]
python tools/work/wiki_index.py [--lookup <Type>]
python tools/work/check_vendor_lib.py <tu>Vendor SDK TUs must be checked with check_vendor_lib.py before decompiling. If the
script prints PRESENT, block the TU as vendor code already covered by a PC library or
open-source vendor source. If it prints MISSING, reconstruct it normally.
Most agents do not need to regenerate exports if .ida-exports/ is already present
and current. On a fresh machine without that cache, or whenever IDA analysis changes,
run the IDA database export first:
tools/export_db.ps1 # generate .ida-exports/ from IDA Files/*.i64
tools/export_db.ps1 -DbName "BURNOUT_X360_ARTIST.XEX"Then rebuild derived DecFIGS/ledger artifacts as needed:
python tools/ida/build_source_tree.py
python tools/work/build_identity.py
python tools/work/build_tu_index.py
work seed --deps --resetUse tools/README.md for the full script inventory and command details.