PAL / ALP / LHT / SHD — paletas e tabelas de consulta de cores
Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub
O Total Annihilation desenhava o seu mundo inteiro com 256 cores. O ficheiro
.palguarda essa paleta; os ficheiros.alp,.shde.lhtsão tabelas de consulta construídas a partir dela, que o motor usa para misturar, sombrear e iluminar píxeis sem sair do espaço de cor indexada.Nenhum dos quatro tem cabeçalho, campo de versão ou compressão. Um
.paltem 1024 bytes (256 × RGBx); um.alptem 65 536 bytes (256 linhas de 256 índices da paleta) e os.shd/.lhttêm 8192 bytes cada (32 linhas de 256 índices da paleta).
palettes/palette.pal — renderizada pelo kbot pal swatch
Tip
Experimente por si.
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
Veja a referência de kbot pal
da linha de comandos.
A partir de Go. Use 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)
}
Disposição no 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
Não há assinatura nem versão. O jogo carrega palettes/<name>.pal desta
forma (o pal.LoadNamed do kbot-io faz o mesmo, e o estúdio e o
explorador de recursos carregam o palette.pal através dele em todas as
renderizações do TA: conjunto de mosaicos, minimapas, terreno da sandbox,
elementos, texturas e cores dos modelos):
- 1024 bytes ou mais: os primeiros 1024 bytes são a paleta; o resto é ignorado.
- Vazio ou em falta: a paleta vem de
palettes/<name>.pcx, ou seja, dos últimos 768 bytes desse ficheiro, haja ou não um marcador0x0Cantes deles. O TA 3.1c reconstrói depois as tabelas.alp,.shde.lhtpara essas cores. - De 1 a 1023 bytes: não é utilizável; o jogo lê 1024 bytes e ultrapassa o fim do ficheiro. O kbot reporta um erro (e o estúdio recorre à paleta do TA incorporada).
.pal — a paleta canónica do TA
Os bytes R, G, B, A de cada entrada significam literalmente
vermelho, verde, azul, sem uso. O índice 0 é um preto
normal. Os mosaicos do terreno, os minimapas e os fundos desenham-no
opaco (62 dos 275 mapas comerciais usam-no nos seus mosaicos). A
transparência é decidida imagem a imagem, não pela paleta: o byte de
chave de um fotograma GAF (muitas vezes 9, às vezes 0) e os píxeis que o
fotograma salta são transparentes, e as texturas dos modelos são
amostradas sem chave.
| Índice | Convenção do TA | Notas |
|---|---|---|
0 |
Preto | Opaco no terreno, nos minimapas e nos fundos; só é transparente nos fotogramas de sprites cuja chave é 0. |
9 |
"Rosa mágico" | Usado pelas ferramentas de edição como cor de preenchimento das zonas transparentes em PCX/GAF antes da codificação; não é transparente durante a execução. |
16–95 |
Ciclos de cor dos jogadores | O motor substitui-os conforme o lado para mudar a cor das unidades. |
223–254 |
Reservados | Usados sobretudo pelos ciclos de cor das equipas e por efeitos especiais. |
255 |
Branco puro | Usado muitas vezes no núcleo dos lasers. |
Note
Os 256 triplos RGB não são arbitrários. A Cavedog afinou a paleta à
mão para que existissem rampas suaves para cada uma das principais
famílias de materiais (metal, orgânico, água, céu, lava, …). Substituir
entradas para meter uma cor "nova" costuma estragar todas as unidades
que usavam essa rampa. Veja a saída de pal describe para os
agrupamentos das rampas.
.alp / .shd / .lht — tabelas de consulta de cores
Estes três ficheiros não são dados RGB: cada byte é um índice da paleta. Cada tabela tem uma linha de 256 entradas por cor de mistura ou por nível, e as suas colunas são as 256 cores de origem:
| Ficheiro | Tamanho | Linhas | Entrada [r][c] |
|---|---|---|---|
.alp (alfa) |
65 536 | 256 | O índice mais próximo da média das cores r e c: uma mistura a meias, usada para desenhar com translucidez. É simétrica, e [c][c] é c. |
.shd (sombra) |
8192 | 32 | O índice mais próximo da cor c multiplicada por r × 0.06875: a linha 0 é preta, as linhas 14–15 deixam as cores quase inalteradas e as linhas mais altas tornam-nas mais claras. |
.lht (luz) |
8192 | 32 | O índice mais próximo da cor c multiplicada por 1 + r/30, desde inalterada (linha 0) até cerca do dobro do brilho. |
uint8 alp[256][256]; // blend = alp[a][b]
uint8 shd[32][256]; // shaded = shd[level][c]
uint8 lht[32][256]; // lit = lht[level][c]
Na prática, o motor nunca mistura cores aritmeticamente: faz uma consulta à tabela, por isso o píxel resultante é sempre um índice real da paleta, que pode ser desenhado pelo processo de 8 bpp existente. É por isso que todas as sombras do TA parecem uma versão mais escura da mesma rampa de cores, e não "preto a 50 % por cima": cada resultado sombreado é o índice da paleta mais próximo dessa mistura matemática.
O jogo só usa um ficheiro de tabela quando o tamanho é exato; uma tabela
em falta, ou com qualquer outro tamanho, é reconstruída a partir da
paleta. Por isso, o kbot pal lookup rejeita ficheiros de qualquer outro
tamanho. O TA: Kingdoms inclui tabelas destes mesmos tamanhos para quase
todas as paletas da sua pasta palettes/; a maioria dessas paletas são
ficheiros PCX, e o kbot pal lookup --palette aceita tanto um .pcx
como um .pal.
Important
Uma tabela de consulta não é uma paleta. Renderizar um .alp com
kbot pal describe mostra valores RGB sem sentido, porque os bytes não
são RGB. Use kbot pal lookup para ver o que fazem de facto: passe o
.pal associado para que cada célula da tabela possa ser colorida
com a entrada da paleta a que corresponde.
Exemplo comentado — palette.pal
As primeiras 16 entradas da paleta original do TA:
| Índ. | Hex | R G B | Função |
|---|---|---|---|
| 0 | #000000 |
0 0 0 | Preto (opaco no terreno; a chave de alguns fotogramas de sprites) |
| 1 | #800000 |
128 0 0 | Vermelho escuro |
| 2 | #008000 |
0 128 0 | Verde escuro |
| 3 | #808000 |
128 128 0 | Verde-azeitona |
| 4 | #000080 |
0 0 128 | Azul escuro (sombra da água) |
| 5 | #800080 |
128 0 128 | Magenta escuro |
| 6 | #008080 |
0 128 128 | Ciano escuro |
| 7 | #808080 |
128 128 128 | Cinzento médio |
| 8 | #C0DCC0 |
192 220 192 | Verde-claro |
| 9 | #5454FC |
84 84 252 | "Rosa mágico" (transparência dos editores) |
| 10–15 | #000000 × 6 |
0 0 0 | Preenchimento reservado |
kbot pal describe palettes/palette.pal imprime a tabela completa.
Exemplo comentado — palette.alp e palette.shd como tabelas de consulta
Renderização das tabelas usando a paleta como fonte de cor
(kbot pal lookup … --cell 2):
palette.alp: 256 × 256 células. A linha a, coluna b mostra a mistura das cores a e b;
a diagonal reproduz cada cor.
palette.shd: 256 × 32 células. Cada coluna é uma cor de origem;
as linhas vão do preto (linha 0), passando pela própria cor, até tons mais claros.
Como ler a tabela de sombras: a coluna 80 (cinzento médio) começa preta
na linha 0, sobe pelos cinzentos mais escuros da sua rampa, chega à
própria cor por volta das linhas 14 e 15 e depois fica mais clara. O
motor nunca precisa de multiplicar valores RGB: limita-se a ler
shd[level][c].
Converter paletas para editores
O kbot pal convert conhece vários formatos de saída fáceis de usar em
editores:
| Formato | Extensão | Ferramenta |
|---|---|---|
.PAL binário do TA |
.pal |
O próprio formato; útil para voltar a gerar o ficheiro depois de o editar. |
| Paleta do GIMP | .gpl |
GIMP, Krita, Inkscape. |
| JASC-PAL (texto) | .pal / .txt (--format jasc) |
Paint Shop Pro, Aseprite. |
| Amostra em PNG | .png (via kbot pal swatch) |
Referência visual; não pode ser carregada como paleta. |
O sentido inverso, importar um .gpl ou um .pal (JASC) de volta para
um .pal binário do TA, funciona desde que a origem tenha 256 entradas.
Note
A paleta do TA tem 13 triplos RGB duplicados. Se o seu editor
eliminar cores duplicadas ao importar (alguns fazem-no), perde entradas
e a paleta passa, sem aviso, a ter 243 entradas. O kbot pal info
indica o número de duplicados para que possa detetar a diferença; faça
uma ida e volta com kbot pal convert -o roundtrip.pal para confirmar.
Armadilhas
Warning
O quarto byte de cada entrada não é alfa. É um byte de
preenchimento sem uso que a Cavedog pôs sempre a 0x00. Várias
ferramentas de paletas de código aberto leem-no como alfa e depois não
conseguem renderizar a paleta (alfa=0 em todo o lado ⇒ tudo
transparente). O kbot ignora-o na leitura e escreve 0x00 na escrita.
- O índice 0 não é transparente por si só. O terreno, os minimapas e os fundos desenham-no a preto; um fotograma de sprite só é transparente onde a sua própria chave (ou uma série de salto) o diz. As renderizações de terreno e de minimapa do kbot usam uma paleta opaca.
- Sem números mágicos, a validação é fraca. A única forma de
verificar se um
.palfaz sentido é exigir pelo menos 1024 bytes e (opcionalmente) que o byte alfa seja zero em todas as entradas. - O jogo ignora uma tabela de consulta com o tamanho errado e reconstrói-a a partir da paleta.
.alp/.lht/.shdnão são intercambiáveis. Estão afinados para efeitos diferentes; trocá-los produz sombras ou iluminação visivelmente erradas.- O TA: Kingdoms usa paletas incorporadas em PCX, uma por lado, e não
o fluxo de trabalho do
.palglobal. Veja PCX para o truque do PCX que transporta a paleta.
Tamanhos típicos
| Ficheiro | Tamanho | Notas |
|---|---|---|
palette.pal |
1024 bytes | O jogo lê os primeiros 1024 bytes de um ficheiro mais comprido. |
palette.alp |
65 536 bytes | 256 × 256 índices da paleta. |
palette.shd / palette.lht |
8192 bytes | 32 × 256 índices da paleta. |
Exportação .gpl do GIMP |
~5 KB | Formato de texto, muito maior do que o binário. |
Exportação .pal JASC (texto) |
~3 KB | Idem. |
PNG do kbot pal swatch |
1–10 KB | Depende do tamanho de --cell. |
| Total de ficheiros de paleta no TA original | ~15 ficheiros | Um conjunto canónico palette.* e algumas paletas alternativas da interface. |