1 // Ported from NSFPlay to VGMPlay (including C++ -> C conversion)
2 // by Valley Bell on 25 September 2013
3 // Updated to NSFPlay 2.3 on 26 September 2013
4 // (Note: Encoding is UTF-8)
5
6 #include <stdlib.h> // for rand
7 #include <stdlib.h>
8 #include <string.h> // for memset
9 #include <stddef.h> // for NULL
10 #include "mamedef.h"
11 #include "../stdbool.h"
12 #include "np_nes_apu.h" // for NES_APU_np_FrameSequence
13 #include "np_nes_dmc.h"
14
15
16 // Master Clock: 21477272 (NTSC)
17 // APU Clock = Master Clock / 12
18 #define DEFAULT_CLOCK 1789772.0
19 #define DEFAULT_CLK_PAL 1662607
20 #define DEFAULT_RATE 44100
21
22
23 /** Bottom Half of APU **/
24 enum
25 {
26 OPT_UNMUTE_ON_RESET=0,
27 OPT_NONLINEAR_MIXER,
28 OPT_ENABLE_4011,
29 OPT_ENABLE_PNOISE,
30 OPT_DPCM_ANTI_CLICK,
31 OPT_RANDOMIZE_NOISE,
32 OPT_TRI_MUTE,
33 OPT_TRI_NULL,
34 OPT_END
35 };
36
37
38 // Note: For increased speed, I'll inline all of NSFPlay's Counter member functions.
39 #define COUNTER_SHIFT 24
40
41 typedef struct _Counter Counter;
42 struct _Counter
43 {
44 double ratio;
45 UINT32 val, step;
46 };
47 #define COUNTER_setcycle(cntr, s) (cntr).step = (UINT32)((cntr).ratio / (s + 1))
48 #define COUNTER_iup(cntr) (cntr).val += (cntr).step
49 #define COUNTER_value(cntr) ((cntr).val >> COUNTER_SHIFT)
50 #define COUNTER_init(cntr, clk, rate) \
51 { \
52 (cntr).ratio = (1 << COUNTER_SHIFT) * (1.0 * clk / rate); \
53 (cntr).step = (UINT32)((cntr).ratio + 0.5); \
54 (cntr).val = 0; \
55 }
56
57
58 typedef struct _NES_DMC NES_DMC;
59 struct _NES_DMC
60 {
61 //const int GETA_BITS;
62 //static const UINT32 freq_table[2][16];
63 //static const UINT32 wavlen_table[2][16];
64 UINT32 tnd_table[2][16][16][128];
65
66 int option[OPT_END];
67 int mask;
68 INT32 sm[2][3];
69 UINT8 reg[0x10];
70 UINT32 len_reg;
71 UINT32 adr_reg;
72 //IDevice *memory;
73 const UINT8* memory;
74 UINT32 out[3];
75 UINT32 daddress;
76 UINT32 length;
77 UINT32 data;
78 INT16 damp;
79 int dac_lsb;
80 bool dmc_pop;
81 INT32 dmc_pop_offset;
82 INT32 dmc_pop_follow;
83 UINT32 clock;
84 UINT32 rate;
85 int pal;
86 int mode;
87 bool irq;
88 bool active;
89
90 UINT32 counter[3]; // frequency dividers
91 int tphase; // triangle phase
92 UINT32 nfreq; // noise frequency
93 UINT32 dfreq; // DPCM frequency
94
95 UINT32 tri_freq;
96 int linear_counter;
97 int linear_counter_reload;
98 bool linear_counter_halt;
99 bool linear_counter_control;
100
101 int noise_volume;
102 UINT32 noise, noise_tap;
103
104 // noise envelope
105 bool envelope_loop;
106 bool envelope_disable;
107 bool envelope_write;
108 int envelope_div_period;
109 int envelope_div;
110 int envelope_counter;
111
112 bool enable[3];
113 int length_counter[2]; // 0=tri, 1=noise
114
115 // frame sequencer
116 void* apu; // apu is clocked by DMC's frame sequencer
117 int frame_sequence_count; // current cycle count
118 int frame_sequence_length; // CPU cycles per FrameSequence
119 int frame_sequence_step; // current step of frame sequence
120 int frame_sequence_steps; // 4/5 steps per frame
121 bool frame_irq;
122 bool frame_irq_enable;
123
124 Counter tick_count;
125 UINT32 tick_last;
126 };
127
128 INLINE UINT32 calc_tri(NES_DMC* dmc, UINT32 clocks);
129 INLINE UINT32 calc_dmc(NES_DMC* dmc, UINT32 clocks);
130 INLINE UINT32 calc_noise(NES_DMC* dmc, UINT32 clocks);
131 static void FrameSequence(NES_DMC* dmc, int s);
132 static void TickFrameSequence(NES_DMC* dmc, UINT32 clocks);
133 static void Tick(NES_DMC* dmc, UINT32 clocks);
134
135 #define GETA_BITS 20
136 static const UINT32 wavlen_table[2][16] = {
137 { // NTSC
138 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068
139 },
140 { // PAL
141 4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778
142 }};
143
144 static const UINT32 freq_table[2][16] = {
145 { // NTSC
146 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54
147 },
148 { // PAL
149 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50
150 }};
151
NES_DMC_np_Create(int clock,int rate)152 void* NES_DMC_np_Create(int clock, int rate)
153 {
154 NES_DMC* dmc;
155 int c, t;
156
157 dmc = (NES_DMC*)malloc(sizeof(NES_DMC));
158 if (dmc == NULL)
159 return NULL;
160 memset(dmc, 0x00, sizeof(NES_DMC));
161
162 //NES_DMC_np_SetClock(dmc, DEFAULT_CLOCK);
163 //NES_DMC_np_SetRate(dmc, DEFAULT_RATE);
164 //NES_DMC_np_SetPal(dmc, false);
165 NES_DMC_np_SetClock(dmc, clock); // does SetPal, too
166 NES_DMC_np_SetRate(dmc, rate);
167 dmc->option[OPT_ENABLE_4011] = 1;
168 dmc->option[OPT_ENABLE_PNOISE] = 1;
169 dmc->option[OPT_UNMUTE_ON_RESET] = 1;
170 dmc->option[OPT_DPCM_ANTI_CLICK] = 0;
171 dmc->option[OPT_NONLINEAR_MIXER] = 1;
172 dmc->option[OPT_RANDOMIZE_NOISE] = 1;
173 dmc->option[OPT_TRI_MUTE] = 1;
174 dmc->tnd_table[0][0][0][0] = 0;
175 dmc->tnd_table[1][0][0][0] = 0;
176
177 dmc->apu = NULL;
178 dmc->frame_sequence_count = 0;
179 dmc->frame_sequence_length = 7458;
180 dmc->frame_sequence_steps = 4;
181
182 for(c=0;c<2;++c)
183 for(t=0;t<3;++t)
184 dmc->sm[c][t] = 128;
185
186 return dmc;
187 }
188
189
NES_DMC_np_Destroy(void * chip)190 void NES_DMC_np_Destroy(void* chip)
191 {
192 free(chip);
193 }
194
NES_DMC_np_GetDamp(void * chip)195 int NES_DMC_np_GetDamp(void* chip)
196 {
197 NES_DMC* dmc = (NES_DMC*)chip;
198
199 return (dmc->damp<<1)|dmc->dac_lsb;
200 }
201
NES_DMC_np_SetMask(void * chip,int m)202 void NES_DMC_np_SetMask(void* chip, int m)
203 {
204 NES_DMC* dmc = (NES_DMC*)chip;
205
206 dmc->mask = m;
207 }
208
NES_DMC_np_SetStereoMix(void * chip,int trk,INT16 mixl,INT16 mixr)209 void NES_DMC_np_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr)
210 {
211 NES_DMC* dmc = (NES_DMC*)chip;
212
213 if (trk < 0) return;
214 if (trk > 2) return;
215 dmc->sm[0][trk] = mixl;
216 dmc->sm[1][trk] = mixr;
217 }
218
FrameSequence(NES_DMC * dmc,int s)219 static void FrameSequence(NES_DMC* dmc, int s)
220 {
221 //DEBUG_OUT("FrameSequence: %d\n",s);
222
223 if (s > 3) return; // no operation in step 4
224
225 if (dmc->apu != NULL)
226 {
227 NES_APU_np_FrameSequence(dmc->apu, s);
228 }
229
230 if (s == 0 && (dmc->frame_sequence_steps == 4))
231 {
232 dmc->frame_irq = true;
233 }
234
235 // 240hz clock
236 {
237 bool divider = false;
238
239 // triangle linear counter
240 if (dmc->linear_counter_halt)
241 {
242 dmc->linear_counter = dmc->linear_counter_reload;
243 }
244 else
245 {
246 if (dmc->linear_counter > 0) --dmc->linear_counter;
247 }
248 if (!dmc->linear_counter_control)
249 {
250 dmc->linear_counter_halt = false;
251 }
252
253 // noise envelope
254 //bool divider = false;
255 if (dmc->envelope_write)
256 {
257 dmc->envelope_write = false;
258 dmc->envelope_counter = 15;
259 dmc->envelope_div = 0;
260 }
261 else
262 {
263 ++dmc->envelope_div;
264 if (dmc->envelope_div > dmc->envelope_div_period)
265 {
266 divider = true;
267 dmc->envelope_div = 0;
268 }
269 }
270 if (divider)
271 {
272 if (dmc->envelope_loop && dmc->envelope_counter == 0)
273 dmc->envelope_counter = 15;
274 else if (dmc->envelope_counter > 0)
275 --dmc->envelope_counter; // TODO: Make this work.
276 }
277 }
278
279 // 120hz clock
280 if ((s&1) == 0)
281 {
282 // triangle length counter
283 if (!dmc->linear_counter_control && (dmc->length_counter[0] > 0))
284 --dmc->length_counter[0];
285
286 // noise length counter
287 if (!dmc->envelope_loop && (dmc->length_counter[1] > 0))
288 --dmc->length_counter[1];
289 }
290
291 }
292
293 // 三角波チャンネルの計算 戻り値は0-15
calc_tri(NES_DMC * dmc,UINT32 clocks)294 UINT32 calc_tri(NES_DMC* dmc, UINT32 clocks)
295 {
296 static UINT32 tritbl[32] =
297 {
298 0, 1, 2, 3, 4, 5, 6, 7,
299 8, 9,10,11,12,13,14,15,
300 15,14,13,12,11,10, 9, 8,
301 7, 6, 5, 4, 3, 2, 1, 0
302 };
303
304 if (dmc->linear_counter > 0 && dmc->length_counter[0] > 0
305 && (!dmc->option[OPT_TRI_MUTE] || dmc->tri_freq > 0))
306 {
307 dmc->counter[0] += clocks;
308 while (dmc->counter[0] > dmc->tri_freq)
309 {
310 dmc->tphase = (dmc->tphase + 1) & 31;
311 dmc->counter[0] -= (dmc->tri_freq + 1);
312 }
313 }
314 // Note: else-block added by VB
315 else if (dmc->option[OPT_TRI_NULL])
316 {
317 if (dmc->tphase && dmc->tphase < 31)
318 {
319 // Finish the Triangle wave to prevent clicks.
320 dmc->counter[0] += clocks;
321 while(dmc->counter[0] > dmc->tri_freq && dmc->tphase)
322 {
323 dmc->tphase = (dmc->tphase + 1) & 31;
324 dmc->counter[0] -= (dmc->tri_freq + 1);
325 }
326 }
327 }
328
329 //UINT32 ret = tritbl[tphase];
330 //return ret;
331 return tritbl[dmc->tphase];
332 }
333
334 // ノイズチャンネルの計算 戻り値は0-127
335 // 低サンプリングレートで合成するとエイリアスノイズが激しいので
336 // ノイズだけはこの関数内で高クロック合成し、簡易なサンプリングレート
337 // 変換を行っている。
calc_noise(NES_DMC * dmc,UINT32 clocks)338 UINT32 calc_noise(NES_DMC* dmc, UINT32 clocks)
339 {
340 UINT32 env, last, count, accum, clocks_accum;
341
342 env = dmc->envelope_disable ? dmc->noise_volume : dmc->envelope_counter;
343 if (dmc->length_counter[1] < 1) env = 0;
344
345 last = (dmc->noise & 0x4000) ? env : 0;
346 if (clocks < 1) return last;
347
348 // simple anti-aliasing (noise requires it, even when oversampling is off)
349 count = 0;
350 accum = 0;
351
352 dmc->counter[1] += clocks;
353 // assert(dmc->nfreq > 0); // prevent infinite loop
354 if (dmc->nfreq <= 0) // prevent infinite loop -VB
355 return last;
356 while (dmc->counter[1] >= dmc->nfreq)
357 {
358 // tick the noise generator
359 UINT32 feedback = (dmc->noise&1) ^ ((dmc->noise&dmc->noise_tap)?1:0);
360 dmc->noise = (dmc->noise>>1) | (feedback<<14);
361
362 ++count;
363 accum += last;
364 last = (dmc->noise & 0x4000) ? env : 0;
365
366 dmc->counter[1] -= dmc->nfreq;
367 }
368
369 if (count < 1) // no change over interval, don't anti-alias
370 {
371 return last;
372 }
373
374 clocks_accum = clocks - dmc->counter[1];
375 // count = number of samples in accum
376 // counter[1] = number of clocks since last sample
377
378 accum = (accum * clocks_accum) + (last * dmc->counter[1] * count);
379 // note accum as an average is already premultiplied by count
380
381 return accum / (clocks * count);
382 }
383
384 // DMCチャンネルの計算 戻り値は0-127
calc_dmc(NES_DMC * dmc,UINT32 clocks)385 UINT32 calc_dmc(NES_DMC* dmc, UINT32 clocks)
386 {
387 dmc->counter[2] += clocks;
388 // assert(dmc->dfreq > 0); // prevent infinite loop
389 if (dmc->dfreq <= 0) // prevent infinite loop -VB
390 return (dmc->damp<<1) + dmc->dac_lsb;
391 while (dmc->counter[2] >= dmc->dfreq)
392 {
393 if ( dmc->data != 0x100 ) // data = 0x100 は EMPTY を意味する。
394 {
395 if ((dmc->data & 1) && (dmc->damp < 63))
396 dmc->damp++;
397 else if (!(dmc->data & 1) && (0 < dmc->damp))
398 dmc->damp--;
399 dmc->data >>=1;
400 }
401
402 if ( dmc->data == 0x100 && dmc->active )
403 {
404 //dmc->memory->Read(dmc->daddress, dmc->data);
405 dmc->data = dmc->memory[dmc->daddress];
406 dmc->data |= (dmc->data&0xFF)|0x10000; // 8bitシフトで 0x100 になる
407 if ( dmc->length > 0 )
408 {
409 dmc->daddress = ((dmc->daddress+1)&0xFFFF)|0x8000 ;
410 dmc->length --;
411 }
412 }
413
414 if ( dmc->length == 0 ) // 最後のフェッチが終了したら(再生完了より前に)即座に終端処理
415 {
416 if (dmc->mode & 1)
417 {
418 dmc->daddress = ((dmc->adr_reg<<6)|0xC000);
419 dmc->length = (dmc->len_reg<<4)+1;
420 }
421 else
422 {
423 dmc->irq = (dmc->mode==2&&dmc->active)?1:0; // 直前がactiveだったときはIRQ発行
424 dmc->active = false;
425 }
426 }
427
428 dmc->counter[2] -= dmc->dfreq;
429 }
430
431 return (dmc->damp<<1) + dmc->dac_lsb;
432 }
433
TickFrameSequence(NES_DMC * dmc,UINT32 clocks)434 static void TickFrameSequence(NES_DMC* dmc, UINT32 clocks)
435 {
436 dmc->frame_sequence_count += clocks;
437 while (dmc->frame_sequence_count > dmc->frame_sequence_length)
438 {
439 FrameSequence(dmc, dmc->frame_sequence_step);
440 dmc->frame_sequence_count -= dmc->frame_sequence_length;
441 ++dmc->frame_sequence_step;
442 if(dmc->frame_sequence_step >= dmc->frame_sequence_steps)
443 dmc->frame_sequence_step = 0;
444 }
445 }
446
Tick(NES_DMC * dmc,UINT32 clocks)447 static void Tick(NES_DMC* dmc, UINT32 clocks)
448 {
449 dmc->out[0] = calc_tri(dmc, clocks);
450 dmc->out[1] = calc_noise(dmc, clocks);
451 dmc->out[2] = calc_dmc(dmc, clocks);
452 }
453
NES_DMC_np_Render(void * chip,INT32 b[2])454 UINT32 NES_DMC_np_Render(void* chip, INT32 b[2])
455 {
456 NES_DMC* dmc = (NES_DMC*)chip;
457 UINT32 clocks;
458 INT32 m[3];
459
460 COUNTER_iup(dmc->tick_count); // increase counter (overflows after 255)
461 clocks = (COUNTER_value(dmc->tick_count) - dmc->tick_last) & 0xFF;
462 TickFrameSequence(dmc, clocks);
463 Tick(dmc, clocks);
464 dmc->tick_last = COUNTER_value(dmc->tick_count);
465
466 dmc->out[0] = (dmc->mask & 1) ? 0 : dmc->out[0];
467 dmc->out[1] = (dmc->mask & 2) ? 0 : dmc->out[1];
468 dmc->out[2] = (dmc->mask & 4) ? 0 : dmc->out[2];
469
470 m[0] = dmc->tnd_table[0][dmc->out[0]][0][0];
471 m[1] = dmc->tnd_table[0][0][dmc->out[1]][0];
472 m[2] = dmc->tnd_table[0][0][0][dmc->out[2]];
473
474 if (dmc->option[OPT_NONLINEAR_MIXER])
475 {
476 INT32 ref = m[0] + m[1] + m[2];
477 INT32 voltage = dmc->tnd_table[1][dmc->out[0]][dmc->out[1]][dmc->out[2]];
478 int i;
479 if (ref)
480 {
481 for (i=0; i < 3; ++i)
482 m[i] = (m[i] * voltage) / ref;
483 }
484 else
485 {
486 for (i=0; i < 3; ++i)
487 m[i] = voltage;
488 }
489 }
490
491 // anti-click nullifies any 4011 write but preserves nonlinearity
492 if (dmc->option[OPT_DPCM_ANTI_CLICK])
493 {
494 if (dmc->dmc_pop) // $4011 will cause pop this frame
495 {
496 // adjust offset to counteract pop
497 dmc->dmc_pop_offset += dmc->dmc_pop_follow - m[2];
498 dmc->dmc_pop = false;
499
500 // prevent overflow, keep headspace at edges
501 //const INT32 OFFSET_MAX = (1 << 30) - (4 << 16);
502 #define OFFSET_MAX ((1 << 30) - (4 << 16))
503 if (dmc->dmc_pop_offset > OFFSET_MAX) dmc->dmc_pop_offset = OFFSET_MAX;
504 if (dmc->dmc_pop_offset < -OFFSET_MAX) dmc->dmc_pop_offset = -OFFSET_MAX;
505 }
506 dmc->dmc_pop_follow = m[2]; // remember previous position
507
508 m[2] += dmc->dmc_pop_offset; // apply offset
509
510 // TODO implement this in a better way
511 // roll off offset (not ideal, but prevents overflow)
512 if (dmc->dmc_pop_offset > 0) --dmc->dmc_pop_offset;
513 else if (dmc->dmc_pop_offset < 0) ++dmc->dmc_pop_offset;
514 }
515
516 b[0] = m[0] * dmc->sm[0][0];
517 b[0] += m[1] * dmc->sm[0][1];
518 b[0] +=-m[2] * dmc->sm[0][2];
519 b[0] >>= 7-2;
520
521 b[1] = m[0] * dmc->sm[1][0];
522 b[1] += m[1] * dmc->sm[1][1];
523 b[1] +=-m[2] * dmc->sm[1][2];
524 b[1] >>= 7-2;
525
526 return 2;
527 }
528
529
NES_DMC_np_SetClock(void * chip,double c)530 void NES_DMC_np_SetClock(void* chip, double c)
531 {
532 NES_DMC* dmc = (NES_DMC*)chip;
533
534 dmc->clock = (UINT32)(c);
535
536 if (abs(dmc->clock - DEFAULT_CLK_PAL) <= 1000) // check for approximately DEFAULT_CLK_PAL
537 NES_DMC_np_SetPal(dmc, true);
538 else
539 NES_DMC_np_SetPal(dmc, false);
540 }
541
NES_DMC_np_SetRate(void * chip,double r)542 void NES_DMC_np_SetRate(void* chip, double r)
543 {
544 NES_DMC* dmc = (NES_DMC*)chip;
545
546 dmc->rate = (UINT32)(r?r:DEFAULT_RATE);
547
548 COUNTER_init(dmc->tick_count, dmc->clock, dmc->rate);
549 dmc->tick_last = 0;
550 }
551
NES_DMC_np_SetPal(void * chip,bool is_pal)552 void NES_DMC_np_SetPal(void* chip, bool is_pal)
553 {
554 NES_DMC* dmc = (NES_DMC*)chip;
555
556 dmc->pal = (is_pal ? 1 : 0);
557 // set CPU cycles in frame_sequence
558 dmc->frame_sequence_length = is_pal ? 8314 : 7458;
559 }
560
NES_DMC_np_SetAPU(void * chip,void * apu_)561 void NES_DMC_np_SetAPU(void* chip, void* apu_)
562 {
563 NES_DMC* dmc = (NES_DMC*)chip;
564
565 dmc->apu = apu_;
566 }
567
568 // Initializing TRI, NOISE, DPCM mixing table
InitializeTNDTable(NES_DMC * dmc,double wt,double wn,double wd)569 static void InitializeTNDTable(NES_DMC* dmc, double wt, double wn, double wd)
570 {
571 // volume adjusted by 0.75 based on empirical measurements
572 const double MASTER = 8192.0 * 0.75;
573 // truthfully, the nonlinear curve does not appear to match well
574 // with my tests, triangle in particular seems too quiet relatively.
575 // do more testing of the APU/DMC DAC later
576
577 int t, n, d;
578
579 { // Linear Mixer
580 for(t=0; t<16 ; t++) {
581 for(n=0; n<16; n++) {
582 for(d=0; d<128; d++) {
583 dmc->tnd_table[0][t][n][d] = (UINT32)(MASTER*(3.0*t+2.0*n+d)/208.0);
584 }
585 }
586 }
587 }
588 { // Non-Linear Mixer
589 dmc->tnd_table[1][0][0][0] = 0;
590 for(t=0; t<16 ; t++) {
591 for(n=0; n<16; n++) {
592 for(d=0; d<128; d++) {
593 if(t!=0||n!=0||d!=0)
594 dmc->tnd_table[1][t][n][d] = (UINT32)((MASTER*159.79)/(100.0+1.0/((double)t/wt+(double)n/wn+(double)d/wd)));
595 }
596 }
597 }
598 }
599
600 }
601
NES_DMC_np_Reset(void * chip)602 void NES_DMC_np_Reset(void* chip)
603 {
604 NES_DMC* dmc = (NES_DMC*)chip;
605 int i;
606 dmc->mask = 0;
607
608 InitializeTNDTable(dmc,8227,12241,22638);
609
610 dmc->counter[0] = 0;
611 dmc->counter[1] = 0;
612 dmc->counter[2] = 0;
613 dmc->tphase = 0;
614 dmc->nfreq = wavlen_table[0][0];
615 dmc->dfreq = freq_table[0][0];
616
617 dmc->envelope_div = 0;
618 dmc->length_counter[0] = 0;
619 dmc->length_counter[1] = 0;
620 dmc->linear_counter = 0;
621 dmc->envelope_counter = 0;
622
623 dmc->frame_irq = false;
624 dmc->frame_irq_enable = false;
625 dmc->frame_sequence_count = 0;
626 dmc->frame_sequence_steps = 4;
627 dmc->frame_sequence_step = 0;
628
629 for (i = 0; i < 0x10; i++)
630 NES_DMC_np_Write(dmc, 0x4008 + i, 0);
631
632 dmc->irq = false;
633 NES_DMC_np_Write(dmc, 0x4015, 0x00);
634 if (dmc->option[OPT_UNMUTE_ON_RESET])
635 NES_DMC_np_Write(dmc, 0x4015, 0x0f);
636
637 dmc->out[0] = dmc->out[1] = dmc->out[2] = 0;
638 dmc->tri_freq = 0;
639 dmc->damp = 0;
640 dmc->dmc_pop = false;
641 dmc->dmc_pop_offset = 0;
642 dmc->dmc_pop_follow = 0;
643 dmc->dac_lsb = 0;
644 dmc->data = 0x100;
645 dmc->adr_reg = 0;
646 dmc->active = false;
647 dmc->length = 0;
648 dmc->len_reg = 0;
649 dmc->daddress = 0;
650 dmc->noise = 1;
651 dmc->noise_tap = (1<<1);
652 if (dmc->option[OPT_RANDOMIZE_NOISE])
653 {
654 dmc->noise |= rand();
655 }
656
657 NES_DMC_np_SetRate(dmc, dmc->rate);
658 }
659
NES_DMC_np_SetMemory(void * chip,const UINT8 * r)660 void NES_DMC_np_SetMemory(void* chip, const UINT8* r)
661 {
662 NES_DMC* dmc = (NES_DMC*)chip;
663
664 dmc->memory = r;
665 }
666
NES_DMC_np_SetOption(void * chip,int id,int val)667 void NES_DMC_np_SetOption(void* chip, int id, int val)
668 {
669 NES_DMC* dmc = (NES_DMC*)chip;
670
671 if(id<OPT_END)
672 {
673 dmc->option[id] = val;
674 if(id==OPT_NONLINEAR_MIXER)
675 InitializeTNDTable(dmc, 8227,12241,22638);
676 }
677 }
678
NES_DMC_np_Write(void * chip,UINT32 adr,UINT32 val)679 bool NES_DMC_np_Write(void* chip, UINT32 adr, UINT32 val)
680 {
681 static const UINT8 length_table[32] = {
682 0x0A, 0xFE,
683 0x14, 0x02,
684 0x28, 0x04,
685 0x50, 0x06,
686 0xA0, 0x08,
687 0x3C, 0x0A,
688 0x0E, 0x0C,
689 0x1A, 0x0E,
690 0x0C, 0x10,
691 0x18, 0x12,
692 0x30, 0x14,
693 0x60, 0x16,
694 0xC0, 0x18,
695 0x48, 0x1A,
696 0x10, 0x1C,
697 0x20, 0x1E
698 };
699 NES_DMC* dmc = (NES_DMC*)chip;
700
701 if (adr == 0x4015)
702 {
703 dmc->enable[0] = (val & 4) ? true : false;
704 dmc->enable[1] = (val & 8) ? true : false;
705
706 if (!dmc->enable[0])
707 {
708 dmc->length_counter[0] = 0;
709 }
710 if (!dmc->enable[1])
711 {
712 dmc->length_counter[1] = 0;
713 }
714
715 if ((val & 16)&&!dmc->active)
716 {
717 dmc->enable[2] = dmc->active = true;
718 dmc->daddress = (0xC000 | (dmc->adr_reg << 6));
719 dmc->length = (dmc->len_reg << 4) + 1;
720 dmc->irq = 0;
721 }
722 else if (!(val & 16))
723 {
724 dmc->enable[2] = dmc->active = false;
725 }
726
727 dmc->reg[adr-0x4008] = val;
728 return true;
729 }
730
731 if (adr == 0x4017)
732 {
733 //DEBUG_OUT("4017 = %02X\n", val);
734 dmc->frame_irq_enable = ((val & 0x40) == 0x40);
735 dmc->frame_irq = (dmc->frame_irq_enable ? dmc->frame_irq : 0);
736 dmc->frame_sequence_count = 0;
737 if (val & 0x80)
738 {
739 dmc->frame_sequence_steps = 5;
740 dmc->frame_sequence_step = 0;
741 FrameSequence(dmc, dmc->frame_sequence_step);
742 ++dmc->frame_sequence_step;
743 }
744 else
745 {
746 dmc->frame_sequence_steps = 4;
747 dmc->frame_sequence_step = 1;
748 }
749 }
750
751 if (adr<0x4008||0x4013<adr)
752 return false;
753
754 dmc->reg[adr-0x4008] = val&0xff;
755
756 //DEBUG_OUT("$%04X %02X\n", adr, val);
757
758 switch (adr)
759 {
760
761 // tri
762
763 case 0x4008:
764 dmc->linear_counter_control = (val >> 7) & 1;
765 dmc->linear_counter_reload = val & 0x7F;
766 break;
767
768 case 0x4009:
769 break;
770
771 case 0x400a:
772 dmc->tri_freq = val | (dmc->tri_freq & 0x700) ;
773 if (dmc->counter[0] > dmc->tri_freq) dmc->counter[0] = dmc->tri_freq;
774 break;
775
776 case 0x400b:
777 dmc->tri_freq = (dmc->tri_freq & 0xff) | ((val & 0x7) << 8) ;
778 if (dmc->counter[0] > dmc->tri_freq) dmc->counter[0] = dmc->tri_freq;
779 dmc->linear_counter_halt = true;
780 if (dmc->enable[0])
781 {
782 dmc->length_counter[0] = length_table[(val >> 3) & 0x1f];
783 }
784 break;
785
786 // noise
787
788 case 0x400c:
789 dmc->noise_volume = val & 15;
790 dmc->envelope_div_period = val & 15;
791 dmc->envelope_disable = (val >> 4) & 1;
792 dmc->envelope_loop = (val >> 5) & 1;
793 break;
794
795 case 0x400d:
796 break;
797
798 case 0x400e:
799 if (dmc->option[OPT_ENABLE_PNOISE])
800 dmc->noise_tap = (val & 0x80) ? (1<<6) : (1<<1);
801 else
802 dmc->noise_tap = (1<<1);
803 dmc->nfreq = wavlen_table[dmc->pal][val&15];
804 if (dmc->counter[1] > dmc->nfreq) dmc->counter[1] = dmc->nfreq;
805 break;
806
807 case 0x400f:
808 if (dmc->enable[1])
809 {
810 dmc->length_counter[1] = length_table[(val >> 3) & 0x1f];
811 }
812 dmc->envelope_write = true;
813 break;
814
815 // dmc
816
817 case 0x4010:
818 dmc->mode = (val >> 6) & 3;
819 dmc->dfreq = freq_table[dmc->pal][val&15];
820 if (dmc->counter[2] > dmc->dfreq) dmc->counter[2] = dmc->dfreq;
821 break;
822
823 case 0x4011:
824 if (dmc->option[OPT_ENABLE_4011])
825 {
826 dmc->damp = (val >> 1) & 0x3f;
827 dmc->dac_lsb = val & 1;
828 dmc->dmc_pop = true;
829 }
830 break;
831
832 case 0x4012:
833 dmc->adr_reg = val&0xff;
834 // ここでdaddressは更新されない
835 break;
836
837 case 0x4013:
838 dmc->len_reg = val&0xff;
839 // ここでlengthは更新されない
840 break;
841
842 default:
843 return false;
844 }
845
846 return true;
847 }
848
NES_DMC_np_Read(void * chip,UINT32 adr,UINT32 * val)849 bool NES_DMC_np_Read(void* chip, UINT32 adr, UINT32* val)
850 {
851 NES_DMC* dmc = (NES_DMC*)chip;
852
853 if (adr == 0x4015)
854 {
855 *val |= (dmc->irq?128:0)
856 | (dmc->frame_irq ? 0x40 : 0)
857 | (dmc->active?16:0)
858 | (dmc->length_counter[1]?8:0)
859 | (dmc->length_counter[0]?4:0)
860 ;
861
862 dmc->frame_irq = false;
863 return true;
864 }
865 else if (0x4008<=adr&&adr<=0x4014)
866 {
867 *val |= dmc->reg[adr-0x4008];
868 return true;
869 }
870 else
871 return false;
872 }
873