Repository navigation
GFF File Format
The Generic File Format (GFF) is the all-purpose binary container used to store structured game data in Knights of the Old Republic and The Sith Lords. Nearly every non-script, non-texture resource the engine reads at runtime is a GFF file: area definitions, creature templates, item blueprints, dialogue trees, journal entries, placeables, triggers, waypoints, and user interface layouts. The format was designed for rapid iteration — new fields can be added to any resource type without breaking backward compatibility, because readers simply skip labels they do not recognize.
GFF is shared across BioWare's Aurora engine family. The official BioWare GFF specification describes the original container design; KotOR and TSL build on that same structure with game-specific field schemas, resource subtypes, and modding workflows. For the common GFF struct schemas shared across area and module files, see Bioware Aurora Common GFF Structs.
Like all game resources, GFF files are resolved through the standard resource resolution order: the engine checks the override folder first, then the active MOD/ERF module capsule, then KEY/BIF base data. Modders can therefore shadow any vanilla GFF by placing a replacement in override or inside a module .mod file (see Mod Creation Best Practices). For merge-safe field-level edits, use TSLPatcher/HoloPatcher GFFList syntax instead of full-file replacement.
GFF files work alongside 2DA configuration tables, TLK localized strings, MDL/MDX 3D models, and NCS compiled scripts. Historical editors include K-GFF (LucasForums thread, Deadly Stream listing) and KotOR Tool; for current editing, use Holocron Toolset.
- GFF — Generic File Format
A GFF file is a hierarchical tree of structs, fields, and lists. Each struct contains named fields; each field holds either a simple value (integer, float, string) or a reference to a nested struct or list of structs. This recursive design means the same binary container can represent a creature with an inventory of items, a dialogue tree with branching replies, or an area definition with dozens of placed objects — all without changing the file format itself.
The format provides several properties that made it practical for rapid game development:
- Type safety: every field carries an explicit data type, so readers can validate structure without external schemas.
- Compact binary encoding: significantly smaller than equivalent XML or JSON, which mattered for CD-based distribution.
- Direct memory mapping: the offset-based layout allows fast load without full parsing.
- Backward and forward compatibility: readers skip unknown labels, so adding a new field to a creature template does not break older tools or saves.
The engine uses the four-character file type signature (e.g. UTC , DLG , ARE ) plus the version tag V3.2 to identify GFF content. The same binary layout serves all of these resource types:
Common Uses:
-
Character/Creature templates:
-
Area definitions:
-
Dialogue trees (DLG)
-
Quest journals (JRL)
-
Module information (IFO)
-
Save game state (SAV files contain GFF resources)
-
User interface layouts (GUI)
Many KotOR file types are GFF containers with different signatures and field schemas, for example:
Dozens of other extensions are documented across this wiki.
Implementation (PyKotor):
- package:
resource/formats/gff/ - binary read
GFFBinaryReader.loadL82+ - write
GFFBinaryWriter.writeL355+ - data model
GFFL509+ GFFStructL689+- XML/JSON/Twine variants in
io_gff_xml,io_gff_json,io_gff_twine
Cross-reference (other implementations):
| Project | Path | Role |
|---|---|---|
| reone | gffreader.cpp |
C++ reader |
| reone | gffwriter.cpp |
C++ writer |
| reone | gff.cpp |
core GFF types |
| xoreos | gff3file.cpp |
Aurora GFF3 |
| KotOR.js | GFFObject.ts L24+ |
TypeScript parser |
| Kotor.NET | GFF.cs L18+ |
.NET reader/writer |
| KotOR-Unity | GFFObject.cs |
C# Unity loader |
| xoreos-tools | gff3file.cpp |
CLI tools |
| bioware-kaitai-formats | GFF Kaitai specs | Format specs |
- TSLPatcher GFFList Syntax - Modding GFF files with TSLPatcher
- 2DA File Format - Configuration data referenced by GFF files
- TLK File Format - Text strings used by GFF LocalizedString fields
- Bioware Aurora GFF Format - Official BioWare specification
The file header is 56 bytes in size:
| Name | type | offset | size | Description |
|---|---|---|---|---|
| file type | char | 0 (0x00) | 4 | Content type (e.g., "GFF ", "ARE ", "UTC ") |
| file Version | char | 4 (0x04) | 4 | format version ("V3.2" for KotOR) |
| Struct array offset | UInt32 | 8 (0x08) | 4 | offset to struct array |
| Struct count | UInt32 | 12 (0x0C) | 4 | Number of structs |
| field array offset | UInt32 | 16 (0x10) | 4 | offset to field array |
| field count | UInt32 | 20 (0x14) | 4 | Number of fields |
| Label array offset | UInt32 | 24 (0x18) | 4 | offset to label array |
| Label count | UInt32 | 28 (0x1C) | 4 | Number of labels |
| field data offset | UInt32 | 32 (0x20) | 4 | offset to field data section |
| field data count | UInt32 | 36 (0x24) | 4 | size of field data section in bytes |
| field indices offset | UInt32 | 40 (0x28) | 4 | offset to field indices array |
| field indices count | UInt32 | 44 (0x2C) | 4 | Number of field indices |
| List indices offset | UInt32 | 48 (0x30) | 4 | offset to list indices array |
| List indices count | UInt32 | 52 (0x34) | 4 | Number of list indices |
References:
Labels are 16-byte null-terminated strings used as field names:
| Name | type | size | Description |
|---|---|---|---|
| Labels | char | 16×N | array of field name labels (null-padded to 16 bytes) |
References:
Each struct entry is 12 bytes:
| Name | type | offset | size | Description |
|---|---|---|---|---|
| Struct ID | int32 | 0 (0x00) | 4 | structure type identifier |
| data/offset | UInt32 | 4 (0x04) | 4 | field index (if 1 field) or offset to field indices (if multiple) |
| field count | UInt32 | 8 (0x08) | 4 | Number of fields in this struct (0, 1, or >1) |
References:
Each field entry is 12 bytes:
| Name | type | offset | size | Description |
|---|---|---|---|---|
| field type | UInt32 | 0 (0x00) | 4 | data type (see GFF Data Types) |
| Label index | UInt32 | 4 (0x04) | 4 | index into label array for field name |
| data/offset | UInt32 | 8 (0x08) | 4 | Inline data (simple types) or offset to field data (complex types) |
References:
Complex field types store their data in the field data section:
| field type | Storage format |
|---|---|
| UInt64 | 8 bytes (uint64) |
| Int64 | 8 bytes (int64) |
| double | 8 bytes (double) |
| string | 4 bytes length + N bytes string data |
| ResRef | 1 byte length + N bytes ResRef data (max 16 chars) |
| LocalizedString | 4 bytes count + N×8 bytes (Language ID + StrRef pairs) |
| Binary | 4 bytes length + N bytes binary data |
| Vector3 | 12 bytes (3×float) |
| Vector4 | 16 bytes (4×float) |
References:
When a struct has multiple fields, the struct's data field contains an offset into the field indices array (also called the "Multiple Element Map" or "MultiMap" in xoreos-docs specs/torlack/itp.html), which lists the field indices for that struct.
Access Pattern: When a struct has exactly one field, the struct's data field directly contains the field index. When a struct has more than one field, the data field contains a byte offset into the field indices array, which is an array of uint32 values listing the field indices.
References:
- xoreos-docs
-
specs/torlack/itp.html— MultiMap, entry/entity access
Lists are stored as arrays of struct indices. The list field contains an offset into the list indices array, which contains the struct indices that make up the list.
Access Pattern: For a LIST type field, the field's data/offset value specifies a byte offset into the list indices table. At that offset, the first uint32 is the count of entries, followed by that many uint32 values representing the struct indices.
References:
- xoreos-docs
-
specs/torlack/itp.html— LIST access
GFF supports the following field types:
| type ID | Name | Size (inline) | Description |
|---|---|---|---|
| 0 | byte | 1 | 8-bit unsigned integer |
| 1 | char | 1 | 8-bit signed integer |
| 2 | Word | 2 | 16-bit unsigned integer |
| 3 | Short | 2 | 16-bit signed integer |
| 4 | DWord | 4 | 32-bit unsigned integer |
| 5 | Int | 4 | 32-bit signed integer |
| 6 | DWord64 | 8 | 64-bit unsigned integer (stored in field data) |
| 7 | Int64 | 8 | 64-bit signed integer (stored in field data) |
| 8 | float | 4 | 32-bit floating point |
| 9 | double | 8 | 64-bit floating point (stored in field data) |
| 10 | CExoString | varies | null-terminated string (stored in field data) |
| 11 | ResRef | varies | Resource reference (stored in field data, max 16 chars) |
| 12 | CExoLocString | varies | Localized string (stored in field data) |
| 13 | Void | varies | Binary data blob (stored in field data) |
| 14 | Struct | 4 | Nested struct (struct index stored inline) |
| 15 | List | 4 | List of structs (offset to list indices stored inline) |
| 16 | orientation | 16 | Quaternion (4×float, stored in field data as Vector4) |
| 17 | vector | 12 | 3D vector (3×float, stored in field data) |
| 18 | StrRef | 4 | string reference (TLK StrRef, stored inline as int32) |
References
PyKotor:
-
Libraries/PyKotor/src/pykotor/resource/formats/gff/gff_data.py:73-108- GFF data type definitions
type Selection Guidelines:
-
Use byte/char for small integers (-128 to 255) and boolean flags
-
Use Word/Short for medium integers like IDs and counts
-
Use DWord/Int for large values and most numeric fields
-
Use float for decimals that don't need high precision (positions, angles)
-
Use double for high-precision calculations (rare in KotOR)
-
Use CExoString for text that doesn't need localization
-
Use CExoLocString for player-visible text that should be translated
-
Use ResRef for filenames without extensions. Typical payloads include:
-
Use Void for binary blobs like encrypted data or custom structures
-
Use Struct for nested objects with multiple fields
-
Use List for arrays of structs (inventory items, dialogue replies)
-
Use vector for 3D positions and directions
-
Use orientation for quaternion rotations
-
Use StrRef for references to dialog.tlk entries
Storage Optimization:
Inline types (0-5, 8, 14, 15, 18) store their value directly in the field entry, saving space and improving access speed. Complex types (6-7, 9-13, 16-17) require an offset to field data, adding overhead. When designing custom GFF schemas, prefer inline types where possible.
A GFF struct is a collection of named fields. Each struct has:
- Struct ID: type identifier (often 0xFFFFFFFF for generic structs)
- fields: Dictionary mapping field names (labels) to field values
References
PyKotor:
-
Libraries/PyKotor/src/pykotor/resource/formats/gff/gff_data.py- GFFStruct, GFFField, GFFList implementation
fields can be accessed using type-specific getter/setter methods:
-
get_uint8(label),set_uint8(label, value) -
get_int32(label),set_int32(label, value) -
get_float(label),set_float(label, value) -
get_string(label),set_string(label, value) -
get_resref(label),set_resref(label, value) -
get_locstring(label),set_locstring(label, value) -
get_vector3(label),set_vector3(label, value) -
get_struct(label),set_struct(label, struct) -
get_list(label),set_list(label, list)
A GFF list is an ordered collection of structs. Lists are accessed via:
-
get_list(label): Returns aGFFListobject -
GFFList.get(i): Gets struct at indexi -
GFFList.append(struct): Adds a struct to the list
Common List Usage:
Lists are used extensively for variable-length arrays:
- ItemList in UTC files: Character inventory items
- Equip_ItemList in UTC files: Equipped items
- EntryList in DLG files: Dialogue entry nodes
- ReplyList in DLG files: Dialogue reply options
- SkillList in UTC files: Character skills
- FeatList in UTC files: Character feats
- EffectList in various files: Applied effects
- Creature_List in GIT files: Spawned creatures in area
When modifying lists, always maintain struct IDs and parent references to avoid breaking internal links.
GFF files are used as containers for various game resource types. Each generic type has its own structure and field definitions.
See ARE (Area) for detailed documentation.
See DLG (Dialogue) for detailed documentation.
See FAC (Faction) for detailed documentation.
See GIT (Game Instance Template) for detailed documentation.
See GUI (Graphical User Interface) for detailed documentation.
See IFO (Module Info) for detailed documentation.
See JRL (Journal) for detailed documentation.
See PTH (Path) for detailed documentation.
See UTC (Creature) for detailed documentation.
See UTD (Door) for detailed documentation.
See UTE (Encounter) for detailed documentation.
See UTI (Item) for detailed documentation.
See UTM (Merchant) for detailed documentation.
See UTP (Placeable) for detailed documentation.
See UTS (Sound) for detailed documentation.
See UTT (Trigger) for detailed documentation.
See UTW (Waypoint) for detailed documentation.
Simple types (uint8, int8, uint16, int16, uint32, int32, float) store their values directly in the field entry's data/offset field (offset 0x0008 in the element structure). These values are stored in little-endian format.
Complex types require accessing data from the field data section:
- UInt64, Int64, double: The field's data/offset contains a byte offset into the field data section where the 8-byte value is stored.
-
String (
CExoString): The offset points to a uint32 length followed by the string bytes (not null-terminated). - ResRef: The offset points to a uint8 length (max 16) followed by the resource name bytes (not null-terminated).
-
LocalizedString (
CExoLocString): The offset points to a structure containing:-
uint32: Total size (not including this count) -
int32: StrRef ID (dialog.tlk reference, -1 if none) -
uint32: Number of language-specific strings - For each language string (if count > 0):
-
uint32: Language ID (Concepts) -
uint32: string length in bytes -
char[]: string data
-
-
-
Void (Binary): The offset points to a
uint32length followed by the binary data bytes. -
Vector3: The offset points to 12 bytes (3×
float) in the field data section. -
Vector4 / orientation: The offset points to 16 bytes (4×
float) in the field data section.
- Struct (CAPREF): The field's data/offset contains a struct index (not an offset). This references a struct in the struct array.
-
List: The field's data/offset contains a byte offset into the list indices array. At that offset, the first uint32 is the entry count, followed by that many uint32 struct indices. Access patterns and code examples are documented in Torlack's Aurora basics, archived at xoreos-docs —
specs/torlack/itp.html.
| Component | PyKotor Reference |
|---|---|
| Binary read | GFFBinaryReader.load (io_gff.py) |
| Binary write | GFFBinaryWriter.write (io_gff.py) |
| GFF data model | GFF (gff_data.py) |
| GFFStruct | GFFStruct (gff_data.py) |
- GFF-ARE
- GFF-DLG
- GFF-IFO
- GFF-UTI
- GFF-UTC
- GIT -- GFF-based game resources
- TSLPatcher GFFList Syntax -- Patching GFF via HoloPatcher/TSLPatcher
- Resource formats and resolution -- Hex resource type IDs (ResRef + type in archives)
- KEY-File-Format -- Resource resolution
- Bioware-Aurora-GFF -- Aurora GFF specification
- Community sources and archives -- DeadlyStream, forums for GFF structure and modding