def read(self, br: BinaryReader): br.seek(0, io.SEEK_SET) self.magic = br.read(4) if self.magic != b"smdl": raise ValueError("SMDHeader does not start with magic value") br.read_uint32() # 0 self.file_length = br.read_uint32() self.version = br.read_uint16() self.unk1 = br.read_uint8() self.unk2 = br.read_uint8() # 8 bytes of 0 br.read_uint32() br.read_uint32() self.year = br.read_uint16() self.month = br.read_uint8() self.day = br.read_uint8() self.hour = br.read_uint8() self.minute = br.read_uint8() self.second = br.read_uint8() self.centisecond = br.read_uint8() self.file_name = br.read_string(16, encoding=None, pad=b"\xFF") br.read_uint32() # 0x1 br.read_uint32() # 0x1 br.read_uint32() # 0xFFFFFFFF br.read_uint32() # 0xFFFFFFFF
def read(self, br: BinaryReader): br.seek(0) self.magic = br.read(4) if self.magic != b"swdl": raise ValueError("SWDHeader does not start with magic value") br.read_uint32() # 0 self.file_length = br.read_uint32() self.version = br.read_uint16() if self.version != 0x415: raise ValueError("SMDHeader does not have correct version") self.is_sample_bank = br.read_bool() self.group = br.read_uint8() # 8 bytes of 0 br.read_uint32() br.read_uint32() self.year = br.read_uint16() self.month = br.read_uint8() self.day = br.read_uint8() self.hour = br.read_uint8() self.minute = br.read_uint8() self.second = br.read_uint8() self.centisecond = br.read_uint8() self.file_name = br.read_string(16, encoding=None, pad=b"\xAA") self.unk10 = br.read_uint32() # 8 bytes of 0 br.read_uint32() br.read_uint32() self.unk13 = br.read_uint32() self.pcmdlen = br.read_uint32() self.unk14 = br.read_uint32() self.wavi_slot_count = br.read_uint16() self.prgi_slot_count = br.read_uint16() self.unk17 = br.read_uint16() self.wavi_len = br.read_uint32()
def read_stream(self, stream: BinaryIO): if isinstance(stream, BinaryReader): rdr = stream else: rdr = BinaryReader(stream) with open("test.bin", "wb+") as f: f.write(rdr.read()) rdr.seek(0) palette_lenght = rdr.read_uint32() for color_i in range(palette_lenght): self.palette[color_i] = ndspy.color.unpack255(rdr.read_uint16()) if color_i: self.palette[color_i, 3] = 255 n_tiles = rdr.read_uint32() tiles = np.frombuffer(rdr.read(n_tiles * 0x40), np.uint8).reshape((n_tiles, 8, 8)) map_w = rdr.read_uint16() map_h = rdr.read_uint16() img_w = map_w * 8 img_h = map_h * 8 self.image = np.zeros((img_h, img_w), np.uint8) for map_y in range(map_h): for map_x in range(map_w): img_y = map_y * 8 img_x = map_x * 8 self.image[img_y:img_y + 8, img_x:img_x + 8] = tiles[rdr.read_uint16()]
def read(self, rdr: BinaryReader): self.chunk_id = rdr.read(4) self.chunk_size = rdr.read_uint32() self.audio_format = rdr.read_uint16() self.num_channels = rdr.read_uint16() self.sample_rate = rdr.read_uint32() self.byte_rate = rdr.read_uint32() self.block_align = rdr.read_uint16() self.bits_per_sample = rdr.read_uint16()
def read(self, rdr: BinaryReader): self.magic_value = rdr.read(4)[::-1] if self.magic_value != b"NFTR": raise ValueError("NFTRHeader does not start with magic value") self.byte_order = rdr.read_uint16() self.version = rdr.read_uint16() self.decompressed_resource_size = rdr.read_uint32() self.offset_to_fnif = rdr.read_uint16() self.following_chunk_count = rdr.read_uint16()
def load(self, rdr): if not isinstance(rdr, BinaryReader): rdr = BinaryReader(rdr) rdr: BinaryReader self.original = rdr.read() rdr.seek(0) self.number = rdr.read_uint16() rdr.read_uint16() # 112 self.title = rdr.read_string(encoding=self.encoding) rdr.seek(0x34) self.tutorial_id = rdr.read_uint8() for i in range(3): self.picarat_decay[i] = rdr.read_uint8() print(rdr.tell()) self._flags = rdr.read_uint8() self.location_id = rdr.read_uint8() self.type = rdr.read_uint8() self.bg_btm_id = rdr.read_uint8() rdr.read_uint16() self.bg_top_id = rdr.read_uint8() self.reward_id = rdr.read_uint8() print(rdr.tell()) puzzle_text_offset = 0x70 + rdr.read_uint32() puzzle_correct_answer_offset = 0x70 + rdr.read_uint32() puzzle_incorrect_answer_offset = 0x70 + rdr.read_uint32() puzzle_hint1_offset = 0x70 + rdr.read_uint32() puzzle_hint2_offset = 0x70 + rdr.read_uint32() puzzle_hint3_offset = 0x70 + rdr.read_uint32() rdr.seek(puzzle_text_offset) self.text = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True) rdr.seek(puzzle_correct_answer_offset) self.correct_answer = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True) rdr.seek(puzzle_incorrect_answer_offset) self.incorrect_answer = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True) rdr.seek(puzzle_hint1_offset) self.hint1 = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True) rdr.seek(puzzle_hint2_offset) self.hint2 = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True) rdr.seek(puzzle_hint3_offset) self.hint3 = subs.replace_substitutions( rdr.read_string(encoding=self.encoding), True)
def read_stream(self, stream: BinaryIO): if isinstance(stream, BinaryReader): rdr = stream else: rdr = BinaryReader(stream) n_entries = rdr.read_uint16() header_length = rdr.read_uint16() entry_length = rdr.read_uint16() rdr.seek(header_length) self._entries = [] for i in range(n_entries): self._entries.append(rdr.read(entry_length))
def read(self, rdr: BinaryReader): self.chunk_id = rdr.read(4)[::-1] if self.chunk_id != b"CMAP": raise ValueError("CMAPChunk does not start with magic value") self.chunk_size = rdr.read_uint32() self.first_character = rdr.read_uint16() self.last_character = rdr.read_uint16() self.map_type = rdr.read_uint32() self.offset_to_next_cmap = rdr.read_uint32() - 8 char_map = {} if self.map_type == 0: tile_no = rdr.read_uint16() i = self.first_character while i <= self.last_character: char_map[i] = tile_no i += 1 tile_no += 1 elif self.map_type == 1: i = self.first_character while i <= self.last_character: tile = rdr.read_uint16() if tile == 0xFFFF: i += 1 continue char_map[i] = tile i += 1 elif self.map_type == 2: groups = rdr.read_uint16() for i in range(groups): ch = rdr.read_uint16() tile = rdr.read_uint16() char_map[ch] = tile self.char_map = char_map
def read(self, rdr: BinaryReader): self.chunk_id = rdr.read(4)[::-1] if self.chunk_id != b"CGLP": raise ValueError("CGLPChunk does not start with magic value") self.chunk_size = rdr.read_uint32() self.tile_width = rdr.read_uint8() self.tile_height = rdr.read_uint8() self.tile_bytes = rdr.read_uint16() bitmap_items = self.tile_width * self.tile_height self.underline_location = rdr.read_uint8() self.max_proportional_width = rdr.read_uint8() self.tile_depth = rdr.read_uint8() self.tile_rotation = rdr.read_uint8() self.tile_bitmaps = [] tile_bytes = self.tile_bytes tile_width = self.tile_width tile_height = self.tile_height tile_depth = self.tile_depth # To avoid byte boundaries efficiently # If bit depth is 2, we can read in blocks of 2 # If bit depth is 1, we can only read in blocks of 1 bit_steps = get_bit_steps(self.tile_depth) bit_mask = ((1 << bit_steps) - 1) for _ in range((self.chunk_size - 0x10) // tile_bytes): buffer = rdr.read(tile_bytes) bitmap = np.zeros(bitmap_items, dtype=np.uint8) current_bit = 0 for i in range(bitmap_items): # Get value from bytes to bit depth v = 0 for _ in range(tile_depth // bit_steps): # Shift the value bit steps v <<= bit_steps # Get the bit index and the byte index bit_i = current_bit % 8 byte_i = (current_bit - bit_i) // 8 # Read <bit steps> bits from byte (bit 7 is the MSB) byte = buffer[byte_i] bit = (byte >> (7 - bit_i)) & bit_mask # Add the value and change the current bit v += bit current_bit += bit_steps bitmap[i] = v bitmap.shape = tile_height, tile_width self.tile_bitmaps.append(bitmap)
def read(self, rdr: BinaryReader, tile_count: int): self.chunk_id = rdr.read(4)[::-1] if self.chunk_id != b"CWDH": raise ValueError("CWDHChunk does not start with magic value") self.chunk_size = rdr.read_uint32() self.first_tile_no = rdr.read_uint16() self.last_tile_no = rdr.read_uint16() rdr.read(4) self.left_spacing = [] self.width = [] self.total_width = [] for i in range(tile_count): left_spacing = rdr.read_uint8() width = rdr.read_uint8() total_width = rdr.read_uint8() self.left_spacing.append(left_spacing) self.width.append(width) self.total_width.append(total_width)
def read_stream(self, stream: BinaryIO): if isinstance(stream, BinaryReader): rdr = stream else: rdr = BinaryReader(stream) self.commands = [] self.params = [] file_length = rdr.read_uint32() while rdr.c < file_length: datatype = rdr.read_uint16() if datatype == 0: break elif datatype == 1: self.params.append(rdr.read_uint32()) elif datatype == 2: self.params.append(rdr.read_float()) elif datatype == 3: self.params.append(rdr.read_string(rdr.read_uint16())) elif datatype == 0xc: return while rdr.c < file_length or True: self.commands.append(command := GDSCommand(rdr.read_uint16())) if command.command == 0xc: self.commands = self.commands[:-1] return while rdr.c < file_length: datatype = rdr.read_uint16() if datatype == 0: break if datatype == 1: command.params.append(rdr.read_uint32()) elif datatype == 2: command.params.append(rdr.read_float()) elif datatype == 3: command.params.append(rdr.read_string(rdr.read_uint16())) elif datatype == 0xc: return
def read(self, br: BinaryReader): br.seek(0x40, io.SEEK_SET) self.label = br.read(4) if self.label != b"song": raise ValueError("SongChunk does not start with magic value") self.unk1 = br.read_uint32() br.read_uint32() # 0xFF10 br.read_uint32() # 0xFFFFFFB0 br.read_uint16() # 0x1 self.tpqn = br.read_uint16() br.read_uint16() # 0xFF10 self.num_tracks = br.read_uint8() self.num_channels = br.read_uint8() br.read_uint32() # 0x0F000000 br.read_uint32() # 0xFFFFFFFF br.read_uint32() # 0x40000000 br.read_uint32() # 0x00404000 br.read_uint16() # 0x0200 br.read_uint16() # 0x0800 br.read_uint32() # 0xFFFFFF00 br.read(16) # 16 0xFF Padding
def read_stream(self, stream: BinaryIO): if isinstance(stream, BinaryReader): rdr = stream else: rdr = BinaryReader(stream) n_images = rdr.read_uint16() self.colordepth = 4 if rdr.read_uint16() == 3 else 8 # import the images self.images = [] for img_i in range(n_images): img_w = rdr.read_uint16() img_h = rdr.read_uint16() n_parts = rdr.read_uint16() img = np.zeros((img_h, img_w), np.uint8) rdr.seek(2, SEEK_CUR) for part_i in range(n_parts): part_x = rdr.read_uint16() part_y = rdr.read_uint16() part_w = 2**(3 + rdr.read_uint16()) part_h = 2**(3 + rdr.read_uint16()) part: np.ndarray if self.colordepth == 8: part = np.frombuffer(rdr.read(part_h * part_w), np.uint8) part = part.reshape((part_h, part_w)) else: bufpart = np.frombuffer(rdr.read(part_h * part_w // 2), np.uint8) part = np.zeros((part_w * part_h), np.uint8) part[0::2] = bufpart & 0xf part[1::2] = bufpart >> 4 part = part.reshape((part_h, part_w)) 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 img[part_y:part_y + part_h, part_x:part_x + part_w] = part[:part_h, :part_w] self.images.append(img) self.palette = np.zeros((256, 4), np.uint8) palette_length = rdr.read_uint32() for color_i in range(palette_length): self.palette[color_i] = ndspy.color.unpack255(rdr.read_uint16()) if color_i: self.palette[color_i, 3] = 255 rdr.seek(0x1E, SEEK_CUR) n_animations = rdr.read_uint32() animation_names = rdr.read_string_array(n_animations, 0x1e) animation_frame_sets = [] for i in range(n_animations): n_frames = rdr.read_uint32() frame_indexes = rdr.read_uint32_array(n_frames) frame_durations = rdr.read_uint32_array(n_frames) image_indexes = rdr.read_uint32_array(n_frames) animation_frame_sets.append([ AnimationFrame(index=frame_indexes[i], duration=frame_durations[i], image_index=image_indexes[i]) for i in range(n_frames) ]) self.animations = [ Animation(name=animation_names[i], frames=animation_frame_sets[i]) for i in range(n_animations) ] if rdr.read_uint16() != 0x1234: return # We hit end of stream variable_labels = rdr.read_string_array(16, 16) variable_data = [[] for _ in range(16)] for _ in range(8): for var_i in range(16): variable_data[var_i].append(rdr.read_int16()) self.variables = { variable_labels[i]: variable_data[i] for i in range(16) } for anim in self.animations: anim.child_image_x = rdr.read_uint16() for anim in self.animations: anim.child_image_y = rdr.read_uint16() for anim in self.animations: anim.child_image_animation_index = rdr.read_uint8() self.child_image = rdr.read_string(128)