fs2port/port/include/chunk5Setup.h
2026-05-13 21:32:05 -05:00

59 lines
2.4 KiB
C

// chunk5Setup: bit-perfect C transliteration of chunk5
// SetupViewProjection (chunk5.s lines 203-432) and its math
// dependencies in chunk4 (cos table at $141A, L177B/L1778 lookups,
// ZPScale multiplier).
//
// Produces the same int16 3x3 rotation matrix the original Apple II
// FS2 stores at $78..$89, given the same inputs ($6C/$6D 16-bit
// "yaw" -> X-axis, $6E/$6F "pitch" -> Z-axis, $70/$71 "bank" ->
// Y-axis, ViewDirection byte). The disassembly's input labels are
// mislabeled vs standard aviation -- see SESSION_RECOVERY.md.
//
// Validated cell-for-cell against `port/bin/fs2trace --matrix` (the
// 6502 emulator running the actual chunk5 binary).
#ifndef CHUNK5_SETUP_H
#define CHUNK5_SETUP_H
#include <stdint.h>
// Run SetupViewProjection with the supplied inputs. Output is the
// 3x3 matrix as it appears at $78..$89 (post-L6301 col shifts:
// col 0 >>= 1, col 2 >>= 2). Each output is int16 in chunk5's R
// (camera-to-world) layout, ready to be mirrored into
// CameraT.rotChunk5 / writableRam[$78..$89].
//
// Inputs:
// yaw16 = $6C/$6D 16-bit signed (X-axis rotation in chunk5 conv)
// pitch16 = $6E/$6F 16-bit signed (Z-axis rotation)
// bank16 = $70/$71 16-bit signed (Y-axis rotation)
// vd = $0A70 ViewDirection byte
// radarView = $0836 RadarView flag (1 = radar view)
void chunk5SetupViewProjection(int16_t yaw16, int16_t pitch16, int16_t bank16,
uint8_t vd, uint8_t radarView,
int16_t outMatrix[3][3]);
// Lower-level primitives, exposed for unit tests. All match their
// 6502 counterparts cell-for-cell (validated by chunk5SetupSelfTest).
// L177B: cos lookup. byteAngle is the 8-bit angle (256 = full
// circle); subByte gives sub-byte fractional precision via linear
// interpolation against the next entry. Result is Q1.15 cos(angle).
int16_t chunk5L177B(uint8_t byteAngle, uint8_t subByte);
// L1778: sin lookup. Equivalent to L177B(byteAngle - 64, subByte)
// since sin(x) = cos(x - 90 deg).
int16_t chunk5L1778(uint8_t byteAngle, uint8_t subByte);
// ScaleC2ByC4 / ZPScale: 16-bit signed Q-format multiply with
// chunk4's specific rounding pattern (chunk4.s lines 1565-1744).
int16_t chunk5ScaleC2ByC4(int16_t a, int16_t b);
// Self-test: sweeps a few input combinations through the cascade
// and aborts if any cell deviates from the known oracle output.
// Returns 0 on success, non-zero on failure.
int chunk5SetupSelfTest(void);
#endif