def write_typetree(obj: dict, nodes: List[Union[dict, TypeTreeNode]], writer: EndianBinaryWriter = None) -> EndianBinaryWriter: """Writes the data of the object via the given typetree of the object into the writer. Parameters ---------- obj : dict Object to be saved nodes : list List of nodes/nodes writer : EndianBinaryWriter Writer of the object to be saved Returns ------- EndianBinaryWriter The writer that was used to save the data of the given object. """ if not writer: writer = EndianBinaryWriter() nodes = check_nodes(nodes) i = c_uint32(1) while i.value < len(nodes): value = obj[nodes[i.value].name] write_value(value, nodes, writer, i) i.value += 1 return writer
def subsound_to_wav(subsound): # get sound settings length = subsound.get_length(0x00000004) # TIMEUNIT.PCMBYTES channels = subsound.format.channels bits = subsound.format.bits sample_rate = int(subsound.default_frequency) # write to buffer w = EndianBinaryWriter(endian="<") # riff chucnk w.write(b"RIFF") w.write_int(length + 36) # sizeof(FmtChunk) + sizeof(RiffChunk) + length w.write(b"WAVE") # fmt chunck w.write(b"fmt ") w.write_int(16) # sizeof(FmtChunk) - sizeof(RiffChunk) w.write_short(1) w.write_short(channels) w.write_int(sample_rate) w.write_int(sample_rate * channels * bits // 8) w.write_short(channels * bits // 8) w.write_short(bits) # data chunck w.write(b"data") w.write_int(length) # data lock = subsound.lock(0, length) for ptr, length in lock: ptr_data = string_at(ptr, length.value) w.write(ptr_data) subsound.unlock(*lock) return w.bytes
def write_value(value: Any, nodes: List[TypeTreeNode], writer: EndianBinaryWriter, i: c_uint32): node = nodes[i.value] typ = node.type align = (node.meta_flag & 0x4000) != 0 if typ == "SInt8": writer.write_byte(value) elif typ in ["UInt8", "char"]: writer.write_u_byte(value) elif typ in ["short", "SInt16"]: writer.write_short(value) elif typ in ["UInt16", "unsigned short"]: writer.write_u_short(value) elif typ in ["int", "SInt32"]: writer.write_int(value) elif typ in ["UInt32", "unsigned int", "Type*"]: writer.write_u_int(value) elif typ in ["long long", "SInt64"]: writer.write_long(value) elif typ in ["UInt64", "unsigned long long", "FileSize"]: writer.write_u_long(value) elif typ == "float": writer.write_float(value) elif typ == "double": writer.write_double(value) elif typ == "bool": writer.write_boolean(value) elif typ == "string": writer.write_aligned_string(value) i.value += 3 # Array, Size, Data(typ) elif typ == "map": if (nodes[i.value + 1].meta_flag & 0x4000) != 0: align = True map_ = get_nodes(nodes, i.value) i.value += len(map_) - 1 first = get_nodes(map_, 4) second = get_nodes(map_, 4 + len(first)) # size writer.write_int(len(value)) # data for key, val in value: write_value(key, first, writer, c_uint32(0)) write_value(val, second, writer, c_uint32(0)) elif typ == "TypelessData": writer.write_int(len(value)) writer.write_bytes(value) i.value += 2 # Size == int, Data(typ) == char/uint8 else: # Vector if i.value < len(nodes) - 1 and nodes[i.value + 1].type == "Array": if (nodes[i.value + 1].meta_flag & 0x4000) != 0: align = True vector = get_nodes(nodes, i.value) i.value += len(vector) - 1 writer.write_int(len(value)) for val in value: write_value(val, vector, writer, c_uint32(3)) else: # Class clz = get_nodes(nodes, i.value) i.value += len(clz) - 1 j = c_uint32(1) while j.value < len(clz): val = value[clz[j.value].name] write_value(val, clz, writer, j) j.value += 1 if align: writer.align_stream()