aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcomex <comexk@gmail.com>2009-01-28 12:34:10 -0500
committercomex <comexk@gmail.com>2009-01-28 12:34:10 -0500
commit50d3baa2cdcdfb8ad20bd5cd59cbdcb07db731bc (patch)
tree007da64a2f08737aa9f1561f16b181d46d0ffd33
parent2a0c75e9811b0d66282765a996b7ebebb1ce5c83 (diff)
refactoring
-rw-r--r--ethyl.py143
-rw-r--r--parse-brlyt.py101
2 files changed, 144 insertions, 100 deletions
diff --git a/ethyl.py b/ethyl.py
index 8db217e..2d0d205 100644
--- a/ethyl.py
+++ b/ethyl.py
@@ -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')