Files
tdkpin/original/tools/verify_extracted_assets.py
2026-08-22 15:52:52 +02:00

79 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""Verify that every manifest resource round-trips to TDKPIN.EXE."""
from __future__ import annotations
import hashlib
import json
import struct
import wave
from collections import Counter
from pathlib import Path
from PIL import Image
ROOT = Path(__file__).resolve().parent.parent
def main() -> None:
manifest = json.loads((ROOT / "assets" / "manifest.json").read_text(encoding="utf-8"))
source = (ROOT / manifest["source"]).read_bytes()
assert hashlib.sha256(source).hexdigest() == manifest["source_sha256"]
assert manifest["resource_count"] == 63
assert len(manifest["resources"]) == 63
assert not manifest["decode_errors"]
expected_types = {
"DAT": 34,
"PAL": 1,
"WAV": 16,
"BITMAP": 3,
"ICON": 1,
"GROUP_ICON": 1,
"VERSION": 1,
"DIALOG": 6,
}
assert Counter(entry["type"] for entry in manifest["resources"]) == expected_types
for entry in manifest["resources"]:
raw = (ROOT / entry["raw_path"]).read_bytes()
offset = entry["file_offset"]
allocated_size = entry["allocated_size"]
assert len(raw) == allocated_size
assert raw == source[offset : offset + allocated_size]
assert hashlib.sha256(raw).hexdigest() == entry["raw_sha256"]
for decoded_path in entry["decoded_paths"]:
assert (ROOT / decoded_path).is_file()
if entry["type"] in {"DAT", "BITMAP", "ICON"}:
png_paths = [path for path in entry["decoded_paths"] if path.endswith(".png")]
assert len(png_paths) == 1
with Image.open(ROOT / png_paths[0]) as image:
assert image.width == entry["image"]["width"]
assert image.height == abs(entry["image"]["height"])
if entry["type"] == "WAV":
wav_path = ROOT / entry["decoded_paths"][0]
with wave.open(str(wav_path), "rb") as stream:
assert stream.getnchannels() == entry["audio"]["channels"]
assert stream.getframerate() == entry["audio"]["sample_rate"]
assert stream.getsampwidth() * 8 == entry["audio"]["sample_width_bits"]
if entry["type"] == "DIALOG":
dialog = json.loads((ROOT / entry["decoded_paths"][0]).read_text(encoding="utf-8"))
assert len(dialog["controls"]) == dialog["declared_control_count"]
if "actual_size" in entry:
assert 0 < entry["actual_size"] <= allocated_size
# Verify that the resource intervals do not overlap one another.
ranges = sorted(
(entry["file_offset"], entry["file_offset"] + entry["allocated_size"])
for entry in manifest["resources"]
)
for previous, current in zip(ranges, ranges[1:]):
assert previous[1] <= current[0]
print("Verified 63/63 raw resources and all decoded derivatives")
if __name__ == "__main__":
main()