pulse.rsannotatedpulse.rssource351 lines · 10.4 KB · raw
1use crate::apu::components::{Envelope, PulseTimer, StandardLengthCounter, TimerTickEffect};
2use bincode::{Decode, Encode};
3use jgenesis_common::num::GetBit;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode)]
6enum DutyCycle {
7    #[default]
8    OneEighth,
9    OneFourth,
10    OneHalf,
11    ThreeFourths,
12}
13
14impl DutyCycle {
15    fn waveform_step(self, phase: u8) -> bool {
16        match self {
17            // 00000001
18            Self::OneEighth => 0b1000_0000_u8.bit(phase),
19            // 10000001
20            Self::OneFourth => 0b1000_0001_u8.bit(phase),
21            // 10000111
22            Self::OneHalf => 0b1110_0001_u8.bit(phase),
23            // 01111110
24            Self::ThreeFourths => 0b0111_1110_u8.bit(phase),
25        }
26    }
27
28    fn from_byte(byte: u8) -> Self {
29        match (byte >> 6) & 0x03 {
30            0x00 => Self::OneEighth,
31            0x01 => Self::OneFourth,
32            0x02 => Self::OneHalf,
33            0x03 => Self::ThreeFourths,
34            _ => unreachable!("value & 0x03 is always <= 0x03"),
35        }
36    }
37
38    fn to_bits(self) -> u8 {
39        match self {
40            Self::OneEighth => 0x00,
41            Self::OneFourth => 0x40,
42            Self::OneHalf => 0x80,
43            Self::ThreeFourths => 0xC0,
44        }
45    }
46}
47
48#[derive(Debug, Clone, Encode, Decode)]
49struct SweepUnit {
50    enabled: bool,
51    shadow_frequency: u16,
52    counter: u8,
53    period: u8,
54    shift: u8,
55    negate: bool,
56    calculated_with_negate_since_trigger: bool,
57}
58
59impl SweepUnit {
60    fn new() -> Self {
61        Self {
62            enabled: false,
63            shadow_frequency: 0,
64            counter: 0,
65            period: 0,
66            shift: 0,
67            negate: false,
68            calculated_with_negate_since_trigger: false,
69        }
70    }
71
72    fn clock(&mut self, timer: &mut PulseTimer, channel_enabled: &mut bool) {
73        if !self.enabled {
74            return;
75        }
76
77        self.counter -= 1;
78        if self.counter == 0 {
79            self.counter = self.counter_reload_value();
80
81            if self.period == 0 {
82                // Period of 0 disables sweep updates (but not the sweep unit counter; a period
83                // of 0 is treated as 8 as far as the counter is concerned)
84                return;
85            }
86
87            let next_frequency = self.calculate_next_frequency();
88            if next_frequency <= 2047 && self.shift != 0 {
89                self.shadow_frequency = next_frequency;
90                timer.write_frequency(next_frequency);
91
92                // When sweep adjusts frequency, it immediately runs another frequency calculation
93                // and will disable the channel if the second calculation overflows
94                if self.calculate_next_frequency() > 2047 {
95                    *channel_enabled = false;
96                }
97            } else if next_frequency > 2047 {
98                *channel_enabled = false;
99            }
100        }
101    }
102
103    fn calculate_next_frequency(&mut self) -> u16 {
104        let mut delta = self.shadow_frequency >> self.shift;
105        if self.negate {
106            delta = (!delta).wrapping_add(1);
107            self.calculated_with_negate_since_trigger = true;
108        }
109
110        self.shadow_frequency.wrapping_add(delta)
111    }
112
113    fn trigger(&mut self, timer: PulseTimer, channel_enabled: &mut bool) {
114        self.shadow_frequency = timer.frequency();
115        self.counter = self.counter_reload_value();
116
117        self.enabled = self.period != 0 || self.shift != 0;
118
119        self.calculated_with_negate_since_trigger = false;
120
121        // If shift is non-zero, trigger immediately runs a frequency calculation and will disable
122        // the channel if it overflows
123        if self.shift != 0 && self.calculate_next_frequency() > 2047 {
124            *channel_enabled = false;
125        }
126    }
127
128    fn counter_reload_value(&self) -> u8 {
129        if self.period == 0 { 8 } else { self.period }
130    }
131
132    fn read_register(&self) -> u8 {
133        0x80 | (self.period << 4) | (u8::from(self.negate) << 3) | self.shift
134    }
135
136    fn write_register(&mut self, value: u8, channel_enabled: &mut bool) {
137        self.period = (value >> 4) & 0x07;
138        self.negate = value.bit(3);
139        self.shift = value & 0x07;
140
141        if self.counter == 0 {
142            self.counter = self.period;
143        }
144
145        if self.calculated_with_negate_since_trigger && !self.negate {
146            // If the negate flag is cleared after frequency was calculated with it set at least
147            // once, the channel is immediately disabled
148            *channel_enabled = false;
149        }
150    }
151}
152
153#[derive(Debug, Clone, Encode, Decode)]
154pub struct PulseChannel {
155    duty_cycle: DutyCycle,
156    length_counter: StandardLengthCounter,
157    envelope: Envelope,
158    sweep: SweepUnit,
159    timer: PulseTimer,
160    channel_enabled: bool,
161    dac_enabled: bool,
162    suppress_output: bool,
163}
164
165impl Default for PulseChannel {
166    fn default() -> Self {
167        Self::new()
168    }
169}
170
171impl PulseChannel {
172    #[must_use]
173    pub fn new() -> Self {
174        Self {
175            duty_cycle: DutyCycle::default(),
176            length_counter: StandardLengthCounter::new(),
177            envelope: Envelope::new(),
178            sweep: SweepUnit::new(),
179            timer: PulseTimer::new(),
180            channel_enabled: false,
181            dac_enabled: false,
182            suppress_output: true,
183        }
184    }
185
186    pub fn clock_sweep(&mut self) {
187        self.sweep.clock(&mut self.timer, &mut self.channel_enabled);
188    }
189
190    pub fn clock_length_counter(&mut self) {
191        self.length_counter.clock(&mut self.channel_enabled);
192    }
193
194    pub fn clock_envelope(&mut self) {
195        self.envelope.clock();
196    }
197
198    pub fn tick_m_cycle(&mut self) {
199        // Obscure behavior: After power-on, pulse channels do not progress through their duty
200        // cycles until after triggering
201        if !self.channel_enabled {
202            return;
203        }
204
205        // More obscure behavior: After power-on, pulse channels output a constant 0 until after
206        // the first phase increment
207        let tick = self.timer.tick();
208        self.suppress_output &= tick != TimerTickEffect::Clocked;
209    }
210
211    #[must_use]
212    pub fn sample(&self) -> Option<u8> {
213        if !self.dac_enabled {
214            return None;
215        }
216
217        if self.suppress_output {
218            return Some(0);
219        }
220
221        let waveform_step = self.duty_cycle.waveform_step(self.timer.phase);
222        Some(u8::from(waveform_step) * self.envelope.volume)
223    }
224
225    #[must_use]
226    pub fn volume(&self) -> u8 {
227        if !self.dac_enabled || self.suppress_output {
228            return 0;
229        }
230
231        self.envelope.volume
232    }
233
234    #[must_use]
235    pub fn read_register_0(&self) -> u8 {
236        self.sweep.read_register()
237    }
238
239    pub fn write_register_0(&mut self, value: u8) {
240        // NR10: Pulse 1 sweep control
241        self.sweep.write_register(value, &mut self.channel_enabled);
242
243        log::trace!("NR10 write, sweep: {:?}", self.sweep);
244    }
245
246    #[must_use]
247    pub fn read_register_1(&self) -> u8 {
248        0x3F | self.duty_cycle.to_bits()
249    }
250
251    pub fn write_register_1(&mut self, value: u8, apu_enabled: bool) {
252        // NR11/NR21: Pulse duty cycle and length counter reload
253        if apu_enabled {
254            self.duty_cycle = DutyCycle::from_byte(value);
255        }
256
257        self.length_counter.load(value);
258
259        log::trace!("NRx1 write");
260        log::trace!("  Duty cycle: {:?}", self.duty_cycle);
261        log::trace!("  Length counter: {}", self.length_counter.counter);
262    }
263
264    #[must_use]
265    pub fn read_register_2(&self) -> u8 {
266        self.envelope.read_register()
267    }
268
269    pub fn write_register_2(&mut self, value: u8) {
270        // NR12/NR22: Pulse envelope control
271        self.envelope.write_register(value);
272        self.dac_enabled = value & 0xF8 != 0;
273
274        if !self.dac_enabled {
275            // Disabling DAC always disables the channel
276            self.channel_enabled = false;
277        }
278
279        log::trace!("NRx2 write");
280        log::trace!("  Envelope: {:?}", self.envelope);
281        log::trace!("  DAC enabled: {}", self.dac_enabled);
282    }
283
284    pub fn write_register_3(&mut self, value: u8) {
285        // NR13/NR23: Pulse frequency low bits
286        let just_reloaded = self.timer.just_reloaded();
287        self.timer.write_frequency_low(value);
288
289        // If the timer just reloaded, update the counter to the new period.
290        // This is a hack to work around the fact that the write actually occurred mid-M-cycle, but
291        // the emulator is processing it post-M-cycle
292        if just_reloaded {
293            self.timer.trigger();
294        }
295
296        log::trace!("NRx3 write");
297        log::trace!("  Timer frequency: {}", self.timer.frequency());
298    }
299
300    #[must_use]
301    pub fn read_register_4(&self) -> u8 {
302        0xBF | (u8::from(self.length_counter.enabled) << 6)
303    }
304
305    pub fn write_register_4(&mut self, value: u8, frame_sequencer_step: u8) {
306        // NR14/NR24: Pulse frequency high bits + length counter enabled + trigger
307        let timer_just_reloaded = self.timer.just_reloaded();
308        self.timer.write_frequency_high(value);
309        self.length_counter.set_enabled(
310            value.bit(6),
311            frame_sequencer_step,
312            &mut self.channel_enabled,
313        );
314
315        // If the timer just reloaded, update the counter to the new period.
316        // This is a hack to work around the fact that the write actually occurred mid-M-cycle, but
317        // the emulator is processing it post-M-cycle
318        if timer_just_reloaded {
319            self.timer.trigger();
320        }
321
322        if value.bit(7) {
323            // Channel triggered
324            let prev_enabled = self.channel_enabled;
325            self.channel_enabled = true;
326
327            self.length_counter.trigger(frame_sequencer_step);
328            self.envelope.trigger();
329            self.timer.trigger();
330            self.sweep.trigger(self.timer, &mut self.channel_enabled);
331
332            self.channel_enabled &= self.dac_enabled;
333
334            if !prev_enabled && self.channel_enabled {
335                // Not sure this is accurate, but adding a 1-cycle delay to the first phase increment
336                // after power-on fixes voice samples in Keitai Denjuu Telefang
337                self.timer.counter += 1;
338            }
339        }
340
341        log::trace!("NRx4 write");
342        log::trace!("  Timer frequency: {}", self.timer.frequency());
343        log::trace!("  Length counter enabled: {}", self.length_counter.enabled);
344        log::trace!("  Triggered: {}", value.bit(7));
345    }
346
347    #[must_use]
348    pub fn enabled(&self) -> bool {
349        self.channel_enabled
350    }
351}