GTA 1 FXT Format

Back to main page

Description

The FXT format contains language specific texts of the game in a slightly encrypted manner.

FXT↔TXT Converter

This converter tool allows you to convert FXT files to TXT and vice versa.
It fully supports all languages, including Japanese, and corrects many issues that other converters handle incorrectly.
It has been thoroughly tested with all official FXT files, and converting from TXT back to FXT reproduces the original file exactly, bit for bit.
It also detects illegal characters such as non-implemented European accent characters or Japanese Kanji characters which are not implemented in the game.
For this reason, this converter is as accurate and reliable as possible.

Download for Windows
Usage: Just drag'n'drop an FXT or TXT file into the EXE. It will then create an converted FXT/TXT file in the same directory. Alternatively, use it via command line (cmd.exe).

Download for Linux
Usage: Call it in the shell. The arguments are a bit different than the Windows version. To converter Japanese, make sure that KANJI.IDX is present.

Source code for Delphi (Windows) and FreePascal (Linux)

TODO for the future: Create a FXTPad clone based on this converter, including real-time view of illegal characters


Technical notes about the FXT Format

Decrypt process (FXT to TXT)

The file is decrypted byte-by-byte, with this code system:

8 Byte Header mask

The first 8 bytes in the FXT file are masked. The decoding is performed as follows:

For i = 0..7:
Unmasked[i] := ((Input[i] + 256 - K[i]) mod 256) + 1

(Note: The addition of 256 ensures consistent non-negative results across programming languages where the modulo operation on negative values differs. The "+1" at the end is because we will do "-1" later.)

The sequence K[i] is generated by a linear congruential generator (LCG):

K[0] := 100
K[i+1] := (2 * K[i] - 1) mod 256

Hence:

K = { 0x64, 0xC7, 0x8D, 0x19, 0x31, 0x61, 0xC1, 0x81 }

