Revisiting WorldMap pathing

Cleaning up some older debugging stuff
This commit is contained in:
Luke Hubmayer-Werner 2024-07-06 01:23:40 +09:30
parent ea3f3441f6
commit 038ab69a54
7 changed files with 114 additions and 172 deletions

View File

@ -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

Can't render this file because it has a wrong number of fields in line 53.

View File

@ -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?

Can't render this file because it has a wrong number of fields in line 43.

View File

@ -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')

View File

@ -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)

View File

@ -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):

View File

@ -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])
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 = MapLoader.worldmap_block_properties[i][block]
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_CENTER
label.valign = Label.VALIGN_CENTER
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<<value)
$BitSelectorMask.text = '%s\n%s\n%s' % [bin2str(mask&0xff), bin2str((mask>>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]

View File

@ -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