Example #1
0
 def add(self, tile):
     if self.is_full():
         raise errors.ChrPageFull()
     ret = self.lower
     self.tiles[self.lower] = tile
     self._adjust_lower()
     return ret
Example #2
0
    def process_image(self, img, palette_text, bg_color_mask, bg_color_fill,
                      is_locked_tiles, lock_sprite_flips, allow_overflow):
        """Process free sprites image, creating the ppu_memory it represents.

    The image represents the entire screen, and is mostly filled with
    bg_color_fill. Anywhere that contains other pixel data is considered to be
    made of sprites. Those sprites are located, treated as tiles, and processed
    to be converted into PPU memory.

    img: Pixel art image.
    palette_text: Optional string representing a palette to be parsed.
    bg_color_mask: Background color that masks existing free sprite tiles.
    bg_color_fill: Background color which fills up the outside space.
    is_locked_tiles: Whether tiles are locked or not.
    allow_overflow: List of components for which to allow overflows.
    """
        self.initialize()
        self.load_image(img)
        config = ppu_memory.PpuMemoryConfig(
            is_sprite=True,
            is_locked_tiles=is_locked_tiles,
            lock_sprite_flips=lock_sprite_flips,
            allow_overflow=allow_overflow)
        is_tall = '8x16' in self.traversal
        # Scan the image, find corners of each tile based upon region merging.
        zones = self._find_zones(bg_color_fill)
        # HACK: Assign zones to ppu_memory so that they can be used by the
        # view renderer.
        self._ppu_memory.zones = zones
        # Convert zones into artifacts.
        artifacts = []
        for z in zones:
            vert_color_needs = None
            for sprite_y, sprite_x in z.each_sprite(is_tall):
                (color_needs,
                 dot_profile) = self.process_tile(sprite_y / 8, sprite_x / 8,
                                                  sprite_y % 8, sprite_x % 8)
                cid = self._color_manifest.id(color_needs)
                did = self._dot_manifest.id(dot_profile)
                artifacts.append([cid, did, None, sprite_y, sprite_x])
                if not is_tall:
                    continue
                elif vert_color_needs is None:
                    vert_color_needs = color_needs
                else:
                    try:
                        self.combine_color_needs(vert_color_needs, color_needs)
                    except errors.PaletteOverflowError as e:
                        e.tile_y = sprite_y / 8
                        e.tile_x = sprite_x / 8
                        self._err.add(e)
                        continue
                    vcid = self._vert_color_manifest.id(vert_color_needs)
                    artifacts[-1][ARTIFACT_VCID] = vcid
                    vert_color_needs = None
        if self._err.has():
            return
        self._needs_provider = self._color_manifest
        if is_tall:
            self._needs_provider = self._vert_color_manifest
        # Build the palette.
        pal = self.make_palette(palette_text, bg_color_mask, True)
        # Build the PPU memory.
        if not is_tall:
            for cid, did, unused, y, x in artifacts:
                color_needs = self._color_manifest.at(cid)
                (pid, palette_option) = pal.select(color_needs)
                dot_xlat = self.get_dot_xlat(color_needs, palette_option)
                try:
                    (chr_num,
                     flip_bits) = self.store_chrdata(dot_xlat, did, config)
                except errors.NametableOverflow, e:
                    self._err.add(errors.NametableOverflow(e.chr_num, y, x))
                    chr_num = 0
                if (config.is_locked_tiles
                        and self._ppu_memory.chr_set.is_full()
                        and chr_num == 0):
                    raise errors.ChrPageFull()
                self._ppu_memory.spritelist.append(
                    [y - 1, chr_num, pid | flip_bits, x])
Example #3
0
                    [y - 1, chr_num, pid | flip_bits, x])
        else:
            ebs_processor = eight_by_sixteen_processor.EightBySixteenProcessor(
            )
            ebs_processor.link_from(self)
            for i in xrange(0, len(artifacts), 2):
                (cid_u, did_u, unused, y, x) = artifacts[i]
                (cid_l, did_l, vcid, unused_y, unused_x) = artifacts[i + 1]
                color_needs = self._vert_color_manifest.at(vcid)
                (pid, palette_option) = pal.select(color_needs)
                chr_num_u, chr_num_l, flip_bits = ebs_processor.store_vert_pair(
                    palette_option, cid_u, did_u, cid_l, did_l, config)
                if (config.is_locked_tiles
                        and self._ppu_memory.chr_set.is_full()
                        and chr_num_u == 0 and chr_num_l == 0):
                    raise errors.ChrPageFull()
                # TODO: Only add this 1 if the sprite chr order is 1.
                chr_num = chr_num_u + 1
                if not 's' in config.allow_overflow:
                    if len(self._ppu_memory.spritelist) >= 0x40:
                        self._err.add(errors.SpritelistOverflow(y, x))
                        continue
                self._ppu_memory.spritelist.append(
                    [y - 1, chr_num, pid | flip_bits, x])
        self._ppu_memory.palette_spr = pal

    def _find_zones(self, fill):
        """Scan the entire image. Calculate the positions of tile corners."""
        if self._verbose:
            print('')
        self._regions = []
