diff --git a/src/reskit/soundtrack/engines/echo/dmf.rs b/src/reskit/soundtrack/engines/echo/dmf.rs index 98b3594..ada429a 100644 --- a/src/reskit/soundtrack/engines/echo/dmf.rs +++ b/src/reskit/soundtrack/engines/echo/dmf.rs @@ -3,7 +3,7 @@ use convert_case::{Case, Casing}; use samplerate::convert; use uuid::Uuid; use crate::reskit::{soundtrack::{formats::dmf::{DmfModule, ECHO_EWF_SAMPLE_RATE}, types::{InstrumentType, SampleFormat, Channel, PatternRow}}, utility::{print_warning, Ring}}; -use super::engine::{EchoFormat, ESF_FM_1, ESF_FM_2, ESF_FM_3, ESF_FM_4, ESF_FM_5, ESF_FM_6, ESF_PSG_1, ESF_PSG_2, ESF_PSG_3, ESF_PSG_4, EchoEvent, get_events_for_row, compact_delays}; +use super::engine::{EchoFormat, ESF_FM_1, ESF_FM_2, ESF_FM_3, ESF_FM_4, ESF_FM_5, ESF_FM_6, ESF_PSG_1, ESF_PSG_2, ESF_PSG_3, ESF_PSG_4, EchoEvent, get_events_for_row, compact_delays, ESF_SET_LOOP, ESF_GO_TO_LOOP, ESF_STOP}; impl EchoFormat for DmfModule { @@ -332,10 +332,16 @@ impl EchoFormat for DmfModule { self.instruments.len() as u8 )?; + // Is this the pattern matrix row that we repeat to? + // If so, insert an ESF_LOOP_SET here. + if let Some( repeat_row ) = self.loop_at { + if row_number == repeat_row { + all_events.push( vec![ ESF_SET_LOOP ] ); + } + } + // Transfer ESF events to the main stream all_events.extend( events_this_row ); - - // Any jumps? } // Compact sequences of delays to save rom space @@ -344,7 +350,7 @@ impl EchoFormat for DmfModule { esf.extend( event ); } - esf.push( 0xFF ); // Terminate the stream + esf.push( if let None = self.loop_at { ESF_STOP } else { ESF_GO_TO_LOOP } ); // Terminate the stream Ok( esf ) } diff --git a/src/reskit/soundtrack/engines/echo/engine.rs b/src/reskit/soundtrack/engines/echo/engine.rs index 97f4ef7..e825361 100644 --- a/src/reskit/soundtrack/engines/echo/engine.rs +++ b/src/reskit/soundtrack/engines/echo/engine.rs @@ -15,10 +15,10 @@ const ESF_SET_FM_DIRECT_0: u8 = 0xF8; const ESF_SET_FM_DIRECT_1: u8 = 0xF9; const ESF_SET_FLAGS: u8 = 0xFA; const ESF_CLEAR_FLAGS: u8 = 0xFB; -const ESF_GOTO: u8 = 0xFC; -const ESF_LOOP_SET: u8 = 0xFD; +pub const ESF_GO_TO_LOOP: u8 = 0xFC; +pub const ESF_SET_LOOP: u8 = 0xFD; const ESF_DELAY_LONG: u8 = 0xFE; -const ESF_STOP: u8 = 0xFF; +pub const ESF_STOP: u8 = 0xFF; pub const ESF_FM_1: u8 = 0x00; pub const ESF_FM_2: u8 = 0x01; @@ -537,6 +537,9 @@ fn apply_effects_to_channel( channel: &mut Channel, effects: &LinkedHashSet { + // Nothing to do - handled as we iterate through the rows. + }, unsupported_effect => print_warning( &format!( "effect unsupported: {:?}. your soundtrack may sound different than expected.", unsupported_effect ) ) } } diff --git a/src/reskit/soundtrack/formats/dmf.rs b/src/reskit/soundtrack/formats/dmf.rs index ab4895e..63631cc 100644 --- a/src/reskit/soundtrack/formats/dmf.rs +++ b/src/reskit/soundtrack/formats/dmf.rs @@ -37,6 +37,7 @@ pub struct DmfModule { frame_mode: FrameMode, pub rows_per_pattern: u32, pattern_matrix: Vec>, + pub loop_at: Option, pub channel_patterns: Vec>, pub instruments: Vec, pub samples: Vec @@ -449,6 +450,7 @@ impl DmfModule { } // (channel, patterns) + let mut loop_at: Option = None; let mut channel_patterns: Vec> = Vec::new(); for channel in 0..system_total_channels { let mut channel_rows: Vec = Vec::new(); @@ -527,6 +529,10 @@ impl DmfModule { DMF_EFFECT_POSITION_JUMP => { let pattern = effect_value.ok_or( "invalid file: expected effect value for position jump" )?; + if let None = loop_at { + loop_at = Some( pattern as u32 * rows_per_pattern ); + } + Effect::PositionJump { pattern } }, DMF_EFFECT_PATTERN_BREAK => { @@ -659,7 +665,7 @@ impl DmfModule { Ok( DmfModule { path: path.to_string(), platform, version, time_base, speed_a, speed_b, frame_mode, rows_per_pattern, - pattern_matrix, channel_patterns, instruments, samples + pattern_matrix, loop_at, channel_patterns, instruments, samples } ) }