Todas las páginas de formatos ↓
Gráficos y multimedia

TAF / TSF: animaciones truecolor de TA: Kingdoms

Fuente: coreprime/kbot @ 0ab97bf · Editar en GitHub

TAF guarda las animaciones de sprites truecolor de Total Annihilation: Kingdoms: efectos de hechizos, explosiones, bolas de fuego, anillos mágicos, sprites de agua y los fondos animados de los menús. Reutiliza la disposición del contenedor GAF de Total Annihilation, pero cambia los píxeles de 8 bits indexados en la paleta por ARGB de 16 bits, así que un TAF lleva su propio color y un canal alfa de verdad: no necesita ninguna paleta externa. TSF es la forma de texto legible de la misma animación: un script delimitado por llaves que el cargador de la interfaz lee directamente.

Secuencia FireballA de fireballa_1555.taf    un fotograma de BlueFire con bordes alfa suaves

Tip

Pruébalo tú mismo.

kbot taf list   anims/manabomb_1555.taf                                 # sequence + frame count
kbot taf export anims/fireballa_1555.taf --format gif -o fireball.gif    # animated preview
kbot taf sheet  anims/manabomb_1555.taf --cols 5 -o manabomb-sheet.png   # contact sheet
kbot taf decompile anims/manabomb_1555.taf --target ./manabomb           # → TSF + PNG layers

Consulta la referencia de kbot taf / kbot tsf de la CLI para ver todas las opciones.

Desde Go. Usa formats/tsf:

import "github.com/coreprime/kbot/formats/tsf"

data, _ := os.ReadFile("anims/manabomb_1555.taf")
taf, _ := tsf.ParseTAF(data)
fmt.Println(taf.Name, len(taf.Frames))
img, _ := taf.FrameImage(0)   // *image.NRGBA, full alpha preserved

De un vistazo

┌─ Header (12B) ─┐
│ ver  1  pad    │   ver = 0x00010100, exactly one sequence
└────────┬───────┘
         ▼
┌─ Entry pointer ─┐  1 × uint32 absolute offset → SequenceHeader
└───┬─────────────┘
    ▼
┌─ SequenceHeader (40B) ─┐
│ frameCount, name[32]   │
└─────────┬──────────────┘
          ▼
┌─ FrameListItem (8B) × frameCount ─┐  ptr + tick duration
└───┬───────────────────────────────┘
    ▼
┌─ FrameInfo (24B) ─┐
│ size, origin,     │
│ format(4/5),      │   ← the GAF "compressed" byte, repurposed
│ layers=0, flag,   │
│ ptrPixelData      │
└─────┬─────────────┘
      ▼
┌─ Pixel data: Width×Height × uint16 ─┐  raw ARGB4444 or ARGB1555
└──────────────────────────────────────┘

Un TAF es una sola secuencia de animación: un array de fotogramas, cada uno un rectángulo de ancho × alto de píxeles truecolor de 16 bits en little-endian, con un punto de origen y una duración en ticks. A nivel binario no hay compresión ni capas: cada fotograma es un mapa de bits plano sin comprimir.

Note

TAF es el contenedor GAF con otros datos de píxeles. Si has leído GAF, la cabecera, la tabla de entradas, la cabecera de secuencia y la lista de fotogramas te resultarán conocidas byte a byte. Solo cambian la interpretación de FrameInfo y la codificación de los píxeles. Los dos conviven bajo la extensión .taf: TA: Kingdoms distribuye archivos .taf con paleta (léelos como un GAF) y archivos .taf truecolor (esta página). kbot los distingue por el byte de formato de cada fotograma: consulta Cómo distinguirlos.


Cabecera (12 bytes)

typedef struct {
    uint32 Version;        // 0x00010100 — identical to the GAF version word
    uint32 SequenceCount;  // Always 1 for a truecolor TAF
    uint32 Unknown1;       // Always 0
} TAFHeader;
Campo Notas
Version 0x00010100, la misma palabra que lleva un GAF de TA. Compruébala antes de fiarte de cualquier desplazamiento.
SequenceCount Siempre 1. Le sigue inmediatamente un desplazamiento absoluto uint32 que apunta a la SequenceHeader. Un archivo con varias secuencias no es un TAF truecolor.
Unknown1 Siempre cero; escribe cero al generar el archivo.

Secuencia (40 bytes)

typedef struct {
    uint16 FrameCount;
    uint16 Unknown1;       // Always 1
    uint32 Unknown2;       // Always 0
    char   Name[32];       // NUL-padded, case-preserved
} TAFSequence;

Le siguen FrameCount × FrameListItem:

typedef struct {
    uint32 PtrFrameInfo;   // → FrameInfo
    uint32 Duration;       // Game ticks (30 ticks = 1 second)
} FrameListItem;

Warning

El campo de nombre de 32 bytes puede llevar basura después del terminador. Varios TAF de la versión comercial dejan bytes de búfer sin inicializar después del NUL. kbot conserva los 32 bytes exactos para que el viaje de ida y vuelta análisis → serialización sea idéntico byte a byte, pero el nombre real es solo el texto hasta el primer NUL.


Fotograma (información de 24 bytes + datos)

typedef struct {
    uint16 Width;
    uint16 Height;
    int16  OriginX;        // Render anchor, may be negative
    int16  OriginY;
    uint8  Transparency;   // 0x08: always 0 (alpha lives in the pixels)
    uint8  Format;         // 0x09: 4 = ARGB4444, 5 = ARGB1555
    uint8  LayerCount;     // 0x0A: always 0 (no sub-frames)
    uint8  Flag;           // 0x0B: 0x00 or 0xFF, meaning unconfirmed
    uint32 Unknown2;       // 0x0C: always 0
    uint32 PtrPixelData;   // 0x10: → raw pixel bytes
    uint32 Unknown3;       // 0x14: always 0
} FrameInfo;

Aquí es donde TAF se separa de GAF. En el FrameInfo de un GAF, el desplazamiento 0x09 es la marca Compressed y los desplazamientos 0x0A–0x0B son un LayerCount de 16 bits. Un TAF truecolor reutiliza esos mismos bytes con este significado:

Desplazamiento Significado en GAF Significado en TAF
0x08 TransparencyIndex Transparency: sin uso, siempre 0
0x09 Compressed (0/1) Format: 4 (ARGB4444) o 5 (ARGB1555)
0x0A byte bajo de LayerCount LayerCount: siempre 0
0x0B byte alto de LayerCount Flag: 0x00 o 0xFF, finalidad desconocida

OriginX / OriginY son el punto de anclaje que se usa al volcar el fotograma; suele ser el centro del efecto, así que una explosión de 50×48 tiene el origen en 25,24. kbot conserva el byte Flag tal cual para que el viaje de ida y vuelta sea exacto byte a byte, aunque su significado no está confirmado en el conjunto de recursos de la versión comercial.

Datos de píxeles

PtrPixelData apunta exactamente a Width × Height valores uint16 en little-endian: 2 bytes por píxel, de arriba abajo y de izquierda a derecha, sin compresión y sin cabeceras de fila. Los 16 bits se decodifican según el Format del fotograma:

ARGB4444 (Format == 4)

 bit 15 ──────────────────────────── bit 0
┌─────┬─────┬─────┬─────┐
│  A  │  R  │  G  │  B  │   4 bits each
└─────┴─────┴─────┴─────┘
  15-12  11-8   7-4   3-0

Cada canal de 4 bits se amplía a 8 bits replicando los bits (v<<4 | v), así que 0xF → 0xFF y 0x0 → 0x00. La expansión es exactamente invertible, y eso es lo que permite a kbot hacer el viaje de ida y vuelta de los píxeles sin pérdidas.

ARGB1555 (Format == 5)

 bit 15 ──────────────────────────── bit 0
┌─┬───────┬───────┬───────┐
│A│   R   │   G   │   B   │   1 + 5 + 5 + 5
└─┴───────┴───────┴───────┘
 15  14-10   9-5    4-0

El único bit alfa es todo o nada (0 → totalmente transparente, 1 → totalmente opaco); cada canal de color de 5 bits se amplía por replicación (v<<3 | v>>2). Usa ARGB1555 para sprites de bordes duros que solo necesitan un recorte de 1 bit, y ARGB4444 cuando necesites 16 niveles de alfa suave (humo, resplandores, fundidos).

Important

TAF no necesita paleta. A diferencia de GAF, que solo guarda índices y depende de palettes/palette.pal o de un PCX acompañante de TA:K, cada píxel de un TAF ya contiene su propio color y su alfa. Renderizar es una expansión directa de 16 a 32 bits, sin ninguna tabla de consulta de por medio.


Cómo distinguir un TAF con paleta de uno truecolor

Las dos clases de .taf comparten la cabecera y la palabra de versión de GAF, así que no puedes distinguirlas por los 12 primeros bytes. Lo que las diferencia es el byte Format/Compressed del fotograma, en el desplazamiento 0x09 de FrameInfo:

Byte en 0x09 El archivo es Se lee con
0 o 1 Animación con paleta al estilo GAF (un valor 0/1 significa sin comprimir/comprimido) El cargador de GAF + una paleta
4 o 5 Animación truecolor (ARGB4444 / ARGB1555) Esta página (formats/tsf)

kbot taf comprueba ese byte y rechaza los archivos con paleta con un error claro; en ese caso, recurre a kbot gaf. La mayoría de los TAF truecolor de TA:K siguen además una convención de nombres, un sufijo _4444 o _1555 (manabomb_1555.taf, bluefire_4444.taf), pero lo que manda es el byte de formato, no el nombre.


TSF: la forma de texto

TSF (TAF Source Format) es la misma animación expresada como un script al estilo INI delimitado por llaves. El cargador de la interfaz de TA: Kingdoms lee TSF directamente para los fondos de los menús, y es el formato de intercambio que genera kbot cuando descompilas un TAF: una sección por animación, un Frame anidado por fotograma y una Layer por fotograma que hace referencia a un archivo de imagen externo.

/* anims/titlescreen.tsf — abridged */
[JPGTest]
{
    Looping = 0;
    [Frame0]
    {
        Delay = 0;
        [Layer0]
        {
            AnchorX = 0;
            AnchorY = 0;
            Filename = TitleScreen.jpg;
        }
    }
    [Frame1] { /* … */ }
}
Token Se corresponde con Notas
[Name] { … } La secuencia de animación Una por documento; Name pasa a ser el nombre de la secuencia del TAF.
Looping (orientativo) Pista para quien crea el archivo; el TAF binario no tiene campo de bucle.
[FrameN] Un Frame Delay es la duración en ticks de juego.
Format Frame.Format ARGB4444 (por defecto si se omite) o ARGB1555.
[LayerN] La imagen del fotograma Filename hace referencia a un PNG/JPG externo; AnchorX/Y pasan a ser el origen del fotograma.

Un TAF compilado aplana la única capa de cada fotograma en un mapa de bits truecolor. kbot espera exactamente una capa por fotograma (la composición de varias capas es una comodidad para crear interfaces que el compilador resuelve al compilar); kbot tsf lint señala todo lo que no vaya a compilar limpiamente.

Tip

Inspecciona un TSF sin tocar las imágenes.

kbot tsf info anims/titlescreen.tsf   # animation, frames, layer filenames
kbot tsf lint anims/titlescreen.tsf   # shape check; non-zero exit on errors

lint solo comprueba la estructura; usa kbot taf compile para poner a prueba todo el proceso de carga de imágenes.


Ejemplo desarrollado: manabomb_1555.taf

los diez fotogramas de manabomb dispuestos en una cuadrícula

$ kbot taf info anims/manabomb_1555.taf
TAF: anims/manabomb_1555.taf
Sequence:  "manabomb"
Frames:    10
Duration:  20 ticks (0.67s)

#  Size   Origin  Format    Duration  Flag
─  ────   ──────  ──────    ────────  ────
0  50x48  25,24   ARGB1555  2         0x00
1  50x48  25,24   ARGB1555  2         0x00
...
9  50x48  25,24   ARGB1555  2         0x00

Diez fotogramas de 50×48, cada uno anclado en su centro (25,24) y mostrado durante 2 ticks: una estrella explosiva de ⅔ de segundo. El archivo completo ocupa 48 376 bytes: 50 × 48 × 2 = 4,800 bytes de píxeles por fotograma × 10, más la cabecera, la cabecera de secuencia, la lista de fotogramas y los diez registros de información de 24 bytes.


Flujos de trabajo con la CLI

El árbol kbot taf cubre la inspección, el renderizado, la conversión y el ciclo de compilación TAF↔TSF; kbot tsf cubre la forma de texto. Cada comando resuelve su entrada a través del contexto de kbot activo o de un montaje --vfs explícito, exactamente igual que kbot gaf y kbot studio, así que los nombres de archivo sin ruta como manabomb_1555.taf se buscan en todos los archivos comprimidos montados.

Inspeccionar y renderizar

kbot taf info   anims/bluefire_4444.taf            # per-frame table
kbot taf list   anims/bluefire_4444.taf            # one-line summary
kbot taf render anims/bluefire_4444.taf --frame 4 -o frame4.png
kbot taf sheet  anims/bluefire_4444.taf --cols 6 --bg "#202830" -o sheet.png
kbot taf export anims/bluefire_4444.taf --format apng -o bluefire.png   # or --format gif

export usa por defecto APNG, que conserva el canal alfa completo; --format gif cuantiza a una tabla de 255 colores más una posición transparente (un recorte de 1 bit), para vistas previas y clientes de chat.

Viaje de ida y vuelta: descompilar ↔ compilar

kbot taf decompile anims/manabomb_1555.taf --target ./manabomb
#   → manabomb/manabomb.tsf  +  manabomb_0.png … manabomb_9.png

kbot taf compile ./manabomb/manabomb.tsf --images ./manabomb -o rebuilt.taf
kbot taf diff anims/manabomb_1555.taf rebuilt.taf      # exits 0 — identical

decompile escribe un TSF y un PNG por fotograma; compile los vuelve a leer y genera un TAF binario. Para cualquier TAF que kbot haya analizado, el viaje de ida y vuelta es idéntico byte a byte: kbot taf roundtrip y kbot taf diff lo verifican.

Importar desde formatos comunes

kbot taf from-gif   boom.gif   --format argb4444 --name Boom        -o boom.taf
kbot taf from-sheet strip.png  --frame-width 64 --frame-height 64 \
                               --count 8 --delay 3 --format argb1555 -o strip.taf

from-gif aplana un GIF animado (respetando sus modos de eliminación y los retardos de cada fotograma) en un TAF truecolor; from-sheet corta en fotogramas una tira de sprites PNG/JPG con cuadrícula fija. Los dos te dejan elegir el formato de píxel de destino.

Validar

kbot taf lint anims/manabomb_1555.taf   # structural findings; non-zero exit on errors

Herramientas MCP

Las mismas funciones se ofrecen a través del servidor MCP para que un agente pueda inspeccionar y mostrar animaciones directamente:

Herramienta Finalidad
taf_info JSON completo por fotograma: nombre, tamaños, orígenes, formatos, duraciones.
taf_list Resumen en JSON de una línea.
taf_render Renderiza un fotograma y lo devuelve en línea como PNG (y opcionalmente lo guarda).
taf_sheet Renderiza todos los fotogramas en una hoja de contactos que devuelve en línea como PNG.
taf_export Escribe en disco un GIF animado o un APNG.
taf_lint Diagnóstico estructural en JSON.
tsf_info Resume un documento TSF (animación, fotogramas, nombres de archivo de las capas).
tsf_lint Comprueba la forma de un documento TSF.

taf_render y taf_sheet devuelven un bloque de contenido de imagen, así que un modelo puede previsualizar un efecto de hechizo sin tener que hacer otra ida y vuelta para leer un archivo. Las rutas se resuelven contra la carpeta game-data configurada, igual que en cualquier otra herramienta MCP de kbot.


Escollos

Warning

.taf tiene dos significados. Un .taf puede ser un GAF con paleta o una animación truecolor. Comprueba siempre el byte de formato del fotograma (0x09), no la extensión ni el nombre del archivo: consulta Cómo distinguirlos.

  • Exactamente una secuencia. Un TAF truecolor siempre contiene una sola animación; un SequenceCount distinto de 1 significa que estás ante otro tipo de archivo (probablemente con paleta).
  • Nunca hay compresión. Cada fotograma es un mapa de bits plano de Width×Height a 16 bits. No hay una vía RLE como la de GAF: los efectos de llamas grandes (composite02flame) llegan a unos 600 KB precisamente porque no se empaqueta nada.
  • El campo de nombre puede contener basura. Los bytes que siguen al NUL final están sin inicializar en varios archivos de la versión comercial; conserva los 32 bytes para un viaje de ida y vuelta exacto, pero lee solo hasta el NUL.
  • El byte de flags 0x0B no tiene explicación. Se ha visto como 0x00 o 0xFF. kbot lo conserva tal cual; no lo normalices o el viaje de ida y vuelta dejará de coincidir.
  • La exportación a GIF pierde información. GIF solo admite un recorte de 1 bit y 255 colores: el alfa suave de ARGB4444 se convierte en bordes duros. Usa APNG para conservar el canal alfa real.
  • Un Delay / Duration de 0 es válido. Como en GAF, un fotograma de cero ticks lo controlan los eventos (el ejemplo de menú JPGTest usa Delay = 0 para un fondo estático). No lo «corrijas» con un valor por defecto.

Tamaños habituales

Recurso Rango observado en los TAF de TA:K
Efecto pequeño (bluefire_4444, 12 fotogramas de unos 32 px) ~30–60 KB
Explosión (manabomb_1555, 10 × 50×48) ~48 KB
Bola de fuego / hechizo (fireballa_1555) ~50–120 KB
Llama compuesta grande (composite02flame) ~600 KB (el truecolor sin comprimir se acumula)
Datos de píxeles por fotograma Width × Height × 2 bytes, exactamente

Véase también

  • GAF: el contenedor con paleta sobre el que se construye TAF; léelo primero y úsalo para los archivos .taf con paleta.
  • PCX: cómo obtienen sus colores los recursos con paleta de TA:K (el TAF truecolor no los necesita).
  • Interfaz de TA:K: el sistema de menús cuyo cargador lee TSF directamente para los fondos animados.
  • Formatos de TA y TA:K: qué comparten los dos juegos y en qué se diferencian.
  • Glosario: origin, tick, sub-frame.