Files
OpenMaidEngine/tools/probe_refs.py
gamer147 aa3da00bfa chore: initialize age-reimpl repo
Reverse-engineering + open reimplementation workspace for Eushully's AGE/SYS4
engine (first target: Himegari). The repo root is age-reimpl/; the original game
install and the extracted ALF data are siblings outside the repo and are never
tracked. build/ (derived corpora) is gitignored and regenerated by the tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 12:58:30 -04:00

77 lines
2.3 KiB
Python

"""What do T1/T2/T3 entries point at? Plus: extract XOR-0xFF strings from scripts.
Prints dword windows around table-entry targets, and scans for complement-encoded
Shift-JIS strings.
"""
import struct
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2] / "extracted" / "DATA1"
def parse(path):
data = path.read_bytes()
f = struct.unpack_from("<13I", data, 8)
body = data[0x3C:]
return data, f, body
def dw(body, i):
return struct.unpack_from("<I", body, i * 4)[0]
def try_string(body, i, max_dwords=40):
"""Try to decode a XOR-0xFF cp932 string starting at dword i."""
raw = bytearray()
n = 0
for j in range(i, min(i + max_dwords, len(body) // 4)):
chunk = bytes(b ^ 0xFF for b in body[j*4:(j+1)*4])
raw += chunk
n += 1
if 0 in chunk:
break
else:
return None, 0
s = raw.split(b"\0")[0]
if len(s) == 0:
return "", n
try:
dec = s.decode("cp932")
except UnicodeDecodeError:
return None, 0
if all(0x20 <= b or b in (0x09,) for b in s):
return dec, n
return None, 0
def windows(name):
data, f, body = parse(ROOT / name)
nd = len(body) // 4
print(f"\n=== {name} (body {nd} dw, code {f[8]} dw) ===")
for label, cnt, off in (("T1", f[7], f[8]), ("T2", f[9], f[10]), ("T3", f[11], f[12])):
entries = [dw(body, off + k) for k in range(min(cnt, 6))]
print(f" {label}: {cnt} entries -> {[hex(e) for e in entries]}")
for e in entries[:4]:
ctx = [dw(body, i) for i in range(max(0, e - 2), min(nd, e + 5))]
s, _ = try_string(body, e)
tag = f" str@target: {s!r}" if s else ""
print(f" target {e:#x}: [-2..+4] = {[hex(v) for v in ctx]}{tag}")
def scan_strings(name, limit=15, min_len=4):
data, f, body = parse(ROOT / name)
nd = len(body) // 4
print(f"\n=== strings in {name} ===")
found = 0
i = 0
while i < nd and found < limit:
s, n = try_string(body, i)
if s and len(s) >= min_len:
print(f" [{i:#x}] {s!r}")
found += 1
i += n
else:
i += 1
if __name__ == "__main__":
for n in ("MENU.BIN", "ADDEXP.BIN", "CALLBACK_LOST.BIN", "ALCHEMY.BIN"):
windows(n)
scan_strings("MENU.BIN")
scan_strings("SC0030.BIN", limit=20, min_len=6)