2个版本
0.8.2 | 2022年1月15日 |
---|---|
0.8.1 | 2021年3月2日 |
#902 in 编码
84KB
1.5K SLoC
vpk0
一个用于处理任天堂N64时代vpk0
数据压缩的Rust库
vpk0
是一种基于LZSS并使用Huffman编码字典偏移量和匹配长度的数据压缩方案。它被HAL实验室用于其三款N64游戏,后来用于在GBA电子阅读器卡上编码数据。
这个包提供了对vpk0
文件的解码和编码。由于这是一个旧的方案,解码和编码的设计旨在与任天堂在20世纪90年代的做法相匹配;这个包不专注于压缩比或速度。
使用方法
函数 [decode()
] 和 [encode()
] 提供了处理 vpk0
数据的快速方法。
use vpk0::{encode, decode};
use std::io::Cursor;
let raw = Cursor::new(data);
let compressed = encode(raw).unwrap();
let decompressed = decode(Cursor::new(&compressed)).unwrap();
assert_eq!(&data, &decompressed);
为了获得更多控制,您可以使用 Decoder
或 Encoder
use vpk0::Encoder;
Encoder::for_bytes(b"ababacdcdeaba")
.two_sample()
.encode_to_writer(std::io::stdout())
.unwrap();
vpk0
背景
vpk0
格式(以魔数字节命名)被认为是在20世纪90年代末由 HAL实验室 开发的。他们的三款N64游戏使用了这种压缩方案
- 超级炸弹人兄弟
- 精灵捕捉
- Shigesato Itoi的No. 1 Bass Fishing: Definitive Edition
这个格式在2000年代中期再次出现,作为GBA电子阅读器的压缩方案。这是这个格式第一次受到互联网大众的关注。Tim Schuerewegen的 nevpk 和 Caitsith的 NVPK Tool and NEDEC Make 是来自电子阅读器的逆向工程的开源实现 vpk0
。
这个包扩展了他们的工作,为HAL的N64游戏提供匹配的压缩。
格式概述
vpk0
是基于两种基本的编码算法:LSZZ 和 Huffman 编码。这两种技术在 80 年代后期就在日本 BSSes 中流传,并且它们共同构成了许多现代编码方案的基础,例如 Deflate。
vpk0
格式相对简单:它是一个可变长度的 LZSS。输入数据通过标准的 LZSS 实现进行压缩。但是,它没有固定长度的字典偏移和长度,而是可变的。可变长度的编码作为 Huffman 代码,并在编码数据前附加必要的 Huffman 树。
更多信息,请参阅 格式模块的文档
实现细节
此实现旨在与用于 超级 Smash Bros. 的编码器完全匹配。截至 2021 年 3 月,LZSS 编码器是字节匹配的,但 Huffman 压缩不是。
匹配的 LZSS 编码方案是:在找到匹配后,查看下一个字节以确定是否存在更长的匹配。继续检查下一个字节,直到找到更短或没有匹配为止。
此包中的编码器最多检查下一个十个字节,因为这是在 SSB64 中匹配所有 500 个 vpk0
编码文件所必需的最大数量。将来,此参数可能成为 Encoder
的另一个选项。
高级用法
从 vpk0
文件中获取信息
use vpk0::vpk_info;
let (header, trees) = vpk_info(vpkfile).unwrap();
println!("Original size: {} bytes", header.size);
println!("VPK encoded with method {}", header.method);
println!("Offsets: {} || Lengths: {}", trees.offsets, trees.lengths);
像标准 LZSS 一样编码
use vpk0::{Encoder, LzssSettings};
// use fixed length compression by setting the offset to 10 and the length to 6.
let compressed = Encoder::for_bytes(b"I am Sam. Sam I am.")
.one_sample()
.with_lzss_settings(LzssSettings::new(10, 6, 2))
.with_offsets("10")
.with_lengths("6")
.encode_to_vec();
许可:MIT
依赖关系
~440–680KB
~11K SLoC