Files
dragon-hd/tools/prep_test.py
T

94 lines
3.4 KiB
Python

import os, re, struct
from PIL import Image, ImageDraw, ImageFont
GAME = r"F:\steam\steamapps\common\The I of the Dragon"
OUT = r"E:\DragonHD\patch"
TBL = os.path.join(OUT, "tables")
KEY = b"GBDFYTNE"
os.makedirs(TBL, exist_ok=True)
CODE = 0xC1FA # GB2312 "龙"
GLYPH = "龙"
GW = GH = 16
AX, AY = 122, 0 # free spot in Shrift_gb_Germany.TGA (256x128)
ATLAS = "Shrift_gb_Germany.TGA"
ADVANCE = 17
HEIGHT = 16
# ---- 1. render glyph ----
font = ImageFont.truetype(r"C:\Windows\Fonts\simhei.ttf", GH)
g = Image.new("RGBA", (GW, GH), (0, 0, 0, 0))
d = ImageDraw.Draw(g)
bb = d.textbbox((0, 0), GLYPH, font=font)
d.text(((GW-(bb[2]-bb[0]))/2 - bb[0], (GH-(bb[3]-bb[1]))/2 - bb[1]), GLYPH, fill=(255, 255, 255, 255), font=font)
gpx = g.load()
def tga_geom(raw):
w = struct.unpack_from("<H", raw, 12)[0]
h = struct.unpack_from("<H", raw, 14)[0]
return w, h, raw[17]
def add_glyph(raw):
w, h, desc = tga_geom(raw)
off = 18 + raw[0]
def row(y): return y if (desc & 0x20) else (h - 1 - y)
for dy in range(GH):
for dx in range(GW):
a = gpx[dx, dy][3]
if a == 0:
continue
i = off + (row(AY+dy) * w + (AX+dx)) * 4
raw[i] = 255; raw[i+1] = 255; raw[i+2] = 255; raw[i+3] = a
# inject into loose + res
loose = os.path.join(GAME, "Data", "Textures", "Ui", "Overhead", ATLAS)
for p in [loose, os.path.join(GAME, "Data", "Textures", "Ui", "Overhead", "Shrift_gb.tga")]:
if os.path.exists(p):
raw = bytearray(open(p, "rb").read())
add_glyph(raw)
open(p, "wb").write(raw)
print("injected loose", 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"]:
if nm in ent:
o, s = ent[nm]
raw = bytearray(data[o:o+s])
add_glyph(raw)
data[o:o+s] = raw
print("injected res", nm)
open(res, "wb").write(data)
# ---- 2. cjk tables ----
glyph_tbl = bytearray(65536 * 16)
metric_tbl = bytearray(65536 * 8)
u1 = AX / 256.0; v1 = AY / 128.0; u2 = (AX + GW) / 256.0; v2 = (AY + GH) / 128.0
struct.pack_into("<4f", glyph_tbl, CODE * 16, u1, v1, u2, v2)
struct.pack_into("<2i", metric_tbl, CODE * 8, ADVANCE, HEIGHT)
open(os.path.join(TBL, "cjk_glyph.bin"), "wb").write(glyph_tbl)
open(os.path.join(TBL, "cjk_metric.bin"), "wb").write(metric_tbl)
print("tables written, code 0x%04X -> uv(%.4f,%.4f,%.4f,%.4f) advance=%d" % (CODE, u1, v1, u2, v2, ADVANCE))
# ---- 3. set test strings ----
strp = os.path.join(GAME, "Data", "Misc", "Strings.dat")
enc = open(strp, "rb").read()
test = bytes([CODE >> 8, CODE & 0xFF])
ids = ["MainMenu_StartNewGame", "MainMenu_LoadGame", "MainMenu_Options", "MainMenu_Credits",
"MainMenu_Exit", "MainMenu_ResumeGame", "MainMenu_SaveLoadGame", "MainMenu_Multi",
"WindowCaption"]
done = []
for sid in ids:
pat = re.compile((r'(Id\s*=\s*"%s"\s*[\r\n]+\s*English\s*=\s*")[^"]*(")' % re.escape(sid)).encode())
enc2 = pat.sub(lambda m: m.group(1) + test + m.group(2), enc, count=1)
if enc2 != enc:
done.append(sid)
enc = enc2
open(strp, "wb").write(enc)
print("test strings set:", done)