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