fs2port/port/tools/matrixProbe.c
2026-05-13 21:32:05 -05:00

148 lines
5.5 KiB
C

// matrixProbe: drives the port's matrix construction (sceneryAttachCamera)
// with controlled inputs and dumps the resulting $78..$89 matrix.
//
// Usage: matrixProbe <yaw> <pitch> <bank> [worldX worldY worldZ]
// yaw/pitch/bank are byte angles (0..255, 256 = full circle)
// world coords default to (0,0,0) in metres.
//
// Compares directly to MAME's captured $78..$89. Inputs corresponding
// to the boot Meigs view: yaw=255 (i.e. -1 byte = ~-1.4 deg), pitch=0,
// bank=0, position metres (95, 0, 268).
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "camera.h"
#include "math6502.h"
#include "renderer.h"
#include "sceneryVm.h"
// Avoid linking aircraft.c just for AC_WORLD_UNITS.
#define AC_WORLD_UNITS(n) ((int32_t)(n) * (1 << CAM_POS_FRACT_BITS))
// Stubs for renderer/palette/fs2math symbols pulled in transitively
// from sceneryVm.c. sceneryAttachCamera never invokes them, so the
// stubs only need to satisfy the linker.
#include "fs2math.h"
#include "palette.h"
void rendererDrawLine(RenderStateT *s, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
(void)s; (void)x1; (void)y1; (void)x2; (void)y2;
}
void rendererDrawColorSpan(RenderStateT *s, int16_t xRight, int16_t length, int16_t y) {
(void)s; (void)xRight; (void)length; (void)y;
}
void rendererFillPolygon(RenderStateT *s, const int16_t *xs, const int16_t *ys, int count) {
(void)s; (void)xs; (void)ys; (void)count;
}
void rendererSetDrawColor(RenderStateT *s, ColorE c) {
(void)s; (void)c;
}
void rendererSetHiresColor(RenderStateT *s, uint8_t code) {
(void)s; (void)code;
}
ColorE paletteFromSceneryCode(uint8_t code) {
(void)code;
return (ColorE)0;
}
int16_t fs2ScaleByAX(int16_t v, int16_t s) { (void)v; (void)s; return 0; }
static int16_t readMatrix16(const uint8_t *ram, uint16_t addr) {
uint16_t v = (uint16_t)ram[addr] | ((uint16_t)ram[addr + 1] << 8);
return (int16_t)v;
}
static void printMatrix(const uint8_t *ram, const char *tag) {
int16_t m[3][3];
m[0][0] = readMatrix16(ram, 0x78);
m[0][1] = readMatrix16(ram, 0x7A);
m[0][2] = readMatrix16(ram, 0x7C);
m[1][0] = readMatrix16(ram, 0x7E);
m[1][1] = readMatrix16(ram, 0x80);
m[1][2] = readMatrix16(ram, 0x82);
m[2][0] = readMatrix16(ram, 0x84);
m[2][1] = readMatrix16(ram, 0x86);
m[2][2] = readMatrix16(ram, 0x88);
printf("%s matrix at $78..$89 (post-L6301):\n", tag);
for (int i = 0; i < 3; i++) {
printf(" row %d: %6d %6d %6d\n", i, m[i][0], m[i][1], m[i][2]);
}
}
static void printMameRef(void) {
printf("MAME reference (boot frame 13000, Meigs view):\n");
printf(" row 0: 16382 0 0\n");
printf(" row 1: 0 32760 100\n");
printf(" row 2: 0 -401 8190\n");
printf(" inputs: yaw=$FF93=-109(16b), pitch=0, bank=0,\n");
printf(" ViewDirection=$0F=15 ($3E=$F0=-22.5deg byte angle)\n");
printf(" camX=287 camY=804 camAlt=0 (scenery units = m*3)\n");
}
int main(int argc, char **argv) {
if (argc < 4) {
fprintf(stderr,
"usage: %s <yaw_byte> <pitch_byte> <bank_byte> [wx_m wy_m wz_m] [vd] [pitchFine]\n",
argv[0]);
fprintf(stderr,
" boot Meigs reference: %s 0 255 0 95 0 268 0 0x93\n",
argv[0]);
return 2;
}
uint8_t yawByte = (uint8_t)strtol(argv[1], NULL, 0);
uint8_t pitchByte = (uint8_t)strtol(argv[2], NULL, 0);
uint8_t bankByte = (uint8_t)strtol(argv[3], NULL, 0);
int32_t wxMetres = (argc > 4) ? (int32_t)strtol(argv[4], NULL, 0) : 0;
int32_t wyMetres = (argc > 5) ? (int32_t)strtol(argv[5], NULL, 0) : 0;
int32_t wzMetres = (argc > 6) ? (int32_t)strtol(argv[6], NULL, 0) : 0;
uint8_t vdByte = (argc > 7) ? (uint8_t)strtol(argv[7], NULL, 0) : 0;
uint8_t pitchFine = (argc > 8) ? (uint8_t)strtol(argv[8], NULL, 0) : 0;
printf("inputs: yaw=%u pitch=%u bank=%u pos_m=(%d,%d,%d)\n\n",
yawByte, pitchByte, bankByte, wxMetres, wyMetres, wzMetres);
math6502Init();
CameraT cam;
cameraInit(&cam);
cam.yaw = yawByte;
cam.pitch = pitchByte;
cam.bank = bankByte;
cam.pitchFine = pitchFine;
cam.viewDirection = vdByte;
cam.worldX = AC_WORLD_UNITS(wxMetres);
cam.worldY = AC_WORLD_UNITS(wyMetres);
cam.worldZ = AC_WORLD_UNITS(wzMetres);
cameraUpdate(&cam);
// sceneryAttachCamera writes the matrix through writableRam at
// $78..$89. Allocate a 64K buffer so addressing matches chunk5.
uint8_t *ram = calloc(0x10000, 1);
if (ram == NULL) { return 1; }
SceneryStateT state;
memset(&state, 0, sizeof(state));
state.writableRam = ram;
// sceneryAttachCamera reads $4A/$4B/$4D/$4E/$50/$51 if
// SCENERY_USE_RAM_BASE is set; we don't, so leave them zero.
printf("cam->rot Q1.15:\n");
for (int i = 0; i < 3; i++) {
printf(" row %d: %6d %6d %6d\n", i,
cam.rot[i][0], cam.rot[i][1], cam.rot[i][2]);
}
printf("\n");
sceneryAttachCamera(&state, &cam);
printMatrix(ram, "PORT");
printf("\n");
printMameRef();
free(ram);
return 0;
}