12 KiB
12 KiB
FS2 C Port - Status vs Original
Comparison of the original Apple II FS2 (disassembled in src/chunk*.s)
against the C port in port/. Updated 2026-05-14.
Legend: ok = done; partial = approximation or limited; missing = not implemented
Flight model
| Feature | Original | Port |
|---|---|---|
| Position integrator (24-bit XYZ) | IntegratePhysicsStep |
ok aircraftStep (Q16.16) |
| Pitch / bank / yaw rates | UpdateAutoTrimAndYaw etc |
ok stepFlight |
| Auto-coordination (bank to yaw) | ApplyAutoCoordination |
ok stepFlight |
| Wind / turbulence | chunk2 ApplyWind (64K) |
ok windCompute / windApply |
| Stall detection and break | per-instrument check | ok stalled flag |
| Spin entry from stall | implicit in stall handling | ok yawRate-driven spinning state |
| Spin recovery | opposite rudder + nose-down | ok 30-frame recovery condition |
| High-G / VNE damage | CheckFlightEnvelope |
ok loadFactor_q88 + airframeDamage accumulator |
| Flap speed drag | RefreshElevatorIndicator |
ok forwardSpeed *= (256 - flaps>>3) / 256 |
| Mixture too-lean = engine cut | implicit | partial audio penalty, no full model |
| Carb heat icing | chunk5 CarbHeat |
partial audio penalty, no icing model |
| Magneto on/off effect on engine | UpdateEngineWithMagneto |
partial audio penalty |
| Engine fault dispatch | FailureProcTable |
ok reality-mode dispatch |
| Engine knock audio | per-fault sound | ok audioUpdate wobble |
| Crash detection (ground) | HandleCrashOrSplash |
ok |
| Splash detection (water) | CheckSplash |
ok via worldZ water range |
| Building / mountain crash | crash_msg_table |
partial type set, no scenery-aware test |
Modes
| Feature | Original | Port |
|---|---|---|
| Free flight | default | ok |
| Slew mode | SlewMode (chunk5) |
ok aircraftToggleSlew |
| Slew digit overlay | DrawSlewOverlays |
ok |
| Demo mode | DemoMode64K |
ok autopilotDemo with 4-waypoint sequence |
| Edit mode | EditModeFlag |
ok F7 toggle, full field editor (editor.c) |
| Reality mode | RealityMode |
ok instrument and engine failures |
| Radar view | RadarView |
ok worldRenderRadar |
| WW1 ace combat | WW1AceMode |
ok bullets, bombs, AI fire, damage |
| Course Plotter | chunk2 CoursePlottingMenu |
ok coursePlotter.c (record/display) |
| Pause | TogglePause |
ok P key |
| Title / config screen | boot menu sequence | ok title.c (MODE/REGION/DISPLAY/TIME/REALITY/START/QUIT) |
| Boot DOS | BootDOS |
missing (no DOS to boot) |
Instruments
| Feature | Original | Port |
|---|---|---|
| Airspeed needle | UpdateAirspeedIndicator |
ok |
| Altimeter main hand | UpdateAltimeterIndicator |
ok |
| Altimeter 10K hand | UpdateAltimeter10K (64K) |
ok |
| Attitude indicator | tilted disc | ok drawHorizonDisc |
| Heading bug | DrawHeading |
ok digit readout |
| Magnetic compass | DrawMagCompass |
partial digit only |
| Vertical speed | UpdateVerticalSpeedIndicator |
ok |
| Turn coordinator | UpdateTurnCoordinator |
ok |
| Slip/skid ball | PLSlipSkidIndicator |
ok reads sideslip_q88 |
| Throttle position | UpdateThrottleIndicator |
ok bar indicator |
| Mixture position | UpdateMixtureControlIndicator |
ok bar indicator |
| Flap position | UpdateFlapsIndicator |
ok bar indicator |
| Trim position | implicit in auto-trim | ok HOME/END keys + indicator |
| Fuel tank L/R | UpdateFuelTankGauges |
ok per-frame burn, alternating tanks |
| Oil temp/pressure | UpdateOilTempAndPressureGauges |
missing |
| RPM display | DrawRPM |
ok digit |
| Magneto state visual | DrawMagnetoState |
ok MAG OFF/L/R/START indicator |
| Carb heat state | switch position | ok "C.H." / "HEAT" indicator |
| Lights state | switch position | ok "1" / "O" indicator |
| Failure indicator (X over gauge) | DrawX per gauge |
ok drawFailX |
| Stall / VNE warning | STALL / VNE text |
ok |
| VOR2 / ADF gauge mode-gating | chunk4 ADFMode flag | ok ac->adfMode switches needle/digits |
Radios / Navigation
| Feature | Original | Port |
|---|---|---|
| NAV1 frequency | NAV1 ($08F7) |
ok radios.c |
| NAV2 frequency | NAV2 ($08F5) |
ok |
| ADF frequency | ADFFreq* |
ok |
| COM1 frequency | str_com1 |
ok |
| Station database (deduped) | per-region | ok 695 entries from extractstations |
| BCD frequency increment | step keys | ok shift+digit / digit |
| BCD per-digit entry | KeyDecreasePatch |
ok Ctrl+1..4 arms input, digit keys append |
| OBS course knob | OBS-related | ok , . keys |
| VOR CDI needle | DrawVOR1IndicatorChanges |
ok |
| VOR TO/FROM flag | msg_vor_flags |
ok "TO" / "FR" / "OFF" |
| ILS glide slope | not in original | missing |
| DME readout | DrawATISMessage ATIS bound |
ok |
| ADF needle | DrawADFPanel |
ok gated on ac->adfMode |
| ADF heading digits | DrawADFHeadingDigits |
ok |
| ATIS chunked text | UpdateCOMMessageChunks |
ok 8-char scrolling window |
| Tune-to-nearest button | not in original | ok T key (port-only) |
Scenery system
| Feature | Original | Port |
|---|---|---|
Disk loader (SceneryReadUntilC0) |
chunk3 SceneryLoaderEntry1 |
ok RAM dump + .SD demand-load (default-on) |
| Block-list indirection | chunk4 ComputeBlockFromSector |
ok doHeader correct mapping |
| Nibble decode | SceneryNibbleDecode |
missing (only used by Entry4 path) |
| HEADER opcode ($0D) | SceneryOpHeader + LA63A |
ok doHeader with cache, default-on demand-load |
| L631D section base | L631D |
ok sceneryComputeBaseL631D |
| EnterLocalFrame ($07) | SceneryOpEnterLocalFrame |
partial simplified passthrough |
| Vertex emit + transform ($00-$02, $40-$42) | SceneryOpEmitV* |
ok |
| Cull ($20/$21/$22) | SceneryOpCullIfOutside* |
ok doCullN |
| Cull by outcode list ($04) | SceneryOpCullByOutcodeList |
partial walks list, no actual cull |
| Jump-if-beyond-XY/XYZ ($13/$14) | SceneryOpJumpIfBeyondXY* |
ok |
| REL_JUMP ($0B) | SceneryOpJumpRelative |
ok |
| SUB_INVOKE ($18) / RETURN ($19) | SceneryOpSubInvoke |
ok |
| RESET_STATE ($2F) | SceneryOpResetState |
ok |
| MODE_WHITE ($1B) | line-kernel patch | ok semantic equivalent |
| DAY_ONLY ($1C) | line-kernel patch | ok skip-on-night flag |
| WriteWord ($1A) / StoreImmWord ($25) | self-mod patches | ok |
| Curve emit ($2B) | SceneryOpEmitCurve |
ok via 6502 interpreter on MAME-patched RAM |
| Vertex-cache ops ($31/$32/$33/$35/$42) | cached vertex pool at $0140 | ok pool reads |
| ADF/NAV/COM record ($05/$1D/$1E) | station records | ok |
| SET_COLOR ($12) | SceneryOpSetColor |
ok |
| Polygon edge emit | EmitClippedLine |
partial line draw only, no polygon close |
| Polygon scanline fill | DrawColorSpan etc |
partial 2D scanline edge-intercept; not chunk5's 3D-clipped emitter (FS2 boot Meigs is line-only) |
| Polygon 4-pass 3D clipper | PolygonScanFillSetup |
ok sceneryClipPolygon3D (Sutherland-Hodgman against Z-X / Z-Y / X+Z / Y+Z) |
| Sky/ground tilted fill | FlipPagesFillViewport |
ok rendererFillTiltedSkyGround |
| Frustum line clip (5-plane) | ClipBothVerticesToFrustum |
ok full-frustum clipper, plane-snap via chunk5ScaleC2ByC4; 36/36 pixel-exact vs MAME |
| Vertex pool / EmitPrimaryVertex | $0AB8 column array | partial small pool, no polygon closure |
Display
| Feature | Original | Port |
|---|---|---|
| 280x192 framebuffer | hires page 1/2 | ok |
| Page flip | FlipPagesFillViewport |
partial single buffer |
| Color/B&W mode | ColorModePatch / BWModePatch |
partial always color |
| Dotted-pattern night | SceneryOpDayOnly etc |
ok DAY_ONLY skip |
| Panel bitmap | hires loaded from disk | ok res/loading_panel.bin |
| Panel lights overlay (64K) | UpdateInstrumentLights |
partial state shown as text |
Message text (DrawMultiMessage) |
string blit | ok font.c + fontDrawStringCentered |
| Crash message overlay | crash_msg_table |
ok MOUNTAIN / BUILDING / SPLASH / CRASH |
| Wing/tail overlays in side views | DrawWingsOrTailOverlays |
ok rendererDrawWingOverlay (right/left strut, back fin, down well) |
| Bomb sight | WW1 bombsight pixels | ok ww1aceHudDraw |
| Gunsight | WW1 only | ok ww1aceHudDraw |
| NTSC fringing (HIRES decode) | true HIRES pair-merge | partial palette buffer by default; SCENERY_NTSC=1 reverts to HIRES decode |
Audio
| Feature | Original | Port |
|---|---|---|
| Engine sound | speaker click | ok sawtooth + throttle modulation |
| Engine fault wobble | not present in original | ok phase-modulated wobble |
| Magneto-off engine cut | engine flag | ok amp = 0 when MAG OFF |
| Stall horn | beeper trill | ok 800 Hz square wave |
| Crash impact | speaker noise | ok noise burst |
| Gun fire (WW1) | not in original | ok rapid sawtooth burst |
| Bomb drop (WW1) | not in original | ok pitch sweep |
| Wind hiss | not in original | ok speed-scaled noise (LCG-driven) |
Input
| Feature | Original | Port |
|---|---|---|
| Yoke (arrows / WASD) | arrow + paddle | ok |
| Rudder | / and Ctrl |
ok Q/E |
| Throttle | [ ] Ctrl+H |
ok Up/PgUp/Dn/PgDn |
| Brake | space | ok space cuts throttle |
| Slew controls | 8/9, 0/-, ,/. , +/= | partial W/A/S/D in slew mode |
| View directions (F1-F5) | 1-5 keys | ok F1-F5 |
| Magneto select | 1-3 keys | ok Shift+M cycles |
| Lights toggle | L key | ok L |
| Carb heat | H key | ok H |
| Pause | Ctrl-P | ok P |
| Edit mode | Ctrl+[ | ok F7 (full field editor) |
| Demo mode | Ctrl+D | ok F10 |
| Slew toggle | Ctrl+S | ok F12 |
| Reality mode | Ctrl+R | ok Tab |
| Radar view | F | ok ` (backquote) |
| Course plotter menu | Ctrl+C | ok C/V/B/N (record/precision/display/off) |
| BCD digit entry arm | KeyDecreasePatch | ok Ctrl+1..4 (NAV1/NAV2/COM1/ADF) |
| Joystick | game port | ok SDL_Joystick (button 0 = gun, 1 = bomb, 2 = view, 3 = radar, 4 = throttle cut) |
Persisted state
| Feature | Original | Port |
|---|---|---|
| Edit-mode instrument save buffer | $FC00+ | ok editSavedState snapshot on toggle |
| Crash recovery snapshot | yes | ok aircraftArmRecovery / aircraftRestoreRecovery (Space when crashed) |
Multi-region scenery
The FS2.1 base disk's four region variants (Chicago / LA / Seattle / NY)
all share the same FS2.1 .SD file as their demand-load source.
port/include/sceneryData.h exposes the per-region enums; the
sceneryDataRegionFromName() table lookup maps SCENERY_REGION env var
strings (e.g. "FS2.1_chicago", "SD3", "SDS1") back to enum values for the
--screenshot path.
| Region | Source | Default start |
|---|---|---|
SCENERY_FS2_1 |
FS2.1 |
WW1 ace training field |
SCENERY_FS2_1_CHICAGO |
FS2.1 |
KCGX / Meigs Field (96, 268) |
SCENERY_FS2_1_LA |
FS2.1 |
KLAX (200, 0) |
SCENERY_FS2_1_SEATTLE |
FS2.1 |
KSEA (970, 0) |
SCENERY_FS2_1_NY |
FS2.1 |
KJFK (400, 0) |
SCENERY_SD1..SDS1 |
A2.SD<n> |
per-disk default |
SCENERY_DEMAND_TRACE=1 logs every fired demand-load. Boot Meigs fires
sid $44 (6 sub-blocks @ $A887) and sid $4E (1 sub-block @ $BA3D).
Still missing
- Polygon scanline fill for non-boot scenes (FS2 boot Meigs is line-only so this is mostly cosmetic until other regions surface real polygons).
- Stuck-key magneto auto-alternation - chunk5
MagnetosLeft/Righthandle key-held edge cases. - Day-side detailed runway striping - chunk5 has runway-specific colour-only details we don't replicate.
- Oil temp/pressure gauges - chunk5
UpdateOilTempAndPressureGauges. - Section anchor / $07 EnterLocalFrame for real bytecode in unsurfaced sections. The simplified passthrough is correct for boot Meigs but full multi-section navigation may need anchor-coord reads from each section's preamble.
- ILS glide slope - FS2 doesn't have it either, but port could add it.
Recent code-cleanup pass (2026-05-14)
- Dead code removed:
ww1aceDropBomb()(legacy stub),Coord16T/VertexT(unused),DEG2RAD(unused macro),rendererSwapFillColors()(uncalled). - Shared helpers consolidated:
camera.h:metresFromQ1616,q1616FromMetres,byteAngleToDegreesfont.h:fontDrawStringCenteredfs2math.h:fs2ClampInt,fs2StepClamp
sceneryDataRegionFromName()replaces the 19-branch SCENERY_REGION strcmp chain in main.c.AC_MAX_FORWARD_SPEED_Q88promoted toaircraft.h(audio.c was redefining the same literal).- Recovery flag tracked via
ac->hasRecoverySnapshotonly (removed therecoveryValidfile-static second-source-of-truth). - Net change: 16104 -> 16018 lines.