1use crate::ym2612::{FrequencyMode, RegisterGroup, Ym2612}; 2use std::array; 3 4pub struct Ym2612DebugView<'a>(&'a Ym2612); 5 6impl Ym2612 { 7 #[must_use] 8 pub fn debug_view(&self) -> Ym2612DebugView<'_> { 9 Ym2612DebugView(self) 10 } 11} 12 13#[derive(Debug, Clone)] 14pub struct LfoState { 15 pub enabled: bool, 16 pub frequency: u8, 17 pub divider: u8, 18} 19 20#[derive(Debug, Clone)] 21pub struct TimerState { 22 pub enabled: bool, 23 pub overflow_flag: bool, 24 pub overflow_flag_enabled: bool, 25 pub interval: u16, 26} 27 28#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29pub enum Channel3FrequencyMode { 30 Normal, 31 PerOperator, 32 Csm, 33} 34 35#[derive(Debug, Clone)] 36pub struct GlobalRegisters { 37 pub dac_channel_enabled: bool, 38 pub dac_channel_sample: u8, 39 pub lfo: LfoState, 40 pub register_address: u8, 41 pub group: RegisterGroup, 42 pub timer_a: TimerState, 43 pub timer_b: TimerState, 44 pub channel_3_frequency_mode: Channel3FrequencyMode, 45 pub channel_3_f_numbers: [u16; 3], 46 pub channel_3_blocks: [u8; 3], 47} 48 49#[derive(Debug, Clone)] 50pub struct ChannelRegisters { 51 pub f_number: u16, 52 pub block: u8, 53 pub algorithm: u8, 54 pub feedback_level: u8, 55 pub am_sensitivity: u8, 56 pub fm_sensitivity: u8, 57 pub l_output: bool, 58 pub r_output: bool, 59} 60 61#[derive(Debug, Clone)] 62pub struct OperatorRegisters { 63 pub key_on: bool, 64 pub detune: u8, 65 pub multiple: u8, 66 pub attack_rate: u8, 67 pub decay_rate: u8, 68 pub sustain_rate: u8, 69 pub release_rate: u8, 70 pub total_level: u8, 71 pub sustain_level: u8, 72 pub key_scale_level: u8, 73 pub tremolo_enabled: bool, 74 pub ssg_enabled: bool, 75 pub ssg_attack: bool, 76 pub ssg_alternate: bool, 77 pub ssg_hold: bool, 78} 79 80impl Ym2612DebugView<'_> { 81 #[must_use] 82 pub fn global_registers(&self) -> GlobalRegisters { 83 GlobalRegisters { 84 dac_channel_enabled: self.0.dac_channel_enabled, 85 dac_channel_sample: self.0.dac_channel_sample, 86 lfo: self.0.lfo.to_debug_state(), 87 register_address: self.0.selected_register, 88 group: self.0.selected_register_group, 89 timer_a: self.0.timer_a.to_debug_state(), 90 timer_b: self.0.timer_b.to_debug_state(), 91 channel_3_frequency_mode: if self.0.csm_enabled { 92 Channel3FrequencyMode::Csm 93 } else if self.0.channels[2].mode == FrequencyMode::Multiple { 94 Channel3FrequencyMode::PerOperator 95 } else { 96 Channel3FrequencyMode::Normal 97 }, 98 channel_3_f_numbers: self.0.channels[2].operator_f_numbers, 99 channel_3_blocks: self.0.channels[2].operator_blocks, 100 } 101 } 102 103 #[must_use] 104 pub fn channel_registers(&self) -> [ChannelRegisters; 6] { 105 array::from_fn(|ch| { 106 let channel = &self.0.channels[ch]; 107 108 ChannelRegisters { 109 f_number: channel.channel_f_number, 110 block: channel.channel_block, 111 algorithm: channel.algorithm, 112 feedback_level: channel.feedback_level, 113 am_sensitivity: channel.am_sensitivity, 114 fm_sensitivity: channel.fm_sensitivity, 115 l_output: channel.l_output, 116 r_output: channel.r_output, 117 } 118 }) 119 } 120 121 #[must_use] 122 pub fn operator_registers(&self) -> [[OperatorRegisters; 4]; 6] { 123 array::from_fn(|ch| { 124 array::from_fn(|operator| { 125 let operator = &self.0.channels[ch].operators[operator]; 126 127 OperatorRegisters { 128 key_on: operator.envelope.is_key_on(), 129 detune: operator.phase.detune, 130 multiple: operator.phase.multiple, 131 attack_rate: operator.envelope.attack_rate, 132 decay_rate: operator.envelope.decay_rate, 133 sustain_rate: operator.envelope.sustain_rate, 134 release_rate: operator.envelope.release_rate, 135 total_level: operator.envelope.total_level, 136 sustain_level: operator.envelope.sustain_level, 137 key_scale_level: operator.envelope.key_scale, 138 tremolo_enabled: operator.am_enabled, 139 ssg_enabled: operator.envelope.ssg_enabled, 140 ssg_attack: operator.envelope.ssg_attack, 141 ssg_alternate: operator.envelope.ssg_alternate, 142 ssg_hold: operator.envelope.ssg_hold, 143 } 144 }) 145 }) 146 } 147}