Rearrange structure
This commit is contained in:
parent
cdc8f96c52
commit
f19a8c0f50
14
Node2D.gd
14
Node2D.gd
|
@ -6,28 +6,28 @@ var sfx_buttons = []
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
Engine.set_target_fps(60)
|
Engine.set_target_fps(60)
|
||||||
var strips = len(load_sprites.strip_textures) # * 4 / 5
|
var strips = len(SpriteLoader.strip_textures) # * 4 / 5
|
||||||
#var strip_divide = strips * 2 / 5
|
#var strip_divide = strips * 2 / 5
|
||||||
var strip_divide = strips * 1 / 5
|
var strip_divide = strips * 1 / 5
|
||||||
for i in strips:
|
for i in strips:
|
||||||
PCs.append(PC.instance())
|
PCs.append(PC.instance())
|
||||||
#PCs[-1].set_position(Vector2((i%strip_divide)*16, (i/strip_divide)*24*11))
|
#PCs[-1].set_position(Vector2((i%strip_divide)*16, (i/strip_divide)*24*11))
|
||||||
PCs[-1].set_position(Vector2((i%strip_divide)*24, (i/strip_divide)*32))
|
PCs[-1].set_position(Vector2((i%strip_divide)*24, (i/strip_divide)*32))
|
||||||
PCs[-1].material.set_shader_param('palette', load_sprites.character_battle_sprite_palette_textures[i])
|
PCs[-1].material.set_shader_param('palette', SpriteLoader.character_battle_sprite_palette_textures[i])
|
||||||
PCs[-1].texture = load_sprites.strip_textures[i]
|
PCs[-1].texture = SpriteLoader.strip_textures[i]
|
||||||
|
|
||||||
add_child(PCs[-1])
|
add_child(PCs[-1])
|
||||||
# PCs.append(PC.instance())
|
# PCs.append(PC.instance())
|
||||||
# PCs[-1].set_position(Vector2(0, 2*24*11))
|
# PCs[-1].set_position(Vector2(0, 2*24*11))
|
||||||
# PCs[-1].material.set_shader_param('palette', load_sprites.character_battle_sprite_palette_textures[45])
|
# PCs[-1].material.set_shader_param('palette', SpriteLoader.character_battle_sprite_palette_textures[45])
|
||||||
# PCs[-1].texture = load_sprites.weapon_textures['Fist']
|
# PCs[-1].texture = SpriteLoader.weapon_textures['Fist']
|
||||||
# add_child(PCs[-1])
|
# add_child(PCs[-1])
|
||||||
|
|
||||||
for i in SoundLoader.INST_NUM:
|
for i in SoundLoader.INST_NUM:
|
||||||
var btn = Button.new()
|
var btn = Button.new()
|
||||||
btn.text = 'Play #%02X' % i
|
btn.text = 'Play #%02X' % i
|
||||||
btn.align = Button.ALIGN_CENTER
|
btn.align = Button.ALIGN_CENTER
|
||||||
btn.set_position(Vector2((i%8)*40, 200 + (i/8)*16))
|
btn.set_position(Vector2((i%8)*36, 200 + (i/8)*12))
|
||||||
btn.set_scale(Vector2(0.5, 0.5))
|
btn.set_scale(Vector2(0.5, 0.5))
|
||||||
add_child(btn)
|
add_child(btn)
|
||||||
btn.connect('pressed', SoundLoader, 'play_sample', [i])
|
btn.connect('pressed', SoundLoader, 'play_sample', [i])
|
||||||
|
@ -36,7 +36,7 @@ func _ready():
|
||||||
var btn = Button.new()
|
var btn = Button.new()
|
||||||
btn.text = 'SFX #%02X' % i
|
btn.text = 'SFX #%02X' % i
|
||||||
btn.align = Button.ALIGN_CENTER
|
btn.align = Button.ALIGN_CENTER
|
||||||
btn.set_position(Vector2((i%8)*40, 290 + (i/8)*16))
|
btn.set_position(Vector2((i%8)*36, 264 + (i/8)*12))
|
||||||
btn.set_scale(Vector2(0.5, 0.5))
|
btn.set_scale(Vector2(0.5, 0.5))
|
||||||
add_child(btn)
|
add_child(btn)
|
||||||
btn.connect('pressed', SoundLoader, 'play_sfx', [i])
|
btn.connect('pressed', SoundLoader, 'play_sfx', [i])
|
||||||
|
|
2
PC.gd
2
PC.gd
|
@ -42,7 +42,7 @@ const Animation_Frames = {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _init():
|
func _init():
|
||||||
material = load_sprites.shader_material.duplicate()
|
material = SpriteLoader.shader_material.duplicate()
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
func _process(_delta):
|
func _process(_delta):
|
||||||
|
|
|
@ -21,8 +21,10 @@ config/icon="res://icon.png"
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
globals="*res://globals.gd"
|
globals="*res://globals.gd"
|
||||||
SoundLoader="*res://scripts/sound_loader.gd"
|
CommonGBA="*res://scripts/loaders/common_gba.gd"
|
||||||
load_sprites="*res://scripts/load_sprites.gd"
|
SoundLoader="*res://scripts/loaders/sound_loader.gd"
|
||||||
|
SpriteLoader="*res://scripts/loaders/sprite_loader.gd"
|
||||||
|
RomLoader="*res://scripts/loaders/rom_loader.gd"
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func ByteArray(size: int) -> PoolByteArray:
|
||||||
|
var arr := PoolByteArray()
|
||||||
|
arr.resize(size)
|
||||||
|
return arr
|
||||||
|
|
||||||
|
func LZ77_decompress(rom: File, address: int) -> PoolByteArray:
|
||||||
|
rom.seek(address)
|
||||||
|
var header := rom.get_32()
|
||||||
|
assert (header & 0x10 == 0x10)
|
||||||
|
var length := header >> 8
|
||||||
|
var output := ByteArray(length)
|
||||||
|
var ptr := 0
|
||||||
|
while ptr < length:
|
||||||
|
var bitmap := rom.get_8()
|
||||||
|
for i in range(8):
|
||||||
|
if (bitmap >> (7-i)) & 1:
|
||||||
|
# Buffer substitution
|
||||||
|
var h1 := rom.get_8()
|
||||||
|
var h2 := rom.get_8()
|
||||||
|
var copy_len := 3 + (h1 >> 4)
|
||||||
|
var copy_ptr := ptr - 1 - (((h1 & 0x0F)<<8) + h2)
|
||||||
|
for j in range(copy_len):
|
||||||
|
output[ptr] = output[copy_ptr]
|
||||||
|
copy_ptr += 1
|
||||||
|
ptr += 1
|
||||||
|
if ptr >= length:
|
||||||
|
return output
|
||||||
|
else:
|
||||||
|
# Literal byte
|
||||||
|
output[ptr] = rom.get_8()
|
||||||
|
ptr += 1
|
||||||
|
if ptr >= length:
|
||||||
|
return output
|
||||||
|
return output
|
|
@ -0,0 +1,16 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
var ROM_filename := 'FF5_SCC_WepTweaks_Inus_Dash.sfc' # 'Final Fantasy V (Japan).sfc'
|
||||||
|
var GBA_filename := '2564 - Final Fantasy V Advance (U)(Independent).gba'
|
||||||
|
|
||||||
|
var rom_snes := File.new()
|
||||||
|
|
||||||
|
func load_snes_rom(filename: String):
|
||||||
|
var error := rom_snes.open(filename, File.READ)
|
||||||
|
if error == OK:
|
||||||
|
SoundLoader.parse_rom(rom_snes)
|
||||||
|
SpriteLoader.load_snes_rom(rom_snes)
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
load_snes_rom(ROM_filename)
|
||||||
|
|
|
@ -1,8 +1,26 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
|
const BGM_NUM := 70
|
||||||
|
const BGM_LOOKUP := 0x043B97
|
||||||
|
const INST_NUM := 35
|
||||||
|
const INST_BRR_LOOKUP := 0x043C6F
|
||||||
|
const INST_SR := 0x043CD8
|
||||||
|
const INST_LOOP := 0x043D1E
|
||||||
|
const INST_ADSR := 0x043D64
|
||||||
|
const SFX_NUM := 8
|
||||||
|
const SFX_BRR_START := 0x041E3F
|
||||||
|
const SFX_ADSR := 0x041F71
|
||||||
|
const SFX_SR := 0x041F83
|
||||||
|
var bgm_tracks = []
|
||||||
|
var instrument_samples = []
|
||||||
|
var sfx_samples = []
|
||||||
|
|
||||||
|
func read_rom_address(rom: File) -> int:
|
||||||
|
# Read a 3-byte little-endian address and wrap the bank to ROM space
|
||||||
|
return rom.get_16() + ((rom.get_8() & 0x3F) << 16)
|
||||||
|
|
||||||
const MAX_15B = 1 << 15
|
const MAX_15B = 1 << 15
|
||||||
const MAX_16B = 1 << 16
|
const MAX_16B = 1 << 16
|
||||||
|
|
||||||
func unsigned16_to_signed(unsigned):
|
func unsigned16_to_signed(unsigned):
|
||||||
return (unsigned + MAX_15B) % MAX_16B - MAX_15B
|
return (unsigned + MAX_15B) % MAX_16B - MAX_15B
|
||||||
|
|
||||||
|
@ -11,7 +29,8 @@ func process_sample(mantissa: int, exponent: int) -> int:
|
||||||
# Sign-extend
|
# Sign-extend
|
||||||
if mantissa >= 8:
|
if mantissa >= 8:
|
||||||
mantissa |= 0xFFF0
|
mantissa |= 0xFFF0
|
||||||
exponent = min(exponent, 12)
|
if exponent > 12:
|
||||||
|
exponent = 12
|
||||||
var unsigned = (mantissa << exponent) & 0xFFFF
|
var unsigned = (mantissa << exponent) & 0xFFFF
|
||||||
return unsigned16_to_signed(unsigned)
|
return unsigned16_to_signed(unsigned)
|
||||||
|
|
||||||
|
@ -65,30 +84,18 @@ func make_sample(rom: File, sample_rate: int) -> AudioStreamSample:
|
||||||
var audio_data = PoolByteArray()
|
var audio_data = PoolByteArray()
|
||||||
for i in range(2, samples.size()):
|
for i in range(2, samples.size()):
|
||||||
var b = samples[i]
|
var b = samples[i]
|
||||||
audio_data.push_back(b & 0xFF)
|
audio_data.append(b & 0xFF)
|
||||||
audio_data.push_back(b >> 8)
|
audio_data.append(b >> 8)
|
||||||
audio.data = audio_data
|
audio.data = audio_data
|
||||||
return audio
|
return audio
|
||||||
|
|
||||||
const INST_NUM := 35
|
|
||||||
const INST_BRR_LOOKUP := 0x043C6F
|
|
||||||
const INST_SR := 0x043CD8
|
|
||||||
const INST_LOOP := 0x043D1E
|
|
||||||
const INST_ADSR := 0x043D64
|
|
||||||
const SFX_NUM := 8
|
|
||||||
const SFX_BRR_START := 0x041E3F
|
|
||||||
const SFX_ADSR := 0x041F71
|
|
||||||
const SFX_SR := 0x041F83
|
|
||||||
var instrument_samples = []
|
|
||||||
var sfx_samples = []
|
|
||||||
|
|
||||||
func get_inst_sample_data(rom: File, id: int) -> AudioStreamSample:
|
func get_inst_sample_data(rom: File, id: int) -> AudioStreamSample:
|
||||||
rom.seek(INST_SR + (id*2))
|
rom.seek(INST_SR + (id*2))
|
||||||
var sample_rate := (rom.get_16() * 32000)/4096
|
var sample_rate := (rom.get_16() * 32000)/4096
|
||||||
|
|
||||||
var lookup_offset := INST_BRR_LOOKUP + (id*3)
|
var lookup_offset := INST_BRR_LOOKUP + (id*3)
|
||||||
rom.seek(lookup_offset)
|
rom.seek(lookup_offset)
|
||||||
var brr_offset := rom.get_16() + ((rom.get_8() & 0x3F) << 16)
|
var brr_offset := read_rom_address(rom)
|
||||||
rom.seek(brr_offset)
|
rom.seek(brr_offset)
|
||||||
var sample := make_sample(rom, sample_rate)
|
var sample := make_sample(rom, sample_rate)
|
||||||
#print_debug('Loaded sample instrument #%02X with lookup offset $%06X, BRR data offset $%06X and length $%04X (%f packets)' % [id, lookup_offset, brr_offset, size, size/9.0])
|
#print_debug('Loaded sample instrument #%02X with lookup offset $%06X, BRR data offset $%06X and length $%04X (%f packets)' % [id, lookup_offset, brr_offset, size, size/9.0])
|
||||||
|
@ -112,6 +119,41 @@ func load_samples(rom: File):
|
||||||
instrument_samples.append(get_inst_sample_data(rom, i))
|
instrument_samples.append(get_inst_sample_data(rom, i))
|
||||||
load_sfx_samples_data(rom)
|
load_sfx_samples_data(rom)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func get_song_data(rom: File, id: int):
|
||||||
|
var lookup_offset := BGM_LOOKUP + (id*3)
|
||||||
|
rom.seek(lookup_offset)
|
||||||
|
var offset := read_rom_address(rom)
|
||||||
|
var bank := offset & 0xFF0000
|
||||||
|
rom.seek(offset)
|
||||||
|
var _block_size := rom.get_16() # Unused since we pull the individual tracks
|
||||||
|
var track_ptrs = []
|
||||||
|
for i in 10:
|
||||||
|
var a := bank + rom.get_16()
|
||||||
|
if a < offset:
|
||||||
|
a += 0x010000 # Bank shift
|
||||||
|
track_ptrs.append(a)
|
||||||
|
|
||||||
|
if track_ptrs[0] != track_ptrs[1]:
|
||||||
|
print('Master is not channel 1, interesting', track_ptrs)
|
||||||
|
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))
|
||||||
|
return tracks
|
||||||
|
|
||||||
|
func load_bgms(rom: File):
|
||||||
|
for i in BGM_NUM:
|
||||||
|
bgm_tracks.append(get_song_data(rom, i))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var player := AudioStreamPlayer.new() # Make one for each channel, later
|
var player := AudioStreamPlayer.new() # Make one for each channel, later
|
||||||
func play_sample(id: int):
|
func play_sample(id: int):
|
||||||
print('Playing sample #%02X' % id)
|
print('Playing sample #%02X' % id)
|
||||||
|
@ -123,6 +165,10 @@ func play_sfx(id: int):
|
||||||
player.stream = sfx_samples[id]
|
player.stream = sfx_samples[id]
|
||||||
player.play()
|
player.play()
|
||||||
|
|
||||||
|
func parse_rom(rom: File):
|
||||||
|
load_samples(rom)
|
||||||
|
load_bgms(rom)
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
add_child(player)
|
add_child(player)
|
||||||
|
|
|
@ -2,7 +2,6 @@ extends Node
|
||||||
|
|
||||||
var shader_material = load('res://palette_mat.tres')
|
var shader_material = load('res://palette_mat.tres')
|
||||||
|
|
||||||
var ROM_filename := 'FF5_SCC_WepTweaks_Inus_Dash.sfc' # 'Final Fantasy V (Japan).sfc'
|
|
||||||
const offset_Character_Battle_Sprite_Tiles: int = 0x120000
|
const offset_Character_Battle_Sprite_Tiles: int = 0x120000
|
||||||
const offset_Character_Battle_Sprite_Palettes: int = 0x14A3C0
|
const offset_Character_Battle_Sprite_Palettes: int = 0x14A3C0
|
||||||
const offset_Character_Battle_Sprite_Layouts: int = 0x14B997
|
const offset_Character_Battle_Sprite_Layouts: int = 0x14B997
|
||||||
|
@ -20,6 +19,11 @@ var character_battle_sprite_palette_disabled_texture: ImageTexture
|
||||||
var character_battle_sprite_palette_stone_texture: ImageTexture
|
var character_battle_sprite_palette_stone_texture: ImageTexture
|
||||||
var weapon_textures = {}
|
var weapon_textures = {}
|
||||||
|
|
||||||
|
func ByteArray(size: int) -> PoolByteArray:
|
||||||
|
var arr := PoolByteArray()
|
||||||
|
arr.resize(size)
|
||||||
|
return arr
|
||||||
|
|
||||||
func texture_from_image(image: Image, flags: int = 0) -> ImageTexture:
|
func texture_from_image(image: Image, flags: int = 0) -> ImageTexture:
|
||||||
var tex = ImageTexture.new()
|
var tex = ImageTexture.new()
|
||||||
tex.create_from_image(image, flags)
|
tex.create_from_image(image, flags)
|
||||||
|
@ -78,11 +82,6 @@ func generate_palette_rgb5_a1(rom: File, offset: int, length: int = 16) -> Image
|
||||||
func generate_palette(rom: File, offset: int, length: int = 16) -> Image:
|
func generate_palette(rom: File, offset: int, length: int = 16) -> Image:
|
||||||
return generate_palette_rgb8(rom, offset, length)
|
return generate_palette_rgb8(rom, offset, length)
|
||||||
|
|
||||||
func ByteArray(size: int) -> PoolByteArray:
|
|
||||||
var arr = PoolByteArray()
|
|
||||||
arr.resize(size)
|
|
||||||
return arr
|
|
||||||
|
|
||||||
func gba_4bpp_to_tile(data: PoolByteArray) -> Image:
|
func gba_4bpp_to_tile(data: PoolByteArray) -> Image:
|
||||||
var tdata := ByteArray(64)
|
var tdata := ByteArray(64)
|
||||||
for i in range(32):
|
for i in range(32):
|
||||||
|
@ -146,10 +145,7 @@ func snes_get_tile(rom: File, offset: int, length: int) -> Image:
|
||||||
return snes_1plane_to_tile(data)
|
return snes_1plane_to_tile(data)
|
||||||
|
|
||||||
|
|
||||||
func load_snes_rom(filename: String):
|
func load_snes_rom(rom: File):
|
||||||
var rom := File.new()
|
|
||||||
var _error = rom.open(filename, File.READ)
|
|
||||||
|
|
||||||
rom.seek(offset_Character_Battle_Sprite_Layouts)
|
rom.seek(offset_Character_Battle_Sprite_Layouts)
|
||||||
var battle_strip_layouts = rom.get_buffer(num_Character_Battle_Sprite_Layouts * 6)
|
var battle_strip_layouts = rom.get_buffer(num_Character_Battle_Sprite_Layouts * 6)
|
||||||
# Character Battle Sprite Tiles
|
# Character Battle Sprite Tiles
|
||||||
|
@ -172,39 +168,6 @@ func load_snes_rom(filename: String):
|
||||||
|
|
||||||
weapon_textures['Fist'] = texture_from_image(snes_get_tile(rom, offset_Tiles_Fist, 24))
|
weapon_textures['Fist'] = texture_from_image(snes_get_tile(rom, offset_Tiles_Fist, 24))
|
||||||
|
|
||||||
SoundLoader.load_samples(rom)
|
|
||||||
|
|
||||||
|
|
||||||
func gba_LZ77_decompress(rom: File, address: int) -> PoolByteArray:
|
|
||||||
rom.seek(address)
|
|
||||||
var header := rom.get_32()
|
|
||||||
assert (header & 0x10 == 0x10)
|
|
||||||
var length := header >> 8
|
|
||||||
var output := ByteArray(length)
|
|
||||||
var ptr := 0
|
|
||||||
while ptr < length:
|
|
||||||
var bitmap := rom.get_8()
|
|
||||||
for i in range(8):
|
|
||||||
if (bitmap >> (7-i)) & 1:
|
|
||||||
# Buffer substitution
|
|
||||||
var h1 := rom.get_8()
|
|
||||||
var h2 := rom.get_8()
|
|
||||||
var copy_len := 3 + (h1 >> 4)
|
|
||||||
var copy_ptr := ptr - 1 - (((h1 & 0x0F)<<8) + h2)
|
|
||||||
for j in range(copy_len):
|
|
||||||
output[ptr] = output[copy_ptr]
|
|
||||||
copy_ptr += 1
|
|
||||||
ptr += 1
|
|
||||||
if ptr >= length:
|
|
||||||
return output
|
|
||||||
else:
|
|
||||||
# Literal byte
|
|
||||||
output[ptr] = rom.get_8()
|
|
||||||
ptr += 1
|
|
||||||
if ptr >= length:
|
|
||||||
return output
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
const gba_marker := 'FINAL FANTASY V ADVANCE SYGMAB'
|
const gba_marker := 'FINAL FANTASY V ADVANCE SYGMAB'
|
||||||
const gba_marker_pos_US := 0x12FE10
|
const gba_marker_pos_US := 0x12FE10
|
||||||
|
@ -238,7 +201,7 @@ func load_gba_rom(filename: String):
|
||||||
var tiles = []
|
var tiles = []
|
||||||
rom.seek(offset_marker + gba_offset_battle_sprite_tiles + strip*4)
|
rom.seek(offset_marker + gba_offset_battle_sprite_tiles + strip*4)
|
||||||
var address = rom.get_32() - 0x08000000
|
var address = rom.get_32() - 0x08000000
|
||||||
var tiledata = gba_LZ77_decompress(rom, address)
|
var tiledata = CommonGBA.LZ77_decompress(rom, address)
|
||||||
tiledata.append(0) # Slicing to end of array causes an engine crash. For shame!
|
tiledata.append(0) # Slicing to end of array causes an engine crash. For shame!
|
||||||
for i in range(8, 57*32+8, 32):
|
for i in range(8, 57*32+8, 32):
|
||||||
tiles.append(gba_4bpp_to_tile(tiledata.subarray(i, i+32)))
|
tiles.append(gba_4bpp_to_tile(tiledata.subarray(i, i+32)))
|
||||||
|
@ -259,6 +222,5 @@ func load_gba_rom(filename: String):
|
||||||
|
|
||||||
var strip_images = []
|
var strip_images = []
|
||||||
var strip_textures = []
|
var strip_textures = []
|
||||||
func _ready():
|
# func _ready():
|
||||||
load_snes_rom(ROM_filename)
|
#pass
|
||||||
#load_gba_rom('2564 - Final Fantasy V Advance (U)(Independent).gba')
|
|
Loading…
Reference in New Issue