예제 #1
0
    def make_spritelist(self, traversal, pal, config):
        """Convert data from the nametable to create spritelist.

    traversal: Method of traversal
    """
        empty_did = self._dot_manifest.get(chr(0) * 64)
        empty_cid = self._color_manifest.get(chr(pal.bg_color) + chr(NULL) * 3)
        # TODO: Only set this to 1 if the sprite chr order is 1.
        tile_low_bit = 1
        for (y, x) in self.get_generator(traversal):
            (cid_u, did_u, bcid_u) = self._artifacts[y][x]
            (cid_l, did_l, bcid_l) = self._artifacts[y + 1][x]
            if (empty_cid == cid_u and empty_did == did_u
                    and empty_cid == cid_l and empty_did == did_l):
                continue
            tile = self._ppu_memory.gfx_0.nametable[y][x]
            if not 's' in config.allow_overflow:
                if len(self._ppu_memory.spritelist) == 0x40:
                    if not config.is_locked_tiles:
                        self._err.add(errors.SpritelistOverflow(y, x))
                    continue
            y_pos = y * 8 - 1 if y > 0 else 0
            x_pos = x * 8
            attr = self._ppu_memory.gfx_0.colorization[y][x] | self._flip_bits[
                y][x]
            self._ppu_memory.spritelist.append(
                [y_pos, tile + tile_low_bit, attr, x_pos])
예제 #2
0
    def make_spritelist(self, traversal, pal, config):
        """Convert data from the nametable to create spritelist.

    traversal: Method of traversal
    """
        empty_did = self._dot_manifest.get(bytes(bytearray([0] * 64)))
        empty_cid = self._color_manifest.get(
            bytes(bytearray([pal.bg_color] + [NULL] * 3)))
        generator = ((y, x) for y in range(self.blocks_y * 2)
                     for x in range(self.blocks_x * 2))
        for (y, x) in generator:
            (cid, did, bcid) = self._artifacts[y][x]
            if empty_cid == cid and empty_did == did:
                continue
            tile = self._ppu_memory.gfx[0].nametable[y][x]
            if not config.allow_overflow or not 's' in config.allow_overflow:
                if len(self._ppu_memory.spritelist) >= 0x40:
                    if not config.is_locked_tiles:
                        self._err.add(errors.SpritelistOverflow(y, x))
                    continue
            y_pos = y * 8 - 1 if y > 0 else 0
            x_pos = x * 8
            attr = self._ppu_memory.gfx[0].colorization[y][
                x] | self._flip_bits[y][x]
            self._ppu_memory.spritelist.append([y_pos, tile, attr, x_pos])
예제 #3
0
            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 = []
        zones = []
        # For each line of the image, starting from the top.
        for y in xrange(self.image_y):
            is_color = False
            x = 0
예제 #4
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