PAL / ALP / LHT / SHD: paletas e tabelas de consulta de cores
Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub
O Total Annihilation foi lançado com o mundo inteiro em 256 cores. O arquivo
.palguarda essa paleta; os arquivos.alp,.shde.lhtsão tabelas de consulta montadas a partir dela, que o motor usa para misturar, sombrear e iluminar pixels sem sair do espaço de cores indexadas.Nenhum dos quatro tem cabeçalho, campo de versão ou compressão. Um
.paltem 1.024 bytes (256 × RGBx); um.alptem 65.536 bytes (256 linhas de 256 índices da paleta), e.shd/.lhttêm 8.192 bytes cada (32 linhas de 256 índices da paleta).
palettes/palette.pal, renderizada pelo kbot pal swatch
Tip
Experimente você mesmo.
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 CLI.
Em 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)
}
Estrutura 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 da
seguinte forma (o pal.LoadNamed do kbot-io faz o mesmo, e o studio e o
explorador de recursos carregam palette.pal por meio dele em toda
renderização do TA: conjunto de blocos, minimapas, terreno da sandbox,
elementos, texturas e cores dos modelos):
- 1.024 bytes ou mais: os primeiros 1.024 bytes são a paleta; o resto é ignorado.
- Vazio ou ausente: a paleta vem de
palettes/<name>.pcx, ou seja, dos últimos 768 bytes desse arquivo, haja ou não um marcador0x0Cantes deles. O TA 3.1c então reconstrói as tabelas.alp,.shde.lhtpara essas cores. - De 1 a 1.023 bytes: inutilizável; o jogo lê 1.024 bytes, passando do fim do arquivo. O kbot informa um erro (e o studio volta à paleta do TA embutida).
.pal: a paleta canônica do TA
Os bytes R, G, B, A de cada entrada significam literalmente
vermelho, verde, azul, não usado. O índice 0 é um preto comum.
Blocos de terreno, minimapas e fundos o desenham opaco (62 dos 275 mapas
da versão comercial o usam em seus blocos). A transparência é decidida por imagem, não
pela paleta: o byte-chave de um quadro GAF (muitas vezes 9, às vezes 0) e
seus pixels pulados são transparentes, e as texturas dos modelos são
amostradas sem chave.
| Índice | Convenção do TA | Observações |
|---|---|---|
0 |
Preto | Opaco em terreno, minimapas e fundos; transparente só nos quadros de sprite cuja chave é 0. |
9 |
"Rosa mágico" | Usado pelas ferramentas de edição como cor de preenchimento das regiões transparentes em PCX/GAF antes da codificação; não é transparente durante o jogo. |
16–95 |
Ciclos de cor do jogador | O motor troca estes índices para cada lado, para recolorir as unidades. |
223–254 |
Reservados | Usados principalmente pelos ciclos de cor das equipes e por efeitos especiais. |
255 |
Branco puro | Muito usado no núcleo dos lasers. |
Note
Os 256 trios RGB não são arbitrários. A Cavedog ajustou a paleta à mão
para que existam rampas suaves para cada uma das principais famílias de
materiais (metal, orgânico, água, céu, lava, …). Trocar entradas para
introduzir uma cor "nova" num mod costuma estragar todas as unidades que
usavam aquela rampa. Veja na saída de pal describe como as rampas se
agrupam.
.alp / .shd / .lht: tabelas de consulta de cores
Estes três arquivos não são dados RGB: cada byte é um índice da paleta. Cada tabela tem uma linha de 256 entradas por cor parceira de mistura ou por nível, e suas colunas são as 256 cores de origem:
| Arquivo | 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 meio a meio, usada no desenho translúcido. É simétrica, e [c][c] é c. |
.shd (sombra) |
8.192 | 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, as linhas acima as clareiam. |
.lht (luz) |
8.192 | 32 | O índice mais próximo da cor c multiplicada por 1 + r/30, de 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 com aritmética: ele consulta uma tabela, e por isso o pixel resultante é sempre um índice real da paleta, que pode ser desenhado pelo fluxo de 8 bpp já existente. É por isso que todas as sombras do TA parecem uma versão mais escura da mesma rampa de cores, e não "50% de preto por cima": cada resultado sombreado é o índice da paleta mais próximo daquela mistura matemática.
O jogo só usa um arquivo de tabela quando o tamanho é exato; uma tabela
ausente ou de qualquer outro tamanho é reconstruída a partir da paleta. Por
isso o kbot pal lookup rejeita arquivos de qualquer outro tamanho. O TA:
Kingdoms traz tabelas dos mesmos tamanhos para quase todas as paletas da
pasta palettes/; a maioria dessas paletas são arquivos PCX, e o
kbot pal lookup --palette aceita um .pcx além de 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 eles realmente fazem, passando o
.pal correspondente para que cada célula da tabela seja colorida com a
entrada da paleta a que ela leva.
Exemplo comentado: palette.pal
As 16 primeiras entradas da paleta original do TA:
| Índ. | Hex | R G B | Papel |
|---|---|---|---|
| 0 | #000000 |
0 0 0 | Preto (opaco no terreno; a chave de alguns quadros de sprite) |
| 1 | #800000 |
128 0 0 | Vermelho-escuro |
| 2 | #008000 |
0 128 0 | Verde-escuro |
| 3 | #808000 |
128 128 0 | Oliva |
| 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 | Cinza médio |
| 8 | #C0DCC0 |
192 220 192 | Verde-claro |
| 9 | #5454FC |
84 84 252 | "Rosa mágico" (transparência do editor) |
| 10–15 | #000000 × 6 |
0 0 0 | Preenchimento reservado |
O kbot pal describe palettes/palette.pal imprime a tabela completa.
Exemplo comentado: palette.alp e palette.shd como tabelas de consulta
Renderizando as tabelas com a paleta como fonte de cores
(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), passam pela própria cor e chegam a tons mais claros.
Como ler a tabela de sombras: a coluna 80 (cinza médio) começa preta na
linha 0, sobe pelos cinzas mais escuros da sua rampa, chega à própria cor por
volta das linhas 14 e 15 e depois clareia. O motor nunca precisa multiplicar
valores RGB: ele só lê shd[level][c].
Converter paletas para editores
O kbot pal convert entende 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 gravar de novo depois de 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 trios RGB duplicados. Se o seu editor elimina
cores duplicadas ao importar (alguns fazem isso), você perde entradas e a
paleta vira, sem aviso, uma paleta de 243 entradas. O kbot pal info
informa quantas duplicatas existem, para você notar a diferença; faça uma
ida e volta com kbot pal convert -o roundtrip.pal para conferir.
Armadilhas
Warning
O 4º byte de cada entrada não é alfa. É um byte de preenchimento não
usado, que a Cavedog sempre deixou em 0x00. Várias ferramentas de paleta
de código aberto o leem como alfa e depois se recusam a renderizar a paleta
(alfa=0 em tudo ⇒ tudo transparente). O kbot o ignora na leitura e grava
0x00.
- O índice 0 não é transparente por si só. Terreno, minimapas e fundos o desenham como preto; um quadro de sprite só é transparente onde a sua própria chave (ou trecho pulado) diz que é. 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 conferir um
.palé exigir pelo menos 1.024 bytes e (opcionalmente) que o byte alfa seja zero em todas as entradas. - O jogo ignora uma tabela de consulta de tamanho errado e a reconstrói a partir da paleta.
.alp/.lht/.shdnão são intercambiáveis. Cada um é ajustado para um efeito diferente; trocá-los produz sombras ou iluminação visivelmente erradas.- O TA: Kingdoms usa paletas por lado embutidas em PCX, e não o fluxo do
.palglobal. Veja PCX para o truque do PCX portador.
Tamanhos típicos
| Arquivo | Tamanho | Observações |
|---|---|---|
palette.pal |
1.024 bytes | O jogo lê os primeiros 1.024 bytes de um arquivo maior. |
palette.alp |
65.536 bytes | 256 × 256 índices da paleta. |
palette.shd / palette.lht |
8.192 bytes | 32 × 256 índices da paleta. |
Exportação .gpl do GIMP |
~5 KB | Formato de texto, bem maior 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 arquivos de paleta no TA original | ~15 arquivos | Um conjunto canônico palette.* e algumas paletas alternativas da interface. |