fs2port/port/include/fs2math.h
2026-05-14 10:03:23 -05:00

82 lines
3.3 KiB
C

// 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 <stdint.h>
// `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