summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@bauklotz.fritz.box>2021-07-13 02:10:46 +0200
committerDirk Engling <erdgeist@bauklotz.fritz.box>2021-07-13 02:10:46 +0200
commitc31eb7a3581d3aa58d98292ff878f29b3a10915a (patch)
tree587eafa40c635b14689b0b61a215f4994f05027c
parent07a020d9dd72f758e4e0d0323a9c13a0ac5f1848 (diff)
parent08cd88ef3ac85a6c6e8071d9b055e6a29c5e711f (diff)
Fix merge conflict
-rw-r--r--crodump.py56
-rw-r--r--docs/cronos-research.md14
2 files changed, 55 insertions, 15 deletions
diff --git a/crodump.py b/crodump.py
index d668915..d0cd67c 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"""
230 2 Base000 - 000001 050001 000000000000000546696c657302464c01000000010000001b000000000000000fd1e8f1f2e5ecedfbe920edeeece5f0010000000000000000010000000000000000 247 2 Base000 - 000001 050001 000000000000000546696c657302464c01000000010000001b000000000000000fd1e8f1f2e5ecedfbe920edeeece5f0010000000000000000010000000000000000
@@ -272,7 +289,11 @@ def destruct_base_definition(args, data):
272 abbrev = rd.readname() 289 abbrev = rd.readname()
273 unk7 = rd.readdword() 290 unk7 = rd.readdword()
274 nrfields = rd.readdword() 291 nrfields = rd.readdword()
292
293 if args.verbose:
294 print("table: %s" % tohex(data[:rd.o]))
275 print("%d,%d,%d,%d,%d,%d %d,%d '%s' '%s'" % (unk1, version, unk2, unk3, unk4, unk5, unk7, nrfields, tablename, abbrev)) 295 print("%d,%d,%d,%d,%d,%d %d,%d '%s' '%s'" % (unk1, version, unk2, unk3, unk4, unk5, unk7, nrfields, tablename, abbrev))
296
276 fields = [] 297 fields = []
277 for _ in range(nrfields): 298 for _ in range(nrfields):
278 l = rd.readword() 299 l = rd.readword()
@@ -396,12 +417,20 @@ class Database:
396 if not self.bank: 417 if not self.bank:
397 print("No CroBank.dat found") 418 print("No CroBank.dat found")
398 return 419 return
420 if args.skipencrypted and self.bank.encoding==3:
421 print("Skipping encrypted CroBank")
422 return
399 nerr = 0 423 nerr = 0
400 xref = defaultdict(int) 424 xref = defaultdict(int)
401 for i in range(args.maxrecs): 425 for i in range(args.maxrecs):
402 try: 426 try:
403 data = self.bank.readrec(i) 427 data = self.bank.readrec(i)
404 if not args.stats: 428 if args.find1d:
429 if data and (data.find(b"\x1d")>0 or data.find(b"\x1b")>0):
430 print("%d -> %s" % (i, b2a_hex(data)))
431 break
432
433 elif not args.stats:
405 if data is None: 434 if data is None:
406 print("%5d: <deleted>" % i) 435 print("%5d: <deleted>" % i)
407 else: 436 else:
@@ -426,6 +455,11 @@ class Database:
426 for k, v in xref.items(): 455 for k, v in xref.items():
427 print("%5d * %s" % (v, k)) 456 print("%5d * %s" % (v, k))
428 457
458 def readrec(self, sysnum):
459 data = self.bank.readrec(sysnum)
460 tabnum, = struct.unpack_from("<B", data, 0)
461 fields = data[1:].split(b"\x1e")
462
429def incdata(data, s): 463def incdata(data, s):
430 """ 464 """
431 add 's' to each byte. 465 add 's' to each byte.
@@ -576,6 +610,8 @@ def main():
576 p.add_argument('--verbose', '-v', action='store_true') 610 p.add_argument('--verbose', '-v', action='store_true')
577 p.add_argument('--ascdump', '-a', action='store_true') 611 p.add_argument('--ascdump', '-a', action='store_true')
578 p.add_argument('--maxrecs', '-n', type=str, help="max nr or recots to output") 612 p.add_argument('--maxrecs', '-n', type=str, help="max nr or recots to output")
613 p.add_argument('--find1d', action='store_true')
614 p.add_argument('--inclencrypted', action='store_false', dest='skipencrypted', default='true', help='include encrypted records in the output')
579 p.add_argument('--stats', action='store_true', help='calc table stats from the first byte of each record') 615 p.add_argument('--stats', action='store_true', help='calc table stats from the first byte of each record')
580 p.add_argument('dbdir', type=str) 616 p.add_argument('dbdir', type=str)
581 p.set_defaults(handler=bank_dump) 617 p.set_defaults(handler=bank_dump)
diff --git a/docs/cronos-research.md b/docs/cronos-research.md
index 1ee75c4..5d0a508 100644
--- a/docs/cronos-research.md
+++ b/docs/cronos-research.md
@@ -157,7 +157,9 @@ The toplevel table-id for CroStru and CroSys is #3, while referenced records hav
157 157
158CroBank.dat contains the actual database entries for multiple tables as described in the CroStru file. After each chunk is re-assembled (and potentially decoded with the per block offset being the record number in the .tad file). 158CroBank.dat contains the actual database entries for multiple tables as described in the CroStru file. After each chunk is re-assembled (and potentially decoded with the per block offset being the record number in the .tad file).
159 159
160Its first byte defines, which table it belongs to. It is encoded in cp1251 (or possibly IBM866) with actual column data separated by 0x1e. There is an extra concept of sub fields in those columns, indicated by a 0x1d byte. 160Its first byte defines, which table it belongs to. It is encoded in cp1251 (or possibly IBM866) with actual column data separated by 0x1e.
161There is an extra concept of sub fields in those columns, indicated by a 0x1d byte.
162Also files seem have have special fields, starting with a 0x1b byte.
161 163
162 164
163## structure definitions 165## structure definitions
@@ -246,10 +248,12 @@ Other unassigned values in the table entry definition are
246 248
247some records are compressed, the format is like this: 249some records are compressed, the format is like this:
248 250
249 uint16 size 251 multiple-chunks {
250 uint8 head[2] = { 8, 0 } 252 uint16 size; // stored in bigendian format.
251 uint32 crc32 253 uint8 head[2] = { 8, 0 }
252 uint8 compdata[size-4] 254 uint32 crc32
255 uint8 compdata[size-6]
256 }
253 uint8 tail[3] = { 0, 0, 2 } 257 uint8 tail[3] = { 0, 0, 2 }
254 258
255## encrypted records 259## encrypted records