Alle Formatseiten ↓
Grafik und Medien

PAL / ALP / LHT / SHD – Paletten und Farb-Nachschlagetabellen

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

Total Annihilation hat seine gesamte Welt in 256 Farben ausgeliefert. Die .pal-Datei enthält diese Palette; die Dateien .alp, .shd und .lht sind daraus abgeleitete Nachschlagetabellen, mit denen die Engine Pixel überblendet, abschattet und aufhellt, ohne den Raum der indizierten Farben zu verlassen.

Keine der vier hat einen Header, ein Versionsfeld oder Kompression. Eine .pal ist 1.024 Byte groß (256 × RGBx); .alp hat 65.536 Byte (256 Zeilen mit je 256 Palettenindizes), .shd / .lht haben je 8.192 Byte (32 Zeilen mit je 256 Palettenindizes).

Farbtafel der TA-Palette (256 Farben, Zellen zu 24 px)
palettes/palette.pal – gerendert mit kbot pal swatch

Tip

Probier es selbst.

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

Siehe die kbot pal-Referenz der CLI.

Aus Go heraus. Verwende 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)
}

Aufbau auf der Platte (.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

Es gibt weder Signatur noch Version. Das Spiel lädt palettes/<name>.pal so (pal.LoadNamed aus kbot-io macht es genauso, und Studio und Asset-Explorer laden palette.pal darüber für jedes Rendering von TA: Kachelvorrat, Minikarten, Gelände der Sandbox, Kartenobjekte, Texturen und Modellfarben):

  • 1.024 Byte oder mehr: Die ersten 1.024 Byte sind die Palette; der Rest wird ignoriert.
  • Leer oder fehlend: Die Palette kommt stattdessen aus palettes/<name>.pcx – aus den letzten 768 Byte dieser Datei, ob ihnen nun ein Marker 0x0C vorausgeht oder nicht. TA 3.1c baut dann die Tabellen .alp, .shd und .lht für diese Farben neu auf.
  • 1 bis 1.023 Byte: nicht verwendbar; das Spiel liest 1.024 Byte über das Ende der Datei hinaus. kbot meldet einen Fehler (und das Studio greift auf die eingebaute Palette von TA zurück).

.pal – die kanonische Palette von TA

Die Bytes R, G, B, A pro Eintrag bedeuten wörtlich Rot, Grün, Blau, unbenutzt. Index 0 ist gewöhnliches Schwarz. Geländekacheln, Minikarten und Hintergründe zeichnen ihn deckend (62 der 275 Karten der Verkaufsversion verwenden ihn in ihren Kacheln). Über Transparenz wird pro Bild entschieden, nicht durch die Palette: Das Schlüsselbyte eines GAF-Frames (oft 9, manchmal 0) und seine übersprungenen Pixel sind transparent, und Modelltexturen werden ohne Schlüssel abgetastet.

Index Konvention in TA Anmerkungen
0 Schwarz Deckend in Gelände, Minikarten und Hintergründen; transparent nur in Sprite-Frames, deren Schlüssel 0 ist.
9 „Magic Pink“ Wird von Editor-Werkzeugen vor dem Kodieren als Füllfarbe für transparente Bereiche in PCX/GAF verwendet; zur Laufzeit nicht transparent.
16–95 Zyklen der Spielerfarben Die Engine tauscht diese pro Seite aus, um Einheiten umzufärben.
223–254 Reserviert Meist von Zyklen der Teamfarben und Spezialeffekten verwendet.
255 Reines Weiß Oft für die Kerne von Laserstrahlen verwendet.

Note

Die 256 RGB-Tripel sind nicht willkürlich. Cavedog hat die Palette von Hand so abgestimmt, dass es für jede der wichtigen Materialfamilien (Metall, Organisches, Wasser, Himmel, Lava, …) gleichmäßige Farbrampen gibt. Einträge zu ersetzen, um eine „neue“ Farbe hineinzumodden, macht meist jede Einheit kaputt, die aus dieser Farbrampe gezeichnet hat. Die Gruppierung der Farbrampen zeigt die Ausgabe von pal describe.


.alp / .shd / .lht – Farb-Nachschlagetabellen

Diese drei Dateien sind keine RGB-Daten: Jedes Byte ist ein Palettenindex. Jede Tabelle hat eine Zeile mit 256 Einträgen pro Mischpartner oder Stufe, und ihre Spalten sind die 256 Ausgangsfarben:

Datei Größe Zeilen Eintrag [r][c]
.alp (Alpha) 65.536 256 Der Index, der dem Mittelwert der Farben r und c am nächsten liegt: eine Mischung zu gleichen Teilen, verwendet für durchscheinendes Zeichnen. Symmetrisch, und [c][c] ist c.
.shd (Schatten) 8.192 32 Der Index, der der Farbe c, skaliert mit r × 0.06875, am nächsten liegt: Zeile 0 ist schwarz, die Zeilen 14–15 lassen die Farben nahezu unverändert, höhere Zeilen hellen sie auf.
.lht (Licht) 8.192 32 Der Index, der der Farbe c, skaliert mit 1 + r/30, am nächsten liegt, von unverändert (Zeile 0) bis etwa doppelt so hell.
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 der Praxis heißt das: Die Engine mischt Farben nie arithmetisch – sie schlägt in einer Tabelle nach, das resultierende Pixel ist also immer ein echter Palettenindex, der durch die vorhandene 8-bpp-Pipeline gezeichnet werden kann. Deshalb sehen alle Schatten in TA wie eine dunklere Version derselben Farbrampe aus und nicht wie „50 % Schwarz darübergelegt“: Jedes abgeschattete Ergebnis ist der Palettenindex, der dieser mathematischen Mischung am nächsten kommt.

Das Spiel verwendet eine Tabellendatei nur, wenn ihre Größe exakt stimmt; eine fehlende Tabelle oder eine mit irgendeiner anderen Größe wird aus der Palette neu aufgebaut. kbot pal lookup weist deshalb Dateien jeder anderen Größe ab. TA: Kingdoms liefert für fast jede Palette in seinem Ordner palettes/ Tabellen derselben Größen aus; die meisten dieser Paletten sind PCX-Dateien, und kbot pal lookup --palette nimmt eine .pcx ebenso wie eine .pal.

Important

Eine Nachschlagetabelle ist keine Palette. Wenn du eine .alp mit kbot pal describe renderst, siehst du unsinnige RGB-Werte, weil die Bytes kein RGB sind. Mit kbot pal lookup siehst du, was sie tatsächlich tun – übergib die zugehörige .pal, damit jede Zelle der Tabelle mit dem Paletteneintrag eingefärbt werden kann, auf den sie verweist.


Beispiel im Detail – palette.pal

Die ersten 16 Einträge der Originalpalette von TA:

Idx Hex R G B Rolle
0 #000000 0 0 0 Schwarz (deckend im Gelände; der Schlüssel mancher Sprite-Frames)
1 #800000 128 0 0 Dunkelrot
2 #008000 0 128 0 Dunkelgrün
3 #808000 128 128 0 Oliv
4 #000080 0 0 128 Dunkelblau (Wasserschatten)
5 #800080 128 0 128 Dunkelmagenta
6 #008080 0 128 128 Dunkelcyan
7 #808080 128 128 128 Mittelgrau
8 #C0DCC0 192 220 192 Blassgrün
9 #5454FC 84 84 252 „Magic Pink“ (Transparenz im Editor)
10–15 #000000 × 6 0 0 0 Reservierte Auffüllung

kbot pal describe palettes/palette.pal gibt die vollständige Tabelle aus.


Beispiel im Detail – palette.alp und palette.shd als Nachschlagetabellen

Die Tabellen, gerendert mit der Palette als Farbquelle (kbot pal lookup … --cell 2):

palette.alp, dargestellt über palette.pal
palette.alp: 256 × 256 Zellen. Zeile a, Spalte b zeigt die Mischung der Farben a und b;
die Diagonale gibt jede Farbe selbst wieder.

palette.shd, dargestellt über palette.pal
palette.shd: 256 × 32 Zellen. Jede Spalte ist eine Ausgangsfarbe;
die Zeilen reichen von Schwarz (Zeile 0) über die Farbe selbst bis zu helleren Tönen.

So liest man die Schattentabelle: Spalte 80 (Mittelgrau) beginnt in Zeile 0 schwarz, steigt durch dunklere Grautöne ihrer Farbrampe an, erreicht sich selbst etwa in den Zeilen 14 und 15 und wird dann heller. Die Engine muss nie RGB-Werte multiplizieren – sie liest einfach shd[level][c].


Paletten für Editoren konvertieren

kbot pal convert beherrscht mehrere editorfreundliche Ausgabeformate:

Format Endung Werkzeug
Binäre .PAL von TA .pal Das Format selbst; nützlich, um nach Bearbeitungen neu auszugeben.
GIMP-Palette .gpl GIMP, Krita, Inkscape.
JASC-PAL (Text) .pal / .txt (--format jasc) Paint Shop Pro, Aseprite.
PNG-Farbtafel .png (über kbot pal swatch) Visuelle Referenz; nicht als Palette ladbar.

Die Gegenrichtung – eine .gpl oder .pal (JASC) wieder in eine binäre .pal von TA importieren – funktioniert, solange die Quelle 256 Einträge hat.

Note

Die Palette von TA enthält 13 doppelte RGB-Tripel. Wenn dein Editor beim Import doppelte Farben entfernt (manche tun das), verlierst du Einträge, und die Palette wird stillschweigend zu einer mit 243 Einträgen. kbot pal info meldet die Anzahl der Duplikate, damit du den Unterschied bemerkst; mach zur Prüfung einen Round-Trip über kbot pal convert -o roundtrip.pal.


Stolperfallen

Warning

Das 4. Byte pro Eintrag ist kein Alpha. Es ist ein unbenutztes Füllbyte, das Cavedog immer auf 0x00 gesetzt hat. Mehrere Open-Source-Werkzeuge für Paletten lesen es als Alpha und rendern die Palette dann nicht (überall alpha=0 ⇒ alles transparent). kbot ignoriert es beim Lesen und gibt beim Schreiben 0x00 aus.

  • Index 0 ist nicht von sich aus transparent. Gelände, Minikarten und Hintergründe zeichnen ihn schwarz; ein Sprite-Frame ist nur dort transparent, wo sein eigener Schlüssel (oder Überspring-Lauf) es sagt. Die Gelände- und Minikarten-Renderings von kbot verwenden eine deckende Palette.
  • Ohne Magic Numbers ist die Prüfung schwach. Die einzige Plausibilitätsprüfung für eine .pal besteht darin, mindestens 1.024 Byte zu verlangen und (optional), dass das Alpha-Byte in jedem Eintrag null ist.
  • Eine Nachschlagetabelle der falschen Größe ignoriert das Spiel und baut sie aus der Palette neu auf.
  • .alp / .lht / .shd sind nicht austauschbar. Sie sind auf unterschiedliche Effekte abgestimmt; vertauscht man sie, entstehen sichtbar falsche Schatten oder Aufhellungen.
  • TA: Kingdoms verwendet in PCX eingebettete Paletten pro Seite, nicht den Weg über die globale .pal. Den Trick mit dem Träger-PCX beschreibt PCX.

Typische Größen

Datei Größe Anmerkungen
palette.pal 1.024 Byte Von einer längeren Datei liest das Spiel die ersten 1.024 Byte.
palette.alp 65.536 Byte 256 × 256 Palettenindizes.
palette.shd / palette.lht 8.192 Byte 32 × 256 Palettenindizes.
GIMP-Export .gpl ~5 KB Textformat, viel größer als binär.
JASC-Export .pal (Text) ~3 KB Ebenso.
PNG von kbot pal swatch 1–10 KB Hängt von der Größe --cell ab.
Palettendateien im Original-TA insgesamt ~15 Dateien Ein kanonischer Satz palette.* plus ein paar alternative Oberflächenpaletten.

Siehe auch

  • PCX – Dateien mit eingebetteten Paletten (und die Konvention der Palettenträger in TA:K).
  • GAF – Animationen, die eine Palette verwenden, aber keine enthalten.
  • TNT, SCT – palettierte Kacheldaten auf der Platte.
  • Glossar – paletted image, lookup table.