旧文件片段理解 - 适合那些挑战的人

时间:2011-06-02 08:19:33

标签: fragment

我正试图从旧游戏格式中获取PVS(使用视线渲染)信息。它有文档,到目前为止我已经能够将所有内容翻译成C ++代码。然而,这部分让我感到困惑。我今天花了几个小时试图了解从哪里开始,但唉,我什么都没有。同样,这仅适用于那些可能需要挑战的人,或者可以提供一些建议甚至伪代码以实现这一目标。

谢谢

Data6条目(其中有大小6):

Data6Size1:WORD 告诉Data6Data字段中的条目数。

Data6Data:BYTE或WORD

这是一个复杂的领域。它包含运行长度编码的数据,告诉客户端哪些区域“在附近”。目的似乎是,客户可以确定区域中的哪些怪物必须检查其Z坐标,以便它们落到地面上(或直到它们落在某物上)。由于这样做很昂贵,所以只对玩家可见的区域执行此操作,而不是对整个区域中的所有怪物(重复)执行此操作。

我只遇到数据,其中流是BYTE而不是WORD的列表。以下讨论描述了编码BYTE流的RLE。

这里的想法是形成一个在一定距离内的所有区域ID的排序列表,然后将该列表写为RLE编码的流以节省空间。程序如下:

  1. 将初始区域ID值设置为零。

  2. 如果(已排序)列表中不存在此区域ID,请跳至列表中的第一个区域ID。在流中写一些东西,告诉它跳过了多少个ID。

  3. 形成列表中的连续ID块,并向流中写入一些内容,告诉客户端列表中有这么多ID。

  4. 如果列表中有更多区域ID,请返回步骤2.

  5. 写入流时,写入一个或三个字节:

    • 0x00..0x3E由此众多区域ID向前跳过
    • 0x3F,WORD以下面的16位WORD中给出的数量向前跳过
    • 0x40..0x7F基于位3..5向前跳过,然后包含基于位0..2的ID数量。
    • 0x80..0xBF包括基于位3..5的ID数,然后根据位0..2
    • 跳过
    • 0xC0..0xFE减去0xC0,这附近有很多区域ID
    • 0xFF,WORD由以下WORD给出的区域ID数量在附近

    应该注意,0x40..0xBF范围内的值允许一次跳过并包含不超过7个ID。此外,它们不必编码区域列表:它们只允许更好的压缩。

1 个答案:

答案 0 :(得分:1)

这是我尝试实现该解包器。未经测试,因为没有用于测试它的示例数据...(实际上甚至没有编译)

std::vector<int> regions(std::vector<unsigned char>& data6)
{
    int rp = 0, sz = data6.size();
    std::vector<int> result;
    int current_id = 0;
    while (rp < sz)
    {
        int c = data6[rp++];
        if (c <= 0x3E)
        {
            // 0x00..0x3E : skip forward by this many region IDs
            current_id += c;
        }
        else if (c == 0x3F)
        {
            // 0x3F WORD skip forward by the amount given in the following 16-bit WORD
            if (rp + 2 > sz) throw std::runtime_error("Invalid data");
            int count = data[rp] + (data[rp + 1] << 8); // (NOTE: May be H/L ?)
            rp += 2;
            current_id += count;
        }
        else if (c <= 0x7F)
        {
            // 0x40..0x7F skip forward based on bits 3..5,
            // then include the number of IDs based on bits 0..2
            int keep = (c & 7);
            int skip = (c >> 3) & 7;
            current_id += skip;
            for (int i=0; i<keep; i++)
                result.push_back(current_id++);
        }
        else if (c <= 0xBF)
        {
            // 0x80..0xBF include the number of IDs based on bits 3..5,
            // then skip the number of IDs based on bits 0..2
            int skip = (c & 7);
            int keep = (c >> 3) & 7;
            for (int i=0; i<keep; i++)
                result.push_back(current_id++);
            current_id += skip;
        }
        else if (c <= 0xFE)
        {
            // 0xC0..0xFE subtracting 0xC0, this many region IDs are nearby
            int keep = c - 0xC0;
            for (int i=0; i<keep; i++)
                result.push_back(current_id++);
        }
        else
        {
            // 0xFF WORD the number of region IDs given by the following WORD are nearby
            if (rp + 2 > sz) throw std::runtime_error("Invalid data");
            int count = data[rp] + (data[rp + 1] << 8); // (NOTE: May be H/L ?)
            rp += 2;
            for (int i=0; i<count; i++)
                result.push_back(current_id++);
        }
    }
    return result;
}

我认为WORD被编码为低/高,但可能是相反的......