PAL / ALP / LHT / SHD — 팔레트와 색상 조회 테이블
Total Annihilation은 세계 전체를 256색으로 담아 출시했습니다.
.pal파일은 그 팔레트를 담고,.alp,.shd,.lht파일은 그 팔레트로 만든 조회 테이블입니다. 엔진은 이 테이블로 인덱스 색상 공간을 벗어나지 않고 픽셀을 섞거나 어둡게 하거나 밝게 합니다.네 가지 모두 헤더, 버전 필드, 압축이 없습니다.
.pal은 1,024바이트(256 × RGBx)이고,.alp는 65,536바이트(팔레트 인덱스 256개짜리 행 256개),.shd/.lht는 각각 8,192바이트(팔레트 인덱스 256개짜리 행 32개)입니다.
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 세 값 조합은 임의로 고른 것이 아닙니다. Cavedog은 주요 재질
계열(금속, 유기물, 물, 하늘, 용암 등)마다 부드러운 색 계조가 있도록 팔레트를
손으로 조정했습니다. "새" 색을 넣으려고 항목을 바꾸면 대개 그 계조를 쓰던 모든
유닛이 망가집니다. 계조별 묶음은 pal describe의 출력을 참고하세요.
.alp / .shd / .lht — 색상 조회 테이블
이 세 파일은 RGB 데이터가 아닙니다: 모든 바이트가 팔레트 인덱스입니다. 각 테이블에는 섞을 상대 색이나 단계마다 256개 항목짜리 행이 하나씩 있고, 열은 256개의 원본 색입니다.
| 파일 | 크기 | 행 | 항목 [r][c] |
|---|---|---|---|
.alp(알파) |
65,536 | 256 | 색 r과 c의 평균에 가장 가까운 인덱스: 반반 섞기로, 반투명하게 그릴 때 씁니다. 대칭이며 [c][c]는 c입니다. |
.shd(그늘) |
8,192 | 32 | 색 c에 r × 0.06875를 곱한 것에 가장 가까운 인덱스: 행 0은 검은색, 행 14–15는 색을 거의 바꾸지 않고, 더 높은 행은 밝게 합니다. |
.lht(빛) |
8,192 | 32 | 색 c에 1 + r/30을 곱한 것에 가장 가까운 인덱스로, 그대로(행 0)부터 약 두 배 밝기까지입니다. |
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.alp: 256 × 256 칸. 행 a, 열 b는 색 a와 b를 섞은 결과를 보여 주며,
대각선은 각 색을 그대로 재현합니다.
palette.shd: 256 × 32 칸. 각 열은 원본 색이며,
행은 검은색(행 0)에서 그 색 자체를 거쳐 더 밝은 색조로 이어집니다.
그늘 테이블 읽는 법: 열 80(중간 회색)은 행 0에서 검은색으로 시작해 자기 계조의
더 어두운 회색들을 거쳐 올라가고, 행 14와 15 근처에서 자기 자신에 도달한 뒤 더
밝아집니다. 엔진은 RGB 값을 곱할 필요가 전혀 없습니다 — shd[level][c]를 읽기만
하면 됩니다.
에디터용으로 팔레트 변환하기
kbot pal convert는 에디터에서 쓰기 좋은 여러 출력 형식을 지원합니다.
| 형식 | 확장자 | 도구 |
|---|---|---|
바이너리 TA .PAL |
.pal |
형식 그 자체. 편집 후 다시 내보낼 때 유용합니다. |
| GIMP Palette | .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 세 값 조합이 13개 있습니다. 에디터가 가져올 때
색 중복을 제거하면(일부는 그렇게 함) 항목을 잃고, 팔레트는 소리 없이 항목
243개짜리 팔레트가 됩니다. kbot pal info가 중복 개수를 보고하므로 차이를
알아챌 수 있습니다. 검증하려면 kbot pal convert -o roundtrip.pal로 왕복
변환해 보세요.
주의할 점
Warning
항목마다 있는 네 번째 바이트는 알파가 아닙니다. Cavedog이 항상 0x00으로
설정한, 쓰이지 않는 패딩 바이트입니다. 여러 오픈 소스 팔레트 도구가 이를
알파로 읽은 다음 팔레트를 제대로 렌더링하지 못합니다(모든 곳이 alpha=0 ⇒ 모두
투명). kbot은 읽을 때 이 바이트를 무시하고 쓸 때 0x00을 씁니다.
- 인덱스 0은 그 자체로는 투명하지 않습니다. 지형, 미니맵, 배경은 이를 검은색으로 그리며, 스프라이트 프레임은 자기 키(또는 건너뛰기 런)가 지정한 곳에서만 투명합니다. kbot의 지형과 미니맵 렌더링은 불투명 팔레트를 씁니다.
- 매직 넘버가 없으므로 검증이 약합니다.
.pal이 정상인지 확인하는 유일한 방법은 최소 1024바이트인지, 그리고 (선택적으로) 모든 항목의 알파 바이트가 0인지 요구하는 것뿐입니다. - 크기가 틀린 조회 테이블은 게임이 무시하고 팔레트로 다시 만듭니다.
.alp/.lht/.shd는 서로 바꿔 쓸 수 없습니다. 각기 다른 효과에 맞춰 조정되어 있으므로, 바꿔 넣으면 그림자나 조명이 눈에 띄게 틀려집니다.- TA: Kingdoms는 전역
.pal방식이 아니라 진영별로 PCX에 담긴 팔레트를 씁니다. 팔레트를 담는 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용 대체 팔레트 몇 개. |