Initial commit: RE tooling and docs for The I of the Dragon localization/HD
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# Font rendering map + double-byte patch
|
||||
|
||||
## Font object layout (size `0x191C`, embedded by value in a manager struct)
|
||||
|
||||
Two UI font objects live at `manager + 0x3A8` and `manager + 0x1CC4` (difference = `0x191C`).
|
||||
|
||||
```
|
||||
+0x00 texture pointer (D3D texture object)
|
||||
+0x04 max width
|
||||
+0x08 max height
|
||||
+0x0C SpaceWidth
|
||||
+0x10 LineDistance
|
||||
+0x14 CharDistance
|
||||
+0x18 flag (1 = built)
|
||||
+0x1C 256 glyph entries x 16 bytes = 4 floats (u1,v1,u2,v2) normalized UV
|
||||
+0x101C 256 metric entries x 8 bytes = { int advance, int height }
|
||||
+0x181C 256 "defined" bytes
|
||||
```
|
||||
|
||||
The table stride differs (16 vs 8 vs 1), which is why the tables cannot be enlarged in place and a
|
||||
side table is used for CJK.
|
||||
|
||||
## Key code
|
||||
|
||||
| VA | role |
|
||||
|---|---|
|
||||
| `0x4EBF90` | parse/load `Fonts.dat` (generic config reader) |
|
||||
| `0x4E7DC0` | set font texture |
|
||||
| `0x4E7E30` | `AddChar(code, x1,y1,x2,y2)` — normalizes rect → stores glyph float[4] + metric[2] |
|
||||
| `0x4EC168` | `mov cl,[ebp]` — parser takes only the **first byte** of `Code` |
|
||||
| `0x4E7FD0` | measure text; loop body `0x4E7FF0`; metric lookups `0x4E802C`, `0x4E8033` |
|
||||
| `0x4EAC40` | draw text; loop head |
|
||||
| `0x4EACB0` | `movzx ecx,al` — glyph lookup site in draw loop |
|
||||
| `0x4EACDC`,`0x4EAE9A` | metric lookups in draw loop |
|
||||
| `0x4E56A0` | `IsCharDefined(font, code)` |
|
||||
|
||||
Texture is bound **once per draw call** (`[font]` + vtable `+0xF4`), so ASCII and CJK glyphs must
|
||||
share one texture atlas.
|
||||
|
||||
## Patch design (implemented)
|
||||
|
||||
A new PE section `.cjk` holds two code caves and two big tables:
|
||||
|
||||
```
|
||||
.cjk RVA 0x566000 (VA 0x966000), size 0x1C0000
|
||||
0x00 draw_cave
|
||||
0x0100 metrics_cave
|
||||
0x0200 cjk_glyph : 65536 x 16 bytes (u1,v1,u2,v2 floats)
|
||||
0x100200 cjk_metric : 65536 x 8 bytes (advance,height ints)
|
||||
```
|
||||
|
||||
Hooks (5-byte `jmp rel32`):
|
||||
|
||||
- `0x4EACB0 -> draw_cave` (was `movzx ecx,al`)
|
||||
- `0x4E8026 -> metrics_cave` (was `mov ebp,[ecx+0x14]`)
|
||||
|
||||
Behaviour of each cave:
|
||||
|
||||
- `al < 0x80`: execute the original instructions, jump back to the next instruction.
|
||||
- `al >= 0x80`: decode a 2-byte code `(al<<8)|[ptr+1]`; copy the glyph float[4] into font glyph slot
|
||||
`0xFF` and the metric into slot `0xFF`; set `ecx = 0xFF`, advance the string pointer by one extra
|
||||
byte; jump back into the engine's unchanged quad-building code.
|
||||
|
||||
Slot `0xFF` glyph lives at `font+0x100C`, its metric at `font+0x1814`; these do not collide with the
|
||||
real tables.
|
||||
|
||||
## Requirements / limits
|
||||
|
||||
- The font texture must contain **both** ASCII and CJK glyphs (one texture per draw).
|
||||
Plan: replace the UI font `Texture` with a 2048x2048 atlas and re-point the ASCII `Char` rects.
|
||||
- Lead bytes >= `0x80` are reserved for DBCS. ASCII is untouched.
|
||||
- Confirmed end to end: a GB2312-coded menu string rendered the mapped glyph on screen.
|
||||
|
||||
## Tools
|
||||
|
||||
- `tools/add_section.py` — append an executable PE section.
|
||||
- `tools/apply_cjk.py` — assemble the caves (keystone), add `.cjk`, write hooks and tables.
|
||||
- `tools/decode_dat.py` — decode/encode the XOR `.dat` files.
|
||||
- `tools/fontparse.py` — parse `Fonts.dat` into blocks + glyph rects.
|
||||
- `tools/xrefs.py`, `tools/disasm.py`, `tools/scan_disp.py` — RE helpers.
|
||||
Reference in New Issue
Block a user