Beachhead 2000 纹理格式技术文档本文档
2026/6/10 7:06:32 网站建设 项目流程
本文档记录 Beachhead 2000 游戏中所有纹理文件格式的二进制结构、解析方式和用途。 基于 Beachhead16.exe.lst 逆向分析和 TexParser 实现代码整理。

格式总览

扩展名格式名称色深是否有调色板用途
.clutCLUT24-bit自身就是调色板256色 RGB 调色板
.rgbRGB56516-bit真彩色纹理
.rmap8RMAP88-bit需要 .clut8位索引纹理(地形/物体)
.tmap8TMAP88-bit需要 .clut8位索引动画纹理
.tmap32TMAP3232-bit带透明通道的真彩色纹理
.hmapHMAP8-bit内置地形色高度图/地形数据
.palPAL24-bit自身就是调色板组多组调色板
.sprSPR8-bit需要 .pal精灵/按钮/字体纹理

CLUT - 调色板

文件结构

+--------+--------------------------------+ | 偏移 | 内容 | +--------+--------------------------------+ | 0 | R0 (红色分量,第0色) | | 1 | G0 (绿色分量,第0色) | | 2 | B0 (蓝色分量,第0色) | | 3 | R1 | | ... | ... | | 765 | R255 | | 766 | G255 | | 767 | B255 | +--------+--------------------------------+

解析方式

for (int i = 0; i < 256; ++i) { int r = data[i * 3 + 0]; int g = data[i * 3 + 1]; int b = data[i * 3 + 2]; palette[i] = RGB(r, g, b); }

用途

.rmap8.tmap8文件提供颜色查找表。一个纹理文件通常对应多个 CLUT 变体(见 CLUT 调色板类型)。


RGB - RGB565 纹理

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 8 | "RAW RGB " (ASCII 文件标识) | | 8 | 2 | Width (uint16, little-endian) | | 10 | 2 | Height (uint16, little-endian) | | 12 | 2 | Pixel[0] (RGB565) | | 14 | 2 | Pixel[1] | | ... | ... | ... | +--------+--------+--------------------------------+

解析方式

// 读取 16-bit 像素 uint16_t pixel = data[offset] | (data[offset + 1] << 8); // 解码 RGB565 int r5 = (pixel >> 11) & 0x1F; // 5-bit red int g6 = (pixel >> 5) & 0x3F; // 6-bit green int b5 = pixel & 0x1F; // 5-bit blue // 扩展到 8-bit int r = (r5 << 3) | (r5 >> 2); // 5->8 bit int g = (g6 << 2) | (g6 >> 4); // 6->8 bit int b = (b5 << 3) | (b5 >> 2); // 5->8 bit

尺寸获取


RMAP8 - 8位索引纹理

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 128 | 文件头 (未知内容) | | 128 | 1 | Pixel[0] (8-bit 调色板索引) | | 129 | 1 | Pixel[1] | | ... | ... | ... | +--------+--------+--------------------------------+

解析方式

// 跳过 128 字节头部 QByteArray pixelData = data.mid(128); // 使用 CLUT 调色板渲染 QImage img(width, height, QImage::Format_Indexed8); img.setColorTable(clutPalette); memcpy(img.bits(), pixelData.constData(), width * height);

常见尺寸


TMAP8 - 8位索引动画纹理

文件结构

与 RMAP8 相同:

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 128 | 文件头 | | 128 | N | 像素数据 (8-bit 索引) | +--------+--------+--------------------------------+

动画检测

int totalPixels = pixelData.size(); int singleFramePixels = width * height; int frameCount = totalPixels / singleFramePixels; // 如果总像素是单帧的整数倍,则为动画 if (totalPixels % singleFramePixels == 0) { // 多帧动画 } // 或者:高度远大于宽度时,可能是竖直条带动画 if (height > width * 2 && height % width == 0) { frameCount = height / width; height = width; // 每帧为正方形 }

帧提取

for (int f = 0; f < frameCount; ++f) { QByteArray frameData = pixelData.mid(f * singleFramePixels, singleFramePixels); QImage frame = indexedToImage(frameData, width, height); }

TMAP32 - 32位 BGRA 纹理

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 1 | B0 (蓝色,第0像素) | | 1 | 1 | G0 (绿色) | | 2 | 1 | R0 (红色) | | 3 | 1 | A0 (Alpha,透明度) | | 4 | 1 | B1 | | ... | ... | ... | +--------+--------+--------------------------------+

