分析游戏地图/地形格式

逆向工程 二元分析 十六进制
2021-06-28 07:24:51

我试图了解这个游戏是如何构建地图和地形的。特别是如果它使用高度图。所以我可以编写一个可以查看地图并自由移动(相机)的应用程序。

首先,我不完全确定游戏是否真的使用了高度图。但它是在 2000/2001 年制造的,所以它是有道理的。

每次加载地图时都会加载以下文件。从这里开始,我将使用地图 4作为示例:

/map/map4.spt
/map/map4.inf
/map/map4.obj
/terrain/chunk4.dat
/terrain/addterrain4.ctr
/terrain/addterrain4.obj
/terrain/addterrain4.inf
/terrain/addterrain4.t16
/terrain/terrain4.obj
/terrain/terrain4.t16

*.T16

我知道这些是纹理。

这是terrain4.t16解压(地形):
在此处输入图片说明

这里是addterrain4.t16解包(建筑):
在此处输入图片说明

*.SPT

我知道这是一个加密脚本。它包含环境光颜色、天空颜色和地图的其他配置等内容。

*.点击率

我对此还不确定,但我认为这不是高度图。

*.INF

我对此还不确定,但我认为这不是高度图。但它看起来像是地图上建筑物/物体的位置。

*.OBJ

虽然这听起来像一个 3D 对象文件,但它不是。到目前为止,我能够用这个脚本解析这个文件:

with open("map4.obj", "rb") as bin:
    bin.seek(0, 2)
    file_size = bin.tell()

    bin.seek(0)

    unk1 = struct.unpack("<h", bin.read(2))[0]

    width  = struct.unpack("<h", bin.read(2))[0]
    height = struct.unpack("<h", bin.read(2))[0]

    c_width = struct.unpack("<h", bin.read(2))[0]
    c_heigth = struct.unpack("<h", bin.read(2))[0]

    size1 = struct.unpack("<I", bin.read(4))[0]
    size2 = struct.unpack("<I", bin.read(4))[0]

    bin.seek(50)

    # (1, 76, 76, 304, 304, 5776, 92416)
    print(unk1, width, height, c_width, c_heigth, size1, size2)

    for x in range(size1):
        unk2 = struct.unpack("<BBBB", bin.read(4))

    for y in range(size2):
        unk3 = struct.unpack("<BB", bin.read(2))

该脚本读取文件直到最后,所以我认为我的解析是正确的。但是我还是不明白那些字节(unk2,unk3)是什么意思。

这是前几个字节:(1, 76, 76, 304, 304, 5776, 92416).

76x76在我看来就像一个图像宽x高。这是我开始怀疑这一定是高度图的部分。

304x304 是地图坐标的大小,如果我转到地图的右下角,坐标会显示 x304 y304。 (0,0) (304,304)

5776 是 76*76。

92416 是 304*304。

我猜细胞间距是 4,因为304/76 = 4.

嗯...也许我应该阅读terrain4.obj而不是map4.obj ???

检查terrain4.obj(文件大小:2,194,888)

with open("terrain4.obj", "rb") as bin:
    bin.seek(0, 2)
    file_size = bin.tell()

    bin.seek(0)

    width  = struct.unpack("<I", bin.read(4))[0]
    height = struct.unpack("<I", bin.read(4))[0]

    print(width, height)

    for x in range(width*height):
        unk1 = struct.unpack("<fffHH", bin.read(16))
        print(unk1)

        for y in range(10):
            unk2 = struct.unpack("<ffffffBBBBff", bin.read(36))
            print(unk2)

        unk3 = struct.unpack("<HH", bin.read(4))
        print(unk3)

    print((bin.tell()-file_size) == 0)

打印结果(最后几行):

