extends Node #warning-ignore-all:return_value_discarded signal rom_loaded 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 = [ 'SLUS_008.79', # US Anthology, both 1.0 and 1.1 'SCES_138.40', # EU/Aus Anthology 'SLPM_860.81', # JP 'SCPS_452.14', # JP original, untested ] var rom_snes := File.new() var snes_data := {} var snes_bytes: PoolByteArray var snes_buffer: StreamPeerBuffer var thread := Thread.new() func load_snes_structs(buffer: StreamPeerBuffer) -> Dictionary: var data := {} var rom_size := len(buffer.data_array) for key in Common.SNES_PSX_addresses: var d = Common.SNES_PSX_addresses[key] if d.format and (d.SNES < rom_size): # Don't try to grab RPGe bank E0-E7 stuff from a smaller JP ROM 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) if '.' in key: var keysplit: PoolStringArray = key.split('.', 1) var k0 := keysplit[0] var k1 = keysplit[1] if k1.is_valid_integer(): k1 = int(k1) if not (k0 in data): data[k0] = {k1: s.get_value(buffer, [0, 0])} else: data[k0][k1] = s.get_value(buffer, [0, 0]) else: data[key] = s.get_value(buffer, [0, 0]) data['job_levels'] = [] for job_id in 21: var ability_list_ptr: int = data.ptrs_job_ability_lists[job_id] var num_abilities: int = data.job_ability_counts[job_id] var ability_list := [] buffer.seek(0x110000 + ability_list_ptr) for i in num_abilities: var abp_requirement: int = buffer.get_u16() var ability_learned: int = buffer.get_u8() ability_list.append({'ABP': abp_requirement, 'ability': ability_learned}) data.job_levels.append(ability_list) return data func load_snes_audio_thread(data_and_buffer: Array): SoundLoader.parse_rom(data_and_buffer[0], data_and_buffer[1]) func load_snes_rom_from_bytes(bytes: PoolByteArray) -> void: if (len(bytes) % 1024) == 512: # Naive header strip bytes = bytes.subarray(512, -1) self.snes_bytes = bytes self.snes_buffer = StreamPeerBuffer.new() self.snes_buffer.data_array = bytes self.snes_data = load_snes_structs(self.snes_buffer) #print(snes_data.job_levels) # Give this its own buffer if threaded, avoid file pointer conflicts self.load_snes_audio_thread([self.snes_data, self.snes_buffer]) # var _thread_error = thread.start(self, 'load_snes_audio_thread', [self.snes_data, self.snes_buffer.duplicate()]) StringLoader.load_snes_rom(self.snes_buffer, true) SpriteLoader.load_from_structs(self.snes_data) SpriteLoader.load_enemy_battle_sprites(self.snes_data, self.snes_buffer) SpriteLoader.load_battle_bgs(self.snes_data, self.snes_buffer) MapLoader.load_snes_rom(self.snes_buffer) emit_signal('rom_loaded') func load_snes_rom(filename: String) -> void: 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 rom_size := rom_snes.get_len() var bytes := rom_snes.get_buffer(rom_size) load_snes_rom_from_bytes(bytes) func load_psx_folder(_dirname: String): pass func load_psx_image(filename: String): # While it would technically be possible to load everything with no temporary files, # It is more convenient to unpack the small files we care about to the user:// directory var rom_psx := File.new() var error := rom_psx.open(filename, File.READ) if error == OK: var cd := loader_cd_image.new(rom_psx) for key in cd.directory: var s = key.trim_prefix('./') var re_match := psx_productcode_regex.search(s) if re_match: print(re_match.get_string(0)) print(cd.directory) 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) STRUCT.parse_struct_definitions_from_tsv_filename('res://data/SNES_other.tsv', structdefs) var _error := psx_productcode_regex.compile('(S[A-Z]{3}_\\d{3}\\.\\d{2});(\\d)') # Debugging breakpoint pass func _exit_tree() -> void: thread.wait_to_finish()