def write_background_data_to_rom(self, rom):
        # Write the background tileset data
        block_size = self.bg_tileset.block_size(bpp=BG_TILESET_BPP)
        with EbCompressibleBlock(block_size) as block:
            self.bg_tileset.to_block(block=block, offset=0, bpp=BG_TILESET_BPP)
            self._write_compressed_block(rom, block, BG_TILESET_POINTER)

        # Write the background tile arrangement data
        block_size = self.bg_arrangement.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.bg_arrangement.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block, BG_ARRANGEMENT_POINTER)

        # Write the background palette data
        # There is an additional pointer to this location, so change that one
        # too
        block_size = self.bg_palette.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.bg_palette.to_block(block=block, offset=0)
            new_offset = self._write_compressed_block(rom, block,
                                                      BG_PALETTE_POINTER)
            write_asm_pointer(block=rom,
                              offset=BG_PALETTE_POINTER_SECONDARY,
                              pointer=to_snes_address(new_offset))

        # Write the background animated palette data
        block_size = self.bg_anim_palette.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.bg_anim_palette.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block, BG_ANIM_PALETTE_POINTER)
示例#2
0
    def to_block(self, block):
        with EbCompressibleBlock(
                self.graphics.block_size(bpp=self.bpp)) as compressed_block:
            self.graphics.to_block(block=compressed_block,
                                   offset=0,
                                   bpp=self.bpp)
            compressed_block.compress()
            graphics_offset = block.allocate(data=compressed_block)

        if self.arrangement:
            with EbCompressibleBlock(
                    self.arrangement.block_size()) as compressed_block:
                self.arrangement.to_block(block=compressed_block, offset=0)
                compressed_block.compress()
                arrangement_offset = block.allocate(data=compressed_block)
        else:
            arrangement_offset = None

        palette_offsets = []
        for i, palette in enumerate(self.palettes):
            with EbCompressibleBlock(palette.block_size()) as compressed_block:
                palette.to_block(block=compressed_block, offset=0)
                if self.compressed_palettes:
                    compressed_block.compress()
                palette_offset = block.allocate(data=compressed_block)
                palette_offsets.append(palette_offset)

        return graphics_offset, arrangement_offset, palette_offsets
