def from_stream(cls, stream, planes_count=3): planes_count = int(planes_count) assert planes_count > 0 plane_offsets = tuple(stream_unpack_array('<L', stream, planes_count)) plane_sizes = tuple(stream_unpack_array('<H', stream, planes_count)) size = stream_unpack('<HH', stream) name = stream_unpack('<16s', stream)[0].decode('ascii') null_char_index = name.find('\0') if null_char_index >= 0: name = name[:null_char_index] name = name.rstrip(' \t\r\n\v\0') return cls(plane_offsets, plane_sizes, size, name)
def from_stream(cls, stream, planes_count=3): planes_count = int(planes_count) assert planes_count > 0 plane_offsets = tuple(stream_unpack_array('<L', stream, planes_count)) plane_sizes = tuple(stream_unpack_array('<H', stream, planes_count)) dimensions = stream_unpack('<HH', stream) name = stream_unpack('<16s', stream)[0].decode('ascii') null_char_index = name.find('\0') if null_char_index >= 0: name = name[:null_char_index] name = name.rstrip(' \t\r\n\v\0') return cls(plane_offsets, plane_sizes, dimensions, name)
def load(self, data_stream, header_stream, data_base=None, data_size=None, header_base=None, header_size=None): super().load(data_stream, data_base, data_size) data_size = self._data_size header_base, header_size = stream_fit(header_stream, header_base, header_size) assert header_size % 4 == 0 chunk_count = header_size // 4 chunk_offsets = list( stream_unpack_array('<L', header_stream, chunk_count)) chunk_offsets.append(data_size) assert all(0 <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._header_stream = header_stream self._header_base = header_base self._header_size = header_size return self
def _read_sounds_infos(self): data_stream = self._data_stream chunk_count = self._chunk_count sounds_start = self.sounds_start assert self.sizeof(chunk_count - 1) % 4 == 0 count = self.sizeof(chunk_count - 1) // 4 self._seek(chunk_count - 1) bounds = list( stream_unpack_array('<HH', data_stream, count, scalar=False)) bounds.append([(chunk_count - sounds_start), bounds[-1][1]]) infos = [None] * count for i in range(count): start, length = bounds[i] if start >= chunk_count - 1: return infos[:i] last = bounds[i + 1][0] if not last or last + sounds_start > chunk_count - 1: last = chunk_count - 1 else: last += sounds_start actual_length = sum( self.sizeof(j) for j in range(sounds_start + start, last)) if actual_length & 0xFFFF0000 and ( actual_length & 0xFFFF) < length: # TBV: really needed? actual_length -= 0x10000 actual_length = (actual_length & 0xFFFF0000) | length infos[i] = (start, actual_length) return infos
def from_stream(cls, stream): length = stream_unpack('<H', stream)[0] assert length % 4 == 0 length //= 4 events = list(stream_unpack_array('<BBH', stream, length, scalar=False)) return cls(events)
def _read_sounds_infos(self): data_stream = self._data_stream chunk_count = self._chunk_count sounds_start = self.sounds_start assert self.sizeof(chunk_count - 1) % struct.calcsize('<HH') == 0 count = self.sizeof(chunk_count - 1) // struct.calcsize('<HH') self._seek(chunk_count - 1) bounds = list(stream_unpack_array('<HH', data_stream, count, scalar=False)) bounds.append([(chunk_count - sounds_start), bounds[-1][1]]) infos = [None] * count for i in range(count): start, length = bounds[i] if start >= chunk_count - 1: return infos[:i] last = bounds[i + 1][0] if not last or last + sounds_start > chunk_count - 1: last = chunk_count - 1 else: last += sounds_start actual_length = sum(self.sizeof(j) for j in range(sounds_start + start, last)) if actual_length & 0xFFFF0000 and (actual_length & 0xFFFF) < length: # FIXME: really needed? actual_length -= 0x10000 actual_length = (actual_length & 0xFFFF0000) | length infos[i] = (start, actual_length) return infos
def load(self, data_stream, data_base=None, data_size=None, dimensions=(64, 64), alpha_index=0xFF, data_size_guard=None): super().load(data_stream, data_base, data_size) data_stream = self._data_stream data_base = self._data_base data_size = self._data_size assert data_size % struct.calcsize('<LH') == 0 alpha_index = int(alpha_index) assert 0x00 <= alpha_index <= 0xFF chunk_count, sprites_start, sounds_start = stream_unpack('<HHH', data_stream) chunk_offsets = list(stream_unpack_array('<L', data_stream, chunk_count)) chunk_offsets.append(data_size) pages_offset = chunk_offsets[0] pages_size = data_size - pages_offset assert data_size_guard is None or data_size < data_size_guard # 100 MiB for i in reversed(range(chunk_count)): if not chunk_offsets[i]: chunk_offsets[i] = chunk_offsets[i + 1] assert all(pages_offset <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._pages_offset = pages_offset self._pages_size = pages_size self._dimensions = dimensions self._alpha_index = alpha_index self.sprites_start = sprites_start self.sounds_start = sounds_start self.sounds_infos = self._read_sounds_infos() return self
def _build_pics_dimensions(self): partition_map = self._partition_map pics_dimensions_index = self._pics_dimensions_index count = partition_map['pics'][1] chunk = self.extract_chunk(pics_dimensions_index) pics_dimensions = list(stream_unpack_array('<HH', io.BytesIO(chunk), count, scalar=False)) return pics_dimensions
def load(self, data_stream, header_stream, huffman_stream, partition_map, pics_size_index=0, data_base=None, data_size=None, header_base=None, header_size=None, huffman_offset=None, huffman_size=None): super().load(data_stream, data_base, data_size) data_size = self._data_size pics_size_index = int(pics_size_index) assert pics_size_index >= 0 header_base, header_size = stream_fit(header_stream, header_base, header_size) huffman_offset, huffman_size = stream_fit(huffman_stream, huffman_offset, huffman_size) assert header_size % 3 == 0 assert huffman_size >= 4 * HUFFMAN_NODE_COUNT chunk_count = header_size // 3 chunk_offsets = [None] * chunk_count for i in range(chunk_count): byte0, byte1, byte2 = stream_unpack('<BBB', header_stream) offset = byte0 | (byte1 << 8) | (byte2 << 16) if offset < 0xFFFFFF: chunk_offsets[i] = offset chunk_offsets.append(data_size) for i in reversed(range(chunk_count)): if chunk_offsets[i] is None: chunk_offsets[i] = chunk_offsets[i + 1] assert all(0 <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) huffman_nodes = list( stream_unpack_array('<HH', huffman_stream, HUFFMAN_NODE_COUNT, scalar=False)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._header_stream = header_stream self._header_base = header_base self._header_size = header_size self._huffman_stream = huffman_stream self._huffman_offset = huffman_offset self._huffman_size = huffman_size self._partition_map = partition_map self._pics_size_index = pics_size_index self._huffman_nodes = huffman_nodes self.pics_size = self._build_pics_size() return self
def _build_pics_size(self): partition_map = self._partition_map pics_size_index = self._pics_size_index count = partition_map['pics'][1] chunk = self.extract_chunk(pics_size_index) pics_size = list( stream_unpack_array('<HH', io.BytesIO(chunk), count, scalar=False)) return pics_size
def load(self, data_stream, header_stream, huffman_stream, partition_map, pics_dimensions_index=0, data_base=None, data_size=None, header_base=None, header_size=None, huffman_offset=None, huffman_size=None): super().load(data_stream, data_base, data_size) data_size = self._data_size pics_dimensions_index = int(pics_dimensions_index) assert pics_dimensions_index >= 0 header_base, header_size = stream_fit(header_stream, header_base, header_size) huffman_offset, huffman_size = stream_fit(huffman_stream, huffman_offset, huffman_size) assert header_size % struct.calcsize('<BBB') == 0 assert huffman_size >= struct.calcsize('<HH') * HUFFMAN_NODES_COUNT chunk_count = header_size // struct.calcsize('<BBB') chunk_offsets = [None] * chunk_count for i in range(chunk_count): byte0, byte1, byte2 = stream_unpack('<BBB', header_stream) offset = byte0 | (byte1 << 8) | (byte2 << 16) if offset < 0xFFFFFF: chunk_offsets[i] = offset chunk_offsets.append(data_size) for i in reversed(range(chunk_count)): if chunk_offsets[i] is None: chunk_offsets[i] = chunk_offsets[i + 1] assert all(0 <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) huffman_nodes = list(stream_unpack_array('<HH', huffman_stream, HUFFMAN_NODES_COUNT, scalar=False)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._header_stream = header_stream self._header_base = header_base self._header_size = header_size self._huffman_stream = huffman_stream self._huffman_offset = huffman_offset self._huffman_size = huffman_size self._partition_map = partition_map self._pics_dimensions_index = pics_dimensions_index self._huffman_nodes = huffman_nodes self.pics_dimensions = self._build_pics_dimensions() return self
def load(self, data_stream, data_base=None, data_size=None, image_size=(64, 64), alpha_index=0xFF, data_size_guard=None): super().load(data_stream, data_base, data_size) data_stream = self._data_stream data_base = self._data_base data_size = self._data_size assert data_size % 6 == 0 alpha_index = int(alpha_index) assert 0x00 <= alpha_index <= 0xFF chunk_count, sprites_start, sounds_start = stream_unpack( '<HHH', data_stream) chunk_offsets = list( stream_unpack_array('<L', data_stream, chunk_count)) chunk_offsets.append(data_size) pages_offset = chunk_offsets[0] pages_size = data_size - pages_offset assert data_size_guard is None or data_size < data_size_guard for i in reversed(range(chunk_count)): if not chunk_offsets[i]: chunk_offsets[i] = chunk_offsets[i + 1] assert all(pages_offset <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._pages_offset = pages_offset self._pages_size = pages_size self._image_size = image_size self._alpha_index = alpha_index self.sprites_start = sprites_start self.sounds_start = sounds_start self.sounds_infos = self._read_sounds_infos() return self
def load(self, data_stream, header_stream, data_base=None, data_size=None, header_base=None, header_size=None): super().load(data_stream, data_base, data_size) data_size = self._data_size header_base, header_size = stream_fit(header_stream, header_base, header_size) assert header_size % struct.calcsize('<L') == 0 chunk_count = header_size // struct.calcsize('<L') chunk_offsets = list(stream_unpack_array('<L', header_stream, chunk_count)) chunk_offsets.append(data_size) assert all(0 <= chunk_offsets[i] <= data_size for i in range(chunk_count)) assert all(chunk_offsets[i] <= chunk_offsets[i + 1] for i in range(chunk_count)) self._chunk_count = chunk_count self._chunk_offsets = chunk_offsets self._header_stream = header_stream self._header_base = header_base self._header_size = header_size return self
def from_stream(cls, chunk_stream): height = stream_unpack('<H', chunk_stream)[0] offsets = list(stream_unpack_array('<H', chunk_stream, cls.CHARACTER_COUNT)) widths = list(stream_unpack_array('<B', chunk_stream, cls.CHARACTER_COUNT)) return cls(height, offsets, widths)
def from_stream(cls, chunk_stream): left, right = stream_unpack('<HH', chunk_stream) width = right - left + 1 offsets = list(stream_unpack_array('<H', chunk_stream, width)) return cls(left, right, offsets)