// matrixProbe: drives the port's matrix construction (sceneryAttachCamera) // with controlled inputs and dumps the resulting $78..$89 matrix. // // Usage: matrixProbe [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 #include #include #include #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 [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; }