Skip to content

Commit 10c0367

Browse files
committed
AGDS: add tools
Add unpackers for database (.db) and resources (.grp)
1 parent 13915a8 commit 10c0367

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

engines/agds/decrypt.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
key = bytes(map(lambda c: ord(c), 'Vyvojovy tym AGDS varuje: Hackerovani skodi obchodu!'))
2+
key_n = len(key)
3+
4+
def decrypt(src):
5+
r = bytearray()
6+
for i in range(len(src)):
7+
r.append(src[i] ^ key[i % key_n] ^ 0xff)
8+
return r

engines/agds/unpack-db

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python3
2+
3+
from argparse import ArgumentParser
4+
from struct import unpack
5+
import sys
6+
import os.path
7+
from decrypt import decrypt
8+
9+
argparser = ArgumentParser('Unpack ADB file')
10+
argparser.add_argument('file')
11+
args = argparser.parse_args()
12+
13+
with open(args.file, "rb") as f:
14+
data = bytearray(f.read())
15+
16+
size = len(data)
17+
magic, h1, h2, h3, h4 = unpack('<IIIII', data[:0x14])
18+
if magic != 666:
19+
raise Exception('invalid db magic', magic)
20+
21+
db_name, _ = os.path.splitext(os.path.basename(args.file))
22+
try:
23+
os.makedirs(db_name)
24+
except:
25+
pass
26+
27+
print('header', h1, h2, h3, h4)
28+
29+
data_offset = h2 * 0x28 + 0x14
30+
print('data offset: 0x%08x' %(data_offset))
31+
for i in range(h3):
32+
offset = 0x14 + i * 0x28
33+
entry = data[offset: offset + 0x28]
34+
name_end = entry.index(bytes([0]), 4)
35+
name = str(entry[4: name_end], 'utf-8')
36+
index, = unpack('<I', entry[0:4])
37+
size, = unpack('<I', entry[0x24:])
38+
print(repr(name), hex(index), hex(data_offset + index), size)
39+
40+
entry_data = data[data_offset + index: data_offset + index + size]
41+
with open(os.path.join(db_name, name + '.dec'), 'wb') as fo:
42+
fo.write(decrypt(entry_data))
43+
44+
with open(os.path.join(db_name, name), 'wb') as fo:
45+
fo.write(entry_data)
46+

engines/agds/unpack-grp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
3+
from argparse import ArgumentParser
4+
from struct import unpack
5+
from decrypt import decrypt
6+
7+
import sys
8+
import os.path
9+
10+
argparser = ArgumentParser('unpack GRP file')
11+
argparser.add_argument('file')
12+
args = argparser.parse_args()
13+
14+
15+
f = open(args.file, "rb")
16+
17+
header = bytes(f.read(0x2c))
18+
grp_dir = bytes(f.read(0x31))
19+
20+
id = decrypt(header[0:0x10])
21+
if id != bytes('AGDS group file\x1a', 'ascii'):
22+
raise Exception('invalid header', id)
23+
24+
version1, magic, version2 = unpack('<III', header[0x10:0x1c])
25+
if magic != 0x1a03c9e6 or version1 != 44 or version2 != 2:
26+
raise Exception("unsupported version")
27+
dir_count, _dc2, _unk14, _unk18 = unpack('<IIII', header[0x1c:])
28+
29+
dir_data = bytearray(f.read(0x31 * dir_count))
30+
31+
gfx_name, _ = os.path.splitext(os.path.basename(args.file))
32+
try:
33+
os.makedirs(gfx_name)
34+
except:
35+
pass
36+
37+
for offset in range(0, dir_count * 0x31, 0x31):
38+
entry = dir_data[offset: offset + 0x31]
39+
name_len = entry.index(bytes([0]))
40+
if name_len == 0:
41+
break
42+
name = str(decrypt(entry[:name_len]), "utf-8")
43+
offset, size, _unk1, _unk2 = unpack('<IIII', entry[0x21:])
44+
f.seek(offset)
45+
46+
print("writing file %s" %name)
47+
with open(os.path.join(gfx_name, name), "wb") as fo:
48+
fo.write(f.read(size))

0 commit comments

Comments
 (0)