Skip to content

About

Independent open X-Plane-compatible engine in Rust. Requires an original copy of X-Plane 12.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

openXplane

openXplane is an independent open engine with gradual compatibility with X-Plane content, written in Rust. Approach: study the original, implement each subsystem independently, and compare the results with the reference build. The first reference is a provided X-Plane 12.

Important

openXplane contains no game content. It needs an original copy of X-Plane 12 and only reads from it.

Cessna 172 SP in the openXplane viewer

Architecture and milestones, modelled on openOMSI: docs/ARCHITECTURE.md.

Download

Every change to main is built by GitHub Actions and published as the rolling nightly release:

Platform File
Windows x64 openXplane-<version>-windows-x64.zip, run openxplane.exe
macOS (Apple silicon) openXplane-<version>-macos-arm64.zip, run openxplane
Linux x64 openXplane-<version>-linux-x64.zip, run openxplane

There is no launcher yet: run it from a terminal and point it at your X-Plane 12 folder (see the commands below).

Goals

  1. 1:1 behaviour. The formats and algorithms of X-Plane 12 behave as in the original, confirmed in the reference build and verified against its machine code.
  2. No original code or assets. Nothing is copied; formats are described in the research notes.
  3. A better engine. Rust, wgpu (Metal, Vulkan, DirectX 12), 64-bit, multithreaded loading.

Documentation

Document What is in it
Keyboard the original's default keys and openXplane's own
User guide install, first flights, data output
Building toolchain, tests, regenerating vectors
FAQ common questions
Releasing versions, nightly builds
Architecture crates and roadmap
Plan phased plan for a full implementation
Compatibility how close it is to the original, and how that is estimated
Discord Rich Presence
Research notes every recovered format and algorithm, with evidence
Verification comparing ports against the original machine code
Changelog what changed in each version

Repository layout

openXplane/
├── VERSION            MAJOR.MINOR of the next release (edited by hand)
├── crates/            the engine, one crate per subsystem
│   ├── xp-acf/          ACF aircraft files, typed parameters, lifting surfaces
│   ├── xp-airfoil/      AFL tables, the verified evaluation chain, the wing element function
│   ├── xp-obj/          OBJ8 model reader
│   ├── xp-scenery/      installation layout, apt.dat, airport ground geometry
│   ├── xp-dataref/      dataref and command registries, default keyboard map
│   ├── xp-sim/          the approximate flight model and pilot commands
│   ├── xp-discord/      Discord Rich Presence
│   └── xp-app/          the `openxplane` binary (viewer, flight, tools) and the tests against the original
├── tools/             research tools: emulator, extractors, vector generators, logo, scoring
├── scripts/           build scripts for every platform, version.sh
├── assets/            logos, screenshots, the keymap table
├── docs/              user documentation (also published on the website)
├── research/          research notes
├── site/              the GitHub Pages website
└── .github/workflows/ CI, nightly builds, the website

Contributing

See CONTRIBUTING.md. Security problems: SECURITY.md.

How close to the original is it?

About 41% implemented, about 28% verified identical to the original. Early stage: it loads the original content, draws it, and flies an approximation; it does not yet behave like X-Plane.

  • Implemented counts work that exists in any form, including approximations (the flight model is one).
  • Verified identical is an estimate of recovered behaviour supported by comparisons with the original code. Evidence distinguishes exact matches from controlled inputs and platform tolerances; it does not establish whole-game equivalence.

This is a self-assessed, weighted rubric, not a measurement (method and per-subsystem numbers in docs/COMPATIBILITY.md; data in docs/compat.json, updated with python3 tools/compat_score.py --write).

