OSDN Git Service

[VM][General][WIP] Apply new (Upstream 2016-02-21) APIs to VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / familybasic / apu.cpp
1 /*
2         Nintendo Family BASIC Emulator 'eFamilyBASIC'
3
4         Origin : nester
5         Author : Takeda.Toshiya
6         Date   : 2010.08.11-
7
8         [ APU ]
9 */
10
11 #include <math.h>
12 #include "apu.h"
13
14 //#define APU_USE_QUEUE
15
16 #define APU_BASEFREQ   1789772.5
17 #define APU_TO_FIXED(x)    ((x) << 16)
18 #define APU_FROM_FIXED(x)  ((x) >> 16)
19
20 static const uint8 vbl_length[32] = {
21          5,     127,
22         10,       1,
23         19,       2,
24         40,       3,
25         80,       4,
26         30,       5,
27          7,       6,
28         13,       7,
29          6,       8,
30         12,       9,
31         24,      10,
32         48,      11,
33         96,      12,
34         36,      13,
35          8,      14,
36         16,      15
37 };
38 static const int freq_limit[8] = {
39         0x3ff, 0x555, 0x666, 0x71c, 0x787, 0x7c1, 0x7e0, 0x7f0
40 };
41 static const int noise_freq[16] = {
42         4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068
43 };
44 static const int dmc_clocks[16] = {
45         428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 85, 72, 54
46 };
47 static const int duty_lut[4] = {
48         2, 4, 8, 12
49 };
50
51 // rectangle wave
52
53 int32 APU::create_rectangle(rectangle_t *chan)
54 {
55         int32 output = 0;
56         double total, sample_weight;
57         
58         if(!chan->enabled || chan->vbl_length <= 0) {
59                 return chan->output_vol;
60         }
61         
62         // vbl length counter
63         if(!chan->holdnote) {
64                 chan->vbl_length -= count_rate;
65         }
66         
67         // envelope decay at a rate of (env_delay + 1) / 240 secs
68         chan->env_phase -= 4 * count_rate;
69         while(chan->env_phase < 0) {
70                 chan->env_phase += chan->env_delay;
71                 if(chan->holdnote) {
72                         chan->env_vol = (chan->env_vol + 1) & 0x0f;
73                 } else if(chan->env_vol < 0x0f) {
74                         chan->env_vol++;
75                 }
76         }
77         if(chan->freq < 8 || (!chan->sweep_inc && chan->freq > chan->freq_limit)) {
78                 return chan->output_vol;
79         }
80         
81         // frequency sweeping at a rate of (sweep_delay + 1) / 120 secs
82         if(chan->sweep_on && chan->sweep_shifts) {
83                 chan->sweep_phase -= 2 * count_rate;
84                 while(chan->sweep_phase < 0) {
85                         chan->sweep_phase += chan->sweep_delay;
86                         if(chan->sweep_inc) {
87                                 if(chan->sweep_complement) {
88                                         chan->freq += ~(chan->freq >> chan->sweep_shifts);
89                                 } else {
90                                         chan->freq -= (chan->freq >> chan->sweep_shifts);
91                                 }
92                         } else {
93                                 chan->freq += (chan->freq >> chan->sweep_shifts);
94                         }
95                 }
96         }
97         
98         if(chan->fixed_envelope) {
99                 output = chan->volume << 8; // fixed volume
100         } else {
101                 output = (chan->env_vol ^ 0x0f) << 8;
102         }
103         sample_weight = chan->phaseacc;
104         if(sample_weight > cycle_rate) {
105                 sample_weight = cycle_rate;
106         }
107         total = (chan->adder < chan->duty_flip) ? sample_weight : -sample_weight;
108         
109         chan->phaseacc -= cycle_rate; // number of cycles per sample
110         while(chan->phaseacc < 0) {
111                 chan->phaseacc += APU_TO_FIXED(chan->freq + 1);
112                 chan->adder = (chan->adder + 1) & 0x0f;
113                 sample_weight = APU_TO_FIXED(chan->freq + 1);
114                 if(chan->phaseacc > 0) {
115                         sample_weight -= chan->phaseacc;
116                 }
117                 total += (chan->adder < chan->duty_flip) ? sample_weight : -sample_weight;
118         }
119         chan->output_vol = (int)floor(output * total / cycle_rate + 0.5);
120         
121         return chan->output_vol;
122 }
123
124 // triangle wave
125
126 int32 APU::create_triangle(triangle_t *chan)
127 {
128         double sample_weight, total;
129         
130         if(!chan->enabled || chan->vbl_length <= 0) {
131                 return ((chan->output_vol * 21) >> 4);
132         }
133         if(chan->counter_started) {
134                 if(chan->linear_length > 0) {
135                         chan->linear_length -= 4 * count_rate;
136                 }
137                 if(chan->vbl_length > 0 && !chan->holdnote) {
138                         chan->vbl_length -= count_rate;
139                 }
140         } else if(!chan->holdnote && chan->write_latency) {
141                 if(--chan->write_latency == 0) {
142                         chan->counter_started = true;
143                 }
144         }
145         if(chan->linear_length <= 0 || chan->freq < APU_TO_FIXED(4)) {
146                 return ((chan->output_vol * 21) >> 4);
147         }
148         
149         sample_weight = chan->phaseacc;
150         if(sample_weight > cycle_rate) {
151                 sample_weight = cycle_rate;
152         }
153         total = (((chan->adder & 0x10) ? 0x1f : 0) ^ chan->adder) * sample_weight;
154         
155         chan->phaseacc -= cycle_rate; // number of cycles per sample
156         while(chan->phaseacc < 0) {
157                 chan->phaseacc += chan->freq;
158                 chan->adder = (chan->adder + 1) & 0x1f;
159                 
160                 sample_weight = chan->freq;
161                 if(chan->phaseacc > 0) {
162                         sample_weight -= chan->phaseacc;
163                 }
164                 total += (((chan->adder & 0x10) ? 0x1f : 0) ^ chan->adder) * sample_weight;
165         }
166         chan->output_vol = (int)floor(total * 512 / cycle_rate + 0.5);
167         
168         return ((chan->output_vol * 21) >> 4);
169 }
170
171 // white noise channel
172
173 int32 APU::create_noise(noise_t *chan)
174 {
175         int32 outvol;
176         double total;
177         double sample_weight;
178         
179         if(!chan->enabled || chan->vbl_length <= 0) {
180                 return ((chan->output_vol * 13) >> 4);
181         }
182         
183         // vbl length counter
184         if(!chan->holdnote) {
185                 chan->vbl_length -= count_rate;
186         }
187         
188         // envelope decay at a rate of (env_delay + 1) / 240 secs
189         chan->env_phase -= 4 * count_rate;
190         while(chan->env_phase < 0) {
191                 chan->env_phase += chan->env_delay;
192                 if(chan->holdnote) {
193                         chan->env_vol = (chan->env_vol + 1) & 0x0f;
194                 } else if(chan->env_vol < 0x0f) {
195                         chan->env_vol++;
196                 }
197         }
198         
199         if(chan->fixed_envelope) {
200                 outvol = chan->volume << 8; // fixed volume
201         } else {
202                 outvol = (chan->env_vol ^ 0x0f) << 8;
203         }
204         sample_weight = chan->phaseacc;
205         if(sample_weight > cycle_rate) {
206                 sample_weight = cycle_rate;
207         }
208         total = chan->noise_bit ? sample_weight : -sample_weight;
209         
210         chan->phaseacc -= cycle_rate; // number of cycles per sample
211         while(chan->phaseacc < 0) {
212                 chan->phaseacc += chan->freq;
213                 int bit0 = chan->shift_reg & 1;
214                 int tap = (chan->shift_reg & chan->xor_tap) ? 1 : 0;
215                 int bit14 = (bit0 ^ tap);
216                 chan->shift_reg >>= 1;
217                 chan->shift_reg |= (bit14 << 14);
218                 chan->noise_bit = bit0 ^ 1;
219                 sample_weight = chan->freq;
220                 if(chan->phaseacc > 0) {
221                         sample_weight -= chan->phaseacc;
222                 }
223                 total += chan->noise_bit ? sample_weight : -sample_weight;
224         }
225         chan->output_vol = (int)floor(outvol * total / cycle_rate + 0.5);
226         
227         return ((chan->output_vol * 13) >> 4);
228 }
229
230 // delta modulation
231
232 inline void APU::dmc_reload(dmc_t *chan)
233 {
234         chan->address = chan->cached_addr;
235         chan->dma_length = chan->cached_dmalength;
236         chan->irq_occurred = false;
237 }
238
239 int32 APU::create_dmc(dmc_t *chan)
240 {
241         double total;
242         double sample_weight;
243         int delta_bit;
244         
245         // only process when channel is alive
246         if(chan->dma_length) {
247                 sample_weight = chan->phaseacc;
248                 if(sample_weight > cycle_rate) {
249                         sample_weight = cycle_rate;
250                 }
251                 total = (chan->regs[1] << 8) * sample_weight;
252                 chan->phaseacc -= cycle_rate; // number of cycles per sample
253                 
254                 while(chan->phaseacc < 0) {
255                         chan->phaseacc += chan->freq;
256                         
257                         if(!(chan->dma_length & 7)) {
258                                 chan->cur_byte = d_mem->read_data8(chan->address);
259                                 //nes6502_burn(1);
260                                 
261                                 if(chan->address == 0xffff) {
262                                         chan->address = 0x8000;
263                                 } else {
264                                         chan->address++;
265                                 }
266                         }
267                         if(--chan->dma_length == 0) {
268                                 if(chan->looping) {
269                                         dmc_reload(chan);
270                                 } else {
271                                         // check to see if we should generate an irq
272                                         if(chan->irq_gen) {
273                                                 chan->irq_occurred = true;
274                                         }
275                                         // bodge for timestamp queue
276                                         sample_weight = chan->freq - chan->phaseacc;
277                                         total += (chan->regs[1] << 8) * sample_weight;
278                                         while(chan->phaseacc < 0) {
279                                                 chan->phaseacc += chan->freq;
280                                         }
281                                         chan->enabled = false;
282                                         break;
283                                 }
284                         }
285                         delta_bit = (chan->dma_length & 7) ^ 7;
286                         
287                         if(chan->cur_byte & (1 << delta_bit)) {
288                                 if(chan->regs[1] < 0x7d) {
289                                         chan->regs[1] += 2;
290                                 }
291                         } else {
292                                 if(chan->regs[1] > 1) {
293                                         chan->regs[1] -= 2;
294                                 }
295                         }
296                         sample_weight = chan->freq;
297                         if(chan->phaseacc > 0) {
298                                 sample_weight -= chan->phaseacc;
299                         }
300                         total += (chan->regs[1] << 8) * sample_weight;
301                 }
302                 chan->output_vol = (int)floor(total / cycle_rate + 0.5);
303         } else {
304                 chan->output_vol = chan->regs[1] << 8;
305         }
306         
307         return ((chan->output_vol * 13) >> 4);
308 }
309
310 void APU::enqueue(queue_t *d)
311 {
312         queue[q_head] = *d;
313         q_head = (q_head + 1) & APUQUEUE_MASK;
314 }
315
316 APU::queue_t* APU::dequeue()
317 {
318         int loc = q_tail;
319         q_tail = (q_tail + 1) & APUQUEUE_MASK;
320         return &queue[loc];
321 }
322
323 void APU::write_data_sync(uint32 addr, uint32 data)
324 {
325         int chan;
326         
327         switch (addr) {
328         case 0x4000:
329         case 0x4004:
330                 chan = (addr & 4) >> 2;
331                 rectangle[chan].regs[0] = data;
332                 rectangle[chan].volume = data & 0x0f;
333                 rectangle[chan].env_delay = decay_lut[data & 0x0f];
334                 rectangle[chan].holdnote = ((data & 0x20) != 0);
335                 rectangle[chan].fixed_envelope = ((data & 0x10) != 0);
336                 rectangle[chan].duty_flip = duty_lut[data >> 6];
337                 break;
338         case 0x4001:
339         case 0x4005:
340                 chan = (addr & 4) >> 2;
341                 rectangle[chan].regs[1] = data;
342                 rectangle[chan].sweep_on = ((data & 0x80) != 0);
343                 rectangle[chan].sweep_shifts = data & 7;
344                 rectangle[chan].sweep_delay = decay_lut[(data >> 4) & 7];
345                 rectangle[chan].sweep_inc = ((data & 0x08) != 0);
346                 rectangle[chan].freq_limit = freq_limit[data & 7];
347                 break;
348         case 0x4002:
349         case 0x4006:
350                 chan = (addr & 4) >> 2;
351                 rectangle[chan].regs[2] = data;
352                 rectangle[chan].freq = (rectangle[chan].freq & ~0xff) | data;
353                 break;
354         case 0x4003:
355         case 0x4007:
356                 chan = (addr & 4) >> 2;
357                 rectangle[chan].regs[3] = data;
358                 rectangle[chan].vbl_length = vbl_lut[data >> 3];
359                 rectangle[chan].env_vol = 0;
360                 rectangle[chan].freq = ((data & 7) << 8) | (rectangle[chan].freq & 0xff);
361                 rectangle[chan].adder = 0;
362                 if(enable_reg & (1 << chan)) {
363                         rectangle[chan].enabled = true;
364                 }
365                 break;
366         case 0x4008:
367                 triangle.regs[0] = data;
368                 triangle.holdnote = ((data & 0x80) != 0);
369                 if(!triangle.counter_started && triangle.vbl_length > 0) {
370                         triangle.linear_length = trilength_lut[data & 0x7f];
371                 }
372                 break;
373         case 0x400a:
374                 triangle.regs[1] = data;
375                 triangle.freq = APU_TO_FIXED((((triangle.regs[2] & 7) << 8) + data) + 1);
376                 break;
377         case 0x400b:
378                 triangle.regs[2] = data;
379                 triangle.write_latency = (int)(228 / APU_FROM_FIXED(cycle_rate));
380                 triangle.freq = APU_TO_FIXED((((data & 7) << 8) + triangle.regs[1]) + 1);
381                 triangle.vbl_length = vbl_lut[data >> 3];
382                 triangle.counter_started = false;
383                 triangle.linear_length = trilength_lut[triangle.regs[0] & 0x7f];
384                 if(enable_reg & 0x04) {
385                         triangle.enabled = true;
386                 }
387                 break;
388         case 0x400c:
389                 noise.regs[0] = data;
390                 noise.env_delay = decay_lut[data & 0x0f];
391                 noise.holdnote = ((data & 0x20) != 0);
392                 noise.fixed_envelope = ((data & 0x10) != 0);
393                 noise.volume = data & 0x0f;
394                 break;
395         case 0x400e:
396                 noise.regs[1] = data;
397                 noise.freq = APU_TO_FIXED(noise_freq[data & 0x0f]);
398                 noise.xor_tap = (data & 0x80) ? 0x40: 0x02;
399                 break;
400         case 0x400f:
401                 noise.regs[2] = data;
402                 noise.vbl_length = vbl_lut[data >> 3];
403                 noise.env_vol = 0; /* reset envelope */
404                 if(enable_reg & 0x08) {
405                         noise.enabled = true;
406                 }
407                 break;
408         case 0x4010:
409                 dmc.regs[0] = data;
410                 dmc.freq = APU_TO_FIXED(dmc_clocks[data & 0x0f]);
411                 dmc.looping = ((data & 0x40) != 0);
412                 if(data & 0x80) {
413                         dmc.irq_gen = true;
414                 } else {
415                         dmc.irq_gen = false;
416                         dmc.irq_occurred = false;
417                 }
418                 break;
419         case 0x4011:    /* 7-bit DAC */
420                 data &= 0x7f; /* bit 7 ignored */
421                 dmc.regs[1] = data;
422                 break;
423         case 0x4012:
424                 dmc.regs[2] = data;
425                 dmc.cached_addr = 0xc000 + (uint16) (data << 6);
426                 break;
427         case 0x4013:
428                 dmc.regs[3] = data;
429                 dmc.cached_dmalength = ((data << 4) + 1) << 3;
430                 break;
431         case 0x4015:
432                 // bodge for timestamp queue
433                 dmc.enabled = ((data & 0x10) != 0);
434                 enable_reg = data;
435                 for(chan = 0; chan < 2; chan++) {
436                         if(!(data & (1 << chan))) {
437                                 rectangle[chan].enabled = false;
438                                 rectangle[chan].vbl_length = 0;
439                         }
440                 }
441                 if(!(data & 0x04)) {
442                         triangle.enabled = false;
443                         triangle.vbl_length = 0;
444                         triangle.linear_length = 0;
445                         triangle.counter_started = false;
446                         triangle.write_latency = 0;
447                 }
448                 if(!(data & 0x08)) {
449                         noise.enabled = false;
450                         noise.vbl_length = 0;
451                 }
452                 if(data & 0x10) {
453                         if(!dmc.dma_length) {
454                                 dmc_reload(&dmc);
455                         }
456                 } else {
457                         dmc.dma_length = 0;
458                         dmc.irq_occurred = false;
459                 }
460                 break;
461         case 0x4009:
462         case 0x400D:
463                 break;
464         case 0x4017:
465                 count_rate = (data & 0x80) ? 4 : 5;
466                 break;
467         default:
468                 break;
469         }
470 }
471
472 void APU::write_data_cur(uint32 addr, uint32 data)
473 {
474         // for sync read $4015
475         int chan;
476         
477         switch (addr) {
478         case 0x4000:
479         case 0x4004:
480                 chan = (addr & 4) >> 2;
481                 rectangle[chan].holdnote_cur = ((data & 0x20) != 0);
482                 break;
483         case 0x4003:
484         case 0x4007:
485                 chan = (addr & 4) >> 2;
486                 rectangle[chan].vbl_length_cur = vbl_length[data >> 3] * 5;
487                 if(enable_reg_cur & (1 << chan)) {
488                         rectangle[chan].enabled_cur = true;
489                 }
490                 break;
491         case 0x4008:
492                 triangle.holdnote_cur = ((data & 0x80) != 0);
493                 break;
494         case 0x400b:
495                 triangle.vbl_length_cur = vbl_length[data >> 3] * 5;
496                 if(enable_reg_cur & 0x04) {
497                         triangle.enabled_cur = true;
498                 }
499                 triangle.counter_started_cur = true;
500                 break;
501         case 0x400c:
502                 noise.holdnote_cur = ((data & 0x20) != 0);
503                 break;
504         case 0x400f:
505                 noise.vbl_length_cur = vbl_length[data >> 3] * 5;
506                 if(enable_reg_cur & 0x08) {
507                         noise.enabled_cur = true;
508                 }
509                 break;
510         case 0x4010:
511                 dmc.freq_cur = dmc_clocks[data & 0x0f];
512                 dmc.phaseacc_cur = 0;
513                 dmc.looping_cur = ((data & 0x40) != 0);
514                 if(data & 0x80) {
515                         dmc.irq_gen_cur = true;
516                 } else {
517                         dmc.irq_gen_cur = false;
518                         dmc.irq_occurred_cur = false;
519                 }
520                 break;
521         case 0x4013:
522                 dmc.cached_dmalength_cur = (data << 4) + 1;
523                 break;
524         case 0x4015:
525                 enable_reg_cur = data;
526                 for(chan = 0; chan < 2; chan++) {
527                         if(!(data & (1 << chan))) {
528                                 rectangle[chan].enabled_cur = false;
529                                 rectangle[chan].vbl_length_cur = 0;
530                         }
531                 }
532                 if(!(data & 0x04)) {
533                         triangle.enabled_cur = false;
534                         triangle.vbl_length_cur = 0;
535                         triangle.counter_started_cur = false;
536                 }
537                 if(!(data & 0x08)) {
538                         noise.enabled_cur = false;
539                         noise.vbl_length_cur = 0;
540                 }
541                 if(data & 0x10) {
542                         if(!dmc.dma_length_cur) {
543                                 dmc.dma_length_cur = dmc.cached_dmalength_cur;
544                         }
545                         dmc.enabled_cur = true;
546                 } else {
547                         dmc.dma_length_cur = 0;
548                         dmc.enabled_cur = false;
549                         dmc.irq_occurred_cur = false;
550                 }
551                 break;
552         }
553 }
554
555 // interface
556
557 void APU::initialize()
558 {
559         register_frame_event(this);
560         register_vline_event(this);
561 }
562
563 void APU::reset()
564 {
565         // reset queue
566         elapsed_cycles = 0;
567         memset(&queue, 0, APUQUEUE_SIZE * sizeof(queue_t));
568         q_head = q_tail = 0;
569         
570         // reset apu
571         for(int i = 0; i < 2; i++) {
572                 memset(&rectangle[i], 0, sizeof(rectangle[i]));
573         }
574         rectangle[0].sweep_complement = true;
575         rectangle[1].sweep_complement = false;
576         memset(&triangle, 0, sizeof(triangle));
577         memset(&noise, 0, sizeof(noise));
578         noise.shift_reg = 0x4000;
579         memset(&dmc, 0, sizeof(dmc));
580         
581         // reset registers
582         for(uint32 addr = 0x4000; addr <= 0x4013; addr++) {
583                 write_data_sync(addr, 0);
584                 write_data_cur(addr, 0);
585         }
586         write_data_sync(0x4015, 0);
587         write_data_cur(0x4015, 0);
588         
589         enable_reg = 0;
590         enable_reg_cur = 0;
591         count_rate = 5;
592         ave = max = min = 0;
593 }
594
595 void APU::write_data8(uint32 addr, uint32 data)
596 {
597         queue_t d;
598         
599         write_data_cur(addr, data);
600         
601         switch (addr) {
602         case 0x4015:
603                 // bodge for timestamp queue
604                 dmc.enabled = ((data & 0x10) != 0);
605         case 0x4000: case 0x4001: case 0x4002: case 0x4003:
606         case 0x4004: case 0x4005: case 0x4006: case 0x4007:
607         case 0x4008: case 0x4009: case 0x400a: case 0x400b:
608         case 0x400c: case 0x400d: case 0x400e: case 0x400f:
609         case 0x4010: case 0x4011: case 0x4012: case 0x4013:
610         case 0x4017:
611                 d.timestamp = get_current_clock();
612                 d.addr = addr;
613                 d.data = data;
614 #ifdef APU_USE_QUEUE
615                 enqueue(&d);
616 #else
617                 write_data_sync(addr, data);
618 #endif
619                 break;
620         }
621 }
622
623 uint32 APU::read_data8(uint32 addr)
624 {
625         if(addr == 0x4015) {
626                 uint32 data = 0;
627                 // return 1 in 0-5 bit pos if a channel is playing
628                 if(rectangle[0].enabled_cur && rectangle[0].vbl_length_cur > 0) {
629                         data |= 0x01;
630                 }
631                 if(rectangle[1].enabled_cur && rectangle[1].vbl_length_cur > 0) {
632                         data |= 0x02;
633                 }
634                 if(triangle.enabled_cur && triangle.vbl_length_cur > 0) {
635                         data |= 0x04;
636                 }
637                 if(noise.enabled_cur && noise.vbl_length_cur > 0) {
638                         data |= 0x08;
639                 }
640                 // bodge for timestamp queue
641                 if(dmc.enabled_cur) {
642                         data |= 0x10;
643                 }
644                 if(dmc.irq_occurred_cur) {
645                         data |= 0x80;
646                 }
647                 return data;
648         }
649         return (addr >> 8);
650 }
651
652 void APU::event_frame()
653 {
654         if(!rectangle[0].holdnote_cur && rectangle[0].vbl_length_cur > 0) {
655                 rectangle[0].vbl_length_cur -= count_rate;
656         }
657         if(!rectangle[1].holdnote_cur && rectangle[1].vbl_length_cur > 0) {
658                 rectangle[1].vbl_length_cur -= count_rate;
659         }
660         if(triangle.counter_started_cur) {
661                 if(triangle.vbl_length_cur > 0 && !triangle.holdnote_cur) {
662                         triangle.vbl_length_cur -= count_rate;
663                 }
664         }
665         if(!noise.holdnote_cur && noise.vbl_length_cur > 0) {
666                 noise.vbl_length_cur -= count_rate;
667         }
668 }
669
670 void APU::event_vline(int v, int clock)
671 {
672         bool irq_occurred = false;
673         
674         dmc.phaseacc_cur -= clock;
675         while(dmc.phaseacc_cur < 0) {
676                 dmc.phaseacc_cur += dmc.freq_cur * 8;
677                 if(dmc.dma_length_cur) {
678                         if(--dmc.dma_length_cur == 0) {
679                                 if(dmc.looping_cur) {
680                                         dmc.dma_length_cur = dmc.cached_dmalength_cur;
681                                         dmc.irq_occurred_cur = false;
682                                 } else {
683                                         dmc.dma_length_cur = 0;
684                                         if(dmc.irq_gen_cur) {
685                                                 dmc.irq_occurred_cur = true;
686                                                 irq_occurred = true;
687                                         }
688                                         dmc.enabled_cur = false;
689                                 }
690                         }
691                 }
692         }
693         if(irq_occurred) {
694                 // pending
695                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
696         }
697 }
698
699 void APU::initialize_sound(int rate, int samples)
700 {
701         cycle_rate = (int32)(APU_BASEFREQ * 65536.0 / (float)rate);
702         
703         // lut used for enveloping and frequency sweeps
704         for(int i = 0; i < 16; i++) {
705                 decay_lut[i] = (rate / 60) * (i + 1) * 5;
706         }
707         // used for note length, based on vblanks and size of audio buffer
708         for(int i = 0; i < 32; i++) {
709                 vbl_lut[i] = vbl_length[i] * (rate / 60) * 5;
710         }
711         // triangle wave channel's linear length table
712         for(int i = 0; i < 128; i++) {
713                 trilength_lut[i] = (rate / 60) * i * 5;
714         }
715 }
716
717 void APU::mix(int32* buffer, int num_samples)
718 {
719         uint32 cpu_cycles = elapsed_cycles;
720         
721         while(num_samples--) {
722 #ifdef APU_USE_QUEUE
723                 // check queue
724                 while((q_head != q_tail) && (queue[q_tail].timestamp <= cpu_cycles)) {
725                         queue_t *d = dequeue();
726                         write_data_sync(d->addr, d->data);
727                 }
728                 cpu_cycles += APU_FROM_FIXED(cycle_rate);
729 #endif
730                 int32 accum = 0;
731                 accum += create_rectangle(&rectangle[0]);
732                 accum += create_rectangle(&rectangle[1]);
733                 accum += create_triangle(&triangle);
734                 accum += create_noise(&noise);
735                 accum += create_dmc(&dmc);
736                 
737                 double delta = (max - min) / 32768.0;
738                 max -= delta;
739                 min += delta;
740                 if(accum > max) {
741                         max = accum;
742                 }
743                 if(accum < min) {
744                         min = accum;
745                 }
746                 ave -= ave / 1024.0;
747                 ave += (max + min) / 2048.0;
748                 accum -= (int32)ave;
749                 
750                 *buffer++ += apply_volume(accum, volume_l); // L
751                 *buffer++ += apply_volume(accum, volume_r); // R
752         }
753         
754         // resync cycle counter
755         elapsed_cycles = get_current_clock();
756 }
757
758 void APU::set_volume(int ch, int decibel_l, int decibel_r)
759 {
760         volume_l = decibel_to_volume(decibel_l);
761         volume_r = decibel_to_volume(decibel_r);
762 }
763
764 #define STATE_VERSION   1
765
766 void APU::save_state(FILEIO* state_fio)
767 {
768         state_fio->FputUint32(STATE_VERSION);
769         state_fio->FputInt32(this_device_id);
770         
771         state_fio->Fwrite(rectangle, sizeof(rectangle), 1);
772         state_fio->Fwrite(&triangle, sizeof(triangle), 1);
773         state_fio->Fwrite(&noise, sizeof(noise), 1);
774         state_fio->Fwrite(&dmc, sizeof(dmc), 1);
775         state_fio->FputUint32(enable_reg);
776         state_fio->FputUint32(enable_reg_cur);
777         state_fio->FputInt32(count_rate);
778         state_fio->Fwrite(queue, sizeof(queue), 1);
779         state_fio->FputInt32(q_head);
780         state_fio->FputInt32(q_tail);
781         state_fio->FputUint32(elapsed_cycles);
782         state_fio->FputDouble(ave);
783         state_fio->FputDouble(max);
784         state_fio->FputDouble(min);
785 }
786
787 bool APU::load_state(FILEIO* state_fio)
788 {
789         if(state_fio->FgetUint32() != STATE_VERSION) {
790                 return false;
791         }
792         if(state_fio->FgetInt32() != this_device_id) {
793                 return false;
794         }
795         state_fio->Fread(rectangle, sizeof(rectangle), 1);
796         state_fio->Fread(&triangle, sizeof(triangle), 1);
797         state_fio->Fread(&noise, sizeof(noise), 1);
798         state_fio->Fread(&dmc, sizeof(dmc), 1);
799         enable_reg = state_fio->FgetUint32();
800         enable_reg_cur = state_fio->FgetUint32();
801         count_rate = state_fio->FgetInt32();
802         state_fio->Fread(queue, sizeof(queue), 1);
803         q_head = state_fio->FgetInt32();
804         q_tail = state_fio->FgetInt32();
805         elapsed_cycles = state_fio->FgetUint32();
806         ave = state_fio->FgetDouble();
807         max = state_fio->FgetDouble();
808         min = state_fio->FgetDouble();
809         return true;
810 }
811