Switch some File API to StreamPeerBuffer
This commit is contained in:
parent
009e6933ef
commit
ed5c0f20b9
|
@ -96,13 +96,13 @@ var worldmaps = [WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new(),
|
|||
|
||||
var worldmap_block_properties = []
|
||||
var worldmap_block_pathings = []
|
||||
func load_worldmap_block_properties(rom: File):
|
||||
rom.seek(0x0FEA00)
|
||||
func load_worldmap_block_properties(buffer: StreamPeerBuffer):
|
||||
buffer.seek(0x0FEA00)
|
||||
for world_ts in 3:
|
||||
var ts_properties = PoolIntArray()
|
||||
var ts_pathings = PoolIntArray()
|
||||
for block in 0xC0:
|
||||
var properties := rom.get_16() + (rom.get_8() << 16)
|
||||
var properties := buffer.get_u16() + (buffer.get_u8() << 16)
|
||||
ts_properties.append(properties)
|
||||
var pathings := 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
|
||||
|
@ -116,14 +116,14 @@ func load_worldmap_block_properties(rom: File):
|
|||
worldmaps[4].block_pathing = worldmap_block_pathings[2]
|
||||
|
||||
|
||||
func load_worldmaps(rom: File):
|
||||
func load_worldmaps(buffer: StreamPeerBuffer):
|
||||
var chunk_addresses = PoolIntArray()
|
||||
chunk_addresses.resize(0x500) # 5 worldmaps * 256 chunks
|
||||
rom.seek(0x0FE000)
|
||||
buffer.seek(0x0FE000)
|
||||
for id in range(0, 0x434):
|
||||
chunk_addresses[id] = rom.get_16() + 0x070000
|
||||
chunk_addresses[id] = buffer.get_u16() + 0x070000
|
||||
for id in range(0x434, 0x500):
|
||||
chunk_addresses[id] = rom.get_16() + 0x080000
|
||||
chunk_addresses[id] = buffer.get_u16() + 0x080000
|
||||
|
||||
for worldmap_id in 5: # Bartz World, Galuf World, Combined World, Underwater Galuf World, Underwater Combined World
|
||||
# Worldmap chunks have a basic compression.
|
||||
|
@ -132,14 +132,14 @@ func load_worldmaps(rom: File):
|
|||
var blockmap = PoolByteArray()
|
||||
# blockmap.resize(WorldMap.block_height * WorldMap.block_width) # Try this later if performance is a problem
|
||||
for chunk_id in range(worldmap_id*0x100, (worldmap_id+1)*0x100):
|
||||
rom.seek(chunk_addresses[chunk_id])
|
||||
buffer.seek(chunk_addresses[chunk_id])
|
||||
var chunk_size := 0
|
||||
while chunk_size < 256:
|
||||
# var b: int = (blockmap.size() % 16) + (16 * (chunk_id % 12)); # For debugging the map shader against blocks
|
||||
var b := rom.get_8()
|
||||
var b := buffer.get_u8()
|
||||
if b >= 0xC0: # RLE
|
||||
var count := b-0xBF
|
||||
var block = rom.get_8()
|
||||
var block = buffer.get_u8()
|
||||
for i in count:
|
||||
blockmap.append(block)
|
||||
chunk_size += count
|
||||
|
@ -161,6 +161,6 @@ func update_worldmap_block_tile_ids(worldmap_block_tile_ids: Array):
|
|||
worldmaps[3].block_tile_ids = worldmap_block_tile_ids[2]
|
||||
worldmaps[4].block_tile_ids = worldmap_block_tile_ids[2]
|
||||
|
||||
func load_snes_rom(rom: File):
|
||||
load_worldmap_block_properties(rom)
|
||||
load_worldmaps(rom)
|
||||
func load_snes_rom(buffer: StreamPeerBuffer):
|
||||
load_worldmap_block_properties(buffer)
|
||||
load_worldmaps(buffer)
|
||||
|
|
|
@ -20,6 +20,46 @@ var snes_data := {}
|
|||
var snes_bytes: PoolByteArray
|
||||
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_rom(filename: String):
|
||||
var error := rom_snes.open(filename, File.READ)
|
||||
if error == OK:
|
||||
|
@ -30,52 +70,16 @@ func load_snes_rom(filename: String):
|
|||
self.snes_bytes = bytes
|
||||
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 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 snes_data):
|
||||
snes_data[k0] = {k1: s.get_value(buffer, [0, 0])}
|
||||
else:
|
||||
snes_data[k0][k1] = s.get_value(buffer, [0, 0])
|
||||
else:
|
||||
snes_data[key] = s.get_value(buffer, [0, 0])
|
||||
snes_data['job_levels'] = []
|
||||
for job_id in 21:
|
||||
var ability_list_ptr: int = snes_data.ptrs_job_ability_lists[job_id]
|
||||
var num_abilities: int = snes_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})
|
||||
snes_data.job_levels.append(ability_list)
|
||||
|
||||
StringLoader.load_snes_rom(buffer, true)
|
||||
# Give this its own buffer, avoid file pointer conflicts
|
||||
var _thread_error = thread.start(SoundLoader, 'parse_rom', buffer.duplicate())
|
||||
self.snes_data = load_snes_structs(buffer)
|
||||
#print(snes_data.job_levels)
|
||||
SpriteLoader.load_from_structs(snes_data)
|
||||
SpriteLoader.load_enemy_battle_sprites(snes_data, buffer)
|
||||
SpriteLoader.load_battle_bgs(snes_data, buffer)
|
||||
MapLoader.load_snes_rom(rom_snes)
|
||||
SpriteLoader.load_from_structs(self.snes_data)
|
||||
SpriteLoader.load_enemy_battle_sprites(self.snes_data, buffer)
|
||||
SpriteLoader.load_battle_bgs(self.snes_data, buffer)
|
||||
MapLoader.load_snes_rom(buffer)
|
||||
|
||||
func load_psx_folder(_dirname: String):
|
||||
pass
|
||||
|
|
|
@ -21,9 +21,9 @@ var bgm_tracks = []
|
|||
var instrument_samples = []
|
||||
var sfx_samples = []
|
||||
|
||||
func read_rom_address(rom: File) -> int:
|
||||
func read_rom_address(buffer: StreamPeerBuffer) -> int:
|
||||
# Read a 3-byte little-endian address and wrap the bank to ROM space
|
||||
return rom.get_16() + ((rom.get_8() & 0x3F) << 16)
|
||||
return buffer.get_u16() + ((buffer.get_u8() & 0x3F) << 16)
|
||||
|
||||
const MAX_15B = 1 << 15
|
||||
const MAX_16B = 1 << 16
|
||||
|
@ -55,14 +55,14 @@ func clamp_short(i: int) -> int:
|
|||
return 0x7FFF
|
||||
return i
|
||||
|
||||
func make_sample(rom: File, size: int, sample_rate: int) -> AudioStreamSample:
|
||||
func make_sample(buffer: StreamPeerBuffer, size: int, sample_rate: int) -> AudioStreamSample:
|
||||
var audio := AudioStreamSample.new()
|
||||
audio.mix_rate = sample_rate
|
||||
audio.stereo = false
|
||||
audio.set_format(AudioStreamSample.FORMAT_16_BITS)
|
||||
|
||||
if (size % 9) != 0:
|
||||
print_debug('Oh no! An instrument sample has an invalid size of %d! at $%06X' % [size, rom.get_position()-2])
|
||||
print_debug('Oh no! An instrument sample has an invalid size of %d! at $%06X' % [size, buffer.get_position()-2])
|
||||
return audio
|
||||
var num_packets := size/9
|
||||
|
||||
|
@ -70,13 +70,13 @@ func make_sample(rom: File, size: int, sample_rate: int) -> AudioStreamSample:
|
|||
var i := 2
|
||||
for pkt in num_packets:
|
||||
# Decode a single 9byte BRR packet
|
||||
var header_byte := rom.get_8()
|
||||
var header_byte := buffer.get_u8()
|
||||
var exponent := header_byte >> 4
|
||||
var filter := (header_byte >> 2) & 0x03
|
||||
var loop := bool(header_byte & 0x02)
|
||||
var end := bool(header_byte & 0x01)
|
||||
for sample in 8:
|
||||
var b := rom.get_8()
|
||||
var b := buffer.get_u8()
|
||||
samples.append(process_sample(b >> 4, exponent))
|
||||
samples.append(process_sample(b & 0x0F, exponent))
|
||||
# Apply filter
|
||||
|
@ -103,75 +103,75 @@ func make_sample(rom: File, size: int, sample_rate: int) -> AudioStreamSample:
|
|||
audio.data = audio_data
|
||||
return audio
|
||||
|
||||
func get_inst_sample_data(rom: File, id: int) -> AudioStreamSample:
|
||||
rom.seek(INST_SR + (id*2))
|
||||
var tuning1 := rom.get_8()
|
||||
var tuning2 := rom.get_8()
|
||||
func get_inst_sample_data(buffer: StreamPeerBuffer, id: int) -> AudioStreamSample:
|
||||
buffer.seek(INST_SR + (id*2))
|
||||
var tuning1 := buffer.get_u8()
|
||||
var tuning2 := buffer.get_u8()
|
||||
var sample_rate := get_reference_pitch_samplerate(tuning1)
|
||||
|
||||
rom.seek(INST_LOOP + (id*2))
|
||||
var loop_start_packet := rom.get_16()/9 # Note that Instrument $1F Steel Guitar has a length of $088B but a loop point of $088D which is 243.22... packets. Luckily it doesn't matter.
|
||||
buffer.seek(INST_LOOP + (id*2))
|
||||
var loop_start_packet := buffer.get_u16()/9 # Note that Instrument $1F Steel Guitar has a length of $088B but a loop point of $088D which is 243.22... packets. Luckily it doesn't matter.
|
||||
|
||||
|
||||
var lookup_offset := INST_BRR_LOOKUP + (id*3)
|
||||
rom.seek(lookup_offset)
|
||||
var brr_offset := read_rom_address(rom)
|
||||
rom.seek(brr_offset)
|
||||
var size := rom.get_16()
|
||||
buffer.seek(lookup_offset)
|
||||
var brr_offset := read_rom_address(buffer)
|
||||
buffer.seek(brr_offset)
|
||||
var size := buffer.get_u16()
|
||||
var num_samples := (size/9)*16
|
||||
var audio := make_sample(rom, size, sample_rate)
|
||||
var audio := make_sample(buffer, size, sample_rate)
|
||||
audio.loop_mode = AudioStreamSample.LOOP_FORWARD
|
||||
audio.loop_begin = loop_start_packet * 16 # Each 9byte packet is 16 samples
|
||||
audio.loop_end = num_samples-1
|
||||
# print_debug('Loaded instrument #%02X with lookup offset $%06X, BRR data offset $%06X, length $%04X (%f packets, %d samples) and loop point %d samples' % [id, lookup_offset, brr_offset, size, size/9.0, num_samples, audio.loop_begin])
|
||||
return audio
|
||||
|
||||
func load_sfx_samples_data(rom: File):
|
||||
func load_sfx_samples_data(buffer: StreamPeerBuffer):
|
||||
var sample_rates = []
|
||||
rom.seek(SFX_SR)
|
||||
buffer.seek(SFX_SR)
|
||||
for i in SFX_NUM:
|
||||
var tuning1 := rom.get_8()
|
||||
var tuning2 := rom.get_8()
|
||||
var tuning1 := buffer.get_u8()
|
||||
var tuning2 := buffer.get_u8()
|
||||
sample_rates.append(get_reference_pitch_samplerate(tuning1))
|
||||
var brr_spc_addrs = []
|
||||
var brr_spc_loop_addrs = []
|
||||
rom.seek(SFX_BRR_SPC_TABLE)
|
||||
buffer.seek(SFX_BRR_SPC_TABLE)
|
||||
for i in SFX_NUM:
|
||||
brr_spc_addrs.append(rom.get_16())
|
||||
brr_spc_loop_addrs.append(rom.get_16())
|
||||
brr_spc_addrs.append(buffer.get_u16())
|
||||
brr_spc_loop_addrs.append(buffer.get_u16())
|
||||
var brr_spc_start = brr_spc_addrs[0]
|
||||
for i in SFX_NUM:
|
||||
brr_spc_addrs[i] += SFX_BRR_START - brr_spc_start
|
||||
for i in SFX_NUM:
|
||||
rom.seek(brr_spc_addrs[i])
|
||||
# print('Loading sfx sample #%X with BRR data offset $%06X' % [i, rom.get_position()])
|
||||
sfx_samples.append(make_sample(rom, 900, sample_rates[i])) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
||||
buffer.seek(brr_spc_addrs[i])
|
||||
# print('Loading sfx sample #%X with BRR data offset $%06X' % [i, buffer.get_position()])
|
||||
sfx_samples.append(make_sample(buffer, 900, sample_rates[i])) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
||||
emit_signal('audio_sfx_sample_loaded', i)
|
||||
# print('size of %d samples' % sfx_samples[i].data.size())
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func load_samples(rom: File):
|
||||
load_sfx_samples_data(rom)
|
||||
func load_samples(buffer: StreamPeerBuffer):
|
||||
load_sfx_samples_data(buffer)
|
||||
# For some reason, this is a bit slow currently. Might optimize later.
|
||||
for i in INST_NUM:
|
||||
instrument_samples.append(get_inst_sample_data(rom, i))
|
||||
instrument_samples.append(get_inst_sample_data(buffer, i))
|
||||
emit_signal('audio_inst_sample_loaded', i)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func get_song_data(rom: File, id: int):
|
||||
func get_song_data(buffer: StreamPeerBuffer, id: int):
|
||||
var lookup_offset := BGM_LOOKUP + (id*3)
|
||||
rom.seek(lookup_offset)
|
||||
var offset := read_rom_address(rom)
|
||||
buffer.seek(lookup_offset)
|
||||
var offset := read_rom_address(buffer)
|
||||
var bank := offset & 0xFF0000
|
||||
rom.seek(offset)
|
||||
var _block_size := rom.get_16() # Unused since we pull the individual tracks
|
||||
buffer.seek(offset)
|
||||
var _block_size := buffer.get_u16() # Unused since we pull the individual tracks
|
||||
var track_ptrs = []
|
||||
for i in 10:
|
||||
var a := bank + rom.get_16()
|
||||
var a := bank + buffer.get_u16()
|
||||
if a < offset:
|
||||
a += 0x010000 # Bank shift
|
||||
track_ptrs.append(a)
|
||||
|
@ -181,12 +181,12 @@ func get_song_data(rom: File, id: int):
|
|||
var tracks = []
|
||||
for i in range(1, track_ptrs.size()-1):
|
||||
var length = track_ptrs[i+1] - track_ptrs[i]
|
||||
tracks.append(rom.get_buffer(length))
|
||||
tracks.append(buffer.get_data(length)[0])
|
||||
return tracks
|
||||
|
||||
func load_bgms(rom: File):
|
||||
func load_bgms(buffer: StreamPeerBuffer):
|
||||
for i in BGM_NUM:
|
||||
bgm_tracks.append(get_song_data(rom, i))
|
||||
bgm_tracks.append(get_song_data(buffer, i))
|
||||
|
||||
|
||||
|
||||
|
@ -204,9 +204,9 @@ func play_sfx(id: int):
|
|||
player.stream = sfx_samples[id]
|
||||
player.play()
|
||||
|
||||
func parse_rom(rom: File):
|
||||
load_samples(rom)
|
||||
#load_bgms(rom)
|
||||
func parse_rom(buffer: StreamPeerBuffer):
|
||||
load_samples(buffer)
|
||||
#load_bgms(buffer)
|
||||
has_loaded_audio_samples = true
|
||||
emit_signal('audio_samples_loaded')
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func decode_array(array, glyph_table, trim_trailing_whitespace: bool = true) ->
|
|||
output.append(decode_string(s, glyph_table, trim_trailing_whitespace))
|
||||
return output
|
||||
|
||||
func load_snes_rom(rom: File, is_RPGe: bool = false) -> void:
|
||||
func load_snes_rom(buffer: StreamPeerBuffer, is_RPGe: bool = false) -> void:
|
||||
for block_name in SNES_block_addresses:
|
||||
var block: Dictionary = SNES_block_addresses[block_name]
|
||||
var glyph_table_small: PoolStringArray = glyph_tables.RPGe_small if is_RPGe else glyph_tables.SNES_small
|
||||
|
@ -41,7 +41,7 @@ func load_snes_rom(rom: File, is_RPGe: bool = false) -> void:
|
|||
var l1_address: int = block.address
|
||||
if (not is_RPGe) and block.snes_address:
|
||||
l1_address = block.snes_address
|
||||
rom.seek(l1_address)
|
||||
buffer.seek(l1_address)
|
||||
|
||||
var ptr_offset = block.rpge_ptr_offset if is_RPGe else block.snes_ptr_offset
|
||||
if ptr_offset is int:
|
||||
|
@ -49,33 +49,33 @@ func load_snes_rom(rom: File, is_RPGe: bool = false) -> void:
|
|||
match l1_width:
|
||||
1:
|
||||
for i in num_entries:
|
||||
ptrs.append((ptr_offset + rom.get_8()) & 0x3FFFFF) # Bank wrapping
|
||||
ptrs.append((ptr_offset + buffer.get_u8()) & 0x3FFFFF) # Bank wrapping
|
||||
2:
|
||||
for i in num_entries:
|
||||
ptrs.append((ptr_offset + rom.get_16()) & 0x3FFFFF) # Bank wrapping
|
||||
ptrs.append((ptr_offset + buffer.get_u16()) & 0x3FFFFF) # Bank wrapping
|
||||
3:
|
||||
for i in num_entries:
|
||||
ptrs.append((ptr_offset + rom.get_16() + (rom.get_8() << 16)) & 0x3FFFFF) # Bank wrapping
|
||||
ptrs.append((ptr_offset + buffer.get_u16() + (buffer.get_u8() << 16)) & 0x3FFFFF) # Bank wrapping
|
||||
_:
|
||||
assert(false, 'Indirect l1_width of %d is not possible' % l1_width)
|
||||
if block.null_terminated:
|
||||
for i in num_entries:
|
||||
rom.seek(ptrs[i])
|
||||
buffer.seek(ptrs[i])
|
||||
var bytes = PoolByteArray()
|
||||
while true:
|
||||
var b = rom.get_8()
|
||||
var b = buffer.get_u8()
|
||||
if b == 0:
|
||||
break
|
||||
bytes.append(b)
|
||||
raw_strings.append(bytes)
|
||||
else:
|
||||
for i in num_entries-1:
|
||||
rom.seek(ptrs[i])
|
||||
raw_strings.append(rom.get_buffer(ptrs[i+1] - ptrs[i]))
|
||||
buffer.seek(ptrs[i])
|
||||
raw_strings.append(buffer.get_data(ptrs[i+1] - ptrs[i])[0])
|
||||
else:
|
||||
# Get first level of data
|
||||
for i in num_entries:
|
||||
raw_strings.append(rom.get_buffer(l1_width))
|
||||
raw_strings.append(buffer.get_data(l1_width)[0])
|
||||
|
||||
# Decode
|
||||
if block.dialog:
|
||||
|
|
Loading…
Reference in New Issue