Subsystem Weight Implemented Verified identical Notes
Aircraft files (ACF) 8 32% 12% All properties are preserved; typed: mass, CG, wings, gear, engine and controls subset. Loader schema recovered from the original; focused property subsets have strict original-code comparisons. Three original-loader replays now reach the return sentinel (13690, 13718 and 15525 tracked words). Previous fixtures were partial; two contain 424 corrected words each. These are reference results, not a count of matching ported fields. The full-object diagnostic is explicitly ignored by default, requires local reference files when requested, and reports remaining differences without asserting parity. The wing chord unit-conversion loop is enforced bit for bit on 312 synthetic original-code cases (3432 output words). Typed wings read all 48 slots and use supplied active rib chords; missing rib arrays retain a declared linear approximation. Active _c_off_for_RIB values are now typed without unit conversion and passed to the recovered boundary writer. The complete 20x18x3 body-grid feet conversion is recovered: 69120 synthetic SSE outputs and all 15120 supplied Cessna body-coordinate fields match exactly in debug/release. These local tests are explicitly ignored in ordinary CI; remaining full-object mismatches are still reported.
3D models (OBJ8) 7 35% 5% Geometry, nested transforms, rotation/translation animation, textures. No normal/lit maps, instruments, panels or most dynamic animation.
Airfoil evaluation (AFL) 6 90% 85% All 34 airfoils; the whole profile function (selection, stall, buffet, blending, Mach factor) matches the original bit for bit on 1800 emulator cases.
Flight model 28 81% 72% An approximate rigid-body model that takes off and flies. Verified against the original machine code in an emulator: the airfoil and per-element aerodynamics, the whole engine update and the propeller force function, the engine controls for every engine kind, the airflow wash, the terrain mesh probes (vertical ray and segment with moving cells), the strut, tire, wheel and body blend contact models, the weight and balance, the input binding query, and the whole flight step block by block: the wing, body and part loops, the landing gear (targets, steering, brakes, drag, strut contact), the wing and body ground contact chain, the hook, tow, float and wave forces, the plug-in force sink, the equations of motion and the integration, the position setter, the attitude, the geographic state, the 4 x 4 matrices and the Euler angles, the flight angles and the end of the step. Remaining recovery and integration work includes scenery-backed terrain and geoid queries, shared-pointer object lookups, per-strip airflow (0x14121a9b0), radiator update and runtime caller state; many ported blocks are not yet connected into a running model. The viewer still flies an approximate model, but now runs the recovered positive-delta coefficient branch and ordered wing grouping with recovered aspect/centroid parameters. Since the previous review, controlled original-code comparisons cover delta parameter curves, noise, target coefficients, full-element and force composition, aircraft bounds point emission, wing enable/join predicates and the 49-pass group scan. Full-element delta output matches 2099/2100 words exactly on macOS, with one platform-trigonometry difference checked by tolerance; some corpora use recorded CRT results or synthetic noise. Live wing chord inputs now use recovered ACF rib conversions and the typed reader scans 48 slots. The live boundary coordinates now use the recovered writer for up to ten elements, with ACF chord offsets and CG-relative origins. Dynamic wing rotation/retraction and aircraft curvature are fixed to zero; element force arms/normals and much of the running flight model remain approximate. Controlled whole-writer comparison covers 240 cases and 1431 points: all 4293 words match with recorded original CRT results, 4292 match using platform trigonometry (one bounded difference). Original geometry update scheduling, reference state and noise initialization are not yet connected. Curvature setup is recovered from acf/_ball_ang_def_deg: a local 521-case original-code comparison matches 1562/1563 words exactly, with one bounded platform-math difference. Live curvature remains zero until complete original reference bounds are supplied; the setup comparison is explicitly opt-in and its corpus is local. No whole-model parity is established. Body quad emission matches 47844 coordinate words across 120 local original-code cases; the ten-slot gear point pass matches 23952 words across 500 cases, both without tolerances. Inputs are explicit transformed body grids and stored gear fields, not proven live runtime state. Propeller point production now matches 28632 words across 400 local original-code cases, without tolerance. Gear, wing, body and propeller point producers are recovered individually; combined reference-vector assembly now matches 22350 point words and 800 final bounds words across 80 single-pass original-code cases. These checks include original auxiliary numerical helpers with only new/delete replaced; their auxiliary output fields are not compared. Body-grid/propeller runtime preparation and live reference integration remain unfinished.
Datarefs and commands 8 34% 20% Registries and catalogs of 5503 datarefs and 3138 native command records from the original, its default keyboard map (182 bindings, 178 distinct chords, including Shift/Alt/Ctrl), values for 6 datarefs; 30 unmodified key commands act in the flight viewer; 2388 datarefs mapped to the field of the flight object or the simulation object that their getter reads (decoded from the getter code). All 182 key/mask pairs match a local original-code copy-block replay; four conflicting original chords are preserved and not dispatched. OS event lifecycle and UI handlers remain unverified. A separate native key-vector transition port matches 2728 local replay cases (active fields, suppression and ordered callback requests); callback bodies are logged, and live wiring is pending.
Scenery and world 14 10% 0% Airport ground from apt.dat (runways, taxiways, aprons). No DSF, terrain, objects, lights or weather.
Cockpit, instruments, Lua systems 10 0% 0% Not started.
Rendering 6 20% 0% wgpu viewer with lighting and glass. No PBR, shadows, sky, clouds or instrument screens. Original Alt/Esc UI is not ported in the active viewer: Esc exits, and its HUD uses Roboto Mono. No paired reference visual or motion comparison establishes UI/graphics fidelity. Original local UI resources now decode through ui-resources: 25 PNG/DXT5 DDS textures at their stored dimensions and 12 intact font files. The viewer is not yet connected to them; local decoding is not visual parity. Native controller/window-registry queries and cumulative parent opacity are recovered: 1033 local contexts match query results, finite opacity bits and 2066 command traces. Four UI action bodies remain logged; explicit state services are not yet live viewer UI. The 2026-10-15 concrete-menu prefix review leaves shares unchanged: 480 original executions from0x140ecb340 to asserted RIP0x140ecb592 match full object/allocation snapshots, global interface linkage, three embedded-member registrations, vector growth and successful/null optional callback allocation. This composes the common/input/member/interface constructors; 710 earlier native constructor cases pass again after shared-helper extraction. Translation and allocator/free/CRT endpoints are controlled, inline strings and small valid registries apply. The stop is before singleton dialogs, not normal constructor return. Remaining dialogs/children/layout/resources, heap strings/full teardown, opening ID3/Alt, live viewer and paired GPU screenshots/GIF/video remain unverified. The bound-callback lifecycle review keeps shares unchanged: 324 original sequences (5832 ctor/copy/bind/base-teardown calls) match live identities, full-width wrapper parameters, ordered reciprocal links and allocation/free sizes/counts. Copies retain registration after temporary destruction, and source removal detaches surviving wrappers. Allocator/free are controlled and custom callables null; native red-black node bytes and free-pointer order are not modeled. Real dialog140ec9c10 copies these wrappers at+1f8/+260, but complete dialog/resource/layout construction and heap-string support remain unfinished. This logical connection comparison is not whole-object/heap-byte or paired visual evidence. The heap-string constructor review keeps shares unchanged: 324 complete original common/wrapper/input/callback/string ctor cases match all panel/source/allocated bytes and exact allocation/free order with full panel snapshots. Mixed inline/heap sources, spare capacity, embedded zeros, length15/16 and 4096-byte aligned-allocation boundaries are covered. Constructor-argument ownership cleanup now composes with the common panel; the earlier64 input/256 common/480 concrete-prefix replays still pass. Allocator/free/CRT copy are controlled; failure/overflow, reentrancy, actual dialog translation/children/layout/resources/full teardown and live viewer/paired pixels remain unverified. The dialog child-factory review keeps shares unchanged: 576 whole original1410d6ca0 executions match full bundle/heap snapshots at every allocator/constructor/resource/refresh entry and final bytes, covering all32 external allocation-null masks, distinct constructor return pointers and opaque resource values. Inline fifth-object/list/hash initialization and original empty-vector resize execute unchanged. Four nested constructors, resource lookup, refresh and allocator remain controlled; internal allocations succeed. This does not prove actual null-parent acceptance or complete dialog/widget/layout/resource construction. Opening/Alt, live viewer and paired GPU evidence remain unfinished. The callback-list receiver review keeps shares unchanged: 72 original combined sequences (576 whole141149460 appends and360 base teardowns) match list next/previous/count fields, all live wrapper parameters/ordered peer sets and allocation/free sizes/counts. Appending copies now composes the recovered callback-link model; retained copies survive temporary-source removal and detach when original containers are destroyed. Allocator/free are controlled and custom callables null. Internal callback-tree bytes/free-pointer order and actual child1410d7490 refresh/composition remain unverified; no complete dialog/viewer or paired visual claim. The third-child constructor review keeps shares unchanged: 108 two-child sequences/216 complete original1410d7490 calls match full96-byte objects,120-byte base sentinels, raw allocation/refresh snapshots, parent list fields, logical callback sets and allocation/free request order. Original bound ctor/copy/list append/temporary teardown bodies execute unchanged; refresh/allocator/free are controlled. Parent+58 is reloaded after controlled refresh, retained copies survive temporary cleanup, and a source adapter plus ordinary test connects kind2 to the outer factory. Callback-tree heap bytes, actual refresh, remaining children, combined native whole-factory heap replay and live viewer/paired pixels remain unverified. The context-refresh caller review keeps shares unchanged: 972 whole original1411396d0 executions match full object/global/listener snapshots at service entries and completion, ordered arguments/requests, engine/global gate reloads, Zulu/day overrides, exact float conversion/clamps/two divisions and post-callback next/head reloads. Inline/heap/aligned option cleanup and NaN/infinity/day2^31 boundaries are covered. Engine/context/option lookup/CRT parsing/time conversion/free/notification bodies remain controlled; this does not establish actual textual parsing/calendar/runtime equivalence. An ordinary child-constructor integration invokes the recovered refresh; combined original constructor/factory replay, remaining children/full dialog, live viewer and paired GPU evidence remain unfinished. The combined child-refresh review keeps shares unchanged: 972 original child1410d7490 executions now include the actual original refresh1411396d0 and callback ctor/bind/list/copy/temporary teardown in one run. Final object/base bytes, allocation/refresh boundaries, leaf object/global/listener snapshots, parent list/logical callback state and ordered requests match. Only leaf providers/CRT/time conversion/allocator/free remain controlled; fresh observer lists and valid stable parents apply. Callback-tree heap bytes and complete provider/factory/dialog/viewer behavior remain unverified. The standalone972 corpus rows are unchanged after shared-harness extraction. This improves composition evidence without a new production or visual parity claim. The second-child construction review keeps shares unchanged: 920 complete original1410d6fc0 executions match full0x2d0 object/base/record-sentinel bytes, raw allocation/provider snapshots, catalog clamping/reloads, global interface links and parent/list/logical callback state. Original nested data initializer, empty clear, variant/equality/assignment/inline optional cleanup and callback/list bodies execute unchanged. There are27 alternate/853 changed/40 equal-skip cases and1201 retained copies. Property/config/effect/allocator bodies remain controlled; stable nonempty catalogs, valid tags/parents and successful allocations apply. Kind1 adapter and ordinary second-to-third receiver integration exist; native whole-factory composition, heap optional cleanup, actual providers/full dialog/viewer/paired pixels remain unverified. First child1410d6a40 now has192 whole native comparisons of object/all seven blocks and every service-entry snapshot; allocator and refresh14113a300/141138cf0 remain controlled. Shared record initializer extraction retains920-case selection evidence; ordinary root/selection/context receiver integration is source-only, not native full-factory or GPU evidence. See research/UI_DIALOG_CHILD_ROOT.md. Estimates reviewed and unchanged; original Alt/Esc and paired captures remain unverified. Fourth child1410d75a0 now matches720 whole native runs: raw weather-record initialization/copying, saved first/reloaded second parent, retained callbacks and temporary teardown. Weather/altitude/selection/refresh/special providers remain controlled; callback RB bytes and live GPU remain unverified. Ordinary source integration joins all four child adapters; native composed factory remains pending. See research/UI_DIALOG_CHILD_WEATHER.md. Estimates reviewed and unchanged. Nested root refresh14113a300 now matches432 whole native runs covering mutable item-vector traversal, engine/resource gates, temporary free/optional-cleanup order and live listeners.192 combined root-constructor runs also execute original nested refresh under engine0/fresh lists. Leaf providers/effects and final root refresh141138cf0 remain controlled; no full factory/GPU evidence. See research/UI_NESTED_REFRESH.md. Estimates reviewed and unchanged. Payload assignment1410faec0, optional string move1405de290 and vector move/growth1410fa780/1408b0660 match720 whole native cases including self-alias, heap/aligned-string release and vector growth.432 nested-refresh compositions include actual assignment in27 reached branches under inline-buffer profiles; providers/free/memcpy remain scoped dependencies. Final root refresh141138cf0 remains unported. See research/UI_PAYLOAD_MOVE.md. Estimates reviewed and unchanged; no GPU/visual evidence. Final root refresh141138cf0 outer body now matches118 whole native runs: resource/configuration and fallback branches, string/vector caller ownership, one-time retained callbacks, count/refill and live notifications. Leaf parsing/provider/effect bodies, including nested refresh in this corpus, remain controlled. Logical callback bodies execute originally; no full constructor/factory/GPU composition claim. See research/UI_ROOT_REFRESH.md. Estimates reviewed and unchanged. Root141138cf0 + actual nested14113a300 + payload1410faec0/string/vector helpers now match118 whole composed native runs.17 cases reach payload assignment; combined payload storage is inline. Root and nested listeners share live memory/global/index state;322 notifications match. Earlier118 independent corpus rows regenerate byte-for-byte. Remaining leaf computations and full constructor/factory/GPU integration remain unverified. See research/UI_REFRESH_CHAIN.md. Estimates reviewed and unchanged. Whole fresh root constructor1410d6a40 now matches118 native runs containing both actual nested14113a300 invocations, final root141138cf0 and payload/string/vector helpers. All seven constructor allocations, raw declared memory/global/index state, live provider operands and final receiver links/logical callback peers match.34 reached inline payload assignments and354 engine checks are covered; all receiver lists start fresh. Callback RB backing, remaining leaf computations and full factory/dialog/viewer/GPU integration remain unverified. See research/UI_ROOT_CONSTRUCT_CHAIN.md. Estimates reviewed and unchanged; no paired visual evidence. Whole child factory1410d6ca0 now matches216 native runs with all four original constructors and inline fifth-object/hash initialization executing in one call. Raw declared heap/bundle snapshots at outer allocations and each child return, constructor allocation/leaf boundaries, all receiver links/counts and the combined callback graph match.972 retained entries share actual prior child receivers. Refresh/provider effects remain controlled here; full-factory composition with actual recovered refreshes, callback RB backing, dialog/layout/menu/viewer/GPU remain pending. See research/UI_FACTORY_COMPOSED.md. Estimates reviewed and unchanged. Whole factory1410d6ca0 now matches118 native calls with all four constructors plus actual root141138cf0, both nested14113a300 calls and payload/string/vector helpers. Shared-state composition exposed and fixed selection-child resource lookup: it reloads global142640504 after the engine gate instead of using0;34 calls use index88 and11 use77.649 retained callback entries and declared heap/list state match;34 actual inline payload assignments are reached. Other child/fifth refresh and leaf providers remain controlled; callback RB backing, full dialog/menu/viewer/GPU remain unverified. See research/UI_FACTORY_ROOT_REFRESH_CHAIN.md. Estimates reviewed and unchanged. Whole factory1410d6ca0 now matches118 native calls containing all four constructors, actual root/nested/payload chain and actual context refresh1411396d0. Shared global/index, contextual Zulu/day arithmetic, inline/heap/aligned string cleanup and649 retained entries match. Context refresh also reloads shared142640504 after the engine gate (34 lookups at88,11 at77); an indexed image bridge now carries it.34 alternate/84 default branches,82 parses and52 frees execute. Context leaf computations/CRT, selection/weather/fifth refresh/providers, callback RB backing and full dialog/menu/viewer/GPU remain unverified. See research/UI_FACTORY_ROOT_CONTEXT_REFRESH.md. Estimates reviewed and unchanged. Fifth refresh141139460 and hash-clear14062b900 dispatcher/bulk path now match528 whole native cases, including cached-next cleanup, sentinel reloads, pointer-vector append/grow callers, override bits and live notifications. Sparse range erase and other provider bodies remain controlled.118 whole factory calls now execute all four constructors plus actual root/nested/payload/context/fifth refreshes and preserve649 retained entries. Fifth collection/sort has34 reached branches;59 payload branches and17 mark lookups are checked. See research/UI_FIFTH_REFRESH.md. Selection/weather refresh and remaining providers, callback RB backing, full dialog/menu/viewer/GPU remain unverified. Estimates reviewed and unchanged. Payload-availability predicate14113b9a0 now executes by default in ui_fifth_refresh and matches528 original fifth-refresh compositions. It repeats engine/global/resource gating, reloads shared index after providers and tests settings+dac as32-bit zero.118 whole factory calls include this actual predicate and the same settings record/word used by root; returned identity and inherited bytes are checked.17 fifth payload branches are reached. Engine/resource/settings lookups and remaining provider/selection/weather/dialog/GPU behavior stay controlled or unverified. See research/UI_FIFTH_PAYLOAD_GATE.md. Earlier528/118 controlled-predicate corpora are unchanged and retain explicit legacy scope. Estimates reviewed and unchanged. Resource/settings accessors141a64260/141a64250 are now ported as signed-low32, wrapping64 address calculations (strides0x6668/0x433c0).872 original no-stub cases match full RAX. Fifth refresh defaults now use mapped real table descriptors;528 composed fifth cases execute original getters, including base changes and distinct adjacent cells.118 whole factory calls execute actual fifth getters plus constructor resource index20, preserving shared root descriptors/word and649 retained entries. Root/selection/context getter bodies and registry loading remain controlled; other dependencies/full dialog/live GPU remain unverified. See research/UI_INDEXED_RECORDS.md. Earlier controlled-getter corpora retain their scope. Estimates reviewed and unchanged. Read-only query1417fb320 now runs by default inside fifth refresh/predicate.768 original full-RAX/no-write comparisons plus528 fifth/118 factory compositions verify it, with1056/236 actual query returns and15 intervening controlled byte changes. Engine-byte production/meaning/lifetime, other callers, registry loading, selection/weather providers, complete dialog/viewer/GPU and paired pixels remain unverified. See research/UI_ENGINE_QUERY.md. Estimates reviewed and unchanged. Root/nested indexed lookups now use production defaults and match118 complete original factories:226 resource returns at5/77/88 and46 settings returns at88, with valid distinct full32-byte strings. All20 array input regions inherit into fifth and649 retained entries match. Actual index flow yields23 fifth sorts/11 payload assignments. Selection/context getter bodies and other providers/registry production/full dialog/live GPU remain controlled or unverified. See research/UI_ROOT_RECORD_TABLES.md. Estimates reviewed and unchanged. Selection/context indexed presence now uses the production mapped helper and Result API/provider defaults.118 complete original factories execute45 actual resource returns per caller (23 at88/22 at77), with45 selection getter-entry byte/map checks and118 context input maps matching20 inherited regions. Context takes23 alternate/95 default paths;649 retained entries match. Engine/query-byte/registry production, remaining selection/weather/providers, complete dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_CHILD_RECORD_TABLES.md. Estimates reviewed and unchanged. Whole weather refresh141139fe0 now matches384 complete original calls: actual engine/getters, live settings/index,424-byte overlapping record copies and575 notifications.118 complete factories execute this actual refresh too, matching20 inherited input regions and649 retained entries across79 reset/11 resource/28 default paths. Weather/context/CLI/notification providers, data producers/lifetime, remaining selection/full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_WEATHER_REFRESH.md. Estimates reviewed and unchanged. Selection changed14113ba10 now matches348 complete original calls with547 notification requests, including live node appends/head reloads and callback-preserved dirty values.118 complete factories execute95 actual change bodies, preserving fresh sentinel bytes and removing48 synthetic second-parent registrations;601 retained entries match instead of the earlier controlled-cohort649. Alternate/other selection and actual notify/effect bodies, data producers/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_CHANGED.md. Estimates reviewed and unchanged. Whole selection alternate14111bb90 now matches528 complete original calls across both major paths/all valid tags,1324 actual settings returns, live vector/result reloads and aligned free/cleanup operands.118 complete factories execute23 actual alternate and95 actual changed bodies;590 retained entries match without either opaque parent-rebinding endpoint. Search/data/cleanup and real state/scratch producers, reset/final, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_ALTERNATE.md. Estimates reviewed and unchanged. Reset predicates14114d330/14113fff0 now match1536 complete native gate calls with897 actual engine and752 actual primary/getter returns,635 controlled memcmp and518 secondary requests. Cached receiver, late flag, signed indices and declared memory match;768 original no-stub tag-query1417fb390 cases match full RAX and unchanged receivers. Whole reset/final and constructor/factory binding, real secondary/CRT/state production, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RESET_GATE.md. Estimates reviewed and unchanged. Whole selection reset14113a460 now matches528 completed original calls with actual gate/query/tag/primary/getter, aliasable strings/variants, fresh catalog base,327 assignments/200 fallbacks/817 notifications and controlled tail finish. Main-owned scratch and every provider boundary match. A fallible reset_checked constructor seam exists, but actual-reset constructor/factory composition, initial callback/finish and other provider bodies, producers/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RESET.md. Estimates reviewed and unchanged. Actual selection reset14113a460 now composes in118 whole original factories, including both explicit controlled finish requests,236 actual queries and64 primary/getter/tag returns. Current source callback/list state publishes before reset; prior parent memory, both sentinels,20 input table regions, globals/index/catalog and590 retained entries match.70 assignments/52 fallbacks/8 cleanups/91 frees execute; lists are fresh/empty; reset-entry+c0 is0 in95 cases and1 in23. No early skip is reached, so standalone notification/early-skip proofs retain their separate scope. Initial/finish/provider bodies, true data production/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_FACTORY_SELECTION_RESET.md. Estimates reviewed and unchanged. Whole initial callback1410fe0f0 now matches712 native calls and768 no-stub helper pairs. Actual tag/payload defaults, live parent/float stores, cached payload versus scratch reloads, flag clear and recursive requests match.528 actual callback/reset and118 whole-factory compositions also pass, with590 retained entries and329 controlled finish requests in the factory cohort. Recursive reset bodies remain controlled in55/11 composed requests; real predicates/float/finish/cleanup/producers, full dialog/menu/viewer/GPU and paired captures remain unverified. Prior reset-only+c0 wording is corrected from95 zero/23 one input snapshots. See research/UI_SELECTION_INITIAL.md. Estimates reviewed and unchanged. Recursive reset14113a460 now executes actual callback/reset bodies:528 outer calls include55 actual nested resets;118 whole factories include11, preserving590 retained entries and all inherited maps. Native/source LIFO frame restoration and full provider boundaries match; factory query/gate/getter counts are258/129/75, and351 finish requests remain controlled. A new replay exposed extra catalog validation: it is replaced by original signed64 division/wrapping-low32 comparison and independently matches504 boundary cases. Depth2 is observed only for these synthetic profiles; arbitrary recursion, real finish/predicate/float/provider/producer/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RECURSIVE_RESET.md. Estimates reviewed and unchanged.
Audio, weather, multiplayer, plugins 7 0% 0% Not started.
Platforms and distribution 6 50% 0% CI on Linux, macOS and Windows, nightly builds, standard folder layout. No launcher or settings UI.

