2026-10-29 — session 1 (autonomous, overnight)#
Source: main@095b875 (partial upload: no objects/, liveries/, plugins/).
- Analysis. Inventoried the upload, parsed the
.acffiles of all five variants, airfoils andb738_cockpit.obj; identified missing folders and the EULA terms. Confirmed the.acfCG envelope maps to 3–33 % MAC with the published reference wing (sanity check of the axis/MAC conversion). - Configs.
tools/msfs/generate_configs.pywrites all 737-800 SimObject configs in the MSFS 2024 modular layout (structure taken from FlyByWire's 2024-native A380X; key semantics from their A32NX). Fuel: 6,875 gal in three tanks ✓. Contact points: tyre bottom at full extension (verified against A32NX numbers). - Models. OBJ8→glTF converter (validated with the Khronos glTF validator,
0 errors). Placeholder exterior from the
.acfgeometry, rendered in headless Chromium to check axes and surface/gear motion directions (fixed flap/slat/rudder/gear signs after the first render). Cockpit click spots (988 mouse rects) and 11 display surfaces extracted fromb738_cockpit.obj. - Systems. TypeScript systems simulation, 8 vitest scenarios passing (cold & dark power-up, ground power, generators + bus transfer, APU start, engine start, fuel pumps + master caution, AFDS CMD/LVL CHG).
- Avionics. PFD, ND, upper/lower engine displays, CDU (10 pages), ISFD, EFB; rendered with the browser harness for visual checks.
- Package.
tools/build_package.pyrebuilds everything; generated output committed (msfs2024/, fallbackmsfs2024-legacy/).
Not tested in MSFS (no simulator in the build environment). Next: user's first
build/test per TEST_PLAN.md; upload of objects/ and liveries/.
Assumptions to verify in the first sim session:
- glTF animation time base 24 fps (
ANIM_FPSin the converters). $-prefixed screen texture names bind topanel.cfgtexture = $NAME.- Asobo stock light effect names (
LIGHT_ASOBO_*). SET_AUTOBRAKE_CONTROLvalue mapping,TURBINE_IGNITION_SWITCH_SETvalues.- MSFS attitude sign conventions used by the PFD (positive bank = left).
- H-events reach the headless systems gauge (
onInteractionEvent).
2026-10-29 — session 2: original models, original instruments#
Owner's direction: complete restoration with the original models, flight deck and instruments; the instruments must be the original ones, not redrawn.
- Original models. All 65 objects of the 737-800 (
_objalist) converted with their original textures (DDS → PNG, X-Plane normal/metalness → MSFS normal + ORM), animations shared per dataref, visibility, LIT/emissive, click spots. Exterior and interior models replace the placeholder exterior and cockpit shell (removed). - Original panel. Interpreter of X-Plane's generic instruments over the
original
PANEL_3Dand bitmaps; conventions recovered from the panel and X-Plane's render of it; validated againstPanel_Preview.png. The self-drawn DU/CDU/ISFD/EFB instruments and the approximated TypeScript systems were removed. - Original logic. xphost hosts the original
xlua.xpl(all Zibo/LevelUp Lua) andzibomod.xplunmodified by implementing the X-Plane plugin API they use. Tested on Linux with thelin_x64plugins and as the Windows build with thewin_x64plugins under wine (same results). - Gauge and bridge. XPanel gauge on one
$LU_PANELrender target; MSFS ↔ X-Plane sim mapping with plugin ownership, AP/AT authority gating, engine-start following and in-flight control-sign learning; cockpit clicks and MSFS key bindings relayed to the original commands. - Package.
tools/build_package.pybuilds the new layout; Windows host binaries inxphost/dist/windows.
Not tested in MSFS. Open items: sound, IRS LED layout, X-Plane EFIS base map, FDE tuning, first in-sim test (TEST_PLAN).
Later the same session#
- Sound: the original FMOD banks and
.sndlogic are played by the host through X-Plane 12's FMOD runtime (tested with a logging FMOD stand-in). - glTF tangents for normal-mapped materials; validator: 0 errors, 0 warnings.
- Fixed duplicated display surfaces that covered the panel render target.
- Renders:
docs/exterior_render.png(exterior),docs/cockpit_render.png(flight deck with the live panel on its displays; overlapping alternative DU surfaces are switched by the visibility rules in MSFS),docs/panel_live_render.png(panel from the plugins' live state).
2026-10-30/31 — session 3: first in-sim feedback#
First runs in MSFS 2024 (user's tests); fixed from their reports, checked offline with the Linux host, the original plugins and the gauge's bridge.
Black displays.
panel.cfg'stexture =names the material the gauge draws on; the screens' material wasPANEL_LU_PANEL(only its placeholder image was$LU_PANEL). Now material and render target areLU_PANEL(no$: in MSFS 2024 it marks a collision material), the material has no textures (black base, white emissive), and the preset holds the onlypanel.cfg(a[MODULAR_MERGE]stub there left the gauge unloaded).Gauge start.
/JS/netbingmap.jsimported (the ND Bing layer needs itsEWeatherRadar/EBingModeglobals); a missing Bing layer no longer stops the panel. The host link retries an attempt that never opens (Coherent GT does not always fireonclose), so a host started after MSFS is found.MCP not clickable. The EFB stand drag (
drag_xy) stayed active over the rest of737_cockpit_pdstl_efis.obj: the glareshield, EFIS panels and knobs were 43 "Adjust stand" click areas, one 1.5 m wide over the MCP.Model centre. The acf origin (cfg datum) is at the nose; the models now have the empty CG at their origin and
reference_datum_position = 60.22, 0, 2.05puts the datum back at the nose (all other cfg positions unchanged).Brightness. Screen emissive ×2 via
L:LU737_DU_GAIN(live adjustable, remembered by the gauge); the DU knobs still dim in the gauge.FO PFD/ND black on battery is the original logic: with the gauge's bridge against a cold host, battery only gives
display_units0 for the captain DUs and the upper DU, −1 (blank) for the FO DUs and the lower DU, as on the real aircraft. AC (APU generator, GPU via ground services, engine generators) powers them.Host.
start = cold/--cold; gear handle down at load (the plugins' lever started at OFF and the gauge sentGEAR_SET 0); commands held from press to release again (they were begun and ended in the same instant, so taps on A/T ARM, trims, test buttons and every hold-type control did nothing; "once" clicks now hold for one frame); EECs on at load. Windows binaries rebuilt (the committed ones predated the 10-30/31 host changes).Dead controls (audit of all click spots against the OBJs and the live plugins): the flap, gear and speedbrake levers were lost to the OBJ parser reading
ATTR_manip_keyframeas a manipulator; they now step between their detents. The 188 EFB tablet buttons were cut by a skip list (only the stand drags are skipped now). Two-command switches and knobs hold the command from press to release (spring-loaded switches, test buttons, knob repeat), the wheel steps once. EEC buttons were mapped to a constant. Model, behaviours and gauge tables regenerated: 991 click spots. Known, from the original OBJ:sim4flight_controls/door_open_4, MARKER volume (obs_audio_vol_marker) and HF SENS (rtp_D) are typos of the original and stay dead; throttle/yoke click drags are overridden by the MSFS controls;drag_xyonly steps its X axis.Second in-sim run (displays frozen, APU/DU knob/flap lever dead, z-fighting): the gauge's frame steps are now guarded one by one (errors in the Coherent console as
LU737 XPanel: <step> failed, link health every 30 s) and only one gauge instance talks to the host (duplicate panels showLU737 DUPLICATE PANEL). Flaps reached MSFS only at the first sync (the plugins writeflap_ratio); hardware flap levers/axes now step the plugins' lever. MSFS fuel valves/pumps follow the plugins (all were closed). Display surfaces lifted 0.5 mm off an opaque panel layer 0.1 mm behind them (z-fighting). Checked offline: OUTBD DU BRT → PFD brightness works in the host (0.3 → 0.3). Not solved: the APU. Held at START, the switch reaches START but Zibo (compiledzibomod) never calls X-Plane'ssim/electrical/APU_startin the host, so MSFS never starts it; one of its start conditions is not met outside X-Plane. Open: APU start (above), speedbrake axis to the plugins' lever, cockpit seen from far outside, liveries (the LevelUp livery folder is not in the repository), LODs, checklists (clist.txt), EFB fuel/payload → MSFS, X-Plane EFIS base map, IRS LED layout, FDE tuning, sound in the sim.
2026-10-31 — session 4: stable cockpit interface (SCI), P0 + P1#
Redesign of the cockpit interaction layer (docs/COCKPIT_IO_REDESIGN.md,
details in docs/SCI_IMPLEMENTATION.md): MSFS uses only stable names
(H:LU737_<CONTROL>_<ACTION>, L:LU737_<STATE>); the host maps them onto the
plugins (data/sci), with a closed-loop result for every click.
- Host: SCI core (contract, profile with alias chains / synthesized
expressions / shadow state / drive modes / gates / effects), synthesized
737NG electrical model, protocol 0x10–0x12 / 0x90–0x92,
--sci-testscripts. X-Plane's bus volts/avionics now follow the synthesized buses (cold and dark was 24.5 V and avionics on: the old code read switch positions). The battery special case in the bridge is gone. - Gauge: relays SCI events by name, writes the states to L-vars, draws a display only while its device is powered, powers everything down on link loss.
- Model: the 17 electrical panel/APU controls, their animations and 16
electrical lights use SCI names only (generator
--sci,data/sci/model_map.json). - APU found: Zibo calls X-Plane's APU_start (passed to MSFS) only when START follows 5–6 s at ON, and not once the MSFS APU N1 is ~20 % already. The SCI gate holds a quicker START back; the gauge no longer starts the MSFS APU at START itself.
- Measured: battery guard closes onto ON; BUS TRANSFER is not modelled by
Zibo 2.S1.50 (cross_tie forced to 1: shadow state);
power_on_busesdoes not exist in 2.S1.50 (nothing used it); the GPU needs on-ground. - Tests:
elec_cold_start.json54 checks,elec_degraded.json(plugins' electrical and display datarefs hidden) 53 checks, gauge e2e 11 checks, vitest 21 — all pass. Not yet run in MSFS; the Windows host is rebuilt but only the Linux build was run.
Session 4 (continued): every control on SCI#
tools/sci/generate_cockpit_sci.pyputs the remaining 974 click spots and 924 cockpit datarefs of the model on the stable interface (generic controls with the original click semantics, raw-valued states); the host runs them (mode: actions, queued per control) and checks each click against a watch list it measured itself (discover.json→91_watch.json).- The legacy path is gone: no
model_io.json, the model has no plugin names, the gauge only relays SCI events and states. The generator fails the build on any plugin name or unknown L-var in the model. - Fixed through the profile: the OBJ typos
sim4flight_controls/door_open_4andobs_audio_vol_marker(dead before), renamedstandby_altimeter_baroandplacard/cat3; HF SENS 3 is shadow state. The exterior landing lights read the SCI switch states. all_controls.json: every action of every generic control (see SCI_IMPLEMENTATION.md §8 for the result counts); e2e: quick wheel steps are not lost.- Exterior engine fans turn again:
L:LU737_fan_angle_1/2had no writer since the first build; the gauge now integrates them from the MSFS N1 on the sim clock (capped shown rate, still when paused).
2026-10-31 — rewrite, milestone 1 (toolchain)#
Owner's decisions (REWRITE_PLAN.md §1): rewrite all logic (zibomod + Lua)
as an MSFS WASM module and FBW-style HTML display units, Zibo AFDS and the
CFM56 tables reproduced exactly, MSFS navigation data, no sound in phase 1,
host removed from the product, builds in GitHub Actions, personal use only.
- SDK and module. MSFS 2024 SDK headers, wasi-sysroot and SimConnect.h in
third_party/msfs2024-sdk(SDK clang 15.0.1).wasm/: portable core behindSimIO, MSFS gauge adapter (LU737_Systems_gauge_callback), heartbeat L:vars, native tests (ASan/UBSan). Built with Ubuntu clang 18,-mcpu=mvp;check_wasm.pychecks exports (gauge callback, SDK allocator hooks), imports (onlyenv.fs*and WASI) and the feature set.panel.cfgVCockpit01 now loads the module (NO_TEXTURE). - Host removed from the product. Deleted
LU737Host.exeand the Windows build, the WebSocket server, the launcher, the FMOD sound player, the XPanel gauge (interpreter, host link and SCI relay, MSFS bridge, fan integration) and its package step, the html_ui asset group (empty until the display units exist),xphost.zip. The stable cockpit interface stays: the model uses only SCI names anddata/sciis the contract the rewrite implements;data/cockpit_io.jsonmoved out of the gauge. - Oracle.
xphostbuilds for Linux only and runs the original plugins headless with SCI:--selftest(5,088 plugin datarefs, 1,183 commands, ~2–3 ms per frame),--sci-test(elec_cold_start 54/54, elec_degraded 53/53, all_controls 2/2 pass) and the new--replay in.bin --out out.binover the frame protocol (xphost/test/replay_smoke.py: the battery switch commands move the plugins'battery_pos0 → 1). - Decompiler. Ghidra release downloads are blocked by the environment's
network policy;
tools/re/setup_decompiler.shbuilds Ghidra's native decompiler (decomp_dbgwith libbfd,sleighx86-64) from the git sources.tools/re/decompile.pydecompiles a zibomod function of the symbol-bearing Linux build with its constants resolved (checked oncfm56_7b_cn2_to_cn1: the N2/N1 tables read as numbers). - CI.
build-wasm.yml(tests, build, checks, artifact, comparison with the committed module),oracle.yml(build, selftest, SCI scripts, replay smoke test).
Next: M1 in-sim check by the owner; M2 specifications (electrics, APU, pneumatics, engine start, CFM56 tables).
2026-11-01 — milestone 1 confirmed in MSFS 2024#
- First loads failed with
WASM: Error getting memory. The owner supplied the SDK's MSBuild files and its toolchain (Asobo's LLVM 15 fork,third_party/msfs2024-sdk/llvm); the module is now built with it and the SDK's exact Release options, including--stack-guard-page(data, guard page, stack), on a windows-latest CI job (identical to the committed module) or under Wine. - In the sim (owner, Behaviors → Variables):
LU737_WASM_ALIVE1,LU737_WASM_BUILD3,LU737_WASM_FRAME4352 atLU737_WASM_TIME107.6 s. M1 done. - M2: CFM56-7B tables (
wasm/src/core/engine/cfm56_7b.*) bit-exact against the original zibomod functions called directly (wasm/test/zibo_direct.*, ~60 M calls); specdocs/specs/cfm56_7b_tables.md. Electrical and engine start/dynamics specs done; APU and pneumatics specs in progress.
2026-11-01 — milestone 2 done (specifications and CFM56 tables)#
Specifications of Zibo 2.S1.50 in docs/specs/ (own words, constants and
timings; no decompiled code), each with oracle scripts that pass and run in
oracle.yml:
| Spec | Oracle scripts (checks) |
|---|---|
electrics.md |
elec_spec_battery (22), elec_spec_sources (25) |
engine_start_and_dynamics.md (+ per-frame call order) |
start_spec_eng1_ground (12) |
apu.md |
apu_spec_start (27), apu_spec_delay_fault (12) |
pneumatics.md |
pneu_spec_ground_air (21), pneu_spec_apu_bleed (17) |
cfm56_7b_tables.md |
C++ implementation bit-exact vs. the original (~60 M calls) |
Findings that shape M3: Zibo computes almost everything itself (buses, N1/N2, thrust, fuel flow, bleed/duct pressure, pressurization, APU controller); X-Plane supplies only engine light-off, oil temperature/ quantity, the APU spool and battery/generator electrics — the rewrite models these in the core (APU spool from the .acf; MSFS APU kept off). Open questions are listed per spec (§9).
Next: M3 — implement electrics, APU, pneumatics and engine start in
wasm/src/core from these specs, with differential tests against the
oracle, and route the cockpit's SCI events to the module.
2026-11-01 — M3a confirmed in MSFS; cockpit controls MSFS-style#
- Owner: the electrical panel (build 4: battery, STBY PWR, ground power, meters, BUS TRANSFER) works in MSFS 2024 as described. M3a done.
- All 991 click spots now use MSFS-style interactions (
4d67342,docs/COCKPIT_CONTROLS.md): knobs wheel/drag/click, switches drag and click with spring positions held until mouse up, levers drag through detents, buttons and guards plain clicks. The 2123 SCI events are unchanged. To be tested in the sim.
2026-11-01 — M3b (APU, build 5) confirmed in MSFS#
- Owner: the APU (build 5,
80ef492) works in MSFS 2024 as described in TEST_PLAN M3b (start, generator, bleed, shutdown/cool-down). M3b done. Next: M3c, pneumatics and engine start.
2026-11-01 — MSFS-style controls confirmed#
- Owner: the cockpit controls with position-dependent cursors (
78161da: knobs TurnLeft/TurnRight, switch arrows, lever grab; wheel/drag/click) work in MSFS 2024. Next: M4 display units, starting with the per-display materials and the upper EICAS.
2026-11-03 — EICAS: back to 752e471, Zibo's PANEL_3D EICAS redone (build 9)#
- The canvas bitmap-interpreter EICAS and the dataref mirror (builds 7–8,
f52b962..382b1fc) never showed reliably in MSFS. Owner's decision: restore 752e471 (1d51041) and redo the EICAS against the original PANEL_3D data, with Zibo's bitmaps. - New EICAS (
docs/EICAS.md): PANEL_3DEICASgroup extracted topanel.json; drawn as HTML/SVG elements (no canvas) in the BaseInstrument shell of 752e471; every one of the 103 datarefs has a documented source. Exact sources checked against Zibo in nine oracle snapshots; drawing checked pixel-for-pixel against a reference PANEL_3D interpreter. - Findings from the oracle:
req_pie= commanded N1 − previous frame's N1; fuel quantities rounded up to 10 kg / 10 lb; LED fuel readouts need the low digits (the old interpreter clamped to 3999/6999). - Systems module build 9: Zibo's EICAS oil press/temp energise, start EGT redline and hot-start flags published per engine.
- Owner test: TEST_PLAN M4a steps 2–3 (build 9); screenshot request for two X-Plane behaviours (
docs/EICAS.md).
2026-11-03 — M4b (upper EICAS, build 9) confirmed in MSFS#
- Owner: the PANEL_3D upper EICAS (
524a73e) works in MSFS 2024. M4b done. Still open: the X-Plane screenshot check of the two assumed X-Plane behaviours (docs/EICAS.md). Next: rest of M4 (lower DU, PFD, ND, CDU, ISFD).
2026-11-03 — M4c: lower DU and MFD ENG / SYS (build 10)#
- Lower DU from Zibo's PANEL_3D
Lower DUgroup (ENG and SYS pages) with the EICAS method; the extractor (tools/msfs/build_du.py), drawing (panel3d, now with gen_pointer) and data sources (avionics/src/du) are shared by both units. - Systems module build 10: Zibo's page logic read from zibomod (
CMD_mfd_eng/_sys,B738_eng_out,EICAS_warning, timers) — MFD buttons, forced ENG page without AC transfer bus 2, auto display, LevelUp page transition, compact-format warning, "was red" latches; checked against oracle traces (page sequence, transition timing, 10 s warning flash). The upper EICAS's compact format, warning box, ENG FAIL and was-red boxes are now driven too. - Pending on the lower DU: hydraulics, brake temperatures (their own subsystems); flight-control surface directions to be checked in the sim. Owner test: TEST_PLAN M4c.
2026-11-03 — DU page-build option#
- Owner asked about the brief partial ENG page on MFD ENG: Zibo/LevelUp's page build (
lu_init, three background stages over 1.2 s), as in X-Plane. AddedL:LU737_DU_PAGE_BUILD_OFF(1 = full page at once; default 0 keeps Zibo's effect). Display only, systems module unchanged (build 10).
2026-11-03 — throttle jumping to idle (build 11)#
- Owner: DUs fine (M4c and the page-build option confirmed). Old bug: after the engine start the throttle
jumps back to idle now and then. The systems module writes the MSFS throttle only for cockpit-lever
clicks; the likely cause is the engine coupling re-sending the MSFS start every 5 s when MSFS's
combustion flag reads 0 for a running engine. Build 11: no re-start while MSFS N1 > 15 %, throttle put
back after a real re-send, diagnostic counters (
wasm/README.md, TEST_PLAN "Throttle jumps to idle").
2026-11-03 — EGT jump to ~1000 C during a start (build 12)#
- Owner screenshots: EGT ~711 C at N1 10 % during a start, then a sudden 990 C. Reproduced natively (wet
start, thrust lever slightly open). Original Zibo in the oracle does not jump: the EEC hot-start latch
cuts the ignition at ~711 C and the start aborts. The rewrite evaluated the latch per frame (ignition
back next frame, start EGT target re-based on the hot EGT → ~1100 C) and cleared
hot_start_warntoo early. Fixed as zibomod; the spec's §4.11.4 misreading corrected; old test expectation (EGT > 725 C) replaced by the oracle's values.
2026-11-03 — option: no EEC hot-start abort (build 13)#
- Owner showed another simulator where a hot start runs into the red. Zibo (oracle) aborts at ~711 C. Added
L:LU737_EEC_HOTSTART_OFF(default 0 = Zibo; 1 = no abort: Zibo's start EGT model then peaks near 980 C on the worst wet start, no jumps, the engine still reaches idle).
2026-11-03 — throttle guard reverted (build 14)#
- Owner: the throttle still jumps back to idle with build 11's guard. Reverted (
git revert b3ed459), the issue stays open and is to be fixed later. Hot-start fix (build 12) and the EEC option (build 13) kept. Next: M4d (PFD).
2026-11-03 — M4d started: PFD#
- Renderer ready for the PFD (
c09cc0d): group / instrument clips, needle deflect, gen_text; the captain PFD's PANEL_3D (LU_DU_CPT_OUTBD: PFD, RA/DH circles, HUD repeater) draws identically to the reference interpreter (Zibo's powered cold state from the oracle and an in-flight state). Zibo draws nothing on the PFD with OpenGL (oracle GL capture empty): the PFD is all PANEL_3D. - PFD datarefs (230): air data / attitude 19, radios (ILS, markers, RA) 31, IRS 4, AFDS / MCP / FMA 77, FMS 23, speed bands / flap speeds 27, EFIS control panel 21, TCAS / GPWS 3, HUD 7, other 17.
- Owner's decisions: rewrite Zibo's IRS (alignment, lights, PFD/ND flags) first; M4d does what can be exact now (air data, IRS, radios, EFIS control panel, speed bands); FMA / FD / V-speeds / path with M5.
- Zibo's IRS is Lua (
B738.LATLON.lua:B738_irs_system,_annun,_electric,_source,pfd_nd, display data; about 2000 lines). Next: spec, systems-module subsystem, oracle differential tests.
2026-11-03 — IRS rewritten (build 15)#
wasm/src/core/irs/ports Zibo's IRS (specdocs/specs/irs.md). Oracle differential tracexphost/test/sci/irs_trace.json(power-up at 22.31 N, both IRS to NAV, 333 s count, keypad position entry, source switch, left quick realign, left OFF): 0 mismatches over 14 445 frames x 21 values, timer edges within ±1 frame. Exactness needed XLua's timer model (float sim time) and Lua's double arithmetic: with float timers the selector delay came one frame late.- Found while testing: Zibo's flight start phase lasts 2 s (not 2 frames); during it the engines-running
start state is re-applied every frame and the ADIRUs are powered (
irs_enablestarts at 1). - Owner's option
L:LU737_IRS_ALIGN_TIME: 0 real (default), 1 fast 60 s, 2 instant, 3 long 150 s. - Temporary: position / ATT heading entered automatically until the IRS display unit and FMC POS INIT are
rewritten (spec §6). Oracle host: new SCI step
set_str(writable string datarefs). - Next: PFD data sources (air data, attitude, radios, EFIS control panel, speed bands, IRS flags).
- Owner tested build 15 in MSFS: IRS works (alignment, lights, options).
2026-11-03 — PFD phase 1#
- Captain PFD instrument (
lu737-pfd, VCockpitLU_DU_CPT_OUTBD), whole PANEL_3D display (230 datarefs). Sources: air data / attitude / radios from MSFS, IRS flags from the systems module, Zibo's display formulas (drums, heading bug, track line, MCP bugs, RA steps and white box from zibomod via the decompiler and oracle sweeps); the rest pending at Zibo's ground values. Oracle tracepfd_trace.json; vitest: every exact source equals Zibo in three states (ground, cruise, approach). - Next: speed bands (
B738.calc.lua), EFIS control panel, ILS source logic, FO PFD.
2026-11-03 — PFD speed bands (build 16)#
wasm/src/core/speeds/: port ofB738_calc_min_max_spd(737-800 path), incl. zibomod's TAS / speed-of-sound filters. Oracle tracespeeds_trace.json: 0 mismatches over 2550 frames. PFD readsL:LU737_PFD_*.- Open: FMS flight phase (Zibo's FMS sets approach phase 7 in descent even without a route) and approach flaps are 0 until M5; Zibo's AOA filter stands in by MSFS alpha.
2026-11-03 — EFIS control panel (build 17)#
wasm/src/core/efis/: both EFIS control panels' PFD part (MINS, BARO, IN/HPA, STD, MTRS, FPV, minimums alert, baro boxes); oracle traceefis_trace.json: 0 mismatches, 0 frame shifts. Found: Zibo resets the minimums every frame while DC standby and DC bus 2 are unpowered. Captain's setting → MSFS altimeter 1.
2026-11-03 — NAV radios and ILS on the PFD (build 18)#
wasm/src/core/nav/: classic NAV radios (Zibo's default, MMR hidden), MSFS receivers tuned from the panel, MMR mode, station identification with the 6.5 s decoding, VHF NAV source. PFD: ILS pointers,pfd_ilstext lines (string datarefs now supported by DuSource). Identification uses MSFS reception (no X-Plane nav DB).
2026-11-03 — first officer PFD#
lu737-pfd-foonLU_DU_FO_OUTBD: FO PANEL_3D, FO EFIS panel / IRS 2 / NAV 2 sources; oracle checks in three states pass. Next: the owner's two engine issues (no thrust in MSFS, throttle snapping back to idle).
2026-11-03 — engine attempts reverted; M4e ND (build 19)#
- Owner: stop the engine work and go back to the last milestone: builds 19–22 reverted (
d8794bc); the thrust / throttle issue stays open. Then "continue all M4": NDs for both sides (lu737-nd,lu737-nd-fo), the EFIS panel's ND part in the systems module (mode, range, CTR, VOR / ADF, map buttons), Zibo's ND heading / track / bug formulas, wind and pointers from MSFS; map content pending until the FMS (Zibo draws the route with OpenGL). Oracle checks pass in three states for both NDs.
2026-11-04 — M4f ISFD (build 20)#
- ISFD instrument (
lu737-isfd); systems modulestandby/from zibomod's standby altimeter commands and altitude formula (constants read from the binary); the renderer gains X-Plane's rolling digits (gen_rolling). M4 displays left: the CDU, which comes with the FMS (M5).
2026-11-04 — M5a MCP dials (build 21)#
- Systems module
mcp/: speed (IAS / Mach), heading, altitude, both course knobs, bank angle, change-over; PFD and ND bugs and course read them. Mode buttons wait for the AFDS (zibomod: the buttons only set requests its mode logic processes each frame).
2026-11-04 — owner's decisions for M5; MSFS fuel feed (build 22)#
- Owner: fix the thrust before the AFDS; AFDS = Zibo's logic with our own control laws flying MSFS's controls; FMS = port of Zibo's FMS on MSFS navigation data, in stages.
- Build 22: MSFS's tank pumps / circuits kept on while Zibo's engine runs (fuel pressure was 0), engines.cfg without ignition / condition gates, engine diagnostics; K: table gets the altimeter / NAV events builds 17-18 missed.
2026-11-04 — MSFS engines burn (build 23); engines.cfg from Zibo's engine model#
- Build 23 (SDK review): with
DisableMixtureControlsthe condition lever is MSFS's fuel cutoff; a Zibo start now also sets condition lever k to low idle and ignition k on. Owner: MSFS's engines burn, N1 99.5 % at TO/GA, but net thrust ~2 400 lbf (gross 24 000, ram drag −21 500). - SDK engine notes read in full: airflow =
corrected_airflow_table×inlet_area× δ_total / √θ_total, ram drag = TAS × airflow / g, gross thrust = corrected gross × δ_total (δ_total = δ (1 + 0.2 M²)^3.5). The airflow table held the whole engine's airflow (×20), and the thrust table ignored δ_total (cruise thrust ~1.8× too high). - engines.cfg's thrust, N1 schedule and fuel flow are now generated from Zibo's engine (
docs/FDE_TUNING.md"Engine schedule from Zibo"):wasm/tools/engine_sweep.shruns the rewrite's Zibo engine to steady state over lever × altitude × Mach (data/msfs/zibo_engine_sweep.json);tools/msfs/engine_schedule.pyfits the tables. ISA match: N1 rms 0.9 % for levers ≥ 0.3, net thrust at Zibo's N1 within 1.5 %; idle within a few % (MSFS cannot tell ground from flight idle). The two commanded-N1 tables, which the SDK says must never be equal (the engine may drop to idle), crossed near lever 0.9 before; they are now ≥ 0.3 % apart everywhere.fde_check.pyuses MSFS's net-thrust formula: cruise FL350 M.785 N1 87 %, approach flaps 30 N1 61 %. - WASM unchanged (build 23). Owner test: TEST_PLAN "Build 23 + engines.cfg from Zibo".
2026-11-04 — M5b-1 AFDS logic translated and verified#
- Engine thrust: owner's own fix (
44ad5ba, engines.cfg from Zibo's engine model) — "engine working now". - AFDS: zibomod's Glareshield / ap_speed_accel / flight_director_new and callees (189 functions) translated by
tools/re/port_cpp.pyfrom Ghidra listings (tools/re/decompile.pynow with prototypes, constant sizes and symbol names) intowasm/src/core/afds/(docs/AFDS.md). - Oracle: traces zibomod globals from memory (
zibo:), samples inside zibomod's frame by call-site hooks (at:), long log lines no longer cut.afds_replay_matches_oracle: 730 state values identical on every frame through power-up, FD, A/T, HDG SEL, ALT HLD, SPEED, CMD A, V/S, LVL CHG, N1, VOR/LOC, CWS, CMD B, disengage. - Next: integration in Systems (inputs, events, L:vars), FD bars, our servo + A/T on MSFS controls.
2026-11-04 — M5b-1 AFDS in the systems module (build 24)#
systems_afds.cpp: AFDS inputs from MSFS and the modules, MainFlightLoopCallback's air data / start-up parts, MCP button and V/S wheel events, 168 outputs as L:vars (cockpit lights, PFD FMA / FD: 57 PFD sources now live). Hydraulics approximated (engine running) until rewritten. The autopilot does not fly yet (servo: M5b-3).- Found on the way: the FO PFD read element 0 of array datarefs (spd_ind_mode[1] etc.); fixed.
2026-11-04 — flight model research; CG frame fix#
- Owner: the EFB weight & balance page shows the CG far aft. Research (
reports/MSFS 2024 737 flight model CG.md, four research notes): MSFS 2024 measuresaero_center_liftfrom the model origin but other positions from the datum (stations from the model centre in the W&B tutorial);wing_sweepis the leading-edge sweep; the EFB divides bywing_cg_refchord; passenger stations are capped at 220 lb; flap stage fields are drag then lift. - Generator: every position from the model origin (empty CG) with the datum at 0, 0, 0;
aero_center_lift−0.51 (was −60.73 = 60 ft aft of the CG as MSFS reads it);wing_sweep27.59;wing_cg_refchord13.04; passenger zones type 0; CG limits 6–32 %; flap tables with the SDK column order and deflection compensation (ΔCLmax per detent from VREF ratios); dihedral 6°; empty inertia 2.6 / 1.0 / 3.3 M slug-ft²; SDK stall ratios. Expected EFB: 21.1 % empty, 22.1 % loaded. Next in the sim:htail_incidencefor zero cruise trim, trim limits, drag polar.
2026-11-04 — M5b-3 servo and autothrottle (build 25)#
- A/T: zibomod's thrust lever logic with MSFS's throttle as X-Plane's throttle ratio and the pilot's last lever as the joystick axis; levers moved by THROTTLE_SET; N1 limits via the engine module's n1-to-throttle-use; AFS speed limit from B738.calc.lua (the oracle default 235 kt was the gear-down limit: A/T reduced thrust before).
- Servo (
afds/servo): our pitch / roll control laws to the FD, trim offload, bumpless; sign L:vars for the field test. Build 24 also showed the levers at idle (zibomod's lever without its throttle input): fixed.
2026-11-04 — panel windows (build 26)#
Panelinstrument on LU_PANEL: Zibo's PANEL_3D groups for the MCP, radio, clock, MMR, IRS display, electrical meter, pressurisation, slat and oxygen windows (docs/PANEL.md). MCP values from the MCP / AFDS L:vars (AFDS now also publishes the V/S dial, digits A / 8, show IAS), NAV fromnav/, COM / ADF / squawk / time / position from MSFS, the meter from the electrics (amps, frequency, warm-up added). Panel lighting knobs at Zibo's defaults.
2026-11-04 — build 27: AP roll direction, ISFD scale#
- Owner: AP engagement rolled the aircraft out of control; ISFD scale wrong. MSFS axis events are opposite to the control SimVars: aileron command negated (elevator was already), yoke / trim read physically, command limits. ISFD drawn at its VCockpit's 768 px (was 1024: cut off).
2026-11-04 — autopilot level-off and MCP speed (build 28)#
- Owner (build 27): the autopilot does not level off at the MCP altitude (LVL CHG, V/S); the MCP speed sometimes
jumps to 100. Both integration gaps (
docs/AFDS.md"Level-off and the MCP speed"):- zibomod's MainFlightLoopCallback copies the altitude into
altitude_pilotfor the flight director; the port did not, so the FD held altitude 0 and kept climbing in ALT HOLD. Closed-loop tests now level off within 5–11 ft (V/S and LVL CHG, climb and descent, with the A/T). - Above the crossover altitude Zibo switches the MCP to Mach through sim/autopilot/knots_mach_toggle and reads X-Plane's flag back; X-Plane's own part of the command was missing, the MCP kept the Mach number as knots and was clamped to 100 kt. Emulated now; the C/O button goes through zibomod's handler.
- Checked against the original plugin (oracle script
afds_mcp_speed_ground.json): LVL CHG / V/S on the ground setting 100 kt is Zibo's own behaviour.
- zibomod's MainFlightLoopCallback copies the altitude into
- Systems module build 28, built with the SDK toolchain under Wine (reproduces the committed build 27 byte for byte). Owner test: TEST_PLAN "Build 28".
2026-11-05 — cold and dark lighting, yoke and CWS (build 29)#
- Owner: the MCP and the clocks light before the battery is on. The panel windows' lit levels
(
instrument_brightness_ratio[n]) were constants from a powered oracle state; now the electrics compute them as zibomod's Systems / Chrono do (bus power, Zibo's lighting knob defaults, daylight): MCP, clocks (F/O clock on DC bus 2), radios, MMR, LE devices, pressurisation, meter. DU states (display_units/*) and the MCP button glow from the same code; NAV status from the AC buses (zibomod Comm); IRS display blank until the ISDU is rewritten. Cold-and-dark comparison with Zibo (battery off / on): every panel window and every 3D light the same. - Audit fixes: bank angle 25 deg at start (A1); A/P, A/T, FMC disconnect lights and the test switches (A2); the pilot's joystick axes observed by the gauge as zibomod's yoke (A3, A5: CMD to CWS on yoke input, CMD refused off centre, disconnect below 400 ft); CWS steering with attitude hold (A4); the pilot's throttle axis for the A/T (A6, partly: MSFS still applies the hardware lever's events).
- Systems module build 29 (SDK toolchain under Wine). Owner test: TEST_PLAN "Build 29".
2026-11-05 — ND track, PFD heading rose (build 30)#
- Owner: the ND map freezes; the PFD heading sometimes flashes.
- PFD: Zibo's heading rose is three images selected by heading range (0-120 / 120-240 / 240-360). MSFS's PLANE HEADING DEGREES MAGNETIC (true heading - variation) can leave [0, 360) near north; X-Plane's never does, so no image was drawn for that frame. All DU and AFDS headings are wrapped now.
- ND: in MAP mode above 45 m/s ground speed it turns with the track, which was MSFS's GPS GROUND MAGNETIC TRACK, a GPS-system variable that is not kept current without an MSFS GPS: the map stopped in flight. The track now comes from the aircraft's velocity (VELOCITY WORLD X / Z) and the heading's variation, in the DUs and the AFDS.
- Not found before: the DU tests and the render / stress harness feed X-Plane-like inputs (headings in range, a GPS track that follows); MSFS's own value ranges and the GPS variables were never questioned.
- Systems module build 30 (SDK toolchain under Wine). Owner test: TEST_PLAN "Build 30".
2026-11-05 — pressurization, yokes, surfaces, LODs (build 31)#
- Pressurization: zibomod's Pressurisation_system, update_press_mode, the mode selector / manual outflow / FLT ALT / LAND ALT / cabin ready commands translated mechanically (tools/re/gen_press.sh, pneu/press_gen.*), the pressurization annunciators of zibomod's Annunciators by hand (pneu/press). Checked against the oracle: 3,076 sampled calls through a whole flight (ground, take-off thrust, climb, ALTN / MAN, FL350, descent, landing), all 102 globals equal (press_replay_matches_oracle; host call hooks press / press_out). Air start: cabin on Zibo's schedule, FLT ALT at the altitude. The digital outflow needle (AFDS) now gets the valve (it sat at -75).
- Yokes were hidden (LevelUp shows them while X-Plane's hide_yoke is 1; nothing wrote it): shown, click toggles; 15 more cockpit variant switches set to Zibo's load values (HUD off, RAAS, RMI, INTV buttons, tablet parts). Yoke / rudder pedal / toe brake animations from MSFS's controls.
- Exterior: aileron and elevator animations reversed (X-Plane positive trailing edge down, MSFS the opposite).
- Exterior LODs: one 243k-vertex LOD was culled by MSFS's LOD limits at a distance (no lower LOD): three lower LODs (30 %, 10 %, 1.5 % of the triangles; gltfpack, every node kept), tools/msfs/build_lods.py.
2026-11-05 — hydraulics and flaps (build 32)#
- Hydraulics and flaps: zibomod's Hydraulic_system, check_hyd_failure, B738_flaps_system, get_flap_time, B738_vib_flaps, the pump / FLT CONTROL / SPOILER / ALTERNATE FLAPS / flap lever commands translated mechanically (tools/re/gen_hyd.sh, hyd/hyd_gen.*), the hydraulic / LE annunciators by hand (hyd/hyd). Checked against the oracle: 4,527 sampled calls (host hooks hyd / flaps / vib), all globals equal except Zibo's rand() draw (hyd_replay_matches_oracle).
- MSFS flaps: the systems module sets MSFS's handle (FLAPS_SET) to zibomod's flap target; the hardware lever becomes zibomod's lever. MSFS moves flaps at one rate, so the flight_model.cfg detent angles are Zibo's cumulative times (tools/msfs/generate_configs.py); the exterior flap / slat animations read zibomod's surface angles.
- Load relief as Zibo's non-SFP -800 (flaps 40 / 30 only). Not yet: yaw damper (in Hydraulic_system, not sent to MSFS), the HYD six-pack light simplified, low-pressure (2.5x slower) flap motion not reflected in MSFS's flaps.
2026-11-05 — gear lever, Mach speed bug, IAS DISAGREE (build 33)#
- Owner (build 32): LVL CHG climbs held 233–236 kt, the MCP's first digit flashed, the A/T went to idle at 260 kt with 280 set, the PFD speed bug sat at the bottom of the tape with Mach .82, IAS DISAGREE with equal speeds.
- Gear lever: the cockpit lever did nothing (list B) and the AFDS read MSFS's gear handle; with the gear left down Zibo's AFS limit is 235 kt (B738.calc), so LVL CHG held 236, the MCP flashed its overspeed "8" and the A/T reduced to 236. Now Zibo's three-position lever (systems_gear.cpp): MSFS's gear follows it (UP needs system A, or B through the transfer unit), a G-key / hardware change moves it, Zibo's ground lock and LOCK OVERRIDE, the three green / red lights from zibomod Annunciators. zibomod's gear actuation itself is not translated (MSFS moves the gear).
- PFD speed bug: B738_mcp_dial reads mcp_speed_dial_kts (zibomod converts Mach); it read the MCP value (0.82).
- The F/O side of the AFDS read MSFS's airspeed indicator 2 (not the F/O's pitot here): IAS DISAGREE with both PFDs showing indicator 1. Both sides read indicator 1; the speed limits module too (it read index 0).
2026-11-05 — zibomod Systems: gear, speedbrake, brakes, autobrake, stab trim, yaw damper (build 34)#
- zibomod's Systems (7,000 lines of pseudo-C: gear, brakes / autobrake / RTO, speedbrake lever and auto speedbrake, stab trim, steering, ...), Annun_timers, Systems_start_flight and the gear / speedbrake / brake / trim / yaw damper commands translated mechanically (tools/re/gen_sys.sh, sys/sys_gen.*; tools/re/sys_fixups.py for a stack array Ghidra split, the lost stab_trim_ratio results, the fuel selector types). Checked against the oracle: new host hooks around MainFlightLoopCallback -> Systems, its subsystems (Electric_bus, Hydraulic_system, Pressurisation_system, Gpws .. B738_autoland_fail: their results replayed) and Annunciators -> Annun_timers; sys_trace.json (gear, yaw damper, trim and cutouts, speedbrake, landing with auto speedbrake and autobrake, brakes, RTO, gear lock): 672 samples, every global equal (sys_replay_matches_oracle).
- MSFS (systems_sys.cpp): gear handle follows zibomod's gear target, spoilers handle zibomod's speedbrake ratio (MSFS's arming off), brakes = zibomod's brake ratios and X-Plane's parking brake ratio zibomod brakes with (autobrake, RTO), MSFS parking brake = the lever, elevator trim when zibomod trims, yaw damper when zibomod's hydraulics engage it (the IRS inputs it needs were missing since build 32). The pilot's G key, spoiler axis / keys, parking brake key and brake pedals go to zibomod. Lights: SPEED BRAKE ARMED, SPEEDBRAKES EXTENDED, AUTO BRAKE DISARM, PARKING BRAKE, STAB OUT OF TRIM, YAW DAMPER (zibomod Annunciators by hand, sys.cpp).
- A/P stab trim stops with the AUTOPILOT cutout switch.
- Not yet: reversers (cockpit reverse levers; MSFS's throttle reverse range as before), aileron / rudder trim switches send MSFS's own trim, wheel speeds from ground speed (no skid model).
2026-11-05 — reversers, fuel system (build 35)#
- Reversers: the cockpit reverse levers (engage = reverse idle, INC / DEC, disengage = stowed; interlock with the forward thrust lever at idle) set MSFS's throttle in its reverse range; the pilot's reverse range (F2, hardware) moves the lever. zibomod's Systems / AFDS get the reverse state (X-Plane prop mode) and MSFS's nozzle deploy ratio; the engine model's N1 follows the reverse lever; the EICAS REV indication reads the deploy ratio.
- Fuel: zibomod's pump / crossfeed commands (translated with Systems), Systems' fuel feed (pumps running by switch and AC transfer bus, centre auto shutdown, suction feed above an N2 by altitude, crossfeed, spar / engine valves) gives the engines' fuel selectors (no fuel: the engine starves, as in X-Plane); MSFS's tank pumps and crossfeed valve follow zibomod's (the forced main tank pumps of the engine coupling removed); LOW PRESSURE and CROSSFEED VALVE OPEN lights from zibomod Annunciators by hand (sys.cpp, with the attitude-dependent unusable fuel).
- Not yet: the FUEL six-pack light, fuel imbalance / LOW fuel indications, fuel temperature.
2026-11-05 — review fixes: CI, glideslope, left-click controls, hardware throttle (build 36)#
- CI: the native test job's sparse checkout lacked
xphost/(the tests linkxphost/src/json.cppand readxphost/test/sci), so every build-wasm run since the SCI tests failed in "Native unit tests" while the SDK build passed. Checked out now. - Glideslope (owner: LOC right, GS not seen): the PFD / ND glideslope flag read MSFS's
NAV GS FLAG, whose sense is unverified and which probably hid the pointer; it now comes fromNAV HAS GLIDE SLOPE. The AFDS tookNAV GSI(0 = centred) also without a glideslope, a false G/S capture risk: full scale then. An ILS tuned while only the localizer was received stayed LOC-only (Zibo knows the glideslope from its database): it becomes ILS when the glideslope comes in. Found while testing: zibomod's AFDS reads each side's active MMR mode, deviations-shown flag and deviations from Zibo's FMS Lua (mmr_active_mode), which nobody computed:mmr_act_modestayed 0 (VOR) andnav_horz_dsp0, so APP never armed and VOR LOC / APP never captured (the LOC the owner saw was the PFD's pointer). Ported, with the VHF NAV source switch (both on 1 / 2), and Zibo's rule that a deviation of exactly 0 is no glideslope. New closed-loop test: APP arms, LOC captures, G/S stays armed without a glideslope and captures when it comes in. The GS sign is still to be confirmed in the sim (docs/AFDS_AUDIT.md D). - Cockpit controls: left button and wheel only (owner: looking around with the right button moved controls). Right clicks removed from every MouseRect (knobs: left / right half, switches: upper / lower half, as before).
- Hardware throttle against the A/T (owner: they fight): the gauge masks MSFS's throttle events (SimConnect,
highest maskable priority: axes, THROTTLEn_SET, FULL / CUT / INCR / DECR) and the systems module places the levers
(
wasm/src/core/thr/thr_arbiter.h).L:LU737_THR_HW_MODE0 last mover (default): the A/T's levers ignore axis noise; moving the hardware more than 3 % is a manual override relative to the A/T's lever (no thrust jump); 2 s after the hardware stops the A/T has the levers again; without the A/T the hardware takes the levers once it reaches them (pickup). 1 follow the A/T, 2 follow the hardware. Reverse from the hardware passes at once.L:LU737_THR_HW_STATE_1/2shows the state. Without SimConnect the old observing path stays. - Aileron / rudder trim as zibomod: the cockpit switch / knob call zibomod's handlers of X-Plane's trim commands; the switch and dial animate to their target (zibomod Switches, Anim_value rate 10); the trim moves as X-Plane's own command does for this .acf (aileron -1..1 in 8 s, rudder in 30 s; bus 1 power) on MSFS's AILERON / RUDDER TRIM PCT (read first, so MSFS's trim keys still work). A click or a knob step trims 0.25 s (the cockpit sends press and release together; before, it trimmed nothing). Still open: the trim switch / dial / rudder trim indicator only animate to the right (the converter baked their 2-key animations over 0..1 only: data/xp_to_msfs_map.json "ranges", needs a model conversion run).
Tests: native 132 (new: G/S capture, NAV LOC->ILS, throttle arbiter 8, aileron / rudder trim), avionics 55.
2026-11-05 — options in one place, Zibo option defaults (build 37)#
- docs/OPTIONS.md rewritten: the options settable now (with
L:LU737_THR_HW_MODE), the troubleshooting sign switches, and every option of Zibo's config files (~270, fromB738.a_fms.lua) with Zibo's default and its status here (L:var / fixed at Zibo's default / not yet / n/a in MSFS); diagnostics extended. - Found while listing them: options the ported zibomod code reads were 0 where Zibo's default is not: Systems
parkbrake_remove_chock1,tire_blown1,pfd_fmc_flap_spd1, the hardware flap axis detents (0 … 0.9375),ctr_fuel_pump_auto1 (build 35's centre pump auto shutdown never ran); AFDSspd_intv_but1 (the model shows the SPD INTV button),vnav_wakeup_idle15,yoke_to_center1 (zibomod's start of flight zeroes them; Zibo's Lua sets them). All set to Zibo's defaults (the oracle's values where it traces them).
2026-11-05 — ALT DISAGREE, panel backlights (build 38)#
- ALT DISAGREE with both BARO knobs equal (owner): the AFDS compared the captain's altitude with MSFS's
INDICATED ALTITUDE:2, whose altimeter (MSFS altimeter 2) nothing sets. The F/O altitude is now the captain's indicated altitude plus what the F/O's setting changes in the altimeter equation (equal settings: equal altitudes), in the AFDS and on the F/O PFD; the AFDS's F/O barometer setting is the F/O knob. - Radio / transponder backlights and the LE DEVICES panel (owner: the lit boxes are skewed): Zibo's PANEL_3D gives
the radio backlight images
CORNERS(corner offsets: bottom-left, top-left, top-right, bottom-right, panel pixels, y up), which the display compiler dropped, so the COM / NAV / ADF backlights sat 80 px left of their windows and bled into the neighbouring LE DEVICES windows.build_display.pykeeps them (co), PanelView draws gen_rotary images onto the moved corners (CSS matrix3d). Checked by overlaying the cockpit model's panel-window UVs on a night render: every backlight inside its window. EICAS / lower DU boxes with CORNERS (a few pixels) follow too; gen_LED / gen_pie CORNERS (sub-pixel / N2 pie) not yet.
2026-11-05 — trim switch / dial / indicator animate both ways#
- The aileron trim switch, the rudder trim dial and the rudder trim indicator only moved to the right: their OBJ
animations are 2-key (X-Plane extrapolates below 0) and the converter authored keyframes over 0..1.
data/xp_to_msfs_map.json"ranges" gives them -1..1; the cockpit model was reconverted (the converter reproduces the committed interior byte for byte without the change; with it exactly these three animations differ) and the behaviours regenerated. The exterior model was left as committed.
2026-11-05 — M5c: architecture decided, Lua 5.1 in the systems module (build 39)#
- Decision with the owner: Zibo's original FMS Lua runs inside the systems module on PUC Lua 5.1 under a C XLua host; navdata from MSFS 2024 itself. Measurements and plan: docs/M5C_PLAN.md (survey: docs/M5C_FMS_SURVEY.md).
- third_party/lua-5.1.5 (MIT): Lua errors without setjmp / exceptions through a Binaryen Asyncify unwind
(
wasm/tools/asyncify.pyafter the link: only Lua's functions instrumented, the SDK's StackSizesSection re-indexed and checked by function name, GuardPages kept). Lua is C in every build. - Spike (tools/fms_spike): the real a_fms runs in WASM Lua 5.1 + Asyncify: RTE, a 40-waypoint route (9 LEGS pages), PERF INIT; 3.8 ms per frame with the XLua glue in C (0.9 ms without a route).
- Build 39 runs a Lua self-test at load (
L:LU737_LUA_SELFTEST= 1): the check that MSFS runs the Asyncify-processed module. CI: the Lua sources in both jobs' checkout.
Tests: native 134 (new: Lua self-test). Module built with the SDK toolchain (3.5 MB).
2026-11-05 — build 40: the Asyncify step keeps the SDK module's form#
- CI (Windows): the Asyncify step got MSYS paths (
/d/a/..., read asD:\d\a\...) and needsnpx.cmd: Windows paths andshutil.which. - Owner: build 39's module did not work in the sim. wasm-opt had changed the module's form: its
target_featuresdeclared mutable-globals / sign-ext / bulk-memory-opt (the SDK toolchain declares only bulk-memory), it added a DataCount section and fiveasyncify_*exports.wasm/tools/asyncify.pynow keeps the SDK build's own target_features, drops DataCount (no memory.init / data.drop in the module) and the exports, and enables only bulk-memory: the section layout equals build 38's.
2026-11-05 — build 41: Lua self-test on request#
- Owner (build 40): BUILD 40, ALIVE 1, but the cockpit does nothing: the gauge most likely stopped in the Lua
self-test at load. The self-test now runs only on request (
L:LU737_LUA_SELFTEST_RUN= 1, in a frame), withL:LU737_LUA_SELFTEST_STEPand a console line before each step (checks without Lua errors first, then the error recovery), so a crash shows its step. If the cockpit still does nothing with no Lua running, the Asyncify-processed module itself is the problem.
2026-11-05 — build 42: 1 MB stack, Lua self-test one step per frame#
- Owner (build 41): the cockpit works until
L:LU737_LUA_SELFTEST_RUN= 1; then the gauge stops (frame counter stuck, nothing in the console). The module's stack was the wasm-ld default 64 KB (data, guard page at 0x80000, stack 0x90000–0xA0000): too small for Lua (parser, protected calls); an overflow hits the guard page and stops the gauge silently (offline tests used 1 MB). Linked with-z stack-size=1048576now (stack 0x90000–0x190000). The self-test runs one step per frame:L:LU737_LUA_SELFTEST_NEXT(about to run) andL:LU737_LUA_SELFTEST_STEP(finished) survive a crash.
2026-11-05 — every display dark since the CDU commit: Object.fromEntries#
- Owner: builds 39–42, all avionics dark (the systems module running). The CDU sources (shared by every display
unit through DuSource) used
Object.fromEntriesandglobalThis, which MSFS's JS engine lacks and esbuild (target es2017) does not polyfill: every display's script stopped at load. Replaced by plain loops /window;avionics/build.mjsnow fails on these APIs in a bundle. - Lua self-test in build 42: steps 1–4 pass in MSFS (state, libraries, code without errors), the gauge stops at step 5, the first Lua error: the Asyncify unwind does not work in MSFS as built. Investigating offline with the SDK-built module itself.
2026-11-05 — build 43: Lua errors work in the shipped module#
- Reproduced build 42's freeze offline:
wasm/tools/fake_msfs_host.pyruns the SDK-built module itself in wasmtime with every MSFS import provided (gauge API with an L:var store, WASI,commit_pages) and drives the gauge callback as the sim does. Step 5 trapped exactly as in MSFS:unreachableinlua_gettop, right after the first protected call returned. - Cause:
luai_asyncify_catch(called byluaD_rawrunprotectedto stop the unwind) was itself instrumented. An instrumented function entered while the Asyncify state is "unwinding" skips its body, sostop_unwindnever ran and the next instrumented Lua function hit itsunreachableguard. The clang 18 -O2 spike build had inlined the catch intoluaD_rawrunprotected, which hid it; the SDK build calls it. - Fix (
wasm/tools/asyncify.py): the catch stays uninstrumented withluaD_rawrunprotected; the build fails if either is missing from the Lua objects.--optimize-level=2lets Asyncify optimise the functions it instruments (no module-wide passes, function indices unchanged): module 3.55 MB → 2.80 MB. - Build 43 in the fake host: self-test 10/10, frames continue. Timing loop (wasmtime): SDK module 580–660 ms,
clang 18 -O3 module 460–540 ms. CI now runs the fake host on both builds (
build-wasm.yml), so a module that would stop the gauge fails CI.
2026-11-05 — build 43 in MSFS: Lua self-test 10/10#
- Owner:
L:LU737_LUA_SELFTEST1, 10 / 10, STEP / NEXT 13 / 13, timing loop 1565 ms. Lua errors (protected, nested, C, unprotected, 1,000 in a loop) are recovered in the sim: the Asyncify approach works in MSFS. - MSFS runs the module about 2.5× slower than wasmtime (580–660 ms there). Estimate for Zibo's FMS in MSFS:
~3 ms per frame without a route, ~12 ms with a 40-leg route; plan in
docs/M5C_PLAN.md(measure in the sim first, run the FMS at its own rate).
2026-11-05 — build 44: Zibo's FMS runs in the systems module (M5c)#
B738.a_fmsunmodified on a C XLua host inside the systems module (wasm/src/core/fms/, details indocs/M5C_PLAN.md"Build 44"): CDU pages on both CDU screens over the CommBus, the cockpit CDU keys, EXEC / MSG lights. No navdata yet (NAV DATA blank, NOT IN DATA BASE for any airport), no LNAV / VNAV, no keyboard.- Native: MENU → IDENT → POS INIT (the sim's zulu time and date), N1 LIMIT, RTE, typing KSEA; 0 Lua errors; about 3 ms per FMS run in the sanitizer build. Fake MSFS host, SDK module: load 395 ms, 4 ms per run (wasmtime; MSFS about 2.5× slower), 0 Lua errors.
- Found on the way: with no scenery pack, Zibo's
create_apt_rnw_dat2calls:close()on a number when it cannot create its cache file. Its aircraft folder is now MSFS's\work\(writable); the native tests used the working directory before this and leftB738X_*.datthere (gitignored, removed). - Owner checks:
L:LU737_FMS_STATE1,_LOAD_MS,_MS/_MS_MAX(the FMS's cost in the sim; 20 Hz byL:LU737_FMS_HZ),_ERRORS0; CDU MENU at power-up,<FMC→ IDENT, the page keys; the EXEC light.
2026-11-06 — build 45: owner's build 44 test flight#
- FMS in MSFS (owner): state 1, 0 Lua errors, load 920 ms, 6.9–7.4 ms per run (max 18 ms) at 20 Hz.
- CDU keys did nothing (not even CLR): the cockpit interface named click spots after their 3-D nodes
(CLR, A_9, PERIOD_2, ...); only the line-select keys, whose nodes carry the command name, reached the FMS.
CDU keys are now named after their commands, 69 per CDU (
tools/sci/generate_cockpit_sci.py; testfms_every_model_cdu_key_reaches_the_fms). The regeneration also kept a hand-written contract state (20_hyd ANNUNCIATOR_STD_RUD_ON) from being duplicated as a_2nothing writes. - REV over the N1 limit on the EICAS: the limit digits' visibility (
eng<n>_N1_bug_dig, AFDS) was a display placeholder fixed at 1; it reads the AFDS's value now (0 with the reverser deployed). Test with reverse thrust. - LOC S-turns on the A/P: deviation scaling by the measured beam width and a faster bank loop
(
docs/AFDS_AUDIT.mdA9). - The owner's APU overspeed change (1680b1d: N1 climbs to 107 % before the trip, about 3.7 s) fails the native
test
apu_overspeed_and_low_oil_failures, which expects Zibo's trip at N1 > 99 within 3 frames: left for the owner to decide.
2026-11-06 — build 46: APU overspeed you can trigger, OVERSPEED / MAINT lamps#
- Owner's APU overspeed model kept (N1 to 107 % before the trip);
apu_overspeed_and_low_oil_failuresfollows it. - APU failures from the sim:
L:LU737_FAIL_APU_*(docs/OPTIONS.md§2b); nothing set them before (only tests). - The cockpit's APU OVERSPEED and MAINT lamps never lit: Zibo's object (
737_cockpit_switch.obj) lights them only in a shared lights-test batch (laminar/B738/annunciator/generic); zibomod'sover_speed_apu/maint_apuhad no lamp.data/light_splits.json(applied intools/xplane/obj8.py) moves each lamp's triangles into a batch of its own, lit by that dataref (L:LU737_ANN_APU_OVERSPEED/_MAINT, which include the lights test).
2026-11-06 — build 47: owner's 17-item list (build 46)#
Fixed (offline checks; the sim check is the owner's):
- 1 CDU text / F/O clock lit with the battery off: X-Plane's BUS_SRC (an element lights only with its power source) was ignored by the display builder; now a show condition (bus 3 DC power, bus 7 hot battery bus); the CDU screens have their own power gate (CDU1_PWR / CDU2_PWR, Zibo's mcdu1_on / mcdu2_on).
- 2 yokes did not move: the yoke columns / wheels animate with zibomod's laminar/yoke/pitch, pitch2, roll, which our port never computed; now MSFS's yoke position (roll animation range widened to -1..1).
- 3 LE DEVICES test did nothing: the panel's power_on_buses / annunciator/flaps_test were placeholders at 0; flaps_test = FLAP TEST held or the lights test (zibomod Annunciators), power_on_buses = DC power.
- 4 speed brake / flap levers: the mouse wheel followed the lever's value (which grows aft); it follows the screen now, as the drag does (also gear, reversers, grab handles, tillers).
- 6 stab trim wheel: zibomod's manual trim command wrote the trim and its X-Plane input together, so no change was seen and the next frame read MSFS's trim back; changes are tracked against the trim MSFS last gave. A wheel step is about 1 s of cranking (1 % of the range). Test stab_trim_wheel_moves_the_trim.
- 7 tillers did not turn: laminar/B738/nosewheel_steer_ratio was never published; MSFS's nosewheel angle now.
- 8 exterior left aileron reversed: MSFS's left / right aileron deflections have the same sign for a roll input.
- 9 MCP lamps never lit: they are hidden while laminar/B738/brightness_level2 < 0.01 and nothing published it; zibomod's brightness2_export = battery bus x brightness x day (annunciator brightness), also the AFDS's lights test value.
- 11 GPU / APU GEN / ENG GEN (spring switches) showed no movement: a click sent the position and its RELEASE at once; a spring position is now held from the press to mouse up, as X-Plane does.
- 13 cockpit vanishing from outside: LOD0's glass is transparent and MSFS stops drawing the interior first; LOD0 now ends at 40 % of the screen (was 25 %), the opaque LOD1 takes over sooner. Tunable in build_lods.py.
- 15 engines did not turn: the fan animations read L:LU737_fan_angle_1/2 (written by the removed JS gauge) and ENGINE_ROT_ANG0/1 over a 0..1 range; both are the fan angle in degrees now, 0..360.
Audit: of the 942 L:vars the cockpit model reads, 579 are not published by the systems module
(model_lvars_the_systems_publish, LU737_MODEL_LVARS=<list>): mostly systems not rewritten yet (IRS display unit,
audio panels, doors, lighting knobs, push-button press animations). Several reported items came from this.
Open: 5 (heavy controls without hydraulics: MSFS has no control-force output, needs a design), 10 (INTV buttons: small click spots behind the knob; with the button press animations), 12 (IRS display unit: not rewritten), 14 (flicker: needs where / what), 16 (start states: FLT files saved in the sim), 17 (cabin differential jumping after landing: needs the values).
2026-11-06 — build 48: manual reversion, EFIS knob centre buttons, cabin window flicker#
- 5 heavy controls without hydraulics (owner: do it): manual reversion,
L:LU737_MANUAL_REVERSION(docs/OPTIONS.md). The gauge masks AXIS_ELEVATOR_SET / AXIS_AILERONS_SET (SimConnect, added to a notification group only while reversion is on); the systems send ELEVATOR_SET / AILERON_SET at 60 % authority and 0.8 / s. Test manual_reversion_slows_the_stick_without_hydraulics. - 10 EFIS STD / RST / CTR / TFC (both sides) hard to click: the knob's click spot took the cursor. 12 ring / knob
click spots (
data/knob_center_buttons.json,tools/msfs/find_knob_buttons.py) push their centre button when pressed within 4 mm of the centre (Asobo's push knobs, CENTER_RADIUS 0.004). - 14 window flicker (owner's video): the cabin windows' inner panes (cabin/737_80NG_glass_interior.obj) lie 5.4 mm inside the outer panes; MSFS draws the interior from outside too and the two layers z-fought. The inner panes are left out of the MSFS interior (not visible from the flight deck).
2026-11-07 — build 49: 10 and 14 rolled back, manual reversion diagnostics#
Owner, build 48: 5 the stick still moves freely to full deflection, then jumps to a fraction of it; 10 and 14 unchanged; roll them back, the owner will look at them.
- 10 and 14 rolled back to build 47:
generate_behaviors.pywithout the centre zones, the cabin windows' inner panes back in the interior,LU738_INTERIOR.*anddata/cockpit_io.jsonfrom build 47;data/knob_center_buttons.jsonandtools/msfs/find_knob_buttons.pyremoved. - 5: the stick unresisted, then the slowed value once the stick stops, is what the systems' output does when the
mask does not hold: MSFS applies the stick's own events; ours (sent only when the slowed value changes) win when
the stick stops sending. Why the mask does not hold is not known from here; the gauge now tells:
L:LU737_SIMCONNECT,L:LU737_REV_MASKED,L:LU737_REV_SC_EVENTS,L:LU737_REV_KEY_EVENTS,L:LU737_REV_KEY_LAST,L:LU737_SIMCONNECT_EXCEPTION(docs/OPTIONS.md§2). Until it does,L:LU737_MANUAL_REVERSION 0turns it off.
2026-11-07 — build 50: M5c navdata, design and the X-Plane folder#
docs/M5C_NAVDATA.md: how Zibo's FMS loads navdata (load order, every table's rows and indexes, the X-Plane file fields it reads, CIFP procedures on demand, AIRAC, magnetic variation, volumes) and the provider's design: a cache in X-Plane's formats written from MSFS's facility database, read by native loaders checked against Zibo's own; CIFP per airport on demand.- XLua host: Lua's
io.openputs Zibo's relative paths (Custom Data/...,Output/FMS plans/...) under\work\xp\and makes the folders of a written file (xlua_set_root).
2026-11-07 — build 51: native navdata loaders#
wasm/src/core/fms/xlua_nav.c: Zibo'sread_navdata2,read_rnw_dat,read_apt_dat,read_awy_dat2andcreate_idx_tablein C, line for line (docs/M5C_NAVDATA.mddesign 3), replacing his in the script's namespace after it loads. Testnavdata_native_loaders_equal_zibos: the 29 tables / indexes / globals equal to Zibo's loaders' on the same files; 3.4 s → 0.6 s on 20,000 fixes (test build). No navdata in the sim yet: the files come with the MSFS crawler (next).
2026-11-07 — build 52: navdata from MSFS's facility database#
fms/navdb.cpp: MSFS's records written in X-Plane's formats (earth_nav / fix / awy / hold) and Zibo's airport / runway caches (his header, his runway sort and measures),\work\xp\and\work\.fms/nav_crawl.cpp: the whole world asked for over frames (lists, then VOR / ILS, NDB, airport + runways, enroute waypoint + airways), 200 requests in flight; answers that never come are counted and skipped. Facility fields, layouts and units:docs/MSFS_FACILITY_DATA.md.fms/nav_provider.cpp: the cache of the current AIRAC cycle, or a crawl → files → FMS reload.L:LU737_NAV_STATE/_PROGRESS/_REQUESTS/_LOST/_COUNTS,L:LU737_NAV_REBUILD,_BATCH(docs/OPTIONS.md).- Checked: native tests (writer files read by Zibo's loaders and ours equal; the crawler against a fake facility
source; crawl → reload → cache hit); the shipped module in
fake_msfs_host.py, whose SimConnect now answers facility requests as MSFS does (lists in parts, data items, data end through CallDispatch): it crawls, writes the files and reloads the FMS. Not yet seen in MSFS: the field names and layouts are from the SDK header and an open-source loader, a refusal shows asL:LU737_SIMCONNECT_EXCEPTION.
2026-11-07 — build 53: SID / STAR / approaches from MSFS#
fms/nav_procs.cpp: an airport's departures, arrivals and approaches from MSFS's facility data written as X-Plane'sCIFP/<ICAO>.dat, which Zibo's FMS reads for the DEP / ARR pages (docs/M5C_NAVDATA.md, build 53).- When: the XLua host reports the files the scripts fail to open; a missing CIFP file (the pilot entered the
airport) is fetched and written within a second or two, so the DEP / ARR page shows it when opened. The 3
airports within 25 nm of the aircraft are fetched once the navdata is ready.
L:LU737_NAV_PROCS/_PROCS_FAILED. - Checked: the generated file read by Zibo's own
read_ref_data/read_des_data(native test); the shipped module fetches and writes KSEA's procedures infake_msfs_host.py, whose A:var reads now return values (the result pointer was in the wrong argument: every A:var had read 0 there).
2026-11-07 — build 54: owner's build-53 test#
- Manual reversion: masked in cold & dark (
L:LU737_REV_SC_EVENTS1006, the key handler saw none), but after the hydraulics came on and went off again the stick moved freely: adding the axis events to the masked group again after removing them did not mask. The axes now stay masked from the first frame whileL:LU737_MANUAL_REVERSIONis 1; with hydraulic pressure the systems pass the stick on as it is (ELEVATOR_SET / AILERON_SET when it moves; testmanual_reversion_passes_the_masked_stick_with_hydraulics). - EFIS knobs / window flicker: back as before (rollback confirmed).
- Navdata:
L:LU737_NAV_STATE-1 with nothing listed: the world list requests (SimConnect_RequestAllFacilities) were refused or not answered (no exception). Now: the older list messages are read too; if the world lists are refused or not answered within 20 s,SimConnect_RequestFacilitiesList(airports of the world; navaids and waypoints around the aircraft) and the airways followed from waypoint to waypoint, every facility met asked for (as Little Navmap reads MSFS); readoutsL:LU737_NAV_FAIL,_FALLBACK,_LISTED,_FOUND,_RECV_LAST, the message kinds in the console. Testsnavdata_crawler_falls_back_and_follows_the_airways,navdata_crawler_fails_without_lists. - M5 LNAV: zibomod's navigation translated (
docs/LNAV.md), not wired yet.
2026-11-07 — build 55: navdata lists first, airways / runways on demand#
- Owner, build 54:
L:LU737_NAV_LISTED349,087 (the world lists answer in seconds),_PROGRESS4.4 % after minutes: asking for every facility's details one by one is far too slow. Now the lists are the files at once (the FMS reloaded within seconds of the load), the VORs' / NDBs' details follow in the background nearest first, airways and airport runways / localizers / transition levels on demand (docs/M5C_NAVDATA.md, build 55;docs/OPTIONS.md). The owner agreed to Zibo's NOT IN DATA BASE / INVALID ENTRY on the first entry. - XLua host:
lu737_call(...)(the scripts' calls to the host),xlua_run(Lua in the script's namespace). - Fixed on the way: the crawler's request order for facilities found during the details indexed past its array (VOR lists).
- Tests:
navdata_provider_crawls_writes_and_reloads_the_fms(lists first, details, a VOR's frequency into the FMS's row, an airway Zibo's find_awy misses then finds); the fake MSFS host (one localizer, with its runway).
2026-11-07 — build 56: airports asked for by their ident#
- Owner, build 55: the lists (message kinds 18–21) and the VOR / NDB details came in within seconds
("AIRAC 2611 … FMS reloaded"; "details done: 7808 navaids"), but every airport's procedures failed
(
L:LU737_NAV_PROCS0,_PROCS_FAILED4,L:LU737_SIMCONNECT_EXCEPTION1; DEP page: SIDs / runways NONE). The airport requests usedSimConnect_RequestFacilityData_EX1with type 'A', which MSFS refused. Airports are now asked for withSimConnect_RequestFacilityData(ident alone, as Little Navmap asks for them); VORs / NDBs / waypoints keep_EX1. - New L:vars:
LU737_SIMCONNECT_EXCEPTION_INDEX(the refused call's parameter),LU737_SIMCONNECT_EXCEPTIONS(count). - Fake MSFS host: answers the plain request and checks that the airports use it.
2026-11-07 — build 57: owner's build-56 test; ND range arcs as Zibo#
- Owner, build 56: SIDs load (RTE LEGS of WMKK: KK720, OLKAN, KK721, MATPO), so airports by ident work. The ND showed no route, and in PLN the expanded map's three range arcs.
- The arcs:
EFIS_control/capt/ringswas a constant 1 (the oracle's value in its only EFIS state, MAP expanded), never Zibo's glareshield formula. Now the systems module's (L:LU737_EFIS_RINGS_CAPT/_FO): expanded APP / VOR / MAP with WXR, TERR or TFC on; 0 in PLN and centred. TFC's toggle starts on as Zibo'scpt_tcas_enable(it started off). Testefis_nd_rings_as_zibo. - Why the tests missed it: the ND oracle (
nd_trace.json) never turns the mode knob, so PLN / APP / VOR / CTR were never compared; a pending value copied from the oracle hides a mode dependence. Next ND oracle: the four modes and CTR, and a review of the other pending values that are not 0. - The route on the ND is not drawn yet (docs/ND.md: pending): zibomod (not Zibo's Lua) computes the symbols' positions and draws the lines, arcs and PLN circles with OpenGL. It is ported after LNAV, which shares its path.
- Owner: the on-demand lookups (airways, an airport's procedures) took too long. Where the time went:
- an airway's first fix is asked for as a waypoint, a VOR and an NDB; MSFS refuses the types it is not (an exception, no data end), and the job waited for the stall frames (300, about 5 s) before the airway counted;
- the airway's segments reached the FMS only when the whole airway was followed, though the VIA entry needs the first one only;
- the airport the FMS asked for queued behind the airports near the aircraft (prefetch), and a refused request
waited 10 s.
Now: the gauge keeps each facility request's packet id (
SimConnect_GetLastSentPacketID); an exception naming it ends the request at once (NavProvider::onRefused,L:LU737_NAV_REFUSED; not counted as a SimConnect exception). Each airway segment goes into the FMS as it arrives. The FMS's airport goes first. Stall frames for airways 120. Tests: the provider test (a refused NDB request ends the airway job within 3 frames), the fake MSFS host (a refused NDB detail).
2026-11-07 — build 58: the FMS's inputs and outputs#
- Owner, build 57: entries fail the first time (on demand, as agreed), TAKEOFF REF without N1 / V-speeds / TOW, no
VNAV, ND MAP without range arcs, PLN without waypoints. Found: 380 of the scripts' inputs were X-Plane's cold &
dark values, and
B738.calc(N1 limits, V-speeds) never ran. docs/FMS_INPUTS.md. B738.calcruns on the XLua host withB738.a_fms. The generator no longer takes a commented-outcreate_datareffor one the script creates (calc'sap_goaround,fd_goaroundhad no value at all).- Inputs: MSFS's A:vars (more: AP references, attitude, air data, NAV receivers), the L:var convention for
sim/too, andSystems::addFmsSources: zibomod's globals and X-Plane values from the ported modules' field tables, the EFIS / MCP / payload / reversers / ADF bearings. Unfilled: 85 read by the scripts, of them about 60 the LNAV path (pending), the station identifiers (strings), ACARS.wasm/out/fms_unbound.txt. - Outputs: 266 numbers the scripts create that the displays read,
L:LU737_FMS_<NAME>; the displays' pending sources read them (V-speed bugs, flap bugs, FIX circles, ...). - Test
fms_perf_init_gives_takeoff_speeds(Systems, GPU power, PERF INIT, TAKEOFF REF flaps 5): N1 98.7, QRH V1 134 / VR 136 / V2 146 selected, TOW,L:LU737_FMS_FMS_V1134. Before:---.-,---. - Not done in this build: LNAV / VNAV (the path and the AFDS modes), the ND route, auto re-entry after NOT IN DATA
BASE, the ND range arcs question (owner to read
L:LU737_EFIS_RINGS_CAPT,_TFC_CAPT).
2026-11-07 — build 59: VIA entries wait for the airway#
- Owner: load the airway first, wait, report an error only if there is none. A VIA entry (RTE page; Zibo's
via_add/via_chg) for an airway the FMS's tables do not have is held (no INVALID ENTRY; the scratchpad keeps it) while the provider follows it from the fix (lu737_call("awy")). When the provider is done (lu737_awy_done, found or not; told at once when there is nothing to fetch) or after 8 s, the entry runs again if the scratchpad still holds it: taken, or Zibo's own INVALID ENTRY. Each airway is held once (lu737_awy_asked);lu737_awy_retriednames the last one run again. Glue:fms.cppkNavGlue. - Test (provider): RTE page as the pilot types it (KSEA / KSEA, TO ALPHA, VIA J1): held, then J1 on the row; VIA changed to J9 (none from ALPHA): held, then not taken, J1 kept.
2026-11-07 — build 60: LNAV in the systems module#
- zibomod's navigation (translated, oracle-checked in build 59) runs each frame between the AFDS's Glareshield part
and its flight director, as in zibomod (docs/LNAV.md "In the systems module"). Its links to the AFDS, the FMS's
datarefs and MSFS are generated (
tools/re/lnav_sync.py->lnav/lnav_sync.inc): the copies between the ports, MainFlightLoopCallback's dataref reads before the block (from its disassembly), zibomod's registered datarefs of the navigation (both ways through the FMS's XLua store), and Read_B738_DR for the AFDS (145 inputs from the Lua FMS: legs_num, end_route, the courses to fly, N1 mode, ...). - Test
lnav_flies_the_route_in_the_systems: airborne heading 180 near KSEA, the route on the CDU, DIRECT TO, FD, LNAV, CMD A: LNAV engaged, course to fly 200.6 towards the first fix, flight director 8 degrees right. - Fixed on the way: an AFDS translation fault the FMS's inputs reached (two stack floats passed as an array:
tools/re/afds_fixups.py). The generators strip Lua comments as Lua does (tools/re/lua_strip.py; the same result for Zibo's scripts today). - Not yet: VNAV (zibomod's VNAV path is not translated), the ND route, the station identifiers.
2026-11-12 — build 61: the ND's route drawing#
- Owner: the ND route first. zibomod draws the route on the NDs with OpenGL (
NDRender_opengl: legs, turn arcs, RF / AF legs, holds, procedure turns, runway, PLN circles), not with the panel's gauges; translated with the LNAV (28 more functions: the drawing,NDRender_xplane/NDRender_xplane2,calc_panel_coord) and checked against the oracle: the oracle records zibomod's OpenGL calls (gl_capture, each 30th frame), the replay draws withlnav.h's recorder: 119 frames, every vertex and colour the same; the LNAV replay still 0 differences (strict too). docs/ND_ROUTE.md. - In the systems module in zibomod's order (
NDRender_xplane,NDRender_xplane2between the navigation block andfms_turn, with what MainFlightLoopCallback copies before them: EFIS mode / range, headings, power); the drawing goes to the NDs on the CommBus (LU737_ND_GL, 15 times a second) andavionics/src/du/NdDraw.tsdraws it on a canvas over each ND. The EFIS's mode, range, DATA / POS / TFC now reach the FMS store as Zibo's glareshield datarefs. Testlnav_flies_the_route_in_the_systems: magenta route lines, every vertex inside the NDs. - Translation faults fixed in the tools (no hand edits):
TransformX/TransformYreturn doubles (decompile.py);last_xa double, not a pointer (port_cpp.py); stack colour arrays, int pairs, short arrays with named tails, string+/+=/to_string,glLineWidth's argument (lnav_fixups.py). - FMS bug fixed (also in build 60): the points the navigation inserts into the route (
fms_add_data_2..6) were published as integers' bits; after a DIRECT TO the modified route could hold a point at latitude 0 (found when the ND drew a NaN line and the clipper hung).Clip_rectno longer loops on a NaN line. - Not yet: the waypoint names / altitudes / ETAs beside the route and the TOC / TOD / decel symbols (computed, not sent to the NDs yet), navaids / airports on the map, TCAS, terrain, weather; the NDs' BRT knobs (full); VOR / ADF bearing lines; the drawing's cost in MSFS not measured yet (the fake host does not fly a route).
2026-11-12 — build 62: the ND's labels and symbols beside the route#
- Owner: the texts and symbols beside the route first. The waypoints' names, altitudes / FL, ETAs, RNP, their
positions and kinds, T/C, T/D, S/C, E/D, DECEL, the GPS / IRS positions: zibomod's symbol datarefs, written by the
translated ND parts; the labels were empty (Ghidra's C-string writes:
sprintf/strcpyinto buffers it typed float[4], argument order of the floating-point ones) — fixed in the tools (port_cpp.py,lnav_fixups.pyc_strings,lnav.hstr_sprintf / str_strcpy). - Oracle-checked: the 402 symbol datarefs the NDs read, after zibomod's drawing (hook
nd_out), byte by byte for the labels: 119 frames, 0 differ (strict too); the drawing and the LNAV replay still 0. - To the NDs: CommBus
LU737_ND_SYM(the changed values with the drawing, all each 2 s); the ND programs read them instead of the ground values (NdSources.ts). Test: in the systems module after LNAV engages, 516 values, the first waypoint labelled. - Caught by build.mjs's guard: a display change used
Object.fromEntries(MSFS's JS engine lacks it): replaced. - Not yet: navaids / airports on the map, the FIX page labels, VNAV, TCAS / terrain / weather; the BRT knobs.
2026-11-12 — build 63: the ND map (stations, airports, fixes)#
- Owner: navaids, airports, waypoints on the map next. zibomod's map (STA / ARPT / WPT:
nd_earth_*,nd_apt_*) and the navdata loaders it runs at its start (read_earth_navdat,read_earth_fix,read_earth_fix2,read_apt) translated; in the systems module after the navigation block, the navdata read from the navigation provider's files each time the FMS loads them (docs/ND_ROUTE.md "The map"). - Oracle-checked: the loaders' tables byte for byte as zibomod's after its start (the oracle dumps its memory); the replay with the map (its inputs at a new "map" hook, its symbols in nd_out, every element of nd/object_* and nd/apt_*): 0 differences after the map's warm-up (strict too); the drawing and the LNAV still 0.
- The translation tools grew what zibomod's map code needs: arrays of records as bytes, a function's locals laid out as zibomod's stack frame where its code relies on it, Ghidra's CONCAT / 6-byte unknowns / float fields through 4-byte copies, C strings on stack addresses, std::ifstream on C stdio. The native and WASM builds use -fno-strict-aliasing; the native tests skip the alignment sanitizer (zibomod reads unaligned record pieces).
- The EFIS's STA / ARPT / WPT / WXR in the FMS store (Zibo's glareshield datarefs); the test world starts with 85 far stations (zibomod's map skips earth_nav's first 80 rows).
- Test
lnav_flies_the_route_in_the_systems: SEA (STA) and an airport ahead (ARPT) on the captain's ND. - Not yet: TCAS, terrain, weather; the FIX page's circles (written, not checked); VNAV; the map's memory (68 MB of zibomod's tables) and the navdata load time in MSFS not measured yet.
2026-11-12 — build 64: the map's navdata near the aircraft#
- Owner: avoid a load stall; plan 1 (only nearby, read in steps, again when far) + 4 (memory by the rows read). The map's navdata is read 2 ms a frame from the provider's files, only the rows within +-10 degrees (what zibomod's map can show is within 145 NM), loaded into zibomod's tables through its own loaders; again after 4 degrees. earth_nav: 0.4 MB instead of 50 MB. After a load, zibomod's first-frame full search, so the map fills at once (its 25-rows-a-frame search would take minutes for the world). docs/ND_ROUTE.md "Nearby navdata".
- Tests: the oracle replay again with the map's navdata read this way: 0 differences; a 380,000-row synthetic world read in 60 frames of 2 ms, loaded in 9 ms (optimised native build).
2026-11-12 — build 65: VNAV#
- Owner: VNAV now (the lights wait). zibomod's VNAV mode (
ap_vnav,vnav_init,vnav_calc_speed,climb_perf, the restriction speeds) translated with the rest of the AFDS; before, they were empty stubs. docs/VNAV.md. - Oracle: a VNAV scenario (PERF INIT FL130, the LNAV route, MCP 13000, A/T, FD, LNAV, VNAV, CMD A, a scripted climb from 10000 ft and level-off): VNAV SPD with FMC N1, then VNAV PTH with FMC SPD and the FMS in cruise. The translation: identical on every frame (3760 frames, 734 values), and the first AFDS scenario too.
- Fixed on the way (all modes): the LNAV heading was cut to whole degrees (an untyped local became an int); the
PFD's GPS / ANP deviation scales were never computed (
lnav_vnav_horiz_vertnot called); the leg before the first leg read a neighbouring C++ member (zibomod reads an unused, empty leg). - Systems: the AFDS's writes to the FMS's datarefs (21: flight phase, descent mode, VNAV speeds,
ap_on, ...) now reach the FMS's Lua with its handlers, as X-Plane does; the FMS's VNAV values reach the AFDS (161 inputs). Testvnav_climbs_and_levels_in_the_systems. L:LU737_WASM_BUILDsaid 60 in builds 61-64 (the number was not bumped); now 65.
2026-11-12 — build 66: VNAV's descent, the IRS modes in the FMS#
- Owner: the descent next. Oracle scenario
afds_vnav_descent_trace(FL240 cruise, T/D, VNAV PTH down Zibo's path, VNAV ALT at the MCP altitude, the MCP lower): the translation is identical on every frame (4920 frames in two windows; the replay starts each window from the oracle's state). The oracle host:trace_restart(windows) andramp(a held value moved in a straight line over the frames: smooth scripted flight). docs/VNAV.md. - Found by the systems test (
vnav_descends_in_the_systems): the FMS never saw the IRSs in NAV. Zibo's IRS script (B738.LATLON, not run: ours is native) writes the IRS modes into datarefs the FMS creates; they stayed 0, so the FMS stopped the route's distances (to the next waypoint, to the destination, the T/D) and asked for LNAV / VNAV disconnect — since build 60. Now our IRS's modes, alignment, selectors go there (Fms::addOwnedSource). With it: the T/D at 43.3 nm (the oracle 43.5), VNAV PTH on 99 % of the descent, the path error within 5 ft.
2026-11-12 — build 67: VNAV's arrival and approach#
- Owner: an arrival and a runway, for the speed limit, the altitude restrictions and the glide path. The test
world gets KPDX's STAR LNVE1 and RNAV approach R10R (
wasm/test/approach_world.h, written with our own CIFP writer): restrictions at or below / at or above, a 230 kt speed restriction, the FAF at 1700, the runway on a 3 degree path, a missed approach. - Oracle scenario
afds_vnav_approach_trace: DEP/ARR on the CDU, the descent from FL240 to 500 ft on the final; the host now flies the altitude on the FMS's own path (follow) and keeps zibomod's engine N1 / N2 at idle (zibo_hold: the oracle has no engine model). Zibo's VNAV: 240 kt at 10000 ft, level-offs at the restrictions with FMC SPD, the approach phase, the 3 degree final. The translation: identical on every frame (13020). - Found by the systems test (
vnav_approach_in_the_systems): VNAV dropped to SPEED after the FAF. zibomod reads some of the FMS's datarefs into globals the navigation and the AFDS share; the AFDS's copies were never filled (rnav_idx_last: the last RNAV approach leg). Now they are (kAfdsPreReads). With it: VNAV PTH down the final, the path error within 25 ft, to 500 ft.
2026-11-12 — build 68: PFD / ND small items#
- PFD: VNAV's speed window (
spd_wup/spd_wdn) and the A/T wake-up flag: the AFDS's own writes (it computed them all along; nothing carried them to the PFD). The SPD REF selector and its knob (zibomod'sCMD_spd_ref_*added to the sys translation, the contract's SPEED_REFERENCE / _ADJUST events): the V-speed display (pfd/vspeed, its digit / REF / VREF flags, V1 off). Testspd_ref_knob_sets_the_pfd_vspeed. - ND: the green arc (Zibo's
B738_draw_arc,efis/green_arc.h; checked in the VNAV climb test: 0.549 of the 10 nm map at 2000 ft to go); the POS button's VOR radial lines and R-xxx labels (NdSources.tsvorPos, unit test); the Lua FMS's strings the NDs read (96: selected VORs, runways, the next waypoint and its ETA, the FIX page's labels, VOR / ADF frequencies) overLU737_ND_SYM. - The sys translation regenerated (four commands added): zibomod's command handlers now return int (their real signature); no behaviour change (all tests).
2026-11-12 — build 69: the takeoff and the climb, DES NOW, SPD / ALT INTV#
- Owner: the takeoff to the climb (SID, VNAV at 400 ft, thrust reduction and acceleration), DES NOW, SPD / ALT
INTV. The test world gets KSEA's SID LNVS1 (
approach_world.h: runway 16L, the runway heading to 1000 ft, LNVSA at or above 5000 and at or below 210 kt). - Oracle scenario
afds_vnav_takeoff_trace: on the ground at KSEA, PERF INIT, the route with the runway and the SID, TAKEOFF REF (flaps 5, QRH V-speeds), the MCP speed to V2, FD, A/T, LNAV and VNAV armed, TO/GA, the roll and the climb (the host's newfollow_spd: the airspeed follows the AFDS's speed); SPD INTV with the speed dialled, the MCP altitude above the cruise altitude and ALT INTV. Zibo: THR HLD at 84 kt, LNAV at 50 ft, VNAV SPD at 400 ft with V2 + 20, the SID's 210 kt, the climb phase and FMC N1 at 1500 ft; ALT INTV raises the cruise altitude. The translation: identical on every frame (5659 frames). - Oracle scenario
afds_vnav_desnow_trace: FL240, DES NOW 10 nm before the T/D: -1000 ft/min (the host'sfollownow flies zibomod's commanded V/S while the FMS's descent_now is 2), the path captured at about 18000 ft, VNAV PTH, VNAV ALT at 16000. Identical on every frame (13836 frames). - Systems: the MCP's ALT INTV button now reaches Zibo's FMS command (
laminar/B738/autopilot/alt_interv) and its light / position (L:LU737_AUTOPILOT_ALT_INTERV_POS); before, the button did nothing. Testsvnav_takeoff_in_the_systems,vnav_des_now_in_the_systems(the same steps through the cockpit's events). - The oracle host: zibomod writes the pilot's indicated airspeed itself (a filter), so the host keeps its own speed.
eec_last_oatis zibomod's engine code's (Idle_mode,Thr_shift), not the AFDS's: no longer compared. - The tests' FMS error count no longer fails on one error of Zibo's own Lua (the ANP's random seed: an empty interval about once in 1000 seeds; in X-Plane too). It made the VNAV systems tests fail now and then.
2026-11-12 — build 70: ILS approach and autoland#
- Owner: the ILS approach and the autoland. The test world gets KPDX's ILS IPDX 110.30 (runway 10R).
- Oracle scenario
afds_ils_trace(docs/AFDS.md "ILS approach and autoland"): a closed loop through zibomod's own laws. The oracle host now flies a kinematic aircraft on zibomod's flight director (fly) and computes the ILS receivers from the geometry (ils). Zibo: LOC and G/S capture and tracking, dual channel, FLARE armed, LAND 3, the flare, RETARD, the touchdown, the rollout. The translation: identical on every frame (11648 frames). - The oracle now prints int globals exactly (zibomod's PID states are floats in int arrays; the flare PID differed after a replay restart).
- Systems test
afds_ils_approach_and_autoland: the same approach through our servo and MSFS's CDI / GSI: LOC within 0.06 degree, G/S within 0.1 degree, flare at 63 ft, touchdown 1860 ft past the threshold at 200 ft/min, rollout on the centreline. MSFS's GSI sense (FSUIPC: positive with the aircraft above the glideslope) is what zibomod wants.
2026-11-13 — build 71: NAV receiver realism#
- Owner: false glideslopes, a glideslope needle that jumps far out, and real-world small details (all four offered:
false paths and range noise, beam bends, the back course and overflying, the DME's slant / lock-on), on by
default with an option. docs/ILS_REALISM.md;
L:LU737_ILS_REALISM_OFF= 1 for MSFS's clean signal. - One receiver model per NAV (
nav/ils_receiver.h) read by zibomod's AFDS, Zibo's FMS scripts and the PFD / ND (they read MSFS's CDI / GSI / DME directly before; the PFD's localizer scale now matches the AFDS's). - Test
afds_false_glideslope_capture: arriving high with APP armed, the G/S captures the 6° false path (reversed: the A/P then holds level), then the 9° one pulls it down; without the realism nothing is captured. The autoland and LOC tests keep their results with it on. - Found while building it: the receiver's needle noise must be smooth (zibomod differentiates the deviation each frame for its lead: frame-to-frame steps rocked the A/P), and a pegged needle must stay pegged under a bend (zibomod reads a needle leaving the stop as the beam coming alive: LOC captured 14 nm out).
- The DME's slant range is MSFS's own (not recomputed).
2026-11-13 — build 72: PFD / ND, batch 1#
- Owner: finish the PFD and the ND first, wiring what already exists; leave what is hard for later.
- zibomod display datarefs that our translated code (Systems, AFDS, navigation) already computes but no display
read:
tools/re/du_exports.pyfinds them (a PFD / ND dataref still pending, zibomod's global computed by translated code, not only reset to one constant) and the systems module publishes them asL:LU737_DU_*(systems_du.cpp): the radio altitude dial, the TCAS RA pitch limits, the ND's FMC source, the ADF / VOR-DME fail flags. Testdu_exports_publish_zibomod_values. - Zibo's display code in
B738.glaresheild.lua(a script we do not run: its MCP / EFIS parts are native) written out inavionics/src/du/GlareDisplay.ts: the flight path vector, the PFD's runway symbol, the expanded localizer scale (hysteresis), the ND's heading-bug line (10 s timer), track-up active, the EFIS mode / MMR disagree (1.8 s), EFIS NAV, WX fail. Checked against the oracle's PFD / ND snapshots and unit-tested for the timers (glare_display.test.ts). The FPV's angle of attack is MSFS'sINCIDENCE ALPHA. - Left pending: PFD 21 / 23 (FO) of about 230 (stall, bank angle and airspeed alerts, PULL UP / WINDSHEAR, DH
minimum, display control panel, GLS / LOC failure flags, HUD); ND about 160 of 1050, nearly all TCAS (traffic, its
flags) and terrain / weather radar, plus ANP, the destination runway ICAO flag,
nd_refresh.
2026-11-13 — build 73: TCAS#
- Owner: TCAS first (then the PFD's alerts, then terrain / weather radar); compare the displays with Zibo's.
- zibomod's TCAS (Tcas_system and its functions, the transponder knob's commands) translated into the Systems loop.
Oracle scenario
tcas_trace: the TCAS test and five traffic targets (other, proximate, two head-on TA / RA, overtaking). The translation is identical on every sample (2543;tcas_replay_matches_oracle). - MSFS's traffic (SimConnect: aircraft and helicopters within 40 nm, about once a second) becomes X-Plane 12's TCAS
targets, each aircraft keeping its slot, airborne first, moved on each frame with its velocity (
tcas/traffic.h). The transponder knob turns (DEC held at STBY: the TCAS test); MSFS's transponder state follows zibomod's. docs/TCAS.md. Systems testtcas_traffic_in_the_systems. - The ND's traffic, its flags and altitude labels and the PFD's RA bands are now Zibo's (
L:LU737_DU_*, labels overLU737_ND_SYM). - Displays compared with X-Plane's own render of Zibo's panel (
cockpit_3d/-PANELS-/Panel_Preview.png): the layouts match. Its horizon colours are an older Zibo's bitmap, not ours. The VS needle matches in our renders; the owner's odd VS indicator in MSFS is still to look at, with a screenshot. - The clang build of the navigation's translation: its GCC-only pragmas guarded (
lnav_fixups.py).
2026-11-13 — build 74: GPWS and the stall alert#
- Owner: the PFD's alerts next.
- zibomod's Gpws and PFD_stall_system translated into the Systems loop, with the GPWS SYS TEST and inhibit switches
and the stall test buttons. Oracle scenario
gpws_trace(GPWS test, approach callouts / minimums / below the glideslope, bank angle, sink rate, terrain closure, too low, windshear, low airspeed and stall, after takeoff): identical on every sample (13785;gpws_replay_matches_oracle). TOO LOW GEAR / FLAPS and DON'T SINK are not reached by the scenario (Zibo's takeoff / go-around state). - The PFD's PULL UP / WINDSHEAR, bank angle, low airspeed and stall band now come from Zibo's code. docs/GPWS.md;
systems test
gpws_alerts_in_the_systems.
2026-11-13 — build 75: ND terrain and weather radar (MSFS's map)#
- Owner: MSFS's map engine for the terrain, MSFS's weather radar layer, the radar's tilt adjustable; asked about external data (lightning, turbulence, windshear).
- Found: Zibo's ND terrain is the TerrainRadar plugin's (another author's X-Plane plugin; zibomod only reads it), and its weather radar X-Plane's own, set by zibomod's WXR() from the radar panel.
- zibomod's WXR() and the radar panel's knobs translated (the panel turns; X-Plane's radar settings as
L:LU737_WXR_*; the ND's mode label and the radar test flags). Systems testwxr_panel_in_the_systems. avionics/src/du/NdMap.ts: MSFS's map (the SDK's BingComponent) in the ND's map slot with zibomod's ND geometry. TERR: EGPWS colours against the aircraft's altitude. WXR: MSFS's radar in 737 colours with gain, WX+A magenta cores (turbulence approximation), the ALT knob as a fade (approximation: MSFS has no cloud tops), MAP ground returns, zibomod's ±60 / ±90 degree sector. docs/TERRAIN_WXR.md. Not checked in MSFS yet.