Example #4
0
 def add(self, tile):
     if self.is_full():
         raise errors.ChrPageFull()
     ret = self.size()
     self.tiles.append(tile)
     return ret
Example #5
0
  def process_image(self, img, palette_text, bg_color_mask, bg_color_fill,
                    platform, is_locked_tiles, lock_sprite_flips,
                    allow_overflow):
    """Process free sprites image, creating the ppu_memory it represents.

    The image represents the entire screen, and is mostly filled with
    bg_color_fill. Anywhere that contains other pixel data is considered to be
    made of sprites. Those sprites are located, treated as tiles, and processed
    to be converted into PPU memory.

    img: Pixel art image.
    palette_text: Optional string representing a palette to be parsed.
    bg_color_mask: Background color that masks existing free sprite tiles.
    bg_color_fill: Background color which fills up the outside space.
    is_locked_tiles: Whether tiles are locked or not.
    allow_overflow: List of components for which to allow overflows.
    """
    self.initialize()
    self.load_image(img)
    self.set_platform(platform)
    config = ppu_memory.PpuMemoryConfig(is_sprite=True,
                                        is_locked_tiles=is_locked_tiles,
                                        lock_sprite_flips=lock_sprite_flips,
                                        allow_overflow=allow_overflow)
    is_tall = '8x16' in self.traversal
    # Scan the image, find corners of each tile based upon region merging.
    try:
      zones = self._find_zones(bg_color_fill)
    except errors.CouldntConvertRGB as e:
      self._err.add(e)
      return None
    # HACK: Assign zones to ppu_memory so that they can be used by the
    # view renderer.
    self._ppu_memory.zones = zones
    # Parse the palette if provided.
    pal = None
    if palette_text or self.img.palette:
      pal = self.parse_palette(palette_text, bg_color_mask)
    # Convert zones into artifacts.
    artifacts = []
    for z in zones:
      vert_color_needs = None
      for sprite_y, sprite_x in z.each_sprite(is_tall):
        (color_needs, dot_profile) = self.process_tile(
          sprite_y // 8, sprite_x // 8, sprite_y % 8, sprite_x % 8)
        cid = self._color_manifest.id(color_needs)
        did = self._dot_manifest.id(dot_profile)
        artifacts.append([cid, did, None, sprite_y, sprite_x])
        if not is_tall:
          continue
        elif vert_color_needs is None:
          vert_color_needs = color_needs
        else:
          try:
            self.combine_color_needs(vert_color_needs, color_needs)
          except errors.PaletteOverflowError as e:
            e.tile_y = sprite_y // 8
            e.tile_x = sprite_x // 8
            self._err.add(e)
            continue
          vcid = self._vert_color_manifest.id(vert_color_needs)
          artifacts[-1][ARTIFACT_VCID] = vcid
          vert_color_needs = None
    if self._err.has():
      return
    self._needs_provider = self._color_manifest
    if is_tall:
      self._needs_provider = self._vert_color_manifest
    # Build the palette.
    if not pal:
      pal = self.make_palette(bg_color_mask, True)
    # Build the PPU memory.
    if not is_tall:
      for cid, did, unused, y, x in artifacts:
        color_needs = self._color_manifest.at(cid)
        (pid, palette_option) = pal.select(color_needs)
        dot_xlat = self.get_dot_xlat(color_needs, palette_option)
        try:
          (chr_num, flip_bits) = self.store_chrdata(dot_xlat, did, config)
        except errors.NametableOverflow as e:
          self._err.add(errors.NametableOverflow(e.chr_num, y, x))
          chr_num = 0
        if (config.is_locked_tiles and self._ppu_memory.chr_set.is_full() and
            chr_num == 0):
          raise errors.ChrPageFull()
        self._ppu_memory.spritelist.append([y - 1, chr_num, pid | flip_bits, x])
    else:
      ebs_processor = eight_by_sixteen_processor.EightBySixteenProcessor()
      ebs_processor.link_from(self)
      for i in range(0, len(artifacts), 2):
        (cid_u, did_u, unused, y, x) = artifacts[i]
        (cid_l, did_l, vcid, unused_y, unused_x) = artifacts[i+1]
        color_needs = self._vert_color_manifest.at(vcid)
        (pid, palette_option) = pal.select(color_needs)
        chr_num_u, chr_num_l, flip_bits = ebs_processor.store_vert_pair(
          palette_option, cid_u, did_u, cid_l, did_l, config)
        if (config.is_locked_tiles and self._ppu_memory.chr_set.is_full() and
            chr_num_u == 0 and chr_num_l == 0):
          raise errors.ChrPageFull()
        # TODO: Only add this 1 if the sprite chr order is 1.
        chr_num = chr_num_u + 1
        if not 's' in config.allow_overflow:
          if len(self._ppu_memory.spritelist) >= 0x40:
            self._err.add(errors.SpritelistOverflow(y, x))
            continue
        self._ppu_memory.spritelist.append([y - 1, chr_num, pid | flip_bits, x])
    self._ppu_memory.palette_spr = pal