forked from Damme/LandLord
-
Notifications
You must be signed in to change notification settings - Fork 0
/
unpack_pck.py
executable file
·96 lines (77 loc) · 2.41 KB
/
unpack_pck.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/python3.5
import sys
if len(sys.argv) <2:
print( "usage:" )
print(" " + sys.argv[0] + " [.PCK file]", "[Folder-prefix]" )
print( " " )
exit()
import os
from binascii import crc32
from struct import unpack
#get unpack file
src_file_path = sys.argv[1]
#read file length
src_file_size = os.path.getsize(src_file_path)
#read file
b = bytearray(open(src_file_path, 'rb').read())
# crude bytearray to String converter
def toStr(b):
return "".join(["%c"%i for i in b]).strip("\x00")
# convert 4 bytes to int
def word2int(w):
return unpack("<I", w)[0]
# crude filetable parser
def getHeader(b, datastart):
beginstart=b.find(63) #"?"
filename = toStr(b[0:beginstart]).replace("\\","/")
beginstart+=1
beginlength=b.find(63,beginstart) #"?"
start = int(b[beginstart:beginlength],16) + datastart + 4
beginlength+=1
length = int(b[beginlength:beginlength+10],16)
return {
"filename": filename,
"start" : start,
"length" : length,
}
#crude way to create nonexisting directories
def checkCreateDir(filename):
if not os.path.exists(os.path.dirname(filename)):
try:
os.makedirs(os.path.dirname(filename))
except OSError as exc: # Guard against race condition
if exc.errno != errno.EEXIST:
raise
def save(filename, data):
checkCreateDir(prefix + "/" + filename) #create missing directories
print ("writing %s\t (%d bytes)"%(filename,len(data)))
open(prefix + "/" + filename, 'wb').write(data)
## Start decoding
print("Unknown byte 0:\t"+ str(b[0]))
print("Unknown byte 1:\t"+ str(b[1]))
print("Unknown byte 2:\t"+ str(b[2]))
print("Unknown byte 3:\t"+ str(b[3]))
prefix = sys.argv[2] if len(sys.argv)>=3 else "."
headerstart_token = bytearray((int(62), int(0x0d), int(0x0a)))
headerstart = b.find(headerstart_token,0)+3
pos=headerstart
datastart_token = bytearray((int(0x0d), int(0x0a), int(0x0d), int(0x0a)))
datastart = b.find(datastart_token,0)
print("header end: \t"+ str(datastart))
nHeaders = b.count(int(13),4,datastart)
print("# files \t: "+str(nHeaders))
# crude way to parse the directory table
files = []
print ("found %i files\n"%nHeaders)
token = bytearray((int(0x0d), int(0x0a)))
for i in range(nHeaders):
pos2=b.find(token,pos)
h = getHeader(b[pos:pos2], datastart)
files.append(h)
print(h)
pos = int(pos2)+2
for h in files:
bFile = b[h["start"]:h["start"]+h["length"]]
#write stripped file
save(h["filename"],bFile)
print("Done!")