示例#3
0
    def write_to_rom(self, rom):
        graphics_1_block_size = self.graphics_1.block_size(bpp=2)
        with EbCompressibleBlock(graphics_1_block_size) as compressed_block:
            self.graphics_1.to_block(block=compressed_block, offset=0, bpp=2)
            compressed_block.compress()
            graphics_1_offset = rom.allocate(data=compressed_block)
            write_asm_pointer(block=rom, offset=GRAPHICS_1_ASM_POINTER_OFFSET,
                              pointer=to_snes_address(graphics_1_offset))

        graphics_2_block_size = self.graphics_2.block_size(bpp=2)
        with EbCompressibleBlock(graphics_2_block_size) as compressed_block:
            self.graphics_2.to_block(block=compressed_block, offset=0, bpp=2)
            compressed_block.compress()
            graphics_2_offset = rom.allocate(data=compressed_block)
            write_asm_pointer(block=rom, offset=GRAPHICS_2_ASM_POINTER_OFFSET,
                              pointer=to_snes_address(graphics_2_offset))

        # Write palettes
        offset = FLAVOR_PALETTES_OFFSET
        for palette in self.flavor_palettes:
            palette.to_block(block=rom, offset=offset)
            offset += 64

        # Write names
        for asm_pointer_offset in FLAVOR_NAME_ASM_POINTER_OFFSETS:
            name = self.flavor_names[asm_pointer_offset]
            offset = rom.allocate(size=FLAVOR_NAME_ENTRY.size)
            FLAVOR_NAME_ENTRY.to_block(block=rom, offset=offset, value=name)
            write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(offset))
    def read_background_data_from_rom(self, rom):
        with EbCompressibleBlock() as block:
            # Read the background tileset data
            self._decompress_block(rom, block, BG_TILESET_POINTER)
            self.bg_tileset.from_block(
                block=block, offset=0, bpp=BG_TILESET_BPP
            )

            # Read the background tile arrangement data
            self._decompress_block(rom, block, BG_ARRANGEMENT_POINTER)
            self.bg_arrangement.from_block(block=block, offset=0)

            # Read the background palette data
            # The decompressed data is smaller than the expected value,
            # so it is extended with black entries.
            self._decompress_block(rom, block, BG_PALETTE_POINTER)
            block.from_array(
                block.to_array() + [0]*(BG_SUBPALETTE_LENGTH*2 - len(block))
            )
            self.bg_palette.from_block(block=block, offset=0)

            # Read the background animated palette data
            # Each subpalette corresponds to an animation frame.
            self._decompress_block(rom, block, BG_ANIM_PALETTE_POINTER)
            self.bg_anim_palette.from_block(block=block, offset=0)
    def read_from_rom(self, rom):
        with EbCompressibleBlock() as block:
            # Read the tileset data
            block.from_compressed_block(
                block=rom, offset=from_snes_address(
                    read_asm_pointer(rom, TILESET_POINTER)
                )
            )
            self.tileset.from_block(block=block, offset=0, bpp=TILESET_BPP)

            # Read the arrangement data
            block.from_compressed_block(
                block=rom, offset=from_snes_address(
                    read_asm_pointer(rom, ARRANGEMENT_POINTER)
                )
            )
            self.arrangement.from_block(block=block, offset=0)

            # Read the palette data
            block.from_compressed_block(
                block=rom, offset=from_snes_address(
                    read_asm_pointer(rom, PALETTE_POINTER)
                )
            )
            self.palette.from_block(block=block, offset=0)
示例#6
0
    def write_to_rom(self, rom):
        self.enemy_config_table.to_block(
            block=rom,
            offset=from_snes_address(ENEMY_CONFIGURATION_TABLE_DEFAULT_OFFSET))
        self.enemy_group_bg_table.to_block(
            block=rom,
            offset=from_snes_address(
                ENEMY_GROUP_BACKGROUND_TABLE_DEFAULT_OFFSET))

        # Write the sprites
        self.graphics_pointer_table.recreate(num_rows=len(self.battle_sprites))
        for i, battle_sprite in enumerate(self.battle_sprites):
            self.graphics_pointer_table[i] = [None, battle_sprite.size()]
            with EbCompressibleBlock(
                    size=battle_sprite.block_size()) as compressed_block:
                battle_sprite.to_block(block=compressed_block, offset=0)
                compressed_block.compress()
                graphics_offset = rom.allocate(data=compressed_block)
                self.graphics_pointer_table[i][0] = to_snes_address(
                    graphics_offset)

        graphics_pointer_table_offset = rom.allocate(
            size=self.graphics_pointer_table.size)
        self.graphics_pointer_table.to_block(
            block=rom, offset=graphics_pointer_table_offset)
        write_asm_pointer(
            block=rom,
            offset=GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSET,
            pointer=to_snes_address(graphics_pointer_table_offset))
        for pointer_offset in GRAPHICS_POINTER_TABLE_POINTER_OFFSETS:
            rom.write_multi(
                pointer_offset,
                item=to_snes_address(graphics_pointer_table_offset),
                size=3)

        # Write the palettes
        if self.palettes:
            palettes_offset = rom.allocate(size=self.palettes[0].block_size() *
                                           len(self.palettes))
            write_asm_pointer(block=rom,
                              offset=PALETTES_ASM_POINTER_OFFSET,
                              pointer=to_snes_address(palettes_offset))
            for palette in self.palettes:
                palette.to_block(block=rom, offset=palettes_offset)
                palettes_offset += palette.block_size()

        # Write the groups
        for i, group in enumerate(self.enemy_groups):
            offset = rom.allocate(
                size=(len(group) * EnemyGroupTableEntry.size + 1))
            self.enemy_group_table[i][0] = to_snes_address(offset)
            for group_entry in group:
                EnemyGroupTableEntry.to_block(block=rom,
                                              offset=offset,
                                              value=group_entry)
                offset += EnemyGroupTableEntry.size
            rom[offset] = 0xff
        self.enemy_group_table.to_block(
            block=rom,
            offset=from_snes_address(ENEMY_GROUP_TABLE_DEFAULT_OFFSET))
