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

97 lines
3.5 KiB
C

// 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
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 <scenery file>\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;
}