-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunpack.py
67 lines (49 loc) · 1.75 KB
/
unpack.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
import os
ASSET_NAME_MAX_SIZE = 80
INTEGER_SIZE = 4
filename = "ChickenInvaders.dat"
folder = f"{filename}_extracted"
assets = []
with open(filename, "rb") as bin:
# Read the assets count
count = int.from_bytes(
bin.read(INTEGER_SIZE), byteorder="little", signed=False
)
for i in range(0, count):
asset_name_size = 0
name = ""
while True:
b = bin.read(1)
# If we reached the end of the file or we encountered a null character, stop reading
if b == b"" or b == b"\x00":
break
asset_name_size += 1
name += b.decode("ascii", errors="ignore")
# Move back by one byte from the current position
bin.seek(-1, os.SEEK_CUR)
# Skip empty bytes
bin.read(ASSET_NAME_MAX_SIZE - asset_name_size)
# Read the offset of the asset
offset = int.from_bytes(
bin.read(INTEGER_SIZE), byteorder="little", signed=False
)
# Read the size of the asset
size = int.from_bytes(
bin.read(INTEGER_SIZE), byteorder="little", signed=False
)
assets.append({
"name": name,
"offset": offset,
"size": size,
})
assert count == len(assets), "Assets count mismatch, error while reading?"
for asset in assets:
path = f'{folder}/{asset["name"]}'
head, tail = os.path.split(path)
# Check if the directory part of the path exists
if not os.path.exists(head):
os.makedirs(head)
bin.seek(asset["offset"])
with open(path, "wb") as out:
out.write(bin.read(asset["size"]))
print(f"Extracted {count} asset(s).")