解析方式

for (每个像素) { uint8_t b = data[offset + 0]; uint8_t g = data[offset + 1]; uint8_t r = data[offset + 2]; uint8_t a = data[offset + 3]; pixel = RGBA(r, g, b, a); }

HMAP - 高度图

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | H | 文件头 (可变大小) | | H | 1128251| 高度数据 (1501×751 字节) | +--------+--------+--------------------------------+

游戏引擎加载方式

根据 Beachhead16.exe.lst 分析:

// sub_4259DA - 加载 HMap FILE* fp = fopen("HMap1501x751C.hmap", "rb"); char buffer[1128251]; // 读取并丢弃头部(通常为 128 字节) fread(buffer, 1, 128, fp); // 读取实际高度数据(覆盖头部缓冲区) fread(buffer, 1, 1128251, fp); fclose(fp); // 获取高度值 uint8_t height = buffer[pixelX + pixelY * 1501];

高度值映射

高度值范围地形类型颜色
0-51 (0-20%)深水深蓝
52-89 (21-35%)浅水蓝色
90-102 (36-40%)沙滩黄色
103-178 (41-70%)草地/陆地绿色
179-216 (71-85%)山丘棕色
217-255 (86-100%)雪地白色

游戏内地形类型值 (dword_460600)

地形
0
1地面
7
9深水
0xA浅水
0xB沙滩
0xC雪地
0xD天空

PAL - 调色板组

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 4 | Offset[0] (uint32, little-endian)| | 4 | 4 | Offset[1] | | ... | ... | ... | | 4N | 4 | Offset[N-1] | | Offset[0] | M0 | Palette[0] 数据 (RGB 三元组) | | Offset[1] | M1 | Palette[1] 数据 | | ... | ... | ... | +--------+--------+--------------------------------+

精灵头部解析

