Files
llamamod/tools/debugviz_check.py
T

59 lines
3.2 KiB
Python

import sys, glob, os, struct
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import geomlib as G, mapchunk, lamapaths
USAGE = 'usage: debugviz_check.py <folder with debug WADs> [<folder with original CD WADs, default $LLAMAMOD_CD/wads>]'
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
sys.exit(USAGE)
SRC = lamapaths.need(sys.argv[2] if len(sys.argv) > 2 else lamapaths.CD_WADS, 'CD wads folder',
'pass it as 2nd argument or set LLAMAMOD_CD') + '/'
bad = 0
for f in sorted(glob.glob(sys.argv[1] + '/*.wad')):
n = os.path.basename(f); err = []
ch = G.wad_read(f); o = G.wad_read(SRC + n)
wf = G.wfpc_flags(ch)
trak = G.parse_trak(G.wad_get(ch, 'TRAK'))
assert G.build_trak(trak) == G.wad_get(ch, 'TRAK')
pages, texs = G.parse_text(G.wad_get(ch, 'TEXT'))
otrak = G.parse_trak(G.wad_get(o, 'TRAK'))
nt = len(texs)
for mi, m in enumerate(trak):
if len(m.verts) > 8000: err.append('model %d %d verts' % (mi, len(m.verts)))
run = 0
for k, fc in enumerate(m.faces):
if fc['tex'] >= nt: err.append('tex idx'); break
if max(fc['v']) >= len(m.verts): err.append('vert idx'); break
run = 1 if fc['flags'] & 8 else run + 1
if run > 256: err.append('batch>256 model %d' % mi); break
if mi < len(otrak):
om = otrak[mi]
if m.coll != om.coll: err.append('COLLISION CHANGED model %d' % mi)
if m.verts[:len(om.verts)] != om.verts or m.faces[:len(om.faces)] != om.faces:
err.append('original geometry changed %d' % mi)
elif any(len(g) for g in m.coll): err.append('new model with collision')
vc = [len(m.verts) for m in trak]
mp = mapchunk.parse(G.wad_get(ch, 'MAP'), wf, vc)
om = mapchunk.parse(G.wad_get(o, 'MAP'), wf, [len(m.verts) for m in otrak])
if mp['rest'] or mapchunk.build(mp, wf) != G.wad_get(ch, 'MAP'): err.append('MAP roundtrip')
for k in ('strats', 'nodes', 'list1', 'lights', 'tab32', 'grid', 'alts', 'strat_x', 'paths', 'x200', 'last'):
if mp[k] != om[k]: err.append('MAP %s changed' % k)
if mp['tiles'][:len(om['tiles'])] != om['tiles']: err.append('tiles changed')
W, H = mp['W'], mp['H']
for t in mp['tiles']:
if not (0 <= t[0] - 0.5 < W and 0 <= -t[2] - 0.5 < H) or t[4] >= len(trak): err.append('tile out of bounds'); break
# colour block: nv*frames per tile
gm = G.parse_map_tiles(G.wad_get(ch, 'MAP'), wf, vc)
for i, fr in enumerate(gm['cols']):
if any(len(c) != vc[gm['midx'][i]] for c in fr): err.append('colour block %d' % i); break
# collision unchanged per tile instance of the original tiles
for k in ('TEXT',):
pass
others = [t for t, _ in ch if t not in ('TRAK', 'MAP ', 'TEXT')]
for t in others:
if G.wad_get(ch, t) != G.wad_get(o, t): err.append('chunk %s changed' % t)
sz = sum(len(G.wad_get(ch, t)) for t in ('TRAK', 'STPC', 'MAP ', 'LGPC'))
print('%-13s %s maxV %4d maxF %4d models %4d tiles %5d TRAK+STPC+MAP+LGPC %.1f MB' % (
n, 'OK ' if not err else 'ERROR ' + '; '.join(sorted(set(err))[:4]), max(vc), max(len(m.faces) for m in trak),
len(trak), len(mp['tiles']), sz / 2**20))
bad += bool(err)
print('errors:', bad)