#!/usr/bin/env python3 """Statically compile the original MapVersion constructor and its declared I/O adapter.""" import argparse import hashlib import json import struct import subprocess from pathlib import Path from a64_lift import Compiler from lift_rng import arm64_image, file_range ROOT = Path(__file__).resolve().parent.parent ADDRESS, SIZE = 0x10150BF28, 192 EXPECTED = 'b9254262cde89c9e79a9fdf6d700860ff9fd623d53c576efaf431600096c8a9b' READ = 0x10035E264 def run(*args): print('+', ' '.join(map(str, args)), flush=True) subprocess.run(list(map(str, args)), cwd=ROOT, check=True) def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('binary', type=Path) args = parser.parse_args() image, slice_offset = arm64_image(args.binary.read_bytes()) offset = file_range(image, ADDRESS, SIZE) body = image[offset:offset + SIZE] if hashlib.sha256(body).hexdigest() != EXPECTED: raise ValueError('Unrecognized MapVersion constructor bytes') compiler = Compiler({READ: 'read_or_throw'}) wat = compiler.compile(body, ADDRESS) out = ROOT / 'build/version' out.mkdir(parents=True, exist_ok=True) (out / 'factorio_version.wat').write_text(wat) manifest = {'symbol': 'MapVersion::MapVersion(Deserialiser&)', 'address': hex(ADDRESS), 'source_file_offset': slice_offset + offset, 'bytes': SIZE, 'sha256': EXPECTED, 'instructions': compiler.instructions, 'host_calls': compiler.calls, 'scope': 'automatic straight-line integer lift; host read errors return status rather than C++ exceptions'} (out / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n') assembly = ['.text', '.p2align 2', '.globl _factorio_version_original', '_factorio_version_original:'] for (word,) in struct.iter_unpack('