示例#7
0
 def to_block(self, block, tileset_asm_pointer_offset, palette_offset):
     tileset_block_size = self.tileset.block_size(bpp=2)
     with EbCompressibleBlock(tileset_block_size) as compressed_block:
         self.tileset.to_block(block=compressed_block, offset=0, bpp=2)
         compressed_block.compress()
         tileset_offset = block.allocate(data=compressed_block)
         write_asm_pointer(block=block, offset=tileset_asm_pointer_offset, pointer=to_snes_address(tileset_offset))
     self.palette.to_block(block=block, offset=palette_offset)
示例#8
0
 def from_block(self, block, offset):
     with EbCompressibleBlock() as compressed_block:
         compressed_block.from_compressed_block(block=block, offset=offset)
         self.palettes[0].from_block(block=compressed_block, offset=0)
         self.arrangement.from_block(block=compressed_block, offset=self.palettes[0].block_size())
         self.graphics.from_block(block=compressed_block,
                                  offset=self.palettes[0].block_size() + 2048,
                                  bpp=self.bpp)
示例#9
0
    def from_block(self, block, graphics_offset, arrangement_offset, palette_offsets):
        with EbCompressibleBlock() as compressed_block:
            compressed_block.from_compressed_block(block=block, offset=graphics_offset)
            self.graphics.from_block(block=compressed_block, offset=0, bpp=self.bpp)

        if self.arrangement:
            with EbCompressibleBlock() as compressed_block:
                compressed_block.from_compressed_block(block=block, offset=arrangement_offset)
                self.arrangement.from_block(block=compressed_block, offset=0)

        for i, palette_offset in enumerate(palette_offsets):
            if self.compressed_palettes:
                with EbCompressibleBlock() as compressed_block:
                    compressed_block.from_compressed_block(block=block, offset=palette_offset)
                    self.palettes[i].from_block(block=compressed_block, offset=0)
            else:
                self.palettes[i].from_block(block=block, offset=palette_offset)
示例#10
0
 def read_from_rom(self, rom):
     graphics_offset = from_snes_address(
         read_asm_pointer(block=rom, offset=GRAPHICS_ASM_POINTER_OFFSET))
     with EbCompressibleBlock() as compressed_block:
         compressed_block.from_compressed_block(block=rom,
                                                offset=graphics_offset)
         self.tileset.from_block(block=compressed_block, bpp=4)
     self.palette.from_block(block=rom, offset=PALETTE_OFFSET)
示例#11
0
 def from_block(self, block, tileset_asm_pointer_offset, palette_offset):
     with EbCompressibleBlock() as compressed_block:
         compressed_block.from_compressed_block(
             block=block,
             offset=from_snes_address(
                 read_asm_pointer(block=block,
                                  offset=tileset_asm_pointer_offset)))
         self.tileset.from_block(block=compressed_block, bpp=2)
     self.palette.from_block(block=block, offset=palette_offset)
示例#12
0
    def write_to_rom(self, rom):
        # Write the tileset data
        block_size = self.tileset.block_size(bpp=TILESET_BPP)
        with EbCompressibleBlock(block_size) as block:
            self.tileset.to_block(block=block, offset=0, bpp=TILESET_BPP)
            self._write_compressed_block(rom, block, TILESET_POINTER)

        # Write the tile arrangement data
        block_size = self.arrangement.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.arrangement.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block, ARRANGEMENT_POINTER)

        # Write the palette data
        block_size = self.palette.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.palette.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block, PALETTE_POINTER)
