Use our save struct DSL for some ROM things
This commit is contained in:
parent
c0dff664eb
commit
877c5d90e4
|
@ -1,23 +1,24 @@
|
|||
Label SNES PSX_file PSX_offset format Comment
|
||||
locations_bg_palettes 0x03BB00 /nar/ff5_binx.bin 0x03BF80
|
||||
worldmap_blocks 0x0FF0C0 /nar/ff5_binx.bin 0x040300
|
||||
worldmap_tile_palettes 0x0FF9C0 /nar/ff5_bin3.bin 0x03FB00
|
||||
worldmap_palettes 0x0FFCC0 /nar/ff5_binx.bin 0x040000
|
||||
worldmap_tiles 0x1B8000 /nar/ff5_bin3.bin 0x039B00
|
||||
character_battle_sprite_tiles 0x120000 /mnu/men_bin.eng 0x010200
|
||||
character_battle_sprite_palettes 0x14A3C0 /btl/ff5_btl.bin 0x0273C0 Also /mnu/men_bin.eng:0x03A5C0
|
||||
character_battle_sprite_layouts 0x14B997 /btl/ff5_btl.bin 0x028997
|
||||
character_battle_sprite_disabled_palette 0x00F867 /mnu/memsave.bin 0x000034
|
||||
character_battle_sprite_stone_palette 0x00F807 N/A N/A Also 0x199835
|
||||
tiles_fist 0x11D710 /btl/ff5_btl.bin 0x021D10 Also /mnu/men_bin.eng:0x00D910
|
||||
tbl_weapons 0x110000 length 0x600
|
||||
tbl_armors 0x110600 length 0x480
|
||||
tbl_items 0x110A80 length 0x100
|
||||
tbl_magic 0x110B80 length 0x800
|
||||
tbl_equip_types 0x112480 64 of ... length 0x100 - Item Equipment type definitions (64x4 bytes, 2B weapon, 2B armor)
|
||||
tbl_armors_elem_def 0x112580 64 of ... length 0x140 - Item Armor Element defense 64x(5B - absorb, evade, immunity, half, weakness)
|
||||
tbl_armors_status 0x1126C0 64 of ... length 0x1C0 - Item Armor Status defense 64x(7B - 4B Initial, 3B Immune)
|
||||
tbl_item_magic_prices 0x112A00 length 0x300
|
||||
locations_bg_palettes 0x03BB00 /nar/ff5_binx.bin 0x03BF80 43 of Palette128Of555
|
||||
worldmap_blocks 0x0FF0C0 /nar/ff5_binx.bin 0x040300 3 of 192 of 4 of u8
|
||||
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 Palette128Of555
|
||||
worldmap_tiles 0x1B8000 /nar/ff5_bin3.bin 0x039B00 3 of 256 of TileSNESMode7c Add the biases
|
||||
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
|
||||
character_battle_sprite_layouts 0x14B997 /btl/ff5_btl.bin 0x028997 11 of 6 of u8
|
||||
character_battle_sprite_disabled_palette 0x00F867 /mnu/memsave.bin 0x000034 Palette16Of555
|
||||
character_battle_sprite_stone_palette 0x00F807 N/A N/A Palette16Of555 Also 0x199835
|
||||
tiles_fist 0x11D710 /btl/ff5_btl.bin 0x021D10 TileSNES3bpp Also /mnu/men_bin.eng:0x00D910
|
||||
tbl_weapons 0x110000 128 of 12 of u8 length 0x600
|
||||
tbl_armors 0x110600 96 of 12 of u8 length 0x480
|
||||
tbl_items 0x110A80 32 of 8 of u8 length 0x100
|
||||
tbl_magic 0x110B80 256 of 8 of u8 length 0x800
|
||||
tbl_equip_types 0x112480 64 of 4 of u8 length 0x100 - Item Equipment type definitions (64x4 bytes, 2B weapon, 2B armor)
|
||||
tbl_armors_elem_def 0x112580 64 of 5 of u8 length 0x140 - Item Armor Element defense 64x(5B - absorb, evade, immunity, half, weakness)
|
||||
tbl_armors_status 0x1126C0 64 of 7 of u8 length 0x1C0 - Item Armor Status defense 64x(7B - 4B Initial, 3B Immune)
|
||||
tbl_prices_items 0x112A00 256 of ItemCost length 0x200
|
||||
tbl_prices_magic 0x112C00 128 of ItemCost length 0x100
|
||||
tbl_charlevels_exp 0x115000 99 of u24
|
||||
tbl_charlevels_hp_base 0x115129 99 of u16
|
||||
tbl_charlevels_mp_base 0x1151EF 99 of u16
|
||||
|
|
|
|
@ -1,5 +1,8 @@
|
|||
extends Node
|
||||
|
||||
const STRUCT := preload('res://scripts/struct.gd')
|
||||
const STRUCT_SNES := preload('res://scripts/loaders/snes/structs.gd')
|
||||
var structdefs := {}
|
||||
const loader_cd_image := preload('res://scripts/loaders/cd/image.gd')
|
||||
var psx_productcode_regex := RegEx.new()
|
||||
const psx_ff5_productcodes = [
|
||||
|
@ -13,15 +16,36 @@ var ROM_filename := 'FF5_SCC_WepTweaks_Inus_Dash.sfc' # 'Final Fantasy V (Japan
|
|||
var GBA_filename := '2564 - Final Fantasy V Advance (U)(Independent).gba'
|
||||
|
||||
var rom_snes := File.new()
|
||||
var snes_data := {}
|
||||
var thread := Thread.new()
|
||||
|
||||
func load_snes_rom(filename: String):
|
||||
var error := rom_snes.open(filename, File.READ)
|
||||
if error == OK:
|
||||
# Copy entire SNES ROM to a buffer for StreamPeerBuffer usage.
|
||||
# Unfortunately, the File API is different and slightly worse than the StreamPeer API.
|
||||
var bytes := rom_snes.get_buffer(rom_snes.get_len())
|
||||
var buffer = StreamPeerBuffer.new()
|
||||
buffer.data_array = bytes
|
||||
SpriteLoader.load_snes_rom(rom_snes)
|
||||
MapLoader.load_snes_rom(rom_snes)
|
||||
StringLoader.load_snes_rom(rom_snes, true)
|
||||
# Don't do this concurrently, avoid file pointer conflicts
|
||||
var _thread_error = thread.start(SoundLoader, 'parse_rom', rom_snes)
|
||||
# Can concurrently work with the preloaded StreamPeerBuffer though
|
||||
for key in Common.SNES_PSX_addresses:
|
||||
var d = Common.SNES_PSX_addresses[key]
|
||||
if d.format:
|
||||
var s: STRUCT.StructType
|
||||
if d.format in structdefs:
|
||||
s = structdefs[d.format]
|
||||
else:
|
||||
s = STRUCT.get_structarraytype(d.format, structdefs)
|
||||
structdefs[d.format] = s
|
||||
if not s:
|
||||
assert(false, 'Invalid StructType: "%s"' % d.format)
|
||||
buffer.seek(d.SNES)
|
||||
snes_data[key] = s.get_value(buffer, [0, 0])
|
||||
|
||||
func load_psx_folder(_dirname: String):
|
||||
pass
|
||||
|
@ -42,6 +66,9 @@ func load_psx_image(filename: String):
|
|||
|
||||
|
||||
func _ready():
|
||||
structdefs.merge(STRUCT.get_base_structarraytypes())
|
||||
structdefs.merge(STRUCT_SNES.get_structtypes())
|
||||
STRUCT.parse_struct_definitions_from_tsv_filename('res://data/SNES_save.tsv', structdefs)
|
||||
var _error := psx_productcode_regex.compile('(S[A-Z]{3}_\\d{3}\\.\\d{2});(\\d)')
|
||||
load_snes_rom(ROM_filename)
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ func snes_load_worldmap(rom: File):
|
|||
worldmap_palette_textures.append(texture_from_image(image))
|
||||
|
||||
var tile_palettes = []
|
||||
rom.seek(Common.SNES_PSX_addresses['worldmap_tile_palettes']['SNES'] + (world_ts*0x100))
|
||||
rom.seek(Common.SNES_PSX_addresses['worldmap_tiles.bias']['SNES'] + (world_ts*0x100))
|
||||
for pal in 256:
|
||||
tile_palettes.append(rom.get_8())
|
||||
|
||||
|
@ -264,7 +264,7 @@ func snes_load_map_sprites(rom: File):
|
|||
func load_snes_rom(rom: File):
|
||||
snes_load_battle_sprites(rom)
|
||||
snes_load_worldmap(rom)
|
||||
snes_load_map_sprites(rom)
|
||||
# snes_load_map_sprites(rom)
|
||||
|
||||
|
||||
const gba_marker := 'FINAL FANTASY V ADVANCE SYGMAB'
|
||||
|
|
|
@ -73,3 +73,11 @@ static func get_tile(rom: File, offset: int, length: int) -> Image:
|
|||
return _2plane_to_tile(data)
|
||||
_:
|
||||
return _1plane_to_tile(data)
|
||||
|
||||
static func bgr555_to_color(short: int) -> Color:
|
||||
var color = Color()
|
||||
color.a = 1
|
||||
color.r = ((short & 0x1F) / 31.0)
|
||||
color.g = (((short >> 5) & 0x1F) / 31.0)
|
||||
color.b = (((short >> 10) & 0x1F) / 31.0)
|
||||
return color
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
#warning-ignore-all:shadowed_variable
|
||||
#warning-ignore-all:unused_argument
|
||||
const STRUCT := preload('res://scripts/struct.gd')
|
||||
const GRAPHICS := preload('res://scripts/loaders/snes/graphics.gd')
|
||||
|
||||
class TileSNESMode7 extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS.mode7_to_tile(buffer.get_data(64))
|
||||
|
||||
class TileSNESMode7c extends STRUCT.StructType:
|
||||
# Note that this will give a palette offset of 0, you will need to postprocess the values.
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS.mode7_compressed_to_tile(buffer.get_data(32)[1])
|
||||
|
||||
class TileSNES4bpp extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS._4plane_to_tile(buffer.get_data(32)[1])
|
||||
|
||||
class TileSNES3bpp extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS._3plane_to_tile(buffer.get_data(24)[1])
|
||||
|
||||
class TileSNES2bpp extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS._2plane_to_tile(buffer.get_data(16)[1])
|
||||
|
||||
class TileSNES1bpp extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS._1plane_to_tile(buffer.get_data(8)[1])
|
||||
|
||||
class ColorBGR555 extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return GRAPHICS.bgr555_to_color(buffer.get_u16())
|
||||
|
||||
class PaletteOf555 extends STRUCT.StructType:
|
||||
var length: int = 16
|
||||
func _init(length: int):
|
||||
self.length = length
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
var array := PoolColorArray()
|
||||
for i in self.length:
|
||||
array.append(GRAPHICS.bgr555_to_color(buffer.get_u16()))
|
||||
return array
|
||||
|
||||
class ItemCost extends STRUCT.StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
var b0 := buffer.get_u8()
|
||||
var mantissa := buffer.get_u8()
|
||||
var exponent := b0 & 0x3F
|
||||
var is_sellable := (b0 & 0x80) == 0
|
||||
var is_sellprice_5gil := (b0 & 0x40) == 0x40
|
||||
var buy_price := mantissa * int(pow(10, exponent))
|
||||
var sell_price := -1 if not is_sellable else (5 if is_sellprice_5gil else buy_price/2)
|
||||
return {'buy_price': buy_price, 'sell_price': sell_price}
|
||||
|
||||
static func get_structtypes() -> Dictionary:
|
||||
return {
|
||||
'TileSNESMode7': TileSNESMode7.new(),
|
||||
'TileSNESMode7c': TileSNESMode7c.new(),
|
||||
'TileSNES4bpp': TileSNES4bpp.new(),
|
||||
'TileSNES3bpp': TileSNES3bpp.new(),
|
||||
'TileSNES2bpp': TileSNES2bpp.new(),
|
||||
'TileSNES1bpp': TileSNES1bpp.new(),
|
||||
'ColorBGR555': ColorBGR555.new(),
|
||||
'Palette16Of555': PaletteOf555.new(16),
|
||||
'Palette128Of555': PaletteOf555.new(128),
|
||||
'ItemCost': ItemCost.new(),
|
||||
}
|
|
@ -4,9 +4,9 @@
|
|||
# array is used for reference semantics as get and put operations may mutate it
|
||||
class StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
return
|
||||
assert(false, 'Deserialization not implemented')
|
||||
func put_value(buffer: StreamPeer, value, leftover_bits: Array):
|
||||
return
|
||||
assert(false, 'Serialization not implemented')
|
||||
|
||||
class U8 extends StructType:
|
||||
func get_value(buffer: StreamPeer, leftover_bits: Array):
|
||||
|
|
Loading…
Reference in New Issue