diff --git a/src/reskit/soundtrack/engines/echo.rs b/src/reskit/soundtrack/engines/echo.rs index e2a0d91..2566efe 100644 --- a/src/reskit/soundtrack/engines/echo.rs +++ b/src/reskit/soundtrack/engines/echo.rs @@ -4,4 +4,6 @@ pub trait EchoFormat { fn get_eefs( &self ) -> Result>, Box>; + fn get_eifs( &self ) -> Result>, Box>; + } \ No newline at end of file diff --git a/src/reskit/soundtrack/formats/dmf.rs b/src/reskit/soundtrack/formats/dmf.rs index 2b3424e..3a9a771 100644 --- a/src/reskit/soundtrack/formats/dmf.rs +++ b/src/reskit/soundtrack/formats/dmf.rs @@ -3,7 +3,7 @@ use flate2::read::ZlibDecoder; use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, Ring}, soundtrack::{types::{SampleRate, SampleFormat, PsgEnvelope, Note, Sample, PsgSettings}, engines::echo::EchoFormat}}; const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask."; -const DMF_SUPPORTED_VERSION: u8 = 0x18; +const DMF_SUPPORTED_VERSION: u8 = 27; const DMF_MD: u8 = 0x02; const DMF_MD_ENHANCED_CH3: u8 = 0x42; @@ -74,7 +74,7 @@ pub struct DmfModule { speed_b: u8, frame_mode: FrameMode, rows_per_pattern: u32, - pattern_matrix: Vec>, + pattern_matrix: Vec>, instruments: Vec, samples: Vec } @@ -166,12 +166,12 @@ impl DmfModule { 13 }; - let mut pattern_matrix: Vec> = vec![vec![0; system_total_channels]; patterns_count.into()]; + let mut pattern_matrix: Vec> = vec![vec![0; system_total_channels]; patterns_count.into()]; for channel in 0..system_total_channels { for pattern in 0..patterns_count { let channel: usize = channel.into(); let pattern: usize = pattern.into(); - pattern_matrix[ pattern ][ channel ] = get_u8( bytes.by_ref() )?; + pattern_matrix[ pattern ][ channel ] = get_u16( bytes.by_ref() )?; } } @@ -471,10 +471,17 @@ impl DmfModule { instruments.push( Instrument { name, instrument_type } ); } - // Wavetables are not used in fm synthesis, this should validate as 0 or error - let wavetable_count = get_u8( bytes.by_ref() )?; - if wavetable_count > 0 { - return Err( "invalid file: wavetables should be zero for system type Sega Megadrive" )?; + // Version 27 of DMF specifies "1 wavetable of 0 bytes" for sega megadrive + // They will never be used in the megadrive, barring use of the audio + // expansion on the cartridge slot (e.g. mp3 fpga, spc700 fpga) + // It may just be easier here to eat the wavetables as they are indicated + // instead of throwing a validation error if anything is present here. + let wavetable_len = get_u8( bytes.by_ref() )?; + for _ in 0..wavetable_len { + let wavetable_size: usize = get_u32( bytes.by_ref() )?.try_into()?; + if wavetable_size > 0 { + skip( bytes.by_ref(), wavetable_size * 4 ); + } } // (channel, patterns) @@ -584,6 +591,9 @@ impl DmfModule { } samples.push( sample ); + + // Fast forward 8 bytes that are unused at the end of the sample + skip( bytes.by_ref(), 8 ); } Ok( @@ -727,6 +737,21 @@ impl EchoFormat for DmfModule { Ok( eefs ) } + fn get_eifs( &self ) -> Result>, Box> { + let mut eifs: HashMap> = HashMap::new(); + + for instrument in &self.instruments { + if let InstrumentType::Fm( settings ) = &instrument.instrument_type { + // Create feedback + algorithm byte + let alg_fb: u8 = ( settings.fb << 3 ) | settings.alg; + + todo!() + } + } + + Ok( eifs ) + } + } fn get_eef_volume( dmf_volume: u8 ) -> Result> {