示例#13
0
 def arrangements_to_block(self, block):
     with EbCompressibleBlock(1024 * 16 * 2) as compressed_block:
         i = 0
         for arrangement in self.arrangements:
             for y in range(4):
                 for x in range(4):
                     compressed_block.write_multi(key=i, item=arrangement[y][x], size=2)
                     i += 2
         compressed_block.compress()
         return block.allocate(data=compressed_block)
示例#14
0
 def write_to_rom(self, rom):
     tileset_block_size = self.tileset.block_size(bpp=4)
     with EbCompressibleBlock(tileset_block_size) as compressed_block:
         self.tileset.to_block(block=compressed_block, offset=0, bpp=4)
         compressed_block.compress()
         tileset_offset = rom.allocate(data=compressed_block)
         write_asm_pointer(block=rom,
                           offset=GRAPHICS_ASM_POINTER_OFFSET,
                           pointer=to_snes_address(tileset_offset))
     self.palette.to_block(block=rom, offset=PALETTE_OFFSET)
示例#15
0
 def to_block(self, rom):
     # Arrangement space is 2048 bytes long since it's 32x32x2 in VRAM
     with EbCompressibleBlock(size=self.palettes[0].block_size() + 2048 + self.graphics.block_size(bpp=self.bpp)) \
             as compressed_block:
         self.palettes[0].to_block(block=compressed_block, offset=0)
         self.arrangement.to_block(block=compressed_block, offset=self.palettes[0].block_size())
         self.graphics.to_block(block=compressed_block,
                                offset=self.palettes[0].block_size() + 2048,
                                bpp=self.bpp)
         compressed_block.compress()
         return rom.allocate(data=compressed_block)
示例#16
0
    def write_chars_data_to_rom(self, rom):
        # Write the characters tileset data
        block_size = self.chars_tileset.block_size(bpp=CHARS_TILESET_BPP)
        with EbCompressibleBlock(block_size) as block:
            self.chars_tileset.to_block(block=block,
                                        offset=0,
                                        bpp=CHARS_TILESET_BPP)
            self._write_compressed_block(rom, block, CHARS_TILESET_POINTER)

        # Write the characters palette data
        block_size = self.chars_palette.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.chars_palette.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block, CHARS_PALETTE_POINTER)

        # Write the characters animation palette data
        block_size = self.chars_anim_palette.block_size()
        with EbCompressibleBlock(block_size) as block:
            self.chars_anim_palette.to_block(block=block, offset=0)
            self._write_compressed_block(rom, block,
                                         CHARS_ANIM_PALETTE_POINTER)
示例#17
0
    def arrangements_from_block(self, block, offset):
        with EbCompressibleBlock() as compressed_block:
            compressed_block.from_compressed_block(block=block, offset=offset)
            num_arrangements = len(compressed_block) // 32

            j = 0
            for i in range(num_arrangements):
                arrangement = [[0 for x in range(4)] for y in range(4)]
                for y in range(4):
                    for x in range(4):
                        arrangement[y][x] = compressed_block.read_multi(key=j, size=2)
                        j += 2
                self.arrangements[i] = arrangement
示例#18
0
    def from_block(self, block, offset):
        with EbCompressibleBlock() as compressed_block:
            compressed_block.from_compressed_block(block=block, offset=offset)
            self.graphics.from_block(block=compressed_block,
                                     offset=0,
                                     bpp=TILE_BPP)
            next_offset = self.graphics_data_size
            self.palette.from_block(block=compressed_block, offset=next_offset)
            next_offset += self.palette.block_size()

            for arrangement in self.arrangements:
                arrangement.from_block(block=compressed_block,
                                       offset=next_offset)
                next_offset += arrangement.block_size()
