// Direct ports of the FS2 disassembly's instrument math. // Each function mirrors a specific routine in the original FS2 // chunks (chunk4 / chunk5) and returns the byte angle to feed into // `needleDraw`. #ifndef FS2_MATH_H #define FS2_MATH_H #include // `UpdateAirspeedDerivedValue` (chunk5 L9FE9 / `$0A33`). Takes a // 16-bit airspeed value (high byte of $0A11..$0A12 in the original), // clamps to the FS2 maximum (0x5A in the high byte), buckets via the // $07DF lookup, and interpolates between buckets. Returns the FS2 // needle position byte (0..0x57 after wrap). uint8_t fs2AirspeedNeedlePos(uint16_t airspeed16); // Convert an FS2 needle position (0..0x57) into a byte angle suitable // for `needleDraw` (0 = up, +ve CW). Centred so position $16 (12 // o'clock) maps to byte angle 0. uint8_t fs2PosToByteAngle(uint8_t pos); // `UpdateAltimeterPose` (chunk5 line 8332). Takes a 16-bit altitude // value (in FS2's internal altitude unit) and produces both the // main-hand position ($29) and the 10K-hand position ($28). Both are // FS2 needle positions (0..0x57). void fs2AltimeterNeedlePos(uint16_t altitude16, uint8_t *mainPos, uint8_t *tenKPos); // Signed 8.8 multiply that mirrors FS2's `ScaleC2ByAX`: the result is // `(value16 * scale16) / 32768`, signed. Used by the altimeter pose // computation and several other scaling routines. int16_t fs2ScaleByAX(int16_t value16, int16_t scale16); // Mirrors the head of `UpdateTurnCoordinator` (chunk5 L4961). Takes the // signed 16-bit yaw-rate input ($09CE:$09CD in FS2), computes the // rounded value `(value16 * 3) / 256 + 8`, and clamps the result into // 0..15. The returned index addresses the wing-bar table at $0DE0. uint8_t fs2TurnCoordIndex(int16_t value16); // Look up a turn-coordinator entry from the FS2 $0DE0 table. `index` // must be 0..15 (clamp via `fs2TurnCoordIndex`). The four returned // deltas are signed colour-pixel offsets: // wing bar: from (12 + dx, 166 + dy) to (12 - dx, 166 - dy) // ball: from (12, 166) to (12 + vx, 166 + vy) // (12, 166) here is the gauge centre in FS2 colour-pixel/hires-Y // coordinates that DrawColorLine consumes. void fs2TurnCoordEntry(uint8_t index, int8_t *dx, int8_t *dy, int8_t *vx, int8_t *vy); // Mirrors the routine FS2 calls "UpdateMagneticHeading" (chunk5 // L8432) but which actually computes the VSI needle target ($2A, // consumed by chunk4 `UpdateVerticalSpeedIndicator`). The input is the // 16-bit signed value at $0A16:$0A15 (climb rate in FS2 internal // units). The high byte is clamped to [-9, 9] before the rest of the // shift / negate / mod-$58 chain runs. Returns the FS2 needle position // (0..0x57). uint8_t fs2VsiNeedlePos(int16_t value16); // Mirrors the head of FS2 `UpdateSlipSkid` (chunk5 L8467). Maps the // signed-byte slip input through `(value+$7F)/4 - $1F`, clamps to // [-8, 8], and adds 9. The returned index 1..17 is what // `UpdateSlipSkidIndicator` (chunk4 L2497) consumes. uint8_t fs2SlipSkidIndex(int8_t slipValue); // Clamp `v` to [lo, hi]. static inline int fs2ClampInt(int v, int lo, int hi) { if (v < lo) { return lo; } if (v > hi) { return hi; } return v; } // Add `step` to `v`, then clamp to [lo, hi]. static inline int fs2StepClamp(int v, int step, int lo, int hi) { return fs2ClampInt(v + step, lo, hi); } #endif