struct SpriteHeader { uint8_t type; // 0x05 uint16_t width; // little-endian uint16_t height; // little-endian uint8_t palIndex; // PAL 调色板索引 uint8_t unknown[2]; // 未知 };

渲染方式

// 1. 加载同名 PAL 文件(如 UNITS.SPR → UNITS.PAL) // 2. 对每个精灵: // - 读取头部获取 width/height/palIndex // - 从 PAL 中选择对应调色板 // - 读取像素数据(width × height 字节) // - 索引 0 为透明色 // - 其他索引通过调色板转换为 RGB

已知 SPR 文件

文件名精灵数用途
MENUS.SPR28菜单元素
INNAME.SPR4姓名输入界面
UNITS.SPR2游戏单位(坦克等)
CONTROLS.SPR2控件按钮
LOGOS.SPR2Logo
ARIAL.SPR2字体

CLUT 调色板类型

根据 Beachhead16.exe.lst 逆向分析,游戏引擎支持以下 CLUT 变体:

后缀完整示例说明
(无)Ocean.clut基础调色板
GenAlphaOceanGenAlpha.clut生成 Alpha 通道
GenAlpha2OceanGenAlpha2.clut生成 Alpha 通道(变体2)
ExpandOceanExpand.clut扩展颜色范围
Expand555OceanExpand555.clut扩展到 RGB555
ShadedOceanShaded.clut带阴影效果

加载策略

QStringList clutTypes = { "", "GenAlpha", "GenAlpha2", "Expand", "Expand555", "Shaded" }; for (const QString &type : clutTypes) { QString clutPath = baseName + type + ".clut"; // 尝试加载... }

调色板匹配策略

自动匹配规则

手动指定

如果自动匹配失败,可通过文件对话框手动选择 CLUT/PAL 文件。


文件关联关系

.rmap8 / .tmap8 ──→ .clut (CLUT 调色板) .spr ──→ .pal (PAL 调色板组) .rgb ──→ (无,自带 RGB565 数据) .tmap32 ──→ (无,自带 BGRA 数据) .hmap ──→ (无,使用内置地形色) .clut ──→ (自身就是调色板) .pal ──→ (自身就是调色板组)

解析方式

// 读取偏移表 while (offset < fileSize) { uint32_t off = read_uint32_le(); if (off >= fileSize) break; offsets.push_back(off); } // 读取每个调色板 for (每个偏移) { int paletteSize = nextOffset - currentOffset; int colorCount = paletteSize / 3; for (int c = 0; c < colorCount; ++c) { int r = data[off + c * 3 + 0]; int g = data[off + c * 3 + 1]; int b = data[off + c * 3 + 2]; } }

已知 PAL 文件

文件名调色板数每调色板大小用途
MENUS.PAL15770 字节菜单界面
INNAME.PAL4770 字节姓名输入
UNITS.PAL2770 字节游戏单位
CONTROLS.PAL2770 字节控件按钮
LOGOS.PAL2770 字节Logo
ARIAL.PAL2~383 字节字体

SPR - 精灵/纹理

文件结构

+--------+--------+--------------------------------+ | 偏移 | 大小 | 内容 | +--------+--------+--------------------------------+ | 0 | 4 | NumSprites (uint32, little-endian)| | 4 | 4 | Offset[0] | | 8 | 4 | Offset[1] | | ... | ... | ... | | Offset[0] | 1 | Type (0x05) | | +1 | 2 | Width (uint16, little-endian) | | +3 | 2 | Height (uint16, little-endian) | | +5 | 1 | PaletteIndex (调色板索引) | | +6 | 1 | Unknown | | +7 | 1 | Unknown | | +8 | W×H | PixelData (8-bit 索引) | +--------+--------+--------------------------------+
  • 本文档记录 Beachhead 2000 游戏中所有纹理文件格式的二进制结构、解析方式和用途。 基于 Beachhead16.exe.lst 逆向分析和 TexParser 实现代码整理。

    目录

  • 格式总览
  • CLUT - 调色板
  • RGB - RGB565 纹理
  • RMAP8 - 8位索引纹理
  • TMAP8 - 8位索引动画纹理
  • TMAP32 - 32位 BGRA 纹理
  • HMAP - 高度图
  • PAL - 调色板组
  • SPR - 精灵/纹理
  • CLUT 调色板类型
  • 调色板匹配策略
  • 文件大小: 固定 768 字节
  • 颜色数: 256 色
  • 每色大小: 3 字节 (RGB)
  • 字节序: 无(单字节分量)
  • 无文件头
  • 文件头: 12 字节 (可选,部分文件无头)
  • 像素格式: RGB565 (16-bit)
    • R: 5 bits(bit 11-15)
    • G: 6 bits(bit 5-10)
    • B: 5 bits(bit 0-4)
  • 字节序: Little-endian
  • 优先从文件头读取 (offset 8-10)
  • 无头文件从文件名解析 (如Barge256x256.RGB)
  • 文件头: 128 字节
  • 像素格式: 8-bit 索引(指向 CLUT 调色板)
  • 尺寸: 从文件名解析(如Ocean256x256.rmap8
  • 256×256、128×128、64×64、512×512
  • 256×128、128×256、64×128、1024×1024
  • 文件头: 128 字节
  • 像素格式: 8-bit 索引
  • 支持动画: 多帧存储在单个文件中
  • 无文件头
  • 像素格式: BGRA (32-bit)
  • 尺寸: 从文件名解析
  • 字节序: 单字节分量,无字节序问题
  • 标准尺寸: 1501 × 751 像素
  • 期望数据大小: 1,128,251 字节
  • 像素格式: 8-bit 高度值 (0-255)
  • 文件头大小:fileSize - 1128251
  • 头部: N × 4 字节偏移表
  • 调色板数量: N(由偏移表长度决定)
  • 每调色板大小:Offset[i+1] - Offset[i](字节)
  • 颜色格式: RGB 三元组
  • 颜色数: 调色板大小 / 3
  • 头部: 4 + NumSprites × 4 字节
  • 精灵头部: 8 字节
  • 像素格式: 8-bit 索引(指向 PAL 调色板)
  • 调色板索引: 精灵头部第 5 字节(从 0 开始)
  • 透明色: 调色板索引 0
  • 同名匹配:Texture.rmap8Texture.clut
  • CLUT 类型后缀: 尝试TextureGenAlpha.clutTextureExpand.clut
  • 尺寸剥离:Texture256x256.rmap8Texture.clut
  • 通用调色板: 尝试Ocean.clutGrass.clutSand.clut

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询