1use super::seq::{FrameSequencer, Event};
8use super::chnl::{SoundChannel, Pulse, Triangle, Noise, Dmc, LengthCounterUnit, EnvelopeUnit, NegateAddMode};
9
10use crate::common::{IoAccess, IoAccessRef, Clockable, Register, Interrupt};
11
12pub type Sample = f32;
13pub const APU_OUTPUT_RATE: f32 = 895_000.0;
14
15#[cfg(feature="events")]
16use std::sync::mpsc::Sender;
17
18#[cfg(feature="events")]
19pub mod events {
20 #[derive(Debug)]
21 pub struct ApuEvent {
22 pub pulse1: f32,
23 pub pulse2: f32,
24 pub triangle: f32,
25 pub noise: f32,
26 pub dmc: f32,
27 pub mixer: f32,
28 }
29}
30
31pub struct Apu {
33 pulse1: Pulse,
34 pulse2: Pulse,
35 triangle: Triangle,
36 noise: Noise,
37 dmc: Dmc,
38
39 sequencer: FrameSequencer,
40
41 pulse_table: [f32; 31],
42 tnd_table: [f32; 203],
43
44 bus: Option<IoAccessRef>,
45
46 #[cfg(feature="events")]
48 logger: Option<Sender<events::ApuEvent>>,
49}
50
51impl Default for Apu {
52 fn default() -> Self {
53 let mut pulse_table = [0f32; 31];
58 for (n, e) in pulse_table.iter_mut().enumerate() {
59 *e = 95.52 / (8128.0 / (n as f32) + 100f32);
60 }
61
62 let mut tnd_table = [0f32; 203];
64 for (n, e) in tnd_table.iter_mut().enumerate() {
65 *e = 163.67 / (24329.0 / (n as f32) + 100f32);
66 }
67
68 Apu {
69 pulse1: Pulse::default(),
70 pulse2: Pulse::default().add_mode(NegateAddMode::TwosComplement),
71 triangle: Triangle::default(),
72 noise: Noise::default(),
73 dmc: Dmc::default(),
74
75 sequencer: FrameSequencer::default(),
76
77 pulse_table,
79 tnd_table,
80
81 bus: None,
82
83 #[cfg(feature="events")]
84 logger: None,
85 }
86 }
87}
88
89impl Clockable<Sample> for Apu {
90 fn tick(&mut self) -> Sample {
91 for event in self.sequencer.tick().iter() {
93 match event {
94 Event::EnvelopAndLinear => {
95 self.clock_envelope();
96 self.triangle.clock_linear();
97 },
98 Event::LengthAndSweep => {
99 self.clock_length();
100 self.clock_sweep();
101 },
102 Event::Irq => {
103 if let Some(ref mut bus) = self.bus {
104 bus.borrow_mut().raise_interrupt(Interrupt::Irq);
105 }
106 },
107 Event::None => {}
108 }
109 }
110
111 self.pulse1.tick();
113 self.pulse2.tick();
114
115 self.triangle.tick();
117 self.triangle.tick();
118
119 self.noise.tick();
121
122 self.dmc.tick();
124
125 self.mix()
127 }
128}
129
130impl IoAccess for Apu {
131 fn read_byte(&self, addr: u16) -> u8 {
132 match addr {
133 0x4000..=0x4003 => self.pulse1.read_byte(addr - 0x4000),
134 0x4004..=0x4007 => self.pulse2.read_byte(addr - 0x4004),
135 0x4008..=0x400B => self.triangle.read_byte(addr - 0x4008),
136 0x400C..=0x400F => self.noise.read_byte(addr - 0x400C),
137 0x4010..=0x4013 => self.dmc.read_byte(addr - 0x4010),
138 0x4015 => self.status(),
139 0x4017 => self.sequencer.value(),
140 _ => panic!("Invalid address for APU: ${:04X}", addr),
141 }
142 }
143
144 fn write_byte(&mut self, addr: u16, data: u8) {
145 match addr {
146 0x4000..=0x4003 => self.pulse1.write_byte(addr - 0x4000, data),
147 0x4004..=0x4007 => self.pulse2.write_byte(addr - 0x4004, data),
148 0x4008..=0x400B => self.triangle.write_byte(addr - 0x4008, data),
149 0x400C..=0x400F => self.noise.write_byte(addr - 0x400C, data),
150 0x4010..=0x4013 => self.dmc.write_byte(addr - 0x4010, data),
151 0x4015 => {
152 self.pulse1.enable_length(bit_is_set!(data, 0));
153 self.pulse2.enable_length(bit_is_set!(data, 1));
154 self.triangle.enable_length(bit_is_set!(data, 2));
155 self.noise.enable_length(bit_is_set!(data, 3));
156 self.dmc.set_enable(bit_is_set!(data, 4));
157 },
158 0x4017 => {
159 self.sequencer.load(data);
160
161 if bit_is_set!(data, 7) {
162 self.pulse1.clock_length();
164 self.pulse2.clock_length();
165 self.triangle.clock_length();
166 self.noise.clock_length();
167 }
168 },
169 _ => panic!("Invalid address for APU: ${:04X}", addr),
170 }
171 }
172}
173
174impl Apu {
175 fn mix(&self) -> Sample {
176 let pulse1 = self.pulse1.output() as f32;
177 let pulse2 = self.pulse2.output() as f32;
178 let triangle = self.triangle.output() as f32;
179 let noise = self.noise.output() as f32;
180 let dmc = self.dmc.output() as f32;
181
182 let pulse_out = self.pulse_table[(pulse1 + pulse2) as usize];
183
184 let tnd_out = self.tnd_table[(3.0 * triangle + 2.0 * noise + dmc) as usize];
185
186 let mixed = pulse_out + tnd_out;
187
188 #[cfg(feature="events")]
189 {
190 let data = events::ApuEvent {
191 pulse1,
192 pulse2,
193 triangle,
194 noise,
195 dmc,
196 mixer: mixed,
197 };
198
199 if let Some(ref logger) = self.logger {
200 if logger.send(data).is_ok() {}
201 }
202 }
203
204 mixed
205 }
206
207 fn status(&self) -> u8 {
208 (self.pulse1.length_status() as u8)
209 | (self.pulse2.length_status() as u8) << 1
210 | (self.triangle.length_status() as u8) << 2
211 | (self.noise.length_status() as u8) << 3
212 | (self.dmc.status() as u8) << 4
213 | (self.sequencer.irq_status() as u8) << 6
214 }
215
216 fn clock_length(&mut self) {
217 self.pulse1.clock_length();
218 self.pulse2.clock_length();
219 self.triangle.clock_length();
220 self.noise.clock_length();
221 }
222
223 fn clock_envelope(&mut self) {
224 self.pulse1.clock_envelope();
225 self.pulse2.clock_envelope();
226 self.noise.clock_envelope();
227 }
228
229 fn clock_sweep(&mut self) {
230 self.pulse1.clock_sweep();
231 self.pulse2.clock_sweep();
232 }
233
234 pub fn load_bus(&mut self, bus: IoAccessRef) {
235 self.dmc.load_bus(bus.clone());
236 self.bus = Some(bus);
237 }
238
239 #[cfg(feature="events")]
240 pub fn set_event_sender(&mut self, sender: Sender<events::ApuEvent>) {
241 self.logger = Some(sender);
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::*;
248
249 use std::rc::Rc;
250 use std::cell::RefCell;
251
252 #[test]
253 fn pulse_lenctr() {
254 let mut apu = init_apu();
255
256 apu.write_byte(0x4017, 0x00);
258
259 apu.write_byte(0x4015, 0x03);
261 apu.write_byte(0x4003, 0x00);
263 apu.write_byte(0x4007, 0x00);
264
265 let status = apu.read_byte(0x4015);
267 assert!(bit_is_set!(status, 0));
268 assert!(bit_is_set!(status, 1));
269
270 for _ in 0..4 {
273 run_for_step4_frame(&mut apu);
274 }
275
276 let status = apu.read_byte(0x4015);
278 assert!(bit_is_set!(status, 0));
279 assert!(bit_is_set!(status, 1));
280
281 run_for_step4_frame(&mut apu);
284
285 let status = apu.read_byte(0x4015);
286 assert!(bit_is_clear!(status, 0));
287 assert!(bit_is_clear!(status, 1));
288 }
289
290 fn run_for_step4_frame(apu: &mut dyn Clockable<Sample>) {
291 for _ in 0..14915 {
292 apu.tick();
293 }
294 }
295
296 struct FakeBus {
297 vram: [u8; 0x4000],
298 }
299
300 impl Default for FakeBus {
301 fn default() -> Self {
302 FakeBus {
303 vram: [0; 0x4000],
304 }
305 }
306 }
307
308 impl IoAccess for FakeBus {
309 fn read_byte(&self, addr: u16) -> u8 {
310 self.vram[addr as usize]
311 }
312 fn write_byte(&mut self, addr: u16, value: u8) {
313 self.vram[addr as usize] = value;
314 }
315 }
316
317 fn init_apu() -> Apu {
318 let mut apu: Apu = Apu::default();
319 apu.load_bus(Rc::new(RefCell::new(FakeBus::default())));
320
321 apu
322 }
323}