97 lines
3.5 KiB
C
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;
|
|
}
|