diff options
Diffstat (limited to '')
| -rw-r--r-- | ethyl.py | 143 | ||||
| -rw-r--r-- | parse-brlyt.py | 101 |
2 files changed, 144 insertions, 100 deletions
@@ -1,3 +1,4 @@ +import sys, struct, re formats = { 'pane': ''' u8 flags_1 // 8 @@ -61,4 +62,144 @@ formats = { u32 c ''', -}
\ No newline at end of file +} + +for (dname, definition) in formats.items(): + definition = re.sub(re.compile('//.*$', re.M), '', definition) + definition = definition.strip() + definition = re.sub('\n[\n ]+', '\n', definition) + df = [[j.strip() for j in i.strip().split()] for i in definition.split('\n')] + df = [] + etc = etcn = False + for i in definition.split('\n'): + i = i.strip() + if i[:3] == 'etc': + etc = True + if i == 'etc!': + etcn = True + continue + typ, name = [j.strip() for j in i.split()] + m = re.match('^([^\[]+)\[([a-zA-Z0-9]+)\]$', name) + if m: + name = m.group(1) + size = eval(m.group(2)) + df.append((typ, (name, size))) + else: + df.append((typ, name)) + formats[dname] = df, etc, etcn + + + +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 repr(b)) +types = { + 'u8': 'B', + 'u16': 'H', + 'u32': 'I', + 'u64': 'Q', + 's8': 'b', + 's16': 'h', + 's32': 'i', + 's64': 'q', + 'float': 'f', + 'f32': 'f', + 'double': 'd', + 'f64': 'd', + 'bool': 'c', + 'char': 'c', +} +def parse_var(pos, typ, chunk): + 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, prefix=None, start=0): + df, etc, etcn = formats[definition] + #print df, repr(definition) + #print df + + pos = start + ret = {} + for typ, name in df: + try: + name, size = name + except: + pos, var = parse_var(pos, typ, chunk) + else: + 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) + if ret.has_key(name): + try: + ret[name].append(var) + except AttributeError: + ret[name] = [ret[name], var] + else: + ret[name] = var + #print hex(pos) + if pos > len(chunk): + raise Exception('too much!') + if pos < len(chunk): + if etc and not etcn: + ret['etc'] = repr(chunk[pos:]) + elif not etc: + raise Exception('Incomplete handling...') + if prefix is not None: + ret2 = {} + for (k, v) in ret.items(): + ret2[prefix + '.' + k] = v + ret = ret2 + return (ret, pos) if etcn else ret +def unparse_var(typ, var): + if not types.has_key(typ): + raise Exception('What\'s a %s?' % typ) + return struct.pack('>' + types[typ], var) +def unparse_data(vars, definition, prefix=None): + df, etc, etcn = formats[definition] + ret = '' + for typ, name in df: + size = None + try: + name, size = name + except: + pass + if prefix is not None: + name = re.sub('^' + re.quote(prefix) + '\.', '', name) + var = vars[name] + if size is None: + ret += unparse_var(typ, var) + else: + if typ == 'char': + ret += var.ljust(size, '\0') + else: + assert len(var) == size + for v in var: + ret += unparse_var(typ, v) + return 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
\ No newline at end of file diff --git a/parse-brlyt.py b/parse-brlyt.py index 428f1e3..c737970 100644 --- a/parse-brlyt.py +++ b/parse-brlyt.py @@ -1,108 +1,10 @@ import sys, struct, re +from ethyl import * f = open(sys.argv[1], 'rb') rlyt = f.read() f.close() -from ethyl import formats -for (name, definition) in formats.items(): - definition = re.sub(re.compile('//.*$', re.M), '', definition) - definition = definition.strip() - definition = re.sub('\n[\n ]+', '\n', definition) - df = [[j.strip() for j in i.strip().split()] for i in definition.split('\n')] - formats[name] = df - -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 repr(b)) -types = { - 'u8': 'B', - 'u16': 'H', - 'u32': 'I', - 'u64': 'Q', - 's8': 'b', - 's16': 'h', - 's32': 'i', - 's64': 'q', - 'float': 'f', - 'f32': 'f', - 'double': 'd', - 'f64': 'd', - 'bool': 'c', - 'char': 'c', -} -def parse_var(pos, typ, chunk): - 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, prefix=None, start=0): - df = formats[definition][:] - #print df, repr(definition) - print df - etc = df[-1][0][:3] == 'etc' - etcn = etc and df.pop() == ['etc!'] - - pos = start - 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 - #print hex(pos) - if pos > len(chunk): - raise Exception('too much!') - if pos < len(chunk): - if etc and not etcn: - ret['etc'] = repr(chunk[pos:]) - elif not etc: - raise Exception('Incomplete handling...') - if prefix is not None: - ret2 = {} - for (k, v) in ret.items(): - ret2[prefix + '.' + k] = v - ret = ret2 - 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:]) @@ -112,6 +14,7 @@ for typ, chunk in ch: vars = None if typ in ('pic1', 'pan1', 'bnd1', 'wnd1', 'txt1'): vars, pos = parse_data(chunk, 'pane') + assert chunk[:pos] == unparse_data(vars, 'pane') # for testing if typ == 'txt1': vars2, pos = parse_data(chunk[pos:], 'text', '~text') |
