Files
dragon-hd/docs/DEVLOG.md
T
DragonHD ca5748821c Translate Strings.dat to Simplified Chinese (479/496)
- cn_strings.py: full GB2312 translation table; make_cn_strings.py is now
  escape-aware so values containing escaped-quote formats survive.
- dump_all_strings.py + check_translations.py: dump the English table and
  verify the printf specifier sequence matches the source (0 mismatches).
- Skipped: pure-format/empty strings, the tutorial texture path, ambiguous
  key labels.
- DEVLOG notes the remaining engine-layout caveats.
2026-09-20 10:44:10 +08:00

5.6 KiB

DEVLOG

Working log for the The I of the Dragon localization / HD project. Newest entries on top.

2026-09-20 — Full Strings.dat translation

  • Translated the English column for 479 / 496 entries (the rest are pure-format strings, empty/whitespace values, the tutorial texture path, and a few odd key labels).
  • tools/check_translations.py verifies the printf specifier sequence (%s/%d/%i/%%) matches the English source exactly (0 mismatches) and that every value GB2312-encodes.
  • tools/dump_all_strings.py dumps the source table to build/strings_en.json.

Known layout caveats (engine UI is tuned for the small Latin pixel font)

  • Some engine UI positions tab/button labels against a box sized for English, so short Chinese labels can look left/right-aligned; a couple of centred dialogs jitter while a teletype reveal is running.
  • In-game HUD button labels wrap and can overlap the shortcut hint because the boxes are small; to revisit via a smaller CJK cell/advance if needed.

2026-09-20 — Chinese in the main menu (first playable)

  • Built tools/build_cjk.py: renders the full GB2312 set (7445 double-byte codes) as 12x12 glyphs with simsun (crisp/binary, matching the game's pixel font) into a 2048x1024 TGA. The original 256x128 ASCII artwork is copied to (0,0), so all existing Fonts.dat rects keep working unchanged (verified byte-identical). Also emits cjk_glyph.bin / cjk_metric.bin. Advance/height = 12 (the UI font cap height is ~11-12px), drawn 1px up to fit the cell.
  • tools/cn_strings.py + tools/make_cn_strings.py: translate the English column of Strings.dat to GB2312 (46 entries; escape-aware so \"%s\" formats survive).
  • tools/install_cjk.py: one-shot deploy/restore (backs up exe/res/strings; rebuilds Textures.res with the new atlas, drops the loose atlas, patches the exe and the strings).
  • Result: the main menu renders Chinese — 开始新游戏 / 载入游戏 / 选项 / 教程 / 制作人员 / 退出 / 载入上次存档:"…" — confirmed by the user on screen.

Fixed a byte-order bug in the metrics cave

The draw cave decoded the code as (first<<8)|second, but the metrics cave used movzx eax,al; mov ah,[ebx+1] which produced (second<<8)|first. Every CJK width measured as 0, so centred labels (the "Start New Game" button) were flushed right. Fixed to movzx eax,al; shl eax,8; mov al,[ebx+1]. Centring is now correct.

Notes / next

  • The menu button labels are dynamic (Strings.dat) — the earlier suspicion of baked button images was wrong; the layer confusion came from the animated particle background.
  • Remaining UI text that is baked into textures (credits, tutorial pics) still needs redrawing.
  • Next: translate the rest of Strings.dat, scripts and *Description.dat; then HD textures.

2026-09-20 — Double-byte font patch proven

  • Reverse-engineered the whole text pipeline (see patch-notes.md).
  • Built tools/add_section.py (PE section injection) and verified the patched exe still runs.
  • Built tools/apply_cjk.py: assembles two code caves with keystone, adds a .cjk section, hooks the draw loop (0x4EACB0) and the metrics loop (0x4E8026).
  • Verified on screen: a GB2312-coded string 0xC1FA (龙) in a menu label rendered a 16x16 glyph at the mapped atlas position (green control test). Double-byte decode + render works.
  • Game files restored afterwards (exe SHA1 9EDB9B99..., Textures.res byte-identical).

Next

  1. Big atlas (2048x2048): ASCII glyphs (copied) + CJK glyphs; re-point Fonts.dat Texture + ASCII rects.
  2. Generator for cjk_glyph / cjk_metric tables from a chosen charset.
  3. Convert Strings.dat, scripts, and *Description.dat display text to GB2312.
  4. Redraw baked-in text textures (menu buttons, credits, tutorial).
  5. Package: patched exe + atlas + data files.

2026-09-20 — HD texture preprocessing

  • Cracked the .res archive format and built res_unpack.py / res_repack.py (byte-identical round-trip once 16-byte alignment was found).
  • Extracted Textures.res (1884) and Geometry.res (1397).
  • Built preprocess.py (TGA/DDS→PNG, classification) and make_plan.py.
  • Result: 63.6 Mpix, 1882 PNG, 0 failures. Plan: 1195 upscale / 499 tiling / 182 review / 8 skip (6 font atlases + 2 non-textures).

2026-09-20 — Cracking the .dat obfuscation

  • Fonts.dat / UnitDescription.dat / AIDescription.dat decoded: b"==" + XOR(plaintext, "GBDFYTNE"); key at 0x620D18, decoder at 0x4AE1D0.
  • Fonts.dat parsed: 4 font blocks, per-char atlas rects; parser keeps only the first byte of Code (0x4EC168), so the stock engine is single-byte.

2026-09-20 — Initial findings

  • Engine has a data-driven multi-language system: per-language folders for scripts/speech/video/UI textures and language columns in Strings.dat.
  • Text is externalized: Strings.dat (499 entries, plain) and plain-text scripts.
  • First font test: replaced the e glyph in Shrift_gb_Germany.TGA and confirmed the atlas override works in game (rendered 龙 where e was).
  • Investigated the "pirate build": PROPHET 2009 Topware release, languages EN/DE/PL/CZ/HU, no Chinese; its exe is identical to the Steam exe (no engine patch), so the Chinese build the user remembers was a different repack (not recoverable from it).

Decisions

  • Do the localization ourselves (route B): patch the engine for double-byte text, build our own font atlas, translate only display text (never Ids / event names / unit types) to avoid trigger bugs.
  • Keep the repository text-only; regenerate binaries from scripts (see .gitignore).