Roadmap

  1. Content without simulation (mostly done): ACF, OBJ8, AFL, apt.dat and the viewer work. Left: PANEL_3D, normal/lit maps, instruments, an apt.dat index. Verification work: turn the diagnostic ACF object comparison into enforced checks over explicitly supported fields, keep local reference diagnostics explicitly opt-in, and resolve differences against completed loader fixtures.
  2. Datarefs and commands (in progress): Registries and original catalogs exist. Left: values for the other 5497 datarefs, command handlers, wiring to the aircraft state. Complete command block-mask query now has 6418 local comparisons, including all 3138 IDs; recover mask lifecycle and full callback dispatch next. Full Begin/End executor now has 1768 native comparisons, including observer mutations and primary replacement; real callback construction/effects and live integration remain unfinished. Native Continue extends the comparison to 2152 combined phase cases; held scheduling and actual callback effects remain unfinished.
  3. Flight model (in progress): Recovered profile, delta-wing, engine, propeller, contact and flight-step kernels exist with original-code comparisons. The approximate viewer now uses the delta branch and ordered wing grouping. The complete boundary coordinate loop and point transform now have original-code comparisons and run with static live inputs. Next: recover dynamic geometry state and full reference bounds, then connect the recovered curvature setup, original noise initialization and per-strip airflow; connect the remaining recovered force, propulsion and contact blocks into the runtime, then compare complete trajectories. Active rib chord values now come from ACF using the recovered conversion, and all 48 wing slots are scanned; dynamic geometry updates and force-arm/normal construction remain incomplete. Recovered body/gear point-list passes narrow the reference-bounds gap; propeller point production is now recovered too. The ordered main point vector and bounds reducer now match a single original-code pass on synthetic state. Next recover runtime body-grid and propeller field preparation, auxiliary outputs and the live geometry update schedule. Body-grid unit conversion now has exact checks on three real aircraft; runtime inclusion, normal generation and geometry scheduling remain work.
  4. World (started): Airport ground from apt.dat. Left: DSF terrain, library objects, lights, start locations, weather.
  5. Cockpit and systems (planned): Instruments, panels, the stock Cessna's Lua scripts and controls.
  6. Original UI and graphics fidelity (started): Whole-game X-Plane 12 UI/graphics parity remains unproven. Available local resources: 25 menu textures and 12 fonts. Recovered input/state includes all 182 default chords, keyboard/UI gates, focused dispatch, window classification/opacity, focus transitions and complete command phases. The supplied Windows XPLM key hook now has 1090 local native comparisons; the missing-file pause is resolved, and 2152 paired CPU cases now execute EXE/DLL keyboard routing together; real module initialization and release-build pairing remain unproven. Left: actual TLS/module initialization and callback-list lifecycle, show_menu/Alt actions and widget registration, live viewer integration, original layout/font roles/GPU rendering and matched screenshots/GIF/video. The viewer still exits on Esc and renders no original menu; service-boundary replays are not pixel evidence. SDK context/activation now has 1108 native cases and runs unchanged in hook/paired tests on ready TLS; actual initialization/module lifecycle remains unfinished. Effective owner lookup through zero context frames now matches 1657 native stacks. Deferred services validate/drain deletions/validate; standalone queue mutation now has 1704 native comparisons for sniffer/hotkey deletion, with diagnostic/tracking/clock/free services controlled. Sniffer registration/unregistration now has 1126 native scenarios and connects to deferred deletion. Registered token-based sniffer phases 0/2 now match 524 native mutable event scenarios, including callback API calls and context-sensitive deletion order. 528 additional combined EXE/DLL cases now verify actual registrations/list mutation across keyboard routing, including callback mode/block gates. Hotkey/window registration and real loader/viewer/widget lifetime integration remain unfinished. Kind-11 construction now identifies the concrete menu panel; its own Esc/Return handler has 1940 native contexts for own/focused paths. Fallback effects and live creation/focus/layout remain unfinished. Concrete fallback request flow now matches 746 direct/own/focused contexts; property2 and empty-wrapper lifecycle are original. Real direct/submission/construction effects and pixels remain unverified. Direct action 0x140f0a2c0 now has 694 native control-flow cases with guard/state stores and kind-11 close requests; concrete close/map/document/dialog effects are still pending. Close helper now has 574 native registered-window contexts, including actual kind-map clearing and post-close query. Renderer/delete/update bodies and complete route integration remain pending. The window-order review keeps shares unchanged: 700 native combined extraction/reinsertion cases verify first-token removal and signed classification ordering, including duplicate identities and low-byte flag semantics. Only allocation/free endpoints are controlled; malformed lists, full visibility effects, viewer integration and matched pixels remain unverified. The visibility-state review keeps shares unchanged: 728 two-call scenarios (1456 native executions) now verify complete show/hide control flow, registry ordering, manager-membership insertion/removal, entry+0x88 and leaf-alpha stores. Owner/preparation/activation/reparent/refresh/event bodies remain controlled, listeners are empty and manager identity is stable. Whole menu route integration, mutable listeners and original GPU/pixel evidence remain incomplete. The widget-tree review keeps shares unchanged: 744 original reparent cases and 744 standalone dirty cases verify ordered child erase/append, parent stores, callback field reloads and full 32-bit new-bit propagation. Binding/parent callbacks and CRT copying are controlled; spare vector capacity, finite chains and stable lifetime are required. Shared visibility ancestry, complete focus effects, renderer and paired visual evidence remain unfinished. The shared-window-graph review keeps shares unchanged: 728 three-action sequences (2184 original visibility executions, including 728 toggle wrappers) now compose show/hide and actual reparent/dirty stores on one ancestry graph, comparing native visibility after each action. Remaining effect bodies and parent callbacks are controlled, listeners empty and identities stable. Complete close/menu routing, original rendering and paired pixels remain unverified. The graph-backed close review keeps shares unchanged: 728 two-call scenarios execute 1456 complete native close helpers and reach 367 real visibility calls, verifying registered getter/mode/toggle/reparent/dirty/map-store composition and post-close queries. Update/reset/delete/environment/final and remaining window effects are controlled; empty observer/protected/listener lists and stable lifetimes apply. Direct/fallback/focused menu integration and matched GPU visuals remain unproven. The combined direct-close replay leaves shares unchanged: 728 two-action scenarios execute 1456 original direct handlers, 1092 real close helpers and 252 visibility bodies on one graph, comparing panel/map/ancestry and post-action queries. This profile is argument0/UI mode0 or2; mode1 document/dialog, fallback/own/focused Esc and actual construction/rendering remain unverified. Remaining effects are controlled; no paired pixels exist. The document/dialog composition review leaves shares unchanged: the same 728 two-action scenarios now cover UI modes0/1/2 with real graph-close and original wrapper lifecycle. 244 controlled document/load requests, 48 load failures and 168 dialog construction/destruction requests match complete request/cleanup order and global-byte stores. Actual document/dialog/binding bodies remain controlled; fallback/own/focused Esc, real construction and paired rendering remain unverified. The combined fallback graph replay leaves shares unchanged: 728 two-action scenarios execute 1456 original fallbacks, 938 reached direct actions, 927 real close helpers and 220 visibility bodies. Both empty/bound wrapper lifecycles, independent queries/engine mutation and every fallback route now compose with actual graph state. Effect bodies remain controlled; own/focused Esc entry, real widget construction/lifetime and paired GPU evidence are still incomplete. The concrete key-graph review leaves shares unchanged: 728 own/focused sequences execute 1456 native key entries, 318 direct actions, 318 real close helpers and 73 visibility bodies, matching consumed bytes and full shared state/requests. Focus is pinned, child absent and effects controlled; real construction/focus, show_menu opening/Alt, viewer and paired pixels remain unproven. The focus-binding review leaves shares unchanged: 1045 native whole-helper scenarios verify owner/selected links, matching-focus blur, post-callback owner reloads, conditional ancestor clearing and final requested-owner store. Virtual callback bodies are controlled and finite stable graphs required. Shared window/key integration, real focus/construction, opening/Alt and paired rendering remain unfinished. The focus/menu composition review leaves shares unchanged: ordinary integration tests now replace binding endpoints with the recovered owner/selected helper, read actual focus state for subsequent keys and preserve child-before-filter consumption. Global focus loss is a controlled blur effect. There is no combined original replay for this new composition yet; other widget classes, real construction/effects, opening/Alt and paired rendering remain unproven. The combined mutable-focus replay leaves shares unchanged: 728 original own/focused sequences execute 1456 key entries, 300 real closes, 72 visibility bodies and 144 original owner-binding calls on shared state. Owner/selected/global-focus links and subsequent routing match, with 16 blur/25 stop callbacks and one asserted nonzero stop. Virtual callbacks/effects remain controlled; construction/lifetime, opening/Alt, viewer and paired pixels remain unproven. The input-constructor review leaves shares unchanged: 64 poisoned inline-name cases compare the whole original input-node base/callback/string constructors, exact object/source/sentinel bytes and four allocator snapshots. Allocation order and transient fields are recovered. Heap names, outer panel/geometry construction, lifetime and live factory/rendering remain unverified; input name+60 must not be confused with widget parent+60. The common-panel constructor review leaves shares unchanged: 256 original nested ctor cases verify complete object/source/sentinel bytes, four allocation snapshots, class/interface stages and raw168/169/16a flags. Getter state now derives from constructor fields. This remains an inline-string raw initialization model; localized/heap strings, concrete main-menu child/layout/resource construction, live factory and paired rendering are unfinished. The menu-member construction review leaves shares unchanged: 180 complete original member/capture/registration/vector-growth cases verify exact member/backing bytes, ordering and capacities, including empty/full/spare vectors. Allocation/free/CRT-copy endpoints are controlled and small valid vectors apply. Global interface linkage, concrete panel/singleton/layout/resource creation, callable bodies and paired visuals remain unfinished. The global interface-chain review leaves shares unchanged: 210 complete original ctor/destructor sequences verify head insertion, neighbor relinking, retained detached links, table restoration and bit0-only sized-free requests. Free remains controlled; valid stable chains are required. Concrete panel composition/teardown, callback lifecycle and paired renderer evidence remain unfinished. The 2026-10-15 concrete-menu prefix review leaves shares unchanged: 480 original executions from0x140ecb340 to asserted RIP0x140ecb592 match full object/allocation snapshots, global interface linkage, three embedded-member registrations, vector growth and successful/null optional callback allocation. This composes the common/input/member/interface constructors; 710 earlier native constructor cases pass again after shared-helper extraction. Translation and allocator/free/CRT endpoints are controlled, inline strings and small valid registries apply. The stop is before singleton dialogs, not normal constructor return. Remaining dialogs/children/layout/resources, heap strings/full teardown, opening ID3/Alt, live viewer and paired GPU screenshots/GIF/video remain unverified. The bound-callback lifecycle review keeps shares unchanged: 324 original sequences (5832 ctor/copy/bind/base-teardown calls) match live identities, full-width wrapper parameters, ordered reciprocal links and allocation/free sizes/counts. Copies retain registration after temporary destruction, and source removal detaches surviving wrappers. Allocator/free are controlled and custom callables null; native red-black node bytes and free-pointer order are not modeled. Real dialog140ec9c10 copies these wrappers at+1f8/+260, but complete dialog/resource/layout construction and heap-string support remain unfinished. This logical connection comparison is not whole-object/heap-byte or paired visual evidence. The heap-string constructor review keeps shares unchanged: 324 complete original common/wrapper/input/callback/string ctor cases match all panel/source/allocated bytes and exact allocation/free order with full panel snapshots. Mixed inline/heap sources, spare capacity, embedded zeros, length15/16 and 4096-byte aligned-allocation boundaries are covered. Constructor-argument ownership cleanup now composes with the common panel; the earlier64 input/256 common/480 concrete-prefix replays still pass. Allocator/free/CRT copy are controlled; failure/overflow, reentrancy, actual dialog translation/children/layout/resources/full teardown and live viewer/paired pixels remain unverified. The dialog child-factory review keeps shares unchanged: 576 whole original1410d6ca0 executions match full bundle/heap snapshots at every allocator/constructor/resource/refresh entry and final bytes, covering all32 external allocation-null masks, distinct constructor return pointers and opaque resource values. Inline fifth-object/list/hash initialization and original empty-vector resize execute unchanged. Four nested constructors, resource lookup, refresh and allocator remain controlled; internal allocations succeed. This does not prove actual null-parent acceptance or complete dialog/widget/layout/resource construction. Opening/Alt, live viewer and paired GPU evidence remain unfinished. The callback-list receiver review keeps shares unchanged: 72 original combined sequences (576 whole141149460 appends and360 base teardowns) match list next/previous/count fields, all live wrapper parameters/ordered peer sets and allocation/free sizes/counts. Appending copies now composes the recovered callback-link model; retained copies survive temporary-source removal and detach when original containers are destroyed. Allocator/free are controlled and custom callables null. Internal callback-tree bytes/free-pointer order and actual child1410d7490 refresh/composition remain unverified; no complete dialog/viewer or paired visual claim. The third-child constructor review keeps shares unchanged: 108 two-child sequences/216 complete original1410d7490 calls match full96-byte objects,120-byte base sentinels, raw allocation/refresh snapshots, parent list fields, logical callback sets and allocation/free request order. Original bound ctor/copy/list append/temporary teardown bodies execute unchanged; refresh/allocator/free are controlled. Parent+58 is reloaded after controlled refresh, retained copies survive temporary cleanup, and a source adapter plus ordinary test connects kind2 to the outer factory. Callback-tree heap bytes, actual refresh, remaining children, combined native whole-factory heap replay and live viewer/paired pixels remain unverified. The context-refresh caller review keeps shares unchanged: 972 whole original1411396d0 executions match full object/global/listener snapshots at service entries and completion, ordered arguments/requests, engine/global gate reloads, Zulu/day overrides, exact float conversion/clamps/two divisions and post-callback next/head reloads. Inline/heap/aligned option cleanup and NaN/infinity/day2^31 boundaries are covered. Engine/context/option lookup/CRT parsing/time conversion/free/notification bodies remain controlled; this does not establish actual textual parsing/calendar/runtime equivalence. An ordinary child-constructor integration invokes the recovered refresh; combined original constructor/factory replay, remaining children/full dialog, live viewer and paired GPU evidence remain unfinished. The combined child-refresh review keeps shares unchanged: 972 original child1410d7490 executions now include the actual original refresh1411396d0 and callback ctor/bind/list/copy/temporary teardown in one run. Final object/base bytes, allocation/refresh boundaries, leaf object/global/listener snapshots, parent list/logical callback state and ordered requests match. Only leaf providers/CRT/time conversion/allocator/free remain controlled; fresh observer lists and valid stable parents apply. Callback-tree heap bytes and complete provider/factory/dialog/viewer behavior remain unverified. The standalone972 corpus rows are unchanged after shared-harness extraction. This improves composition evidence without a new production or visual parity claim. The second-child construction review keeps shares unchanged: 920 complete original1410d6fc0 executions match full0x2d0 object/base/record-sentinel bytes, raw allocation/provider snapshots, catalog clamping/reloads, global interface links and parent/list/logical callback state. Original nested data initializer, empty clear, variant/equality/assignment/inline optional cleanup and callback/list bodies execute unchanged. There are27 alternate/853 changed/40 equal-skip cases and1201 retained copies. Property/config/effect/allocator bodies remain controlled; stable nonempty catalogs, valid tags/parents and successful allocations apply. Kind1 adapter and ordinary second-to-third receiver integration exist; native whole-factory composition, heap optional cleanup, actual providers/full dialog/viewer/paired pixels remain unverified. First child1410d6a40 now has192 whole native comparisons of object/all seven blocks and every service-entry snapshot; allocator and refresh14113a300/141138cf0 remain controlled. Shared record initializer extraction retains920-case selection evidence; ordinary root/selection/context receiver integration is source-only, not native full-factory or GPU evidence. See research/UI_DIALOG_CHILD_ROOT.md. Estimates reviewed and unchanged; original Alt/Esc and paired captures remain unverified. Fourth child1410d75a0 now matches720 whole native runs: raw weather-record initialization/copying, saved first/reloaded second parent, retained callbacks and temporary teardown. Weather/altitude/selection/refresh/special providers remain controlled; callback RB bytes and live GPU remain unverified. Ordinary source integration joins all four child adapters; native composed factory remains pending. See research/UI_DIALOG_CHILD_WEATHER.md. Estimates reviewed and unchanged. Nested root refresh14113a300 now matches432 whole native runs covering mutable item-vector traversal, engine/resource gates, temporary free/optional-cleanup order and live listeners.192 combined root-constructor runs also execute original nested refresh under engine0/fresh lists. Leaf providers/effects and final root refresh141138cf0 remain controlled; no full factory/GPU evidence. See research/UI_NESTED_REFRESH.md. Estimates reviewed and unchanged. Payload assignment1410faec0, optional string move1405de290 and vector move/growth1410fa780/1408b0660 match720 whole native cases including self-alias, heap/aligned-string release and vector growth.432 nested-refresh compositions include actual assignment in27 reached branches under inline-buffer profiles; providers/free/memcpy remain scoped dependencies. Final root refresh141138cf0 remains unported. See research/UI_PAYLOAD_MOVE.md. Estimates reviewed and unchanged; no GPU/visual evidence. Final root refresh141138cf0 outer body now matches118 whole native runs: resource/configuration and fallback branches, string/vector caller ownership, one-time retained callbacks, count/refill and live notifications. Leaf parsing/provider/effect bodies, including nested refresh in this corpus, remain controlled. Logical callback bodies execute originally; no full constructor/factory/GPU composition claim. See research/UI_ROOT_REFRESH.md. Estimates reviewed and unchanged. Root141138cf0 + actual nested14113a300 + payload1410faec0/string/vector helpers now match118 whole composed native runs.17 cases reach payload assignment; combined payload storage is inline. Root and nested listeners share live memory/global/index state;322 notifications match. Earlier118 independent corpus rows regenerate byte-for-byte. Remaining leaf computations and full constructor/factory/GPU integration remain unverified. See research/UI_REFRESH_CHAIN.md. Estimates reviewed and unchanged. Whole fresh root constructor1410d6a40 now matches118 native runs containing both actual nested14113a300 invocations, final root141138cf0 and payload/string/vector helpers. All seven constructor allocations, raw declared memory/global/index state, live provider operands and final receiver links/logical callback peers match.34 reached inline payload assignments and354 engine checks are covered; all receiver lists start fresh. Callback RB backing, remaining leaf computations and full factory/dialog/viewer/GPU integration remain unverified. See research/UI_ROOT_CONSTRUCT_CHAIN.md. Estimates reviewed and unchanged; no paired visual evidence. Whole child factory1410d6ca0 now matches216 native runs with all four original constructors and inline fifth-object/hash initialization executing in one call. Raw declared heap/bundle snapshots at outer allocations and each child return, constructor allocation/leaf boundaries, all receiver links/counts and the combined callback graph match.972 retained entries share actual prior child receivers. Refresh/provider effects remain controlled here; full-factory composition with actual recovered refreshes, callback RB backing, dialog/layout/menu/viewer/GPU remain pending. See research/UI_FACTORY_COMPOSED.md. Estimates reviewed and unchanged. Whole factory1410d6ca0 now matches118 native calls with all four constructors plus actual root141138cf0, both nested14113a300 calls and payload/string/vector helpers. Shared-state composition exposed and fixed selection-child resource lookup: it reloads global142640504 after the engine gate instead of using0;34 calls use index88 and11 use77.649 retained callback entries and declared heap/list state match;34 actual inline payload assignments are reached. Other child/fifth refresh and leaf providers remain controlled; callback RB backing, full dialog/menu/viewer/GPU remain unverified. See research/UI_FACTORY_ROOT_REFRESH_CHAIN.md. Estimates reviewed and unchanged. Whole factory1410d6ca0 now matches118 native calls containing all four constructors, actual root/nested/payload chain and actual context refresh1411396d0. Shared global/index, contextual Zulu/day arithmetic, inline/heap/aligned string cleanup and649 retained entries match. Context refresh also reloads shared142640504 after the engine gate (34 lookups at88,11 at77); an indexed image bridge now carries it.34 alternate/84 default branches,82 parses and52 frees execute. Context leaf computations/CRT, selection/weather/fifth refresh/providers, callback RB backing and full dialog/menu/viewer/GPU remain unverified. See research/UI_FACTORY_ROOT_CONTEXT_REFRESH.md. Estimates reviewed and unchanged. Fifth refresh141139460 and hash-clear14062b900 dispatcher/bulk path now match528 whole native cases, including cached-next cleanup, sentinel reloads, pointer-vector append/grow callers, override bits and live notifications. Sparse range erase and other provider bodies remain controlled.118 whole factory calls now execute all four constructors plus actual root/nested/payload/context/fifth refreshes and preserve649 retained entries. Fifth collection/sort has34 reached branches;59 payload branches and17 mark lookups are checked. See research/UI_FIFTH_REFRESH.md. Selection/weather refresh and remaining providers, callback RB backing, full dialog/menu/viewer/GPU remain unverified. Estimates reviewed and unchanged. Payload-availability predicate14113b9a0 now executes by default in ui_fifth_refresh and matches528 original fifth-refresh compositions. It repeats engine/global/resource gating, reloads shared index after providers and tests settings+dac as32-bit zero.118 whole factory calls include this actual predicate and the same settings record/word used by root; returned identity and inherited bytes are checked.17 fifth payload branches are reached. Engine/resource/settings lookups and remaining provider/selection/weather/dialog/GPU behavior stay controlled or unverified. See research/UI_FIFTH_PAYLOAD_GATE.md. Earlier528/118 controlled-predicate corpora are unchanged and retain explicit legacy scope. Estimates reviewed and unchanged. Resource/settings accessors141a64260/141a64250 are now ported as signed-low32, wrapping64 address calculations (strides0x6668/0x433c0).872 original no-stub cases match full RAX. Fifth refresh defaults now use mapped real table descriptors;528 composed fifth cases execute original getters, including base changes and distinct adjacent cells.118 whole factory calls execute actual fifth getters plus constructor resource index20, preserving shared root descriptors/word and649 retained entries. Root/selection/context getter bodies and registry loading remain controlled; other dependencies/full dialog/live GPU remain unverified. See research/UI_INDEXED_RECORDS.md. Earlier controlled-getter corpora retain their scope. Estimates reviewed and unchanged. Read-only query1417fb320 now runs by default inside fifth refresh/predicate.768 original full-RAX/no-write comparisons plus528 fifth/118 factory compositions verify it, with1056/236 actual query returns and15 intervening controlled byte changes. Engine-byte production/meaning/lifetime, other callers, registry loading, selection/weather providers, complete dialog/viewer/GPU and paired pixels remain unverified. See research/UI_ENGINE_QUERY.md. Estimates reviewed and unchanged. Root/nested indexed lookups now use production defaults and match118 complete original factories:226 resource returns at5/77/88 and46 settings returns at88, with valid distinct full32-byte strings. All20 array input regions inherit into fifth and649 retained entries match. Actual index flow yields23 fifth sorts/11 payload assignments. Selection/context getter bodies and other providers/registry production/full dialog/live GPU remain controlled or unverified. See research/UI_ROOT_RECORD_TABLES.md. Estimates reviewed and unchanged. Selection/context indexed presence now uses the production mapped helper and Result API/provider defaults.118 complete original factories execute45 actual resource returns per caller (23 at88/22 at77), with45 selection getter-entry byte/map checks and118 context input maps matching20 inherited regions. Context takes23 alternate/95 default paths;649 retained entries match. Engine/query-byte/registry production, remaining selection/weather/providers, complete dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_CHILD_RECORD_TABLES.md. Estimates reviewed and unchanged. Whole weather refresh141139fe0 now matches384 complete original calls: actual engine/getters, live settings/index,424-byte overlapping record copies and575 notifications.118 complete factories execute this actual refresh too, matching20 inherited input regions and649 retained entries across79 reset/11 resource/28 default paths. Weather/context/CLI/notification providers, data producers/lifetime, remaining selection/full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_WEATHER_REFRESH.md. Estimates reviewed and unchanged. Selection changed14113ba10 now matches348 complete original calls with547 notification requests, including live node appends/head reloads and callback-preserved dirty values.118 complete factories execute95 actual change bodies, preserving fresh sentinel bytes and removing48 synthetic second-parent registrations;601 retained entries match instead of the earlier controlled-cohort649. Alternate/other selection and actual notify/effect bodies, data producers/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_CHANGED.md. Estimates reviewed and unchanged. Whole selection alternate14111bb90 now matches528 complete original calls across both major paths/all valid tags,1324 actual settings returns, live vector/result reloads and aligned free/cleanup operands.118 complete factories execute23 actual alternate and95 actual changed bodies;590 retained entries match without either opaque parent-rebinding endpoint. Search/data/cleanup and real state/scratch producers, reset/final, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_ALTERNATE.md. Estimates reviewed and unchanged. Reset predicates14114d330/14113fff0 now match1536 complete native gate calls with897 actual engine and752 actual primary/getter returns,635 controlled memcmp and518 secondary requests. Cached receiver, late flag, signed indices and declared memory match;768 original no-stub tag-query1417fb390 cases match full RAX and unchanged receivers. Whole reset/final and constructor/factory binding, real secondary/CRT/state production, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RESET_GATE.md. Estimates reviewed and unchanged. Whole selection reset14113a460 now matches528 completed original calls with actual gate/query/tag/primary/getter, aliasable strings/variants, fresh catalog base,327 assignments/200 fallbacks/817 notifications and controlled tail finish. Main-owned scratch and every provider boundary match. A fallible reset_checked constructor seam exists, but actual-reset constructor/factory composition, initial callback/finish and other provider bodies, producers/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RESET.md. Estimates reviewed and unchanged. Actual selection reset14113a460 now composes in118 whole original factories, including both explicit controlled finish requests,236 actual queries and64 primary/getter/tag returns. Current source callback/list state publishes before reset; prior parent memory, both sentinels,20 input table regions, globals/index/catalog and590 retained entries match.70 assignments/52 fallbacks/8 cleanups/91 frees execute; lists are fresh/empty; reset-entry+c0 is0 in95 cases and1 in23. No early skip is reached, so standalone notification/early-skip proofs retain their separate scope. Initial/finish/provider bodies, true data production/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_FACTORY_SELECTION_RESET.md. Estimates reviewed and unchanged. Whole initial callback1410fe0f0 now matches712 native calls and768 no-stub helper pairs. Actual tag/payload defaults, live parent/float stores, cached payload versus scratch reloads, flag clear and recursive requests match.528 actual callback/reset and118 whole-factory compositions also pass, with590 retained entries and329 controlled finish requests in the factory cohort. Recursive reset bodies remain controlled in55/11 composed requests; real predicates/float/finish/cleanup/producers, full dialog/menu/viewer/GPU and paired captures remain unverified. Prior reset-only+c0 wording is corrected from95 zero/23 one input snapshots. See research/UI_SELECTION_INITIAL.md. Estimates reviewed and unchanged. Recursive reset14113a460 now executes actual callback/reset bodies:528 outer calls include55 actual nested resets;118 whole factories include11, preserving590 retained entries and all inherited maps. Native/source LIFO frame restoration and full provider boundaries match; factory query/gate/getter counts are258/129/75, and351 finish requests remain controlled. A new replay exposed extra catalog validation: it is replaced by original signed64 division/wrapping-low32 comparison and independently matches504 boundary cases. Depth2 is observed only for these synthetic profiles; arbitrary recursion, real finish/predicate/float/provider/producer/lifetime, full dialog/menu/viewer/GPU and paired captures remain unverified. See research/UI_SELECTION_RECURSIVE_RESET.md. Estimates reviewed and unchanged.
  7. Audio, multiplayer, plugins (planned): Sound, networking and the plugin interface.
  8. Platforms and distribution (started): CI and nightly builds exist. Left: a launcher, settings, tagged releases.

