diff --git a/data/SNES_PSX_addresses.tsv b/data/SNES_PSX_addresses.tsv index a60311e..30bd1f8 100644 --- a/data/SNES_PSX_addresses.tsv +++ b/data/SNES_PSX_addresses.tsv @@ -2,6 +2,7 @@ Label SNES PSX_file PSX_offset format Comment character_battle_sprite_stone_palette 0x00F807 N/A N/A Palette16Of555 Also 0x199835 character_battle_sprite_disabled_palette 0x00F867 /mnu/memsave.bin 0x000034 Palette16Of555 locations_bg_palettes 0x03BB00 /nar/ff5_binx.bin 0x03BF80 43 of Palette128Of555 +font_glyphs_dialogue 0x03E800 256 of SNESTritile length 0x1800 enemy_battle_sprite_palettes 0x0ED000 See enemy_battle_sprite_data for pointers. Some are 8 colours instead of 16. worldmap_blocks 0x0FF0C0 /nar/ff5_binx.bin 0x040300 3 of 4 of 192 of u8 # Top-left corners, top-right corners, bottom-left corners, bottom-right corners worldmap_tiles.bias 0x0FF9C0 /nar/ff5_bin3.bin 0x03FB00 3 of 256 of u8 Add to each pixel of the mode7c tiles @@ -38,6 +39,7 @@ attack_layouts 0x117FA0 5 of 2048 of u8 length 0x2400 weapon_palettes 0x11A3A0 enemy_battle_status_sprite_palette 0x11A400 Palette16Of555 tiles_fist 0x11D710 /btl/ff5_btl.bin 0x021D10 TileSNES3bpp Also /mnu/men_bin.eng:0x00D910 +font_glyphs_small 0x11F000 256 of TileSNES2bpp length 0x1000 character_battle_sprite_tiles 0x120000 /mnu/men_bin.eng 0x010200 5 of 22 of 48 of TileSNES4bpp character_battle_sprite_palettes 0x14A3C0 /btl/ff5_btl.bin 0x0273C0 5 of 22 of Palette16Of555 Also /mnu/men_bin.eng:0x03A5C0 enemy_battle_sprite_data 0x14B180 384 of EnemySpriteData length 0x780 @@ -70,4 +72,5 @@ tiles_npcs 0x1A0000 worldmap_tiles.0 0x1B8000 /nar/ff5_bin3.bin 0x039B00 256 of TileSNESMode7c Add the biases worldmap_tiles.1 0x1BA000 /nar/ff5_bin3.bin 0x039B00 256 of TileSNESMode7c Add the biases worldmap_tiles.2 0x1BC000 /nar/ff5_bin3.bin 0x039B00 128 of TileSNESMode7c Add the biases - +font_glyphs_kanji 0x1BD000 426 of SNESTritile length of 0x27F0 +? 0x1BF800 diff --git a/scripts/loaders/SpriteLoader.gd b/scripts/loaders/SpriteLoader.gd index 4b3a0a8..a2f964e 100644 --- a/scripts/loaders/SpriteLoader.gd +++ b/scripts/loaders/SpriteLoader.gd @@ -7,6 +7,7 @@ const snes_battle_bgs := preload('res://scripts/loaders/snes/battle_bgs.gd') const gba_graphics := preload('res://scripts/loaders/gba/graphics.gd') var shader_material = load('res://palette_mat.tres') const TILE_RECT := Rect2(0, 0, 8, 8) +const GLYPH_RECT := Rect2(0, 0, 16, 12) # Offsets @@ -39,6 +40,8 @@ var character_battle_sprite_palette_textures = [] var character_battle_sprite_palette_disabled_texture: ImageTexture var character_battle_sprite_palette_stone_texture: ImageTexture var weapon_textures = {} +var font_atlas_image: Image +var font_atlas_texture: ImageTexture var character_status_palette_replacements = { 'poison': {4: '$7EDB = #DEB5FF', 8: '$4DD3 = #9C739C'}, # Also kneel @@ -143,6 +146,36 @@ static func make_tile_atlas(tile_images) -> Image: image.blit_rect(tile_images[tile], TILE_RECT, Vector2((tile%16)*8, (tile/16)*8)) return image +static func make_font_glyph_atlas(small_glyph_indexed_images, dialog_glyph_images, kanji_glyph_images) -> Image: + # Pack 256 small glyphs, 256 dialog glyphs, 426 kanji glyphs into a 512x512 atlas + var atlas = Image.new() + atlas.create(512, 512, false, Image.FORMAT_LA8) + for i in 256: + # First, convert indexed to LA8 + var indexed: Image = small_glyph_indexed_images[i] + var data := PoolByteArray() + for pixel in indexed.get_data(): + match pixel: + 0: + data.append(0) + data.append(0xFF) + 1: + data.append(0) + data.append(0) + 2: + data.append(0x80) + data.append(0xFF) + 3: + data.append(0xFF) + data.append(0xFF) + var tile = Image.new() + tile.create_from_data(8, 8, false, Image.FORMAT_LA8, data) + atlas.blit_rect(tile, TILE_RECT, Vector2((i%64)*8, (i/64)*8)) + for i in 256: + atlas.blit_rect(dialog_glyph_images[i], GLYPH_RECT, Vector2((i%32)*16, (i/32)*12 + 32)) + for i in 426: + atlas.blit_rect(kanji_glyph_images[i], GLYPH_RECT, Vector2((i%32)*16, (i/32)*12 + 128)) + return atlas # func snes_load_worldmap(rom: File): # # Load Worldmap Graphics @@ -501,6 +534,10 @@ func load_from_structs(data: Dictionary): MapLoader.update_worldmap_block_tile_ids(worldmap_block_tile_ids) + # Make font atlas + self.font_atlas_image = make_font_glyph_atlas(data.font_glyphs_small, data.font_glyphs_dialogue, data.font_glyphs_kanji) + self.font_atlas_texture = texture_from_image(self.font_atlas_image) + const gba_marker := 'FINAL FANTASY V ADVANCE SYGMAB' const gba_marker_pos_US := 0x12FE10 const gba_marker_pos_EU := 0x131294 diff --git a/scripts/loaders/snes/graphics.gd b/scripts/loaders/snes/graphics.gd index 863f5c7..875aba7 100644 --- a/scripts/loaders/snes/graphics.gd +++ b/scripts/loaders/snes/graphics.gd @@ -74,6 +74,24 @@ static func get_tile(rom: File, offset: int, length: int) -> Image: _: return _1plane_to_tile(data) +static func get_tritile(buffer: StreamPeer) -> Image: + # Converts 1bpp planar font tile to 16bpp image for convenience. + var tdata := ByteArray(384) # 16*12*2 + for plane in 2: + for row in 12: + var byte = buffer.get_u8() + for bit in 8: + var idx: int = 2 * (bit + (plane*8) + (row*16)) + if (byte >> (7-bit)) & 1: + tdata[idx] = 0xFF + tdata[idx+1] = 0xFF + else: + tdata[idx] = 0 + tdata[idx+1] = 0 + var tile := Image.new() + tile.create_from_data(16, 12, false, Image.FORMAT_LA8, tdata) + return tile + static func bgr555_to_color(short: int) -> Color: var color = Color() color.a = 1 diff --git a/scripts/loaders/snes/structs.gd b/scripts/loaders/snes/structs.gd index fa8c2fc..ccc9776 100644 --- a/scripts/loaders/snes/structs.gd +++ b/scripts/loaders/snes/structs.gd @@ -28,6 +28,10 @@ class TileSNES1bpp extends STRUCT.StructType: func get_value(buffer: StreamPeer, leftover_bits: Array): return GRAPHICS._1plane_to_tile(buffer.get_data(8)[1]) +class SNESTritile extends STRUCT.StructType: # Not TileSNESTritile as these are 16x12 not 8x8 + func get_value(buffer: StreamPeer, leftover_bits: Array): + return GRAPHICS.get_tritile(buffer) + class ColorBGR555 extends STRUCT.StructType: func get_value(buffer: StreamPeer, leftover_bits: Array): return GRAPHICS.bgr555_to_color(buffer.get_u16()) @@ -102,6 +106,7 @@ static func get_structtypes() -> Dictionary: 'TileSNES3bpp': TileSNES3bpp.new(), 'TileSNES2bpp': TileSNES2bpp.new(), 'TileSNES1bpp': TileSNES1bpp.new(), + 'SNESTritile': SNESTritile.new(), 'ColorBGR555': ColorBGR555.new(), 'Palette16Of555': PaletteOf555.new(16), 'Palette128Of555': PaletteOf555.new(128), diff --git a/test_scene.gd b/test_scene.gd index ed32092..7fc82dd 100644 --- a/test_scene.gd +++ b/test_scene.gd @@ -49,6 +49,10 @@ func _ready(): bbg.align = LineEdit.ALIGN_RIGHT add_child(bbg) + var fontbox := TextureRect.new() + fontbox.texture = SpriteLoader.font_atlas_texture + add_child(fontbox) + # var lbl = Label.new() # for i in 22: # lbl.text = lbl.text + '%s - %s\n' % [StringLoader.get_job_name(i), StringLoader.get_job_desc(i)]