Ejemplo n.º 1
0
    def write_stream(self, stream):
        if not isinstance(stream, BinaryWriter):
            wtr = BinaryWriter(stream)
        else:
            wtr = stream

        wtr.write(self.original_header)
        wtr.seek(0)
        wtr.write(self.chunk_id)
        wtr.seek(0x31)
        wtr.write_uint8(self.loop_flag)
        wtr.write_uint8(self.channels)

        coding = self.coding
        if self.sample_rate == 32728:
            coding |= 4
        elif self.sample_rate == 16364:
            coding |= 2
        else:
            raise NotImplementedError()

        wtr.seek(0x100)
        buffer = self.buffer.copy()
        buffer = buffer.reshape((buffer.shape[0], buffer.shape[1] // 0x10, 0x10))
        buffer = buffer.swapaxes(0, 1)
        wtr.write(buffer.tobytes())

        size = wtr.tell()
        wtr.seek(0x40)
        wtr.write_uint32(size)
Ejemplo n.º 2
0
def decompress(data: bytes):
    rdr = BinaryReader(data)
    wtr = BinaryWriter()
    type = rdr.read_uint8()
    if type != 0x30:
        raise Exception("Tried to decompress commands that isn't RLE")
    ds = rdr.read_uint24()
    if ds == 0:
        rdr.read_uint32()

    while True:
        flag = rdr.read_uint8()
        if flag is None:
            break  # we've hit the end
        compressed = (flag & 0x80) > 0
        lenght = flag & 0x7f
        lenght += 3 if compressed else 1
        if compressed:
            next = rdr.read_uint8()
            for i in range(lenght):
                wtr.write_uint8(next)
        else:
            wtr.write(rdr.read(lenght))

    return wtr.data
Ejemplo n.º 3
0
def decompress(data: bytes) -> bytes:
    rdr = BinaryReader(data)
    wtr = BinaryWriter()
    compression_type = rdr.read_uint8()
    if compression_type == 0x24:
        blocksize = 4
    elif compression_type == 0x28:
        blocksize = 8
    else:
        raise Exception(
            "Tried to decompress something as huffman that isn't huffman")
    ds = rdr.read_uint24()
    if ds == 0:
        rdr.read_uint32()

    # Read the tree
    treesize = (rdr.read_uint8() + 1) * 2
    tree_end = (rdr.c - 1) + treesize
    rootNode = HuffTreeNode.from_rdr(rdr, False, 5, tree_end)
    rdr.c = tree_end

    # Decompress with the tree
    bitsleft = 0  # amount of bits left to read from {commands}
    current_size = 0
    currentNode = rootNode

    cashedbyte = -1

    while current_size < ds:
        # Find next refrence to commands node
        while not currentNode.is_data:
            if bitsleft == 0:
                data = rdr.read_uint32()
                bitsleft = 32

            bitsleft -= 1
            nextIsOne = (data & (1 << bitsleft)) != 0
            if nextIsOne:
                currentNode = currentNode.child1
            else:
                currentNode = currentNode.child0

        if blocksize == 8:
            current_size += 1
            wtr.write_uint8(currentNode.data)

        elif blocksize == 4:
            if cashedbyte < 0:
                cashedbyte = currentNode.data
            else:
                cashedbyte |= currentNode.data << 4
                wtr.write_uint8(cashedbyte)
                current_size += 1
                cashedbyte = -1
        currentNode = rootNode

    return wtr.data
Ejemplo n.º 4
0
 def write(self, bw: BinaryWriter):
     bw.seek(0x40, io.SEEK_SET)
     bw.write(self.label)
     bw.write_uint32(self.unk1)
     bw.write_uint32(0xFF10)
     bw.write_uint32(0xFFFFFFB0)
     bw.write_uint16(0x1)
     bw.write_uint16(self.tpqn)
     bw.write_uint16(0xFF01)
     bw.write_uint8(self.num_tracks)
     bw.write_uint8(self.num_channels)
     bw.write_uint32(0x0F000000)
     bw.write_uint32(0xFFFFFFFF)
     bw.write_uint32(0x40000000)
     bw.write_uint32(0x00404000)
     bw.write_uint16(0x0200)
     bw.write_uint16(0x0800)
     bw.write_uint32(0xFFFFFF00)
     bw.write(b"\xFF" * 16)
Ejemplo n.º 5
0
def pcm16_to_adpcm(pcm16: np.ndarray):
    enc_sample = pcm16_to_adpcm_encode_sample

    # Uses BytesIO which is faster then concatination.
    wtr = BinaryWriter()

    wtr.write_uint16(pcm16[0])
    sample, enc_index, enc_pred = enc_sample(pcm16[0], 0, 0)
    wtr.write_uint16(enc_index)

    for i in range(1, len(pcm16)):
        if sample is None:
            sample, enc_index, enc_pred = \
                enc_sample(pcm16[0], enc_index, enc_pred)
        else:
            sample2, enc_index, enc_pred = \
                enc_sample(pcm16[0], enc_index, enc_pred)
            wtr.write_byte(sample2 << 4 | sample)
            sample = None

    if sample is not None:
        wtr.write_uint8(sample)
    return wtr.data
Ejemplo n.º 6
0
 def write_stream(self, stream: BinaryIO):
     if isinstance(stream, BinaryWriter):
         wtr = stream
     else:
         wtr = BinaryWriter(stream)
     wtr.write_uint32(0)  # placeholder for file length
     for p in self.params:
         if isinstance(p, int):
             wtr.write_uint16(1)
             wtr.write_uint32(p)
         elif isinstance(p, float):
             wtr.write_uint16(2)
             wtr.write_float(p)
         elif isinstance(p, str):
             wtr.write_uint16(3)
             wtr.write_uint16(len(p) + 1)
             wtr.write_string(p)
             wtr.write_uint8(0)
     for c in self.commands:
         wtr.write_uint16(0)
         wtr.write_uint16(c.command)
         for p in c.params:
             if isinstance(p, int):
                 wtr.write_uint16(1)
                 wtr.write_uint32(p)
             elif isinstance(p, float):
                 wtr.write_uint16(2)
                 wtr.write_float(p)
             elif isinstance(p, str):
                 wtr.write_uint16(3)
                 wtr.write_uint16(len(p) + 1)
                 wtr.write_string(p)
                 wtr.write_uint8(0)
     wtr.write_uint16(0xc)
     wtr.seek(0)
     wtr.write_uint32(len(wtr.data) - 4)
Ejemplo n.º 7
0
def compress(input_data: bytes, datablock_size=None) -> bytes:
    if datablock_size is None:
        # Return the smallest we can
        return min(compress(input_data, 4),
                   compress(input_data, 8),
                   key=lambda x: len(x))

    assert datablock_size in [4, 8]

    wtr = BinaryWriter()

    wtr.write_uint8(0x20 | datablock_size)  # huffman identifier

    wtr.write_uint24(len(input_data) if len(input_data) < 0xffffff else 0)
    if len(input_data) > 0xffffff:
        wtr.write_uint32(len(input_data))

    # build frequency table
    frequencies = [0 for _ in range(0x100 if datablock_size == 8 else 0x10)]
    for b in input_data:
        if datablock_size == 8:
            frequencies[b] += 1
        else:
            b0, b1 = b & 0xf, b >> 4
            frequencies[b0] += 1
            frequencies[b1] += 1

    # build the huffman tree
    node_count = 0
    leaf_queue = []
    node_queue = []
    leaves: List[HuffTreeNode] = [
        None for _ in range(0x100 if datablock_size == 8 else 0x10)
    ]
    for i in range(0x10 if datablock_size == 4 else 0x100):
        if frequencies[i] == 0:
            continue
        node = HuffTreeNode(True, data=i)
        leaves[i] = node
        leaf_queue.append((frequencies[i], node))
        node_count += 1

    if len(leaf_queue) < 2:  # Add an unused node to make it posible
        node = HuffTreeNode(True, data=0)
        leaves[0] = node
        leaf_queue.append((1, node))
        node_count += 1

    def take_lowest(
            queue0: List[Tuple[int, HuffTreeNode]],
            queue1: List[Tuple[int,
                               HuffTreeNode]]) -> Tuple[int, HuffTreeNode]:
        if queue0:
            lowest_queue0 = min(queue0, key=lambda x: x[0])
        elif queue1:
            lowest_queue1 = min(queue1, key=lambda x: x[0])
            queue1.remove(lowest_queue1)
            return lowest_queue1
        else:
            raise ValueError("take_lowest() arg are empty sequences")
        if queue1:
            lowest_queue1 = min(queue1, key=lambda x: x[0])
        else:
            queue0.remove(lowest_queue0)
            return lowest_queue0
        if lowest_queue0[0] < lowest_queue1[0]:
            queue0.remove(lowest_queue0)
            return lowest_queue0
        else:
            queue1.remove(lowest_queue1)
            return lowest_queue1

    while len(leaf_queue) + len(node_queue) > 1:
        one_prio, one = take_lowest(leaf_queue, node_queue)
        two_prio, two = take_lowest(leaf_queue, node_queue)

        newnode = HuffTreeNode(False, child0=one, child1=two)
        node_queue.append((one_prio + two_prio, newnode))
        node_count += 1

    root: HuffTreeNode = node_queue[0][1]

    # write the huffman tree
    wtr.write_uint8((node_count - 1) // 2)
    root.to_wtr(wtr)

    datablock = 0
    bits_left = 32
    cached_byte = 0
    for i in range(len(input_data) * (2 if datablock_size == 4 else 1)):
        if datablock_size == 4:
            if i & 1 == 0:
                cached_byte = input_data[i // 2]
                data = cached_byte & 0xf
            else:
                data = cached_byte >> 4
        else:
            data = input_data[i]

        node = leaves[data]
        depth = node.depth
        path: List[bool] = [False for _ in range(depth)]
        for d in range(depth):
            path[depth - d - 1] = node.is_child1
            node = node.parent
        for p in path:
            if bits_left == 0:
                wtr.write_uint32(datablock)
                datablock = 0
                bits_left = 32
            bits_left -= 1
            if p:
                datablock |= 1 << bits_left
    if bits_left != 32:
        wtr.write_uint32(datablock)
    return wtr.getvalue()
Ejemplo n.º 8
0
def compress(data: bytes):
    rdr = BinaryReader(data)
    wtr = BinaryWriter()

    wtr.write_uint8(0x30)  # rle identifier

    wtr.write_uint24(len(data) if len(data) < 0xffffff else 0)
    if len(data) > 0xffffff:
        wtr.write_uint32(len(data))

    repCount = 1
    currentBlockLenght = 0
    dataBlock = [0 for _ in range(130)]
    while rdr.c < len(rdr.data):
        foundRepetition = False
        while (currentBlockLenght < 130 and rdr.c < len(rdr.data)):
            nextByte = rdr.read_uint8()
            dataBlock[currentBlockLenght] = nextByte
            currentBlockLenght += 1
            if (currentBlockLenght > 1):
                if nextByte == dataBlock[currentBlockLenght - 2]:
                    repCount += 1
                else:
                    repCount = 1
            foundRepetition = repCount > 2
            if foundRepetition:
                break
        if foundRepetition:
            numUncompToCopy = currentBlockLenght - 3
        else:
            numUncompToCopy = min(currentBlockLenght, 130 - 2)

        if numUncompToCopy > 0:
            flag = numUncompToCopy - 1
            wtr.write_uint8(flag)
            for i in range(numUncompToCopy):
                wtr.write_uint8(dataBlock[i])
            for i in range(numUncompToCopy, currentBlockLenght):
                dataBlock[i - numUncompToCopy] = dataBlock[i]
            currentBlockLenght -= numUncompToCopy
        if foundRepetition:
            while currentBlockLenght < 130 and rdr.c < len(rdr.data):
                nextByte = rdr.read_uint8()
                dataBlock[currentBlockLenght] = nextByte
                currentBlockLenght += 1
                if nextByte != dataBlock[0]:
                    break
                else:
                    repCount += 1
            flag = 0x80 | (repCount - 3)
            wtr.write_uint8(flag)
            wtr.write_uint8(dataBlock[0])
            if (repCount != currentBlockLenght):
                dataBlock[0] = dataBlock[currentBlockLenght - 1]
            currentBlockLenght -= repCount

    if currentBlockLenght > 0:
        flag = currentBlockLenght - 1
        wtr.write_uint8(flag)
        for i in range(currentBlockLenght):
            wtr.write_uint8(dataBlock[i])
        currentBlockLenght = 0

    return wtr.data
Ejemplo n.º 9
0
    def export_data(self, wtr):
        if not isinstance(wtr, BinaryWriter):
            wtr = BinaryWriter(wtr)
        wtr: BinaryWriter

        puzzle_text_section = BinaryWriter()
        puzzle_text_section.write_string(self.text, encoding=self.encoding)
        puzzle_correct_offset = puzzle_text_section.tell()
        puzzle_text_section.write_string(self.correct_answer, encoding=self.encoding)
        puzzle_incorrect_offset = puzzle_text_section.tell()
        puzzle_text_section.write_string(self.incorrect_answer, encoding=self.encoding)
        puzzle_hint1_offset = puzzle_text_section.tell()
        puzzle_text_section.write_string(self.hint1, encoding=self.encoding)
        puzzle_hint2_offset = puzzle_text_section.tell()
        puzzle_text_section.write_string(self.hint2, encoding=self.encoding)
        puzzle_hint3_offset = puzzle_text_section.tell()
        puzzle_text_section.write_string(self.hint3, encoding=self.encoding)

        wtr.write_uint16(self.number)
        wtr.write_uint16(112)
        wtr.write_string(self.title, encoding=self.encoding, size=0x30)
        wtr.write_uint8(self.tutorial_id)
        for picarat in self.picarat_decay:
            wtr.write_uint8(picarat)
        wtr.write_uint8(self._flags)
        wtr.write_uint8(self.location_id)
        wtr.write_uint8(self.type)
        wtr.write_uint8(self.bg_btm_id)
        wtr.write(self.original[0x3c:0x3e])  # UnkSoundId
        wtr.write_uint8(self.bg_top_id)
        wtr.write_uint8(self.reward_id)

        wtr.write_uint32(0)
        wtr.write_uint32(puzzle_correct_offset)
        wtr.write_uint32(puzzle_incorrect_offset)
        wtr.write_uint32(puzzle_hint1_offset)
        wtr.write_uint32(puzzle_hint2_offset)
        wtr.write_uint32(puzzle_hint3_offset)
        wtr.write(b"\x00" * 4 * 6)
        wtr.write(puzzle_text_section.data)

        return wtr
Ejemplo n.º 10
0
    def write_stream(self, stream):
        if isinstance(stream, BinaryWriter):
            wtr = stream
        else:
            wtr = BinaryWriter(stream)

        wtr.write_uint16(len(self.images))
        wtr.write_uint16(3 if self.colordepth == 4 else 4)

        for img in self.images:
            img_h, img_w = img.shape
            wtr.write_uint16(img_w)
            wtr.write_uint16(img_h)

            # number of parts
            wtr.write_uint16(
                calculate_power_of_2_steps(img_w) *
                calculate_power_of_2_steps(img_h))
            wtr.write_zeros(2)

            w_left, h_left = img_w, img_h
            part_x, part_y = 0, 0
            while h_left > 0:
                part_h = get_nearest_power_of_2(h_left)
                good_h = part_h
                h_left -= part_h
                w_left = img_w
                part_x = 0
                while w_left > 0:
                    part_w = get_nearest_power_of_2(w_left)
                    w_left -= part_w
                    part_h = good_h

                    wtr.write_uint16(part_x)
                    wtr.write_uint16(part_y)
                    wtr.write_uint16(int(log(part_w, 2)) - 3)
                    wtr.write_uint16(int(log(part_h, 2)) - 3)

                    part = np.zeros((part_h, part_w), np.uint8)

                    if part_x + part_w > img_w:
                        part_w = img_w - part_x
                    if part_y + part_h > img_h:
                        part_h = img_h - part_y

                    part[:part_h, :part_w] = img[part_y:part_y + part_h,
                                                 part_x:part_x + part_w]

                    if self.colordepth == 8:
                        wtr.write(part.tobytes())
                    else:
                        h, w = part.shape
                        bufpart = part.reshape((w * h))
                        part_4bit = np.zeros((h * w // 2), np.uint8)
                        part_4bit[:] = np.ndarray = bufpart[
                            0::2] & 0xf | bufpart[1::2] << 4
                        wtr.write(part_4bit.tobytes())

                    part_x += part_w
                part_y += part_h

        wtr.write_uint32(256 if self.colordepth == 8 else 16)
        for color_i in range(256 if self.colordepth == 8 else 16):
            self.palette[color_i]: np.ndarray
            wtr.write_uint16(ndspy.color.pack255(*self.palette[color_i]))

        wtr.write_zeros(0x1e)
        wtr.write_uint32(len(self.animations))

        for anim in self.animations:
            wtr.write_string(anim.name, 0x1e)
        for anim in self.animations:
            wtr.write_uint32(len(anim.frames))
            wtr.write_uint32_array([frame.index for frame in anim.frames])
            wtr.write_uint32_array([frame.duration for frame in anim.frames])
            wtr.write_uint32_array(
                [frame.image_index for frame in anim.frames])

        wtr.write_uint16(0x1234)  # magic number probably

        variable_labels = list(self.variables)
        assert len(variable_labels) == 16
        wtr.write_string_array(variable_labels, 16)
        for dat_i in range(8):
            for var_l in variable_labels:
                wtr.write_int16(self.variables[var_l][dat_i])

        for anim in self.animations:
            wtr.write_uint16(anim.child_image_x)
        for anim in self.animations:
            wtr.write_uint16(anim.child_image_y)
        for anim in self.animations:
            wtr.write_uint8(anim.child_image_animation_index)

        wtr.write_string(self.child_image, 128)

        return stream
Ejemplo n.º 11
0
 def write(self, bw: BinaryWriter):
     bw.seek(0, io.SEEK_SET)
     bw.write(self.magic)
     bw.write_uint32(0)
     bw.write_uint32(self.file_length)
     bw.write_uint16(self.version)
     bw.write_uint8(self.unk1)
     bw.write_uint8(self.unk2)
     bw.write_uint32(0)
     bw.write_uint32(0)
     bw.write_uint16(self.year)
     bw.write_uint8(self.month)
     bw.write_uint8(self.day)
     bw.write_uint8(self.hour)
     bw.write_uint8(self.minute)
     bw.write_uint8(self.second)
     bw.write_uint8(self.centisecond)
     if self.file_name[-1] != 0:
         self.file_name += b"\0"
     bw.write_string(self.file_name, size=16, encoding=None, pad=b"\xFF")
     bw.write_uint32(0x1)
     bw.write_uint32(0x1)
     bw.write_uint32(0xFFFFFFFF)
     bw.write_uint32(0xFFFFFFFF)
Ejemplo n.º 12
0
 def write(self, bw: BinaryWriter):
     bw.write_uint8(self.track_id)
     bw.write_uint8(self.channel_id)
     bw.write_uint8(self.unk1)
     bw.write_uint8(self.unk2)
Ejemplo n.º 13
0
def compress(data: bytes):
    rdr = BinaryReader(data)
    wtr = BinaryWriter()

    wtr.write_uint8(0x30)  # rle identifier

    wtr.write_uint24(len(data) if len(data) < 0xffffff else 0)
    if len(data) > 0xffffff:
        wtr.write_uint32(len(data))

    rep_count = 1
    current_block_length = 0
    data_block = [0 for _ in range(130)]
    while rdr.c < len(rdr.data):
        found_repetition = False
        while current_block_length < 130 and rdr.c < len(rdr.data):
            next_byte = rdr.read_uint8()
            data_block[current_block_length] = next_byte
            current_block_length += 1
            if current_block_length > 1:
                if next_byte == data_block[current_block_length - 2]:
                    rep_count += 1
                else:
                    rep_count = 1
            found_repetition = rep_count > 2
            if found_repetition:
                break
        if found_repetition:
            num_uncomp_to_copy = current_block_length - 3
        else:
            num_uncomp_to_copy = min(current_block_length, 130 - 2)

        if num_uncomp_to_copy > 0:
            flag = num_uncomp_to_copy - 1
            wtr.write_uint8(flag)
            for i in range(num_uncomp_to_copy):
                wtr.write_uint8(data_block[i])
            for i in range(num_uncomp_to_copy, current_block_length):
                data_block[i - num_uncomp_to_copy] = data_block[i]
            current_block_length -= num_uncomp_to_copy
        if found_repetition:
            while current_block_length < 130 and rdr.c < len(rdr.data):
                next_byte = rdr.read_uint8()
                data_block[current_block_length] = next_byte
                current_block_length += 1
                if next_byte != data_block[0]:
                    break
                else:
                    rep_count += 1
            flag = 0x80 | (rep_count - 3)
            wtr.write_uint8(flag)
            wtr.write_uint8(data_block[0])
            if rep_count != current_block_length:
                data_block[0] = data_block[current_block_length - 1]
            current_block_length -= rep_count

    if current_block_length > 0:
        flag = current_block_length - 1
        wtr.write_uint8(flag)
        for i in range(current_block_length):
            wtr.write_uint8(data_block[i])

    return wtr.data