Next up:

  • Recover finish14113d660, predicates141a3cbc0/14113ff10 and float1411363f0; recursive caller bodies now compose, but real pending-state production, further reentry and observer effects remain unverified. Recover real context/readiness/override/search/filter/erase/data/string-cleanup/allocator bodies. Both selection exits now execute originally alongside root/nested/context/weather/fifth in118 child factories; real registry/engine/scratch producers and ownership remain unproven. Bind actual engine query1417fb320 in root/nested/context/selection-constructor callers, recover notification/effect dispatch1410c9d10, sparse hash erase1406215a0, remaining iterator/growth/sort/payload and callback backing. Complete dialog/layout/widgets/singleton/Main Menu/teardown and original Alt/Esc/live GPU with paired screenshots/GIF/video.
  • Recover real window update/reset/delete/environment/final and document/dialog/binding effect bodies; factory/registry lifetime, opening ID3/Alt and full viewer integration remain incomplete.
  • Trace actual Alt/Esc show_menu/main-menu/settings actions: live observer/override/primary registration, held-command scheduling, UI classification/registry lifecycle, focus callers, leave/enter notifications, widget masks and concrete child callbacks. Connect the verified keyboard/command routing to the live viewer.
  • Recover original menu state, layout and font roles; connect the 25 available textures and 12 fonts to GPU rendering, then compare paired screenshots and GIF/video under identical conditions. Esc still exits the viewer and no original menu is drawn.
  • Recover dynamic wing geometry updates and complete reference bounds; connect recovered curvature setup and original element force arms/normals
  • Recover runtime body grids and propeller radius/center fields; validate real-aircraft reference snapshots and connect the verified main reference-vector pipeline
  • Port per-strip airflow (0x14121a9b0) and connect recovered propulsion and contact blocks to the live model
  • Compare complete live trajectories against the original after runtime integration
  • Fill datarefs from aircraft state and implement remaining command handlers
  • Read DSF scenery tiles and implement cockpit instruments and the stock Cessna Lua systems

