import struct, sys, zlib, os from collections import OrderedDict from cStringIO import StringIO if(len(sys.argv) < 4): print("Usage: python dtls.py dt ls ") sys.exit(0) dtfn, lsfn, outdir = sys.argv[1:] dtfp = open(dtfn, 'rb') lsfp = open(lsfn, 'rb') dtlstype = (struct.unpack('> 16 #Magic + Version count, = struct.unpack('> 24 name_offset = name_offset_etc & 0xfffff name = get_from_offset(name_offset, 128) if name_offset_etc & 0x00800000: reference, = struct.unpack('> 6 << 8 | (reference >> 8) name = get_from_offset(name_offset - ref_reloff, ref_len) + name[2:] if '\0' in name: name = name[:name.find('\0')] name += extensions[ext] nesting_level = derp1 & 0xff localized = bool(derp1 & 0x800) final = bool(derp1 & 0x400) compressed = bool(derp1 & 0x200) parts = parts[:nesting_level - 1] + [name] path = ''.join(parts) if final: start, size = None, None crc_path = 'data/' + path.rstrip('/') + ('/packed' if compressed else '') crc = stupidcrc(crc_path) if crc in dt_offsets: offset = dt_offsets[crc] else: offset = None else: offset = None offset_parts = offset_parts[:nesting_level - 1] + [offset] outfn = os.path.join(outdir, path) if path.endswith('/'): if not os.path.exists(outfn): os.mkdir(outfn) else: for part in offset_parts[::-1]: if part is not None: chunk_start, chunk_size = part break else: continue assert off_in_chunk + cmp_size <= chunk_size dtfp.seek(chunk_start + off_in_chunk) cmp_data = dtfp.read(cmp_size) # XXX why isn't 'compressed' right? if cmp_data.startswith('x\x9c'): file_data = zlib.decompress(cmp_data) else: file_data = cmp_data assert len(file_data) == dec_size open(outfn, 'wb').write(file_data) resource_total_size += cmp_size if 0: for missing in set(dt_offsets.keys()) - known_crcs: print 'Missing', missing