Files

73 lines
2.1 KiB
Python

import argparse, os, struct, csv, sys
def align16(x):
return (x + 15) & ~15
def collect(args):
items = []
if args.csv and os.path.exists(args.csv):
with open(args.csv, newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
items.append((row["name"], row["file"]))
else:
for root, dirs, files in os.walk(args.dir):
for fn in files:
full = os.path.join(root, fn)
rel = os.path.relpath(full, args.dir)
name = rel.replace("/", "\\")
items.append((name, rel))
return items
def main():
ap = argparse.ArgumentParser(description="Rebuild a Dragon .res archive from a directory (16-byte aligned blobs).")
ap.add_argument("dir")
ap.add_argument("out")
ap.add_argument("--csv", default=None)
args = ap.parse_args()
items = collect(args)
blobs = []
for name, rel in items:
full = os.path.join(args.dir, rel)
if not os.path.isfile(full):
print("missing: %s" % full, file=sys.stderr)
sys.exit(2)
blobs.append((name, open(full, "rb").read()))
hdr = 4
for name, _ in blobs:
hdr += 4 + len(name) + 8
data_start = align16(hdr)
out = bytearray()
out += struct.pack("<I", len(blobs))
index = bytearray()
offset = data_start
payload = bytearray()
for i, (name, blob) in enumerate(blobs):
nb = name.encode("latin1")
index += struct.pack("<I", len(nb)) + nb + struct.pack("<II", offset, len(blob))
payload += blob
if i != len(blobs) - 1:
pad = align16(len(blob)) - len(blob)
payload += b"\x00" * pad
offset += len(blob) + pad
else:
offset += len(blob)
assert len(index) + 4 == hdr, (len(index) + 4, hdr)
out += index
out += b"\x00" * (data_start - len(out))
out += payload
with open(args.out, "wb") as f:
f.write(out)
print("repacked %d files -> %s (%d bytes)" % (len(blobs), args.out, len(out)))
if __name__ == "__main__":
main()