Files
llamamod/tools/wadtool.py
T

65 lines
1.9 KiB
Python

#!/usr/bin/env python3
"""Liest und schreibt Level-WADs von "Ein Königreich für ein Lama" (Argonaut).
Aufbau: u32 Gesamtlänge (ohne dieses Feld), dann Chunks:
4 Byte Kennung (rückwärts gespeichert, z. B. 'OFNI' = INFO), u32 Länge, Daten
bis zum Chunk 'END '.
wadtool.py list level.wad
wadtool.py name level.wad neu.wad "Neuer Levelname"
wadtool.py extract level.wad CHUNK datei.bin
wadtool.py replace level.wad neu.wad CHUNK datei.bin
"""
import struct
import sys
def read(path):
d = open(path, 'rb').read()
total = struct.unpack_from('<I', d, 0)[0]
if total != len(d) - 4:
raise ValueError(f'{path}: Längenfeld {total} passt nicht zu {len(d) - 4}')
chunks, o = [], 4
while o + 8 <= len(d):
tag = d[o:o + 4][::-1].decode('latin1')
ln = struct.unpack_from('<I', d, o + 4)[0]
chunks.append([tag, d[o + 8:o + 8 + ln]])
o += 8 + ln
if tag == 'END ':
break
return chunks
def write(path, chunks):
body = b''.join(t.encode('latin1')[::-1] + struct.pack('<I', len(c)) + c for t, c in chunks)
open(path, 'wb').write(struct.pack('<I', len(body)) + body)
def get(chunks, tag):
for c in chunks:
if c[0] == tag:
return c
raise KeyError(tag)
if __name__ == '__main__':
cmd, src = sys.argv[1], sys.argv[2]
ch = read(src)
if cmd == 'list':
for t, c in ch:
extra = ''
if t == 'NAME':
extra = repr(c[4:].split(b'\0')[0].decode('latin1'))
print(f'{t!r:8} {len(c):10d} {extra}')
elif cmd == 'name':
c = get(ch, 'NAME')
c[1] = c[1][:4] + sys.argv[4].encode('latin1') + b'\0'
write(sys.argv[3], ch)
elif cmd == 'extract':
open(sys.argv[4], 'wb').write(get(ch, sys.argv[3].ljust(4))[1])
elif cmd == 'replace':
get(ch, sys.argv[4].ljust(4))[1] = open(sys.argv[5], 'rb').read()
write(sys.argv[3], ch)
else:
sys.exit(__doc__)