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