Details and the target crate layout: docs/ARCHITECTURE.md.

Current state

The ACF property loader, OBJ8 geometry reading and a static-view window of the stock Cessna on wgpu all work. The Metal backend is verified on this Mac. There is no flight simulation yet.

From the analysis of the original EXE, typed reading of mass, maximum fuel, centre-of-gravity coordinates and engine count has been added. Unit conversion factors keep the float32 values of the reference build.

cargo run --offline -- aircraft-info "Xplane12/Cessna 172 SP/Cessna_172SP.acf"

Results and the limits of the confirmed behaviour: research/ACF_LOADING.md.

AFL 1110 is read: header, shape points, parameters and several Cl/Cd/Cm tables of 721 rows each. All 34 provided airfoils have been checked. To print values at an angle of attack of 5°:

cargo run --offline -- airfoil-info "Xplane12/Airfoils/NACA 2412 (popular).afl" 5

Sampling is linear inside each table, with no regime blending and no flight-model corrections. Research: research/AIRFOILS.md.

The section of angle correction and fixed-grid lookup confirmed in the EXE is implemented separately. Arguments: the angle after the previous stages, and the correction multiplier and divisor. For example:

cargo run --offline -- airfoil-eval "Xplane12/Airfoils/NACA 2412 (popular).afl" 10 1 2

