String tables (.str)
The game’s text is stored in plain, unencrypted tables: media\Stripped\StringTables\<LANG>.zip holds one .str file
per table, in ordinary deflate zips. There are 24 languages (BR CHS CHT CZ DE DK EL EN ES FI FR GB HU IT JP KO MX NL NO
PL PT RU SV TR); English has 290 tables plus a _list.txt that names them, a few languages 289. Observed The text is
stored uncompressed as UTF-8; the high entropy is the hash tables. Observed
All figures on this page are from a recorded census of a build no longer installed. Observed
Layout
Section titled “Layout”Little-endian. Two sections of the same shape, the texts first and then the keys; both list the same hashes in the same order.
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 1 | u8 = 0 | zero | Observed | |
| 0x1 | 1 | u8 = 8 | eight | Observed | every file |
| 0x2 | 128 | char[] | table name | Observed | NUL padded to offset 0x82 |
| 0x82 | 2 | u16 = 2 | version | Observed | |
| 0x84 | 4 | u32 = 0x8C | text section offset | Observed | absolute |
| 0x88 | 4 | u32 | key section offset | Observed | = text section offset + 12 + text section size |
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 4 | u32 | size | Observed | = count × 8 + string bytes |
| 0x4 | 4 | u32 | string bytes | Observed | |
| 0x8 | 4 | u32 | count | Observed | |
| 0xC | 8 × count | entry[] | entries | Observed | u32 hash, u32 offset into the string bytes |
| 12 + 8 × count | string bytes | char[] | strings | Observed | NUL-terminated UTF-8 |
The key section’s strings are the string ids (for example IDS_DisplayName_1282); the text section’s are the texts.
Observed
Key hash
Section titled “Key hash”The hash of a key is h = 0xFFFFFFFF; for each UTF-8 byte c: h = rotl32(h ^ c, 7). Observed Over all 6,953 .str files
of all 24 languages: every file walks to its exact end, every string is strict UTF-8, the strings cover every byte of
every string blob, keys are unique per table, and 1,438,048 of 1,438,048 entry hashes equal the formula. Observed
Car names
Section titled “Car names”Data_Car.str holds two keys per car, IDS_DisplayName_<carId> (the model name: “240SX”, “Acty”) and
IDS_ModelShort_<carId> (the short label, usually with make and sometimes a year: “Nissan 240SX ’93”). The carId is
the one in the car’s .carbin. Observed There are 682 car archives with 682
distinct car ids, and all of them hit both keys with no table id left over. Observed
Other tables are keyed by database row ids, not by anything in the car files:
| Table | Content | Linkable from plain files | Confidence |
|---|---|---|---|
List_CarMake.str |
94 makes (IDS_DisplayName_<makeId>, IDS_Profile_<makeId>) |
no: no plain file stores a car’s make id | Observed |
Upgrades.str |
248 upgrade names and descriptions (IDS_Name_<n>) |
no: neither the part id, the part enum nor the carbin level is that n |
Observed |
UpgradeTypes.str |
53 upgrade type names; numbers the same parts 38, 25, 24 … where the part enum has 2, 9, 34 … | no | Observed |
A car’s year appears nowhere in plain files; the year in a file name does not always agree with the year in the
short label (NIS_240SX_94 is “Nissan 240SX ’93”). Observed The link from car to make, year and part names is in the
encrypted game database. Inferred