diff options
-rw-r--r-- | crodump.py | 81 |
1 files changed, 50 insertions, 31 deletions
@@ -9,7 +9,15 @@ python3 crodump.py crodump chechnya_proverki_ul_2012 | |||
9 | python3 crodump.py kodump -s 6 -o 0x4cc9 -e 0x5d95 chechnya_proverki_ul_2012/CroStru.dat | 9 | python3 crodump.py kodump -s 6 -o 0x4cc9 -e 0x5d95 chechnya_proverki_ul_2012/CroStru.dat |
10 | """ | 10 | """ |
11 | 11 | ||
12 | def toout(args, data): | ||
13 | """ return either ascdump or hexdump """ | ||
14 | if args.ascdump: | ||
15 | return asasc(data) | ||
16 | else: | ||
17 | return tohex(data) | ||
18 | |||
12 | def enumunreferenced(ranges, filesize): | 19 | def enumunreferenced(ranges, filesize): |
20 | """ from a list of used ranges and the filesize, enumerate the list of unused ranges """ | ||
13 | o = 0 | 21 | o = 0 |
14 | for start, end, desc in sorted(ranges): | 22 | for start, end, desc in sorted(ranges): |
15 | if start > o: | 23 | if start > o: |
@@ -19,6 +27,7 @@ def enumunreferenced(ranges, filesize): | |||
19 | yield o, filesize-o | 27 | yield o, filesize-o |
20 | 28 | ||
21 | class Datafile: | 29 | class Datafile: |
30 | """ Represent a single .dat with it's .tad index file """ | ||
22 | def __init__(self, dat, tad): | 31 | def __init__(self, dat, tad): |
23 | self.dat = dat | 32 | self.dat = dat |
24 | self.tad = tad | 33 | self.tad = tad |
@@ -39,7 +48,7 @@ class Datafile: | |||
39 | self.dat.seek(ofs) | 48 | self.dat.seek(ofs) |
40 | return self.dat.read(size) | 49 | return self.dat.read(size) |
41 | 50 | ||
42 | def dump(self, args, dokodecode=False, plainbytes=0): | 51 | def dump(self, args, nodecode=False): |
43 | print("tadhdr: %08x %08x" % tuple(self.tadhdr)) | 52 | print("tadhdr: %08x %08x" % tuple(self.tadhdr)) |
44 | ranges = [] | 53 | ranges = [] |
45 | for i, (ofs, ln, chk) in enumerate(self.tadidx): | 54 | for i, (ofs, ln, chk) in enumerate(self.tadidx): |
@@ -50,30 +59,45 @@ class Datafile: | |||
50 | 59 | ||
51 | ln &= 0xFFFFFFF | 60 | ln &= 0xFFFFFFF |
52 | dat = self.readdata(ofs, ln) | 61 | dat = self.readdata(ofs, ln) |
62 | ranges.append((ofs, ofs+ln, "item #%d" % i)) | ||
53 | plain = b'' | 63 | plain = b'' |
54 | decrypted = ' ' | 64 | decflag = ' ' |
55 | if dokodecode and not args.nokod: | 65 | infostr = "" |
56 | pb = plainbytes if flags else 8 | 66 | tail = b'' |
57 | plain = dat[:pb] | 67 | if not nodecode and not flags: |
58 | dat = kodecode(i+1, dat[pb:]) | 68 | extofs, extlen = struct.unpack("<LL", dat[:8]) |
59 | decrypted = '*' if flags else '+' | 69 | infostr = "%08x;%08x" % (extofs, extlen) |
60 | if args.ascdump: | 70 | encdat = dat[8:] |
61 | print("%5d: %08x-%08x: (%02x:%08x) %s %s%s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), decrypted, asasc(dat))) | 71 | while len(encdat)<extlen: |
72 | dat = self.readdata(extofs, 0x200) | ||
73 | ranges.append((extofs, extofs+0x200, "item #%d ext" % i)) | ||
74 | extofs, = struct.unpack("<L", dat[:4]) | ||
75 | infostr += ";%08x" % (extofs) | ||
76 | encdat += dat[4:] | ||
77 | tail = encdat[extlen:] | ||
78 | encdat = encdat[:extlen] | ||
79 | decflag = '+' | ||
62 | else: | 80 | else: |
63 | print("%5d: %08x-%08x: (%02x:%08x) %s %s%s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), decrypted, tohex(dat))) | 81 | encdat = dat |
64 | ranges.append((ofs, ofs+ln, "item #%d" % i)) | 82 | decflag = '*' |
83 | |||
84 | if nodecode: | ||
85 | decdat = encdat | ||
86 | decflag = ' ' | ||
87 | else: | ||
88 | decdat = kodecode(i+1, encdat) | ||
89 | |||
90 | print("%5d: %08x-%08x: (%02x:%08x) %s %s%s %s" % (i, ofs, ofs+ln, flags, chk, infostr, decflag, toout(args, decdat), tohex(tail))) | ||
65 | 91 | ||
66 | if args.verbose: | 92 | if args.verbose: |
67 | # output parts not referenced in the .tad file. | 93 | # output parts not referenced in the .tad file. |
68 | for o, l in enumunreferenced(ranges, self.datsize): | 94 | for o, l in enumunreferenced(ranges, self.datsize): |
69 | dat = self.readdata(o, l) | 95 | dat = self.readdata(o, l) |
70 | if args.ascdump: | 96 | print("%08x-%08x: %s" % (o, o+l, toout(args, dat))) |
71 | print("%08x-%08x: %s" % (o, o+l, asasc(dat))) | ||
72 | else: | ||
73 | print("%08x-%08x: %s" % (o, o+l, tohex(dat))) | ||
74 | 97 | ||
75 | 98 | ||
76 | class Database: | 99 | class Database: |
100 | """ represent the entire database, consisting of stru, index and bank files """ | ||
77 | def __init__(self, dbdir): | 101 | def __init__(self, dbdir): |
78 | self.dbdir = dbdir | 102 | self.dbdir = dbdir |
79 | 103 | ||
@@ -114,22 +138,12 @@ def decode_kod(args, data): | |||
114 | # explicitly specified shift. | 138 | # explicitly specified shift. |
115 | for s in range(256): | 139 | for s in range(256): |
116 | enc = incdata(data, s) | 140 | enc = incdata(data, s) |
117 | if args.ascdump: | 141 | print("%02x: %s" % (s, toout(args, enc))) |
118 | print("%02x: %s" % (s, asasc(enc))) | ||
119 | else: | ||
120 | print("%02x: %s" % (s, tohex(enc))) | ||
121 | |||
122 | |||
123 | |||
124 | else: | 142 | else: |
125 | # output with all possible 'shift' values. | 143 | # output with all possible 'shift' values. |
126 | for s in range(256): | 144 | for s in range(256): |
127 | enc = kodecode(s, data) | 145 | enc = kodecode(s, data) |
128 | if args.ascdump: | 146 | print("%02x: %s" % (s, toout(args, enc))) |
129 | print("%02x: %s" % (s, asasc(enc))) | ||
130 | else: | ||
131 | print("%02x: %s" % (s, tohex(enc))) | ||
132 | |||
133 | 147 | ||
134 | 148 | ||
135 | def kod_hexdump(args): | 149 | def kod_hexdump(args): |
@@ -145,6 +159,10 @@ def kod_hexdump(args): | |||
145 | 159 | ||
146 | if args.filename: | 160 | if args.filename: |
147 | with open(args.filename, "rb") as fh: | 161 | with open(args.filename, "rb") as fh: |
162 | if args.length is None: | ||
163 | fh.seek(0, io.SEEK_END) | ||
164 | filesize = fh.tell() | ||
165 | args.length = filesize-args.offset | ||
148 | fh.seek(args.offset) | 166 | fh.seek(args.offset) |
149 | data = fh.read(args.length) | 167 | data = fh.read(args.length) |
150 | decode_kod(args, data) | 168 | decode_kod(args, data) |
@@ -158,22 +176,23 @@ def kod_hexdump(args): | |||
158 | 176 | ||
159 | 177 | ||
160 | def cro_dump(args): | 178 | def cro_dump(args): |
179 | """ handle 'crodump' subcommand """ | ||
161 | db = Database(args.dbdir) | 180 | db = Database(args.dbdir) |
162 | 181 | ||
163 | if db.stru: | 182 | if db.stru: |
164 | print("stru") | 183 | print("stru") |
165 | db.stru.dump(args, dokodecode=True) | 184 | db.stru.dump(args) |
166 | if args.struonly: | 185 | if args.struonly: |
167 | return | 186 | return |
168 | if db.index: | 187 | if db.index: |
169 | print("index") | 188 | print("index") |
170 | db.index.dump(args) | 189 | db.index.dump(args, nodecode=True) |
171 | if db.bank: | 190 | if db.bank: |
172 | print("bank") | 191 | print("bank") |
173 | db.bank.dump(args) | 192 | db.bank.dump(args, nodecode=True) |
174 | if db.sys: | 193 | if db.sys: |
175 | print("sys") | 194 | print("sys") |
176 | db.sys.dump(args, dokodecode=True, plainbytes=8) | 195 | db.sys.dump(args) |
177 | 196 | ||
178 | 197 | ||
179 | def main(): | 198 | def main(): |