示例#19
0
    def read_from_rom(self, rom):
        with EbCompressibleBlock() as compressed_block:
            compressed_block.from_compressed_block(
                block=rom,
                offset=from_snes_address(read_asm_pointer(rom, GRAPHICS_1_ASM_POINTER_OFFSET)))
            self.graphics_1.from_block(block=compressed_block, bpp=2)

        with EbCompressibleBlock() as compressed_block:
            compressed_block.from_compressed_block(
                block=rom,
                offset=from_snes_address(read_asm_pointer(rom, GRAPHICS_2_ASM_POINTER_OFFSET)))
            self.graphics_2.from_block(block=compressed_block, bpp=2)

        # Read palettes
        offset = FLAVOR_PALETTES_OFFSET
        for palette in self.flavor_palettes:
            palette.from_block(block=rom, offset=offset)
            offset += 64

        # Read names
        for asm_pointer_offset in FLAVOR_NAME_ASM_POINTER_OFFSETS:
            self.flavor_names[asm_pointer_offset] = FLAVOR_NAME_ENTRY.from_block(
                block=rom,
                offset=from_snes_address(read_asm_pointer(block=rom, offset=asm_pointer_offset)))
示例#20
0
    def read_chars_data_from_rom(self, rom):
        with EbCompressibleBlock() as block:
            # Read the characters tileset data
            self._decompress_block(rom, block, CHARS_TILESET_POINTER)
            self.chars_tileset.from_block(block=block,
                                          offset=0,
                                          bpp=CHARS_TILESET_BPP)

            # Read the characters palette data
            self._decompress_block(rom, block, CHARS_PALETTE_POINTER)
            self.chars_palette.from_block(block=block, offset=0)

            # Read the characters animated palette data
            # Each subpalette corresponds to an animation frame.
            self._decompress_block(rom, block, CHARS_ANIM_PALETTE_POINTER)
            self.chars_anim_palette.from_block(block=block, offset=0)
示例#21
0
    def read_from_rom(self, rom):
        self.enemy_config_table.from_block(block=rom,
                                           offset=from_snes_address(ENEMY_CONFIGURATION_TABLE_DEFAULT_OFFSET))
        self.enemy_group_bg_table.from_block(block=rom,
                                             offset=from_snes_address(ENEMY_GROUP_BACKGROUND_TABLE_DEFAULT_OFFSET))

        # Read the sprites
        log.debug("Reading battle sprites")
        self.graphics_pointer_table.from_block(
            rom, from_snes_address(read_asm_pointer(block=rom, offset=GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSET)))
        self.battle_sprites = []
        for i in range(self.graphics_pointer_table.num_rows):
            with EbCompressibleBlock() as compressed_block:
                compressed_block.from_compressed_block(
                    block=rom,
                    offset=from_snes_address(self.graphics_pointer_table[i][0]))
                sprite = EbBattleSprite()
                sprite.from_block(block=compressed_block, offset=0, size=self.graphics_pointer_table[i][1])
                self.battle_sprites.append(sprite)

        # Determine how many palettes there are
        num_palettes = 0
        for i in range(self.enemy_config_table.num_rows):
            num_palettes = max(num_palettes, self.enemy_config_table[i][14])
        num_palettes += 1

        # Read the palettes
        log.debug("Reading palettes")
        palettes_offset = from_snes_address(read_asm_pointer(block=rom, offset=PALETTES_ASM_POINTER_OFFSET))
        self.palettes = []
        for i in range(num_palettes):
            palette = EbPalette(num_subpalettes=1, subpalette_length=16)
            palette.from_block(block=rom, offset=palettes_offset)
            self.palettes.append(palette)
            palettes_offset += palette.block_size()

        # Read the groups
        log.debug("Reading enemy groups")
        self.enemy_group_table.from_block(rom, from_snes_address(ENEMY_GROUP_TABLE_DEFAULT_OFFSET))
        self.enemy_groups = []
        for i in range(self.enemy_group_table.num_rows):
            group = []
            group_offset = from_snes_address(self.enemy_group_table[i][0])
            while rom[group_offset] != 0xff:
                group.append(EnemyGroupTableEntry.from_block(block=rom, offset=group_offset))
                group_offset += EnemyGroupTableEntry.size
            self.enemy_groups.append(group)
示例#22
0
    def to_block(self, block):
        self.graphics_data_size = self.graphics.block_size(bpp=TILE_BPP,
                                                           trimmed=True)
        total_block_size = (self.graphics_data_size +
                            self.palette.block_size() +
                            sum(arrangement.block_size()
                                for arrangement in self.arrangements))

        with EbCompressibleBlock(total_block_size) as compressed_block:
            self.graphics.to_block(block=compressed_block,
                                   offset=0,
                                   bpp=TILE_BPP)
            next_offset = self.graphics_data_size
            self.palette.to_block(block=compressed_block, offset=next_offset)
            next_offset += self.palette.block_size()

            for arrangement in self.arrangements:
                arrangement.to_block(block=compressed_block,
                                     offset=next_offset)
                next_offset += arrangement.block_size()

            compressed_block.compress()
            return block.allocate(data=compressed_block)
示例#23
0
 def minitiles_to_block(self, block):
     with EbCompressibleBlock(
             self.minitiles.block_size(bpp=4)) as compressed_block:
         self.minitiles.to_block(block=compressed_block, offset=0, bpp=4)
         compressed_block.compress()
         return block.allocate(data=compressed_block)
示例#24
0
 def minitiles_from_block(self, block, offset):
     with EbCompressibleBlock() as compressed_block:
         compressed_block.from_compressed_block(block=block, offset=offset)
         self.minitiles.from_block(block=compressed_block, bpp=4)
示例#25
0
    def write_to_rom(self, rom):
        # Write the data table
        self.bg_table.to_block(
            block=rom, offset=from_snes_address(BACKGROUND_TABLE_OFFSET))
        self.scroll_table.to_block(
            block=rom, offset=from_snes_address(SCROLL_TABLE_OFFSET))
        self.distortion_table.to_block(
            block=rom, offset=from_snes_address(DISTORTION_TABLE_OFFSET))

        # Write graphics and arrangements
        self.graphics_pointer_table.recreate(num_rows=len(self.backgrounds))
        self.arrangement_pointer_table.recreate(num_rows=len(self.backgrounds))
        for i, (tileset, color_depth,
                arrangement) in enumerate(self.backgrounds):
            with EbCompressibleBlock(size=tileset.block_size(
                    bpp=color_depth)) as compressed_block:
                tileset.to_block(block=compressed_block,
                                 offset=0,
                                 bpp=color_depth)
                compressed_block.compress()
                tileset_offset = rom.allocate(data=compressed_block)
                self.graphics_pointer_table[i] = [
                    to_snes_address(tileset_offset)
                ]

            with EbCompressibleBlock(
                    size=arrangement.block_size()) as compressed_block:
                arrangement.to_block(block=compressed_block, offset=0)
                compressed_block.compress()
                arrangement_offset = rom.allocate(data=compressed_block)
                self.arrangement_pointer_table[i] = [
                    to_snes_address(arrangement_offset)
                ]

        graphics_pointer_table_offset = rom.allocate(
            size=self.graphics_pointer_table.size)
        self.graphics_pointer_table.to_block(
            block=rom, offset=graphics_pointer_table_offset)
        for asm_pointer_offset in GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSETS:
            write_asm_pointer(
                block=rom,
                offset=asm_pointer_offset,
                pointer=to_snes_address(graphics_pointer_table_offset))

        arrangement_pointer_table_offset = rom.allocate(
            size=self.arrangement_pointer_table.size)
        self.arrangement_pointer_table.to_block(
            block=rom, offset=arrangement_pointer_table_offset)
        for asm_pointer_offset in ARRANGEMENT_POINTER_TABLE_ASM_POINTER_OFFSETS:
            write_asm_pointer(
                block=rom,
                offset=asm_pointer_offset,
                pointer=to_snes_address(arrangement_pointer_table_offset))

        # Write pals
        self.palette_pointer_table.recreate(num_rows=len(self.palettes))
        for i, palette in enumerate(self.palettes):
            with Block(32) as block:
                palette.to_block(block=block, offset=0)
                palette_offset = rom.allocate(data=block)
                self.palette_pointer_table[i] = [
                    to_snes_address(palette_offset)
                ]

        palette_pointer_table_offset = rom.allocate(
            size=self.palette_pointer_table.size)
        self.palette_pointer_table.to_block(
            block=rom, offset=palette_pointer_table_offset)
        for asm_pointer_offset in PALETTE_POINTER_TABLE_ASM_POINTER_OFFSETS:
            write_asm_pointer(
                block=rom,
                offset=asm_pointer_offset,
                pointer=to_snes_address(palette_pointer_table_offset))
