Files
dragon-hd/tools/prep_test2.py
T

77 lines
3.3 KiB
Python

import os, re, struct
from PIL import Image, ImageDraw, ImageFont
GAME = r"F:\steam\steamapps\common\The I of the Dragon"
TBL = r"E:\DragonHD\patch\tables"
KEY = b"GBDFYTNE"
os.makedirs(TBL, exist_ok=True)
CODE = 0xC1FA
RED = (122, 0, 138, 16)
GREEN = (140, 0, 156, 16)
ATLAS = "Shrift_gb_Germany.TGA"
# 1. paint red + green solid rects into atlas
def paint(raw, x1, y1, x2, y2, b, g, r):
w = struct.unpack_from("<H", raw, 12)[0]
h = struct.unpack_from("<H", raw, 14)[0]
desc = raw[17]; off = 18 + raw[0]
row = (lambda y: y) if (desc & 0x20) else (lambda y: h - 1 - y)
for y in range(y1, y2):
for x in range(x1, x2):
i = off + (row(y) * w + x) * 4
raw[i] = b; raw[i+1] = g; raw[i+2] = r; raw[i+3] = 255
loose = os.path.join(GAME, "Data", "Textures", "Ui", "Overhead")
for p in [os.path.join(loose, "Shrift_gb.tga")]:
if os.path.exists(p):
d = bytearray(open(p, "rb").read()); paint(d, *RED, 0, 0, 255); paint(d, *GREEN, 0, 255, 0)
open(p, "wb").write(d); print("loose painted", p)
res = os.path.join(GAME, "Data", "Textures.res")
data = bytearray(open(res, "rb").read())
cnt = struct.unpack_from("<I", data, 0)[0]; p = 4; ent = {}
for i in range(cnt):
ln = struct.unpack_from("<I", data, p)[0]; p += 4
nm = data[p:p+ln].decode("latin1"); p += ln
o, s = struct.unpack_from("<II", data, p); p += 8; ent[nm] = (o, s)
for nm in ["UI\\Overhead\\Shrift_gb_Germany.TGA", "UI\\Overhead\\Shrift_gb.tga"]:
o, s = ent[nm]; b = bytearray(data[o:o+s]); paint(b, *RED, 0, 0, 255); paint(b, *GREEN, 0, 255, 0)
data[o:o+s] = b; print("res painted", nm)
open(res, "wb").write(data)
# 2. Fonts.dat: point UI English 'e' at RED
fp = os.path.join(GAME, "Data", "Misc", "Fonts.dat")
d = open(fp, "rb").read()
dec = bytes(d[2:][i] ^ KEY[i % len(KEY)] for i in range(len(d) - 2)).decode("latin1")
first = dec.index("Font"); second = dec.index("Font", first + 4)
block0 = dec[first:second]
pat = re.compile(r'(Code\s*=\s*"e"\s*X1\s*=\s*)(-?\d+)(\s*Y1\s*=\s*)(-?\d+)(\s*X2\s*=\s*)(-?\d+)(\s*Y2\s*=\s*)(-?\d+)')
block0b, n = pat.subn(lambda m: "%s%d%s%d%s%d%s%d" % (m.group(1), RED[0], m.group(3), RED[1], m.group(5), RED[2], m.group(7), RED[3]), block0, count=1)
dec2 = dec[:first] + block0b + dec[second:]
enc = b"==" + bytes(dec2.encode("latin1")[i] ^ KEY[i % len(KEY)] for i in range(len(dec2)))
open(fp, "wb").write(enc)
print("Fonts.dat 'e' -> red", n)
# 3. cjk tables: code -> GREEN
gt = bytearray(65536 * 16); mt = bytearray(65536 * 8)
u1 = GREEN[0] / 256.0; v1 = GREEN[1] / 128.0; u2 = GREEN[2] / 256.0; v2 = GREEN[3] / 128.0
struct.pack_into("<4f", gt, CODE * 16, u1, v1, u2, v2)
struct.pack_into("<2i", mt, CODE * 8, 17, 16)
open(os.path.join(TBL, "cjk_glyph.bin"), "wb").write(gt)
open(os.path.join(TBL, "cjk_metric.bin"), "wb").write(mt)
print("cjk 0x%04X -> green" % CODE)
# 4. strings: set menu ids to CODE
sp = os.path.join(GAME, "Data", "Misc", "Strings.dat")
encs = open(sp, "rb").read()
test = bytes([CODE >> 8, CODE & 0xFF])
pat2 = re.compile(rb'(Id\s*=\s*"([^"]*)"\s*[\r\n]+\s*English\s*=\s*")[^"]*(")')
def repl(m):
sid = m.group(2)
if sid.startswith((b"MainMenu", b"OptionsMenu", b"SaveLoadMenu", b"VideoOptions", b"AudioOptions")):
return m.group(1) + test + m.group(3)
return m.group(0)
encs2, n2 = pat2.subn(repl, encs)
open(sp, "wb").write(encs2)
print("menu strings set:", n2)