@tmustier/pi-nes 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/AGENTS.md +89 -1
  2. package/README.md +78 -49
  3. package/extensions/nes/config.ts +1 -18
  4. package/extensions/nes/index.ts +1 -21
  5. package/extensions/nes/native/nes-core/Cargo.lock +0 -2
  6. package/extensions/nes/native/nes-core/Cargo.toml +1 -1
  7. package/extensions/nes/native/nes-core/index.d.ts +5 -0
  8. package/extensions/nes/native/nes-core/index.node +0 -0
  9. package/extensions/nes/native/nes-core/native.d.ts +5 -0
  10. package/extensions/nes/native/nes-core/src/lib.rs +25 -0
  11. package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo-ok +1 -0
  12. package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo_vcs_info.json +5 -0
  13. package/extensions/nes/native/nes-core/vendor/nes_rust/.travis.yml +3 -0
  14. package/extensions/nes/native/nes-core/vendor/nes_rust/Cargo.toml +23 -0
  15. package/extensions/nes/native/nes-core/vendor/nes_rust/LICENSE +21 -0
  16. package/extensions/nes/native/nes-core/vendor/nes_rust/README.md +59 -0
  17. package/extensions/nes/native/nes-core/vendor/nes_rust/src/apu.rs +1114 -0
  18. package/extensions/nes/native/nes-core/vendor/nes_rust/src/audio.rs +6 -0
  19. package/extensions/nes/native/nes-core/vendor/nes_rust/src/button.rs +23 -0
  20. package/extensions/nes/native/nes-core/vendor/nes_rust/src/cpu.rs +2364 -0
  21. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_audio.rs +49 -0
  22. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_display.rs +47 -0
  23. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_input.rs +33 -0
  24. package/extensions/nes/native/nes-core/vendor/nes_rust/src/display.rs +10 -0
  25. package/extensions/nes/native/nes-core/vendor/nes_rust/src/input.rs +7 -0
  26. package/extensions/nes/native/nes-core/vendor/nes_rust/src/joypad.rs +86 -0
  27. package/extensions/nes/native/nes-core/vendor/nes_rust/src/lib.rs +168 -0
  28. package/extensions/nes/native/nes-core/vendor/nes_rust/src/mapper.rs +502 -0
  29. package/extensions/nes/native/nes-core/vendor/nes_rust/src/memory.rs +73 -0
  30. package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +1378 -0
  31. package/extensions/nes/native/nes-core/vendor/nes_rust/src/register.rs +560 -0
  32. package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +231 -0
  33. package/extensions/nes/nes-component.ts +3 -8
  34. package/extensions/nes/nes-core.ts +29 -9
  35. package/extensions/nes/paths.ts +40 -0
  36. package/extensions/nes/renderer.ts +53 -88
  37. package/package.json +1 -1