The command shows the effective angle, the indices, the weights and the coefficients of each table. The multiplier and divisor are still given by hand: how they are obtained for a wing, the later corrections and the integration of forces are not implemented yet. Formulas and addresses: research/AERO_LOOKUP.md.

airfoil-eval also prints the normalised angle and the stall state without memory of the previous state. The library has a mode with the original's hysteresis: it switches on above 1 and resets below 0.75 of the absolute normalised angle. The Cl/Cd changes of the later perturbation function are not applied yet. Evidence: research/STALL_STATE.md.

The separate buffet module implements the perturbation generator and the active-stall Cl/Cd corrections. The shared noise table and the time in seconds are passed in explicitly. The time source is established: sim/time/total_running_time_sec. The runtime module reproduces the double storage and access through a float32 dataref. Noise initialisation and time advance are not recovered yet, so this module is not wired into airfoil-eval automatically. Check with a given table:

cargo run --offline -- buffet-eval table.f32le 0 0 0 0 2 0.25 -0.1

The table is 262144 little-endian float32 numbers. Arguments after it: x, y, phase, time in seconds (the internal double), Cl, Cd, Cm. Research: research/BUFFET.md, research/RUNTIME_TIME.md.

Choosing a pair of tables and blending the results by an input parameter:

cargo run --offline -- airfoil-mix "Xplane12/Airfoils/NACA 2412 (popular).afl" 5 1 1 0.75

