class_name AssetRipper extends Node const SPRITES_PATH: String = "res://Resources/AssetRipper/Sprites/" const SPRITE_LIST_PATH: String = "res://Resources/AssetRipper/SpriteList.json" const DEFAULT_PALETTE_GROUP: String = "Default" const PREVIEW_PALETTE: Array[Color] = [ Color.TRANSPARENT, Color.DIM_GRAY, Color.WHITE, Color.DARK_GRAY ] const PALETTES_FOLDER: String = "res://Resources/AssetRipper/Palettes/%s/%s.json" var rom: PackedByteArray var prg_rom_size: int var chr_rom: PackedByteArray ## UTIL func index_to_coords(index: int, max_x: int) -> Vector2i: var x: int = wrapi(index, 0, max_x) @warning_ignore("integer_division") var y: int = floor(index / max_x) return Vector2i(x, y) func combine_bytes(byte0: int, byte1: int) -> PackedByteArray: var output_value: PackedByteArray for index in range(8): var bit_mask: int = 1 << index var shifted_byte0: int = (byte0 & bit_mask) >> index var shifted_byte1: int = (byte1 & bit_mask) >> index << 1 output_value.insert(0, shifted_byte0 + shifted_byte1) return output_value func reverse_bits(num: int): num = (num & 0xF0) >> 4 | (num & 0x0F) << 4 num = (num & 0xCC) >> 2 | (num & 0x33) << 2 num = (num & 0xAA) >> 1 | (num & 0x55) << 1 return num func png_path_to_json(png_path: String) -> String: return png_path.replace( "res://Assets/Sprites/", "res://Resources/AssetRipper/Sprites/" ).replace(".png", ".json") ## TILE HANDLING func draw_tile( chroma_key: bool, image: Image, index: int, pos: Vector2i, palette: PackedColorArray, flip_h: bool = false, flip_v: bool = false ) -> void: var y = 0 var img_size: Vector2i = image.get_size() var loaded_tile: Array[Array] = load_tile(index) if flip_h: for row in range(loaded_tile.size()): for byte in range(loaded_tile[row].size()): loaded_tile[row][byte] = reverse_bits(loaded_tile[row][byte]) if flip_v: loaded_tile.reverse() for row: Array in loaded_tile: if y + pos.y < img_size.y: var x = 0 for pixel: int in combine_bytes(row[0], row[1]): if x + pos.x < img_size.x: if not chroma_key or image.get_pixelv(Vector2i(x, y) + pos) == Color.GREEN: image.set_pixelv(Vector2i(x, y) + pos, palette[pixel]) x += 1 y += 1 func load_tile(index: int) -> Array: var address: int = 16*index var data: Array[Array] = [] for i: int in range(8): var byte0: int = chr_rom[address + i] var byte1: int = chr_rom[address + i + 8] data.append([byte0, byte1]) return data