PAL / ALP / LHT / SHD — Palette e tabelle di ricerca dei colori
Total Annihilation disegna il suo intero mondo con 256 colori. Il file
.palcontiene quella palette; i file.alp,.shde.lhtsono tabelle di ricerca costruite a partire da essa, che il motore usa per fondere, ombreggiare e illuminare i pixel senza uscire dallo spazio dei colori indicizzati.Nessuno dei quattro ha un'intestazione, un campo di versione o una compressione. Un
.palè di 1.024 byte (256 × RGBx); un.alpè di 65.536 byte (256 righe di 256 indici della palette) e.shd/.lhtsono di 8.192 byte ciascuno (32 righe di 256 indici della palette).
palettes/palette.pal — disegnata da kbot pal swatch
Tip
Provalo tu stesso.
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
Consulta il riferimento CLI di kbot pal.
Da Go. Usa 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)
}
Struttura su disco (.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
Non c'è né una firma né una versione. Il gioco carica
palettes/<name>.pal in questo modo (pal.LoadNamed di kbot-io fa lo
stesso, e lo studio e l'esploratore di asset caricano palette.pal tramite
questa funzione per ogni rendering di TA: pool dei tile, minimappe, terreno
della sandbox, elementi, texture e colori dei modelli):
- 1.024 byte o più: i primi 1.024 byte sono la palette; il resto viene ignorato.
- Vuoto o mancante: la palette viene invece da
palettes/<name>.pcx, dagli ultimi 768 byte di quel file, che siano preceduti o no da un marcatore0x0C. TA 3.1c ricostruisce poi le tabelle.alp,.shde.lhtper quei colori. - Da 1 a 1.023 byte: inutilizzabile; il gioco legge 1.024 byte, oltre la fine del file. kbot segnala un errore (e lo studio ripiega sulla palette di TA integrata).
.pal — la palette canonica di TA
I byte R, G, B, A di ogni voce significano letteralmente rosso,
verde, blu, inutilizzato. L'indice 0 è un normale nero. Tile del
terreno, minimappe e fondali lo disegnano opaco (62 delle 275 mappe
originali lo usano nei loro tile). La trasparenza si decide immagine per
immagine, non nella palette: il byte chiave di un frame GAF (spesso 9, a
volte 0) e i suoi pixel saltati sono trasparenti, e le texture dei modelli
vengono campionate senza chiave.
| Indice | Convenzione di TA | Note |
|---|---|---|
0 |
Nero | Opaco nel terreno, nelle minimappe e nei fondali; trasparente solo nei frame degli sprite la cui chiave è 0. |
9 |
"Rosa magico" | Usato dagli strumenti di editing come colore di riempimento per le regioni trasparenti nei PCX/GAF prima della codifica; non è trasparente durante il gioco. |
16–95 |
Cicli dei colori dei giocatori | Il motore li sostituisce per ogni fazione per ricolorare le unità. |
223–254 |
Riservati | Usati per lo più dai cicli dei colori delle squadre e dagli effetti speciali. |
255 |
Bianco puro | Usato spesso per il nucleo dei laser. |
Note
Le 256 terne RGB non sono casuali. Cavedog ha messo a punto a mano la
palette in modo che esistano sfumature continue per ciascuna delle
principali famiglie di materiali (metallo, materia organica, acqua, cielo,
lava, …). Sostituire delle voci per inserire un colore "nuovo" di solito
rovina ogni unità che attingeva a quella sfumatura. Vedi l'output di
pal describe per i raggruppamenti delle sfumature.
.alp / .shd / .lht — tabelle di ricerca dei colori
Questi tre file non sono dati RGB: ogni byte è un indice della palette. Ogni tabella ha una riga di 256 voci per ogni partner di fusione o livello, e le sue colonne sono i 256 colori di partenza:
| File | Dimensione | Righe | Voce [r][c] |
|---|---|---|---|
.alp (alfa) |
65.536 | 256 | L'indice più vicino alla media dei colori r e c: una fusione metà e metà, usata per il disegno traslucido. Simmetrica, e [c][c] vale c. |
.shd (ombra) |
8.192 | 32 | L'indice più vicino al colore c scalato di r × 0.06875: la riga 0 è nera, le righe 14–15 lasciano i colori quasi invariati, le righe più alte li schiariscono. |
.lht (luce) |
8.192 | 32 | L'indice più vicino al colore c scalato di 1 + r/30, da invariato (riga 0) a circa il doppio della luminosità. |
uint8 alp[256][256]; // blend = alp[a][b]
uint8 shd[32][256]; // shaded = shd[level][c]
uint8 lht[32][256]; // lit = lht[level][c]
In pratica il motore non fonde mai i colori aritmeticamente: fa una ricerca in tabella, quindi il pixel risultante è sempre un vero indice della palette che si può disegnare con la pipeline esistente a 8 bpp. È per questo che tutte le ombre di TA sembrano una versione più scura della stessa sfumatura di colore, e non un "nero al 50% sovrapposto": ogni risultato ombreggiato è l'indice della palette più vicino a quella miscela matematica.
Il gioco usa un file di tabella solo quando la sua dimensione è esatta; una
tabella mancante o di qualsiasi altra dimensione viene ricostruita dalla
palette. Per questo kbot pal lookup rifiuta i file di qualsiasi altra
dimensione. TA: Kingdoms distribuisce tabelle delle stesse dimensioni per
quasi ogni palette della sua cartella palettes/; la maggior parte di
quelle palette sono file PCX, e kbot pal lookup --palette accetta un
.pcx oltre che un .pal.
Important
Una tabella di ricerca non è una palette. Disegnare un .alp con
kbot pal describe ti mostrerà valori RGB senza senso, perché i byte non
sono RGB. Usa kbot pal lookup per vedere che cosa fanno davvero: passa il
.pal che li accompagna, così ogni cella della tabella può essere colorata
con la voce della palette a cui rimanda.
Esempio svolto — palette.pal
Le prime 16 voci della palette standard di TA:
| Ind. | Hex | R G B | Ruolo |
|---|---|---|---|
| 0 | #000000 |
0 0 0 | Nero (opaco nel terreno; la chiave di alcuni frame degli sprite) |
| 1 | #800000 |
128 0 0 | Rosso scuro |
| 2 | #008000 |
0 128 0 | Verde scuro |
| 3 | #808000 |
128 128 0 | Oliva |
| 4 | #000080 |
0 0 128 | Blu scuro (ombra dell'acqua) |
| 5 | #800080 |
128 0 128 | Magenta scuro |
| 6 | #008080 |
0 128 128 | Ciano scuro |
| 7 | #808080 |
128 128 128 | Grigio medio |
| 8 | #C0DCC0 |
192 220 192 | Verde pallido |
| 9 | #5454FC |
84 84 252 | "Rosa magico" (trasparenza dell'editor) |
| 10–15 | #000000 × 6 |
0 0 0 | Riempimento riservato |
kbot pal describe palettes/palette.pal stampa la tabella completa.
Esempio svolto — palette.alp e palette.shd come tabelle di ricerca
Disegnando le tabelle con la palette come fonte dei colori
(kbot pal lookup … --cell 2):
palette.alp: 256 × 256 celle. La riga a, colonna b mostra la fusione dei colori a e b;
la diagonale riproduce ciascun colore.
palette.shd: 256 × 32 celle. Ogni colonna è un colore di partenza;
le righe vanno dal nero (riga 0), passano per il colore stesso e arrivano a tonalità più chiare.
Come leggere la tabella delle ombre: la colonna 80 (grigio medio) parte
dal nero nella riga 0, sale attraverso i grigi più scuri della sua
sfumatura, raggiunge sé stessa intorno alle righe 14 e 15 e poi si
schiarisce. Il motore non ha mai bisogno di moltiplicare valori RGB: legge
semplicemente shd[level][c].
Convertire le palette per gli editor
kbot pal convert conosce diversi formati di output adatti agli editor:
| Formato | Estensione | Strumento |
|---|---|---|
.PAL binario di TA |
.pal |
Il formato stesso; utile per riscriverlo dopo le modifiche. |
| GIMP Palette | .gpl |
GIMP, Krita, Inkscape. |
| JASC-PAL (testo) | .pal / .txt (--format jasc) |
Paint Shop Pro, Aseprite. |
| Campionario PNG | .png (tramite kbot pal swatch) |
Riferimento visivo; non si può caricare come palette. |
La direzione inversa, cioè importare un .gpl o un .pal (JASC) di nuovo
in un .pal binario di TA, funziona purché il file di partenza abbia 256
voci.
Note
La palette di TA contiene 13 terne RGB duplicate. Se il tuo editor
elimina i colori duplicati all'importazione (alcuni lo fanno), perderai
delle voci e la palette diventerà silenziosamente una palette di 243 voci.
kbot pal info riporta il numero di duplicati, così puoi accorgerti della
differenza; fai un round-trip con kbot pal convert -o roundtrip.pal per
verificare.
Insidie
Warning
Il 4° byte di ogni voce non è l'alfa. È un byte di riempimento
inutilizzato che Cavedog ha sempre impostato a 0x00. Diversi strumenti
open source per le palette lo leggono come alfa e poi non riescono a
disegnare la palette (alfa=0 ovunque ⇒ tutto trasparente). kbot lo ignora
in lettura e scrive 0x00 in scrittura.
- L'indice 0 non è trasparente di per sé. Terreno, minimappe e fondali lo disegnano nero; un frame di uno sprite è trasparente solo dove lo dice la sua chiave (o un run saltato). I rendering di terreno e minimappa di kbot usano una palette opaca.
- Niente magic number significa validazione debole. L'unico modo per
verificare la plausibilità di un
.palè richiedere almeno 1024 byte e (facoltativamente) che il byte dell'alfa sia zero in ogni voce. - Il gioco ignora una tabella di ricerca della dimensione sbagliata e la ricostruisce dalla palette.
.alp/.lht/.shdnon sono intercambiabili. Sono tarati per effetti diversi; scambiarli produce ombre o illuminazione visibilmente sbagliate.- TA: Kingdoms usa palette per fazione incorporate in file PCX, non il
flusso di lavoro con il
.palglobale. Vedi PCX per il trucco dei PCX che fanno da contenitori di palette.
Dimensioni tipiche
| File | Dimensione | Note |
|---|---|---|
palette.pal |
1.024 byte | Di un file più lungo il gioco legge i primi 1.024 byte. |
palette.alp |
65.536 byte | 256 × 256 indici della palette. |
palette.shd / palette.lht |
8.192 byte | 32 × 256 indici della palette. |
Esportazione GIMP .gpl |
~5 KB | Formato testuale, molto più grande del binario. |
Esportazione JASC .pal (testo) |
~3 KB | Idem. |
PNG di kbot pal swatch |
1–10 KB | Dipende dalla dimensione di --cell. |
| File di palette totali in TA standard | ~15 file | Un insieme canonico palette.* più alcune palette alternative per l'interfaccia. |