The last argument is given in the scale of the AFL file's parameters[0]. The units of this input and its computation in the flight model are not established yet. The command blends the implemented lookup stage; the original blends the outputs of a fuller evaluator. Research: research/AFL_REGIMES.md.

The loader keeps unknown properties, their order, repeats, string values and line numbers. It reads the PROPERTIES_BEGIN / PROPERTIES_END section; the other sections, including PANEL_3D, are not interpreted yet. The file version is kept as metadata, not as a guarantee that a whole X-Plane version is supported.

cargo run --offline -- inspect Xplane12
cargo test --offline
python3 tools/inspect_pe.py Xplane12/X-Plane.exe
python3 tools/find_acf_xrefs.py Xplane12/X-Plane.exe

inspect takes a content directory, finds ACF files recursively, checks the references to models and airfoils and parses the AFL files it finds. Exit code: 0 - the checked references and AFL files are fine, 2 - dependencies are missing or there are AFL errors, 1 - an ACF read or format error, or bad arguments. Textures, panels, Lua, sound and scenery are not checked by this command yet.

Unified profile evaluator

profile combines angle correction, AFL lookup, the shared stall memory for the chosen table pair, perturbations and result blending. The airfoil-replay command carries the state between the rows of an input CSV:

cargo run --offline -- airfoil-replay "Xplane12/Airfoils/NACA 2412 (popular).afl" examples/profile-replay.csv research/local/runtime-snapshot/noise.f32le 0

