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
|
// Key on or key off note
|
||||||
if let Some( note ) = &row.note {
|
if let Some( note ) = &row.note {
|
||||||
if let Note::NoteOff = 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 ] );
|
events.push( vec![ ESF_NOTE_OFF | channels[ active_channel ].id ] );
|
||||||
} else {
|
} else {
|
||||||
|
channels[ active_channel ].note_keyed = true;
|
||||||
channels[ active_channel ].active_note = Some(
|
channels[ active_channel ].active_note = Some(
|
||||||
OctaveFrequency {
|
OctaveFrequency {
|
||||||
octave: note.get_octave()?,
|
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 let Effect::DcsgNoiseMode { mode, noise_type: _ } = dcsg_noise_mode {
|
||||||
if mode == &DcsgChannelMode::Ch3Frequency {
|
if mode == &DcsgChannelMode::Ch3Frequency {
|
||||||
let index = channels.iter().position( | channel | channel.id == ESF_PSG_3 ).ok_or( "internal error: where is psg3??" )?;
|
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
|
// Issue a set frequency for psg3 but don't tell the channel state (matches behaviour in deflemask)
|
||||||
channels[ index ].active_note = channels[ active_channel ].active_note;
|
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 {
|
} else {
|
||||||
return Err( "internal error: wtf happened here (3)??" )?
|
return Err( "internal error: wtf happened here (3)??" )?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let index = channels.iter().position( | channel | channel.id == ESF_PSG_3 ).ok_or( "internal error: where is psg3??" )?;
|
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
|
// Issue a set frequency for psg3 but don't tell the channel state (matches behaviour in deflemask)
|
||||||
channels[ index ].active_note = channels[ active_channel ].active_note;
|
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 )? {
|
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.
|
* for the next event.
|
||||||
*/
|
*/
|
||||||
pub fn get_portamento( channel: &mut Channel, portamento_effect: &Effect ) -> Result<EchoEvent, Box<dyn Error>> {
|
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(
|
Ok(
|
||||||
if channel.id == ESF_FM_6_PCM || channel.id == ESF_PSG_4 {
|
if channel.id == ESF_FM_6_PCM || channel.id == ESF_PSG_4 {
|
||||||
// Generate no events if channel is set to pcm
|
// 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 tick >= after_ticks {
|
||||||
if channel.active_note.is_some() {
|
channel.note_keyed = false;
|
||||||
channel.active_note = None;
|
|
||||||
// Consume the note cut after we are done with it - it does not remain active
|
// Consume the note cut after we are done with it - it does not remain active
|
||||||
channel.active_effects = channel.active_effects
|
channel.active_effects = channel.active_effects
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) )
|
.filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) )
|
||||||
.collect();
|
.collect();
|
||||||
return Ok( vec![ ESF_NOTE_OFF | channel.id ] );
|
return Ok( vec![ ESF_NOTE_OFF | channel.id ] );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to generate this tick
|
// Nothing to generate this tick
|
||||||
|
|
|
@ -98,6 +98,7 @@ pub struct Channel {
|
||||||
pub id: u8,
|
pub id: u8,
|
||||||
pub active_instrument: Option<u16>,
|
pub active_instrument: Option<u16>,
|
||||||
pub active_note: Option<OctaveFrequency>,
|
pub active_note: Option<OctaveFrequency>,
|
||||||
|
pub note_keyed: bool,
|
||||||
pub current_volume: Option<u8>,
|
pub current_volume: Option<u8>,
|
||||||
pub active_effects: LinkedHashSet<Effect>
|
pub active_effects: LinkedHashSet<Effect>
|
||||||
}
|
}
|
||||||
|
@ -144,6 +145,7 @@ impl Channel {
|
||||||
id,
|
id,
|
||||||
active_instrument: None,
|
active_instrument: None,
|
||||||
active_note: None,
|
active_note: None,
|
||||||
|
note_keyed: false,
|
||||||
current_volume: None,
|
current_volume: None,
|
||||||
active_effects: LinkedHashSet::new()
|
active_effects: LinkedHashSet::new()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue