summaryrefslogtreecommitdiff
path: root/crodump.py
diff options
context:
space:
mode:
authoritsme <itsme@xs4all.nl>2021-07-06 19:26:42 +0200
committeritsme <itsme@xs4all.nl>2021-07-06 19:26:42 +0200
commita9886b9d52c3bce0a4b58805b5597efccc55225a (patch)
tree4133e30e57109385ade3f756970058fe1edac255 /crodump.py
initial commit
Diffstat (limited to 'crodump.py')
-rw-r--r--crodump.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/crodump.py b/crodump.py
new file mode 100644
index 0000000..a2a94a1
--- /dev/null
+++ b/crodump.py
@@ -0,0 +1,160 @@
1import os.path
2import struct
3from binascii import b2a_hex
4from hexdump import hexdump, asasc, tohex
5from koddecoder import kodecode
6"""
7python3 crodump.py crodump chechnya_proverki_ul_2012
8python3 crodump.py kodump -s 6 -o 0x4cc9 -e 0x5d95 chechnya_proverki_ul_2012/CroStru.dat
9"""
10
11class Datafile:
12 def __init__(self, dat, tad):
13 self.dat = dat
14 self.tad = tad
15
16 self.readtad()
17
18 def readtad(self):
19 self.tad.seek(0)
20 hdrdata = self.tad.read(2*4)
21 self.tadhdr = struct.unpack("<2L", hdrdata)
22 indexdata = self.tad.read()
23 self.tadidx = [ struct.unpack_from("<3L", indexdata, 12*_) for _ in range(len(indexdata)//12) ]
24
25 def readdata(self, ofs, size):
26 self.dat.seek(ofs)
27 return self.dat.read(size)
28
29 def dump(self, args, dokodecode=False, plainbytes=0):
30 print("tadhdr: %08x %08x" % tuple(self.tadhdr))
31 for i, (ofs, ln, chk) in enumerate(self.tadidx):
32 if ln==0xFFFFFFFF:
33 print("%5d: %08x %08x %08x" % (i, ofs, ln, chk))
34 continue
35 flags = ln>>24
36 ln &= 0xFFFFFFF
37 dat = self.readdata(ofs, ln)
38 plain = b''
39 if dokodecode and not args.nokod:
40 plain = dat[:plainbytes]
41 dat = kodecode(i+1, dat[plainbytes:])
42 if args.ascdump:
43 print("%5d: %08x-%08x: (%02x:%08x) %s %s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), asasc(dat)))
44 else:
45 print("%5d: %08x-%08x: (%02x:%08x) %s %s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), tohex(dat)))
46
47class Database:
48 def __init__(self, dbdir):
49 self.dbdir = dbdir
50
51 self.stru = self.getfile("Stru")
52 self.index = self.getfile("Index")
53 self.bank = self.getfile("Bank")
54 self.sys = self.getfile("Sys")
55
56 def getfile(self, name):
57 try:
58 return Datafile(open(self.getname(name, "dat"), "rb"), open(self.getname(name, "tad"), "rb"))
59 except IOError:
60 return
61
62 def getname(self, name, ext):
63 return os.path.join(self.dbdir, "Cro%s.%s" % (name, ext))
64
65
66def decode_kod(args, data):
67 """
68 various methods of hexdumping KOD decoded data.
69 """
70 if args.nokod:
71 # plain hexdump, no KOD decode
72 hexdump(args.offset, data)
73 elif args.shift:
74 # explicitly specified shift.
75 args.shift = int(args.shift, 0)
76 enc = kodecode(args.shift, data)
77 hexdump(args.offset, enc)
78 else:
79 # output with all possible 'shift' values.
80 for s in range(256):
81 enc = kodecode(s, data)
82 if args.ascdump:
83 print("%02x: %s" % (s, asasc(enc)))
84 else:
85 print("%02x: %s" % (s, tohex(enc)))
86
87
88
89def kod_hexdump(args):
90 """
91 KOD decode a section of a data file
92 """
93 args.offset = int(args.offset, 0)
94 if args.length:
95 args.length = int(args.length, 0)
96 elif args.endofs:
97 args.endofs = int(args.endofs, 0)
98 args.length = args.endofs - args.offset
99
100 if args.filename:
101 with open(args.filename, "rb") as fh:
102 fh.seek(args.offset)
103 data = fh.read(args.length)
104 decode_kod(args, data)
105 else:
106 # no filename -> read from stdin.
107 import sys
108 data = sys.stdin.buffer.read()
109 decode_kod(args, data)
110
111
112def cro_dump(args):
113 db = Database(args.dbdir)
114
115 if db.stru:
116 print("stru")
117 db.stru.dump(args, dokodecode=True)
118 if db.index:
119 print("index")
120 db.index.dump(args)
121 if db.bank:
122 print("bank")
123 db.bank.dump(args)
124 if db.sys:
125 print("sys")
126 db.sys.dump(args, dokodecode=True, plainbytes=8)
127
128
129def main():
130 import argparse
131 parser = argparse.ArgumentParser(description='CRO hexdumper')
132 subparsers = parser.add_subparsers()
133 parser.set_defaults(handler=None)
134
135 ko = subparsers.add_parser('kodump', help='KOD dumper')
136 ko.add_argument('--offset', '-o', type=str, default="0")
137 ko.add_argument('--length', '-l', type=str)
138 ko.add_argument('--endofs', '-e', type=str)
139 ko.add_argument('--shift', '-s', type=str)
140 ko.add_argument('--ascdump', '-a', action='store_true')
141 ko.add_argument('--nokod', '-n', action='store_true')
142 ko.add_argument('filename', type=str, nargs='?')
143 ko.set_defaults(handler=kod_hexdump)
144
145 cro = subparsers.add_parser('crodump', help='CROdumper')
146 cro.add_argument('--kodecode', '-k', action='store_true')
147 cro.add_argument('--ascdump', '-a', action='store_true')
148 cro.add_argument('--nokod', '-n', action='store_true')
149 cro.add_argument('dbdir', type=str)
150 cro.set_defaults(handler=cro_dump)
151
152 args = parser.parse_args()
153
154 if args.handler:
155 args.handler(args)
156
157
158if __name__=='__main__':
159 main()
160