示例#26
0
    def read_from_rom(self, rom):
        self.bg_table.from_block(
            block=rom, offset=from_snes_address(BACKGROUND_TABLE_OFFSET))
        self.scroll_table.from_block(
            block=rom, offset=from_snes_address(SCROLL_TABLE_OFFSET))
        self.distortion_table.from_block(
            block=rom, offset=from_snes_address(DISTORTION_TABLE_OFFSET))
        self.graphics_pointer_table.from_block(
            block=rom,
            offset=from_snes_address(
                read_asm_pointer(
                    block=rom,
                    offset=GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSETS[0])))
        self.arrangement_pointer_table.from_block(
            block=rom,
            offset=from_snes_address(
                read_asm_pointer(
                    block=rom,
                    offset=ARRANGEMENT_POINTER_TABLE_ASM_POINTER_OFFSETS[0])))
        self.palette_pointer_table.from_block(
            block=rom,
            offset=from_snes_address(
                read_asm_pointer(
                    block=rom,
                    offset=PALETTE_POINTER_TABLE_ASM_POINTER_OFFSETS[0])))

        self.backgrounds = [
            None for i in range(self.graphics_pointer_table.num_rows)
        ]
        self.palettes = [
            None for i in range(self.palette_pointer_table.num_rows)
        ]
        for i in range(self.bg_table.num_rows):
            graphics_id = self.bg_table[i][0]
            color_depth = self.bg_table[i][2]
            if self.backgrounds[graphics_id] is None:
                # Max tiles used in rom: 421 (2bpp) 442 (4bpp)
                tileset = EbGraphicTileset(num_tiles=512,
                                           tile_width=8,
                                           tile_height=8)
                with EbCompressibleBlock() as compressed_block:
                    compressed_block.from_compressed_block(
                        block=rom,
                        offset=from_snes_address(
                            self.graphics_pointer_table[graphics_id][0]))
                    tileset.from_block(compressed_block,
                                       offset=0,
                                       bpp=color_depth)

                arrangement = EbTileArrangement(width=32, height=32)
                with EbCompressibleBlock() as compressed_block:
                    compressed_block.from_compressed_block(
                        block=rom,
                        offset=from_snes_address(
                            self.arrangement_pointer_table[graphics_id][0]))
                    arrangement.from_block(block=compressed_block, offset=0)

                self.backgrounds[graphics_id] = (tileset, color_depth,
                                                 arrangement)

            palette_id = self.bg_table[i][1]
            if self.palettes[palette_id] is None:
                palette = EbPalette(num_subpalettes=1, subpalette_length=16)
                palette.from_block(
                    block=rom,
                    offset=from_snes_address(
                        self.palette_pointer_table[palette_id][0]))
                self.palettes[palette_id] = palette