def test_from_block(self): block = Block() block.from_list([1] * 5) block.write_multi(1, 0x8000 | 0x2000 | (7 << 10) | 0x120, 2) block.write_multi(3, 0x4000 | (2 << 10) | 0x3f5, 2) arrangement = EbTileArrangement(2, 1) arrangement.from_block(block, 1) assert_true(arrangement[0, 0].is_vertically_flipped) assert_false(arrangement[0, 0].is_horizontally_flipped) assert_true(arrangement[0, 0].is_priority, True) assert_equal(arrangement[0, 0].subpalette, 7) assert_equal(arrangement[0, 0].tile, 0x120) assert_false(arrangement[1, 0].is_vertically_flipped) assert_true(arrangement[1, 0].is_horizontally_flipped) assert_false(arrangement[1, 0].is_priority) assert_equal(arrangement[1, 0].subpalette, 2) assert_equal(arrangement[1, 0].tile, 0x3f5) arrangement = EbTileArrangement(1, 2) arrangement.from_block(block, 1) assert_true(arrangement[0, 0].is_vertically_flipped) assert_false(arrangement[0, 0].is_horizontally_flipped) assert_true(arrangement[0, 0].is_priority, True) assert_equal(arrangement[0, 0].subpalette, 7) assert_equal(arrangement[0, 0].tile, 0x120) assert_false(arrangement[0, 1].is_vertically_flipped) assert_true(arrangement[0, 1].is_horizontally_flipped) assert_false(arrangement[0, 1].is_priority) assert_equal(arrangement[0, 1].subpalette, 2) assert_equal(arrangement[0, 1].tile, 0x3f5)
def test_from_image_8x8_1bpp(self): palette = EbPalette(1, 2) palette[0, 0].from_tuple((0xff, 0xff, 0xff)) palette[0, 1].from_tuple((0x0, 0x0, 0x0)) arrangement = EbTileArrangement(width=2, height=2) arrangement[0, 0].tile = 0 arrangement[1, 0].tile = 2 arrangement[0, 1].tile = 1 arrangement[1, 1].tile = 3 tileset = EbGraphicTileset(num_tiles=4, tile_width=8, tile_height=8) tileset.from_image(self.tile_8x8_2bpp_img, arrangement=arrangement, palette=palette) assert_list_equal(tileset[0], [[0] * 8] * 8) assert_list_equal(tileset[2], [[1] * 8] * 8) assert_list_equal(tileset[1], [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) assert_list_equal(tileset[3], [[0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 1, 0, 1, 1], [1, 1, 0, 1, 0, 0, 1, 1], [1, 1, 0, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 0]])
def __init__(self): super(TitleScreenModule, self).__init__() # Background data (includes the central "B", the copyright # notice and the glow around the letters) self.bg_tileset = EbGraphicTileset(num_tiles=BG_NUM_TILES, tile_width=TILE_WIDTH, tile_height=TILE_HEIGHT) self.bg_arrangement = EbTileArrangement(width=BG_ARRANGEMENT_WIDTH, height=BG_ARRANGEMENT_HEIGHT) self.bg_anim_palette = EbPalette( num_subpalettes=BG_NUM_ANIM_SUBPALETTES, subpalette_length=ANIM_SUBPALETTE_LENGTH) self.bg_palette = EbPalette(num_subpalettes=NUM_SUBPALETTES, subpalette_length=BG_SUBPALETTE_LENGTH) # Characters data (the title screen's animated letters) self.chars_tileset = EbGraphicTileset(num_tiles=CHARS_NUM_TILES, tile_width=TILE_WIDTH, tile_height=TILE_HEIGHT) self.chars_anim_palette = EbPalette( num_subpalettes=CHARS_NUM_ANIM_SUBPALETTES, subpalette_length=ANIM_SUBPALETTE_LENGTH) self.chars_palette = EbPalette( num_subpalettes=NUM_SUBPALETTES, subpalette_length=CHARS_SUBPALETTE_LENGTH) self.chars_layouts = [[] for _ in xrange(NUM_CHARS)]
def test_to_image_single_subpalette(self): palette = EbPalette(1, 2) tileset = EbGraphicTileset(num_tiles=6, tile_width=8, tile_height=8) arrangement = EbTileArrangement(width=6, height=1) arrangement.from_image(self.tile_8x8_2bpp_2_img, tileset=tileset, palette=palette) new_image = arrangement.image(tileset, palette) assert_images_equal(self.tile_8x8_2bpp_2_img, new_image)
def __init__(self): super(DeathScreenModule, self).__init__() self.tileset = EbGraphicTileset(num_tiles=NUM_TILES, tile_width=TILE_WIDTH, tile_height=TILE_HEIGHT) self.arrangement = EbTileArrangement(width=ARRANGEMENT_WIDTH, height=ARRANGEMENT_HEIGHT) self.palette = EbPalette(num_subpalettes=NUM_SUBPALETTES, subpalette_length=SUBPALETTE_LENGTH)
def test_init(self): arrangement = EbTileArrangement(32, 28) assert_equal(arrangement.width, 32) assert_equal(arrangement.height, 28) assert_raises(InvalidArgumentError, EbTileArrangement, 0, 32) assert_raises(InvalidArgumentError, EbTileArrangement, -1, 32) assert_raises(InvalidArgumentError, EbTileArrangement, 32, 0) assert_raises(InvalidArgumentError, EbTileArrangement, 32, -1) assert_raises(InvalidArgumentError, EbTileArrangement, 0, 0) assert_raises(InvalidArgumentError, EbTileArrangement, -1, -1)
def read_background_data_from_project(self, resource_open): # Load the background reference image # The image's arrangement, tileset and palette will be used for the # animation frames with resource_open(BG_REFERENCE_PATH, "png") as f: image = open_indexed_image(f) self.bg_arrangement.from_image( image, self.bg_tileset, self.bg_palette ) # Read the background animated frames for frame in range(NUM_ANIM_FRAMES): # Create temporary structures used to check consistency between # frames tileset = EbGraphicTileset(BG_NUM_TILES, TILE_WIDTH, TILE_HEIGHT) arrangement = EbTileArrangement( BG_ARRANGEMENT_WIDTH, BG_ARRANGEMENT_HEIGHT ) palette = EbPalette(NUM_SUBPALETTES, BG_SUBPALETTE_LENGTH) # Read one frame's image data with resource_open(BG_FRAMES_PATH.format(frame), "png") as f: image = open_indexed_image(f) arrangement.from_image(image, tileset, palette) # Make sure each frame's tileset and arrangement is identical # The background palette is checked only if it isn't the fake # palette used for the first few frames if frame >= CHARS_NUM_ANIM_SUBPALETTES: # Get the background animated subpalette from the background # palette colors = palette[0, BG_ANIM_SLICE] self.bg_anim_palette.subpalettes[ frame - CHARS_NUM_ANIM_SUBPALETTES ] = colors palette[0, BG_ANIM_SLICE] = self.bg_palette[ 0, BG_ANIM_SLICE ] if self.bg_palette != palette: log.warn( "Palette from background frame {} does not match " "reference.".format(frame) ) if self.bg_tileset != tileset: log.warn( "Tileset from background frame {} does not match " "reference.".format(frame) ) if self.bg_arrangement != arrangement: log.warn( "Arrangement from background frame {} does not match " "reference.".format(frame) )
def test_getitem(self): arrangement = EbTileArrangement(2, 1) assert_is_instance(arrangement[0, 0], EbTileArrangementItem) assert_is_instance(arrangement[1, 0], EbTileArrangementItem) assert_raises(InvalidArgumentError, arrangement.__getitem__, (-1, 0)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (0, -1)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (-1, -1)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (0, 1)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (0, 2)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (1, 2)) assert_raises(InvalidArgumentError, arrangement.__getitem__, (3, 0))
def write_chars_data_to_project(self, resource_open): # Build an arrangement combining every character for convenience chars_positions = {} arrangement = EbTileArrangement(3*9, 6) for c, layout in enumerate(self.chars_layouts): top_left = {'x': 128, 'y': 128} for e, entry in enumerate(layout): tile = entry.tile & (CHARS_NUM_TILES - 1) top_left['x'] = min(top_left['x'], int(entry.x)) top_left['y'] = min(top_left['y'], int(entry.y)) x = c*3 + (entry.x + 16) // 8 y = (entry.y + 24) // 8 arrangement[x, y].tile = tile if not entry.is_single(): arrangement[x+1, y].tile = tile + 1 arrangement[x, y+1].tile = tile + 16 arrangement[x+1, y+1].tile = tile + 17 chars_positions[c] = { 'x': c*3*8, 'y': 0, 'width': 3*8, 'height': 6*8, 'top_left_offset': top_left, 'unknown': layout[0].unknown } # Write the characters animation frames for p in range(CHARS_NUM_ANIM_SUBPALETTES): with resource_open(CHARS_FRAMES_PATH.format(p), "png") as f: image = arrangement.image( self.chars_tileset, self.chars_anim_palette.get_subpalette(p) ) image.save(f) # Write out the initial characters palette with resource_open(CHARS_INITIAL_PATH, "png") as f: image = arrangement.image( self.chars_tileset, self.chars_palette ) image.save(f) # Write out the positions of the characters with resource_open(CHARS_POSITIONS_PATH, "yml", True) as f: yml_dump(chars_positions, f, False)
def test_from_image_2_subpalettes(self): palette = EbPalette(2, 4) tileset = EbGraphicTileset(num_tiles=4, tile_width=8, tile_height=8) arrangement = EbTileArrangement(width=4, height=1) arrangement.from_image(image=self.tile_8x8_2bpp_3_img, tileset=tileset, palette=palette) img_palette = self.tile_8x8_2bpp_3_img.getpalette() self.tile_8x8_2bpp_3_img.putpalette([x & 0xf8 for x in img_palette]) before_image_rgb = self.tile_8x8_2bpp_3_img.convert("RGB") after_image_rgb = arrangement.image(tileset, palette).convert("RGB") assert_images_equal(before_image_rgb, after_image_rgb) assert_set_equal({palette[1, i] for i in range(4)}, { EbColor(24, 0, 248), EbColor(0, 248, 24), EbColor(152, 0, 248), EbColor(248, 144, 0) }) assert_set_equal({palette[0, i] for i in range(4)}, { EbColor(24, 0, 248), EbColor(0, 248, 24), EbColor(216, 248, 0), EbColor(152, 0, 248) }) assert_equal(arrangement[0, 0].tile, 0) assert_equal(arrangement[0, 0].subpalette, 0) assert_equal({tileset[0][0][i] for i in [-1, -2, -3, -4]}, {0, 1, 2, 3}) assert_equal(arrangement[1, 0].tile, 1) assert_equal(arrangement[1, 0].subpalette, 1) assert_equal({tileset[1][0][i] for i in [-1, -2, -3, -4]}, {0, 1, 2, 3}) assert_equal(arrangement[2, 0].tile, 2) assert_equal(arrangement[2, 0].subpalette, 0) assert_equal(arrangement[3, 0].tile, 3) assert_equal(arrangement[3, 0].subpalette, 1)
def test_from_image_8x16_2bpp(self): palette = EbPalette(1, 4) palette[0, 0].from_tuple((0xff, 0xff, 0xff)) palette[0, 1].from_tuple((0x30, 0x00, 0xff)) palette[0, 2].from_tuple((0xff, 0x00, 0x00)) palette[0, 3].from_tuple((0x00, 0xff, 0x48)) arrangement = EbTileArrangement(width=2, height=3) arrangement[0, 0].tile = 1 arrangement[1, 0].tile = 1 arrangement[0, 1].tile = 3 arrangement[1, 1].tile = 2 arrangement[0, 2].tile = 0 arrangement[1, 2].tile = 4 tileset = EbGraphicTileset(num_tiles=5, tile_width=8, tile_height=16) tileset.from_image(self.tile_8x16_4bpp_img, arrangement=arrangement, palette=palette) assert_list_equal(tileset[1], [[2] * 8] * 16) assert_list_equal(tileset[3], [[3] * 8] * 16) assert_list_equal(tileset[2], [[3] * 8, [3] * 8, [3] * 8, [3] * 8, [3] * 8, [3, 3, 1, 3, 3, 3, 3, 3], [3, 3, 1, 3, 3, 1, 3, 3], [1] * 8, [1, 1, 2, 2, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 2, 1, 1], [1, 1, 1, 1, 2, 2, 1, 1], [1, 1, 2, 2, 2, 1, 1, 1], [1] * 8, [1] * 8, [1, 1, 1, 3, 1, 1, 1, 1]]) assert_list_equal(tileset[0], [[2, 1, 1, 1, 1, 1, 1, 1], [2, 3, 3, 3, 3, 3, 3, 1], [0, 2, 3, 3, 3, 3, 1, 3], [0, 2, 3, 3, 3, 3, 1, 3], [0, 0, 2, 3, 3, 1, 3, 3], [0, 0, 2, 3, 3, 1, 3, 3], [0, 0, 0, 2, 1, 3, 3, 3], [0, 0, 0, 2, 1, 3, 3, 3], [0, 0, 0, 1, 2, 3, 3, 3], [0, 0, 0, 1, 2, 3, 3, 3], [0, 0, 1, 0, 0, 2, 3, 3], [0, 0, 1, 0, 0, 2, 3, 3], [0, 1, 0, 0, 0, 0, 2, 3], [0, 1, 0, 0, 0, 0, 2, 3], [1, 0, 0, 0, 0, 0, 0, 2], [1, 0, 0, 0, 0, 0, 0, 2]]) assert_list_equal(tileset[4], [[3] * 8, [3] * 8, [3] * 8, [3] * 8, [3] * 8, [3, 2, 3, 3, 3, 2, 3, 3], [3] * 8, [3] * 8, [3, 3, 3, 3, 3, 3, 3, 2], [2, 3, 3, 3, 3, 3, 2, 3], [3, 2, 3, 3, 3, 2, 2, 3], [3, 2, 2, 2, 2, 2, 3, 3], [3] * 8, [3] * 8, [3] * 8, [3] * 8])
def test_from_image_single_subpalette(self): palette = EbPalette(1, 2) tileset = EbGraphicTileset(num_tiles=6, tile_width=8, tile_height=8) arrangement = EbTileArrangement(width=6, height=1) arrangement.from_image(self.tile_8x8_2bpp_2_img, tileset=tileset, palette=palette) assert_equal(palette[0, 0], EbColor(0, 0, 0)) assert_equal(palette[0, 1], EbColor(0xf8, 0xf8, 0xf8)) item = arrangement[0, 0] assert_equal(item.subpalette, 0) assert_equal(arrangement[1, 0].tile, item.tile) assert_equal(arrangement[1, 0].is_horizontally_flipped, not item.is_horizontally_flipped) assert_equal(arrangement[1, 0].is_vertically_flipped, item.is_vertically_flipped) assert_equal(arrangement[1, 0].subpalette, 0) assert_equal(arrangement[2, 0].tile, item.tile) assert_equal(arrangement[2, 0].is_horizontally_flipped, item.is_horizontally_flipped) assert_equal(arrangement[2, 0].is_vertically_flipped, not item.is_vertically_flipped) assert_equal(arrangement[2, 0].subpalette, 0) assert_equal(arrangement[3, 0].tile, item.tile) assert_equal(arrangement[3, 0].is_horizontally_flipped, not item.is_horizontally_flipped) assert_equal(arrangement[2, 0].is_vertically_flipped, not item.is_vertically_flipped) assert_equal(arrangement[3, 0].subpalette, 0) assert_not_equal(arrangement[4, 0].tile, item.tile) assert_equal(arrangement[4, 0].subpalette, 0) assert_equal(arrangement[5, 0].tile, item.tile) assert_equal(arrangement[5, 0].is_horizontally_flipped, item.is_horizontally_flipped) assert_equal(arrangement[5, 0].is_vertically_flipped, item.is_vertically_flipped) assert_equal(arrangement[5, 0].subpalette, 0)
def read_from_project(self, resource_open): with resource_open("bg_data_table", "yml", True) as f: self.bg_table.from_yml_file(f) with resource_open("bg_scrolling_table", "yml", True) as f: self.scroll_table.from_yml_file(f) with resource_open("bg_distortion_table", "yml", True) as f: self.distortion_table.from_yml_file(f) self.backgrounds = [] self.palettes = [] for i in range(self.bg_table.num_rows): new_color_depth = self.bg_table[i][2] with resource_open("BattleBGs/" + str(i).zfill(3), "png") as f: image = open_indexed_image(f) new_palette = EbPalette(num_subpalettes=1, subpalette_length=16) new_tileset = EbGraphicTileset(num_tiles=512, tile_width=8, tile_height=8) new_arrangement = EbTileArrangement(width=32, height=32) new_arrangement.from_image(image, new_tileset, new_palette) for j, (tileset, color_depth, arrangement) in enumerate(self.backgrounds): if (color_depth == new_color_depth) \ and (tileset == new_tileset) \ and (arrangement == new_arrangement): self.bg_table[i][0] = j break else: self.bg_table[i][0] = len(self.backgrounds) self.backgrounds.append( (new_tileset, new_color_depth, new_arrangement)) for j, palette in enumerate(self.palettes): if palette == new_palette: self.bg_table[i][1] = j break else: self.bg_table[i][1] = len(self.palettes) self.palettes.append(new_palette)
def __init__(self, frames, unknown, graphics_data_size=None): self.graphics_data_size = graphics_data_size self.frames = frames self.unknown = unknown if graphics_data_size: num_tiles = EbGraphicTileset.tiles_from_parameters( graphics_data_size, TILE_WIDTH, TILE_HEIGHT, TILE_BPP) else: # Make tileset with maximum number of tiles possible for each frame of animation num_tiles = SCREEN_WIDTH_TILES * SCREEN_HEIGHT_TILES * frames # Animations are 2 bpp, so the palette will have 4 colors self.palette = EbPalette(num_subpalettes=1, subpalette_length=4) self.graphics = EbGraphicTileset(num_tiles=num_tiles, tile_width=TILE_WIDTH, tile_height=TILE_HEIGHT) self.arrangements = [ EbTileArrangement(width=SCREEN_WIDTH_TILES, height=SCREEN_HEIGHT_TILES) for i in range(self.frames) ]
def read_chars_data_from_project(self, resource_open): # Read the characters positions with resource_open(CHARS_POSITIONS_PATH, "yml") as f: chars_positions = yml_load(f) # Read the characters animated frames self.chars_tileset = None self.chars_anim_palette = EbPalette(CHARS_NUM_ANIM_SUBPALETTES, ANIM_SUBPALETTE_LENGTH) original_tileset = None for p in xrange(CHARS_NUM_ANIM_SUBPALETTES): # Read one of the animation frames with resource_open(CHARS_FRAMES_PATH.format(p), "png") as f: # Create temporary structures to hold the data image = open_indexed_image(f) arrangement = EbTileArrangement(image.width / TILE_WIDTH, image.height / TILE_HEIGHT) tileset = EbGraphicTileset(CHARS_NUM_TILES, TILE_WIDTH, TILE_HEIGHT) anim_subpalette = EbPalette(NUM_SUBPALETTES, ANIM_SUBPALETTE_LENGTH) arrangement.from_image(image, tileset, anim_subpalette, True) # Add the characters animation subpalette for i in xrange(ANIM_SUBPALETTE_LENGTH): self.chars_anim_palette[p, i] = anim_subpalette[0, i] # Add the characters tileset if not already set, otherwise # ensure that it the current tileset is identical if not self.chars_tileset: original_tileset = tileset self.chars_tileset = EbGraphicTileset(CHARS_NUM_TILES, TILE_WIDTH, TILE_HEIGHT) self.chars_tileset.tiles = [[[0 for _ in xrange(TILE_HEIGHT)] for _ in xrange(TILE_WIDTH)] for _ in xrange(CHARS_NUM_TILES)] unused_tiles = set(xrange(CHARS_NUM_TILES)) # Set the new character layouts self.chars_layouts = [[] for _ in xrange(NUM_CHARS)] for c, data in chars_positions.items(): # Get the data from the YAML file x = int(data['x'] / TILE_WIDTH) y = int(data['y'] / TILE_HEIGHT) width = int(data['width'] / TILE_WIDTH) height = int(data['height'] / TILE_HEIGHT) x_offset = data['top_left_offset']['x'] y_offset = data['top_left_offset']['y'] unknown = data['unknown'] # Generate a list of all tiles must be visited # Where possible, we try to generate a multi tile (4 tiles # stored as one); otherwise, bordering tiles that are # visited will all be single tiles. l = [(i, j) for i in xrange(0, width, 2) for j in xrange(0, height, 2)] if width % 2 == 1: l.extend([(width - 1, j) for j in xrange(1, height, 2)]) if height % 2 == 1: l.extend([(i, height - 1) for i in xrange(1, width, 2)]) # Generate the new reduced tileset for i, j in l: # Put the tile in the new tileset o_tile = arrangement[x + i, y + j].tile n_tile = unused_tiles.pop() self.chars_tileset.tiles[n_tile] = tileset[o_tile] entry = TitleScreenLayoutEntry(i * 8 + x_offset, j * 8 + y_offset, n_tile, 0, unknown) # Create a multi entry if possible to save space if i < width - 1 and j < height - 1: entry.set_single(True) o_tile_r = arrangement[x + i + 1, y + j].tile o_tile_d = arrangement[x + i, y + j + 1].tile o_tile_dr = arrangement[x + i + 1, y + j + 1].tile n_tile_r = n_tile + 1 n_tile_d = n_tile + 16 n_tile_dr = n_tile + 17 unused_tiles.difference_update( (n_tile_r, n_tile_d, n_tile_dr)) self.chars_tileset.tiles[n_tile_r] = \ tileset[o_tile_r] self.chars_tileset.tiles[n_tile_d] = \ tileset[o_tile_d] self.chars_tileset.tiles[n_tile_dr] = \ tileset[o_tile_dr] self.chars_layouts[c].append(entry) self.chars_layouts[c][-1].set_final(True) elif original_tileset != tileset: log.warn("Tileset from characters frame {} does not match " "tileset from characters frame 0.".format(p)) # Read the initial characters palette with resource_open(CHARS_INITIAL_PATH, "png") as f: image = open_indexed_image(f) arrangement = EbTileArrangement(image.width / TILE_WIDTH, image.height / TILE_HEIGHT) tileset = EbGraphicTileset(CHARS_NUM_TILES, TILE_WIDTH, TILE_HEIGHT) self.chars_palette = EbPalette(NUM_SUBPALETTES, ANIM_SUBPALETTE_LENGTH) arrangement.from_image(image, tileset, self.chars_palette)
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
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 1, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 1, 0, 0 ] ARRANGEMENT_1 = EbTileArrangement(width=16, height=26) for y in range(ARRANGEMENT_1.height): for x in range(ARRANGEMENT_1.width): i = y * ARRANGEMENT_1.width + x ARRANGEMENT_1[x, y].tile = i ARRANGEMENT_1[x, y].subpalette = ARRANGEMENT_PREVIEW_SUBPALETTES[i] ARRANGEMENT_2 = EbTileArrangement(width=7, height=1) for y in range(ARRANGEMENT_2.height): for x in range(ARRANGEMENT_2.width): ARRANGEMENT_2[x, y].tile = y * ARRANGEMENT_1.width + x ARRANGEMENT_2[x, y].subpalette = 0 class WindowGraphicsModule(EbModule): NAME = "Window Graphics" FREE_RANGES = [(0x200000, 0x20079f)] # Graphics
TOWN_MAP_ICON_PREVIEW_SUBPALETTES = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] TOWN_MAP_ICON_PREVIEW_ARRANGEMENT = EbTileArrangement(width=16, height=18) for i in range(16 * 18): item = TOWN_MAP_ICON_PREVIEW_ARRANGEMENT[i % 16, i // 16] item.is_priority = False item.is_horizontally_flipped = False item.is_vertically_flipped = False item.subpalette = TOWN_MAP_ICON_PREVIEW_SUBPALETTES[i] item.tile = i class CompressedGraphicsModule(EbModule): NAME = "Compressed Graphics" FREE_RANGES = [ (0x2021a8, 0x20ed02), # Town Map data (0x214ec1, 0x21ae7b ), # Company Logos, "Produced by" and "Presented by", and Gas Station
from coilsnake.model.eb.blocks import EbCompressibleBlock from coilsnake.model.eb.graphics import EbTileArrangement, EbGraphicTileset from coilsnake.model.eb.palettes import EbPalette from coilsnake.util.common.image import open_indexed_image from coilsnake.util.common.yml import yml_load, yml_dump from coilsnake.util.eb.pointer import from_snes_address, read_asm_pointer, write_asm_pointer, to_snes_address FONT_IMAGE_PALETTE = EbPalette(1, 2) FONT_IMAGE_PALETTE[0, 0].from_tuple((255, 255, 255)) FONT_IMAGE_PALETTE[0, 1].from_tuple((0, 0, 0)) FONT_IMAGE_ARRANGEMENT_WIDTH = 16 _FONT_IMAGE_ARRANGEMENT_96 = EbTileArrangement(width=FONT_IMAGE_ARRANGEMENT_WIDTH, height=6) _FONT_IMAGE_ARRANGEMENT_128 = EbTileArrangement(width=FONT_IMAGE_ARRANGEMENT_WIDTH, height=8) for y in range(_FONT_IMAGE_ARRANGEMENT_96.height): for x in range(_FONT_IMAGE_ARRANGEMENT_96.width): _FONT_IMAGE_ARRANGEMENT_96[x, y].tile = y * _FONT_IMAGE_ARRANGEMENT_96.width + x for y in range(_FONT_IMAGE_ARRANGEMENT_128.height): for x in range(_FONT_IMAGE_ARRANGEMENT_128.width): _FONT_IMAGE_ARRANGEMENT_128[x, y].tile = y * _FONT_IMAGE_ARRANGEMENT_128.width + x class EbFont(object): def __init__(self, num_characters=96, tile_width=16, tile_height=8): self.num_characters = num_characters self.tileset = EbGraphicTileset(num_tiles=num_characters, tile_width=tile_width, tile_height=tile_height) self.character_widths = None def from_block(self, block, tileset_offset, character_widths_offset): self.tileset.from_block(block=block, offset=tileset_offset, bpp=1)
[1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3], [5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1]] SOUND_STONE_ARRANGEMENT = EbTileArrangement(width=16, height=22) for y in range(SOUND_STONE_ARRANGEMENT.height): for x in range(SOUND_STONE_ARRANGEMENT.width): SOUND_STONE_ARRANGEMENT[x, y].tile = y * SOUND_STONE_ARRANGEMENT.width + x SOUND_STONE_ARRANGEMENT[x, y].subpalette = SOUND_STONE_SUBPALETTES[y][x] class SoundStoneModule(EbModule): NAME = "Sound Stone" FREE_RANGES = [(0x0EDD5D, 0x0EF805)] # Sound stone graphics def __init__(self): super(SoundStoneModule, self).__init__() self.tileset = EbGraphicTileset(num_tiles=352,