import struct header = struct.Struct("<4s5sB") unclear_chunk1 = struct.Struct("<12s1B") unclear_chunk2 = struct.Struct("<12s1B") unclear_chunk3 = struct.Struct("<12s1B") unclear_chunk4 = struct.Struct("<12s1B") unclear_chunk5 = struct.Struct("<12s1B") def modify_tsc(filename, changes): with open(filename, "rb+") as tsc: data = tsc.read() offset = 0 magic, unknown1, map_path_size = header.unpack_from(data, offset) assert magic == b"CTSC", magic print("Processing %s" % filename) offset += header.size map_path = data[offset:offset + map_path_size].decode("ascii") print("Old path: %s" % map_path) offset += map_path_size if changes.map_path is not None: map_path = changes.map_path unknown2, til_path_size = unclear_chunk1.unpack_from(data, offset) offset += unclear_chunk1.size til_path = data[offset:offset + til_path_size].decode("ascii") print("Old path: %s" % til_path) offset += til_path_size if changes.til_path is not None: til_path = changes.til_path unknown3, ocs_path_size = unclear_chunk2.unpack_from(data, offset) offset += unclear_chunk2.size ocs_path = data[offset:offset + ocs_path_size].decode("ascii") print("Old path: %s" % ocs_path) offset += ocs_path_size if changes.ocs_path is not None: ocs_path = changes.ocs_path unknown4, olo_path_size = unclear_chunk3.unpack_from(data, offset) offset += unclear_chunk3.size olo_path = data[offset:offset + olo_path_size].decode("ascii") print("Old path: %s" % olo_path) offset += olo_path_size if changes.olo_path is not None: olo_path = changes.olo_path unknown5, uia_path_size = unclear_chunk4.unpack_from(data, offset) offset += unclear_chunk4.size uia_path = data[offset:offset + uia_path_size].decode("ascii") print("Old path: %s" % uia_path) offset += uia_path_size if changes.uia_path is not None: uia_path = changes.uia_path unknown6, scn_path_size = unclear_chunk5.unpack_from(data, offset) offset += unclear_chunk5.size scn_path = data[offset:offset + scn_path_size].decode("ascii") print("Old path: %s" % scn_path) offset += scn_path_size if changes.scn_path is not None: scn_path = changes.scn_path unknown7 = data[offset:] tsc.seek(0) tsc.write(header.pack(magic, unknown1, len(map_path))) tsc.write(map_path.encode("ascii")) tsc.write(unclear_chunk1.pack(unknown2, len(til_path))) tsc.write(til_path.encode("ascii")) tsc.write(unclear_chunk2.pack(unknown3, len(ocs_path))) tsc.write(ocs_path.encode("ascii")) tsc.write(unclear_chunk2.pack(unknown4, len(olo_path))) tsc.write(olo_path.encode("ascii")) tsc.write(unclear_chunk2.pack(unknown5, len(uia_path))) tsc.write(uia_path.encode("ascii")) tsc.write(unclear_chunk2.pack(unknown6, len(scn_path))) tsc.write(scn_path.encode("ascii")) tsc.write(unknown7) tsc.truncate() if __name__ == "__main__": from optparse import OptionParser parser = OptionParser(description="Modify information in Achron .tsc files", usage="usage: %prog [options] FILE [FILE ...]") parser.add_option("--map-path", dest="map_path", type="string", help="set the path to the .map file", metavar="FILE") parser.add_option("--til-path", dest="til_path", type="string", help="set the path to the .til file", metavar="FILE") parser.add_option("--ocs-path", dest="ocs_path", type="string", help="set the path to the .ocs file", metavar="FILE") parser.add_option("--olo-path", dest="olo_path", type="string", help="set the path to the .olo file", metavar="FILE") parser.add_option("--uia-path", dest="uia_path", type="string", help="set the path to the .uia file", metavar="FILE") parser.add_option("--scn-path", dest="scn_path", type="string", help="set the path to the .scn file", metavar="FILE") options, args = parser.parse_args() for arg in args: modify_tsc(arg, options)