- batch-1 cheap tier (83) now 100% drafted: the 29-continuation recovered via resumeFromRunId (9 session-cap failures re-run, 20 cached-replay, 0 errors). - 22/29 -O2 match_one-MATCH; gate banked 8 clean (main 3, _a 2, _after 3) + family_sweep +533 siblings across 133 overlays (5 exemplars, ~0 tokens). - R22 clean-fleet 136/136; dedup-check 1813/0; 0 NON_MATCHING (G4). - backlog: func_801457A4 (MATCH but -O0-only -> batch-3), func_80135004/8013AD38 (need the T7 caller-decl reconcile), func_80168828 (close=8, permuter fuel). - frontier map now 93 exemplars measured (.run/t5_frontier.jsonl). - docs/gen3-parking-lot.md: captured the Gen3 native-port recomp architecture (PsyQ-SDK HLE boundary on Vulkan; recomp-front-end + decomp-incrementally hybrid). - session totals: fleet 71.36 -> 72.18% (+2820 fns). Cheap tier done; giants next (hold).
11 KiB
Gen3 Parking Lot — asset export / native rebuild (speculative; NOT in scope)
The evolvable docs/-layer home for Gen3 ideas (
PROJECT_CONTEXT.mdis static/permanent — P1 — so its "Gen3" + "Parking Lot" sections can't be appended to; this file is where Gen3 speculation and its supporting findings accumulate). Gen3 is PARKED per the roadmap: do not start until Gen2 is substantially matched. Recorded 2026-07-01 at Drew's request, after a "could we export the town mesh / Musashi model and rebuild it in Unity?" discussion + a read-only survey of the current state.
The idea
Export BFM's 3D assets — location/town meshes + textures, and character models (Musashi et al.) — and rebuild / inspect them in Unity (or any modern engine). This is enabled by the code decomp but is a separate axis from it (the decomp byte-matches CODE; this interprets DATA). None of the asset-export tooling exists yet.
Current state — what we ALREADY have (VERIFIED 2026-07-01, read-only survey)
Rendering = stock PsyQ libgpu (understood). The game builds primitives with SetPolyF3/F4/FT3/FT4/ G3/G4/GT3/GT4, manages ordering tables (AddPrim/CatPrim/NextPrim/TermPrim/DrawOTag/DrawSync),
all byte-matched/linked (Phase 7/8). So on-screen geometry is standard PS1 polys (flat/gouraud,
textured/untextured tris & quads) with vertices/colors/UVs/tpage/clut.
Model data = the libgs TMD path IS used (the key positive finding). Verified by real jal call
sites in the disassembly — not grep-count speculation (R14):
jal GsMapModelingData(maps/relocates a TMD in RAM) in the EXE model subsystem —func_8001C214 / C320 / C4A4 / C5B8 / C810 / C924 / C97Cclustered at ~0x8001C2xx–0x8001C9xx— and in ≥1 overlay (ov_SC02_005/func_801871E4).jal GsLinkObject5(link a TMD → a texture-mapped GsDOBJ) infunc_8001C320 / C5B8.- ⇒ BFM's model data is TMD (or GsMapModelingData-compatible) — a documented Sony format. This makes static geometry substantially more exportable than a fully custom format would.
Animation / scene mgmt likely CUSTOM. No call sites found for GsSortObject*, GsInitCoordinate2,
or GsGetLws (the libgs LWS/TOD animation + auto-sort path). Read: the game uses libgs for model data
but a custom sort/draw loop and custom animation on top. ⇒ static town geometry (TMD) is the easy
case; animated characters (Musashi) are harder (bespoke skeleton + animation format to RE).
Textures — the tractable half. The upload/handling path is named (LoadTPage/LoadClut/GetTPage/
GetClut/SetDrawTPage/DumpTPage/DumpClut). PS1 textures live in VRAM (1024×512 16-bit; texture
pages + CLUTs), so a VRAM dump → texpage/CLUT decode → PNG rip needs no full format RE, and PCSX-Redux
is already wired (Phase 3). The type-0 PAC entries (301 extracted .0 "graphics" blobs, each with a
+0x08 dimension/format param — see formats.md) are the prime TIM-candidate source.
Data is all extracted; WHERE a town's geometry lives is TBD. Every raw byte is on disk
(extracted/retail/SCxx.CD.dir/...). Candidate geometry/texture blobs: type-0 (301, "graphics"),
type-7 (139, uninterpreted .7), and possibly the type-4 overlay data tails. Which blob holds a
given town's TMDs is unknown — trace it from a GsMapModelingData caller's source pointer.
Tooling: NONE. No TIM/TMD/mesh decoder or exporter in tools/; formats.md has zero geometry
coverage (only disc-sector "geometry"). This is greenfield.
Difficulty read
| Target | Difficulty | Why |
|---|---|---|
| Town textures | Low | VRAM rip (no format RE); type-0 "graphics" blobs; harness exists |
| Town static mesh | Medium | TMD is documented; locate the blob + confirm stock-TMD vs a Square tweak, then decode |
| Musashi character model | High | Skinned + custom animation (no libgs LWS) — bespoke skeleton/anim format on top of the mesh |
| Unity rebuild (static) | Low–Med | Import glTF/OBJ + PNG; handle fixed-point→float, handedness, unlit/vertex-color + affine→perspective |
| Unity rebuild (animated) | High | Needs the recovered rig + anim export |
Decisive next probes (in order, WHEN we pick this up)
- VRAM texture rip first (quick, high-reward): PCSX-Redux VRAM dump at a town → decode texpages/CLUTs → PNG.
- Trace a
GsMapModelingDatacaller (Ghidra) → find which loaded blob/offset the TMD is read from → locate town geometry on disc (map the type-0/7/overlay-tail question). - Confirm stock-TMD vs Square variant: parse a candidate blob as TMD (header id
0x41, flags, primitive list); a stock TMD decodes with existing PS1 tooling. - Write a
TMD→glTF/OBJexporter +TIM→PNGconverter (tools/— leverage existing PS1 TMD/TIM knowledge). - Unity import + the PS1-ism handling above.
- Animated (Musashi): RE the custom skeleton + animation format (separate, harder sub-project).
Related Gen3 / parking-lot items (from PROJECT_CONTEXT.md, kept here for continuity)
- Shiftable build; asset repack (LZSS recompression becomes real here — a standing Gen3 problem).
- Native recomp / PC port (the original psxrecomp ambition, properly sequenced).
- Randomizer-grade tooling; JP/proto as extra splat versions; text/translation tooling; decomp.me preset; frogress/decomp.dev dashboards; the public flip (Phase 14, deferred to Gen3+).
Honest caveat
This is speculation + a survey, not committed RE. The load-bearing new fact — BFM uses libgs TMD model
data — is byte-verified (real jal sites). Everything downstream (which blob, stock-vs-variant, the
exporter, Musashi's anim) is unstarted and belongs to a future Gen3 effort. The decomp is the enabler:
the matched renderer + the located call sites are the format spec.
Native PC port — the recomp architecture (PsyQ→Vulkan HLE boundary)
Spitball with Drew, 2026-07-08 (during a T5b wait). The fleshed-out "native recomp / PC port" parking-lot item. PARKED — Gen3. Not committed; captured while fresh (R30). The key architectural insight is the PsyQ-SDK HLE boundary, which is what makes a PS1 port tractable rather than "write another emulator."
The idea
A native PC build of BFM via a static-recomp front-end for the game's MIPS code + a PsyQ-SDK HLE layer on modern backends (Vulkan for the GPU, an audio lib for the SPU, native FS for the CD). Distinct from the asset-export axis above (that interprets DATA; this makes the CODE run natively).
The key insight — HLE the SDK API, not the hardware
A naïve PS1 recomp is hard because you end up re-emulating the GPU at the command/register level (the
emulator problem). But BFM never touches GPU registers — it goes through the PsyQ SDK (libgpu
GsSortObject/DrawOTag, libgte RotTransPers, libspu, libcd). The SDK is a finite, documented API,
and we've already isolated it byte-exact (Phase 7/8 linked libgpu/libgte/libspu/libcd from the real
PsyQ 4.0 objects; we know precisely which addresses are SDK vs game code). So reimplement the API, not
the hardware — Wine/Proton-shaped, not emulator-shaped.
Our decomp already draws the exact boundary: every function is partitioned "game code (matched C)" vs "PsyQ library (linked object)." That split IS the "translate vs HLE" partition — Phase 7/8 hands the port its function partition for free. So: game code → static-recomp (or use our decomp'd C where it exists); PsyQ SDK → replace with the Vulkan/audio/FS HLE layer (don't translate it).
Three architectures (and the winning hybrid)
- A — full static recomp (N64Recomp-style): translate ALL MIPS + emulate the GPU at command level. Hard; re-does emulator work.
- B — PsyQ-HLE port (this idea): game code recomp'd/decomp'd, boundary cut at the SDK, HLE'd on Vulkan. The sweet spot.
- C — decomp port: compile our matched C native + a PsyQ shim — converges with B (both need a PsyQ reimplementation).
- Hybrid (the winning move): a recomp front-end boots a native build far sooner than a 100% decomp, then the decomp incrementally replaces recomp'd functions with readable C (recomp-now, decomp-forever). This is the N64 world's proven pattern.
Hard parts (honest)
- Overlays — the #1 PS1 gotcha, and BFM is overlay-heavy (134 overlays streamed to
0x80128158). Static recomp hates "same address = different code over time." N64Recomp handles it by recompiling each overlay separately + dispatching on which is loaded — and we've already mapped every overlay boundary + the loader state machine (Phase 3), so this is derisked for us specifically. This is the biggest reason our recomp is more feasible than a cold one. - GPU HLE (biggest single chunk): walk the OT in
DrawOTag, translate each primitive (POLY_FT4, …) to Vulkan. Choose fidelity — replicate PS1 quirks (affine warp, OT painter's-algo, 15-bit dither) or "fix" them (perspective-correct, hi-res). DuckStation's hardware renderer = a reference for the mapping. - GTE: mostly free via libgte HLE, except BFM uses inline GTE macros (
gte_rtps→ raw cop2; why our import auto-detects GTEMAC +gte_macros.inc) — those cop2 ops land in recomp'd game code → still need a small software GTE (fully documented, a few hundred lines). - SPU + CD: HLE libspu (SEQ/VAB) + libcd → read our extracted assets. The CD loader is already RE'd (Phase 3), so the streaming state machine maps to a file/event model.
The gap + the reusability sleeper
- No mature PS1→PC static recompiler exists the way N64Recomp does (the PS1 world went the emulator +
per-game-decomp routes). Drew's own psxrecomp (rocky v1–v3 post-mortem) is the closest prior art.
⚠️ Verify via web before committing (X2/R17) — check for recent experimental MIPS-R3000/PS1 static-BT
efforts or anyone extending N64Recomp's
RabbitizerLib/N64ModernRuntimetoward R3000. - Reusability: because ~every PS1 game used PsyQ, a PsyQ-HLE + MIPS-R3000-recomp toolkit generalizes to the whole PsyQ library — "N64Recomp for PS1," a genuinely new community tool + a Gen2-public-flip hook.
Sequencing
Gen3, parked — do NOT fork Gen2 focus. This capture is the architecture decision to revisit at Gen3: port architecture = PsyQ-SDK HLE boundary on Vulkan; recomp front-end for early boot, decomp replaces incrementally; overlays per-N64Recomp; reuses the Phase-7/8 SDK partition + the Phase-3 overlay/loader map.
Also worth noting — C++ vs C# (from the same discussion)
- C++ = natural port target: closest to the decomp's C (structs/unions/pointer-math/manual-memory carry over ~mechanically), best perf, direct graphics/audio interop. Port native first, modernize incrementally.
- C# = a reimplementation character (pointer arithmetic/unions fight the managed model) using the decomp as an executable spec/oracle — the Unity-remake route. Valid, more freedom, much more work.
- The decomp enables both; C++ is pragmatic, C# is the "remake."