1 // Nes_Snd_Emu $vers. http://www.slack.net/~ant/
2
3 #include "Nes_Apu.h"
4
5 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6 can redistribute it and/or modify it under the terms of the GNU Lesser
7 General Public License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version. This
9 module is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 details. You should have received a copy of the GNU Lesser General Public
13 License along with this module; if not, write to the Free Software Foundation,
14 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16 #include "blargg_source.h"
17
18 // Nes_Osc
19
clock_length(int halt_mask)20 void Nes_Osc::clock_length( int halt_mask )
21 {
22 if ( length_counter && !(regs [0] & halt_mask) )
23 length_counter--;
24 }
25
clock_envelope()26 void Nes_Envelope::clock_envelope()
27 {
28 int period = regs [0] & 15;
29 if ( reg_written [3] )
30 {
31 reg_written [3] = false;
32 env_delay = period;
33 envelope = 15;
34 }
35 else if ( --env_delay < 0 )
36 {
37 env_delay = period;
38 if ( envelope | (regs [0] & 0x20) )
39 envelope = (envelope - 1) & 15;
40 }
41 }
42
volume() const43 int Nes_Envelope::volume() const
44 {
45 return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
46 }
47
48 // Nes_Square
49
clock_sweep(int negative_adjust)50 void Nes_Square::clock_sweep( int negative_adjust )
51 {
52 int sweep = regs [1];
53
54 if ( --sweep_delay < 0 )
55 {
56 reg_written [1] = true;
57
58 int period = this->period();
59 int shift = sweep & shift_mask;
60 if ( shift && (sweep & 0x80) && period >= 8 )
61 {
62 int offset = period >> shift;
63
64 if ( sweep & negate_flag )
65 offset = negative_adjust - offset;
66
67 if ( period + offset < 0x800 )
68 {
69 period += offset;
70 // rewrite period
71 regs [2] = period & 0xFF;
72 regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
73 }
74 }
75 }
76
77 if ( reg_written [1] )
78 {
79 reg_written [1] = false;
80 sweep_delay = (sweep >> 4) & 7;
81 }
82 }
83
84 // TODO: clean up
maintain_phase(nes_time_t time,nes_time_t end_time,nes_time_t timer_period)85 inline Nes_Square::nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_time,
86 nes_time_t timer_period )
87 {
88 nes_time_t remain = end_time - time;
89 if ( remain > 0 )
90 {
91 int count = (remain + timer_period - 1) / timer_period;
92 phase = (phase + count) & (phase_range - 1);
93 time += count * timer_period;
94 }
95 return time;
96 }
97
run(nes_time_t time,nes_time_t end_time)98 void Nes_Square::run( nes_time_t time, nes_time_t end_time )
99 {
100 const int period = this->period();
101 const int timer_period = (period + 1) * 2;
102
103 if ( !output )
104 {
105 delay = maintain_phase( time + delay, end_time, timer_period ) - end_time;
106 return;
107 }
108
109 int offset = period >> (regs [1] & shift_mask);
110 if ( regs [1] & negate_flag )
111 offset = 0;
112
113 const int volume = this->volume();
114 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
115 {
116 if ( last_amp )
117 {
118 output->set_modified();
119 synth.offset( time, -last_amp, output );
120 last_amp = 0;
121 }
122
123 time += delay;
124 time = maintain_phase( time, end_time, timer_period );
125 }
126 else
127 {
128 // handle duty select
129 int duty_select = (regs [0] >> 6) & 3;
130 int duty = 1 << duty_select; // 1, 2, 4, 2
131 int amp = 0;
132 if ( duty_select == 3 )
133 {
134 duty = 2; // negated 25%
135 amp = volume;
136 }
137 if ( phase < duty )
138 amp ^= volume;
139
140 output->set_modified();
141 {
142 int delta = update_amp( amp );
143 if ( delta )
144 synth.offset( time, delta, output );
145 }
146
147 time += delay;
148 if ( time < end_time )
149 {
150 Blip_Buffer* const output = this->output;
151 const Synth& synth = this->synth;
152 int delta = amp * 2 - volume;
153 int phase = this->phase;
154
155 do
156 {
157 phase = (phase + 1) & (phase_range - 1);
158 if ( phase == 0 || phase == duty )
159 {
160 delta = -delta;
161 synth.offset_inline( time, delta, output );
162 }
163 time += timer_period;
164 }
165 while ( time < end_time );
166
167 last_amp = (delta + volume) >> 1;
168 this->phase = phase;
169 }
170 }
171
172 delay = time - end_time;
173 }
174
175 // Nes_Triangle
176
clock_linear_counter()177 void Nes_Triangle::clock_linear_counter()
178 {
179 if ( reg_written [3] )
180 linear_counter = regs [0] & 0x7F;
181 else if ( linear_counter )
182 linear_counter--;
183
184 if ( !(regs [0] & 0x80) )
185 reg_written [3] = false;
186 }
187
calc_amp() const188 inline int Nes_Triangle::calc_amp() const
189 {
190 int amp = phase_range - phase;
191 if ( amp < 0 )
192 amp = phase - (phase_range + 1);
193 return amp;
194 }
195
196 // TODO: clean up
maintain_phase(nes_time_t time,nes_time_t end_time,nes_time_t timer_period)197 inline Nes_Square::nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_time,
198 nes_time_t timer_period )
199 {
200 nes_time_t remain = end_time - time;
201 if ( remain > 0 )
202 {
203 int count = (remain + timer_period - 1) / timer_period;
204 phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
205 phase++;
206 time += count * timer_period;
207 }
208 return time;
209 }
210
run(nes_time_t time,nes_time_t end_time)211 void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
212 {
213 const int timer_period = period() + 1;
214 if ( !output )
215 {
216 time += delay;
217 delay = 0;
218 if ( length_counter && linear_counter && timer_period >= 3 )
219 delay = maintain_phase( time, end_time, timer_period ) - end_time;
220 return;
221 }
222
223 // to do: track phase when period < 3
224 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
225
226 int delta = update_amp( calc_amp() );
227 if ( delta )
228 {
229 output->set_modified();
230 synth.offset( time, delta, output );
231 }
232
233 time += delay;
234 if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
235 {
236 time = end_time;
237 }
238 else if ( time < end_time )
239 {
240 Blip_Buffer* const output = this->output;
241
242 int phase = this->phase;
243 int volume = 1;
244 if ( phase > phase_range )
245 {
246 phase -= phase_range;
247 volume = -volume;
248 }
249 output->set_modified();
250
251 do
252 {
253 if ( --phase == 0 )
254 {
255 phase = phase_range;
256 volume = -volume;
257 }
258 else
259 {
260 synth.offset_inline( time, volume, output );
261 }
262
263 time += timer_period;
264 }
265 while ( time < end_time );
266
267 if ( volume < 0 )
268 phase += phase_range;
269 this->phase = phase;
270 last_amp = calc_amp();
271 }
272 delay = time - end_time;
273 }
274
275 // Nes_Dmc
276
reset()277 void Nes_Dmc::reset()
278 {
279 address = 0;
280 dac = 0;
281 buf = 0;
282 bits_remain = 1;
283 bits = 0;
284 buf_full = false;
285 silence = true;
286 next_irq = Nes_Apu::no_irq;
287 irq_flag = false;
288 irq_enabled = false;
289
290 Nes_Osc::reset();
291 period = 0x1AC;
292 }
293
recalc_irq()294 void Nes_Dmc::recalc_irq()
295 {
296 nes_time_t irq = Nes_Apu::no_irq;
297 if ( irq_enabled && length_counter )
298 irq = apu->last_dmc_time + delay +
299 ((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t (period) + 1;
300 if ( irq != next_irq )
301 {
302 next_irq = irq;
303 apu->irq_changed();
304 }
305 }
306
count_reads(nes_time_t time,nes_time_t * last_read) const307 int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
308 {
309 if ( last_read )
310 *last_read = time;
311
312 if ( length_counter == 0 )
313 return 0; // not reading
314
315 nes_time_t first_read = next_read_time();
316 nes_time_t avail = time - first_read;
317 if ( avail <= 0 )
318 return 0;
319
320 int count = (avail - 1) / (period * 8) + 1;
321 if ( !(regs [0] & loop_flag) && count > length_counter )
322 count = length_counter;
323
324 if ( last_read )
325 {
326 *last_read = first_read + (count - 1) * (period * 8) + 1;
327 check( *last_read <= time );
328 check( count == count_reads( *last_read, NULL ) );
329 check( count - 1 == count_reads( *last_read - 1, NULL ) );
330 }
331
332 return count;
333 }
334
335 static short const dmc_period_table [2] [16] = {
336 {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
337 190, 160, 142, 128, 106, 84, 72, 54},
338
339 {398, 354, 316, 298, 276, 236, 210, 198, // PAL
340 176, 148, 132, 118, 98, 78, 66, 50}
341 };
342
reload_sample()343 inline void Nes_Dmc::reload_sample()
344 {
345 address = 0x4000 + regs [2] * 0x40;
346 length_counter = regs [3] * 0x10 + 1;
347 }
348
349 static int const dmc_table [128] =
350 {
351 0, 24, 48, 71, 94, 118, 141, 163, 186, 209, 231, 253, 275, 297, 319, 340,
352 361, 383, 404, 425, 445, 466, 486, 507, 527, 547, 567, 587, 606, 626, 645, 664,
353 683, 702, 721, 740, 758, 777, 795, 813, 832, 850, 867, 885, 903, 920, 938, 955,
354 972, 989,1006,1023,1040,1056,1073,1089,1105,1122,1138,1154,1170,1185,1201,1217,
355 1232,1248,1263,1278,1293,1308,1323,1338,1353,1368,1382,1397,1411,1425,1440,1454,
356 1468,1482,1496,1510,1523,1537,1551,1564,1578,1591,1604,1618,1631,1644,1657,1670,
357 1683,1695,1708,1721,1733,1746,1758,1771,1783,1795,1807,1819,1831,1843,1855,1867,
358 1879,1890,1902,1914,1925,1937,1948,1959,1971,1982,1993,2004,2015,2026,2037,2048,
359 };
360
update_amp_nonlinear(int in)361 inline int Nes_Dmc::update_amp_nonlinear( int in )
362 {
363 if ( !nonlinear )
364 in = dmc_table [in];
365 int delta = in - last_amp;
366 last_amp = in;
367 return delta;
368 }
369
write_register(int addr,int data)370 void Nes_Dmc::write_register( int addr, int data )
371 {
372 if ( addr == 0 )
373 {
374 period = dmc_period_table [pal_mode] [data & 15];
375 irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
376 irq_flag &= irq_enabled;
377 recalc_irq();
378 }
379 else if ( addr == 1 )
380 {
381 dac = data & 0x7F;
382 }
383 }
384
start()385 void Nes_Dmc::start()
386 {
387 reload_sample();
388 fill_buffer();
389 recalc_irq();
390 }
391
fill_buffer()392 void Nes_Dmc::fill_buffer()
393 {
394 if ( !buf_full && length_counter )
395 {
396 require( apu->dmc_reader.f ); // dmc_reader must be set
397 buf = apu->dmc_reader.f( apu->dmc_reader.data, 0x8000u + address );
398 address = (address + 1) & 0x7FFF;
399 buf_full = true;
400 if ( --length_counter == 0 )
401 {
402 if ( regs [0] & loop_flag )
403 {
404 reload_sample();
405 }
406 else
407 {
408 apu->osc_enables &= ~0x10;
409 irq_flag = irq_enabled;
410 next_irq = Nes_Apu::no_irq;
411 apu->irq_changed();
412 }
413 }
414 }
415 }
416
run(nes_time_t time,nes_time_t end_time)417 void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
418 {
419 int delta = update_amp_nonlinear( dac );
420 if ( !output )
421 {
422 silence = true;
423 }
424 else if ( delta )
425 {
426 output->set_modified();
427 synth.offset( time, delta, output );
428 }
429
430 time += delay;
431 if ( time < end_time )
432 {
433 int bits_remain = this->bits_remain;
434 if ( silence && !buf_full )
435 {
436 int count = (end_time - time + period - 1) / period;
437 bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
438 time += count * period;
439 }
440 else
441 {
442 Blip_Buffer* const output = this->output;
443 const int period = this->period;
444 int bits = this->bits;
445 int dac = this->dac;
446 if ( output )
447 output->set_modified();
448
449 do
450 {
451 if ( !silence )
452 {
453 int step = (bits & 1) * 4 - 2;
454 bits >>= 1;
455 if ( unsigned (dac + step) <= 0x7F )
456 {
457 dac += step;
458 synth.offset_inline( time, update_amp_nonlinear( dac ), output );
459 }
460 }
461
462 time += period;
463
464 if ( --bits_remain == 0 )
465 {
466 bits_remain = 8;
467 if ( !buf_full )
468 {
469 silence = true;
470 }
471 else
472 {
473 silence = false;
474 bits = buf;
475 buf_full = false;
476 if ( !output )
477 silence = true;
478 fill_buffer();
479 }
480 }
481 }
482 while ( time < end_time );
483
484 this->dac = dac;
485 this->bits = bits;
486 }
487 this->bits_remain = bits_remain;
488 }
489 delay = time - end_time;
490 }
491
492 // Nes_Noise
493
494 static short const noise_period_table [16] = {
495 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
496 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
497 };
498
run(nes_time_t time,nes_time_t end_time)499 void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
500 {
501 int period = noise_period_table [regs [2] & 15];
502
503 if ( !output )
504 {
505 // TODO: clean up
506 time += delay;
507 delay = time + (end_time - time + period - 1) / period * period - end_time;
508 return;
509 }
510
511
512 const int volume = this->volume();
513 int amp = (noise & 1) ? volume : 0;
514 {
515 int delta = update_amp( amp );
516 if ( delta )
517 {
518 output->set_modified();
519 synth.offset( time, delta, output );
520 }
521 }
522
523 time += delay;
524 if ( time < end_time )
525 {
526 const int mode_flag = 0x80;
527
528 if ( !volume )
529 {
530 // round to next multiple of period
531 time += (end_time - time + period - 1) / period * period;
532
533 // approximate noise cycling while muted, by shuffling up noise register
534 // to do: precise muted noise cycling?
535 if ( !(regs [2] & mode_flag) )
536 {
537 int feedback = (noise << 13) ^ (noise << 14);
538 noise = (feedback & 0x4000) | (noise >> 1);
539 }
540 }
541 else
542 {
543 Blip_Buffer* const output = this->output;
544
545 // using resampled time avoids conversion in synth.offset()
546 blip_resampled_time_t rperiod = output->resampled_duration( period );
547 blip_resampled_time_t rtime = output->resampled_time( time );
548
549 int noise = this->noise;
550 int delta = amp * 2 - volume;
551 const int tap = (regs [2] & mode_flag ? 8 : 13);
552 output->set_modified();
553
554 do
555 {
556 int feedback = (noise << tap) ^ (noise << 14);
557 time += period;
558
559 if ( (noise + 1) & 2 )
560 {
561 // bits 0 and 1 of noise differ
562 delta = -delta;
563 synth.offset_resampled( rtime, delta, output );
564 }
565
566 rtime += rperiod;
567 noise = (feedback & 0x4000) | (noise >> 1);
568 }
569 while ( time < end_time );
570
571 last_amp = (delta + volume) >> 1;
572 this->noise = noise;
573 }
574 }
575
576 delay = time - end_time;
577 }
578
579