debug.rsannotateddebug.rssource147 lines · 4.5 KB · raw
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}