@@ -0,0 +1,1114 @@
1
+ use register::Register;
2
+ use audio::Audio;
3
+
4
+ /*
5
+ * Audio Processing Unit implementation. Consists of
6
+ * - Pulse 1/2 channel
7
+ * - Triangle channel
8
+ * - Noise channel
9
+ * - DMC channel
10
+ * Refer to https://wiki.nesdev.com/w/index.php/APU
11
+ */
12
+ pub struct Apu {
13
+ cycle: u32,
14
+ step: u16,
15
+
16
+ // CPU memory mapped sub units/registers
17
+
18
+ pulse1: ApuPulse, // 0x4000 - 0x4003
19
+ pulse2: ApuPulse, // 0x4004 - 0x4007
20
+ triangle: ApuTriangle, // 0x4008 - 0x400B
21
+ noise: ApuNoise, // 0x400C - 0x400F
22
+ dmc: ApuDmc, // 0x4010 - 0x4013
23
+ status: Register<u8>, // 0x4015
24
+ frame: ApuFrameRegister, // 0x4017
25
+
26
+ sample_period: u32,
27
+ frame_irq_active: bool,
28
+ dmc_irq_active: bool,
29
+ pub irq_interrupted: bool,
30
+
31
+ audio: Box<dyn Audio>
32
+ }
33
+
34
+ static LENGTH_TABLE: [u8; 32] = [
35
+ 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
36
+ 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
37
+ 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
38
+ 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
39
+ ];
40
+
41
+ impl Apu {
42
+ pub fn new(audio: Box<dyn Audio>) -> Self {
43
+ Apu {
44
+ cycle: 0,
45
+ step: 0,
46
+ pulse1: ApuPulse::new(ApuPulseChannel::Channel1),
47
+ pulse2: ApuPulse::new(ApuPulseChannel::Channel2),
48
+ triangle: ApuTriangle::new(),
49
+ noise: ApuNoise::new(),
50
+ dmc: ApuDmc::new(),
51
+ status: Register::<u8>::new(),
52
+ frame: ApuFrameRegister::new(),
53
+ sample_period: 1764000 / 44100, // @TODO: Fix me
54
+ frame_irq_active: false,
55
+ dmc_irq_active: false,
56
+ irq_interrupted: false,
57
+ audio: audio
58
+ }
59
+ }
60
+
61
+ pub fn bootup(&mut self) {
62
+ self.status.store(0x00);
63
+ }
64
+
65
+ pub fn reset(&mut self) {
66
+ self.status.store(0x00);
67
+ // @TODO: Implement properly
68
+ }
69
+
70
+ pub fn get_mut_audio(&mut self) -> &mut Box<dyn Audio> {
71
+ &mut self.audio
72
+ }
73
+
74
+ // Expects being called at CPU clock rate
75
+ pub fn step(&mut self, dmc_sample_data: u8) {
76
+ self.cycle += 1;
77
+
78
+ // Samping at sample rate timing
79
+ // @TODO Fix me, more precise timing
80
+
81
+ if (self.cycle % self.sample_period) == 0 {
82
+ self.sample();
83
+ }
84
+
85
+ // Timers
86
+ // Clocked on every CPU cycles for triangle and
87
+ // every two CPU cycles for others
88
+
89
+ if (self.cycle % 2) == 0 {
90
+ self.pulse1.drive_timer();
91
+ self.pulse2.drive_timer();
92
+ self.noise.drive_timer();
93
+ // @TODO: Add note
94
+ if self.dmc.drive_timer(dmc_sample_data) {
95
+ self.dmc_irq_active = true;
96
+ }
97
+ }
98
+
99
+ self.triangle.drive_timer();
100
+
101
+ // 240Hz Frame sequencer
102
+ // @TODO: Fix me, more precise timing
103
+
104
+ if (self.cycle % 7457) == 0 {
105
+ if self.frame.five_step_mode() {
106
+ // Five-step sequence
107
+ //
108
+ // 0 1 2 3 4 function
109
+ // ----------- -----------------------------
110
+ // - - - - - IRQ (if bit 6 is clear)
111
+ // l - l - - Length counter and sweep
112
+ // e e e e - Envelope and linear counter
113
+
114
+ if self.step < 4 {
115
+ self.pulse1.drive_envelope();
116
+ self.pulse2.drive_envelope();
117
+ self.triangle.drive_linear();
118
+ self.noise.drive_envelope();
119
+ }
120
+
121
+ if self.step == 0 || self.step == 2 {
122
+ self.pulse1.drive_length();
123
+ self.pulse1.drive_sweep();
124
+ self.pulse2.drive_length();
125
+ self.pulse2.drive_sweep();
126
+ self.triangle.drive_length();
127
+ self.noise.drive_length()
128
+ }
129
+
130
+ self.step = (self.step + 1) % 5;
131
+ } else {
132
+ // Four-step sequence
133
+ //
134
+ // 0 1 2 3 function
135
+ // --------- -----------------------------
136
+ // - - - f IRQ (if bit 6 is clear)
137
+ // - l - l Length counter and sweep
138
+ // e e e e Envelope and linear counter
139
+
140
+ self.pulse1.drive_envelope();
141
+ self.pulse2.drive_envelope();
142
+ self.triangle.drive_linear();
143
+ self.noise.drive_envelope();
144
+
145
+ if self.step == 1 || self.step == 3 {
146
+ self.pulse1.drive_length();
147
+ self.pulse1.drive_sweep();
148
+ self.pulse2.drive_length();
149
+ self.pulse2.drive_sweep();
150
+ self.triangle.drive_length();
151
+ self.noise.drive_length();
152
+ }
153
+
154
+ if self.step == 3 && !self.frame.irq_disabled() {
155
+ self.frame_irq_active = true;
156
+ }
157
+
158
+ // Seems like keep invoking IRQ once frame IRQ flag is on
159
+ // until IRQ flag is cleared or it's disabled...?
160
+
161
+ if self.frame_irq_active && !self.frame.irq_disabled() {
162
+ self.irq_interrupted = true;
163
+ }
164
+
165
+ self.step = (self.step + 1) % 4;
166
+ }
167
+
168
+ // @TODO: check sending IRQ timing
169
+ if self.dmc_irq_active {
170
+ self.irq_interrupted = true;
171
+ }
172
+ }
173
+ }
174
+
175
+ pub fn load_register(&mut self, address: u16) -> u8 {
176
+ match address {
177
+ 0x4015 => {
178
+ // Loading status register
179
+ //
180
+ // bit
181
+ // 7: DMC interrupt
182
+ // 6: Frame interrupt
183
+ // 4: DMC remaining bytes > 0
184
+ // 3: Noise length counter > 0
185
+ // 2: Triangle length couter > 0
186
+ // 1: Pulse2 length counter > 0
187
+ // 0: Pulse1 length counter > 0
188
+
189
+ let mut value = 0;
190
+
191
+ if self.dmc_irq_active {
192
+ value |= 0x80;
193
+ }
194
+
195
+ if self.frame_irq_active && !self.frame.irq_disabled() {
196
+ value |= 0x40;
197
+ }
198
+
199
+ if self.dmc.remaining_bytes_counter > 0 {
200
+ value |= 0x10;
201
+ }
202
+
203
+ if self.noise.length_counter > 0 {
204
+ value |= 0x08;
205
+ }
206
+
207
+ if self.triangle.length_counter > 0 {
208
+ value |= 0x04;
209
+ }
210
+
211
+ if self.pulse2.length_counter > 0 {
212
+ value |= 0x02;
213
+ }
214
+
215
+ if self.pulse1.length_counter > 0 {
216
+ value |= 0x01;
217
+ }
218
+
219
+ // Loading status register clears the frame IRQ flag
220
+
221
+ self.frame_irq_active = false;
222
+
223
+ value
224
+ },
225
+ _ => 0
226
+ }
227
+ }
228
+
229
+ pub fn store_register(&mut self, address: u16, value: u8) {
230
+ match address {
231
+ 0x4000..=0x4003 => self.pulse1.store_register(address, value),
232
+ 0x4004..=0x4007 => self.pulse2.store_register(address, value),
233
+ 0x4008..=0x400B => self.triangle.store_register(address, value),
234
+ 0x400C..=0x400F => self.noise.store_register(address, value),
235
+ 0x4010..=0x4013 => self.dmc.store_register(address, value),
236
+ 0x4015 => {
237
+ // Storing status register
238
+ //
239
+ // bit: Enable(1) / Disable(0)
240
+ // 4: DMC unit
241
+ // 3: Noise unit
242
+ // 2: Triangle unit
243
+ // 1: Pulse2 unit
244
+ // 0: Pulse1 unit
245
+ //
246
+ // Writing a zero to any of channel enables bits will
247
+ // set its length counter/remaining bytes to zero.
248
+
249
+ self.status.store(value);
250
+
251
+ self.dmc.set_enable((value & 0x10) == 0x10);
252
+ self.noise.set_enable((value & 0x8) == 0x8);
253
+ self.triangle.set_enable((value & 0x4) == 0x4);
254
+ self.pulse2.set_enable((value & 0x2) == 0x2);
255
+ self.pulse1.set_enable((value & 0x1) == 0x1);
256
+
257
+ // Storing status register clears the DMC interrupt flag
258
+
259
+ self.dmc_irq_active = false;
260
+ },
261
+ 0x4017 => {
262
+ // Storing frame counter register
263
+ self.frame.store(value);
264
+
265
+ // If interrupt inhibit flag is set, the frame IRQ flag is cleared.
266
+
267
+ if self.frame.irq_disabled() {
268
+ self.frame_irq_active = false;
269
+ }
270
+ },
271
+ _ => {}
272
+ };
273
+ }
274
+
275
+ // See cpu.step() for what the following two methods are for
276
+ // @TODO: A bit hacky. Simplify.
277
+
278
+ pub fn dmc_needs_cpu_memory_data(&self) -> bool {
279
+ (self.cycle % 2) == 1 && self.dmc.needs_cpu_memory_data()
280
+ }
281
+
282
+ pub fn dmc_sample_address(&self) -> u16 {
283
+ self.dmc.address_counter
284
+ }
285
+
286
+ fn sample(&mut self) {
287
+ // Calculates the audio output within the range of 0.0 to 1.0.
288
+ // Refer to https://wiki.nesdev.com/w/index.php/APU_Mixer
289
+
290
+ let pulse1 = self.pulse1.output() as f32;
291
+ let pulse2 = self.pulse2.output() as f32;
292
+ let triangle = self.triangle.output() as f32;
293
+ let noise = self.noise.output() as f32;
294
+ let dmc = self.dmc.output() as f32;
295
+
296
+ let mut pulse_out = 0.0;
297
+ let mut tnd_out = 0.0;
298
+
299
+ if pulse1 != 0.0 || pulse2 != 0.0 {
300
+ pulse_out = 95.88 / ((8128.0 / (pulse1 + pulse2)) + 100.0);
301
+ }
302
+
303
+ if triangle != 0.0 || noise != 0.0 || dmc != 0.0 {
304
+ tnd_out = 159.79 / (1.0 / (triangle / 8227.0 + noise / 12241.0 + dmc / 22638.0) + 100.0);
305
+ }
306
+
307
+ self.audio.push(pulse_out + tnd_out);
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Apu Pulse channel. Consists of
313
+ * - Timer
314
+ * - Length counter
315
+ * - Envelope
316
+ * - Sweep
317
+ */
318
+ struct ApuPulse {
319
+ channel: ApuPulseChannel,
320
+ register0: Register<u8>, // 0x4000, 0x4004
321
+ register1: Register<u8>, // 0x4001, 0x4005
322
+ register2: Register<u8>, // 0x4002, 0x4006
323
+ register3: Register<u8>, // 0x4003, 0x4007
324
+ enabled: bool,
325
+
326
+ timer_counter: u16,
327
+ timer_period: u16,
328
+ timer_sequence: u8,
329
+
330
+ envelope_start_flag: bool,
331
+ envelope_counter: u8,
332
+ envelope_decay_level_counter: u8,
333
+
334
+ length_counter: u8,
335
+
336
+ sweep_reload_flag: bool,
337
+ sweep_counter: u8
338
+ }
339
+
340
+ static DUTY_TABLE: [u8; 32] = [
341
+ 0, 1, 0, 0, 0, 0, 0, 0,
342
+ 0, 1, 1, 0, 0, 0, 0, 0,
343
+ 0, 1, 1, 1, 1, 0, 0, 0,
344
+ 1, 0, 0, 1, 1, 1, 1, 1
345
+ ];
346
+
347
+ enum ApuPulseChannel {
348
+ Channel1,
349
+ Channel2
350
+ }
351
+
352
+ impl ApuPulse {
353
+ fn new(channel: ApuPulseChannel) -> Self {
354
+ ApuPulse {
355
+ channel: channel,
356
+ register0: Register::<u8>::new(),
357
+ register1: Register::<u8>::new(),
358
+ register2: Register::<u8>::new(),
359
+ register3: Register::<u8>::new(),
360
+ enabled: false,
361
+ timer_counter: 0,
362
+ timer_period: 0,
363
+ timer_sequence: 0,
364
+ envelope_start_flag: true,
365
+ envelope_counter: 0,
366
+ envelope_decay_level_counter: 0,
367
+ length_counter: 0,
368
+ sweep_reload_flag: false,
369
+ sweep_counter: 0
370
+ }
371
+ }
372
+
373
+ fn store_register(&mut self, address: u16, value: u8) {
374
+ match address & 0x4003 {
375
+ 0x4000 => self.register0.store(value),
376
+ 0x4001 => {
377
+ self.register1.store(value);
378
+ self.sweep_reload_flag = true;
379
+ },
380
+ 0x4002 => {
381
+ self.register2.store(value);
382
+ self.timer_period = self.timer();
383
+ },
384
+ 0x4003 => {
385
+ self.register3.store(value);
386
+
387
+ // Side effects
388
+ // - If the enabled flag is set, the length counter is reloaded
389
+ // - The envelope is restarted
390
+ // - The sequencer is immediately restarted at the first value of the current
391
+ // sequence. The period divider is not reset.
392
+
393
+ if self.enabled {
394
+ self.length_counter = LENGTH_TABLE[self.length_counter_index() as usize];
395
+ }
396
+ self.timer_period = self.timer();
397
+ self.timer_sequence = 0;
398
+ self.envelope_start_flag = true;
399
+ },
400
+ _ => {} // @TODO: Throw an error?
401
+ };
402
+ }
403
+
404
+ fn set_enable(&mut self, enabled: bool) {
405
+ self.enabled = enabled;
406
+
407
+ // When the enabled bit is cleared (via $4015), the length counter is forced to 0
408
+
409
+ if !enabled {
410
+ self.length_counter = 0;
411
+ }
412
+ }
413
+
414
+ fn drive_timer(&mut self) {
415
+ if self.timer_counter > 0 {
416
+ self.timer_counter -= 1;
417
+ } else {
418
+ self.timer_counter = self.timer_period;
419
+ self.timer_sequence += 1;
420
+
421
+ // 8-step sequencer
422
+ if self.timer_sequence == 8 {
423
+ self.timer_sequence = 0
424
+ }
425
+ }
426
+ }
427
+
428
+ fn drive_length(&mut self) {
429
+ if !self.envelope_loop_enabled() && self.length_counter > 0 {
430
+ self.length_counter -= 1;
431
+ }
432
+ }
433
+
434
+ fn drive_envelope(&mut self) {
435
+ if self.envelope_start_flag {
436
+ self.envelope_counter = self.envelope_period();
437
+ self.envelope_decay_level_counter = 0xF;
438
+ self.envelope_start_flag = false;
439
+ return;
440
+ }
441
+
442
+ if self.envelope_counter > 0 {
443
+ self.envelope_counter -= 1;
444
+ } else {
445
+ self.envelope_counter = self.envelope_period();
446
+ if self.envelope_decay_level_counter > 0 {
447
+ self.envelope_decay_level_counter -= 1;
448
+ } else if self.envelope_decay_level_counter == 0 && self.envelope_loop_enabled() {
449
+ self.envelope_decay_level_counter = 0xF;
450
+ }
451
+ }
452
+ }
453
+
454
+ fn drive_sweep(&mut self) {
455
+ if self.sweep_counter == 0 &&
456
+ self.sweep_enabled() &&
457
+ self.sweep_shift_amount() != 0 &&
458
+ self.timer_period >= 8 &&
459
+ self.timer_period <= 0x7FF {
460
+
461
+ let change = self.timer_period >> self.sweep_shift_amount();
462
+
463
+ // In negated mode, Pulse 1 adds the ones' complement while
464
+ // Pulse 2 adds the twos' complement
465
+
466
+ self.timer_period += match self.negated_sweep() {
467
+ // @TODO: Fix me
468
+ true => match self.channel {
469
+ ApuPulseChannel::Channel1 => !change,
470
+ ApuPulseChannel::Channel2 => !change + 1
471
+ },
472
+ false => change
473
+ };
474
+ }
475
+
476
+ if self.sweep_reload_flag || self.sweep_counter == 0 {
477
+ self.sweep_reload_flag = false;
478
+ self.sweep_counter = self.sweep_period();
479
+ } else {
480
+ self.sweep_counter -= 1;
481
+ }
482
+ }
483
+
484
+ fn output(&self) -> u8 {
485
+ if self.length_counter == 0 ||
486
+ self.timer_period < 8 ||
487
+ self.timer_period > 0x7FF ||
488
+ DUTY_TABLE[(self.duty() * 8 + self.timer_sequence) as usize] == 0 {
489
+ return 0;
490
+ }
491
+
492
+ // 4-bit output
493
+ 0x0F & match self.envelope_disabled() {
494
+ true => self.envelope_period(),
495
+ false => self.envelope_decay_level_counter
496
+ }
497
+ }
498
+
499
+ fn duty(&self) -> u8 {
500
+ self.register0.load_bits(6, 2)
501
+ }
502
+
503
+ fn envelope_loop_enabled(&self) -> bool {
504
+ self.register0.is_bit_set(5)
505
+ }
506
+
507
+ fn envelope_disabled(&self) -> bool {
508
+ self.register0.is_bit_set(4)
509
+ }
510
+
511
+ fn envelope_period(&self) -> u8 {
512
+ self.register0.load_bits(0, 4)
513
+ }
514
+
515
+ fn sweep_enabled(&self) -> bool {
516
+ self.register1.is_bit_set(7)
517
+ }
518
+
519
+ fn sweep_period(&self) -> u8 {
520
+ self.register1.load_bits(4, 3)
521
+ }
522
+
523
+ fn negated_sweep(&self) -> bool {
524
+ self.register1.is_bit_set(3)
525
+ }
526
+
527
+ fn sweep_shift_amount(&self) -> u8 {
528
+ self.register1.load_bits(0, 3)
529
+ }
530
+
531
+ fn timer_low(&self) -> u8 {
532
+ self.register2.load()
533
+ }
534
+
535
+ fn timer_high(&self) -> u8 {
536
+ self.register3.load_bits(0, 3)
537
+ }
538
+
539
+ fn timer(&self) -> u16 {
540
+ ((self.timer_high() as u16) << 8) | self.timer_low() as u16
541
+ }
542
+
543
+ fn length_counter_index(&self) -> u8 {
544
+ self.register3.load_bits(3, 5)
545
+ }
546
+ }
547
+
548
+ /*
549
+ * Apu Triangle channel. Consists of
550
+ * - Timer
551
+ * - Length counter
552
+ * - Linear counter
553
+ */
554
+ struct ApuTriangle {
555
+ register0: Register<u8>, // 0x4008
556
+ register1: Register<u8>, // 0x4009
557
+ register2: Register<u8>, // 0x400A
558
+ register3: Register<u8>, // 0x400B
559
+ enabled: bool,
560
+
561
+ timer_counter: u16,
562
+ timer_sequence: u8,
563
+
564
+ length_counter: u8,
565
+
566
+ linear_reload_flag: bool,
567
+ linear_counter: u8
568
+ }
569
+
570
+ static SEQUENCE_TABLE: [u8; 32] = [
571
+ 15, 14, 13, 12, 11, 10, 9, 8,
572
+ 7, 6, 5, 4, 3, 2, 1, 0,
573
+ 0, 1, 2, 3, 4, 5, 6, 7,
574
+ 8, 9, 10, 11, 12, 13, 14, 15
575
+ ];
576
+
577
+ impl ApuTriangle {
578
+ fn new() -> Self {
579
+ ApuTriangle {
580
+ register0: Register::<u8>::new(),
581
+ register1: Register::<u8>::new(),
582
+ register2: Register::<u8>::new(),
583
+ register3: Register::<u8>::new(),
584
+ enabled: false,
585
+ timer_counter: 0,
586
+ timer_sequence: 0,
587
+ length_counter: 0,
588
+ linear_reload_flag: false,
589
+ linear_counter: 0
590
+ }
591
+ }
592
+
593
+ fn store_register(&mut self, address: u16, value: u8) {
594
+ match address {
595
+ 0x4008 => self.register0.store(value),
596
+ 0x4009 => self.register1.store(value),
597
+ 0x400A => self.register2.store(value),
598
+ 0x400B => {
599
+ self.register3.store(value);
600
+
601
+ // Side effects
602
+ // - If the enabled flag is set, the length counter is reloaded
603
+ // - Sets the linear counter reload flag
604
+ // - The sequencer is immediately restarted at the first value of the current
605
+ // sequence. The period divider is not reset.
606
+ if self.enabled {
607
+ self.length_counter = LENGTH_TABLE[self.length_counter_index() as usize];
608
+ }
609
+
610
+ self.linear_reload_flag = true;
611
+ },
612
+ _ => {} // @TODO: Throw an error?
613
+ };
614
+ }
615
+
616
+ fn set_enable(&mut self, enabled: bool) {
617
+ self.enabled = enabled;
618
+
619
+ // When the enabled bit is cleared (via $4015), the length counter is forced to 0
620
+
621
+ if !enabled {
622
+ self.length_counter = 0;
623
+ }
624
+ }
625
+
626
+ fn drive_timer(&mut self) {
627
+ if self.timer_counter > 0 {
628
+ self.timer_counter -= 1;
629
+ } else {
630
+ self.timer_counter = self.timer();
631
+
632
+ // The sequencer is clocked by the timer as long as
633
+ // both the linear counter and the length counter are nonzero.
634
+
635
+ if self.length_counter > 0 && self.linear_counter > 0 {
636
+ self.timer_sequence += 1;
637
+
638
+ // 32-step sequencer
639
+
640
+ if self.timer_sequence == 32 {
641
+ self.timer_sequence = 0;
642
+ }
643
+ }
644
+ }
645
+ }
646
+
647
+ fn drive_linear(&mut self) {
648
+ if self.linear_reload_flag {
649
+ self.linear_counter = self.linear_counter();
650
+ } else if self.linear_counter > 0 {
651
+ self.linear_counter -= 1;
652
+ }
653
+
654
+ if !self.length_counter_disabled() {
655
+ self.linear_reload_flag = false;
656
+ }
657
+ }
658
+
659
+ fn drive_length(&mut self) {
660
+ if !self.length_counter_disabled() && self.length_counter > 0 {
661
+ self.length_counter -= 1;
662
+ }
663
+ }
664
+
665
+ fn output(&self) -> u8 {
666
+ if !self.enabled ||
667
+ self.length_counter == 0 ||
668
+ self.linear_counter == 0 ||
669
+ self.timer() < 2 {
670
+ return 0;
671
+ }
672
+
673
+ // 4-bit output
674
+ return SEQUENCE_TABLE[self.timer_sequence as usize] & 0xF;
675
+ }
676
+
677
+ fn linear_counter(&self) -> u8 {
678
+ self.register0.load_bits(0, 7)
679
+ }
680
+
681
+ fn length_counter_disabled(&self) -> bool {
682
+ self.register0.is_bit_set(7)
683
+ }
684
+
685
+ fn timer_low(&self) -> u8 {
686
+ self.register2.load()
687
+ }
688
+
689
+ fn length_counter_index(&self) -> u8 {
690
+ self.register3.load_bits(3, 5)
691
+ }
692
+
693
+ fn timer_high(&self) -> u8 {
694
+ self.register3.load_bits(0, 3)
695
+ }
696
+
697
+ fn timer(&self) -> u16 {
698
+ ((self.timer_high() as u16) << 8) | self.timer_low() as u16
699
+ }
700
+ }
701
+
702
+ /*
703
+ * Apu Noise channel. Consists of
704
+ * - Timer
705
+ * - Length counter
706
+ * - Envelope
707
+ * - Linear feedback shift register
708
+ */
709
+ struct ApuNoise {
710
+ register0: Register<u8>, // 0x400C
711
+ register1: Register<u8>, // 0x400D
712
+ register2: Register<u8>, // 0x400E
713
+ register3: Register<u8>, // 0x400F
714
+
715
+ enabled: bool,
716
+
717
+ timer_counter: u16,
718
+ timer_period: u16,
719
+
720
+ envelope_start_flag: bool,
721
+ envelope_counter: u8,
722
+ envelope_decay_level_counter: u8,
723
+
724
+ length_counter: u8,
725
+
726
+ shift_register: u16 // 15-bit register
727
+ }
728
+
729
+ static NOISE_TIMER_TABLE: [u16; 16] = [
730
+ 0x004, 0x008, 0x010, 0x020,
731
+ 0x040, 0x060, 0x080, 0x0A0,
732
+ 0x0CA, 0x0FE, 0x17C, 0x1FC,
733
+ 0x2FA, 0x3F8, 0x7F2, 0xFE4
734
+ ];
735
+
736
+ impl ApuNoise {
737
+ fn new() -> Self {
738
+ ApuNoise {
739
+ register0: Register::<u8>::new(),
740
+ register1: Register::<u8>::new(),
741
+ register2: Register::<u8>::new(),
742
+ register3: Register::<u8>::new(),
743
+ enabled: false,
744
+ timer_counter: 0,
745
+ timer_period: 0,
746
+ envelope_start_flag: false,
747
+ envelope_counter: 0,
748
+ envelope_decay_level_counter: 0,
749
+ length_counter: 0,
750
+ shift_register: 1
751
+ }
752
+ }
753
+
754
+ fn store_register(&mut self, address: u16, value: u8) {
755
+ match address {
756
+ 0x400C => self.register0.store(value),
757
+ 0x400D => self.register1.store(value),
758
+ 0x400E => {
759
+ self.register2.store(value);
760
+ self.timer_period = NOISE_TIMER_TABLE[self.timer_index() as usize];
761
+ },
762
+ 0x400F => {
763
+ self.register3.store(value);
764
+
765
+ // Side effects
766
+ // - If the enabled flag is set, the length counter is reloaded
767
+ // - The envelope is restarted
768
+
769
+ if self.enabled {
770
+ self.length_counter = LENGTH_TABLE[self.length_counter_index() as usize];
771
+ }
772
+
773
+ self.envelope_start_flag = true;
774
+ },
775
+ _ => {} // @TODO: Throw an error?
776
+ };
777
+ }
778
+
779
+ fn set_enable(&mut self, enabled: bool) {
780
+ self.enabled = enabled;
781
+
782
+ // When the enabled bit is cleared (via $4015), the length counter is forced to 0
783
+
784
+ if !enabled {
785
+ self.length_counter = 0;
786
+ }
787
+ }
788
+
789
+
790
+ fn drive_timer(&mut self) {
791
+ if self.timer_counter > 0 {
792
+ self.timer_counter -= 1;
793
+ } else {
794
+ self.timer_counter = self.timer_period;
795
+
796
+ // Feedback is calculated as the exclusive-OR of bit 0
797
+ // and another bit: bit 6 if Mode flag is set, otherwise bit 1.
798
+
799
+ let feedback = (self.shift_register & 1) ^
800
+ (((self.shift_register >> match self.is_random() { true => 6, false => 1 })) & 1);
801
+
802
+ self.shift_register = ((feedback as u16) << 14) | (self.shift_register >> 1);
803
+ }
804
+ }
805
+
806
+ fn drive_envelope(&mut self) {
807
+ if self.envelope_start_flag {
808
+ self.envelope_counter = self.envelope_period();
809
+ self.envelope_decay_level_counter = 0xF;
810
+ self.envelope_start_flag = false;
811
+ return;
812
+ }
813
+
814
+ if self.envelope_counter > 0 {
815
+ self.envelope_counter -= 1;
816
+ } else {
817
+ self.envelope_counter = self.envelope_period();
818
+
819
+ if self.envelope_decay_level_counter > 0 {
820
+ self.envelope_decay_level_counter -= 1;
821
+ } else if self.envelope_decay_level_counter == 0 &&
822
+ self.length_counter_disabled() {
823
+ self.envelope_decay_level_counter = 0xF;
824
+ }
825
+ }
826
+ }
827
+
828
+ fn drive_length(&mut self) {
829
+ if !self.length_counter_disabled() && self.length_counter > 0 {
830
+ self.length_counter -= 1;
831
+ }
832
+ }
833
+
834
+ fn output(&self) -> u8 {
835
+ if self.length_counter == 0 ||
836
+ (self.shift_register & 1) == 1 {
837
+ return 0;
838
+ }
839
+
840
+ // 4-bit output
841
+ 0x0F & match self.envelope_disabled() {
842
+ true => self.envelope_period(),
843
+ false => self.envelope_decay_level_counter
844
+ }
845
+ }
846
+
847
+ fn length_counter_disabled(&self) -> bool {
848
+ self.register0.is_bit_set(5)
849
+ }
850
+
851
+ fn envelope_disabled(&self) -> bool {
852
+ self.register0.is_bit_set(4)
853
+ }
854
+
855
+ fn envelope_period(&self) -> u8 {
856
+ self.register0.load_bits(0, 4)
857
+ }
858
+
859
+ fn is_random(&self) -> bool {
860
+ self.register2.is_bit_set(7)
861
+ }
862
+
863
+ fn timer_index(&self) -> u8 {
864
+ self.register2.load_bits(0, 4)
865
+ }
866
+
867
+ fn length_counter_index(&self) -> u8 {
868
+ self.register3.load_bits(3, 5)
869
+ }
870
+ }
871
+
872
+ /*
873
+ * Apu DMC channel. Consists of
874
+ * - Timer
875
+ * - Memory reader
876
+ * - Sample buffer
877
+ * - Output unit
878
+ */
879
+ struct ApuDmc {
880
+ register0: Register<u8>, // 0x4010
881
+ register1: Register<u8>, // 0x4011
882
+ register2: Register<u8>, // 0x4012
883
+ register3: Register<u8>, // 0x4013
884
+
885
+ enabled: bool,
886
+
887
+ timer_period: u16,
888
+ timer_counter: u16,
889
+
890
+ delta_counter: u8,
891
+ address_counter: u16,
892
+ remaining_bytes_counter: u16,
893
+
894
+ sample_buffer: u8,
895
+ sample_buffer_is_empty: bool,
896
+
897
+ shift_register: u8,
898
+ remaining_bits_counter: u8,
899
+
900
+ silence_flag: bool
901
+ }
902
+
903
+ static DMC_TIMER_TABLE: [u16; 16] = [
904
+ 0x1AC, 0x17C, 0x154, 0x140,
905
+ 0x11E, 0x0FE, 0x0E2, 0x0D6,
906
+ 0x0BE, 0x0A0, 0x08E, 0x080,
907
+ 0x06A, 0x054, 0x048, 0x036
908
+ ];
909
+
910
+ impl ApuDmc {
911
+ fn new() -> Self {
912
+ ApuDmc {
913
+ register0: Register::<u8>::new(),
914
+ register1: Register::<u8>::new(),
915
+ register2: Register::<u8>::new(),
916
+ register3: Register::<u8>::new(),
917
+ enabled: false,
918
+ timer_period: 0,
919
+ timer_counter: 0,
920
+ delta_counter: 0,
921
+ address_counter: 0,
922
+ remaining_bytes_counter: 0,
923
+ sample_buffer: 0,
924
+ sample_buffer_is_empty: true,
925
+ shift_register: 0,
926
+ remaining_bits_counter: 0,
927
+ silence_flag: true
928
+ }
929
+ }
930
+
931
+ fn store_register(&mut self, address: u16, value: u8) {
932
+ match address {
933
+ 0x4010 => {
934
+ self.register0.store(value);
935
+ self.timer_period = DMC_TIMER_TABLE[self.timer_index() as usize] >> 1;
936
+ },
937
+ 0x4011 => {
938
+ self.register1.store(value);
939
+ self.delta_counter = self.delta_counter();
940
+ },
941
+ 0x4012 => {
942
+ self.register2.store(value);
943
+ self.address_counter = ((self.sample_address() as u16) << 6) | 0xC000;
944
+ },
945
+ 0x4013 => {
946
+ self.register3.store(value);
947
+ self.remaining_bytes_counter = ((self.sample_length() as u16) << 4) | 1;
948
+ },
949
+ _ => {} // @TODO
950
+ }
951
+ }
952
+
953
+ fn set_enable(&mut self, enabled: bool) {
954
+ self.enabled = enabled;
955
+
956
+ // If DMC enable flag is set via 0x4015,
957
+ // the DMC sample will be restarted only if its remaining bytes is 0.
958
+
959
+ if enabled {
960
+ if self.remaining_bytes_counter == 0 {
961
+ self.start();
962
+ }
963
+ } else {
964
+ self.remaining_bytes_counter = 0;
965
+ }
966
+ }
967
+
968
+ fn start(&mut self) {
969
+ self.delta_counter = self.delta_counter();
970
+ self.address_counter = ((self.sample_address() as u16) << 6) | 0xC000;
971
+ self.remaining_bytes_counter = ((self.sample_length() as u16) << 4) | 1;
972
+ }
973
+
974
+ // See cpu.step() for what this method is for
975
+ // @TODO: Solution to remove this workaround
976
+ fn needs_cpu_memory_data(&self) -> bool {
977
+ self.timer_counter == 0 &&
978
+ self.remaining_bytes_counter > 0 &&
979
+ self.sample_buffer_is_empty
980
+ }
981
+
982
+ fn drive_timer(&mut self, sample_data: u8) -> bool {
983
+ let mut irq_active = false;
984
+ if self.timer_counter > 0 {
985
+ self.timer_counter -= 1;
986
+ } else {
987
+ self.timer_counter = self.timer_period;
988
+
989
+ // Memory reader
990
+
991
+ if self.remaining_bytes_counter > 0 && self.sample_buffer_is_empty {
992
+ self.sample_buffer = sample_data;
993
+
994
+ // if address exceeds 0xFFFF, it is wrapped around to 0x8000.
995
+ self.address_counter = match self.address_counter {
996
+ 0xFFFF => 0x8000,
997
+ _ => self.address_counter + 1
998
+ };
999
+
1000
+ self.sample_buffer_is_empty = false;
1001
+
1002
+ // If the bytes remaining counter becomes zero
1003
+ // - the sample is restarted if the loop flag is set
1004
+ // - otherwise, the interrupt flag is set if IRQ enabled flag is set
1005
+
1006
+ self.remaining_bytes_counter -= 1;
1007
+
1008
+ if self.remaining_bytes_counter == 0 {
1009
+ if self.is_loop() {
1010
+ self.start();
1011
+ } else if self.irq_enabled() {
1012
+ irq_active = true;
1013
+ }
1014
+ }
1015
+ }
1016
+
1017
+ // Output unit
1018
+
1019
+ if self.remaining_bits_counter == 0 {
1020
+ self.remaining_bits_counter = 8;
1021
+ if self.sample_buffer_is_empty {
1022
+ self.silence_flag = true;
1023
+ } else {
1024
+ self.silence_flag = false;
1025
+ self.sample_buffer_is_empty = true;
1026
+ self.shift_register = self.sample_buffer;
1027
+ self.sample_buffer = 0;
1028
+ }
1029
+ }
1030
+
1031
+ if !self.silence_flag {
1032
+ if (self.shift_register & 1) == 0 {
1033
+ if self.delta_counter > 1 {
1034
+ self.delta_counter -= 2;
1035
+ }
1036
+ } else {
1037
+ if self.delta_counter < 126 {
1038
+ self.delta_counter += 2;
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ // The bits-remaining counter is updated whenever the timer outputs a clock
1044
+ self.remaining_bits_counter -= 1;
1045
+ self.shift_register = self.shift_register >> 1;
1046
+ }
1047
+
1048
+ irq_active
1049
+ }
1050
+
1051
+ fn output(&self) -> u8 {
1052
+ // Seems like we should ignore enable bit set via 0x4015
1053
+ // (or no enable bit in DMC unit?)
1054
+
1055
+ // if !self.enabled {
1056
+ // return 0;
1057
+ // }
1058
+
1059
+ if self.silence_flag {
1060
+ return 0;
1061
+ }
1062
+
1063
+ // 7-bit output
1064
+ self.delta_counter & 0x7F
1065
+ }
1066
+
1067
+ fn irq_enabled(&self) -> bool {
1068
+ self.register0.is_bit_set(7)
1069
+ }
1070
+
1071
+ fn is_loop(&self) -> bool {
1072
+ self.register0.is_bit_set(6)
1073
+ }
1074
+
1075
+ fn timer_index(&self) -> u8 {
1076
+ self.register0.load_bits(0, 4)
1077
+ }
1078
+
1079
+ fn delta_counter(&self) -> u8 {
1080
+ self.register1.load_bits(0, 7)
1081
+ }
1082
+
1083
+ fn sample_address(&self) -> u8 {
1084
+ self.register2.load()
1085
+ }
1086
+
1087
+ fn sample_length(&self) -> u8 {
1088
+ self.register3.load()
1089
+ }
1090
+ }
1091
+
1092
+ struct ApuFrameRegister {
1093
+ register: Register<u8>
1094
+ }
1095
+
1096
+ impl ApuFrameRegister {
1097
+ fn new() -> Self {
1098
+ ApuFrameRegister {
1099
+ register: Register::<u8>::new()
1100
+ }
1101
+ }
1102
+
1103
+ fn store(&mut self, value: u8) {
1104
+ self.register.store(value);
1105
+ }
1106
+
1107
+ fn five_step_mode(&self) -> bool {
1108
+ self.register.is_bit_set(7)
1109
+ }
1110
+
1111
+ fn irq_disabled(&mut self) -> bool {
1112
+ self.register.is_bit_set(6)
1113
+ }
1114
+ }