Correct-er implemenation of psg3/psg4 relationship in deflemask
parent
f276051133
commit
21b3de950e
|
@ -309,9 +309,10 @@ pub fn get_events_for_channel( channels: &mut [Channel], active_channel: usize,
|
|||
// Key on or key off note
|
||||
if let Some( note ) = &row.note {
|
||||
if let Note::NoteOff = note {
|
||||
channels[ active_channel ].active_note = None;
|
||||
channels[ active_channel ].note_keyed = false;
|
||||
events.push( vec![ ESF_NOTE_OFF | channels[ active_channel ].id ] );
|
||||
} else {
|
||||
channels[ active_channel ].note_keyed = true;
|
||||
channels[ active_channel ].active_note = Some(
|
||||
OctaveFrequency {
|
||||
octave: note.get_octave()?,
|
||||
|
@ -334,16 +335,24 @@ pub fn get_events_for_channel( channels: &mut [Channel], active_channel: usize,
|
|||
if let Effect::DcsgNoiseMode { mode, noise_type: _ } = dcsg_noise_mode {
|
||||
if mode == &DcsgChannelMode::Ch3Frequency {
|
||||
let index = channels.iter().position( | channel | channel.id == ESF_PSG_3 ).ok_or( "internal error: where is psg3??" )?;
|
||||
// Copy over the active note to psg3
|
||||
channels[ index ].active_note = channels[ active_channel ].active_note;
|
||||
// Issue a set frequency for psg3 but don't tell the channel state (matches behaviour in deflemask)
|
||||
events.push( vec![
|
||||
ESF_SET_FREQUENCY | channels[ index ].id,
|
||||
( 0x000F & channels[ active_channel ].active_note.ok_or( "internal error: wtf happened here (1)??" )?.frequency ) as u8,
|
||||
( ( 0x3F0 & channels[ active_channel ].active_note.ok_or( "internal error: wtf happened here (2)??" )?.frequency ) >> 4 ) as u8
|
||||
] );
|
||||
}
|
||||
} else {
|
||||
return Err( "internal error: wtf happened here (3)??" )?
|
||||
}
|
||||
} else {
|
||||
let index = channels.iter().position( | channel | channel.id == ESF_PSG_3 ).ok_or( "internal error: where is psg3??" )?;
|
||||
// Copy over the active note to psg3
|
||||
channels[ index ].active_note = channels[ active_channel ].active_note;
|
||||
// Issue a set frequency for psg3 but don't tell the channel state (matches behaviour in deflemask)
|
||||
events.push( vec![
|
||||
ESF_SET_FREQUENCY | channels[ index ].id,
|
||||
( 0x000F & channels[ active_channel ].active_note.ok_or( "internal error: wtf happened here (1)??" )?.frequency ) as u8,
|
||||
( ( 0x3F0 & channels[ active_channel ].active_note.ok_or( "internal error: wtf happened here (2)??" )?.frequency ) >> 4 ) as u8
|
||||
] );
|
||||
}
|
||||
|
||||
if let Some( noise_generator_setting ) = get_noise_generator_setting( note, dcsg_noise_mode )? {
|
||||
|
@ -554,6 +563,18 @@ pub fn compact_delays( events: Vec<EchoEvent> ) -> Result<Vec<EchoEvent>, Box<dy
|
|||
* for the next event.
|
||||
*/
|
||||
pub fn get_portamento( channel: &mut Channel, portamento_effect: &Effect ) -> Result<EchoEvent, Box<dyn Error>> {
|
||||
if channel.id != ESF_FM_6_PCM && channel.id != ESF_PSG_4 {
|
||||
// A portamento was called for on this channel, and if none was provided, we need to start with C, octave 0
|
||||
// This replicates the behaviour in deflemask
|
||||
if let None = channel.active_note {
|
||||
channel.active_note = match channel.id {
|
||||
ESF_FM_1..=ESF_FM_3 | ESF_FM_4..=ESF_FM_6 => Some( OctaveFrequency { octave: 0, frequency: get_fm_semitone_frequency( ESF_SEMITONE_C )? } ),
|
||||
ESF_PSG_1..=ESF_PSG_3 => Some( OctaveFrequency { octave: 0, frequency: get_psg_semitone_frequency( 0, ESF_SEMITONE_C )? } ),
|
||||
invalid_channel => return Err( format!( "internal error: get_note: invalid default portamento setting channel {:#04X}", invalid_channel ) )?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(
|
||||
if channel.id == ESF_FM_6_PCM || channel.id == ESF_PSG_4 {
|
||||
// Generate no events if channel is set to pcm
|
||||
|
@ -639,16 +660,15 @@ pub fn get_note_cut( channel: &mut Channel, note_cut_effect: &Effect, tick: u8 )
|
|||
};
|
||||
|
||||
if tick >= after_ticks {
|
||||
if channel.active_note.is_some() {
|
||||
channel.active_note = None;
|
||||
// Consume the note cut after we are done with it - it does not remain active
|
||||
channel.active_effects = channel.active_effects
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) )
|
||||
.collect();
|
||||
return Ok( vec![ ESF_NOTE_OFF | channel.id ] );
|
||||
}
|
||||
channel.note_keyed = false;
|
||||
|
||||
// Consume the note cut after we are done with it - it does not remain active
|
||||
channel.active_effects = channel.active_effects
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) )
|
||||
.collect();
|
||||
return Ok( vec![ ESF_NOTE_OFF | channel.id ] );
|
||||
}
|
||||
|
||||
// Nothing to generate this tick
|
||||
|
|
|
@ -98,6 +98,7 @@ pub struct Channel {
|
|||
pub id: u8,
|
||||
pub active_instrument: Option<u16>,
|
||||
pub active_note: Option<OctaveFrequency>,
|
||||
pub note_keyed: bool,
|
||||
pub current_volume: Option<u8>,
|
||||
pub active_effects: LinkedHashSet<Effect>
|
||||
}
|
||||
|
@ -144,6 +145,7 @@ impl Channel {
|
|||
id,
|
||||
active_instrument: None,
|
||||
active_note: None,
|
||||
note_keyed: false,
|
||||
current_volume: None,
|
||||
active_effects: LinkedHashSet::new()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue