Submit initial patch from FS#12176. Adds support for several new game music formats...
[kugel-rb.git] / apps / codecs / libgme / nes_oscs.c
blobf04d5fa9ad16ce31aaa48f96ed3646a5a2fa0dad
1 // Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
3 #include "nes_apu.h"
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 */
16 #include "blargg_source.h"
18 // Nes_Osc
20 void Osc_clock_length( struct Nes_Osc* this, int halt_mask )
22 if ( this->length_counter && !(this->regs [0] & halt_mask) )
23 this->length_counter--;
26 // Nes_Square
28 void Square_clock_envelope( struct Nes_Square* this )
30 struct Nes_Osc* osc = &this->osc;
31 int period = osc->regs [0] & 15;
32 if ( osc->reg_written [3] ) {
33 osc->reg_written [3] = false;
34 this->env_delay = period;
35 this->envelope = 15;
37 else if ( --this->env_delay < 0 ) {
38 this->env_delay = period;
39 if ( this->envelope | (osc->regs [0] & 0x20) )
40 this->envelope = (this->envelope - 1) & 15;
44 int Square_volume( struct Nes_Square* this )
46 struct Nes_Osc* osc = &this->osc;
47 return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
50 void Square_clock_sweep( struct Nes_Square* this, int negative_adjust )
52 struct Nes_Osc* osc = &this->osc;
53 int sweep = osc->regs [1];
55 if ( --this->sweep_delay < 0 )
57 osc->reg_written [1] = true;
59 int period = Osc_period( osc );
60 int shift = sweep & shift_mask;
61 if ( shift && (sweep & 0x80) && period >= 8 )
63 int offset = period >> shift;
65 if ( sweep & negate_flag )
66 offset = negative_adjust - offset;
68 if ( period + offset < 0x800 )
70 period += offset;
71 // rewrite period
72 osc->regs [2] = period & 0xFF;
73 osc->regs [3] = (osc->regs [3] & ~7) | ((period >> 8) & 7);
78 if ( osc->reg_written [1] ) {
79 osc->reg_written [1] = false;
80 this->sweep_delay = (sweep >> 4) & 7;
84 // TODO: clean up
85 inline nes_time_t Square_maintain_phase( struct Nes_Square* this, nes_time_t time, nes_time_t end_time,
86 nes_time_t timer_period )
88 nes_time_t remain = end_time - time;
89 if ( remain > 0 )
91 int count = (remain + timer_period - 1) / timer_period;
92 this->phase = (this->phase + count) & (square_phase_range - 1);
93 time += (blargg_long) count * timer_period;
95 return time;
98 void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
100 struct Nes_Osc* osc = &this->osc;
101 const int period = Osc_period( osc );
102 const int timer_period = (period + 1) * 2;
104 if ( !osc->output )
106 osc->delay = Square_maintain_phase( this, time + osc->delay, end_time, timer_period ) - end_time;
107 return;
110 Blip_set_modified( osc->output );
112 int offset = period >> (osc->regs [1] & shift_mask);
113 if ( osc->regs [1] & negate_flag )
114 offset = 0;
116 const int volume = Square_volume( this );
117 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
119 if ( osc->last_amp ) {
120 Synth_offset( this->synth, time, -osc->last_amp, osc->output );
121 osc->last_amp = 0;
124 time += osc->delay;
125 time = Square_maintain_phase( this, time, end_time, timer_period );
127 else
129 // handle duty select
130 int duty_select = (osc->regs [0] >> 6) & 3;
131 int duty = 1 << duty_select; // 1, 2, 4, 2
132 int amp = 0;
133 if ( duty_select == 3 ) {
134 duty = 2; // negated 25%
135 amp = volume;
137 if ( this->phase < duty )
138 amp ^= volume;
141 int delta = Osc_update_amp( osc, amp );
142 if ( delta )
143 Synth_offset( this->synth, time, delta, osc->output );
146 time += osc->delay;
147 if ( time < end_time )
149 struct Blip_Buffer* const output = osc->output;
150 Synth* synth = this->synth;
151 int delta = amp * 2 - volume;
152 int phase = this->phase;
154 do {
155 phase = (phase + 1) & (square_phase_range - 1);
156 if ( phase == 0 || phase == duty ) {
157 delta = -delta;
158 Synth_offset_inline( synth, time, delta, output );
160 time += timer_period;
162 while ( time < end_time );
164 osc->last_amp = (delta + volume) >> 1;
165 this->phase = phase;
169 osc->delay = time - end_time;
172 // Nes_Triangle
174 void Triangle_clock_linear_counter( struct Nes_Triangle* this )
176 struct Nes_Osc* osc = &this->osc;
177 if ( osc->reg_written [3] )
178 this->linear_counter = osc->regs [0] & 0x7F;
179 else if ( this->linear_counter )
180 this->linear_counter--;
182 if ( !(osc->regs [0] & 0x80) )
183 osc->reg_written [3] = false;
186 inline int Triangle_calc_amp( struct Nes_Triangle* this )
188 int amp = Triangle_phase_range - this->phase;
189 if ( amp < 0 )
190 amp = this->phase - (Triangle_phase_range + 1);
191 return amp;
194 // TODO: clean up
195 inline nes_time_t Triangle_maintain_phase( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time,
196 nes_time_t timer_period )
198 nes_time_t remain = end_time - time;
199 if ( remain > 0 )
201 int count = (remain + timer_period - 1) / timer_period;
202 this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1);
203 this->phase++;
204 time += (blargg_long) count * timer_period;
206 return time;
209 void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time )
211 struct Nes_Osc* osc = &this->osc;
212 const int timer_period = Osc_period( osc ) + 1;
213 if ( !osc->output )
215 time += osc->delay;
216 osc->delay = 0;
217 if ( osc->length_counter && this->linear_counter && timer_period >= 3 )
218 osc->delay = Triangle_maintain_phase( this, time, end_time, timer_period ) - end_time;
219 return;
222 Blip_set_modified( osc->output );
224 // to do: track phase when period < 3
225 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
227 int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) );
228 if ( delta )
229 Synth_offset( &this->synth, time, delta, osc->output );
231 time += osc->delay;
232 if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 )
234 time = end_time;
236 else if ( time < end_time )
238 struct Blip_Buffer* const output = osc->output;
240 int phase = this->phase;
241 int volume = 1;
242 if ( phase > Triangle_phase_range ) {
243 phase -= Triangle_phase_range;
244 volume = -volume;
247 do {
248 if ( --phase == 0 ) {
249 phase = Triangle_phase_range;
250 volume = -volume;
252 else {
253 Synth_offset_inline( &this->synth, time, volume, output );
256 time += timer_period;
258 while ( time < end_time );
260 if ( volume < 0 )
261 phase += Triangle_phase_range;
262 this->phase = phase;
263 osc->last_amp = Triangle_calc_amp( this );
265 osc->delay = time - end_time;
268 // Nes_Dmc
270 void Dmc_reset( struct Nes_Dmc* this )
272 this->address = 0;
273 this->dac = 0;
274 this->buf = 0;
275 this->bits_remain = 1;
276 this->bits = 0;
277 this->buf_full = false;
278 this->silence = true;
279 this->next_irq = apu_no_irq;
280 this->irq_flag = false;
281 this->irq_enabled = false;
283 Osc_reset( &this->osc );
284 this->period = 0x1AC;
287 void Dmc_recalc_irq( struct Nes_Dmc* this )
289 struct Nes_Osc* osc = &this->osc;
290 nes_time_t irq = apu_no_irq;
291 if ( this->irq_enabled && osc->length_counter )
292 irq = this->apu->last_dmc_time + osc->delay +
293 ((osc->length_counter - 1) * 8 + this->bits_remain - 1) * (nes_time_t) (this->period) + 1;
294 if ( irq != this->next_irq ) {
295 this->next_irq = irq;
296 Apu_irq_changed( this->apu );
300 int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t time, nes_time_t* last_read )
302 struct Nes_Osc* osc = &this->osc;
303 if ( last_read )
304 *last_read = time;
306 if ( osc->length_counter == 0 )
307 return 0; // not reading
309 nes_time_t first_read = Dmc_next_read_time( this );
310 nes_time_t avail = time - first_read;
311 if ( avail <= 0 )
312 return 0;
314 int count = (avail - 1) / (this->period * 8) + 1;
315 if ( !(osc->regs [0] & loop_flag) && count > osc->length_counter )
316 count = osc->length_counter;
318 if ( last_read )
320 *last_read = first_read + (count - 1) * (this->period * 8) + 1;
321 check( *last_read <= time );
322 check( count == count_reads( *last_read, NULL ) );
323 check( count - 1 == count_reads( *last_read - 1, NULL ) );
326 return count;
329 static short const dmc_period_table [2] [16] ICONST_ATTR = {
330 {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
331 190, 160, 142, 128, 106, 84, 72, 54},
333 {398, 354, 316, 298, 276, 236, 210, 198, // PAL
334 176, 148, 132, 118, 98, 78, 66, 50}
337 inline void Dmc_reload_sample( struct Nes_Dmc* this )
339 this->address = 0x4000 + this->osc.regs [2] * 0x40;
340 this->osc.length_counter = this->osc.regs [3] * 0x10 + 1;
343 static byte const dac_table [128] ICONST_ATTR =
345 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
346 15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
347 27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
348 39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
349 50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
350 59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
351 68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
352 76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
355 void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
357 if ( addr == 0 )
359 this->period = dmc_period_table [this->pal_mode] [data & 15];
360 this->irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
361 this->irq_flag &= this->irq_enabled;
362 Dmc_recalc_irq( this );
364 else if ( addr == 1 )
366 int old_dac = this->dac;
367 this->dac = data & 0x7F;
369 // adjust last_amp so that "pop" amplitude will be properly non-linear
370 // with respect to change in dac
371 int faked_nonlinear = this->dac - (dac_table [this->dac] - dac_table [old_dac]);
372 if ( !this->nonlinear )
373 this->osc.last_amp = faked_nonlinear;
377 void Dmc_start( struct Nes_Dmc* this )
379 Dmc_reload_sample( this );
380 Dmc_fill_buffer( this );
381 Dmc_recalc_irq( this );
384 void Dmc_fill_buffer( struct Nes_Dmc* this )
386 if ( !this->buf_full && this->osc.length_counter )
388 require( this->prg_reader ); // prg_reader must be set
389 this->buf = this->prg_reader( this->prg_reader_data, 0x8000u + this->address );
390 this->address = (this->address + 1) & 0x7FFF;
391 this->buf_full = true;
392 if ( --this->osc.length_counter == 0 )
394 if ( this->osc.regs [0] & loop_flag ) {
395 Dmc_reload_sample( this );
397 else {
398 this->apu->osc_enables &= ~0x10;
399 this->irq_flag = this->irq_enabled;
400 this->next_irq = apu_no_irq;
401 Apu_irq_changed( this->apu );
407 void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
409 struct Nes_Osc* osc = &this->osc;
410 int delta = Osc_update_amp( osc, this->dac );
411 if ( !osc->output )
413 this->silence = true;
415 else
417 Blip_set_modified( osc->output );
418 if ( delta )
419 Synth_offset( &this->synth, time, delta, osc->output );
422 time += osc->delay;
423 if ( time < end_time )
425 int bits_remain = this->bits_remain;
426 if ( this->silence && !this->buf_full )
428 int count = (end_time - time + this->period - 1) / this->period;
429 bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
430 time += count * this->period;
432 else
434 struct Blip_Buffer* const output = osc->output;
435 const int period = this->period;
436 int bits = this->bits;
437 int dac = this->dac;
441 if ( !this->silence )
443 int step = (bits & 1) * 4 - 2;
444 bits >>= 1;
445 if ( (unsigned) (dac + step) <= 0x7F ) {
446 dac += step;
447 Synth_offset_inline( &this->synth, time, step, output );
451 time += period;
453 if ( --bits_remain == 0 )
455 bits_remain = 8;
456 if ( !this->buf_full ) {
457 this->silence = true;
459 else {
460 this->silence = false;
461 bits = this->buf;
462 this->buf_full = false;
463 if ( !output )
464 this->silence = true;
465 Dmc_fill_buffer( this );
469 while ( time < end_time );
471 this->dac = dac;
472 osc->last_amp = dac;
473 this->bits = bits;
475 this->bits_remain = bits_remain;
477 osc->delay = time - end_time;
480 // Nes_Noise
482 static short const noise_period_table [16] ICONST_ATTR = {
483 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
484 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
487 void Noise_clock_envelope( struct Nes_Noise* this )
489 struct Nes_Osc* osc = &this->osc;
490 int period = osc->regs [0] & 15;
491 if ( osc->reg_written [3] ) {
492 osc->reg_written [3] = false;
493 this->env_delay = period;
494 this->envelope = 15;
496 else if ( --this->env_delay < 0 ) {
497 this->env_delay = period;
498 if ( this->envelope | (osc->regs [0] & 0x20) )
499 this->envelope = (this->envelope - 1) & 15;
503 int Noise_volume( struct Nes_Noise* this )
505 struct Nes_Osc* osc = &this->osc;
506 return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
509 void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
511 struct Nes_Osc* osc = &this->osc;
512 int period = noise_period_table [osc->regs [2] & 15];
514 if ( !osc->output )
516 // TODO: clean up
517 time += osc->delay;
518 osc->delay = time + (end_time - time + period - 1) / period * period - end_time;
519 return;
522 Blip_set_modified( osc->output );
524 const int volume = Noise_volume( this );
525 int amp = (this->noise & 1) ? volume : 0;
527 int delta = Osc_update_amp( osc, amp );
528 if ( delta )
529 Synth_offset( &this->synth, time, delta, osc->output );
532 time += osc->delay;
533 if ( time < end_time )
535 const int mode_flag = 0x80;
537 if ( !volume )
539 // round to next multiple of period
540 time += (end_time - time + period - 1) / period * period;
542 // approximate noise cycling while muted, by shuffling up noise register
543 // to do: precise muted noise cycling?
544 if ( !(osc->regs [2] & mode_flag) ) {
545 int feedback = (this->noise << 13) ^ (this->noise << 14);
546 this->noise = (feedback & 0x4000) | (this->noise >> 1);
549 else
551 struct Blip_Buffer* const output = osc->output;
553 // using resampled time avoids conversion in synth.offset()
554 blip_resampled_time_t rperiod = Blip_resampled_duration( output, period );
555 blip_resampled_time_t rtime = Blip_resampled_time( output, time );
557 int noise = this->noise;
558 int delta = amp * 2 - volume;
559 const int tap = (osc->regs [2] & mode_flag ? 8 : 13);
561 do {
562 int feedback = (noise << tap) ^ (noise << 14);
563 time += period;
565 if ( (noise + 1) & 2 ) {
566 // bits 0 and 1 of noise differ
567 delta = -delta;
568 Synth_offset_resampled( &this->synth, rtime, delta, output );
571 rtime += rperiod;
572 noise = (feedback & 0x4000) | (noise >> 1);
574 while ( time < end_time );
576 osc->last_amp = (delta + volume) >> 1;
577 this->noise = noise;
581 osc->delay = time - end_time;