After unmasking, the resulting bytes are processed according to the code system described above.
In other words, this header handlings are to be COMBINED with the code system (Most converters don't do this!).

All operations are performed in the ring ℤ/256ℤ (8-bit arithmetic).

European Charset

        0 1 2 3 4 5 6 7 8 9 A B C D E F
C4 0x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
C4 1x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
C4 2x  ß à á â ! ä ! æ ç è é ê ë ì í î
C4 3x  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !
C4 4x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
C4 5x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
C4 6x  ß à á â ! ä ! æ ç è é ê ë ì í î
C4 7x  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !
C4 8x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î  (used in GTA 1)
C4 9x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !  (used in GTA 1)
C4 Ax  ß à á â ! ä ! æ ç è é ê ë ì í î  (used in GTA 1)
C4 Bx  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !  (used in GTA 1)
C4 Cx  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
C4 Dx  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
C4 Ex  ß à á â ! ä ! æ ç è é ê ë ì í î
C4 Fx  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !

       0 1 2 3 4 5 6 7 8 9 A B C D E F
84 0x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î  (used in GTA London)
84 1x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !  (used in GTA London)
84 2x  ß à á â ! ä ! æ ç è é ê ë ì í î  (used in GTA London)
84 3x  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !  (used in GTA London)
84 4x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
84 5x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
84 6x  ß à á â ! ä ! æ ç è é ê ë ì í î
84 7x  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !
84 8x  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
84 9x  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
84 Ax  ß à á â ! ä ! æ ç è é ê ë ì í î
84 Bx  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !
84 Cx  ! À Á Â ! Ä ! Æ Ç È É Ê Ë Ì Í Î
84 Dx  Ï ! ! Ò Ó Ô ! Ö ! ! Ù Ú Û Ü ! !
84 Ex  ß à á â ! ä ! æ ç è é ê ë ì í î
84 Fx  ï ! ! ò ó ô ! ö ! ! ù ú û ü ! !

Japanese translation

Converting FXT to Shift-JIS, and vice-versa

Background

The FXT format encodes Japanese characters (originally stored as Shift-JIS) into 3-byte sequences with a prefix byte of 0xEz.

Forward Formula (FXT → Shift-JIS)

To convert from FXT to Shift-JIS, the formula is:

ShiftJIS(0xEZ B0 B1) = 0xZFFE − 0x40*(0xFF−B0) − (0xFF−B1)

The game accepts the prefix Fz which behaves exactly like Ez. For example, you could use F9 instead of E9.

Inverse Formula (Shift-JIS → FXT)

Step 1 — Determine prefix from Shift-JIS value:

| Shift-JIS range | Prefix | Base    |
| --------------- | ------ | ------- |
| 0x0000 – 0x0FFF | 0xE1   | 0x1FFE  |
| 0x1000 – 0x1FFF | 0xE2   | 0x2FFE  |
| 0x2000 – 0x2FFF | 0xE3   | 0x3FFE  |
| 0x3000 – 0x3FFF | 0xE4   | 0x4FFE  |
| 0x4000 – 0x4FFF | 0xE5   | 0x5FFE  |
| 0x5000 – 0x5FFF | 0xE6   | 0x6FFE  |
| 0x6000 – 0x6FFF | 0xE7   | 0x7FFE  |
| 0x7000 – 0x7FFF | 0xE8   | 0x8FFE  |
| 0x8000 – 0x8FFF | 0xE9   | 0x9FFE  |  (used in GTA1 + GTA London)
| 0x9000 – 0x9FFF | 0xEA   | 0xAFFE  |  (used in GTA1 + GTA London)
| 0xA000 – 0xAFFF | 0xEB   | 0xBFFE  |
| 0xB000 – 0xBFFF | 0xEC   | 0xCFFE  |
| 0xC000 – 0xCFFF | 0xED   | 0xDFFE  |
| 0xD000 – 0xDFFF | 0xEE   | 0xEFFE  |
| 0xE000 – 0xEFFF | 0xEF   | 0xFFFE  |  (used in GTA London, but character is unimplemented)
| 0xF000 – 0xFFFF | 0xF0?  | 0x000E? |

The two ranges are non-overlapping, so the prefix is determined unambiguously by the Shift-JIS value alone. No lookup table is needed.

Step 2 — Compute B0 and B1:

D := Base − ShiftJIS

Y := D mod 0x40
if Y < 0x3F then Y := Y + 0x40 // correction: Y always lies in [0x3F..0x7E]
X := (D − Y) div 0x40

B0 := 0xFF − X
B1 := 0xFF − Y

Why the correction?

The formula D = 0x40*X + Y is not a standard positional system because Y can exceed the factor 0x40. Analysis of all known FXT codes shows that 0xFF − B1 (i.e. Y) always falls in the range [0x3F..0x7E]. A raw D mod 0x40 yields values in [0..0x3F], which means values in [0x40..0x7E] get incorrectly folded down. Adding 0x40 when Y < 0x3F restores the correct value.

Step 3 — Output:

Output: Prefix || B0 || B1

Example

Encode Shift-JIS 0x8345 (ウ):

Prefix = 0xE9 (since 0x8345 < 0x9000), Base = 0x9FFE
D = 0x9FFE − 0x8345 = 0x1CB9
Y = 0x1CB9 mod 0x40 = 0x39 → 0x39 < 0x3F → Y = 0x39 + 0x40 = 0x79
X = (0x1CB9 − 0x79) div 0x40 = 0x1C40 div 0x40 = 0x71
B0 = 0xFF − 0x71 = 0x8E
B1 = 0xFF − 0x79 = 0x86

Result: E9 8E 86 ✓

Displaying Japanese Text

The index becomes transformed (unknown) and looked up in KANJI.IDX (which is a Int16 → Int16 Lookup Table), and then gather the graphics from KANJI.BIT which has 5040 glyphs á 16x16 pixels.

KANJI.BIT is a raw graphics file where 1 bit is 1 pixel.  (See the file being converted to PNG here. Your browser might not display this 16x80640 pixels picture correct, though.)

Examples:

The rendering/lookup process for the FXT code E9 8F 8E is as follows:

  1. FXT to Shift-JIS
    1. The FXT Code E9 8F 8E is converted to Shift-JIS using the formula 0xZFFE − 0x40*(0xFF−B0) − (0xFF−B1), for example E9 8F 8E becomes Shift-JIS 83 8D
  2. Shift-JIS to IDX
    1. Multiply the value by 2, since IDX has 16 bit offsets.  The offset in the IDX file will be 0x838D * 2 = 0x1071A.
  3. IDX to BIT
    1. At the IDX offset, a 16 bit value will be read, for example at offset 01 07 1A you will find AA 02.
    2. Swap the bytes.  AA 02 becomes 0x2AA, which means: Read glyph # 682.
    3. Multiply by 0x20 (because each 16x16 glyph occupies 32 bytes).  0x2AA * 0x20 = 0x5540
    4. This is the offset in the KANJI.BIT file.
  4. Reading the BIT file
    1. At 0x5540, read 0x20 bytes, and render it as raw binary data, 1 bit per pixel, 16x16 pixels.
    2. You will see the symbol ロ rendered.

See also:

Decoded contents

The decoded contents look like this:

[1001]Answer the South Park phones to get jobs. Keep your eyes open for opportunities. Remember - you mess up, we mess you up.
[1002]Crazy Jimmy's dumped a car in North East Park. Find it before the cops do - or die.
[1003]Bring the car to Dulli's in West Park. Move it! We got some fresh pussy here!

The number at the beginning is the brief number that can be used in mission.ini scripts.

Footer

The FXT file must end with "5C 5E", which represents "[]" in the TXT file, otherwise the game won't read the file.

The usual footer in the published FXT files is 01 5C 5E 1B 01 5C 5E which represents "\n[]\x1A\n[]". (The meaning of the 1A character is unknown; it is probably only an artefact from the original FXT development tools).

Encrypt process (TXT to FXT)

The encrypt process is similar to the decrypt process, just vice-versa.

For the extended charset, you can decide if you want to encode it with 0x84 (GTA London style) or 0xC4 (GTA1 style), since both London and GTA1 can read each other's encodings.
The GTA London style 0x84 is recommended, because you have more usable space in the extended characters.