(64656, 900)
(9536.0, 0.0, -9664.0, 8, 60)
(9536.0, 367.3583679199219, -9664.0, 0.6106882691383362, 0.7202576398849487, -0.3290725350379944, 125, 125, 125, 255, 0.5, 0.5)
(9472.0, 439.9534912109375, -9664.0, 0.6727219820022583, 0.5930730104446411, -0.4423908591270447, 72, 72, 72, 255, 0.0, 0.5)
(9472.0, 529.98291015625, -9600.0, 0.5103294849395752, 0.5574429631233215, -0.6548444032669067, 91, 91, 91, 255, 0.0, 0.0)
(9536.0, 428.7572021484375, -9600.0, 0.5774530172348022, 0.5274922251701355, -0.6231372356414795, 83, 83, 83, 255, 0.5, 0.0)
(9600.0, 382.6859436035156, -9600.0, 0.32311421632766724, 0.6967470049858093, -0.6404222846031189, 110, 110, 110, 255, 1.0, 0.0)
(9600.0, 331.24566650390625, -9664.0, 0.4635116457939148, 0.8214490413665771, -0.3322325348854065, 149, 149, 149, 255, 1.0, 0.5)
(9600.0, 326.34356689453125, -9728.0, 0.5303630828857422, 0.847672700881958, -0.012873286381363869, 122, 122, 122, 255, 1.0, 1.0)
(9536.0, 370.5403747558594, -9728.0, 0.603411078453064, 0.7964465618133545, 0.039598409086465836, 107, 107, 107, 255, 0.5, 1.0)
(9472.0, 423.61572265625, -9728.0, 0.6945193409919739, 0.7165639996528625, -0.06464438885450363, 97, 97, 97, 255, 0.0, 1.0)
(9472.0, 439.9534912109375, -9664.0, 0.6727219820022583, 0.5930730104446411, -0.4423908591270447, 72, 72, 72, 255, 0.0, 0.5)
(64656, 900)
(9664.0, 0.0, -9664.0, 8, 60)
(9664.0, 323.531005859375, -9664.0, -0.16421209275722504, 0.9194830656051636, -0.3571907877922058, 202, 202, 202, 255, 0.5, 0.5)
(9600.0, 331.24566650390625, -9664.0, 0.11137175559997559, 0.9239282011985779, -0.3659959137439728, 199, 199, 199, 255, 0.0, 0.5)
(9600.0, 382.6859436035156, -9600.0, 0.32311421632766724, 0.6967470049858093, -0.6404222846031189, 110, 110, 110, 255, 0.0, 0.0)
(9664.0, 370.8617248535156, -9600.0, -0.030711062252521515, 0.8036384582519531, -0.5943247675895691, 202, 202, 202, 255, 0.5, 0.0)
(9728.0, 387.73626708984375, -9600.0, -0.3357184827327728, 0.8114649057388306, -0.478348970413208, 202, 202, 202, 255, 1.0, 0.0)
(9728.0, 359.2901306152344, -9664.0, -0.4858676493167877, 0.869583010673523, -0.0880785584449768, 202, 202, 202, 255, 1.0, 0.5)
(9728.0, 373.6744079589844, -9728.0, -0.6241185665130615, 0.7812370657920837, -0.012026631273329258, 202, 202, 202, 255, 1.0, 1.0)
(9664.0, 302.3572998046875, -9728.0, -0.23366673290729523, 0.9231089949607849, -0.3054006099700928, 202, 202, 202, 255, 0.5, 1.0)
(9600.0, 326.34356689453125, -9728.0, 0.23029862344264984, 0.9547197222709656, -0.18834225833415985, 177, 177, 177, 255, 0.0, 1.0)
(9600.0, 331.24566650390625, -9664.0, 0.11137175559997559, 0.9239282011985779, -0.3659959137439728, 199, 199, 199, 255, 0.0, 0.5)
(64656, 900)
True

*.DAT

总共 2,127,308 个字节的前几个字节:

00000000 19 00 00 00 00 01 00 00 23 00 00 00 00 00 80 42 ........#......B
00000016 00 00 FF 43 00 00 80 C2 00 00 00 00 FF FF 7F 3F ...C...........?
00000032 00 00 00 00 7A 7A 7A FF 00 00 00 3F 00 00 00 3F ....zzz....?...?
00000048 00 00 00 00 00 00 FF 43 00 00 80 C2 00 00 00 00 .......C........
00000064 FF FF 7F 3F 00 00 00 00 7A 7A 7A FF 00 00 00 00 ...?....zzz.....
00000080 00 00 00 3F 00 00 00 00 00 00 FF 43 00 00 00 80 ...?.......C....
00000096 00 00 00 00 FF FF 7F 3F 00 00 00 00 7A 7A 7A FF .......?....zzz.
00000112 00 00 00 00 00 00 00 00 00 00 80 42 00 00 FF 43 ...........B...C

我不确定这一点。

我的问题:

  • .obj 文件可能是高度图,如果不是,它是什么?
  • 知道 .CTR 和 .INF 文件是什么吗?(你猜?)

附加信息:

地图 4 称为熔岩峡谷。它的特色是被熔岩峡谷环绕的路径。

小地图纹理:

在此处输入图片说明

相关文件:从 Mediafire 下载

0个回答
没有发现任何回复~