Initial commit: RE tooling and docs for The I of the Dragon localization/HD
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# File formats
|
||||
|
||||
All addresses are absolute VAs in `TheIOfTheDragon.exe` (image base `0x400000`).
|
||||
|
||||
## 1. `Data\Misc\Strings.dat` — plain text
|
||||
|
||||
Same syntax as the other `.dat` files, but **not** obfuscated. Blocks look like:
|
||||
|
||||
```
|
||||
String
|
||||
{
|
||||
Id = "WindowCaption"
|
||||
English = "..."
|
||||
Russian = "..."
|
||||
German = "..."
|
||||
}
|
||||
```
|
||||
|
||||
- 499 blocks in the Steam build. Keys are `String{ Id, English, Russian, German }`
|
||||
(retail multilanguage builds also carry `Polish`, `Czech`, `Hungarian`, `Hungarian/Russian` variants
|
||||
split across separate installed files).
|
||||
- **Translate only the language values.** Never touch `Id`.
|
||||
- The file is single-byte code page text (Russian is CP1251).
|
||||
|
||||
## 2. `Data\Misc\Fonts.dat`, `UnitDescription.dat`, `AIDescription.dat` — XOR-obfuscated text
|
||||
|
||||
Layout: `b"==" + XOR(plaintext, repeating key)`.
|
||||
|
||||
- Magic `==` at VA `0x620D24`.
|
||||
- Repeating XOR key `GBDFYTNE` (8 bytes) at VA `0x620D18`.
|
||||
- Decoder/encoder routine at `0x4AE1D0`.
|
||||
|
||||
Decoded, these are the same text format as `Strings.dat`:
|
||||
|
||||
- `Fonts.dat`: `Font { Name; Language; Texture; SpaceWidth; LineDistance; Char { Code; X1;Y1;X2;Y2 } ... }`
|
||||
- `UnitDescription.dat`: unit/enemy definitions (Russian comments in CP1251 + English keys).
|
||||
- `AIDescription.dat`: `Brain { AI = ...; TypeAI = ...; ... }`.
|
||||
|
||||
Round-trip is exact; see `tools/decode_dat.py`.
|
||||
|
||||
## 3. `res` archives (`Textures.res`, `Geometry.res`)
|
||||
|
||||
```
|
||||
uint32 count
|
||||
repeat count:
|
||||
uint32 nameLen
|
||||
char[] name (backslash separated)
|
||||
uint32 offset (absolute file offset)
|
||||
uint32 size (exact blob size)
|
||||
pad the index to 16 bytes
|
||||
data region:
|
||||
for each entry: write blob, then pad to 16-byte boundary
|
||||
(the last blob is NOT padded)
|
||||
```
|
||||
|
||||
- All offsets are 16-byte aligned.
|
||||
- `Textures.res` holds 1884 entries: 947 TGA + 935 DDS (DXT1/DXT5) + 2 misc.
|
||||
- `res_unpack.py` / `res_repack.py` round-trip is **byte identical** (verified by SHA1).
|
||||
|
||||
## 4. Scripts
|
||||
|
||||
- `Data\Scripts\<Language>\MainMission.dsc`, `Tutorial.dsc` — plain text, **loaded by the engine**
|
||||
(path template `Data\Scripts\%s\...`; `.dsc` is referenced, `.csc` is not).
|
||||
- Block-structured scripting language. Quoted strings are of two kinds:
|
||||
- **display text** (translate): `SetMissionDescription("...")`
|
||||
- **logic identifiers** (never translate): event names `EnableEvent("TimePassed")`,
|
||||
`LastEvent_Type == "TimePassed"`, commands `EntityCommand("FaceThePlayer",...)`,
|
||||
modes `SetGlobalAIMode("Disable")`, unit types `CreateEntity(..., "Human", ...)`, etc.
|
||||
- Translating logic identifiers is what breaks mission triggers ("完成任务不触发剧情").
|
||||
|
||||
## 5. Language mechanism
|
||||
|
||||
- Current language: registry `HKCU\Software\Primal\Dragon` value `language`.
|
||||
- Assets are per-language by folder: `Data\Scripts\<L>`, `Data\Sounds\Speech\<L>`,
|
||||
`Data\Video\<L>`, `Data\Textures\Ui\...\<L>`.
|
||||
- `Fonts.dat` / `Strings.dat` are installed per language group (observed: `[en de] [pl] [cs] [hu]`;
|
||||
Steam build ships a single English variant with `English/Russian/German`).
|
||||
- Loose files under `Data\Textures\...` override the packed copies.
|
||||
|
||||
## 6. Textures
|
||||
|
||||
- TGA: uncompressed 24/32 bpp and RLE 32 bpp.
|
||||
- DDS: DXT1 (535) and DXT5 (400), plus dimensions from 8x8 up to 1024x1024.
|
||||
- Total 63.6 Mpix across 1884 textures.
|
||||
Reference in New Issue
Block a user