Fix makefile conditions
[maemo-rb.git] / apps / codecs / libgme / nes_oscs.c
blobac6e5759da9ddac5b4823671a81b81dba5603ec6
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 static 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 += 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 int offset = period >> (osc->regs [1] & shift_mask);
111 if ( osc->regs [1] & negate_flag )
112 offset = 0;
114 const int volume = Square_volume( this );
115 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
117 if ( osc->last_amp ) {
118 Blip_set_modified( osc->output );
119 Synth_offset( this->synth, time, -osc->last_amp, osc->output );
120 osc->last_amp = 0;
123 time += osc->delay;
124 time = Square_maintain_phase( this, time, end_time, timer_period );
126 else
128 // handle duty select
129 int duty_select = (osc->regs [0] >> 6) & 3;
130 int duty = 1 << duty_select; // 1, 2, 4, 2
131 int amp = 0;
132 if ( duty_select == 3 ) {
133 duty = 2; // negated 25%
134 amp = volume;
136 if ( this->phase < duty )
137 amp ^= volume;
139 Blip_set_modified( osc->output );
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 static 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 static 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 += 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 // to do: track phase when period < 3
223 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
225 int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) );
226 if ( delta )
228 Blip_set_modified( osc->output );
229 Synth_offset( &this->synth, time, delta, osc->output );
232 time += osc->delay;
233 if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 )
235 time = end_time;
237 else if ( time < end_time )
239 struct Blip_Buffer* const output = osc->output;
241 int phase = this->phase;
242 int volume = 1;
243 if ( phase > Triangle_phase_range ) {
244 phase -= Triangle_phase_range;
245 volume = -volume;
247 Blip_set_modified( osc->output );
249 do {
250 if ( --phase == 0 ) {
251 phase = Triangle_phase_range;
252 volume = -volume;
254 else
256 Synth_offset_inline( &this->synth, time, volume, output );
259 time += timer_period;
261 while ( time < end_time );
263 if ( volume < 0 )
264 phase += Triangle_phase_range;
265 this->phase = phase;
266 osc->last_amp = Triangle_calc_amp( this );
268 osc->delay = time - end_time;
271 // Nes_Dmc
273 void Dmc_reset( struct Nes_Dmc* this )
275 this->address = 0;
276 this->dac = 0;
277 this->buf = 0;
278 this->bits_remain = 1;
279 this->bits = 0;
280 this->buf_full = false;
281 this->silence = true;
282 this->next_irq = apu_no_irq;
283 this->irq_flag = false;
284 this->irq_enabled = false;
286 Osc_reset( &this->osc );
287 this->period = 0x1AC;
290 void Dmc_recalc_irq( struct Nes_Dmc* this )
292 struct Nes_Osc* osc = &this->osc;
293 nes_time_t irq = apu_no_irq;
294 if ( this->irq_enabled && osc->length_counter )
295 irq = this->apu->last_dmc_time + osc->delay +
296 ((osc->length_counter - 1) * 8 + this->bits_remain - 1) * (nes_time_t) (this->period) + 1;
297 if ( irq != this->next_irq ) {
298 this->next_irq = irq;
299 Apu_irq_changed( this->apu );
303 int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t time, nes_time_t* last_read )
305 struct Nes_Osc* osc = &this->osc;
306 if ( last_read )
307 *last_read = time;
309 if ( osc->length_counter == 0 )
310 return 0; // not reading
312 nes_time_t first_read = Dmc_next_read_time( this );
313 nes_time_t avail = time - first_read;
314 if ( avail <= 0 )
315 return 0;
317 int count = (avail - 1) / (this->period * 8) + 1;
318 if ( !(osc->regs [0] & loop_flag) && count > osc->length_counter )
319 count = osc->length_counter;
321 if ( last_read )
323 *last_read = first_read + (count - 1) * (this->period * 8) + 1;
324 check( *last_read <= time );
325 check( count == count_reads( *last_read, NULL ) );
326 check( count - 1 == count_reads( *last_read - 1, NULL ) );
329 return count;
332 static short const dmc_period_table [2] [16] = {
333 {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
334 190, 160, 142, 128, 106, 84, 72, 54},
336 {398, 354, 316, 298, 276, 236, 210, 198, // PAL
337 176, 148, 132, 118, 98, 78, 66, 50}
340 static inline void Dmc_reload_sample( struct Nes_Dmc* this )
342 this->address = 0x4000 + this->osc.regs [2] * 0x40;
343 this->osc.length_counter = this->osc.regs [3] * 0x10 + 1;
346 static int const dmc_table [128] =
348 0, 24, 48, 71, 94, 118, 141, 163, 186, 209, 231, 253, 275, 297, 319, 340,
349 361, 383, 404, 425, 445, 466, 486, 507, 527, 547, 567, 587, 606, 626, 645, 664,
350 683, 702, 721, 740, 758, 777, 795, 813, 832, 850, 867, 885, 903, 920, 938, 955,
351 972, 989,1006,1023,1040,1056,1073,1089,1105,1122,1138,1154,1170,1185,1201,1217,
352 1232,1248,1263,1278,1293,1308,1323,1338,1353,1368,1382,1397,1411,1425,1440,1454,
353 1468,1482,1496,1510,1523,1537,1551,1564,1578,1591,1604,1618,1631,1644,1657,1670,
354 1683,1695,1708,1721,1733,1746,1758,1771,1783,1795,1807,1819,1831,1843,1855,1867,
355 1879,1890,1902,1914,1925,1937,1948,1959,1971,1982,1993,2004,2015,2026,2037,2048,
358 static inline int update_amp_nonlinear( struct Nes_Dmc* this, int in )
360 if ( !this->nonlinear )
361 in = dmc_table [in];
362 int delta = in - this->osc.last_amp;
363 this->osc.last_amp = in;
364 return delta;
367 void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
369 if ( addr == 0 )
371 this->period = dmc_period_table [this->pal_mode] [data & 15];
372 this->irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
373 this->irq_flag &= this->irq_enabled;
374 Dmc_recalc_irq( this );
376 else if ( addr == 1 )
378 this->dac = data & 0x7F;
382 void Dmc_start( struct Nes_Dmc* this )
384 Dmc_reload_sample( this );
385 Dmc_fill_buffer( this );
386 Dmc_recalc_irq( this );
389 void Dmc_fill_buffer( struct Nes_Dmc* this )
391 if ( !this->buf_full && this->osc.length_counter )
393 require( this->prg_reader ); // prg_reader must be set
394 this->buf = this->prg_reader( this->prg_reader_data, 0x8000u + this->address );
395 this->address = (this->address + 1) & 0x7FFF;
396 this->buf_full = true;
397 if ( --this->osc.length_counter == 0 )
399 if ( this->osc.regs [0] & loop_flag ) {
400 Dmc_reload_sample( this );
402 else {
403 this->apu->osc_enables &= ~0x10;
404 this->irq_flag = this->irq_enabled;
405 this->next_irq = apu_no_irq;
406 Apu_irq_changed( this->apu );
412 void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
414 struct Nes_Osc* osc = &this->osc;
415 int delta = update_amp_nonlinear( this, this->dac );
416 if ( !osc->output )
418 this->silence = true;
420 else if ( delta )
422 Blip_set_modified( osc->output );
423 Synth_offset( &this->synth, time, delta, osc->output );
426 time += osc->delay;
427 if ( time < end_time )
429 int bits_remain = this->bits_remain;
430 if ( this->silence && !this->buf_full )
432 int count = (end_time - time + this->period - 1) / this->period;
433 bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
434 time += count * this->period;
436 else
438 struct Blip_Buffer* const output = osc->output;
439 const int period = this->period;
440 int bits = this->bits;
441 int dac = this->dac;
442 if ( output )
443 Blip_set_modified( output );
447 if ( !this->silence )
449 int step = (bits & 1) * 4 - 2;
450 bits >>= 1;
451 if ( (unsigned) (dac + step) <= 0x7F ) {
452 dac += step;
453 Synth_offset_inline( &this->synth, time, update_amp_nonlinear( this, dac ), output );
457 time += period;
459 if ( --bits_remain == 0 )
461 bits_remain = 8;
462 if ( !this->buf_full ) {
463 this->silence = true;
465 else
467 this->silence = false;
468 bits = this->buf;
469 this->buf_full = false;
470 if ( !output )
471 this->silence = true;
472 Dmc_fill_buffer( this );
476 while ( time < end_time );
478 this->dac = dac;
479 //osc->last_amp = dac;
480 this->bits = bits;
482 this->bits_remain = bits_remain;
484 osc->delay = time - end_time;
487 // Nes_Noise
489 static short const noise_period_table [16] = {
490 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
491 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
494 void Noise_clock_envelope( struct Nes_Noise* this )
496 struct Nes_Osc* osc = &this->osc;
497 int period = osc->regs [0] & 15;
498 if ( osc->reg_written [3] ) {
499 osc->reg_written [3] = false;
500 this->env_delay = period;
501 this->envelope = 15;
503 else if ( --this->env_delay < 0 ) {
504 this->env_delay = period;
505 if ( this->envelope | (osc->regs [0] & 0x20) )
506 this->envelope = (this->envelope - 1) & 15;
510 int Noise_volume( struct Nes_Noise* this )
512 struct Nes_Osc* osc = &this->osc;
513 return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
516 void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
518 struct Nes_Osc* osc = &this->osc;
519 int period = noise_period_table [osc->regs [2] & 15];
521 if ( !osc->output )
523 // TODO: clean up
524 time += osc->delay;
525 osc->delay = time + (end_time - time + period - 1) / period * period - end_time;
526 return;
529 const int volume = Noise_volume( this );
530 int amp = (this->noise & 1) ? volume : 0;
532 int delta = Osc_update_amp( osc, amp );
533 if ( delta )
535 Blip_set_modified( osc->output );
536 Synth_offset( &this->synth, time, delta, osc->output );
540 time += osc->delay;
541 if ( time < end_time )
543 const int mode_flag = 0x80;
545 if ( !volume )
547 // round to next multiple of period
548 time += (end_time - time + period - 1) / period * period;
550 // approximate noise cycling while muted, by shuffling up noise register
551 // to do: precise muted noise cycling?
552 if ( !(osc->regs [2] & mode_flag) ) {
553 int feedback = (this->noise << 13) ^ (this->noise << 14);
554 this->noise = (feedback & 0x4000) | (this->noise >> 1);
557 else
559 struct Blip_Buffer* const output = osc->output;
561 // using resampled time avoids conversion in synth.offset()
562 blip_resampled_time_t rperiod = Blip_resampled_duration( output, period );
563 blip_resampled_time_t rtime = Blip_resampled_time( output, time );
565 int noise = this->noise;
566 int delta = amp * 2 - volume;
567 const int tap = (osc->regs [2] & mode_flag ? 8 : 13);
568 Blip_set_modified( output );
570 do {
571 int feedback = (noise << tap) ^ (noise << 14);
572 time += period;
574 if ( (noise + 1) & 2 ) {
575 // bits 0 and 1 of noise differ
576 delta = -delta;
577 Synth_offset_resampled( &this->synth, rtime, delta, output );
580 rtime += rperiod;
581 noise = (feedback & 0x4000) | (noise >> 1);
583 while ( time < end_time );
585 osc->last_amp = (delta + volume) >> 1;
586 this->noise = noise;
590 osc->delay = time - end_time;