Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import struct
- from collections import namedtuple
- from sys import argv
- # this code will extract the contents of Quake 1 format pak files
- # usage python pak_extract.py <filename>
- # the pak contents will be extracted under a folder named after the pak file
- # type definitions
- PAKHeader = namedtuple('PAKHeader', "format, dir_ofs, dir_size")
- fmt_PAKHeader = '<4s2i'
- PAKEntry = namedtuple('PAKDirectory', "path, ofs, size")
- fmt_PAKEntry = '<56s2I'
- def extract(pak_path):
- with open(pak_path, 'rb') as pak_file:
- header_data = pak_file.read(struct.calcsize(fmt_PAKHeader))
- header = PAKHeader._make(struct.unpack(fmt_PAKHeader, header_data))
- entry_struct = struct.Struct(fmt_PAKEntry)
- entry_size = struct.calcsize(fmt_PAKEntry)
- num_entries = int(header.dir_size / struct.calcsize(fmt_PAKEntry))
- print("File: %s (found directory at %d containing %d entries)" % (pak_path, header.dir_ofs, num_entries))
- pak_file.seek(header.dir_ofs)
- pak_directory_data = pak_file.read(header.dir_size)
- for i in range(0, num_entries):
- entry_ofs = i * entry_size
- entry_data = pak_directory_data[entry_ofs:entry_ofs+entry_size]
- entry = PAKEntry._make(entry_struct.unpack_from(entry_data))
- # some entries (e.g. PAK0.PAK/progs.dat) are not correctly 0 padded,
- # so this is required as .decode doesn't work
- entry_path = ""
- for j, b in enumerate(entry.path):
- if b == '\x00':
- entry_path = entry.path[0:j].decode('ascii')
- break
- elif j == 55:
- entry_path = entry.path.decode('ascii')
- # save the file
- if entry_path != "":
- print("[%d] %s (%d bytes at %d)" % (i, entry.path, entry.size, entry.ofs))
- file_name = os.path.basename(entry_path)
- file_path = os.path.dirname(entry_path)
- # read the file data
- pak_file.seek(entry.ofs)
- file_data = pak_file.read(entry.size)
- # prepare the output path
- output_dir = os.path.splitext(pak_path)[0] + "/" + file_path
- if not os.path.exists(output_path):
- os.makedirs(output_dir)
- output_path = output_dir + "/" + file_name
- # write the file
- with open(output_path, 'wb') as output_file:
- output_file.write(file_data)
- extract(argv[1])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement