TO:R Data Map

txte: localized text tables

Source
docs/formats/txte.md
SHA-256
33c1e1b7…c5120a72

The game's text format. Each txte text table is a 16-byte header, then 32-byte rows, then a pool of strings. A row pairs a text key, such as ARMSTEXT_LC_ARMS_001_NAME, with its text in one language. The keys are the strings that other files point to, for example xlce string pools (xlce.md). In localize/LocalizeText_<lang>.dat, the payload is a pakd (containers.md) of txte tables.

Based on All eight localize/LocalizeText_<lang>.dat (de-de, en-us, es-es, fr-fr, ja-jp, ko-kr, zh-cn, zh-tw), 72 tables each, 576 in all (the English one: LocalizeText_en-us.dat); Font/FontAllFilePackage.dat for the code sizes (font.md); Gibbed's EventTextFile.cs (reference_tools/Gibbed.LetUsClingTogether/projects/Gibbed.Reborn.FileFormats/), and RebornDecoder.cs, BaseDecoder.cs, MacroCode.cs and MacroCodeHelpers.cs (reference_tools/Gibbed.LetUsClingTogether/projects/Gibbed.TacticsOgre.TextFormats/), each the same in reference_tools/gibbed10/projects/; Gibbed's docs/text_encoding/text_formatting.md (reference_tools/Gibbed.LetUsClingTogether/docs/), which describes the PSP game's codes; the unpacked executable, SHA-256 7b0230a11498f40396c9048345e7cfe0ef442cb7ca8faffc6f197920d2669599.
Checked 2026-10-12
Method Layout and code sizes copied from these sources and checked against them. How the game reads it and the control codes' names: static analysis of the unpacked executable with Ghidra 12.1.4, through the decompiled code in local/exe/decomp/, and DuckDB over the decoded text (R31 review, 2026-10-11). Checked against the game data, 2026-10-11: the round trip, tor round-trip local/game/Data/localize/LocalizeText_en-us.dat local/game/Data/event/event_data.dat --docs docs, rebuilt all 72 English text tables (31,053 rows) from their rows in the text form, with no byte taken from the original, and the whole file byte for byte, with no decode problem reported; tor read-back over the same file read the decoded text back to the same file. 2026-10-12 (R19): tor round-trip local/game/Data/localize --docs docs rebuilt all 576 tables of the eight languages (1,205,348 strings) and all 8 files byte for byte, with no decode problem reported, and tor read-back read each back to the same file; the decode walks every escape and offset, and the encoder recomputes every zombie_condition length. 2026-10-13 (R36): DuckDB over the decoded text of the eight languages (data/game/localize/*/*.txte.jsonl, from tor export) tallied the codes, icons, extra NULs and zombie_condition length bytes below from their text forms, by language. The code sizes were found by searching the game files for Gibbed's sizes (r19/findbytes.cs). No in-game tests yet.
Offset Size Type Name Meaning Confidence Source
0x0 4 raw[4] magic txte. confirmed The round trip (576/576). Gibbed EventTextFile agrees (Signature 0x65747874, read little-endian).
0x4 4 s32 row_count Number of rows. confirmed The round trip. 0x1402ba410. Gibbed EventTextFile agrees (count).
0x8 4 u32 row_offset Where the rows start; always 16. Gibbed rejects any other value. confirmed The round trip (the decode refuses any other value). 0x1402ba410: row n is at entry + row_offset + n × row_size. Gibbed EventTextFile agrees (headerSize).
0xC 4 u32 row_size Size of one row; always 32. Gibbed rejects any other value. confirmed The round trip (as above). 0x1402ba410 (the stride). Gibbed EventTextFile agrees (entrySize).
0x10 row_count × 32 — rows The rows, packed with no gaps. See Row. confirmed The round trip. Gibbed EventTextFile agrees.

Row

Every field is a str_ofs64: an offset from the start of the table (the txte magic) to a NUL-terminated string in the pool. Gibbed reads each as a u32 offset followed by a u32 that must be zero, which is the same bytes.

