すべての形式のページ ↓
グラフィックとメディア

PAL / ALP / LHT / SHD — パレットと色のルックアップテーブル

出典:coreprime/kbot @ 0ab97bf · GitHubで編集

Total Annihilationは、その世界のすべてを256色で描いていました。.palファイルはそのパレットを格納し、.alp、.shd、.lhtの各ファイルは、そこから作られたルックアップテーブルです。エンジンはこれらを使い、インデックスカラーの色空間から出ることなく、ピクセルの混色、陰影付け、明るさの調整を行います。

4つのどれにも、ヘッダー、バージョンのフィールド、圧縮はありません。.palは1,024バイト(256 × RGBx)、.alpは65,536バイト(256個のパレットインデックスが256行)、.shd / .lhtはそれぞれ8,192バイト(256個のパレットインデックスが32行)です。

TAパレットの色見本(256色、24pxのセル)
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を次のように読み込みます(kbot-ioのpal.LoadNamedも同じ処理を行い、スタジオとアセットエクスプローラーは、TAのあらゆる描画でこれを通じてpalette.palを読み込みます。タイルプール、ミニマップ、サンドボックスの地形、地形物、テクスチャ、モデルの色がその対象です)。

  • 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はごく普通の黒です。地形のタイル、ミニマップ、背景はこれを不透明で描きます(製品版の275のマップのうち62がタイルにこれを使っています)。透過はパレットではなく画像ごとに決まります。GAFのフレームのキーのバイト(多くは9、ときに0)とスキップされたピクセルが透過になり、モデルのテクスチャはキーなしでサンプリングされます。

インデックス TAでの慣習 備考
0 黒 地形、ミニマップ、背景では不透明。キーが0のスプライトのフレームでだけ透過。
9 「マジックピンク」 エディター系のツールが、エンコード前のPCX/GAFで透過にする領域の塗りつぶし色として使う。実行時には透過にならない。
16–95 プレイヤーカラーの循環 エンジンが陣営ごとにこれを入れ替えて、ユニットの色を変える。
223–254 予約 主にチームカラーの循環と特殊効果に使われる。
255 純白 レーザーの芯によく使われる。

Note

256個のRGBの3つ組は、適当に決められたものではありません。Cavedogはパレットを手作業で調整し、主な素材の系統(金属、有機物、水、空、溶岩など)ごとになめらかなグラデーションが得られるようにしています。「新しい」色を入れるためにエントリを置き換えると、たいていはそのグラデーションを使って描かれていたユニットがすべて崩れます。グラデーションのまとまりについてはpal describeの出力を参照してください。


.alp / .shd / .lht — 色のルックアップテーブル

この3つのファイルはRGBのデータではありません。どのバイトもパレットインデックスです。各テーブルは、混色の相手または段階ごとに256エントリの行を1つ持ち、列は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)から、約2倍の明るさまで。
uint8 alp[256][256];   // blend = alp[a][b]
uint8 shd[32][256];    // shaded = shd[level][c]
uint8 lht[32][256];    // lit    = lht[level][c]

実際のところ、エンジンは色を算術的に混ぜることは一切なく、テーブルを引くだけです。そのため、得られるピクセルは常に実在するパレットインデックスで、既存の8bppの描画パイプラインでそのまま描けます。TAの影がどれも「50 %の黒を重ねた」ものではなく、同じグラデーションの暗いものに見えるのはこのためです。陰影付けの結果はそれぞれ、計算上の混色に最も近いパレットインデックスなのです。

ゲームがテーブルのファイルを使うのは、サイズが正確な場合だけです。テーブルがない場合や、ほかのサイズのテーブルは、パレットから作り直されます。そのため、kbot pal lookupはほかのサイズのファイルを受け付けません。TA: Kingdomsは、palettes/フォルダーにあるほぼすべてのパレットについて同じサイズのテーブルを同梱しています。それらのパレットの多くはPCXファイルで、kbot pal lookup --paletteは.palだけでなく.pcxも受け付けます。

