summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritsme <itsme@xs4all.nl>2021-07-12 23:00:24 +0200
committeritsme <itsme@xs4all.nl>2021-07-12 23:06:55 +0200
commitaccc195b894c45f1a9a837188d38bf9df1ab0fd5 (patch)
tree7e10395b56d469e806d3fae6f4d9050f4d2cf5e5
parent1ff6d6d7a20ca924998374ee54cede1f86450d52 (diff)
now handling long compressed records.
-rw-r--r--crodump.py55
1 files changed, 45 insertions, 10 deletions
diff --git a/crodump.py b/crodump.py
index 1b2540f..77f00e9 100644
--- a/crodump.py
+++ b/crodump.py
@@ -87,6 +87,9 @@ class Datafile:
87 return self.dat.read(size) 87 return self.dat.read(size)
88 88
89 def readrec(self, idx): 89 def readrec(self, idx):
90 """
91 extract and decode a single record.
92 """
90 ofs, ln, chk = self.tadidx[idx-1] 93 ofs, ln, chk = self.tadidx[idx-1]
91 if ln==0xFFFFFFFF: 94 if ln==0xFFFFFFFF:
92 # deleted record 95 # deleted record
@@ -120,6 +123,9 @@ class Datafile:
120 123
121 124
122 def dump(self, args): 125 def dump(self, args):
126 """
127 dump decodes all references data, and optionally will print out all unused bytes in the .dat file.
128 """
123 print("hdr: %-6s dat: %04x %s enc:%04x bs:%04x, tad: %08x %08x" % (self.name, self.hdrunk, self.version, self.encoding, self.blocksize, self.nrdeleted, self.firstdeleted)) 129 print("hdr: %-6s dat: %04x %s enc:%04x bs:%04x, tad: %08x %08x" % (self.name, self.hdrunk, self.version, self.encoding, self.blocksize, self.nrdeleted, self.firstdeleted))
124 ranges = [] # keep track of used bytes in the .dat file. 130 ranges = [] # keep track of used bytes in the .dat file.
125 for i, (ofs, ln, chk) in enumerate(self.tadidx): 131 for i, (ofs, ln, chk) in enumerate(self.tadidx):
@@ -183,20 +189,31 @@ class Datafile:
183 print("%08x-%08x: %s" % (o, o+l, toout(args, dat))) 189 print("%08x-%08x: %s" % (o, o+l, toout(args, dat)))
184 190
185 def iscompressed(self, data): 191 def iscompressed(self, data):
192 """
193 Note that the compression header uses big-endian numbers.
194 """
186 if len(data)<11: 195 if len(data)<11:
187 return 196 return
188 size, flag = struct.unpack_from(">HH", data, 0)
189 if size+5 != len(data):
190 return
191 if flag!=0x800:
192 return
193 if data[-3:] != b"\x00\x00\x02": 197 if data[-3:] != b"\x00\x00\x02":
194 return 198 return
199 o = 0
200 while o < len(data)-3:
201 size, flag = struct.unpack_from(">HH", data, o)
202 if flag!=0x800 and flag!=0x008:
203 return
204 o += size + 2
195 return True 205 return True
196 206
197 def decompress(self, data): 207 def decompress(self, data):
198 C = zlib.decompressobj(-15) 208 result = b""
199 return C.decompress(data[8:-3]) 209 o = 0
210 while o < len(data)-3:
211 size, flag, crc = struct.unpack_from(">HHL", data, o)
212 C = zlib.decompressobj(-15)
213 result += C.decompress(data[o+8:o+8+size])
214 o += size + 2
215 return result
216
200 217
201def dump_bank_definition(args, bankdict): 218def dump_bank_definition(args, bankdict):
202 """ 219 """
@@ -222,9 +239,9 @@ def decode_field(data):
222 unk4 = rd.readdword() # Always 0x00000009 or 0x0001000d 239 unk4 = rd.readdword() # Always 0x00000009 or 0x0001000d
223 remain = rd.readbytes() 240 remain = rd.readbytes()
224 241
225 print("Type: %d (%02d/%02d) %04x,(%d-%d),%04x - '%s' -- %s" % (typ, idx1, idx2, unk1, unk2, unk3, unk4, name, tohex(remain))) 242 print("Type: %2d (%2d/%2d) %04x,(%d-%4d),%04x - '%s' -- %s" % (typ, idx1, idx2, unk1, unk2, unk3, unk4, name, tohex(remain)))
226 else: 243 else:
227 print("Type: %d %2d %d,%d - '%s'" % (typ, idx1, unk1, unk2, name)) 244 print("Type: %2d %2d %d,%d - '%s'" % (typ, idx1, unk1, unk2, name))
228 245
229 246
230def destruct_base_definition(args, data): 247def destruct_base_definition(args, data):
@@ -239,7 +256,10 @@ def destruct_base_definition(args, data):
239 unkname = rd.readname() 256 unkname = rd.readname()
240 unk7 = rd.readdword() 257 unk7 = rd.readdword()
241 nrfields = rd.readdword() 258 nrfields = rd.readdword()
259 if args.verbose:
260 print("table: %s" % tohex(data[:rd.o]))
242 print("%d,%d,%d,%d,%d %d,%d '%s' '%s'" % (*unk123, *unk45, unk7, nrfields, tablename, unkname)) 261 print("%d,%d,%d,%d,%d %d,%d '%s' '%s'" % (*unk123, *unk45, unk7, nrfields, tablename, unkname))
262
243 fields = [] 263 fields = []
244 for _ in range(nrfields): 264 for _ in range(nrfields):
245 l = rd.readword() 265 l = rd.readword()
@@ -363,12 +383,20 @@ class Database:
363 if not self.bank: 383 if not self.bank:
364 print("No CroBank.dat found") 384 print("No CroBank.dat found")
365 return 385 return
386 if args.skipencrypted and self.bank.encoding==3:
387 print("Skipping encrypted CroBank")
388 return
366 nerr = 0 389 nerr = 0
367 xref = defaultdict(int) 390 xref = defaultdict(int)
368 for i in range(args.maxrecs): 391 for i in range(args.maxrecs):
369 try: 392 try:
370 data = self.bank.readrec(i) 393 data = self.bank.readrec(i)
371 if not args.stats: 394 if args.find1d:
395 if data and (data.find(b"\x1d")>0 or data.find(b"\x1b")>0):
396 print("%d -> %s" % (i, b2a_hex(data)))
397 break
398
399 elif not args.stats:
372 if data is None: 400 if data is None:
373 print("%5d: <deleted>" % i) 401 print("%5d: <deleted>" % i)
374 else: 402 else:
@@ -393,6 +421,11 @@ class Database:
393 for k, v in xref.items(): 421 for k, v in xref.items():
394 print("%5d * %s" % (v, k)) 422 print("%5d * %s" % (v, k))
395 423
424 def readrec(self, sysnum):
425 data = self.bank.readrec(sysnum)
426 tabnum, = struct.unpack_from("<B", data, 0)
427 fields = data[1:].split(b"\x1e")
428
396def incdata(data, s): 429def incdata(data, s):
397 """ 430 """
398 add 's' to each byte. 431 add 's' to each byte.
@@ -543,6 +576,8 @@ def main():
543 p.add_argument('--verbose', '-v', action='store_true') 576 p.add_argument('--verbose', '-v', action='store_true')
544 p.add_argument('--ascdump', '-a', action='store_true') 577 p.add_argument('--ascdump', '-a', action='store_true')
545 p.add_argument('--maxrecs', '-n', type=str, help="max nr or recots to output") 578 p.add_argument('--maxrecs', '-n', type=str, help="max nr or recots to output")
579 p.add_argument('--find1d', action='store_true')
580 p.add_argument('--inclencrypted', action='store_false', dest='skipencrypted', default='true', help='include encrypted records in the output')
546 p.add_argument('--stats', action='store_true', help='calc table stats from the first byte of each record') 581 p.add_argument('--stats', action='store_true', help='calc table stats from the first byte of each record')
547 p.add_argument('dbdir', type=str) 582 p.add_argument('dbdir', type=str)
548 p.set_defaults(handler=bank_dump) 583 p.set_defaults(handler=bank_dump)