82 lines
3.3 KiB
C
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
|