diff options
| author | comex <comexk@gmail.com> | 2009-01-27 19:45:08 -0500 |
|---|---|---|
| committer | comex <comexk@gmail.com> | 2009-01-27 19:45:08 -0500 |
| commit | 0a8406b37fdcaa42212914c0420d8394ba4dde02 (patch) | |
| tree | 2f3f4eed97fcd490d7ea724599fa742c9cbe4047 /parse-brlyt.py | |
| parent | c0c8423ca06336ffdf8061a8ee02616ae16c7fc9 (diff) | |
parse-brlyt
Diffstat (limited to '')
| -rw-r--r-- | parse-brlyt.py | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/parse-brlyt.py b/parse-brlyt.py new file mode 100644 index 0000000..6f1b58f --- /dev/null +++ b/parse-brlyt.py @@ -0,0 +1,146 @@ +import sys, struct, re +f = open(sys.argv[1], 'rb') +rlyt = f.read() +f.close() +def pr_dict(data, start=''): + for a in sorted(data.keys()): + b = data[a] + print '%s%s: %s' % (start, str(a), hex(b) if type(b) in (int, long) else str(b)) +def parse_var(pos, typ, chunk): + types = { + 'u16': 'H', + 'u32': 'I', + 'u64': 'Q', + 's16': 'h', + 's32': 'i', + 's64': 'q', + 'float': 'f', + 'f32': 'f', + 'double': 'd', + 'f64': 'd', + 'bool': 'c', + 'char': 'c', + } + if not types.has_key(typ): + raise Exception('What\'s a %s?' % typ) + fmt = '>' + types[typ] + size = struct.calcsize(fmt) + + return (pos + size), struct.unpack(fmt, chunk[pos:pos + size])[0] +def nullterm(str_plus): + z = str_plus.find('\0') + if z != -1: + return str_plus[:z] + else: + return str_plus +def parse_data(chunk, definition): + df = [[j.strip() for j in i.strip().split()] for i in definition.strip().split('\n')] + + etc = df[-1][0][:3] == 'etc' + etcn = etc and df.pop() == ['etc!'] + + pos = 0 + ret = {} + for typ, name in df: + m = re.match('^([^\[]+)\[([a-zA-Z0-9]+)\]$', name) + if m: + name = m.group(1) + size = eval(m.group(2)) + if typ == 'char': + var = chunk[pos:pos+size].rstrip(chr(0)) + pos += size + else: + var = [] + for n in xrange(size): + pos, varn = parse_var(pos, typ, chunk) + var.append(varn) + else: + pos, var = parse_var(pos, typ, chunk) + if ret.has_key(name): + try: + ret[name].append(var) + except AttributeError: + ret[name] = [ret[name], var] + else: + ret[name] = var + if not etc and pos != len(chunk): + raise Exception('Incomplete handling...') + return (ret, pos) if etcn else ret + +def iff_to_chunks(z): + pos = 0 + chunks = [] + while pos < len(z): + cc = z[pos:pos+4] + length, = struct.unpack('>I', z[pos+4:pos+8]) + #print cc + #print hex(length) + data = z[pos+8:pos+length] + pos += length + chunks.append((cc, data)) + return chunks +assert rlyt[0:8] == 'RLYT\xfe\xff\x00\x08' +offs, = struct.unpack('>h', rlyt[0xc:0xe]) +ch = iff_to_chunks(rlyt[offs:]) +indent = 0 +for typ, chunk in ch: + print ' ' * indent + typ + ' ' + hex(len(chunk)) + vars = None + if typ in ('pic1', 'pan1', 'bnd1', 'wnd1'): + vars = parse_data(chunk, ''' + u16 flags + u16 alpha + char name[0x18] + float x + float y + float unk[3] + float angle + float xmag + float ymag + float width + float height + etc + ''') + elif typ == 'lyt1': + vars = parse_data(chunk, ''' + u32 unk[3] + ''') + elif typ == 'grp1': + print repr(chunk) + vars, pos = parse_data(chunk, ''' + char name[16] + u16 numsubs + u16 unk + etc! + ''') + vars['subs'] = [] + for n in xrange(vars['numsubs']): + vars['subs'].append(nullterm(chunk[pos:pos+16])) + pos += 16 + elif typ in ('txl1', 'fnl1', 'mat1'): + things = {'txl1': 'textures', 'fnl1': 'files', 'mat1': 'materials'}[typ] + vars, pos = parse_data(chunk, ''' + u16 num + u16 offs + etc! + ''') + vars[things] = [] + pos += vars['offs'] + del vars['offs'] # unneeded + for n in xrange(vars['num']): + if typ == 'mat1': + offset, = struct.unpack('>I', chunk[pos:pos+4]) + pos += 4 + else: + offset, unk = struct.unpack('>II', chunk[pos:pos+8]) + pos += 8 + name = nullterm(chunk[offset - 8:]) + vars[things].append(name if typ == 'mat1' else {'name': name, 'unk': unk}) + elif typ in ('grs1', 'pas1'): + indent += 1 + elif typ in ('gre1', 'pae1'): + indent -= 1 + else: + print repr(chunk) + if vars: pr_dict(vars, ' ' * indent + ' ') +#print hex(len(ch)) |