An active stall needs an explicitly passed noise table. The tools/capture_xplane_runtime.py tool is prepared to read it from the original on Windows; its Windows branch is not verified yet. Without an active stall, - can be passed instead of the table. The evaluator creates no forces and moves no aircraft; flight-model inputs are given explicitly. Instructions and confirmation of the state order: research/PROFILE_PIPELINE.md.

Cessna viewer

cargo run --offline -- view "Xplane12/Cessna 172 SP/Cessna_172SP.acf"

Left mouse button and movement rotate the camera; the wheel zooms; R resets; Esc closes. The window redraws on camera and size changes, not continuously in the background.

To save an image without a window:

cargo run --offline -- render "Xplane12/Cessna 172 SP/Cessna_172SP.acf" /tmp/cessna.png

Diagnostics of all attached OBJ files:

cargo run --offline -- mesh-info "Xplane12/Cessna 172 SP/Cessna_172SP.acf"

mesh-info continues after errors in individual objects. It returns 2 if a file could not be read or parsed or a base texture is missing. Unsupported commands are listed separately and do not by themselves mean a geometry error.

The viewer uses seven objects: fuselage, landing gear, propeller, wings, front and rear seats, and the outer glass. All animation datarefs are 0. This is the chosen set of geometry for the first view, not a reproduction of the aircraft state. VT/IDX/IDX10/TRIS, the nested transform stack, rotation and translation keys, show/hide, a DDS lookup in place of the declared PNG, base colour, lighting and approximate glass transparency work. 4x MSAA is supported.

Limitations: no normal/lit maps, PBR, mipmaps, mirrors, instrument screens, clickable controls or simulation. Geometry is still double-sided; glass is sorted per object; LOD is fixed to the first set; non-zero ACF attachment poses are rejected. All attached OBJ files of the three provided Cessna variants pass geometry parsing; this does not mean all their commands or the full display of the aircraft are supported. Protocol: research/VIEWER.md.

Installation layout. A standard X-Plane folder (Aircraft/, Airfoils/, Custom Data/, Custom Scenery/, Global Scenery/, Resources/) is supported with its folder precedence: Custom Data/ before Resources/default data/, scenery packs from scenery_packs.ini before Global Airports before the default apt.dat, an aircraft's own airfoils/ before the shared Airfoils/. Evidence and which rules are only documentation-based: research/INSTALL_LAYOUT.md.

The minimal layout used while only a few files were provided is still accepted:

Xplane12/
├── X-Plane.exe
├── Cessna 172 SP/
├── Airfoils/
└── Earth nav data/
    ├── apt.dat
    └── earth_nav.dat

The content directory and local reports are excluded from Git. The engine must read user content separately from its own code. The research tools do not modify the original files.

Airport scene

cargo run --offline -- airport-render Xplane12 KSEA "Xplane12/Cessna 172 SP/Cessna_172SP.acf" ksea.png
cargo run --offline -- airport-view Xplane12 KSEA "Xplane12/Cessna 172 SP/Cessna_172SP.acf"

Draws an airport from apt.dat (runways with markings, taxiway and apron pavements with holes) and puts the aircraft on the first runway. Static, no terrain or objects. Rules and limits: research/WORLD_GEOMETRY.md.

Cessna on runway 16L at KSEA

Datarefs

cargo run --offline -- datarefs "Xplane12/Cessna 172 SP/Cessna_172SP.acf"
python3 tools/extract_datarefs.py Xplane12/X-Plane.exe --prefix sim/aircraft/weight/

datarefs registers the datarefs whose backing ACF fields are confirmed in the original (empty, maximum and fuel mass, CG Y/Z, engine count) with the type and writability of the reference build. extract_datarefs.py lists all 5503 registration records of the original's table. Layout, evidence and limits: research/DATAREFS.md.

Flight (approximate flight model)

cargo run --release --offline -- fly Xplane12 KSEA "Xplane12/Cessna 172 SP/Cessna_172SP.acf"
cargo run --release --offline -- fly-render Xplane12 KSEA "Xplane12/Cessna 172 SP/Cessna_172SP.acf" frame 0 20 30 45
cargo run --release --offline -- wing-info "Xplane12/Cessna 172 SP/Cessna_172SP.acf"
cargo run --release --offline -- fly-test Xplane12 "Xplane12/Cessna 172 SP/Cessna_172SP.acf" 60

fly opens a window with the Cessna on the first runway of the airport. It uses the original's default keyboard map, read from the reference build: F1/F2/F3 throttle down/up/full, 1/2 flaps up/down, B brakes (hold), V maximum brakes, [ ] pitch trim, 5 6 7 rudder trim, 8 9 0 aileron trim, P pause, W default view, Q E R F and = - move the camera. The original has no keyboard stick, so openXplane adds one: arrow keys pitch and roll, Z/X rudder (Tab gives them their original meaning back), Delete resets, Esc quits. OPENXPLANE_DATA_OUTPUT=0,3,4,17,18,21 draws the reference build's data-output lines with those indexes (the Data Output list of X-Plane: 0 frame rate, 3 speeds, 4 Mach and vertical speed, 8 stick, 13 trims and flaps, 17 attitude, 18 alpha and flight path, 20 altitude, 21 position and velocity, 25 throttle; OPENXPLANE_FRAME_RATE=1 adds line 0); see crates/xp-app/src/dout.rs. Commands without anything to act on yet (mixture, magnetos, carb heat...) are reported in the window title as not simulated. The title also shows speed, altitude, vertical speed, pitch, bank, heading, throttle, flaps and a stall warning. Full table: docs/KEYBOARD.md; source of the map: research/KEYMAP.md. fly-render runs a scripted takeoff and saves chase-camera frames at the given times.

Cessna climbing out of KSEA

An approximate rigid-body model on the Cessna's real ACF and airfoil data: the wing is split into elements and each one uses the airfoil code verified against the original; thrust, landing gear and control surfaces are openXplane's own simplifications. It takes off and climbs under a scripted pilot. It is not the original's flight model; what is original and what is assumed is listed in research/FLIGHT_MODEL.md.

Verification against the original machine code

tools/emulate_xp.py runs isolated functions of X-Plane.exe in a CPU emulator on synthetic inputs, and tests/original_vectors.rs requires the Rust port to match their outputs bit for bit: 1200 cases of the profile stage (angle correction, lookup, stall, buffet noise) and the interpolation helper all agree. Method and limits: research/VERIFICATION.md.

ACF loader schema

python3 tools/extract_acf_schema.py Xplane12/X-Plane.exe > research/local/acf-schema.tsv

Lists the 1117 ACF property reads the original's loader performs in a recognisable shape, with the field offset, reader type and unit coefficient (wing geometry, part positions, engine fields). Evidence and limits: research/ACF_SCHEMA.md.

Commands

python3 tools/extract_commands.py Xplane12/X-Plane.exe > research/local/commands.tsv
cargo run --offline -- commands research/local/commands.tsv sim/flight_controls/flaps

The original's command table (3138 native command records) is enumerated by the tool, and CommandRegistry loads it and runs begin/continue/end phases through handler chains. Layout, evidence and limits: research/COMMANDS.md.

Airports (apt.dat)

cargo run --offline -- airport-info "Xplane12/Earth nav data/apt.dat" KSEA
cargo run --offline -- airport-info Xplane12 KSEA   # whole installation, priority order

Reads one airport as a stream: the header, the metadata (1302) and the land runways (100). The other rows are only counted. Exit code 2 if the ICAO code is not found. Limits and verification: research/APT_DAT.md.

Discord

While the viewer is open, Discord Rich Presence can show what you are looking at. It uses the project's own Discord application (set OPENXPLANE_DISCORD_APP_ID to an empty value to turn it off, or to another id to use your own); details and limits: docs/DISCORD.md. The website gets a Discord button as soon as an invite link is set in site/app.js.

Roadmap

  1. Continue analysing the original EXE's loaders and confirm the ACF/OBJ rules.
  2. Extend OBJ8: instruments, materials, normal/lit maps, dynamic animations.
  3. Datarefs, commands and the runtime of the stock Cessna's Lua scripts.
  4. Application of the AFL tables, ACF parameters, engines, landing gear and aerodynamics, with measurements in the original.
  5. apt.dat, DSF and the library dependencies of one test airport.

Support for X-Plane 10/11 and third-party binary plugins comes in later stages. There is no timeline for full compatibility yet.

Results of the first investigation: research/BASELINE.md.

License

GPL-3.0-or-later, see LICENSE and NOTICE. X-Plane is a trademark of its respective owner. openXplane is an independent project and is not affiliated with it.

About

Independent open X-Plane-compatible engine in Rust. Requires an original copy of X-Plane 12.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages