TAF / TSF — повнокольорові анімації TA: Kingdoms
Джерело: coreprime/kbot @ 0ab97bf · Редагувати на GitHub
TAF зберігає повнокольорові анімації спрайтів для Total Annihilation: Kingdoms: ефекти заклинань, вибухи, вогняні кулі, магічні кільця, спрайти води й анімовані фони меню. Він повторно використовує структуру контейнера GAF із Total Annihilation, але замінює 8-бітні пікселі з індексами палітри на 16-бітний ARGB, тож TAF містить власні кольори й справжній альфа-канал — зовнішня палітра не потрібна. TSF — це зрозуміла людині текстова форма тієї самої анімації: скрипт, розмежований фігурними дужками, який завантажувач інтерфейсу читає безпосередньо.
Tip
Спробуйте самі.
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
Усі прапорці описано в довіднику CLI kbot taf / kbot tsf.
З Go. Скористайтеся пакетом 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
Коротко
┌─ 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
└──────────────────────────────────────┘
TAF — це одна анімаційна послідовність: масив кадрів, кожен із яких є прямокутником width × height з 16-бітних повнокольорових пікселів у little-endian, із точкою прив'язки (origin) і тривалістю в тіках. На двійковому рівні немає ні стиснення, ні шарів: кожен кадр — пласке растрове зображення без стиснення.
Note
TAF — це контейнер GAF з іншими піксельними даними. Якщо ви читали
GAF, то заголовок, таблиця записів, заголовок послідовності й
список кадрів будуть знайомі вам байт у байт. Змінюються лише
тлумачення FrameInfo і кодування пікселів. Обидва різновиди
співіснують під розширенням .taf: TA: Kingdoms постачає і
палітрові файли .taf (читайте їх як GAF), і
повнокольорові файли .taf (ця сторінка). kbot розрізняє їх за
байтом формату в кожному кадрі — див. Як їх розрізнити.
Заголовок (12 байтів)
typedef struct {
uint32 Version; // 0x00010100 — identical to the GAF version word
uint32 SequenceCount; // Always 1 for a truecolor TAF
uint32 Unknown1; // Always 0
} TAFHeader;
| Поле | Примітки |
|---|---|
Version |
0x00010100 — те саме слово, що й у GAF із TA. Перевіряйте його, перш ніж довіряти будь-якому зміщенню. |
SequenceCount |
Завжди 1. Одразу за ним іде одне абсолютне зміщення uint32, що вказує на SequenceHeader. Файл із кількома послідовностями — не повнокольоровий TAF. |
Unknown1 |
Завжди нуль; під час запису виводьте нуль. |
Послідовність (40 байтів)
typedef struct {
uint16 FrameCount;
uint16 Unknown1; // Always 1
uint32 Unknown2; // Always 0
char Name[32]; // NUL-padded, case-preserved
} TAFSequence;
Далі йдуть FrameCount × FrameListItem:
typedef struct {
uint32 PtrFrameInfo; // → FrameInfo
uint32 Duration; // Game ticks (30 ticks = 1 second)
} FrameListItem;
Warning
32-байтове поле імені може містити сміття після завершального символу. Кілька релізних TAF лишають після NUL неініціалізовані байти буфера. kbot зберігає всі 32 байти точно, тож round-trip «розбір → серіалізація» дає результат, ідентичний до байта, але справжнє ім'я — це лише текст до першого NUL.
Кадр (24-байтова інформація + дані)
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;
Саме тут TAF відходить від GAF. У FrameInfo формату GAF зміщення 0x09
— це прапорець Compressed, а зміщення 0x0A–0x0B — 16-бітний
LayerCount. Повнокольоровий TAF використовує ті самі байти в іншому
значенні:
| Зміщення | Значення в GAF | Значення в TAF |
|---|---|---|
0x08 |
TransparencyIndex |
Transparency — не використовується, завжди 0 |
0x09 |
Compressed (0/1) |
Format — 4 (ARGB4444) або 5 (ARGB1555) |
0x0A |
молодший байт LayerCount |
LayerCount — завжди 0 |
0x0B |
старший байт LayerCount |
Flag — 0x00 або 0xFF, призначення невідоме |
OriginX / OriginY — це точка прив'язки, яка використовується під час
виведення (blit) кадру; зазвичай це центр ефекту, тож вибух 50×48 має
точку прив'язки 25,24. kbot зберігає байт Flag без змін, щоб
round-trip був точним до байта, хоча його значення в релізному наборі
ресурсів не підтверджено.
Піксельні дані
PtrPixelData вказує рівно на Width × Height значень uint16 у
little-endian — 2 байти на піксель, згори вниз і зліва направо, без
стиснення й без заголовків рядків. 16 бітів декодуються відповідно до
Format кадру:
ARGB4444 (Format == 4)
bit 15 ──────────────────────────── bit 0
┌─────┬─────┬─────┬─────┐
│ A │ R │ G │ B │ 4 bits each
└─────┴─────┴─────┴─────┘
15-12 11-8 7-4 3-0
Кожен 4-бітний канал розширюється до 8 бітів повторенням бітів
(v<<4 | v), тож 0xF → 0xFF, а 0x0 → 0x00. Це розширення точно
оборотне, і саме завдяки цьому kbot проводить round-trip пікселів без
втрат.
ARGB1555 (Format == 5)
bit 15 ──────────────────────────── bit 0
┌─┬───────┬───────┬───────┐
│A│ R │ G │ B │ 1 + 5 + 5 + 5
└─┴───────┴───────┴───────┘
15 14-10 9-5 4-0
Єдиний біт альфа-каналу працює за принципом «усе або нічого» (0 →
повністю прозорий, 1 → повністю непрозорий); кожен 5-бітний колірний
канал розширюється повторенням (v<<3 | v>>2). Використовуйте ARGB1555
для спрайтів із чіткими краями, яким досить 1-бітної маски вирізання, а
ARGB4444 — коли потрібні 16 рівнів м'якої прозорості (дим, світіння,
затухання).
Important
TAF не потребує палітри. На відміну від GAF, який зберігає лише
індекси й залежить від palettes/palette.pal або супровідного PCX у
TA:K, кожен піксель TAF уже містить власні колір і альфу. Рендеринг —
це пряме розширення 16 біт → 32 біти без жодної таблиці пошуку.
Як розрізнити палітровий і повнокольоровий TAF
Обидва різновиди .taf мають спільні заголовок і слово версії GAF, тож
за першими 12 байтами їх не розрізнити. Ознака — байт
Format/Compressed кадру за зміщенням 0x09 у FrameInfo:
| Байт за 0x09 | Файл — це | Чим читати |
|---|---|---|
0 або 1 |
Палітрова анімація в стилі GAF (значення 0/1 означає без стиснення / зі стисненням) | Завантажувач GAF + палітра |
4 або 5 |
Повнокольорова анімація (ARGB4444 / ARGB1555) | ця сторінка (formats/tsf) |
kbot taf перевіряє цей байт і відмовляється працювати з палітровим
файлом, видаючи зрозумілу помилку; у такому разі беріть kbot gaf.
Більшість повнокольорових TAF у TA:K також дотримуються домовленості
щодо імен файлів — суфікса _4444 або _1555 (manabomb_1555.taf,
bluefire_4444.taf), — але вирішальним є байт формату, а не ім'я.
TSF — текстова форма
TSF (TAF Source Format) — це та сама анімація, записана у вигляді
скрипту в стилі INI, розмежованого фігурними дужками. Завантажувач
інтерфейсу TA: Kingdoms читає TSF безпосередньо для фонів меню, і
саме цей формат обміну kbot виводить, коли ви декомпілюєте TAF: одна
секція на анімацію, вкладена секція Frame на кожен кадр і одна Layer
на кадр із посиланням на зовнішній файл зображення.
/* anims/titlescreen.tsf — abridged */
[JPGTest]
{
Looping = 0;
[Frame0]
{
Delay = 0;
[Layer0]
{
AnchorX = 0;
AnchorY = 0;
Filename = TitleScreen.jpg;
}
}
[Frame1] { /* … */ }
}
| Токен | Відповідає | Примітки |
|---|---|---|
[Name] { … } |
Анімаційній послідовності | Одна на документ; Name стає іменем послідовності TAF. |
Looping |
(рекомендаційне) | Підказка для автора; у двійковому TAF поля зациклення немає. |
[FrameN] |
Frame |
Delay — тривалість у ігрових тіках. |
Format |
Frame.Format |
ARGB4444 (за замовчуванням, якщо пропущено) або ARGB1555. |
[LayerN] |
Зображенню кадру | Filename посилається на зовнішній PNG/JPG; AnchorX/Y стають точкою прив'язки кадру. |
Скомпільований TAF зводить єдиний шар кожного кадру в одне повнокольорове
растрове зображення. kbot очікує рівно один шар на кадр (компонування
кількох шарів — це зручність для авторів інтерфейсу, яку компілятор
розв'язує під час збирання); kbot tsf lint позначає все, що не
скомпілюється без проблем.
Tip
Перевірте TSF, не торкаючись зображень.
kbot tsf info anims/titlescreen.tsf # animation, frames, layer filenames
kbot tsf lint anims/titlescreen.tsf # shape check; non-zero exit on errors
lint перевіряє лише структуру — щоб пройти весь конвеєр завантаження
зображень, скористайтеся kbot taf compile.
Розібраний приклад — manabomb_1555.taf
$ 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
Десять кадрів 50×48, кожен прив'язаний до свого центру (25,24) і
показується 2 тіки — зірка вибуху тривалістю ⅔ секунди. Увесь файл має
48 376 байтів: 50 × 48 × 2 = 4,800 байтів пікселів на кадр × 10, плюс
заголовок, заголовок послідовності, список кадрів і десять 24-байтових
інформаційних записів.
Робота в CLI
Дерево команд kbot taf охоплює перегляд, рендеринг, конвертацію й цикл
компіляції TAF↔TSF; kbot tsf працює з текстовою формою. Кожна команда
знаходить вхідні дані через активний контекст kbot
або явне монтування --vfs, точно так само, як kbot gaf і
kbot studio, тож голі імена файлів на кшталт manabomb_1555.taf
шукаються в усіх змонтованих архівах.
Перегляд і рендеринг
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 за замовчуванням виводить APNG, який зберігає повний
альфа-канал; --format gif квантує кольори до таблиці з 255 кольорів
плюс один прозорий слот (1-бітна маска вирізання) — для попереднього
перегляду й чат-клієнтів.
Round-trip декомпіляції ↔ компіляції
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 записує TSF і по одному PNG на кадр; compile читає їх назад
у двійковий TAF. Для будь-якого TAF, який kbot розібрав, round-trip дає
результат, ідентичний до байта, — це перевіряють і kbot taf roundtrip,
і kbot taf diff.
Імпорт із поширених форматів
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 зводить анімований GIF (з урахуванням його режимів disposal і
затримок окремих кадрів) у повнокольоровий TAF; from-sheet нарізає на
кадри стрічку спрайтів PNG/JPG із фіксованою сіткою. Обидві команди
дають змогу обрати цільовий формат пікселів.
Перевірка
kbot taf lint anims/manabomb_1555.taf # structural findings; non-zero exit on errors
Інструменти MCP
Ті самі можливості доступні через сервер MCP, тож агент може переглядати й показувати анімації безпосередньо:
| Інструмент | Призначення |
|---|---|
taf_info |
Повний JSON по кадрах: ім'я, розміри, точки прив'язки, формати, тривалості. |
taf_list |
Однорядкове зведення в JSON. |
taf_render |
Рендерить один кадр і повертає його вбудованим PNG (за бажанням також зберігає). |
taf_sheet |
Рендерить усі кадри в аркуш кадрів (contact sheet), що повертається вбудованим PNG. |
taf_export |
Записує на диск анімований GIF або APNG. |
taf_lint |
Структурна діагностика у форматі JSON. |
tsf_info |
Зведення документа TSF (анімація, кадри, імена файлів шарів). |
tsf_lint |
Перевірка структури документа TSF. |
taf_render і taf_sheet повертають блок вмісту із зображенням, тож
модель може переглянути ефект заклинання без окремого читання файлу.
Шляхи шукаються в налаштованій теці game-data так само, як і в усіх
інших інструментах MCP у kbot.
Підводні камені
Warning
.taf має кілька значень. .taf може бути палітровим GAF або
повнокольоровою анімацією. Завжди перевіряйте байт формату кадру
(0x09), а не розширення чи ім'я файлу — див. Як їх розрізнити.
- Рівно одна послідовність. Повнокольоровий TAF завжди містить одну
анімацію;
SequenceCount, відмінний від1, означає, що перед вами інший (імовірно, палітровий) файл. - Жодного стиснення. Кожен кадр — пласке 16-бітне растрове
зображення
Width×Height. Шляху RLE, як у GAF, немає — великі ефекти полум'я (composite02flame) сягають ~600 КБ саме тому, що нічого не запаковано. - Поле імені може містити сміття. У кількох релізних файлах байти після завершального NUL неініціалізовані; для точного round-trip зберігайте всі 32 байти, але читайте лише до NUL.
- Байт прапорця
0x0Bне пояснено. Трапляються значення0x00або0xFF. kbot зберігає його без змін; не нормалізуйте його, інакше round-trip перестане збігатися. - Експорт у GIF іде із втратами. GIF вміщує лише 1-бітну маску вирізання й 255 кольорів — м'яка прозорість ARGB4444 перетворюється на чіткі краї. Щоб зберегти справжній альфа-канал, використовуйте APNG.
Delay/Duration, що дорівнює 0, — допустимі. Як і в GAF, кадр із нулем тіків керується подіями (приклад менюJPGTestвикористовуєDelay = 0для статичного фону). Не «виправляйте» його на значення за замовчуванням.
Типові розміри
| Ресурс | Діапазон, що трапляється в TAF із TA:K |
|---|---|
Невеликий ефект (bluefire_4444, 12 кадрів приблизно 32 px) |
~30–60 КБ |
Вибух (manabomb_1555, 10 × 50×48) |
~48 КБ |
Вогняна куля / заклинання (fireballa_1555) |
~50–120 КБ |
Велике складене полум'я (composite02flame) |
~600 КБ (повний колір без стиснення накопичується) |
| Піксельні дані одного кадру | рівно Width × Height × 2 байтів |
Див. також
- GAF — палітровий контейнер, на якому побудовано TAF; прочитайте
його першим і використовуйте для палітрових файлів
.taf. - PCX — як палітрові ресурси TA:K отримують свої кольори (повнокольоровому TAF вони не потрібні).
- Інтерфейс TA:K — система меню, завантажувач якої напряму споживає TSF для анімованих фонів.
- Формати TA і TA:K — що спільне в обох ігор і де вони розходяться.
- Глосарій — origin, tick, sub-frame.