アンパック

pak ファイルにデータはまとめられている。展開した状態でゲーム起動は可能。

pak ファイルは 4G 超えていますので、大容量のデータを取り扱えるバイナリエディタでないとデータは見れません注意してください。

struct PakInfo {
    magic: u32,
    version: i32,
    index_offset: u64,
    index_size: u64,
    index_hash: [u8; 20],
}
まず PakInfo なんですがこれは pak の末尾にあります。
offset, size は u64(4G超可能) なんで注意 8 バイトです。
magic は末尾から seek(-44) です。

index_offset ここに index があるのでそこへ seek
3F 89 CF 4F 01 00 00 00 = 0x14FCF893F

struct Pak {
    mount_point: FString,
    num_entries: i32,
    entries: Vec<PakEntry>,
}
struct PakEntry {
    file_name: FString,
    offset: u64,
    size: u64,
    uncompressed_size: u64,
    compression_method: i32,
    hash: [u8; 20],
    compression_blocks: Vec<PakCompressedBlock>,
    bencrypted: u8,
    compression_block_size: u32,
}
PakCompressedBlock は今回の non commpres では取り扱いません。comppresed のゲームの時に書きます。

まず FString について
struct FString {
    legth: i32,
    string: Vec<u8>,
}
length の値が < 0 の場合 string は UTF-16LE で > 0 の場合は ANSI
String は null 終端
path は ANSI なので length は正の値

0A 00 00 00 2E 2E 2F 2E 2E 2F 2E 2E 2F 00
length = 10, String = "../../../"

mount_point = "../../../"

となります。後は num_entries 分 PakEntry を読み込むcompression_blocksは無いものとして考えてください。

後は実際のアンパック処理なんですが
file_name, offset, size がわかっているので
offset へシークして size 分読み込んだものを file_name として出力するだけ。

追記:
忘れていました。offserへシークした場所に PakEntry の file_name を除いた他の要素が付加されていますので。それを読み込んでその次のデータから取り扱うが正解です。