"""Patch the `English` column of `Data\\Misc\\Strings.dat` with simplified Chinese. Reads the byte-exact file (single byte code page), replaces only the value that follows `Id = ""` and `English = "..."`, and writes GB2312 double byte text. The original is preserved next to it as `Strings.dat.orig` (once). """ import argparse import os import re import sys from cn_strings import CN_STRINGS DEFAULT_GAME = r"F:\steam\steamapps\common\The I of the Dragon" def patch(raw, mapping): done, missing = [], [] for sid, cn in mapping.items(): enc = cn.encode("gb2312") pat = re.compile( rb'(Id\s*=\s*"' + re.escape(sid.encode("latin1")) + rb'"' rb'\s*[\r\n]+\s*English\s*=\s*")(?:[^"\\]|\\.)*(")' ) new, n = pat.subn(lambda m: m.group(1) + enc + m.group(2), raw, count=1) if n: raw = new done.append(sid) else: missing.append(sid) return raw, done, missing def main(): ap = argparse.ArgumentParser() ap.add_argument("--game", default=DEFAULT_GAME) ap.add_argument("--file", default=None) ap.add_argument("--restore", action="store_true") args = ap.parse_args() path = args.file or os.path.join(args.game, "Data", "Misc", "Strings.dat") bak = path + ".orig" if args.restore: if os.path.exists(bak): open(path, "wb").write(open(bak, "rb").read()) print("restored", path) else: print("no backup at", bak) return if not os.path.exists(bak): open(bak, "wb").write(open(path, "rb").read()) print("backup ->", bak) raw = open(path, "rb").read() out, done, missing = patch(raw, CN_STRINGS) open(path, "wb").write(out) print("patched %d/%d strings (%d bytes)" % (len(done), len(CN_STRINGS), len(out))) if missing: print("MISSING:", missing, file=sys.stderr) sys.exit(2) if __name__ == "__main__": main()