#ea #far #game #dbpf #qfs

refpack

一个提供RefPack压缩格式压缩/解压缩的crate,许多2000年代初期的EA游戏都使用这种格式

10个稳定版本 (3个主要版本)

4.0.2 2023年10月30日
3.0.3 2023年6月24日
3.0.1 2023年3月31日
2.0.0 2022年11月29日
0.1.0 2021年11月14日

#63 in 压缩

Download history 21/week @ 2024-04-02 1/week @ 2024-05-14 8/week @ 2024-05-21 3/week @ 2024-05-28

每月58次下载

MPL-2.0许可证

100KB
1.5K SLoC

refpack-rs

Rust Build and Test docs.rs Crates.io GitHub license fuck it Coverage Status

一个非常过度设计的rust crate,用于压缩和解压缩许多2000年代初EA游戏使用的RefPack格式中的数据

RefPack

RefPack,也称为QFS,是一种半标准化的压缩格式,被90年代到2000年代末电子艺界(EA)出版的许多游戏所使用。在许多情况下,它与自定义的头部格式一起使用。

结构

RefPack与lz77压缩有很多相似之处;它是一种无损压缩格式,依赖于解压缩缓冲区中现有字节的长距离对。与lz77的不同之处在于,它不是使用单一格式为“字面量”控制代码和“指针”控制代码,而是使用4种不同的控制代码,用于不同大小的指针和字面量块。还有一个第五个控制代码,用于指示流的结束,而不是在解压缩前指定大小。

代码

RefPack使用一个类似于lz77的“字面量”只字节的控制代码,但精度限制为4的倍数。其余三个控制代码是不同大小的“指针”控制代码,用于小型、中型和大型的回溯和长度。通过“指针”控制代码也有能力将多达3个字面量字节写入流,来补偿“字面量”控制代码的精度限制。

有关详细信息,请参阅Command

解压缩

解压缩只需从RefPack数据流中读取,直到遇到停止码。

有关详细信息,请参阅解压缩

压缩

通过RefPack进行压缩在很大程度上类似于lz77压缩算法,涉及在数据上滑动窗口以查找重复块,然后将之前指定的代码写入流中。

有关详细信息,请参阅压缩

头部

尽管RefPack的实际数据块只有一个已知的实现,但已识别出多种类型的库头部。

其他实现

RefPack已在各种其他语言和各种游戏中得到实现。

  • RefPack.cpp (下载):Frank Barchard为Origin Software开发的RefPack的原始规范实现。被一些早期的Origin Software游戏使用。
  • JDBPF:早期用于读取DBPF文件的Simcity 4 Java库,使用了RefPack。
  • JDBPFX:JDBPF的后续维护分支。
  • DBPFSharp:用C#编写的Simcity 4 DBPF库。
  • Sims2Tools:用C#编写的Sims 2 DBPF库。

本库

本库是一个Rust实现,用于压缩和解压缩具有任何头文件格式的RefPack数据。它使用泛型来支持任意头文件格式,允许纯使用此库而无需编写解析头信息“粘合”代码。

简单来说,这意味着您可以在不产生动态分派带来的性能开销的情况下,使用任何您喜欢的格式,同时还可以实现自己的任意格式,这些格式仍然与相同的压缩算法兼容。

用法

refpack-rs公开了两个函数:compressdecompress,以及更易于使用但灵活性较低的easy变体。

compressdecompress分别接受可变引用到一个缓冲区,用于读取和写入,该缓冲区实现了std::io::Readstd::io::Write

decompress将读取缓冲区,直到遇到停止码(字节在(0xFC..=0xFF)之间),而compress将读取提供的长度。

所有压缩和解压缩函数接受一个泛型参数,限制为Format特质。实现可以是“不可构造”的类型,推荐类型为空枚举。

实现

格式 游戏 头文件
参考 90年代的各种Origin Software和EA游戏 参考
Maxis 《模拟人生》、《模拟人生在线》、《模拟城市4》、《模拟人生2》 Maxis
SimEA 《模拟人生3》、《模拟人生4》 SimEA

示例

use std::io::{Cursor, Seek};

use refpack::format::Reference;

let mut source_reader = Cursor::new(b"Hello World!".to_vec());
let mut out_buf = Cursor::new(vec![]);
refpack::compress::<Reference>(
    source_reader.get_ref().len(),
    &mut source_reader,
    &mut out_buf,
)
.unwrap();

易于使用的变体是compress_easydecompress_easy,它们接受一个&[u8],并返回一个Result<Vec<u8>, RefPackError>

它们在内部简单地调用compressdecompress,传递输入和输出缓冲区的Cursor,但在许多情况下使用起来更方便。

许可证

此存储库受Mozilla Public License Version 2.0条款的约束。

MPL是一种弱版权许可,用简单、非法律约束性的语言表达。

您可以使用...

  1. 请私用此软件
  2. 请商用此软件
  3. 修改此软件
  4. 重新分发此软件

只要

  1. 您公开此库的许可和版权信息
  2. 您公开此库的来源
  3. 您公开对此库文件进行的源代码更改
  4. 您为对库文件进行的更改使用相同的许可

更简单地说,您几乎可以用它来做什么,只要您提供信用和链接,但如果您更改了此库中的任何文件,您还必须共享您更改的源代码。再次强调,这并不是具有法律约束力的,请参阅实际许可文本等。

依赖项

~120KB