Important

ルックアップテーブルはパレットではありません。.alpをkbot pal describeで描画すると、バイトがRGBではないため、でたらめなRGB値が表示されます。実際に何をしているかを見るにはkbot pal lookupを使ってください。対になる.palを渡すと、ルックアップの各セルを、それが指すパレットのエントリの色で塗ることができます。


実例 — palette.pal

標準のTAパレットの最初の16エントリ:

インデックス 16進 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.palを通して可視化したpalette.alp
palette.alp:256 × 256セル。行a、列bには色aとbの混色が表示されます。
対角線上には各色がそのまま現れます。

palette.palを通して可視化したpalette.shd
palette.shd:256 × 32セル。各列が元の色です。
行は黒(行0)から始まり、その色自身を経て、より明るい色調へと進みます。

陰影のテーブルの読み方:列80(中間の灰色)は、行0では黒から始まり、そのグラデーションのより暗い灰色を経て、行14と15のあたりで自分自身の色に達し、そこから明るくなっていきます。エンジンはRGBの値を掛け算する必要がなく、shd[level][c]を読むだけです。


エディター向けのパレット変換

kbot pal convertは、エディターで扱いやすいいくつかの出力形式に対応しています。

形式 拡張子 ツール
バイナリのTA .PAL .pal この形式そのもの。編集後に書き出し直すときに便利。
GIMPパレット .gpl GIMP、Krita、Inkscape。
JASC-PAL(テキスト) .pal / .txt(--format jasc) Paint Shop Pro、Aseprite。
PNGの色見本 .png(kbot pal swatchで出力) 目で見るための参考。パレットとしては読み込めない。

逆方向、つまり.gplや.pal(JASC)をバイナリのTA .palに読み込み直す変換も、元のファイルに256エントリあれば機能します。

Note

TAのパレットには、重複したRGBの3つ組が13個あります。エディターが読み込み時に色の重複を除くと(そうするものもあります)、エントリが失われ、パレットは知らないうちに243エントリのパレットになってしまいます。kbot pal infoは重複の数を報告するので、違いに気づくことができます。確認するにはkbot pal convert -o roundtrip.palでラウンドトリップしてください。


注意点

Warning

各エントリの4バイト目はアルファではありません。Cavedogが常に0x00にしていた、使われない埋め草のバイトです。オープンソースのパレットツールのいくつかはこれをアルファとして読み、パレットを描画できなくなります(どこでもalpha=0 ⇒ すべて透過)。kbotは読み込み時にこれを無視し、書き出し時には0x00を出力します。

  • インデックス0は、それだけでは透過になりません。地形、ミニマップ、背景はこれを黒として描きます。スプライトのフレームが透過になるのは、そのフレーム自身のキー(またはスキップのラン)が指定する場所だけです。kbotの地形とミニマップの描画では、不透明のパレットを使います。
  • マジックナンバーがないので、検証は弱くなります。.palの妥当性を確かめる方法は、少なくとも1024バイトあることと、(任意で)すべてのエントリでアルファのバイトが0であることを求めることくらいです。
  • サイズの違うルックアップテーブルはゲームに無視され、パレットから作り直されます。
  • .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 KB テキスト形式で、バイナリよりずっと大きい。
JASCの.pal(テキスト)への書き出し 約3 KB 同上。
kbot pal swatchのPNG 1–10 KB --cellのサイズによる。
標準のTAに含まれるパレットファイルの合計 約15ファイル 正規のpalette.*一式と、UI用の別パレットがいくつか。

関連項目

  • PCX:パレットを埋め込んだファイル(とTA:Kのパレットを運ぶ慣習)。
  • GAF:パレットを使うものの、パレット自体は含まないアニメーション。
  • TNT、SCT:ディスク上のパレット付きタイルデータ。
  • 用語集:paletted image(パレット付き画像)、lookup table(ルックアップテーブル)。