VPK File Format/vpk2 reader.py

From Valve Developer Community
Jump to: navigation, search
Dead End - Icon.png
This article has no links to other VDC articles. Please help improve this article by adding links that are relevant to the context within the existing text.
January 2024

Put next to pak01_dir.vpk and run.

import os,struct,binascii

def get_int4():
	return int( struct.unpack("I",index.read(4))[0] )
def get_int2():
	return int( struct.unpack("H",index.read(2))[0] )
	
def get_sz():
	out = ""
	while True:
		cur = index.read(1)
		if cur == b'\x00': break
		out += struct.unpack("c",cur)[0].decode("ASCII")
	return out
	
index = open("pak01_dir.vpk",'rb')

print( "Signature:",binascii.b2a_hex(index.read(4)) )
print( "Version:",get_int4() )
print( "Directory length:", get_int4() )
print( "Unknown1:", get_int4() )
unknown2 = get_int4() # footer length?
print( "Unknown2:", unknown2 )
unknown3 = get_int4()
print( "Unknown3:", unknown3 )
print( "Unknown4:", get_int4() )

class VpkFile():
	path = ""
	CRC = -1
	archive_index = -1
	offset = -1
	length = -1
	preload = bytes()
	
vpk_files = []

while True:
	extension = get_sz()
	if not extension: break		
	
	while True:
		folder = get_sz()
		if not folder: break
		
		while True:
			filename = get_sz()
			if not filename: break
			
			cur_file = VpkFile()
			vpk_files.append(cur_file)
			cur_file.path = "{}/{}.{}".format(folder,filename,extension)
			
			cur_file.CRC = get_int4()
			preload_bytes = get_int2()
			cur_file.archive_index = get_int2()
			if cur_file.archive_index == b'\x7fff':
				print("EMBED")
			cur_file.offset = get_int4()
			cur_file.length = get_int4()
			get_int2() # terminator
			
			if preload_bytes:
				cur_file.preload = index.read(preload_bytes)

index.close()

print("Extracting...")
for vf in vpk_files:
	print(vf.path,"({} bytes)".format(len(vf.preload)+vf.length))
	full_path = os.path.join(os.getcwd(),"vpk_extracted",vf.path.replace("/","\\"))
	dir = os.path.dirname(full_path)
	if not os.path.isdir(dir):
		os.makedirs(dir)
	out_data = open(full_path,'wb')
	out_data.write(vf.preload)
	if vf.length:
		vpk = open("pak01_{}.vpk".format(str(vf.archive_index).zfill(3)),'rb')
		vpk.seek(vf.offset)
		out_data.write(vpk.read(vf.length))
		vpk.close()
	out_data.close()
Wikipedia - Letter.png
This article has not been added to any content categories. Please help out by adding categories.
January 2024