1use crate::cartridge::TVSystem;
2use crate::savestate::{SaveStateError, StateReader, StateWriter};
3
4pub(crate) mod dmc;
5pub(crate) mod noise;
6pub(crate) mod pulse;
7pub(crate) mod triangle;
8
9use dmc::{DmcDmaRequest, DmcState};
10use noise::NoiseChannel;
11use pulse::PulseChannel;
12use triangle::TriangleChannel;
13
14const CPU_CLOCK_NTSC: f64 = 1_789_773.0;
15const DEFAULT_SAMPLE_RATE: u32 = 44_100;
16const FRAME_SEQUENCER_DIVIDER: u16 = 7_456;
17pub const LENGTH_TABLE: [u8; 32] = [
18 10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16, 24, 18, 48, 20, 96, 22,
19 192, 24, 72, 26, 16, 28, 32, 30,
20];
21
22pub trait ExpansionAudioChip {
23 fn cpu_write(&mut self, _addr: u16, _data: u8) {}
24 #[allow(dead_code)]
25 fn cpu_read(&mut self, _addr: u16) -> Option<u8> {
26 None
27 }
28 fn tick_cpu_cycle(&mut self) {}
29 fn clock_quarter_frame(&mut self) {}
30 fn clock_half_frame(&mut self) {}
31 fn irq_line(&self) -> bool {
32 false
33 }
34 fn output_sample(&self) -> f32 {
35 0.0
36 }
37}
38
39pub struct APU {
40 pulse1: PulseChannel,
41 pulse2: PulseChannel,
42 triangle: TriangleChannel,
43 noise: NoiseChannel,
44 dmc: DmcState,
45 frame_irq_inhibit: bool,
46 frame_irq_flag: bool,
47 frame_mode_five_step: bool,
48 frame_step: u8,
49 frame_divider: u16,
50 pending_dmc_dma: Option<DmcDmaRequest>,
51 sample_rate: u32,
52 cycles_per_sample: f64,
53 sample_phase: f64,
54 sample_accum_pulse: i64,
56 sample_accum_tri: i64,
57 sample_accum_noise: i64,
58 sample_accum_dmc: i64,
59 sample_accum_exp: i64,
60 sample_accum_count: u32,
61 audio_samples: Vec<f32>,
62 expansions: Vec<Box<dyn ExpansionAudioChip>>,
63 apu_subclock_even: bool,
64 debug_mute_mask: u8,
65}
66
67impl APU {
68 pub fn new() -> Self {
69 let sample_rate = DEFAULT_SAMPLE_RATE;
70 Self {
71 pulse1: PulseChannel::new(true),
72 pulse2: PulseChannel::new(false),
73 triangle: TriangleChannel::default(),
74 noise: NoiseChannel::default(),
75 dmc: DmcState::default(),
76 frame_irq_inhibit: false,
77 frame_irq_flag: false,
78 frame_mode_five_step: false,
79 frame_step: 0,
80 frame_divider: FRAME_SEQUENCER_DIVIDER,
81 pending_dmc_dma: None,
82 sample_rate,
83 cycles_per_sample: CPU_CLOCK_NTSC / sample_rate as f64,
84 sample_phase: 0.0,
85 sample_accum_pulse: 0,
86 sample_accum_tri: 0,
87 sample_accum_noise: 0,
88 sample_accum_dmc: 0,
89 sample_accum_exp: 0,
90 sample_accum_count: 0,
91 audio_samples: Vec::new(),
92 expansions: Vec::new(),
93 apu_subclock_even: false,
94 debug_mute_mask: 0,
95 }
96 }
97
98 pub fn add_expansion_chip(&mut self, chip: Box<dyn ExpansionAudioChip>) {
99 self.expansions.push(chip);
100 }
101
102 pub fn set_tv_system(&mut self, tv: TVSystem) {
103 self.dmc.set_tv_system(tv);
104 }
105
106 pub fn reset(&mut self) {
107 self.frame_irq_flag = false;
108 self.frame_step = 0;
109 self.frame_divider = FRAME_SEQUENCER_DIVIDER;
110 self.pending_dmc_dma = None;
111 self.sample_phase = 0.0;
112 self.sample_accum_pulse = 0;
113 self.sample_accum_tri = 0;
114 self.sample_accum_noise = 0;
115 self.sample_accum_dmc = 0;
116 self.sample_accum_exp = 0;
117 self.sample_accum_count = 0;
118 self.apu_subclock_even = false;
119 }
120
121 pub fn tick_cpu_cycle(&mut self) {
122 self.tick_frame_counter();
123 if self.apu_subclock_even {
124 self.pulse1.tick_timer();
125 self.pulse2.tick_timer();
126 self.noise.tick_timer();
127 }
128 self.apu_subclock_even = !self.apu_subclock_even;
129 self.triangle.tick_timer();
130 self.dmc.tick_timer();
131 if self.pending_dmc_dma.is_none() {
132 self.pending_dmc_dma = self.dmc.request_dma_if_needed();
133 }
134 if !self.expansions.is_empty() {
135 for chip in &mut self.expansions {
136 chip.tick_cpu_cycle();
137 }
138 }
139
140 let mask = self.debug_mute_mask;
142 let (p1, p2, tri, noise, dmc) = if mask == 0 {
143 (
144 self.pulse1.output(),
145 self.pulse2.output(),
146 self.triangle.output(),
147 self.noise.output(),
148 self.dmc.output_level,
149 )
150 } else {
151 (
152 if mask & 0x01 != 0 {
153 0
154 } else {
155 self.pulse1.output()
156 },
157 if mask & 0x02 != 0 {
158 0
159 } else {
160 self.pulse2.output()
161 },
162 if mask & 0x04 != 0 {
163 0
164 } else {
165 self.triangle.output()
166 },
167 if mask & 0x08 != 0 {
168 0
169 } else {
170 self.noise.output()
171 },
172 if mask & 0x10 != 0 {
173 0
174 } else {
175 self.dmc.output_level
176 },
177 )
178 };
179
180 self.sample_accum_pulse += i64::from(p1 + p2);
182 self.sample_accum_tri += i64::from(tri);
183 self.sample_accum_noise += i64::from(noise);
184 self.sample_accum_dmc += i64::from(dmc);
185
186 if !self.expansions.is_empty() {
187 let mut exp_out = 0i64;
188 for chip in &self.expansions {
189 exp_out += (chip.output_sample() * 1000.0) as i64;
190 }
191 self.sample_accum_exp += exp_out;
192 }
193
194 self.sample_accum_count = self.sample_accum_count.saturating_add(1);
195
196 self.sample_phase += 1.0;
197 if self.sample_phase >= self.cycles_per_sample {
198 self.sample_phase -= self.cycles_per_sample;
199 let count = self.sample_accum_count.max(1) as f64;
200 let inv_count = 1.0 / count;
201 let avg_pulse = self.sample_accum_pulse as f64 * inv_count;
203 let avg_tri = self.sample_accum_tri as f64 * inv_count;
204 let avg_noise = self.sample_accum_noise as f64 * inv_count;
205 let avg_dmc = self.sample_accum_dmc as f64 * inv_count;
206 let avg_exp = self.sample_accum_exp as f64 * inv_count * (1.0 / 1000.0);
207
208 let pulse_mix = if avg_pulse > 0.0 {
209 (95.88 / ((8128.0 / avg_pulse) + 100.0)) as f32
210 } else {
211 0.0
212 };
213
214 let tnd_input = avg_tri / 8227.0 + avg_noise / 12241.0 + avg_dmc / 22638.0;
215 let tnd_mix = if tnd_input > 0.0 {
216 159.79 / ((1.0 / tnd_input) + 100.0)
217 } else {
218 0.0
219 };
220
221 let sample = (pulse_mix + tnd_mix as f32 + avg_exp as f32).clamp(-1.0, 1.0);
222
223 self.sample_accum_pulse = 0;
224 self.sample_accum_tri = 0;
225 self.sample_accum_noise = 0;
226 self.sample_accum_dmc = 0;
227 self.sample_accum_exp = 0;
228 self.sample_accum_count = 0;
229
230 self.audio_samples.push(sample);
231 }
232 }
233
234 pub fn read_status_at_offset(&mut self, _cycle_offset: u8) -> u8 {
235 let mut status = 0u8;
236 if self.pulse1.length_counter > 0 {
237 status |= 0x01;
238 }
239 if self.pulse2.length_counter > 0 {
240 status |= 0x02;
241 }
242 if self.triangle.length_counter > 0 {
243 status |= 0x04;
244 }
245 if self.noise.length_counter > 0 {
246 status |= 0x08;
247 }
248 if self.dmc.bytes_remaining > 0 {
249 status |= 0x10;
250 }
251 if self.frame_irq_flag {
252 status |= 0x40;
253 }
254 if self.dmc.irq_flag {
255 status |= 0x80;
256 }
257 self.frame_irq_flag = false;
258 status
259 }
260
261 pub fn write_register_at_offset(&mut self, addr: u16, data: u8, _cycle_offset: u8) {
262 match addr {
263 0x4000 => self.pulse1.write_control(data),
264 0x4001 => self.pulse1.write_sweep(data),
265 0x4002 => self.pulse1.write_timer_low(data),
266 0x4003 => self.pulse1.write_timer_high(data, self.pulse1.enabled),
267 0x4004 => self.pulse2.write_control(data),
268 0x4005 => self.pulse2.write_sweep(data),
269 0x4006 => self.pulse2.write_timer_low(data),
270 0x4007 => self.pulse2.write_timer_high(data, self.pulse2.enabled),
271 0x4008 => self.triangle.write_linear_control(data),
272 0x400A => self.triangle.write_timer_low(data),
273 0x400B => {
274 self.triangle.write_timer_high(data, self.triangle.enabled);
275 }
276 0x400C => self.noise.write_control(data),
277 0x400E => self.noise.write_period(data),
278 0x400F => self.noise.write_length(data, self.noise.enabled),
279 0x4010 => self.dmc.write_control(data),
280 0x4011 => self.dmc.write_output_level(data),
281 0x4012 => self.dmc.write_sample_address(data),
282 0x4013 => self.dmc.write_sample_length(data),
283 0x4015 => self.write_status(data),
284 0x4017 => self.write_frame_counter(data),
285 _ => {
286 for chip in &mut self.expansions {
287 chip.cpu_write(addr, data);
288 }
289 }
290 }
291 }
292
293 pub fn sample_rate(&self) -> u32 {
294 self.sample_rate
295 }
296
297 pub fn set_sample_rate(&mut self, sample_rate: u32) {
298 if sample_rate == 0 || sample_rate == self.sample_rate {
299 return;
300 }
301
302 self.sample_rate = sample_rate;
303 self.cycles_per_sample = CPU_CLOCK_NTSC / sample_rate as f64;
304 self.sample_phase = 0.0;
305 self.sample_accum_pulse = 0;
306 self.sample_accum_tri = 0;
307 self.sample_accum_noise = 0;
308 self.sample_accum_dmc = 0;
309 self.sample_accum_exp = 0;
310 self.sample_accum_count = 0;
311 self.audio_samples.clear();
312 }
313
314 pub fn audio_samples(&self) -> &[f32] {
315 &self.audio_samples
316 }
317
318 pub fn clear_audio_samples(&mut self) {
319 self.audio_samples.clear();
320 }
321
322 pub fn irq_line(&self) -> bool {
323 self.frame_irq_flag
324 || self.dmc.irq_flag
325 || self.expansions.iter().any(|chip| chip.irq_line())
326 }
327
328 pub fn set_debug_mute_mask(&mut self, mask: u8) {
329 self.debug_mute_mask = mask & 0x1F;
330 }
331
332 pub fn debug_mute_mask(&self) -> u8 {
333 self.debug_mute_mask
334 }
335
336 pub fn take_dmc_dma_request(&mut self) -> Option<DmcDmaRequest> {
337 self.pending_dmc_dma.take()
338 }
339
340 pub fn submit_dmc_dma_sample(&mut self, data: u8) {
341 self.dmc.submit_dma_sample(data);
342 }
343
344 pub fn save_state(&self, writer: &mut StateWriter) {
345 writer.write_u8(self.pulse1.enabled as u8);
346 writer.write_u8(self.pulse1.length_counter);
347 writer.write_u8(self.pulse2.enabled as u8);
348 writer.write_u8(self.pulse2.length_counter);
349 writer.write_u8(self.triangle.enabled as u8);
350 writer.write_u8(self.triangle.length_counter);
351 writer.write_u8(self.noise.enabled as u8);
352 writer.write_u8(self.noise.length_counter);
353 writer.write_bool(self.frame_irq_inhibit);
354 writer.write_bool(self.frame_irq_flag);
355 writer.write_bool(self.frame_mode_five_step);
356 writer.write_u8(self.frame_step);
357 writer.write_u16(self.frame_divider);
358 writer.write_bool(self.dmc.enabled);
359 writer.write_bool(self.dmc.irq_enabled);
360 writer.write_bool(self.dmc.loop_flag);
361 writer.write_bool(self.dmc.irq_flag);
362 writer.write_u8(self.dmc.output_level);
363 writer.write_u16(self.dmc.sample_address);
364 writer.write_u16(self.dmc.sample_length);
365 writer.write_u16(self.dmc.current_address);
366 writer.write_u16(self.dmc.bytes_remaining);
367 writer.write_bool(self.dmc.silence);
368 writer.write_bool(self.apu_subclock_even);
369 }
370
371 pub fn load_state(&mut self, reader: &mut StateReader<'_>) -> Result<(), SaveStateError> {
372 self.pulse1.enabled = reader.read_u8()? != 0;
373 self.pulse1.length_counter = reader.read_u8()?;
374 self.pulse2.enabled = reader.read_u8()? != 0;
375 self.pulse2.length_counter = reader.read_u8()?;
376 self.triangle.enabled = reader.read_u8()? != 0;
377 self.triangle.length_counter = reader.read_u8()?;
378 self.noise.enabled = reader.read_u8()? != 0;
379 self.noise.length_counter = reader.read_u8()?;
380 self.frame_irq_inhibit = reader.read_bool()?;
381 self.frame_irq_flag = reader.read_bool()?;
382 self.frame_mode_five_step = reader.read_bool()?;
383 self.frame_step = reader.read_u8()?;
384 self.frame_divider = reader.read_u16()?;
385 self.dmc.enabled = reader.read_bool()?;
386 self.dmc.irq_enabled = reader.read_bool()?;
387 self.dmc.loop_flag = reader.read_bool()?;
388 self.dmc.irq_flag = reader.read_bool()?;
389 self.dmc.output_level = reader.read_u8()?;
390 self.dmc.sample_address = reader.read_u16()?;
391 self.dmc.sample_length = reader.read_u16()?;
392 self.dmc.current_address = reader.read_u16()?;
393 self.dmc.bytes_remaining = reader.read_u16()?;
394 self.dmc.silence = reader.read_bool()?;
395 self.apu_subclock_even = reader.read_bool()?;
396 self.pending_dmc_dma = None;
397 self.sample_accum_pulse = 0;
398 self.sample_accum_tri = 0;
399 self.sample_accum_noise = 0;
400 self.sample_accum_dmc = 0;
401 self.sample_accum_exp = 0;
402 self.sample_accum_count = 0;
403 Ok(())
404 }
405
406 fn write_status(&mut self, data: u8) {
407 self.pulse1.set_enabled((data & 0x01) != 0);
408 self.pulse2.set_enabled((data & 0x02) != 0);
409 self.triangle.set_enabled((data & 0x04) != 0);
410 self.noise.set_enabled((data & 0x08) != 0);
411 self.pending_dmc_dma = self.dmc.set_enabled((data & 0x10) != 0);
412 self.dmc.irq_flag = false;
413 }
414
415 fn write_frame_counter(&mut self, data: u8) {
416 self.frame_mode_five_step = (data & 0x80) != 0;
417 self.frame_irq_inhibit = (data & 0x40) != 0;
418 if self.frame_irq_inhibit {
419 self.frame_irq_flag = false;
420 }
421 self.frame_step = 0;
422 self.frame_divider = FRAME_SEQUENCER_DIVIDER + 8;
423
424 if self.frame_mode_five_step {
425 self.clock_quarter_frame();
426 self.clock_half_frame();
427 }
428 }
429
430 fn tick_frame_counter(&mut self) {
431 if self.frame_divider == 0 {
432 self.frame_divider = FRAME_SEQUENCER_DIVIDER;
433 self.clock_frame_step();
434 } else {
435 self.frame_divider -= 1;
436 }
437 }
438
439 fn clock_frame_step(&mut self) {
440 if !self.frame_mode_five_step {
441 self.clock_quarter_frame();
442 if self.frame_step == 1 || self.frame_step == 3 {
443 self.clock_half_frame();
444 }
445 if self.frame_step == 3 && !self.frame_irq_inhibit {
446 self.frame_irq_flag = true;
447 }
448 self.frame_step = (self.frame_step + 1) & 0x03;
449 return;
450 }
451
452 if self.frame_step != 3 {
453 self.clock_quarter_frame();
454 }
455 if self.frame_step == 1 || self.frame_step == 4 {
456 self.clock_half_frame();
457 }
458 self.frame_step = (self.frame_step + 1) % 5;
459 }
460
461 fn clock_quarter_frame(&mut self) {
462 self.pulse1.quarter_frame_tick();
463 self.pulse2.quarter_frame_tick();
464 self.triangle.quarter_frame_tick();
465 self.noise.quarter_frame_tick();
466 for chip in &mut self.expansions {
467 chip.clock_quarter_frame();
468 }
469 }
470
471 fn clock_half_frame(&mut self) {
472 self.pulse1.half_frame_tick();
473 self.pulse2.half_frame_tick();
474 self.triangle.half_frame_tick();
475 self.noise.half_frame_tick();
476 for chip in &mut self.expansions {
477 chip.clock_half_frame();
478 }
479 }
480}
481
482impl Default for APU {
483 fn default() -> Self {
484 Self::new()
485 }
486}
487
488#[cfg(test)]
489mod tests;