PAL / ALP / LHT / SHD — палітри й таблиці пошуку кольорів
Джерело: coreprime/kbot @ 0ab97bf · Редагувати на GitHub
Увесь світ Total Annihilation вміщено в 256 кольорів. Файл
.palмістить цю палітру; файли.alp,.shdі.lht— це побудовані на її основі таблиці пошуку, за допомогою яких рушій змішує, затінює й освітлює пікселі, не виходячи за межі простору індексованих кольорів.Жоден із чотирьох форматів не має ні заголовка, ні поля версії, ні стиснення.
.palзаймає 1 024 байти (256 × RGBx);.alp— 65 536 байтів (256 рядків по 256 індексів палітри), а.shd/.lht— по 8 192 байти (32 рядки по 256 індексів палітри).
palettes/palette.pal — відрендерено командою kbot pal swatch
Tip
Спробуйте самі.
kbot pal info palettes/palette.pal # one-liner
kbot pal describe palettes/palette.pal # full RGB dump
kbot pal swatch palettes/palette.pal -o pal.png --cell 24
# Render a lookup table, coloured by the palette:
# .alp as 256×256 cells, .shd / .lht as 256×32 cells
kbot pal lookup palettes/palette.alp --palette palettes/palette.pal --target alp.png
kbot pal lookup palettes/palette.shd --target shd.png
# TA: Kingdoms: the palette is usually a PCX next to its tables
kbot pal lookup palettes/aramon.alp --palette palettes/aramon.pcx --target aramon.png
# Round-trip to editor-friendly formats
kbot pal convert palettes/palette.pal -o palette.gpl # GIMP
kbot pal convert palettes/palette.pal -o palette.txt --format jasc # JASC
Див. довідник CLI kbot pal.
З Go. Скористайтеся пакетом formats/pal:
import "github.com/coreprime/kbot/formats/pal"
p, _ := pal.LoadFromFile("palettes/palette.pal")
fmt.Printf("RGB[0] = %v (black; sprites key it per frame)\n", p.Colors[0])
for i, c := range p.Colors {
fmt.Printf("%3d #%02x%02x%02x\n", i, c.R, c.G, c.B)
}
Структура на диску (.pal)
typedef struct {
uint8 R;
uint8 G;
uint8 B;
uint8 A; // Unused. Cavedog files have this as 0 throughout.
} PALEntry;
PALEntry entries[256]; // 256 × 4 = 1024 bytes
Немає ні сигнатури, ні версії. Гра завантажує palettes/<name>.pal так
(pal.LoadNamed у kbot-io робить те саме, і студія та оглядач ресурсів
завантажують через нього palette.pal для кожного рендеру TA: пулу
тайлів, мінімап, рельєфу в пісочниці, об'єктів, текстур і кольорів
моделей):
- 1 024 байти або більше: перші 1 024 байти — це палітра, решта ігнорується.
- Порожній або відсутній: палітра натомість береться з
palettes/<name>.pcx— це останні 768 байтів того файлу, незалежно від того, чи стоїть перед ними маркер0x0C. Після цього TA 3.1c будує заново таблиці.alp,.shdі.lhtдля цих кольорів. - Від 1 до 1 023 байтів: непридатний; гра читає 1 024 байти, виходячи за кінець файлу. kbot повідомляє про помилку (а студія повертається до вбудованої палітри TA).
.pal — канонічна палітра TA
Байти R, G, B, A у кожному записі буквально означають червоний,
зелений, синій, не використовується. Індекс 0 — звичайний
чорний. Тайли рельєфу, мінімапи й фони малюють його непрозорим (62 з
275 релізних мап використовують його у своїх тайлах). Прозорість
визначається для кожного зображення окремо, а не палітрою: прозорими є
ключовий байт кадру GAF (часто 9, інколи 0) і його пропущені пікселі, а
текстури моделей вибираються без ключа.
| Індекс | Домовленість у TA | Примітки |
|---|---|---|
0 |
Чорний | Непрозорий у рельєфі, мінімапах і фонах; прозорий лише в кадрах спрайтів, ключ яких 0. |
9 |
«Чарівний рожевий» (magic pink) | Інструменти редактора використовують його як колір заливки прозорих ділянок у PCX/GAF перед кодуванням; під час гри не прозорий. |
16–95 |
Цикли кольорів гравців | Рушій підміняє їх для кожної сторони, щоб перефарбувати юніти. |
223–254 |
Зарезервовано | Здебільшого використовуються циклами кольорів команд і спецефектами. |
255 |
Чистий білий | Часто використовується для серцевини лазерних променів. |
Note
256 RGB-трійок обрано не довільно. Cavedog вручну налаштувала
палітру так, щоб для кожної основної групи матеріалів (метал, органіка,
вода, небо, лава, …) існували плавні градієнти. Заміна записів, щоб
додати «новий» колір у мод, зазвичай ламає кожен юніт, який брав кольори
з цього градієнта. Групування градієнтів див. у виводі pal describe.
.alp / .shd / .lht — таблиці пошуку кольорів
Ці три файли не є RGB-даними: кожен байт — це індекс палітри. Кожна таблиця має по одному рядку з 256 записів на кожного партнера змішування чи рівень, а її стовпці — це 256 вихідних кольорів:
| Файл | Розмір | Рядків | Запис [r][c] |
|---|---|---|---|
.alp (alpha) |
65 536 | 256 | Індекс, найближчий до середнього кольорів r і c: змішування навпіл, що використовується для напівпрозорого малювання. Симетрична, і [c][c] дорівнює c. |
.shd (shade) |
8 192 | 32 | Індекс, найближчий до кольору c, помноженого на r × 0.06875: рядок 0 — чорний, рядки 14–15 лишають кольори майже без змін, вищі рядки освітлюють їх. |
.lht (light) |
8 192 | 32 | Індекс, найближчий до кольору c, помноженого на 1 + r/30, — від незміненого (рядок 0) до приблизно вдвічі яскравішого. |
uint8 alp[256][256]; // blend = alp[a][b]
uint8 shd[32][256]; // shaded = shd[level][c]
uint8 lht[32][256]; // lit = lht[level][c]
На практиці рушій ніколи не змішує кольори арифметично — він звертається до таблиці, тож отриманий піксель завжди є справжнім індексом палітри, який можна намалювати через наявний 8-бітний конвеєр. Ось чому всі тіні в TA виглядають як темніший варіант того самого градієнта, а не як «накладений 50-відсотковий чорний»: кожен затінений результат — це індекс палітри, найближчий до відповідної математичної суміші.
Гра використовує файл таблиці, лише якщо його розмір точний; відсутня
таблиця або таблиця будь-якого іншого розміру будується заново з
палітри. Тому kbot pal lookup відхиляє файли будь-якого іншого розміру.
TA: Kingdoms постачає таблиці тих самих розмірів майже для кожної палітри
у своїй теці palettes/; більшість цих палітр — файли PCX, і
kbot pal lookup --palette приймає .pcx так само, як і .pal.
Important
Таблиця пошуку — не палітра. Якщо відрендерити .alp через
kbot pal describe, ви побачите безглузді значення RGB, бо ці байти не
є RGB. Щоб побачити, що вони насправді роблять, використовуйте
kbot pal lookup — передайте супровідний .pal, щоб кожну клітинку
таблиці можна було забарвити тим записом палітри, на який вона
посилається.
Розібраний приклад — palette.pal
Перші 16 записів стандартної палітри TA:
| Індекс | Hex | R G B | Роль |
|---|---|---|---|
| 0 | #000000 |
0 0 0 | Чорний (непрозорий у рельєфі; ключ деяких кадрів спрайтів) |
| 1 | #800000 |
128 0 0 | Темно-червоний |
| 2 | #008000 |
0 128 0 | Темно-зелений |
| 3 | #808000 |
128 128 0 | Оливковий |
| 4 | #000080 |
0 0 128 | Темно-синій (тінь води) |
| 5 | #800080 |
128 0 128 | Темно-пурпуровий |
| 6 | #008080 |
0 128 128 | Темно-бірюзовий |
| 7 | #808080 |
128 128 128 | Середньо-сірий |
| 8 | #C0DCC0 |
192 220 192 | Блідо-зелений |
| 9 | #5454FC |
84 84 252 | «Чарівний рожевий» (прозорість у редакторі) |
| 10–15 | #000000 × 6 |
0 0 0 | Зарезервоване доповнення |
kbot pal describe palettes/palette.pal виводить повну таблицю.
Розібраний приклад — palette.alp і palette.shd як таблиці пошуку
Рендеринг таблиць із палітрою як джерелом кольорів
(kbot pal lookup … --cell 2):
palette.alp: 256 × 256 клітинок. Рядок a, стовпець b показує суміш кольорів a і b;
діагональ відтворює кожен колір.
palette.shd: 256 × 32 клітинки. Кожен стовпець — вихідний колір;
рядки йдуть від чорного (рядок 0) через сам колір до світліших відтінків.
Як читати таблицю затінення: стовпець 80 (середньо-сірий) у рядку 0
починається з чорного, піднімається через темніші сірі свого градієнта,
досягає самого себе приблизно в рядках 14 і 15, а далі світлішає. Рушію
ніколи не треба множити значення RGB — він просто читає shd[level][c].
Конвертація палітр для редакторів
kbot pal convert підтримує кілька вихідних форматів, зручних для
редакторів:
| Формат | Розширення | Інструмент |
|---|---|---|
Двійковий .PAL із TA |
.pal |
Сам формат; корисний для повторного виведення після редагування. |
| GIMP Palette | .gpl |
GIMP, Krita, Inkscape. |
| JASC-PAL (текстовий) | .pal / .txt (--format jasc) |
Paint Shop Pro, Aseprite. |
| PNG зі зразками кольорів | .png (через kbot pal swatch) |
Візуальний довідник; як палітру не завантажується. |
Зворотний напрямок — імпорт .gpl чи .pal (JASC) назад у двійковий
.pal для TA — працює, якщо джерело має 256 записів.
Note
Палітра TA містить 13 однакових RGB-трійок. Якщо ваш редактор під
час імпорту прибирає дублікати кольорів (деякі так роблять), ви
втратите записи, і палітра мовчки скоротиться до 243 записів.
kbot pal info повідомляє кількість дублікатів, щоб ви помітили
різницю; для перевірки зробіть round-trip через
kbot pal convert -o roundtrip.pal.
Підводні камені
Warning
4-й байт кожного запису — не альфа. Це невикористовуваний байт
доповнення, який Cavedog завжди встановлювала в 0x00. Кілька
відкритих інструментів для палітр читають його як альфу, а потім
відмовляються рендерити палітру (alpha=0 скрізь ⇒ усе прозоре). kbot
ігнорує його під час читання й записує 0x00.
- Індекс 0 сам по собі не прозорий. Рельєф, мінімапи й фони малюють його чорним; кадр спрайта прозорий лише там, де це визначає його власний ключ (або серія пропуску). Рендери рельєфу й мінімап у kbot використовують непрозору палітру.
- Без магічних чисел перевірка слабка. Єдиний спосіб перевірити
.palна адекватність — вимагати щонайменше 1024 байти й (за бажанням) нульовий байт альфи в кожному записі. - Таблицю пошуку неправильного розміру гра ігнорує й будує заново з палітри.
.alp/.lht/.shdне взаємозамінні. Їх налаштовано для різних ефектів; якщо їх поміняти місцями, тіні чи освітлення будуть помітно неправильними.- TA: Kingdoms використовує палітри, вбудовані в PCX окремих сторін,
а не робочий процес із глобальним
.pal. Прийом із PCX-носіями див. на сторінці PCX.
Типові розміри
| Файл | Розмір | Примітки |
|---|---|---|
palette.pal |
1 024 байти | З довшого файлу гра читає перші 1 024 байти. |
palette.alp |
65 536 байтів | 256 × 256 індексів палітри. |
palette.shd / palette.lht |
8 192 байти | 32 × 256 індексів палітри. |
Експорт GIMP .gpl |
~5 КБ | Текстовий формат, значно більший за двійковий. |
Експорт JASC .pal (текстовий) |
~3 КБ | Те саме. |
PNG з kbot pal swatch |
1–10 КБ | Залежить від розміру --cell. |
| Усього файлів палітр у стандартній TA | ~15 файлів | Один канонічний набір palette.* плюс кілька альтернативних палітр інтерфейсу. |