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