🛡️ TA Archive

TNT Map Format — Programmer's Field Guide

TA FILE FORMAT · TNT · LITTLE-ENDIAN

The terrain file, drawn to scale

A TNT is not one bitmap. It is a compact terrain database: a tile-index grid, a 16-pixel attribute grid, an embedded tile atlas, optional feature records, and a 252×252 minimap — all connected by absolute file pointers.

Scope. This page documents the classic TA TNT layout used by the original game and validated against TAUtil, Mappy, the historical TNT format notes, and a corpus of real maps. Unknown/reserved fields are labelled honestly rather than guessed.

1. File anatomy

absolute byte offsets →0x000x40ptrGfxptrEndGfxptrMiniMapHEADER64 bytes16 × uint32 LETILE MAP(W/2 × H/2) × uint16padded to 8 entriesATTRIBUTESW × H × 4 bytesheight + feature + padTILE GRAPHICSN × 1024 bytesN × 32×32 palette IDsFEATURESoptional0×…×132MINIMAP8 + 63,504252×252Every pointer in the header is an absolute file offset.The feature-name table may occupy the gap before the minimap.Do not assume ptrTileAnims == ptrMiniMap when features exist.

2. Header — 0x40 bytes

OffsetSizeFieldMeaning
0x00uint32idVersionAlways 0x2000 in valid classic TNT files.
0x04uint32widthAttribute cells across the map. Graphic tile width is width / 2.
0x08uint32heightAttribute cells down the map. Graphic tile height is height / 2.
0x0Cuint32ptrMapDataAbsolute offset to the uint16 tile-index array.
0x10uint32ptrMapAttrAbsolute offset to 4-byte attributes; one per 16×16 attribute cell.
0x14uint32ptrTileGfxAbsolute offset to the embedded 32×32 tile atlas.
0x18uint32tilesNumber of unique tile bitmaps.
0x1Cuint32tileAnimsNumber of feature/animation records.
0x20uint32ptrTileAnimsFeature-record/string-table location; historically named “pointer to animations”.
0x24uint32seaLevelAny attribute height below this is underwater.
0x28uint32ptrMiniMapAbsolute offset to minimap dimensions and pixels.
0x2Cuint32unknown1Write 1. Real maps and TAUtil identify this as required for the minimap/game path.
0x30–0x3F4×uint32reservedUsually zero; do not invent semantics.
Dimension rule. Header width/height are the 16×16 attribute grid. A 16×16 map in OTA terms therefore has a TNT attribute grid of 512×512, not 16×16 and not 256×256.

3. Two grids, one map

GRAPHICS32×32 pixel tile gridOne uint16 tile index per graphic tile position. A map with header dimensions W×H has (W/2)×(H/2) tile positions.
GEOMETRY16×16 attribute gridOne attribute record per height/feature cell. Each graphic tile covers four attribute cells.
SERIALIZATIONBoth arrays are row-majorEnumerate the tile map top-to-bottom, left-to-right; do the same for attributes. The 2×2 relationship is spatial, not a tile-major file-order rule.
one 32×32 graphic tiletilemap[ty, tx]uint16 tile indexfour 16×16 attribute cells(2tx,2ty)(2tx+1,2ty)(2tx,2ty+1)(2tx+1,2ty+1)same spatial origindifferent rasterdifferent purpose

4. Attribute cell — exactly 4 bytes

BYTE 0Heightuint8. TA terrain elevation at this 16×16 location. Values are game heights, not automatically “meters”.
BYTES 1–2Feature indexuint16 little-endian. 0xFFFF = none; 0xFFFC = void; 0xFFFE occurs in some early Cavedog maps with unknown meaning.
BYTE 3Padding / unknown Usually zero. TAUtil calls it padding and documents no known purpose.
// Read one attribute, little-endian
height   = read_u8();
feature  = read_u16_le();
padding  = read_u8();

// Attribute at (x, y), row-major
file_offset = ptrMapAttr + ((y * width) + x) * 4;

5. Tile map and tile graphics

tileWidth  = width  / 2;
tileHeight = height / 2;
tileCountInMap = tileWidth * tileHeight;

// The file may pad this array to a multiple of 8 uint16 entries.
tileIndex = read_u16_le(ptrMapData + ((ty * tileWidth) + tx) * 2);

tilePixels = file[ptrTileGfx + tileIndex * 1024 : +1024];
// 1024 bytes = 32 × 32 palette indices, row-major.
Palette reminder. Tile and minimap bytes are palette indices, not RGB values. Decode them through TA's PALETTE.PAL; displaying the byte as grayscale can be misleading.

6. Feature records and minimap

FEATURE RECORDUsually 0x84 bytes A common layout is a 4-byte index/value followed by a 128-byte, null-terminated feature name. The exact feature table conventions vary between tools; trust the count and pointers in the specific file.
MINIMAP252×252 palette IDs At ptrMiniMap: uint32 width, uint32 height, then width×height bytes. Classic maps normally use 252×252.

Known feature strings

The feature index in attribute bytes 1–2 points into this table. These are the strings currently confirmed in our local TNT corpus; this is a verified list, not a claim that the original TA feature vocabulary ends here.

CONFIRMEDRockMetalMetal extractor / metal deposit used by the image-map importer.
CONFIRMEDGeothermalGeothermal vent used by the image-map importer.
CONFIRMEDTree1Tree feature used by the image-map importer.
CONFIRMEDRockRock feature used by the image-map importer.
ORIGINAL MAPMetalVent05Observed in an original-style local TNT map; feature naming is map/feature-set dependent.
Do not hard-code feature indices. Index 0 means the first record in that TNT's own feature table, not a universal TA feature ID. Read the table, resolve the string, then interpret the corresponding game feature definition.

The Kingdom Of TA II — complete feature table

This original map contains 579 feature records. The list below is copied from the TNT feature table in index order; spelling and case are preserved. The map header is 1120 × 960 attribute cells, 49266 tiles, sea level 95.

Show all 579 feature strings
000 MetalZone_MAX
001 GreenVent01
002 GreenVent03
003 DryVent04
004 DryVent02
005 EGVent4
006 EGVent2
007 EGVent1
008 EGVent3
009 WetVent06
010 AquaOre3
011 WaterMetal03
012 AquaOre2
013 EverGnMetal1
014 EverGnMetal2
015 RockMetal1
016 RockMetal
017 RockMetal2
018 DryMetal01
019 DryMetal03
020 DryMetal02
021 RockMetal3
022 EverGnMetal3
023 EverGnMetal4
024 ArchMetal1
025 ArchMetal3
026 ArchMetal2
027 WetMetal01
028 MAMetal1
029 MMedium01
030 WetMetal03
031 WetMetal02
032 EverGnMetal6
033 EverGnMetal5
034 LushVent01
035 LushVent03
036 GreenVent08
037 WetVent02
038 WetVent03
039 GreenVent06
040 GreenVent04
041 WetVent05
042 WetVent01
043 WetVent04
044 SlateMetal4
045 DryRuin01
046 DryRuin03
047 DryRuin05
048 DryRuin06
049 DryRuin02
050 DryRuin07
051 AraHut01
052 AraHut03
053 AraHut07
054 AraHut08
055 AraHut09
056 AraHut05
057 AraHut11
058 AraHut10
059 AraHut12
060 Alien2
061 Arrow2left
062 Biohazard1
063 Circlearrows
064 Construction1
065 Pod1
066 Satellite
067 Csymbol
068 Airpad2
069 Road2
070 Road1arrow2
071 Bluefingers_SM
072 ButterWasp_SM
073 NeckTrap_SM
074 MorningHorn_SM
075 AraTree01
076 AraTree02
077 AraTree03
078 AraTree04
079 AraTree04a
080 AraTree06
081 AraTree05
082 AraTree03a
083 AraTree01a
084 DryRock10
085 DryRock11
086 DryRock09
087 DryCrush34
088 DryCrush44
089 DryRock14
090 DryRock04
091 DryRock03
092 DryRock01
093 DryRock12
094 DryRock15
095 DryCrush43
096 DryRock05
097 DryRock02
098 DryRock08
099 DryRock07
100 DryRock06
101 AraTree02a
102 ZonWall07
103 HollyCock_SM
104 SeaLeaf_SM
105 Aracrop01
106 Aracrop04
107 Aracrop02
108 Lush09
109 Lush08
110 tubertreesmudge2
111 Lush07crisp
112 lushfoliage06
113 Lush07
114 Rock4
115 ArchiTree01
116 ArchiTree04
117 DryCrush33
118 ArchiVent02
119 AcidAquaOre1
120 AcidAquaOre2
121 AcidAquaOre3
122 WaterMetal02
123 WaterMetal01
124 AquaOre1
125 AraTree07
126 AraTree09
127 AraTree07a
128 PGVent01
129 GreenVent09
130 GreenVent02
131 GreenVent05
132 eiffel
133 VerWall08
134 VerWall03
135 VerTow01
136 VerWall01
137 VerJoint12
138 VerJoint09
139 VerJoint10
140 VerJoint08
141 VerWall04
142 VerJoint06
143 VerJoint11
144 VerWall05
145 VerWall02
146 VerJoint05
147 VerJoint07
148 VerWall09
149 VerWall12
150 VerTow04
151 VerBuild05
152 VerTow02
153 VerTow03
154 VerJoint03
155 VerJoint01
156 VerWall06
157 VerJoint04
158 VerJoint02
159 VerBuild04
160 VerBuild06
161 VerBuild08
162 VerBuild03
163 VerBuild02
164 VerBuild01
165 VerBuild07
166 VerHut02
167 VerHut07
168 VerHut06
169 VerHut01
170 VerHut03
171 VerHut04
172 VerHut05
173 VerHut09
174 VerHut08
175 VerHut10
176 ZonTree09a
177 ZonTree07a
178 ZonTree08a
179 ZonTreeDead07a
180 ZonTree06
181 FTree2
182 TTree3
183 Lush05
184 ZonTreeDead08a
185 ZonTreeDead09a
186 VerFountain01
187 TarDev04
188 TarDev05
189 VerAlt01
190 YellowHuskies_SM
191 SilkyWeb_SM
192 Mystique_SM
193 Heartless_SM
194 VelvetLuster_SM
195 VerPlant04
196 ZonPlant06
197 blossom1
198 blossom2
199 MarsPlant02Crisp
200 MarsPlant02
201 MarsPlant07
202 MarsPlant05
203 MarsPlant01Crisp
204 VerPlant02
205 VerPlant01
206 VerPlant03
207 VerPlant06
208 VerPlant05
209 VerPlantScar01
210 LavaCrush02
211 LavaRockA008
212 LavaRockA006
213 LavaRockA012
214 LavaRockB017
215 LavaRockC003
216 LavaRockC008
217 LavaRockC012
218 LavaRockC012Scar
219 LavaCrush03
220 brock4
221 Brock2
222 Rock6
223 Rock5
224 Rock2
225 Rock3
226 Rock
227 Rock1a
228 Rock3a
229 Rock4a
230 Rock3b
231 Rock2b
232 Rock05
233 Rock07
234 Rock1b
235 Rockgone02
236 Rock11
237 Rock11a
238 Rock12
239 Rock07b
240 Rock08
241 Rock06b
242 Rock09
243 Rock06a
244 Rock10
245 Rock05a
246 MoonRock11
247 MoonRock13
248 MoonRock10
249 MoonRock12
250 MoonRock15
251 MoonRock17
252 MoonRock18
253 MoonCrush18
254 MoonCrushB
255 MoonRock14
256 MoonRock09
257 MoonRock08
258 MoonRock07
259 MoonRock06
260 MoonRock03
261 MoonRock02
262 MoonRock04
263 MoonRock09Scar
264 MoonCrush10
265 ArchiTree02
266 ArchiTree05
267 Palm02
268 Palm04
269 HangingPearls_SM
270 ZonTree01
271 ZonTree03
272 ZonTree04
273 ZonTreeDead04
274 ZonTreeDead06
275 ZonTreeDead05
276 ZonTree05
277 ZonPlant04
278 ZonPlant02
279 ZonPlant03
280 ZonPlant01
281 ZonPlant05
282 ZonPlant07
283 ZonPlant08
284 ZonPlant09
285 ZonPlant10
286 ZonPlant11
287 ZonPlant14
288 ZonPlant15
289 ZonPlant13
290 ZonPlant17
291 ZonPlant18
292 ZonPlant19
293 ZonPlant12
294 PowerBells_SM
295 GroundHuggers_SM
296 FirePlant_SM
297 StarLights_SM
298 AraWall05
299 AraWall04
300 AraWall02
301 AraWall01
302 AraWall06
303 AraWall03
304 ZonTree02
305 ZonTreeSmudge03
306 ZonTreeSmudge02
307 ZonTreeSmudge01
308 ZonTreeSmudge04
309 ZonHut01
310 ZonHut02
311 ZonHut03
312 ZonHut04
313 ZonHut05
314 VerTree04
315 VerTree06
316 VerTree05
317 VerTree07
318 VerTree08
319 VerTree09
320 MarsPlant01
321 lushfoliage05
322 lushfoliage2-01
323 ArchiFoliage01
324 ArchiFoliage03
325 ArchiFoliage04x
326 Frond02
327 ZonHut06
328 ZonRuin01
329 ZonRuin02
330 ZonRuin03
331 ZonHut07
332 ArchiTree06
333 LushRock07
334 LushRock08
335 LushRock05
336 LushRock04
337 LushRock02
338 LushCrushed06
339 LushRock06
340 LavaRockB012
341 LavaRockB011
342 TarDev06
343 TarDev08
344 ZonRuin15
345 ZonRuin16
346 TarDev07
347 ZonHut08
348 ZonHut09
349 ZonHut11
350 ZonHut10
351 Lush04
352 Lush06
353 Lush04crisp
354 Lush05crisp
355 Lush06crisp
356 ZonTmound01
357 ZonTmound03
358 ZonTmound05
359 ZonTmound06
360 ZonTmound04
361 SatinsMist_SM
362 Aracrop03
363 Aracrop05
364 DVCactus01
365 DVCactus02
366 DVCactus03
367 DVBloom01
368 DVBloom02
369 AraTree10
370 AraTree08
371 AraTree08a
372 DawnSunburst_SM
373 Tree1
374 Tree4
375 Tree5
376 Tree6
377 Tree4Dead
378 Tree5Dead
379 Tree3
380 Tree2
381 Tree1Dead
382 Tree2Dead
383 Tree3Dead
384 IWantYou_SM
385 lushfoliage02
386 lushfoliage2-03
387 lushvine01
388 lushfoliage2-02
389 Lush08crisp
390 lushfoliage01
391 lushfoliage07
392 lushfoliage2-05
393 lushvine02
394 lushvine03
395 FTree1
396 TTree1
397 FTree3
398 TTree2
399 Rock2a
400 Rock06
401 Frond01
402 MoonRock19
403 MoonRock16
404 EGHead1b
405 EGHead3b
406 EGHead7
407 Totem Pole 1
408 MoonRock05
409 ZonWall08
410 AraTow01
411 AraTow02
412 AraTow03
413 AraTow04
414 Pipe03Hole
415 Pipe03
416 Light02
417 Barrier04
418 Barrier10
419 DryRock13
420 Palm05
421 Palm06
422 Lushpsmudge01
423 Lushpsmudge02
424 DryCrush43Scar
425 DryCrush44Scar
426 Rockgone01
427 MoonRock01
428 Lushpsmudge04
429 Lushpsmudge03
430 ZonWall06
431 Barrier01
432 Barrier12
433 Barrier16
434 Barrier19
435 Barrier20
436 widget17
437 widget15
438 widget18
439 widget16
440 widgetscar02
441 widgetscar01
442 widget14
443 widgetscar04
444 widgetscar03
445 widgetscar06
446 Truck07
447 Truck04
448 Truck03
449 Pastascar01
450 lushfoliage2-04
451 MetalZone_+1.5
452 MetalTower14
453 MetalTower13
454 MetalTower02
455 MetalTower01
456 MetalTower12
457 MetalTower11
458 MetalTower03
459 LavaCrushA003
460 LavaCrushA013
461 LavaCrushA004Scar
462 LavaRockA005
463 Tree6Dead
464 ArchiTree02crisp
465 LushTree01
466 Lush03
467 Lush02crisp
468 Lush02
469 Aracrop06
470 DryRock01Scar
471 lushfoliage04
472 lushfoliage03
473 Lush09crisp
474 Building06
475 Building08
476 Building15
477 dvspire1
478 dvspire3
479 dvspire2
480 dvspire4
481 dvspire7
482 Lunar Spire 1
483 Lunar Spire 2
484 Lunar Spire 5
485 Lunar Spire 4
486 Lunar Spire 7
487 Lunar Spire 8
488 Lunar Spire 10
489 Lunar Spire 11
490 Lunar Spire 12
491 Lunar Spire 13
492 Lunar Spire 6
493 Lunar Spire 3
494 LavaRockA015Scar
495 LavaRockA008Scar
496 LavaRockA016Scar
497 LavaRockA003
498 LavaCrush01
499 LavaRockC015
500 LavaRockA004
501 LavaRockA004Scar
502 LavaRockB012Scar
503 LavaRockA015
504 LavaRockA016
505 LavaCrushB012
506 LavaRockA013
507 LavaRockC005
508 LavaCrushC003Scar
509 LavaCrush03Scar
510 LushCrushed04
511 LushRock01
512 LushCrushed08
513 LushCrushed208
514 LushCrushed206
515 LushRock03
516 LavaRockC008Scar
517 LushCrushed03
518 LushCrushed05
519 LushCrushed207
520 TarTree07
521 TarTree09
522 TarTree08
523 TarTreeSmudge02
524 TarTreeSmudge01
525 TarTree06
526 TarTree05
527 TarTree04
528 TarTree03
529 TarTreeSmudge03
530 Building01
531 Building09
532 Building11
533 Building14c
534 Building15c
535 Building06c
536 Building07
537 Building05b
538 Building05
539 Building04b
540 Building02c
541 Building01c
542 Building13c
543 Building14b
544 EGSPatch1
545 EGShroom3
546 EGshroom2
547 EGShroom1
548 Coral01
549 AquaCoral03
550 anemone-03
551 anemone-04
552 anemone-05
553 anemone-06
554 anemone-07
555 anemone-08
556 anemone-10
557 anemone-16
558 anemone-12
559 anemone-11
560 aquacoral-01
561 aquacoral-02
562 aquacoral=04
563 aquacoral-05
564 anemone-14
565 aquacoral-03
566 aquacoral-07
567 anemone-15
568 aquacoral-06
569 anemone-09
570 anemone-13
571 Seagrass01
572 Seagrass02
573 Seagrass03
574 VerTreeDead06
575 ZonTreeSmudge05a
576 VerLampBurning01
577 VerLampBurning02
578 vent02
mmWidth  = read_u32_le(ptrMiniMap + 0);
mmHeight = read_u32_le(ptrMiniMap + 4);
for (y = 0; y < mmHeight; y++)
  for (x = 0; x < mmWidth; x++)
    pixel = file[ptrMiniMap + 8 + y * mmWidth + x];

7. Resolving a feature: TNT → TDF → GAF

The TNT does not contain the complete feature asset. It contains the placement reference: an attribute-cell index points into the TNT's own feature-name table. The name then resolves into a feature definition and, normally, a GAF animation or image set supplied by the game, a tileset, a map archive, or a mod.

TNTfeature index → nameTDFdefinition + asset refsGAF / bitmapframes + pixelsThe index is map-local; filenames and definitions are library/mod-dependent.

TDF — text definition files

  • TDF is TA's bracketed, semicolon-terminated text format: named sections contain key/value entries and nested sections.
  • Feature definitions commonly provide the feature section name, world/asset name, footprint, blocking/collision flags, reclaim/resource properties, damage or animation references, and rendering metadata.
  • The section name is the important bridge: a TNT string such as Tree1 must match the feature definition/asset naming used by the installed data set.
  • TDF is not a universal global registry. A map may depend on stock TA data, a custom feature pack, or files bundled in its UFO/HPI.

Concrete TDF example: Bluefingers_SM

The following is a shortened, documented excerpt from features\\Flowers\\AtlFlowers2.tdf, bundled with The Kingdom Of TA II. The section name is the feature key; the values describe gameplay behaviour and name the GAF sequences used for rendering and state changes.

[Bluefingers_SM]
{
    world=Atlantis;
    description=BlueFingers;
    category=Atlantis;
    animating=0;
    footprintx=1;
    footprintz=1;
    height=4;

    filename=Atlflowers2;
    seqname=BlueFingers_SM;
    seqnameshad=BlueFingersShad_SM;
    seqnamereclamate=FlowerSMrec_01;

    energy=20;
    seqnameburn=FlowerBurn_01;
    featureburnt=Smudge01;
    burnmin=5;
    burnmax=15;
    sparktime=5;
    spreadchance=70;

    seqnamedie=Smudge01;
    featuredead=Smudge01;
    Damage=1;
    animtrans=0;
    shadtrans=1;
    flamable=1;
    reclaimable=1;
    featurereclamate=Smudge01;
    reproduce=1;
    reproducearea=6;
    hitdensity=5;
    blocking=0;
}
IDENTITY[Bluefingers_SM]The section key is the name resolved from the map's feature table.
GEOMETRYfootprintx/z, heightPlacement footprint and approximate visual/physical height.
ASSETSfilename + seqname*The GAF basename and named entries for normal, shadow, reclaim, burn and death states.
GAMEPLAYblocking, reclaimable, Damage, …Runtime behaviour; exact supported keys depend on the TA/mod data set.

GAF — indexed animation files

  • GAF begins with a header containing an entry count and an array of absolute pointers to entries.
  • Each entry has a frame count, two unknown/reserved fields, and a 32-byte name.
  • Each frame table stores width, height, X/Y offsets, a transparency palette index, a compression flag, optional nested-frame pointers, and a pointer to frame data.
  • Frame data is either an uncompressed palette-index image or a compressed image decoded with the GAF frame codec. A GAF entry can therefore represent a static image, an animation, or nested/compound frames.
  • Pixels are palette indices; resolve them through PALETTE.PAL. Transparency is indicated by the frame's transparency index.
// conceptual resolver
cell = tnt.attributes[y * width + x];
if (cell.feature != 0xFFFF && cell.feature != 0xFFFC) {
    name = tnt.featureNames[cell.feature];
    definition = tdf.lookup(name);       // installed data / feature pack
    animation = gaf.lookup(definition.assetName);
    image = gaf.decode(animation, palette);
}
Packaging matters. The Kingdom Of TA II bundles its terrain plus feature resources in one UFO: its TNT contains 579 names, while the same archive also contains features\\Flowers\\AtlFlowers2.tdf and Anims\\AtlFlowers2.gaf. A TNT alone can identify a placed feature, but cannot guarantee that the referenced visual/definition assets are installed.

8. Minimal parser checklist

  1. Read the 16 little-endian uint32 header fields.
  2. Validate idVersion == 0x2000, even dimensions, and every pointer within the file.
  3. Read (width/2)×(height/2) uint16 tile indices; account for padding to an 8-entry boundary when calculating the next block.
  4. Read width×height four-byte attributes row-major.
  5. Read tiles×1024 tile pixels and decode them through the TA palette.
  6. Use the feature count and pointer to locate the feature table/string area; do not blindly assume it is empty.
  7. Read the minimap dimensions and palette-index pixels from ptrMiniMap.
  8. Pair the TNT with its OTA. TNT contains terrain; OTA contains mission metadata, schema and start positions.

References and tools

Primary format references: TAUtil source, especially TntHeader, TileAttr, TntReader and TntWriter; Mappy source, especially MapModelTntAdapter; and the historical TA TNT format notes.

Site implementation: Reverse Engineering TA Files, Procedural Map Generation, and the independent _render_tnt.py decoder in the TA Archive working tree.