75 lines
3.2 KiB
C
75 lines
3.2 KiB
C
// FS2 wind system port (chunk2 `ComputeWindComponents` and `ApplyWind`).
|
|
//
|
|
// FS2 splits the sky into four altitude bands; each band carries a
|
|
// 4-byte record `[magnitude, turbByte, reserved, directionByteAngle]`.
|
|
// `windCompute` (called every other frame in the original) selects the
|
|
// active band, resolves the record into a signed 16-bit (X, Z) wind
|
|
// vector, and caches `WindLayerByte1` for the turbulence kick.
|
|
// `windApply` (called every frame) returns the per-frame world-position
|
|
// delta and updates the bank-accumulator + turbulence-kick state that
|
|
// downstream FS2 routines consume.
|
|
//
|
|
// Default state is all zeros, matching the FS2 ROM image's
|
|
// uninitialised wind tables; that yields no wind until layers are
|
|
// configured.
|
|
|
|
#ifndef WIND_H
|
|
#define WIND_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
typedef struct WindLayerT {
|
|
int8_t magnitude; // record byte 0 (signed)
|
|
uint8_t turbByte; // record byte 1 (bit 0 enables turbulence)
|
|
uint8_t reserved; // record byte 2 (ignored by `resolve`)
|
|
uint8_t direction; // record byte 3 (byte angle)
|
|
} WindLayerT;
|
|
|
|
typedef struct WindStateT {
|
|
// Configuration: altitude thresholds (FS2 cells `WindAlt1/2/3`)
|
|
// and the four layer records. Ordering: surface < layer1 <
|
|
// layer2 < layer3 by altitude.
|
|
uint16_t altThreshold1;
|
|
uint16_t altThreshold2;
|
|
uint16_t altThreshold3;
|
|
WindLayerT surface;
|
|
WindLayerT layer1;
|
|
WindLayerT layer2;
|
|
WindLayerT layer3;
|
|
|
|
// Auxiliary FS2 state cells.
|
|
uint8_t yokeOffset1; // $0847 (added to direction always)
|
|
uint8_t yokeOffset2; // $0849 (added on the surface band)
|
|
uint8_t scaleByteLo; // $09DE (turbulence scale low)
|
|
uint8_t scaleByteHi; // $09DF (turbulence scale hi + L180C scale)
|
|
uint8_t updateCounter; // mirrors FS2 `UpdateCounter`
|
|
|
|
// Computed by windCompute.
|
|
int16_t componentX; // $09A2/$09A3 (signed 16-bit wind X)
|
|
int16_t componentZ; // $09A4/$09A5 (signed 16-bit wind Z)
|
|
uint8_t layerByte1; // `WindLayerByte1` cache
|
|
uint8_t surfaceFlag; // $09A6 (1 when the surface band was picked)
|
|
|
|
// Computed by windApply.
|
|
int16_t bankAccum; // $09AF/$09B0 (downstream bank derivation)
|
|
int16_t turbKick; // $08A1/$08A2 (turbulence kick output)
|
|
} WindStateT;
|
|
|
|
void windInit(WindStateT *w);
|
|
|
|
// Pick the active layer based on `altitude16` and resolve its (X, Z)
|
|
// components. Direct port of `ComputeWindComponents` (chunk2 L483).
|
|
// The original is called every other frame; we leave the cadence to
|
|
// the caller.
|
|
void windCompute(WindStateT *w, uint16_t altitude16);
|
|
|
|
// Per-frame wind step. Direct port of `ApplyWind` (chunk2 L397). On
|
|
// the ground, returns zero delta. Off the ground, advances the
|
|
// bank-accumulator and turbulence-kick state and returns the
|
|
// world-position delta for this frame in (deltaX, deltaZ) as a Q16.16
|
|
// world-unit value (matching the FS2 32-bit position cell convention
|
|
// and aircraft.h's `AC_POS_FRACT_BITS`).
|
|
void windApply(WindStateT *w, bool onGround, int32_t *deltaX_q1616, int32_t *deltaZ_q1616);
|
|
|
|
#endif
|