141 lines
3.2 KiB
GDScript
141 lines
3.2 KiB
GDScript
"""
|
|
MOD reader by Yui Kinomoto @arlez80
|
|
"""
|
|
|
|
"""
|
|
ファイルから読み込み
|
|
@param path File path
|
|
@return smf
|
|
"""
|
|
func read_file( path ):
|
|
var f = File.new( )
|
|
|
|
if not f.file_exists( path ):
|
|
print( "file %s is not found" % path )
|
|
breakpoint
|
|
|
|
f.open( path, f.READ )
|
|
var stream = StreamPeerBuffer.new( )
|
|
stream.set_data_array( f.get_buffer( f.get_len( ) ) )
|
|
stream.big_endian = true
|
|
f.close( )
|
|
|
|
return self._read( stream )
|
|
|
|
"""
|
|
配列から読み込み
|
|
@param data PoolByteArray
|
|
@return smf
|
|
"""
|
|
func read_data( data ):
|
|
var stream = StreamPeerBuffer.new( )
|
|
stream.set_data_array( data )
|
|
stream.big_endian = true
|
|
return self._read( stream )
|
|
|
|
"""
|
|
読み込み
|
|
@param stream
|
|
@return smf
|
|
"""
|
|
func _read( stream ):
|
|
var name = self._read_string( stream, 20 )
|
|
var samples = self._read_sample_informations( stream )
|
|
var song_length = stream.get_u8( )
|
|
var unknown_number = stream.get_u8( )
|
|
var song_positions = stream.get_partial_data( 128 )[1]
|
|
var max_song_position = 0
|
|
for sp in song_positions:
|
|
if max_song_position < sp:
|
|
max_song_position = sp
|
|
|
|
var magic = self._read_string( stream, 4 )
|
|
var channel_count = 4
|
|
match magic:
|
|
"6CHN":
|
|
channel_count = 6
|
|
"FLT8", "8CHN", "CD81", "OKTA":
|
|
channel_count = 8
|
|
"16CN":
|
|
channel_count = 16
|
|
"32CN":
|
|
channel_count = 32
|
|
_:
|
|
# print( "Unknown magic" )
|
|
# breakpoint
|
|
pass
|
|
|
|
var patterns = self._read_patterns( stream, max_song_position, channel_count )
|
|
self._read_sample_data( stream, samples )
|
|
|
|
return {
|
|
"name": name,
|
|
"song_length": song_length,
|
|
"unknown_number": unknown_number,
|
|
"song_positions": song_positions,
|
|
"magic": magic,
|
|
|
|
"patterns": patterns,
|
|
"samples": samples,
|
|
}
|
|
|
|
"""
|
|
サンプルのデータを読み込む
|
|
"""
|
|
func _read_sample_informations( stream ):
|
|
var samples = []
|
|
|
|
for i in range( 0, 31 ):
|
|
var sample = {}
|
|
sample.name = self._read_string( stream, 22 )
|
|
sample.length = stream.get_u16( ) * 2
|
|
sample.fine_tune = stream.get_u8( ) & 0x0F
|
|
if 0x08 < sample.fine_tune:
|
|
sample.fine_tune = 0x10 - sample.fine_tune
|
|
sample.volume = stream.get_u8( )
|
|
sample.loop_start = stream.get_u16( ) * 2
|
|
sample.loop_length = stream.get_u16( ) * 2
|
|
|
|
samples.append( sample )
|
|
|
|
return samples
|
|
|
|
"""
|
|
パターンを読み込む
|
|
"""
|
|
func _read_patterns( stream, max_position, channels ):
|
|
var patterns = []
|
|
for position in range( 0, max_position ):
|
|
var pattern = []
|
|
for i in range( 0, 64 ):
|
|
var line = []
|
|
for ch in range( 0, channels ):
|
|
var v1 = stream.get_u16( )
|
|
var v2 = stream.get_u16( )
|
|
var sample_number = ( ( v1 >> 8 ) & 0xF0 ) | ( ( v2 >> 12 ) & 0x0F )
|
|
var key_number = v1 & 0x0FFF
|
|
var effect_command = v2 & 0x0FFF
|
|
line.append({
|
|
"sample_number": sample_number,
|
|
"key_number": key_number,
|
|
"effect_command": effect_command,
|
|
})
|
|
pattern.append( line )
|
|
patterns.append( pattern )
|
|
|
|
"""
|
|
波形データ読み込む
|
|
"""
|
|
func _read_sample_data( stream, samples ):
|
|
for sample in samples:
|
|
sample.data = stream.get_partial_data( sample.length )[1]
|
|
|
|
"""
|
|
文字列の読み込み
|
|
@param stream Stream
|
|
@param size string size
|
|
@return string
|
|
"""
|
|
func _read_string( stream, size ):
|
|
return stream.get_partial_data( size )[1].get_string_from_ascii( )
|