diff --git a/data/5/addresses_SNES_PSX.tsv b/data/5/addresses_SNES_PSX.tsv index 6ab7f76..992af1b 100644 --- a/data/5/addresses_SNES_PSX.tsv +++ b/data/5/addresses_SNES_PSX.tsv @@ -50,7 +50,7 @@ ptrs_tile_properties 0x0FC540 23 of u16 tile_properties 0x0FC56E See above for offsets worldmap_minimap_border_tiles 0x0FD800 32 of TileSNES4bpp length 0x400 ptrs_worldmap_tilesets 0x0FE000 5 of 256 of u16 Every offset points to a horizontal line of 256 tiles stored in banks C7 and C8 -worldmap_block_properties 0x0FEA00 3 of 192 of u24 +worldmap_block_properties 0x0FEA00 3 of 192 of WorldMapBlockProperties 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 worldmap_palettes 0x0FFCC0 /nar/ff5_binx.bin 0x040000 3 of 128 of ColorBGR555 diff --git a/data/5/structs/SNES.tsv b/data/5/structs/SNES.tsv index ccb7032..739093a 100644 --- a/data/5/structs/SNES.tsv +++ b/data/5/structs/SNES.tsv @@ -204,3 +204,27 @@ u8 x u8 num_bytes u8 event_flag # Add 0x1D0 to this for actual event flag u16 ptr_bytes # Read num_bytes from this address (0xC0 bank implied, so just from the start of the ROM) + +struct WorldMapBlockProperties +u1 is_pathable_foot +u1 is_pathable_chocobo +u1 is_pathable_black_chocobo +u1 is_pathable_hiryuu +u1 is_pathable_submarine +u1 is_pathable_ship +u1 is_pathable_airship +u1 is_surfaceable +u1 unk0_east # ship related? mostly seaside edges=0 but sometimes not +u1 unk0_west # ship related? mostly seaside edges=0 but sometimes not +u1 unk0_south # ship related? mostly seaside edges=0 but sometimes not +u1 unk0_north # ship related? mostly seaside edges=0 but sometimes not +u1 isnt_landable_chocobo +u1 isnt_landable_black_chocobo +u1 isnt_landable_hiryuu +u1 isnt_landable_airship +u4 unk1 # Maybe battle bg? 0=plains/other, 1=forest, 2=desert, 3=sea, 5=swamp, no others spotted for these 4 bits +u1 unk21 # Mountains and Exdeath's Castle =1 +u1 unk22 # Forests have this =1, except the southernmost tiles of them +u1 unk23 # Most rivers have this +u1 unk24 # Most walkable/boatable tiles have this - possibly random encounters enabled? + diff --git a/globals.gd b/globals.gd index 2cb864c..cdd043b 100644 --- a/globals.gd +++ b/globals.gd @@ -14,6 +14,7 @@ enum Menu { DEBUG, DEBUG_AUDIO_SYSTEM, DEBUG_BATTLE_SPRITES, + DEBUG_WORLD_MAP_BLOCKS, } const MENUS = { @@ -23,6 +24,7 @@ const MENUS = { Menu.DEBUG: ['res://test/debug_menu.tscn', 'Debug Menu'], Menu.DEBUG_BATTLE_SPRITES: ['res://test/battle_sprites.tscn', 'Battle Sprites'], Menu.DEBUG_AUDIO_SYSTEM: ['res://test/audio_system.tscn', 'Audio'], + Menu.DEBUG_WORLD_MAP_BLOCKS: ['res://test/worldmap_blocks.tscn', 'Worldmap Blocks'], Menu.WORLD_MAP: ['res://test/worldmap_system.tscn', 'World Map'], } @@ -37,6 +39,7 @@ const POST_ROM_MENUS = [ Menu.BATTLE, Menu.DEBUG_BATTLE_SPRITES, Menu.DEBUG_AUDIO_SYSTEM, + Menu.DEBUG_WORLD_MAP_BLOCKS, ] const FOLDER_ICON := preload('res://theme/icons/file_folder.tres') diff --git a/scripts/loaders/MapLoader.gd b/scripts/loaders/MapLoader.gd index bab59bb..4c27508 100644 --- a/scripts/loaders/MapLoader.gd +++ b/scripts/loaders/MapLoader.gd @@ -45,32 +45,24 @@ extends Node # Probably going to shader this effect instead of storing hundreds of frames # No palette cycling -enum FlagsBlockPathing { - PATHABLE_FOOT = 0x001, - PATHABLE_CHOCOBO = 0x002, - PATHABLE_BLACK_CHOCOBO = 0x004, - PATHABLE_HIRYUU = 0x008, - PATHABLE_SUBMARINE = 0x010, - PATHABLE_SHIP = 0x020, - PATHABLE_AIRSHIP = 0x040, - SURFACEABLE = 0x080, - LANDABLE_CHOCOBO = 0x100, - LANDABLE_BLACK_CHOCOBO = 0x200, - LANDABLE_HIRYUU = 0x400, - LANDABLE_AIRSHIP = 0x800, -} - class WorldMap: - const block_width := 256 - const block_height := 256 - const tile_width := block_width * 2 - const tile_height := block_height * 2 + var block_width: int + var block_height: int + var tile_width: int + var tile_height: int var blockmap: PoolByteArray var blockmap_original: PoolByteArray var block_tile_ids: PoolByteArray var block_pathing: PoolIntArray var event_replacements: Array # Array[int flag, EventReplacementRegion] + func _init(width: int = 256, height: int = 256) -> void: + self.block_width = width + self.block_height = height + self.tile_width = width * 2 + self.tile_height = height * 2 + + class EventReplacementRegion: var start_y: int var rows: Array # Array[Array[int, PoolByteArray]] @@ -78,7 +70,7 @@ class WorldMap: self.rows = [] func get_min_x() -> int: - var min_x = block_width + var min_x = 1000000 for row in rows: var x = row[0] if x < min_x: @@ -103,23 +95,23 @@ class WorldMap: func make_tile_map() -> Image: var image := Image.new() var data := PoolByteArray() - data.resize(tile_width*tile_height) + data.resize(self.tile_width * self.tile_height) var block_idx := 0 - for y_off in range(0, tile_height*tile_width, tile_width*2): - for x_off in range(0, tile_width, 2): + for y_off in range(0, self.tile_height*self.tile_width, self.tile_width*2): + for x_off in range(0, self.tile_width, 2): var tile_offset = self.blockmap[block_idx] * 4 block_idx += 1 data[y_off + x_off] = self.block_tile_ids[tile_offset] data[y_off + x_off + 1] = self.block_tile_ids[tile_offset+1] - data[y_off + tile_width + x_off] = self.block_tile_ids[tile_offset+2] - data[y_off + tile_width + x_off + 1] = self.block_tile_ids[tile_offset+3] - image.create_from_data(tile_width, tile_height, false, SpriteLoader.INDEX_FORMAT, data) + data[y_off + self.tile_width + x_off] = self.block_tile_ids[tile_offset+2] + data[y_off + self.tile_width + x_off + 1] = self.block_tile_ids[tile_offset+3] + image.create_from_data(self.tile_width, self.tile_height, false, SpriteLoader.INDEX_FORMAT, data) return image func apply_event_region_replacement(region: WorldMap.EventReplacementRegion): # Apply a single event region replacement var y := region.start_y - var y_offset = y * block_width + var y_offset = y * self.block_width for row in region.rows: var x: int = row[0] var blocks: PoolByteArray = row[1] @@ -131,7 +123,7 @@ class WorldMap: if len(new_blockmap) < len(self.blockmap): # Append behind if non-empty (weakness of PoolXArray::subarray) new_blockmap = new_blockmap + self.blockmap.subarray(len(new_blockmap), -1) self.blockmap = new_blockmap - y_offset += block_width + y_offset += self.block_width func apply_event_replacements(event_flags): # Any integer array is fine for flag_and_region in self.event_replacements: @@ -170,25 +162,6 @@ class WorldMap: var worldmaps = [WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new()] -var worldmap_block_properties = [] -var worldmap_block_pathings = [] -func load_worldmap_block_properties(data: Dictionary): # TODO: replace this with a struct definition - for world_ts in data.worldmap_block_properties: # 3 - var ts_properties = PoolIntArray() - var ts_pathings = PoolIntArray() - for properties in world_ts: - ts_properties.append(properties) - var pathings: int = properties >> 16 # First 8 pathable flags map directly - pathings |= (((properties >> 12) & 0xF) ^ 0xF) << 8 # Next 4 flags (can land) are taken from high bits of second byte and inverted - ts_pathings.append(pathings) - worldmap_block_properties.append(ts_properties) - worldmap_block_pathings.append(ts_pathings) - worldmaps[0].block_pathing = worldmap_block_pathings[0] - worldmaps[1].block_pathing = worldmap_block_pathings[1] - worldmaps[2].block_pathing = worldmap_block_pathings[0] - worldmaps[3].block_pathing = worldmap_block_pathings[2] - worldmaps[4].block_pathing = worldmap_block_pathings[2] - func load_worldmaps(data: Dictionary, buffer: StreamPeerBuffer): var offset1: int = Common.SNES_PSX_addresses.worldmap_compressed_tilesets.SNES @@ -238,5 +211,4 @@ func update_worldmap_block_tile_ids(worldmap_block_tile_ids: Array): worldmaps[4].block_tile_ids = worldmap_block_tile_ids[2] func load_snes_rom(data: Dictionary, buffer: StreamPeerBuffer): - load_worldmap_block_properties(data) load_worldmaps(data, buffer) diff --git a/scripts/loaders/SpriteLoader.gd b/scripts/loaders/SpriteLoader.gd index 0e96569..39b69a9 100644 --- a/scripts/loaders/SpriteLoader.gd +++ b/scripts/loaders/SpriteLoader.gd @@ -33,7 +33,6 @@ var worldmap_block_individual_imgs = [] var worldmap_block_individual_textures = [] var worldmap_block_atlas_imgs = [] var worldmap_block_atlas_textures = [] -# var worldmap_tile_atlas_textures = [] #var character_battle_sprite_tiles = [] #var character_battle_sprite_palette_imgs = [] @@ -179,97 +178,6 @@ static func make_font_glyph_atlas(small_glyph_indexed_images, dialog_glyph_image 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 -# var worldmap_tile_counts = [256, 256, 128] # Only 128 underwater tiles -# for world_ts in 3: # Bartz/Combined World, Galuf World, Underwater (world tilesets, not to be confused with the 5 world maps) -# var tile_count: int = worldmap_tile_counts[world_ts] -# var image := generate_palette(rom, Common.SNES_PSX_addresses['worldmap_palettes']['SNES'] + (world_ts*0x100), 0x100) -# worldmap_palette_imgs.append(image) -# worldmap_palette_textures.append(texture_from_image(image)) - -# var tile_palettes = [] -# rom.seek(Common.SNES_PSX_addresses['worldmap_tiles.bias']['SNES'] + (world_ts*0x100)) -# for pal in 256: -# tile_palettes.append(rom.get_8()) - -# var tile_images = [] -# # var tile_textures = [] -# rom.seek(Common.SNES_PSX_addresses['worldmap_tiles']['SNES'] + (world_ts*0x2000)) -# for tile in tile_count: -# var tiledata := rom.get_buffer(32) -# image = snes_graphics.mode7_compressed_to_tile(tiledata, tile_palettes[tile]) -# tile_images.append(image) -# # tile_textures.append(texture_from_image(image)) -# if world_ts == 0: # Waterfall hack: lay it out vertically, pushing out dummy tiles -# tile_images[0x97] = tile_images[0x88] -# tile_images[0x98] = tile_images[0x87] -# worldmap_tile_individual_imgs.append(tile_images) -# worldmap_tile_atlas_textures.append(texture_from_image(make_tile_atlas(tile_images))) - - -# # Block definitions -# var block_images = [] -# var block_textures = [] -# var block_bank_start: int = Common.SNES_PSX_addresses['worldmap_blocks']['SNES'] + (world_ts*0x300) -# var block_tile_ids := PoolByteArray() -# for block in 0xC0: # 192 blocks per world tileset -# image = Image.new() -# image.create(16, 16, false, INDEX_FORMAT) -# for tile in 4: -# rom.seek(block_bank_start + block + (tile * 0xC0)) # Horrible interleaving scheme -# var src_idx := rom.get_8() -# block_tile_ids.append(src_idx) -# if src_idx < tile_count: -# image.blit_rect(tile_images[src_idx], Rect2(0, 0, 8, 8), Vector2((tile%2)*8, (tile/2)*8)) -# block_images.append(image) -# block_textures.append(texture_from_image(image)) -# worldmap_block_individual_imgs.append(block_images) -# worldmap_block_individual_textures.append(block_textures) -# worldmap_block_tile_ids.append(block_tile_ids) -# # Make block atlas -# image = Image.new() -# image.create(16*16, 16*12, false, INDEX_FORMAT) -# for block in 0xC0: -# image.blit_rect(block_images[block], Rect2(0, 0, 16, 16), Vector2((block%16)*16, (block/16)*16)) -# worldmap_block_atlas_imgs.append(image) -# worldmap_block_atlas_textures.append(texture_from_image(image)) - -# # # DEBUG: Make tile atlas -# # image = Image.new() -# # image.create(16*8, (tile_count/16)*8, false, INDEX_FORMAT) -# # for tile in tile_count: -# # image.blit_rect(tile_images[tile], Rect2(0, 0, 8, 8), Vector2((tile%16)*8, (tile/16)*8)) -# # worldmap_tile_atlas_textures.append(texture_from_image(image)) - -# MapLoader.update_worldmap_block_tile_ids(worldmap_block_tile_ids) - - -# func snes_load_battle_sprites(rom: File): -# # Load Battle sprites -# rom.seek(Common.SNES_PSX_addresses['character_battle_sprite_layouts']['SNES']) -# var battle_strip_layouts = rom.get_buffer(num_Character_Battle_Sprite_Layouts * 6) -# # Character Battle Sprite Tiles -# for strip in range(0, 22*5): -# var tiles = [] -# for i in range(0, 32*48, 32): -# tiles.append(snes_graphics.get_tile(rom, Common.SNES_PSX_addresses['character_battle_sprite_tiles']['SNES'] + (strip*32*48) + i, 32)) -# var strip_image = Image.new() -# strip_image.create(16, 24 * num_Character_Battle_Sprite_Layouts, false, INDEX_FORMAT) -# for i in range(6 * num_Character_Battle_Sprite_Layouts): -# strip_image.blit_rect(tiles[battle_strip_layouts[i]], Rect2(0, 0, 8, 8), Vector2((i%2) * 8, (i/2) * 8)) -# strip_images.append(strip_image) -# strip_textures.append(texture_from_image(strip_image)) - -# # Character Battle Sprite Palettes -# for palette in range(0, 22*5): -# character_battle_sprite_palette_textures.append(texture_from_image(generate_palette(rom, Common.SNES_PSX_addresses['character_battle_sprite_palettes']['SNES'] + (palette*32)))) -# character_battle_sprite_palette_disabled_texture = texture_from_image(generate_palette(rom, Common.SNES_PSX_addresses['character_battle_sprite_disabled_palette']['SNES'])) -# character_battle_sprite_palette_stone_texture = texture_from_image(generate_palette(rom, Common.SNES_PSX_addresses['character_battle_sprite_stone_palette']['SNES'])) - -# weapon_textures['Fist'] = texture_from_image(snes_graphics.get_tile(rom, Common.SNES_PSX_addresses['tiles_fist']['SNES'], 24)) - - # var json_sprite_blocks: Dictionary = Common.load_json('res://data/5/sprite_blocks.json') # This needs error handling later # var sprite_blocks := {} # func snes_load_map_sprites(rom: File): diff --git a/test/worldmap_blocks.gd b/test/worldmap_blocks.gd index ba9e847..b7cc958 100644 --- a/test/worldmap_blocks.gd +++ b/test/worldmap_blocks.gd @@ -1,7 +1,10 @@ extends Node2D -var worldmap_blocks = [] +var tileset_tex := TextureRect.new() +var worldmaps := [] +var block_images := [] +var block_textures := [] var block_labels = [] - +var worldmap_shader_mat := preload('res://worldmap_palette_mat.tres') func bin2str(bin: int) -> String: var string := '' @@ -9,48 +12,73 @@ func bin2str(bin: int) -> String: if i == 4: string += ' ' if ((bin >> 7-i) & 0x01) != 0: - string += '1' + string += ',' #'1' else: - string += '0' + string += '.' #'0' return string -# Called when the node enters the scene tree for the first time. + func _ready() -> void: - var _scale := 5 - var _size = Vector2.ONE * 16 * _scale + var blockmap = PoolByteArray() + for i in 0xC0: + blockmap.append(i) + for i in 0x40: + blockmap.append(i) for i in 3: - worldmap_blocks.append(TextureRect.new()) - worldmap_blocks[-1].texture = SpriteLoader.worldmap_block_atlas_textures[i] - # worldmap_blocks[-1].texture = SpriteLoader.worldmap_tile_atlas_textures[i] - worldmap_blocks[-1].material = SpriteLoader.shader_material.duplicate() - worldmap_blocks[-1].material.set_shader_param('palette', SpriteLoader.worldmap_palette_textures[i]) - worldmap_blocks[-1].rect_scale *= _scale - var pos = Vector2(i * 256 * _scale, 50) - worldmap_blocks[-1].rect_position = pos - add_child(worldmap_blocks[-1]) - # x0 += 4 * _scale - # y0 += 12 * _scale - for block in 0xC0: - var label = Label.new() - var p = MapLoader.worldmap_block_properties[i][block] - label.text = '%s\n%s\n%s' % [bin2str(p&0xff), bin2str((p>>8)&0xff), bin2str(p>>16)] - label.add_color_override('font_color_shadow', Color.black) - label.add_constant_override('shadow_as_outline', true) - label.rect_position = pos + (Vector2(block%16, block/16) * _size) - label.rect_size = _size - label.align = Label.ALIGN_CENTER - label.valign = Label.VALIGN_CENTER - add_child(label) - block_labels.append(label) + worldmaps.append(MapLoader.WorldMap.new(16, 16)) + worldmaps[i].block_tile_ids = SpriteLoader.worldmap_block_tile_ids[i] + worldmaps[i].blockmap = blockmap + block_images.append(worldmaps[i].make_tile_map()) + block_textures.append(SpriteLoader.texture_from_image(block_images[i])) + + self.tileset_tex.show_behind_parent = true + self.tileset_tex.material = worldmap_shader_mat.duplicate() + self.tileset_tex.material.set_shader_param('enable_waterfall_scroll', 0) + self.tileset_tex.material.set_shader_param('enable_sea_scroll', 0) + self.tileset_tex.material.set_shader_param('tilemap_width', 32) + self.tileset_tex.material.set_shader_param('uv_scale', 32) + var _scale := 8 + var _size = Vector2.ONE * 2 * _scale + self.tileset_tex.rect_scale *= _scale + # x0 += 4 * _scale + # y0 += 12 * _scale + var pos = Vector2(0, 48) + self.tileset_tex.rect_position = pos + add_child(tileset_tex) + + for block in 0xC0: + var label = Label.new() + var p = 0 #MapLoader.worldmap_block_properties[i][block] + label.text = '%s\n%s\n%s' % [bin2str(p&0xff), bin2str((p>>8)&0xff), bin2str(p>>16)] + label.add_color_override('font_color_shadow', Color.black) + label.add_constant_override('shadow_as_outline', true) + label.rect_position = pos + (Vector2(block%16, block/16) * _size) + label.rect_size = _size + label.align = Label.ALIGN_LEFT + label.valign = Label.VALIGN_TOP + add_child(label) + block_labels.append(label) $BitSelector.connect('value_changed', self, '_update_block_mask') + $tileset_sel.connect('value_changed', self, '_update_tileset') + self._update_tileset(0) func _update_block_mask(value: int): var mask = 0xFFFFFF if (value<0) else (1<>8)&0xff), bin2str(mask>>16)] for i in block_labels.size(): - var p = MapLoader.worldmap_block_properties[i/0xC0][i%0xC0] + var p = 0 #MapLoader.worldmap_block_properties[i/0xC0][i%0xC0] if (p & mask) > 0: block_labels[i].add_color_override('font_color', Color.white) else: block_labels[i].add_color_override('font_color', Color.black) + +func _update_tileset(i: int): + self.tileset_tex.texture = block_textures[i] + self.tileset_tex.material.set_shader_param('palette', SpriteLoader.worldmap_palette_textures[i]) + self.tileset_tex.material.set_shader_param('tile_atlas', SpriteLoader.worldmap_tile_atlas_textures[i]) + var map = RomLoader.snes_data.worldmap_block_properties[i] + var fmt = '.,' + for b in 0xC0: + var p = map[b] + block_labels[b].text = fmt[p.isnt_landable_chocobo] + fmt[p.isnt_landable_black_chocobo] + fmt[p.isnt_landable_hiryuu] + fmt[p.isnt_landable_airship] diff --git a/test/worldmap_blocks.tscn b/test/worldmap_blocks.tscn index f559825..3f0d343 100644 --- a/test/worldmap_blocks.tscn +++ b/test/worldmap_blocks.tscn @@ -21,3 +21,10 @@ margin_bottom = 48.0 text = "1111 1111 1111" + +[node name="tileset_sel" type="SpinBox" parent="."] +margin_left = 300.0 +margin_right = 330.0 +margin_bottom = 22.0 +rect_min_size = Vector2( 30, 0 ) +max_value = 2.0