diff options
| author | itsme <itsme@xs4all.nl> | 2021-07-07 12:25:09 +0200 |
|---|---|---|
| committer | itsme <itsme@xs4all.nl> | 2021-07-07 12:25:09 +0200 |
| commit | a8824d8041a975d6304106dbb33d547a97ada4a1 (patch) | |
| tree | f6426458cc9bef4c8082becd5a9f3339ffa46c90 | |
| parent | bb1e9b68213b74d5c777425bbd8a3a1216b4c4b8 (diff) | |
crodump: the --struonly option now prints detailed info on tables and fields
| -rw-r--r-- | crodump.py | 108 |
1 files changed, 88 insertions, 20 deletions
| @@ -53,7 +53,7 @@ class Datafile: | |||
| 53 | return self.dat.read(size) | 53 | return self.dat.read(size) |
| 54 | 54 | ||
| 55 | def readrec(self, idx): | 55 | def readrec(self, idx): |
| 56 | ofs, ln, chk = self.tabidx[idx-1] | 56 | ofs, ln, chk = self.tadidx[idx-1] |
| 57 | if ln==0xFFFFFFFF: | 57 | if ln==0xFFFFFFFF: |
| 58 | # deleted record | 58 | # deleted record |
| 59 | return | 59 | return |
| @@ -133,6 +133,75 @@ class Datafile: | |||
| 133 | dat = self.readdata(o, l) | 133 | dat = self.readdata(o, l) |
| 134 | print("%08x-%08x: %s" % (o, o+l, toout(args, dat))) | 134 | print("%08x-%08x: %s" % (o, o+l, toout(args, dat))) |
| 135 | 135 | ||
| 136 | def destruct_bank_definition(args, data): | ||
| 137 | """ | ||
| 138 | decode the 'bank' / database definition | ||
| 139 | """ | ||
| 140 | rd = ByteReader(data) | ||
| 141 | |||
| 142 | version = rd.readbyte() | ||
| 143 | print("bank version: %02x" % version) | ||
| 144 | |||
| 145 | d = dict() | ||
| 146 | while not rd.eof(): | ||
| 147 | keyname = rd.readname() | ||
| 148 | if keyname in d: | ||
| 149 | print("WARN: duplicate key: %s" % keyname) | ||
| 150 | |||
| 151 | index_or_length = rd.readdword() | ||
| 152 | if index_or_length >> 31: | ||
| 153 | d[keyname] = rd.readbytes(index_or_length & 0x7FFFFFFF) | ||
| 154 | print("%-20s - %s" % (keyname, toout(args, d[keyname]))) | ||
| 155 | else: | ||
| 156 | d[keyname] = index_or_length | ||
| 157 | print("%-20s -> %s" % (keyname, d[keyname])) | ||
| 158 | return d | ||
| 159 | |||
| 160 | def decode_field(data): | ||
| 161 | rd = ByteReader(data) | ||
| 162 | typ = rd.readword() | ||
| 163 | idx1 = rd.readdword() | ||
| 164 | name = rd.readname() | ||
| 165 | unk1 = rd.readdword() | ||
| 166 | unk2 = rd.readbyte() | ||
| 167 | if typ: | ||
| 168 | idx2 = rd.readdword() | ||
| 169 | unk3 = rd.readdword() | ||
| 170 | unk4 = rd.readdword() | ||
| 171 | remain = rd.readbytes() | ||
| 172 | |||
| 173 | print("%d %2d/%2d %d,%d,%d,%d - '%s' -- %s" % (typ, idx1, idx2, unk1, unk2, unk3, unk4, name, tohex(remain))) | ||
| 174 | else: | ||
| 175 | print("%d %2d %d,%d - '%s'" % (typ, idx1, unk1, unk2, name)) | ||
| 176 | |||
| 177 | |||
| 178 | def destruct_base_definition(args, data): | ||
| 179 | """ | ||
| 180 | decode the 'base' / table definition | ||
| 181 | """ | ||
| 182 | rd = ByteReader(data) | ||
| 183 | |||
| 184 | version = rd.readbyte() | ||
| 185 | print("base version: %02x" % version) | ||
| 186 | unk123 = [rd.readword() for _ in range(3)] | ||
| 187 | unk45 = [rd.readdword() for _ in range(2)] | ||
| 188 | tablename = rd.readname() | ||
| 189 | unkname = rd.readname() | ||
| 190 | unk7 = rd.readdword() | ||
| 191 | nrfields = rd.readdword() | ||
| 192 | print("%d,%d,%d,%d,%d %d,%d '%s' '%s'" % (*unk123, *unk45, unk7, nrfields, tablename, unkname)) | ||
| 193 | fields = [] | ||
| 194 | for _ in range(nrfields): | ||
| 195 | l = rd.readword() | ||
| 196 | fielddef = rd.readbytes(l) | ||
| 197 | if args.verbose: | ||
| 198 | print("field: @%04x: %04x - %s" % (rd.o, l, tohex(fielddef))) | ||
| 199 | fields.append(decode_field(fielddef)) | ||
| 200 | remaining = rd.readbytes() | ||
| 201 | |||
| 202 | print("rem: %s" % tohex(remaining)) | ||
| 203 | |||
| 204 | |||
| 136 | 205 | ||
| 137 | class Database: | 206 | class Database: |
| 138 | """ represent the entire database, consisting of stru, index and bank files """ | 207 | """ represent the entire database, consisting of stru, index and bank files """ |
| @@ -170,6 +239,7 @@ class Database: | |||
| 170 | print("stru") | 239 | print("stru") |
| 171 | self.stru.dump(args) | 240 | self.stru.dump(args) |
| 172 | if args.struonly: | 241 | if args.struonly: |
| 242 | self.dumptabledefs(args) | ||
| 173 | return | 243 | return |
| 174 | if self.index: | 244 | if self.index: |
| 175 | print("index") | 245 | print("index") |
| @@ -181,6 +251,17 @@ class Database: | |||
| 181 | print("sys") | 251 | print("sys") |
| 182 | self.sys.dump(args) | 252 | self.sys.dump(args) |
| 183 | 253 | ||
| 254 | def dumptabledefs(self, args): | ||
| 255 | dbinfo = self.stru.readrec(1) | ||
| 256 | dbdef = destruct_bank_definition(args, dbinfo) | ||
| 257 | |||
| 258 | for i in range(1, 100): | ||
| 259 | idx = dbdef.get("Base%03d" % i) | ||
| 260 | if idx: | ||
| 261 | print("== Base%03d ==" % i) | ||
| 262 | tbinfo = self.stru.readrec(idx) | ||
| 263 | tbdef = destruct_base_definition(args, tbinfo) | ||
| 264 | |||
| 184 | 265 | ||
| 185 | def incdata(data, s): | 266 | def incdata(data, s): |
| 186 | """ | 267 | """ |
| @@ -262,25 +343,10 @@ def destruct(args): | |||
| 262 | data = sys.stdin.buffer.read() | 343 | data = sys.stdin.buffer.read() |
| 263 | data = unhex(data) | 344 | data = unhex(data) |
| 264 | 345 | ||
| 265 | d = dict() | 346 | if args.type==1: |
| 266 | 347 | destruct_bank_definition(args, data) | |
| 267 | rd = ByteReader(data) | 348 | elif args.type==2: |
| 268 | 349 | destruct_base_definition(args, data) | |
| 269 | o = 0 | ||
| 270 | startbyte = rd.readbyte() | ||
| 271 | while not rd.eof(): | ||
| 272 | keylen = rd.readbyte() | ||
| 273 | keyname = rd.readbytes(keylen).decode('ascii') | ||
| 274 | if keyname in d: | ||
| 275 | print("duplicate key: %s" % keyname) | ||
| 276 | |||
| 277 | index_or_length = rd.readdword() | ||
| 278 | if index_or_length >> 31: | ||
| 279 | d[keyname] = rd.readbytes(index_or_length & 0x7FFFFFFF) | ||
| 280 | print("%-20s - %s" % (keyname, toout(args, d[keyname]))) | ||
| 281 | else: | ||
| 282 | d[keyname] = index_or_length | ||
| 283 | print("%-20s -> %s" % (keyname, d[keyname])) | ||
| 284 | 350 | ||
| 285 | def main(): | 351 | def main(): |
| 286 | import argparse | 352 | import argparse |
| @@ -310,7 +376,9 @@ def main(): | |||
| 310 | cro.set_defaults(handler=cro_dump) | 376 | cro.set_defaults(handler=cro_dump) |
| 311 | 377 | ||
| 312 | des = subparsers.add_parser('destruct', help='Stru dumper') | 378 | des = subparsers.add_parser('destruct', help='Stru dumper') |
| 379 | des.add_argument('--verbose', '-v', action='store_true') | ||
| 313 | des.add_argument('--ascdump', '-a', action='store_true') | 380 | des.add_argument('--ascdump', '-a', action='store_true') |
| 381 | des.add_argument('--type', '-t', type=int, help='what type of record to destruct') | ||
| 314 | des.set_defaults(handler=destruct) | 382 | des.set_defaults(handler=destruct) |
| 315 | 383 | ||
| 316 | args = parser.parse_args() | 384 | args = parser.parse_args() |