Offset Size Type Name Meaning Confidence Source
0x00 8 str_ofs64 key The text key, plain UTF-8. likely The round trip (layout). 0x1402ba410 indexes the rows by it; 0x1402b95d0 looks keys up. Gibbed EventTextFile agrees (IdOffset, Id).
0x08 8 str_ofs64 text The text, in the text encoding. likely The round trip (layout). 0x1402b95d0 returns it. Gibbed EventTextFile agrees (ValueOffset, Value, decoded with RebornDecoder).
0x10 8 str_ofs64 unk_0x10 Unknown; no reader found. Empty in every row but the unit names of German, Spanish and French: there it is M or F on the random-name tables #19–#23 (UNITNAME1–5; #20 and #22 all F, the others mostly M) and on some rows of #18 (UNITNAME0), which looks like the grammatical gender of the name. Gibbed reads it as a plain UTF-8 string. — The round trip, all 8 languages; DuckDB over localize/*/*.txte.jsonl. Gibbed EventTextFile (Unknown10Offset).
0x18 8 str_ofs64 unk_0x18 Unknown; no reader found. X in every row of table #0 in every language, empty in every other row. Gibbed reads it as a plain UTF-8 string. — The round trip; DuckDB as above. Gibbed EventTextFile (Unknown18Offset).

String pool

Padding

Text encoding

text is UTF-8 with escapes mixed in. Each escape starts with a Unicode private-use code point. All rows are likely: the eight languages' text uses every escape and icon below and every code whose row doesn't say no text uses it, and decodes with them with no problem reported (no unknown code, no unlisted private-use code point, no invalid UTF-8) and rebuilds byte for byte, but a round trip would also pass with some wrong code sizes, since the text form keeps every byte either way. No text uses U+F8FC or U+F8FE.

Bytes Code point Followed by Meaning Confidence Source
EF A3 BF U+F8FF A code byte, then its arguments. A control code. likely Gibbed RebornDecoder (Macro), BaseDecoder.
EF A3 BD U+F8FD 1 byte. Inserts stored string number xx − 1 (Escapes and control codes). Shown as {f8fd xx}; used in CONFIRM_ rows. likely The game's drawing routines (0x1402a4a00 …) pass xx − 1 to 0x14029b720. Gibbed RebornDecoder (UnknownFD), BaseDecoder (reads 1 byte).
F4 80 80 80–F4 80 80 9E U+100000–U+10001E Nothing. An icon; the ones listed there are all the text uses. likely DuckDB over the text forms of all eight languages (R36, see Method); Gibbed BaseDecoder (gaiji labels).

In the file pages and the decoded data (../../toolchain/README.md#decoded-data), control codes and icons are shown as {name}, or {name args} with the argument bytes in hex: How {wrap 01 01}could (an illustration). This text form is what the encoder reads back to bytes, so every byte string has exactly one text form:

Text form Bytes When
{{ and }} { and } A literal brace in the game text. A lone { or } is an error when encoding. Gibbed's BaseDecoder escapes braces the same way.
{name}, {name args} U+F8FF, the code byte, then the argument bytes A control code; the number of argument bytes must be its Size − 1.
{f8fd xx} U+F8FD, then byte xx The U+F8FD escape.
{nul} One extra NUL after the string's own Only at the end, once per extra NUL (String pool). The game stops reading at the first NUL, so it never shows.
{icon_…} The icon's code point, in UTF-8 An icon.
{U+XXXX} That code point, in UTF-8 A private-use code point or a control character (below U+0020) not in this doc. Reported as a problem.
{?? hex} U+F8FF, then the bytes as given A control code not in this doc. The decoder can't know its size, so the hex runs to the end of the string. Reported as a problem.
{byte xx} Byte xx A byte that isn't valid UTF-8. Reported as a problem.

Everything else is the character itself, in UTF-8. A string can't contain NUL.

Control codes

Size counts the code byte and its arguments, not the U+F8FF before it. The sizes are the 54 bytes of control_code_sizes in Font/FontAllFilePackage.dat (font.md), one per code from 0x80 to 0xB5, which is the shape of the size table the drawing routines skip codes by (Escapes and control codes); Gibbed's MacroCodeHelpers.GetSize gives the same sizes for 0x80–0xB3. Only the codes below are decoded; an unlisted code stops the decoder, which reports it and keeps the rest of the string as {?? hex}. Names and meanings are from the drawing routines (0x1402a4a00 and the others in Escapes and control codes), the game's keys and the decoded text; codes the drawing routines hand to a virtual function (0x93–0x96, 0xA9 and others) rest on keys and data only. text_formatting.md describes the PSP game, where codes start with byte FF instead of U+F8FF. Which languages use a code is from DuckDB over the text forms of the eight LocalizeText_<lang>.dat (R36, see Method); a code with no use says so.

Code Size Name Meaning Confidence Source
0x80 1 newline Line break: the pen goes back to the line start and down one line height. likely 0x1402a4a00 case 0x80. Gibbed MacroCode (InsertNewline), MacroCodeHelpers.
0x81 3 wrap A wrap area: where a line break may go if what follows doesn't fit. Arguments: the width (× 2 is the game's width; Gibbed: pixels), then a byte; 01 01 is the usual form, and a second argument of 0xDE acts as 0x86. likely Case 0x81: breaks the line when the text's wrap bit (0x200) is set and the pen would pass the width. Gibbed MacroCode (IndicateWrapArea), MacroCodeHelpers; text_formatting.md (FF 81).
0x82 5 color Sets the text color: three bytes, each minus 1, then an alpha minus 1 (scaled by the renderer's alpha). No text uses it. likely Case 0x82. Gibbed MacroCode (SetTextColor), MacroCodeHelpers.
0x83 6 string_param Inserts a string parameter of the text object. Arguments: the parameter slot (from 1), unknown, a number slot (from 1; FF for none), unknown, unknown; when that number is above 1 the parameter's second string is used. likely Case 0x83: slot arg1 − 1 (0x14029b7e0, +0x50 + 8n), number slot arg3 − 1 (0x14029b510). Gibbed MacroCodeHelpers, BaseDecoder (var str); text_formatting.md (FF 83).
0x84 5 number_param Inserts a number parameter of the text object. Arguments: the parameter slot (from 1), a string slot for 1 (from 1), unknown, then a format (from 1; Reborn's fourth byte). likely Case 0x84: 0x14029b510; 1 → string slot arg2 − 1; otherwise formats the number (0x14029db90, arg4 − 1). Gibbed MacroCodeHelpers (5 in Reborn, 4 on PSP), BaseDecoder (var num); text_formatting.md (FF 84).
0x85 3 unk_85 Unknown; the drawing routine computes arg2 + arg1 × 255 − 256 (the length formula of 0x95) and skips. — Case 0x85. Gibbed MacroCodeHelpers.
0x86 1 page_break Page break: drawing stops there; in MODAL_ rows the text after it is a separate message. likely Case 0x86 sets the done flags; data. Gibbed MacroCode (InsertPageBreak), MacroCodeHelpers.
0x87 2 unk_87 Unknown; switches between two styles by its argument (1 or other). No text uses it. — Case 0x87. Gibbed MacroCodeHelpers.
0x88 2 spacing Horizontal spacing: moves the pen by the signed argument, in pixels. English only. likely Case 0x88. Gibbed MacroCode (InsertPixelSpacing), MacroCodeHelpers.
0x89 2 wait A pause in text that is shown a character at a time: takes (argument − 1) × 10 from the countdown each drawn character also takes from, and stops drawing there, as 0x86 does, once that countdown is used up. None in English or Spanish. likely Case 0x89. Gibbed MacroCodeHelpers (Unknown89).
0x8A 2 unk_8a Unknown; no text uses it. — Size only. Gibbed MacroCode (InsertIcon), MacroCodeHelpers.
0x8B 3 unk_8b Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x8C 2 choice Starts a choice; the argument is the default option, from 1. {choice 01} starts every numbered choice in SCENARIO_ texts, whose options are CHOICE_ rows. The drawing routine only sets a scale flag. likely Data (DuckDB); case 0x8C. Gibbed MacroCode (InsertSelect), MacroCodeHelpers; text_formatting.md (FF 8C).
0x8D 3 unk_8d Unknown; moves the pen to half the line width minus arg1 unless arg2 is 1. — Case 0x8D. Gibbed MacroCodeHelpers.
0x8E 3 unk_8e Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x8F 3 unk_8f Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x90 3 unk_90 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x91 1 unk_91 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x92 1 unk_92 Unknown. — Gibbed MacroCodeHelpers.
0x93 1 hero_name Inserts the hero's name: it stands where Denam's name goes (CHARA_TEXT_, BATTLE_TEXT_). likely Key MODAL_LC_SYSTEM_MESNAME_HERO_TEXT; data. Gibbed MacroCode (InsertHeroName), MacroCodeHelpers.
0x94 1 order_name Inserts the order's name: "leads the Order of {order_name}". Not the order titles of the ORDER_ table. likely Data (CHARA_TEXT_LC_WR_CHARA_0003_CHR_TEXT). Gibbed MacroCode (InsertOrderName), MacroCodeHelpers.
0x95 4 zombie_condition Starts a span, which 0x96 ends, of text about undeath ("…As true in undeath…", in CLASS_TEXT_DATA_ rows). Arguments: a value (Gibbed shows it minus 1), then two length bytes a b: the span length L = a × 255 + b − 256 is the number of bytes from just after b to the end of the 0x96 code, its U+F8FF included; Gibbed checks that the last 4 of them are EF A3 BF 96. An encoder recomputes the length (Rebuilding). likely Data; the game's string "ZombieFadeIn" (0x1406958c0). Gibbed MacroCode (ZombieCondition), MacroCodeHelpers, BaseDecoder.
0x96 1 zombie_condition_end Ends the span 0x95 starts. likely Data. Gibbed MacroCode (ZombieConditionEnd), MacroCodeHelpers.
0x97 1 unk_97 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x98 3 unk_98 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0x99 3 unk_99 Unknown. — Gibbed MacroCodeHelpers.
0x9A 2 unk_9a Unknown. — Gibbed MacroCodeHelpers.
0x9B 1 unk_9b Unknown; the drawing routine adds the same render command it adds after a callback's style change. No text uses it. — Case 0x9B. Gibbed MacroCode (ResetTextColor), MacroCodeHelpers.
0x9C 3 unk_9c Unknown. — Gibbed MacroCodeHelpers.
0x9D 2 unk_9d Unknown; sets a value of the renderer to the argument minus 1, which 0x9E resets. No text uses it. — Case 0x9D. Gibbed MacroCode (SetFontPalette), MacroCodeHelpers.
0x9E 1 unk_9e Unknown; resets the value 0x9D sets. No text uses it. — Case 0x9E. Gibbed MacroCode (ResetFontPalette), MacroCodeHelpers.
0x9F 1 uppercase_next Uppercases the next character (toupper, or − 0x20 for U+00E0–U+00FF). likely Case 0x9F sets a flag that the next character clears (0x1402a45e0). Gibbed MacroCode (UppercaseFollowingCharacter), MacroCodeHelpers.
0xA0 1 unk_a0 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA1 1 unk_a1 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA2 1 unk_a2 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA3 1 unk_a3 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA4 1 unk_a4 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA5 1 unk_a5 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA6 1 unk_a6 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA7 1 unk_a7 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA8 1 unk_a8 Unknown; no text uses it. — Size only. Gibbed MacroCodeHelpers.
0xA9 1 new_page Starts most dialogue texts (the SCENARIO_C4_ rows, for one); not handled by the drawing routines. likely (size); guess (name) Data. Gibbed MacroCode (MaybeNewPage), MacroCodeHelpers; text_formatting.md ("New page?/reset state?").
0xAA 2 unk_aa Unknown; Reborn only. Switches between two styles by its argument; German, Spanish and French mark terms with it ({unk_aa 02}Attaque physique{unk_aa 01}). — Case 0xAA; data. Gibbed MacroCodeHelpers.
0xAB 3 unk_ab Unknown; French only. — Size only. Gibbed MacroCodeHelpers.
0xAC 3 unk_ac Unknown; French only. — Size only. Gibbed MacroCodeHelpers.
0xAD 1 unk_ad Unknown; French only. — Size only. Gibbed MacroCodeHelpers.
0xAE 3 unk_ae Unknown; French only. — Size only. Gibbed MacroCodeHelpers.
0xAF 3 unk_af Unknown; French only. — Size only. Gibbed MacroCodeHelpers.
0xB0 1 unk_b0 Unknown; Reborn only. Depends on the voice language (0x140286e90). — Case 0xB0. Gibbed MacroCodeHelpers.
0xB1 1 unk_b1 Unknown; Reborn only. As 0xB0, for the other language. — Case 0xB1. Gibbed MacroCodeHelpers.
0xB2 4 unk_b2 Draws an image from the renderer's table at +0x600; Reborn only. Gibbed shows each argument minus 1. — Case 0xB2 → 0x1402a32f0. Gibbed MacroCodeHelpers, BaseDecoder (symbol).
0xB3 4 button Draws a button image; Reborn only. Some of its uses are in keys with BTN (GUIDE_LC_GUIDE_BTN_SELECT_NAME), none of 0xB2's. Gibbed shows each argument minus 1. likely 0x1402a32f0(…, code == 0xB3, …); DuckDB. Gibbed MacroCodeHelpers, BaseDecoder (button).
0xB4 3 unk_b4 Picks one of two text variants by whether a character is in the font package's char_set_150 (in French, the vowels): probably French elision (le/l'). French only, in BATTLE_TEXT_ and CHARA_TEXT_ rows. — font.md (char_set_150, tested by 0xB4 and 0xB5 through 0x14029be20). Gibbed lists no 0xB4.
0xB5 3 unk_b5 As 0xB4; French only. — As 0xB4.

Icons

Code point Name Meaning Confidence Source
U+10000B icon_ai Icon; the game's word AI is in the keys it's used with (COMMAND_LC_COMMAND_NAME_AI02_NAME …). likely DuckDB. Gibbed BaseDecoder (ai).
U+10000C icon_skillrankup Icon: the whole text of TAG_LC_TAG_BTLBYHIT_SKILLRANKUP_NAME. likely DuckDB. Gibbed BaseDecoder (skillrankup).
U+10000D icon_enemy Icon before the enemy side's line in BATTLE_TEXT_ briefings ("The Dark Knights"). likely DuckDB. Gibbed BaseDecoder (enemy).
U+10000E icon_leader Icon before the enemy leaders' line in briefings ("The Dark Knights Volaq and Ozma"). likely DuckDB. Gibbed BaseDecoder (leader).
U+10000F icon_guest Icon before a guest unit's line in briefings ("Azelstan"). likely DuckDB; the game's word GUESTMENU_. Gibbed BaseDecoder (guest).
U+100000 icon_heart Icon at the end of Deneb's playful lines ("W-I-C-C-E! {icon_heart}" in German, the title "Mit Herz und Kürbis" of CURRENT_AFFAIRS_TEXT_LC_CURRENT_0246_TITLE); not in English or Spanish, which use none. likely DuckDB (CLASS_TEXT_DATA_CLASS0061_HELP in German, French, Japanese, Korean and Chinese). Gibbed BaseDecoder (heart).
U+100001 icon_unk_100001 Icon after the same kind of line as icon_heart, in Deneb's skill helps (EFFECTTEXT_LC_EFFECT_640_HELP: "…poison them──{icon_unk_100001}"). What it shows is unknown. guess DuckDB.
U+100010 icon_letter_w One letter of a word drawn as icons: "World Tarot" is {icon_letter_w}{icon_letter_o}{icon_letter_r}{icon_letter_l}{icon_letter_d} after 運命の輪 in Japanese, Korean and Chinese (COMMAND_LC_COMMAND_NAME_WRMAIN09_NAME), where English writes "World Tarot". likely DuckDB; the letters line up across "WORLD" and "CHARIOT" (BATTLETASK_LC_BTL_TSK0560_NAME, "Chariot Tarot"), which share O and R.
U+100011 icon_letter_o The letter O, as U+100010. likely As U+100010.
U+100012 icon_letter_r The letter R, as U+100010. likely As U+100010.
U+100013 icon_letter_l The letter L, as U+100010. likely As U+100010.
U+100014 icon_letter_d The letter D, as U+100010. likely As U+100010.
U+100015 icon_letter_c The letter C: "CHARIOT" is U+100015, U+100016, U+100017, U+100012, U+100018, U+100011, U+100019. likely As U+100010.
U+100016 icon_letter_h The letter H, as U+100015. likely As U+100010.
U+100017 icon_letter_a The letter A, as U+100015. likely As U+100010.
U+100018 icon_letter_i The letter I, as U+100015. likely As U+100010.
U+100019 icon_letter_t The letter T, as U+100015. likely As U+100010.
U+10001B icon_arrow_up Up arrow: German, Spanish and French write it where English writes "Up", "+" or "Ascending" (CHOICE_LC_CHOICE_NAME_TCS_KEY0100_NAME "Cursor/Dirección {icon_arrow_up}", TAG_LC_TAG_BTLBYHIT_AGL_PLUS_NAME "AGI {icon_arrow_up}"). likely DuckDB, against the English rows of the same keys.
U+10001C icon_arrow_down Down arrow: where English writes "Down", "−" or "Descending" (…TCS_KEY0110_NAME, …AGL_MINUS_NAME). likely As U+10001B.
U+10001D icon_arrow_left Left arrow: where English writes "Left" (…TCS_KEY0120_NAME). likely As U+10001B.
U+10001E icon_arrow_right Right arrow: where English writes "Right" (…TCS_KEY0130_NAME) or ">" (TAG_LC_TAG_TCS_NOTICE_UNI_LV_VALUE_NAME, "Lv. 2 > Lv. 3"). likely As U+10001B.

How the game reads it

From text/textmanager.cpp and the font renderer (BaseFontRenderer, graphics/font/basefontrenderer.cpp), by static analysis with Ghidra 12.1.4 of the unpacked executable (SHA-256 7b0230a1…), so at most likely.

Loading and lookup

How a table's ID becomes text

Escapes and control codes

Rebuilding

How a table is rebuilt from its rows in the text form. All steps are confirmed for the eight languages: the encoder follows them with no byte taken from the original, and gives back all 576 tables byte for byte (the round trip, see Method). Step 5 recomputes every zombie_condition length to the original bytes, and step 7 writes back every extra NUL.

  1. Header: magic txte, row_count = the number of rows, row_offset 16, row_size 32 (Header).
  2. Rows: in their original order, each field an offset (upper 4 bytes zero) to its string (Row).
  3. String pool: right after the last row; each row's strings in field order (key, text, unk_0x10, unk_0x18), each encoded from the text form and followed by one NUL. No string is shared, so every offset is recomputed from the lengths (String pool).
  4. Padding: zeros up to align16(data_size + 1), where data_size is the end of the pool (Padding).
  5. zombie_condition's length bytes are recomputed for each 0x95 from its matching 0x96 (paired like brackets), so edits inside the span stay valid: with L as in Control codes, a = L div 255 + 1 and b = L mod 255 + 1, so neither byte is ever 0 (a NUL would end the string); L must be below 255 × 255. A 0x95 with no 0x96 keeps the bytes given. Every span in the eight languages is written so (one French span has a = 2). Source for the length: Gibbed BaseDecoder; for the bytes, the round trip and DuckDB over the text forms (R36, see Method).
  6. unk_0x10 and unk_0x18 are kept as given; their meaning is unknown.
  7. A {nul} at the end of a string writes one more NUL after it (String pool).

Leads