Initial commit: RE tooling and docs for The I of the Dragon localization/HD
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import argparse, os, struct, csv, hashlib, sys
|
||||
|
||||
|
||||
def read_index(path):
|
||||
data = open(path, "rb").read()
|
||||
count = struct.unpack_from("<I", data, 0)[0]
|
||||
p = 4
|
||||
entries = []
|
||||
for i in range(count):
|
||||
ln = struct.unpack_from("<I", data, p)[0]
|
||||
p += 4
|
||||
name = data[p:p + ln].decode("latin1")
|
||||
p += ln
|
||||
off, size = struct.unpack_from("<II", data, p)
|
||||
p += 8
|
||||
entries.append((name, off, size))
|
||||
return data, entries, p
|
||||
|
||||
|
||||
def safe_rel(name):
|
||||
rel = name.replace("\\", os.sep).replace("/", os.sep)
|
||||
parts = [x for x in rel.split(os.sep) if x not in ("", ".", "..")]
|
||||
return os.path.join(*parts) if parts else "_unnamed"
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Extract the Dragon .res archive (index + raw blobs).")
|
||||
ap.add_argument("res")
|
||||
ap.add_argument("out")
|
||||
ap.add_argument("--csv", default=None)
|
||||
args = ap.parse_args()
|
||||
|
||||
data, entries, header_end = read_index(args.res)
|
||||
os.makedirs(args.out, exist_ok=True)
|
||||
rows = []
|
||||
used = set()
|
||||
for name, off, size in entries:
|
||||
rel = safe_rel(name)
|
||||
dst = os.path.join(args.out, rel)
|
||||
base, ext = os.path.splitext(dst)
|
||||
n = 1
|
||||
while dst.lower() in used:
|
||||
dst = "%s__%d%s" % (base, n, ext)
|
||||
n += 1
|
||||
used.add(dst.lower())
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
blob = data[off:off + size]
|
||||
with open(dst, "wb") as f:
|
||||
f.write(blob)
|
||||
rows.append({
|
||||
"name": name,
|
||||
"offset": off,
|
||||
"size": size,
|
||||
"file": os.path.relpath(dst, args.out),
|
||||
"sha1": hashlib.sha1(blob).hexdigest(),
|
||||
})
|
||||
print("[%4d/%d] %s (%d bytes)" % (len(rows), len(entries), name, size))
|
||||
|
||||
if args.csv:
|
||||
with open(args.csv, "w", newline="", encoding="utf-8") as f:
|
||||
w = csv.DictWriter(f, fieldnames=["name", "offset", "size", "file", "sha1"])
|
||||
w.writeheader()
|
||||
w.writerows(rows)
|
||||
print("done: %d files -> %s" % (len(rows), args.out))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user