// Scan an FS2 scenery file for clusters of vertex-emit opcodes. // chunk5 vertex opcodes are $00, $01, $02, $40, $41, $42 (5 bytes each // in 80C5/7EBC variants), and the cached-vertex ops $32/$33/$35 (2-3 // bytes). Polygon scenery sections concentrate these; pure // COM/NAV-database sections have almost none. // // We slide a 64-byte window over the file and report windows where // at least 6 opcode bytes look like vertex emits. Output: file // offsets where polygon clusters start, plus the dominant opcode. #include #include #include #include static int isVertexOp(uint8_t b) { switch (b) { case 0x00: case 0x01: case 0x02: case 0x40: case 0x41: case 0x42: return 5; // 5-byte stream-vertex record case 0x32: case 0x33: case 0x35: return 2; // 2-byte cached-vertex record default: return 0; } } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } FILE *f = fopen(argv[1], "rb"); if (f == NULL) { perror(argv[1]); return 1; } fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); uint8_t *buf = malloc(size); if (buf == NULL) { fclose(f); return 1; } fread(buf, 1, size, f); fclose(f); const int windowSize = 64; const int threshold = 6; // min vertex-op count per window int lastReportedOff = -1; printf("# File %s: %ld bytes (%ld blocks of 512)\n", argv[1], size, size / 512); printf("# Windows of %d bytes with >=%d vertex-op bytes:\n", windowSize, threshold); printf("# offset block sector vertex-ops first-bytes (first 16 hex)\n"); // Look for windows where we see the $41-pattern (V2 emit + line // draw) repeated regularly. Real chunk5 polygon sections look // like `41 xx xx xx xx 41 xx xx xx xx ...`. Count $41 ops at // 5-byte stride. for (long off = 0; off + windowSize <= size; off++) { int regularCount = 0; for (int i = 0; i + 5 < windowSize; i += 5) { if (buf[off + i] == 0x41 || buf[off + i] == 0x42) { regularCount++; } } int totalNonZero = 0; for (int i = 0; i < windowSize; i++) { if (buf[off + i] != 0) totalNonZero++; } if (regularCount >= 5 && totalNonZero > windowSize / 2 && off > lastReportedOff + windowSize) { long block = off / 512; long sector = off / 256; printf("# $%06lX block=%4ld sec=%4ld $41-stride=%2d nonzero=%d hex: ", off, block, sector, regularCount, totalNonZero); for (int i = 0; i < 16; i++) { printf("%02x ", buf[off + i]); } printf("\n"); lastReportedOff = off; } } free(buf); return 0; }