1 // Based on MAME driver by Juergen Buchmueller, Mike Balfour, Howie Cohen, Olivier Galibert, Aaron Giles
2
3 #include "burnint.h"
4 #include "upd7759.h"
5 #include "downsample.h"
6 #include "timer.h"
7 #include <math.h>
8 #include "biquad.h"
9
10 #define FRAC_BITS 20
11 #define FRAC_ONE (1 << FRAC_BITS)
12 #define FRAC_MASK (FRAC_ONE - 1)
13
14 static INT32 SlaveMode = 0;
15
16 /* chip states */
17 enum
18 {
19 STATE_IDLE,
20 STATE_DROP_DRQ,
21 STATE_START,
22 STATE_FIRST_REQ,
23 STATE_LAST_SAMPLE,
24 STATE_DUMMY1,
25 STATE_ADDR_MSB,
26 STATE_ADDR_LSB,
27 STATE_DUMMY2,
28 STATE_BLOCK_HEADER,
29 STATE_NIBBLE_COUNT,
30 STATE_NIBBLE_MSN,
31 STATE_NIBBLE_LSN
32 };
33
34 struct upd7759_chip
35 {
36 INT32 ChipNum; // for callback
37 /* internal clock to output sample rate mapping */
38 UINT32 pos; /* current output sample position */
39 UINT32 step; /* step value per output sample */
40 double clock_period;
41 INT32 start_delay;
42
43 /* I/O lines */
44 UINT8 fifo_in; /* last data written to the sound chip */
45 UINT8 reset; /* current state of the RESET line */
46 UINT8 start; /* current state of the START line */
47 UINT8 drq; /* current state of the DRQ line */
48 void (*drqcallback)(INT32 param); /* drq callback */
49
50 /* internal state machine */
51 INT8 state; /* current overall chip state */
52 INT32 clocks_left; /* number of clocks left in this state */
53 UINT16 nibbles_left; /* number of ADPCM nibbles left to process */
54 UINT8 repeat_count; /* number of repeats remaining in current repeat block */
55 INT8 post_drq_state; /* state we will be in after the DRQ line is dropped */
56 INT32 post_drq_clocks; /* clocks that will be left after the DRQ line is dropped */
57 UINT8 req_sample; /* requested sample number */
58 UINT8 last_sample; /* last sample number available */
59 UINT8 block_header; /* header byte */
60 UINT8 sample_rate; /* number of UPD clocks per ADPCM nibble */
61 UINT8 first_valid_header; /* did we get our first valid header yet? */
62 UINT32 offset; /* current ROM offset */
63 UINT32 repeat_offset; /* current ROM repeat offset */
64
65 /* ADPCM processing */
66 INT8 adpcm_state; /* ADPCM state index */
67 UINT8 adpcm_data; /* current byte of ADPCM data */
68 INT16 sample; /* current sample value */
69 INT32 sample_counts; // this frame
70
71 /* ROM access */
72 UINT8 * rom; /* pointer to ROM data or NULL for slave mode */
73 UINT8 * rombase; /* pointer to ROM data or NULL for slave mode */
74 UINT32 romoffset; /* ROM offset to make save/restore easier */
75
76 // downsampler
77 Downsampler resamp;
78 INT16 * out_buf;
79 INT16 * out_buf_linear;
80 INT16 * out_buf_linear_resampled;
81 INT32 out_buf_size;
82 INT32 out_pos;
83
84 // filter
85 BIQ biquadL;
86 BIQ biquadR;
87
88 // stream sync
89 INT32 (*pTotalCyclesCB)();
90 INT32 nCpuMHZ;
91
92 /* route */
93 double volume;
94 INT32 output_dir;
95 };
96
97 static struct upd7759_chip *Chips[2] = { NULL, NULL }; // more?
98 static struct upd7759_chip *Chip = NULL;
99
100 static INT32 nNumChips = 0;
101
102 static const INT32 upd7759_step[16][16] =
103 {
104 { 0, 0, 1, 2, 3, 5, 7, 10, 0, 0, -1, -2, -3, -5, -7, -10 },
105 { 0, 1, 2, 3, 4, 6, 8, 13, 0, -1, -2, -3, -4, -6, -8, -13 },
106 { 0, 1, 2, 4, 5, 7, 10, 15, 0, -1, -2, -4, -5, -7, -10, -15 },
107 { 0, 1, 3, 4, 6, 9, 13, 19, 0, -1, -3, -4, -6, -9, -13, -19 },
108 { 0, 2, 3, 5, 8, 11, 15, 23, 0, -2, -3, -5, -8, -11, -15, -23 },
109 { 0, 2, 4, 7, 10, 14, 19, 29, 0, -2, -4, -7, -10, -14, -19, -29 },
110 { 0, 3, 5, 8, 12, 16, 22, 33, 0, -3, -5, -8, -12, -16, -22, -33 },
111 { 1, 4, 7, 10, 15, 20, 29, 43, -1, -4, -7, -10, -15, -20, -29, -43 },
112 { 1, 4, 8, 13, 18, 25, 35, 53, -1, -4, -8, -13, -18, -25, -35, -53 },
113 { 1, 6, 10, 16, 22, 31, 43, 64, -1, -6, -10, -16, -22, -31, -43, -64 },
114 { 2, 7, 12, 19, 27, 37, 51, 76, -2, -7, -12, -19, -27, -37, -51, -76 },
115 { 2, 9, 16, 24, 34, 46, 64, 96, -2, -9, -16, -24, -34, -46, -64, -96 },
116 { 3, 11, 19, 29, 41, 57, 79, 117, -3, -11, -19, -29, -41, -57, -79, -117 },
117 { 4, 13, 24, 36, 50, 69, 96, 143, -4, -13, -24, -36, -50, -69, -96, -143 },
118 { 4, 16, 29, 44, 62, 85, 118, 175, -4, -16, -29, -44, -62, -85, -118, -175 },
119 { 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214 },
120 };
121
122 static const INT32 upd7759_state[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 };
123
UpdateAdpcm(INT32 Data)124 inline static void UpdateAdpcm(INT32 Data)
125 {
126 Chip->sample += upd7759_step[Chip->adpcm_state][Data];
127 Chip->adpcm_state += upd7759_state[Data];
128
129 /* clamp the state to 0..15 */
130 if (Chip->adpcm_state < 0)
131 Chip->adpcm_state = 0;
132 else if (Chip->adpcm_state > 15)
133 Chip->adpcm_state = 15;
134 }
135
SyncUPD(upd7759_chip * Chippy,INT32 cycles)136 static INT32 SyncUPD(upd7759_chip *Chippy, INT32 cycles)
137 {
138 return (INT32)((double)cycles * ((double)(Chippy->pTotalCyclesCB()) / ((double)Chippy->nCpuMHZ / (nBurnFPS / 100.0000))));
139 }
140
141 static void UpdateStream(INT32 chip, INT32 end);
142
UPD7759AdvanceState()143 static void UPD7759AdvanceState()
144 {
145 switch (Chip->state)
146 {
147 /* Idle state: we stick around here while there's nothing to do */
148 case STATE_IDLE:
149 Chip->clocks_left = 4;
150 break;
151
152 /* drop DRQ state: update to the intended state */
153 case STATE_DROP_DRQ:
154 Chip->drq = 0;
155
156 Chip->clocks_left = Chip->post_drq_clocks;
157 Chip->state = Chip->post_drq_state;
158 break;
159
160 /* Start state: we begin here as soon as a sample is triggered */
161 case STATE_START:
162 Chip->req_sample = (Chip->rom) ? Chip->fifo_in : 0x10;
163 /* 35+ cycles after we get here, the /DRQ goes low
164 * (first byte (number of samples in ROM) should be sent in response)
165 *
166 * (35 is the minimum number of cycles I found during heavy tests.
167 * Depending on the state the chip was in just before the /MD was set to 0 (reset, standby
168 * or just-finished-playing-previous-sample) this number can range from 35 up to ~24000).
169 * It also varies slightly from test to test, but not much - a few cycles at most.) */
170 Chip->clocks_left = 70 + Chip->start_delay; /* 35 - breaks cotton */
171 Chip->state = STATE_FIRST_REQ;
172 break;
173
174 /* First request state: issue a request for the first byte */
175 /* The expected response will be the index of the last sample */
176 case STATE_FIRST_REQ:
177 Chip->drq = 1;
178
179 /* 44 cycles later, we will latch this value and request another byte */
180 Chip->clocks_left = 44;
181 Chip->state = STATE_LAST_SAMPLE;
182 break;
183
184 /* Last sample state: latch the last sample value and issue a request for the second byte */
185 /* The second byte read will be just a dummy */
186 case STATE_LAST_SAMPLE:
187 Chip->last_sample = Chip->rom ? Chip->rom[0] : Chip->fifo_in;
188
189 Chip->drq = 1;
190
191 /* 28 cycles later, we will latch this value and request another byte */
192 Chip->clocks_left = 28; /* 28 - breaks cotton */
193 Chip->state = (Chip->req_sample > Chip->last_sample) ? STATE_IDLE : STATE_DUMMY1;
194 break;
195
196 /* First dummy state: ignore any data here and issue a request for the third byte */
197 /* The expected response will be the MSB of the sample address */
198 case STATE_DUMMY1:
199 Chip->drq = 1;
200
201 /* 32 cycles later, we will latch this value and request another byte */
202 Chip->clocks_left = 32;
203 Chip->state = STATE_ADDR_MSB;
204 break;
205
206 /* Address MSB state: latch the MSB of the sample address and issue a request for the fourth byte */
207 /* The expected response will be the LSB of the sample address */
208 case STATE_ADDR_MSB:
209 Chip->offset = ((Chip->rom) ? Chip->rom[Chip->req_sample * 2 + 5] : Chip->fifo_in) << 9;
210
211 Chip->drq = 1;
212
213 /* 44 cycles later, we will latch this value and request another byte */
214 Chip->clocks_left = 44;
215 Chip->state = STATE_ADDR_LSB;
216 break;
217
218 /* Address LSB state: latch the LSB of the sample address and issue a request for the fifth byte */
219 /* The expected response will be just a dummy */
220 case STATE_ADDR_LSB:
221 Chip->offset |= ((Chip->rom) ? Chip->rom[Chip->req_sample * 2 + 6] : Chip->fifo_in) << 1;
222 Chip->drq = 1;
223
224 /* 36 cycles later, we will latch this value and request another byte */
225 Chip->clocks_left = 36;
226 Chip->state = STATE_DUMMY2;
227 break;
228
229 /* Second dummy state: ignore any data here and issue a request for the the sixth byte */
230 /* The expected response will be the first block header */
231 case STATE_DUMMY2:
232 Chip->offset++;
233 Chip->first_valid_header = 0;
234 Chip->drq = 1;
235
236 /* 36?? cycles later, we will latch this value and request another byte */
237 Chip->clocks_left = 36;
238 Chip->state = STATE_BLOCK_HEADER;
239 break;
240
241 /* Block header state: latch the header and issue a request for the first byte afterwards */
242 case STATE_BLOCK_HEADER:
243
244 /* if we're in a repeat loop, reset the offset to the repeat point and decrement the count */
245 if (Chip->repeat_count)
246 {
247 Chip->repeat_count--;
248 Chip->offset = Chip->repeat_offset;
249 }
250 Chip->block_header = (Chip->rom) ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in;
251 Chip->drq = 1;
252
253 /* our next step depends on the top two bits */
254 switch (Chip->block_header & 0xc0)
255 {
256 case 0x00: /* silence */
257 Chip->clocks_left = 1024 * ((Chip->block_header & 0x3f) + 1);
258 Chip->state = (Chip->block_header == 0 && Chip->first_valid_header) ? STATE_IDLE : STATE_BLOCK_HEADER;
259 Chip->sample = 0;
260 Chip->adpcm_state = 0;
261 break;
262
263 case 0x40: /* 256 nibbles */
264 Chip->sample_rate = (Chip->block_header & 0x3f) + 1;
265 Chip->nibbles_left = 256;
266 Chip->clocks_left = 36; /* just a guess */
267 Chip->state = STATE_NIBBLE_MSN;
268 break;
269
270 case 0x80: /* n nibbles */
271 Chip->sample_rate = (Chip->block_header & 0x3f) + 1;
272 Chip->clocks_left = 36; /* just a guess */
273 Chip->state = STATE_NIBBLE_COUNT;
274 break;
275
276 case 0xc0: /* repeat loop */
277 Chip->repeat_count = (Chip->block_header & 7) + 1;
278 Chip->repeat_offset = Chip->offset;
279 Chip->clocks_left = 36; /* just a guess */
280 Chip->state = STATE_BLOCK_HEADER;
281 break;
282 }
283
284 /* set a flag when we get the first non-zero header */
285 if (Chip->block_header != 0)
286 Chip->first_valid_header = 1;
287 break;
288
289 /* Nibble count state: latch the number of nibbles to play and request another byte */
290 /* The expected response will be the first data byte */
291 case STATE_NIBBLE_COUNT:
292 Chip->nibbles_left = ((Chip->rom) ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in) + 1;
293 Chip->drq = 1;
294
295 /* 36?? cycles later, we will latch this value and request another byte */
296 Chip->clocks_left = 36; /* just a guess */
297 Chip->state = STATE_NIBBLE_MSN;
298 break;
299
300 /* MSN state: latch the data for this pair of samples and request another byte */
301 /* The expected response will be the next sample data or another header */
302 case STATE_NIBBLE_MSN:
303 Chip->adpcm_data = (Chip->rom) ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in;
304 UpdateAdpcm(Chip->adpcm_data >> 4);
305 Chip->drq = 1;
306
307 /* we stay in this state until the time for this sample is complete */
308 Chip->clocks_left = Chip->sample_rate * 4;
309 if (--Chip->nibbles_left == 0)
310 Chip->state = STATE_BLOCK_HEADER;
311 else
312 Chip->state = STATE_NIBBLE_LSN;
313 break;
314
315 /* LSN state: process the lower nibble */
316 case STATE_NIBBLE_LSN:
317 UpdateAdpcm(Chip->adpcm_data & 15);
318
319 /* we stay in this state until the time for this sample is complete */
320 Chip->clocks_left = Chip->sample_rate * 4;
321 if (--Chip->nibbles_left == 0)
322 Chip->state = STATE_BLOCK_HEADER;
323 else
324 Chip->state = STATE_NIBBLE_MSN;
325 break;
326 }
327
328 /* if there's a DRQ, fudge the state */
329 if (Chip->drq)
330 {
331 Chip->post_drq_state = Chip->state;
332 Chip->post_drq_clocks = Chip->clocks_left - 21;
333 Chip->state = STATE_DROP_DRQ;
334 Chip->clocks_left = 21;
335 }
336 }
337
UPD7759SlaveModeUpdate()338 static void UPD7759SlaveModeUpdate()
339 {
340 Chip = Chips[0]; // slave mode only available on Chip 0
341 UINT8 OldDrq = Chip->drq;
342
343 UpdateStream(Chip->ChipNum, 0);
344
345 UPD7759AdvanceState();
346
347 if (OldDrq != Chip->drq && Chip->drqcallback) {
348 (*Chip->drqcallback)(Chip->drq);
349 }
350
351 /* set a timer to go off when that is done */
352
353 if (Chip->state != STATE_IDLE) {
354 BurnTimerSetRetrig(0, (double)Chip->clocks_left * Chip->clock_period);
355 }
356 }
357
slave_timer_cb(INT32 n,INT32 c)358 INT32 slave_timer_cb(INT32 n, INT32 c)
359 {
360 UPD7759SlaveModeUpdate();
361
362 return 0;
363 }
364
365
UPD7759Update(INT32 chip,INT32 nLength)366 void UPD7759Update(INT32 chip, INT32 nLength)
367 {
368 #if defined FBNEO_DEBUG
369 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Update called without init\n"));
370 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759Update called with invalid chip %x\n"), chip);
371 #endif
372 Chip = Chips[chip];
373 INT32 ClocksLeft = Chip->clocks_left;
374 INT16 Sample = Chip->sample;
375 UINT32 Step = Chip->step;
376 UINT32 Pos = Chip->pos;
377
378 /* loop until done */
379 if (Chip->state != STATE_IDLE)
380 {
381 while (nLength != 0)
382 {
383 Chip->out_buf[Chip->out_pos] = Sample * 128;
384 Chip->out_pos = (Chip->out_pos + 1) % Chip->out_buf_size;
385
386 Chip->sample_counts++;
387
388 nLength--;
389
390 /* advance by the number of clocks/output sample */
391 Pos += Step;
392
393 /* handle clocks, but only in standalone mode */
394 while (Chip->rom && Pos >= FRAC_ONE)
395 {
396 INT32 ClocksThisTime = Pos >> FRAC_BITS;
397 if (ClocksThisTime > ClocksLeft)
398 ClocksThisTime = ClocksLeft;
399
400 /* clock once */
401 Pos -= ClocksThisTime * FRAC_ONE;
402 ClocksLeft -= ClocksThisTime;
403
404 /* if we're out of clocks, time to handle the next state */
405 if (ClocksLeft == 0)
406 {
407 /* advance one state; if we hit idle, bail */
408 UPD7759AdvanceState();
409 if (Chip->state == STATE_IDLE)
410 break;
411
412 /* reimport the variables that we cached */
413 ClocksLeft = Chip->clocks_left;
414 Sample = Chip->sample;
415 }
416 }
417 }
418 }
419
420 while (nLength > 0) { // fill unused with nothing
421 Chip->out_buf[Chip->out_pos] = 0;
422 Chip->out_pos = (Chip->out_pos + 1) % Chip->out_buf_size;
423
424 Chip->sample_counts++;
425
426 nLength--;
427 }
428
429 Chip->clocks_left = ClocksLeft;
430 Chip->pos = Pos;
431 }
432
UpdateStream(INT32 chip,INT32 end)433 static void UpdateStream(INT32 chip, INT32 end)
434 {
435 if (!pBurnSoundOut) return;
436
437 Chip = Chips[chip];
438
439 INT32 framelen = Chip->resamp.samples_to_source(nBurnSoundLen);
440 INT32 position = (end) ? framelen : SyncUPD(Chip, framelen);
441
442 INT32 samples = position - Chip->sample_counts;
443
444 if (samples < 1) return;
445
446 UPD7759Update(chip, samples);
447 }
448
UPD7759Render(INT16 * pSoundBuf,INT32 samples)449 void UPD7759Render(INT16 *pSoundBuf, INT32 samples)
450 {
451 #if defined FBNEO_DEBUG
452 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Render called without init\n"));
453 #endif
454
455 for (INT32 i = 0; i <= nNumChips; i++) // first chip 0, second chip 1...
456 {
457 UPD7759Render(i, pSoundBuf, samples);
458 }
459 }
460
UPD7759Render(INT32 chip,INT16 * pSoundBuf,INT32 samples)461 void UPD7759Render(INT32 chip, INT16 *pSoundBuf, INT32 samples)
462 {
463 #if defined FBNEO_DEBUG
464 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Render called without init\n"));
465 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759Render called with invalid chip %x\n"), chip);
466 #endif
467
468 Chip = Chips[chip];
469
470 if (Chip->pTotalCyclesCB) UpdateStream(chip, 1); // fill 'er up!
471
472 INT32 nFrameLength = Chip->resamp.samples_to_source(nBurnSoundLen);
473
474 // copy frame worth of samples out of circular buffer into linear buffer.
475 for (INT32 i = 0; i < nFrameLength; i++) {
476 INT32 cpos = (Chip->out_pos + nFrameLength + i) % Chip->out_buf_size;
477 Chip->out_buf_linear[i] = Chip->out_buf[cpos];
478 Chip->out_buf[cpos] = 0;
479 }
480
481 // resample to host rate
482 Chip->resamp.resample(Chip->out_buf_linear, Chip->out_buf_linear_resampled, samples, Chip->volume, Chip->output_dir);
483
484 // filter and mix into pSoundBuf
485 for (INT32 i = 0; i < samples; i++) {
486 INT32 l = Chip->biquadL.filter(Chip->out_buf_linear_resampled[i*2 + 0]);
487 INT32 r = Chip->biquadR.filter(Chip->out_buf_linear_resampled[i*2 + 1]);
488 pSoundBuf[i*2 + 0] = BURN_SND_CLIP(pSoundBuf[i*2 + 0] + l);
489 pSoundBuf[i*2 + 1] = BURN_SND_CLIP(pSoundBuf[i*2 + 1] + r);
490 }
491
492 Chip->sample_counts = 0; // ready for next frame!
493 }
494
UPD7759ResetINT(INT32 chip)495 static void UPD7759ResetINT(INT32 chip)
496 {
497 upd7759_chip *rChip = Chips[chip];
498
499 if (SlaveMode) {
500 BurnTimerReset();
501 }
502
503 rChip->pos = 0;
504 rChip->fifo_in = 0;
505 rChip->drq = 0;
506 rChip->state = STATE_IDLE;
507 rChip->clocks_left = 0;
508 rChip->nibbles_left = 0;
509 rChip->repeat_count = 0;
510 rChip->post_drq_state = STATE_IDLE;
511 rChip->post_drq_clocks = 0;
512 rChip->req_sample = 0;
513 rChip->last_sample = 0;
514 rChip->block_header = 0;
515 rChip->sample_rate = 0;
516 rChip->first_valid_header = 0;
517 rChip->offset = 0;
518 rChip->repeat_offset = 0;
519 rChip->adpcm_state = 0;
520 rChip->adpcm_data = 0;
521 rChip->sample = 0;
522 }
523
UPD7759Reset()524 void UPD7759Reset()
525 {
526 #if defined FBNEO_DEBUG
527 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Reset called without init\n"));
528 #endif
529
530 if (SlaveMode) {
531 BurnTimerReset();
532 }
533
534 for (INT32 i = 0; i <= nNumChips; i++) { // first chip 0, second chip 1...
535 UPD7759ResetINT(i);
536 }
537 }
538
UPD7759Init(INT32 chip,INT32 clock,UINT8 * pSoundData)539 void UPD7759Init(INT32 chip, INT32 clock, UINT8* pSoundData)
540 {
541 DebugSnd_UPD7759Initted = 1;
542
543 Chips[chip] = (struct upd7759_chip*)BurnMalloc(sizeof(upd7759_chip));
544 Chip = Chips[chip];
545
546 memset(Chip, 0, sizeof(upd7759_chip));
547
548 SlaveMode = 0;
549
550 Chip->ChipNum = chip;
551 // init resampler
552 Chip->resamp.init(clock / 4, nBurnSoundRate, 0);
553
554 // init filter (basically passthru w/these settings)
555 Chip->biquadL.init(FILT_LOWPASS, nBurnSoundRate, 15000, 0.554, 0.0);
556 Chip->biquadR.init(FILT_LOWPASS, nBurnSoundRate, 15000, 0.554, 0.0);
557
558 Chip->step = (INT32)(4 * FRAC_ONE);
559 Chip->state = STATE_IDLE;
560 Chip->clock_period = 1.0 / (double)clock;
561
562 // our 16bit (INT16) output buffer is 2 frames in length @ 640,000 kHz
563 // out_buf - circular buffer @ clock/4 rate
564 // out_buf_linear - linearized right before resampling and rendering
565 // out_buf_linear_resampled - resampled and ready to be filtered
566 Chip->out_buf_size = (clock / 4) * 100 / (nBurnFPS / 2); // word-size (byte size = *2)
567 Chip->out_buf = (INT16*)BurnMalloc(Chip->out_buf_size * sizeof(INT16));
568 Chip->out_buf_linear = (INT16*)BurnMalloc(Chip->out_buf_size * sizeof(INT16));
569 Chip->out_buf_linear_resampled = (INT16*)BurnMalloc(Chip->out_buf_size * sizeof(INT16));
570 Chip->out_pos = 0;
571
572 if (pSoundData) {
573 Chip->rom = pSoundData;
574 SlaveMode = 0;
575 } else {
576 SlaveMode = 1;
577 BurnTimerInit(&slave_timer_cb, NULL); // for high-freq timer
578 }
579
580 Chip->reset = 1;
581 Chip->start = 1;
582 Chip->volume = 1.00;
583 Chip->output_dir = BURN_SND_ROUTE_BOTH;
584
585 nNumChips = chip;
586
587 UPD7759Reset();
588 }
589
UPD7759SetStartDelay(INT32 chip,INT32 nDelay)590 void UPD7759SetStartDelay(INT32 chip, INT32 nDelay)
591 {
592 Chip = Chips[chip];
593
594 Chip->start_delay = nDelay;
595 }
596
UPD7759SetFilter(INT32 chip,INT32 nCutOff)597 void UPD7759SetFilter(INT32 chip, INT32 nCutOff)
598 {
599 #if defined FBNEO_DEBUG
600 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759SetFilter called without init\n"));
601 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759SetFilter called with invalid chip %i\n"), chip);
602 #endif
603
604 Chip = Chips[chip];
605
606 Chip->biquadL.init(FILT_LOWPASS, nBurnSoundRate, nCutOff, 0.554, 0.0);
607 Chip->biquadR.init(FILT_LOWPASS, nBurnSoundRate, nCutOff, 0.554, 0.0);
608 }
609
UPD7759SetRoute(INT32 chip,double nVolume,INT32 nRouteDir)610 void UPD7759SetRoute(INT32 chip, double nVolume, INT32 nRouteDir)
611 {
612 #if defined FBNEO_DEBUG
613 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759SetRoute called without init\n"));
614 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759SetRoute called with invalid chip %i\n"), chip);
615 #endif
616
617 Chip = Chips[chip];
618 Chip->volume = nVolume;
619 Chip->output_dir = nRouteDir;
620 }
621
UPD7759SetDrqCallback(INT32 chip,drqcallback Callback)622 void UPD7759SetDrqCallback(INT32 chip, drqcallback Callback)
623 {
624 #if defined FBNEO_DEBUG
625 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759SetDrqCallback called without init\n"));
626 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759SetDrqCallback called with invalid chip %x\n"), chip);
627 #endif
628
629 Chip = Chips[chip];
630 Chip->drqcallback = Callback;
631 }
632
UPD7759SetSyncCallback(INT32 chip,INT32 (* pCPUCyclesCB)(),INT32 nCPUMhz)633 void UPD7759SetSyncCallback(INT32 chip, INT32 (*pCPUCyclesCB)(), INT32 nCPUMhz)
634 {
635 #if defined FBNEO_DEBUG
636 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759SetSyncCallback called without init\n"));
637 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759SetSyncCallback called with invalid chip %x\n"), chip);
638 #endif
639
640 Chip = Chips[chip];
641 Chip->pTotalCyclesCB = pCPUCyclesCB;
642 Chip->nCpuMHZ = nCPUMhz;
643 }
644
UPD7759BusyRead(INT32 chip)645 INT32 UPD7759BusyRead(INT32 chip)
646 {
647 #if defined FBNEO_DEBUG
648 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759BusyRead called without init\n"));
649 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759BusyRead called with invalid chip %x\n"), chip);
650 #endif
651
652 Chip = Chips[chip];
653 return (Chip->state == STATE_IDLE);
654 }
655
UPD7759ResetWrite(INT32 chip,UINT8 Data)656 void UPD7759ResetWrite(INT32 chip, UINT8 Data)
657 {
658 #if defined FBNEO_DEBUG
659 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759ResetWrite called without init\n"));
660 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759ResetWrite called with invalid chip %x\n"), chip);
661 #endif
662
663 Chip = Chips[chip];
664
665 if (Chip->pTotalCyclesCB) UpdateStream(chip, 0);
666
667 UINT8 Oldreset = Chip->reset;
668 Chip->reset = (Data != 0);
669
670 if (Oldreset && !Chip->reset) {
671 UPD7759ResetINT(chip);
672 }
673 }
674
UPD7759StartWrite(INT32 chip,UINT8 Data)675 void UPD7759StartWrite(INT32 chip, UINT8 Data)
676 {
677 #if defined FBNEO_DEBUG
678 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759StartWrite called without init\n"));
679 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759StartWrite called with invalid chip %x\n"), chip);
680 #endif
681
682 Chip = Chips[chip];
683
684 UINT8 Oldstart = Chip->start;
685 Chip->start = (Data != 0);
686
687 if (Chip->pTotalCyclesCB) UpdateStream(chip, 0);
688
689 if (Chip->state == STATE_IDLE && !Oldstart && Chip->start && Chip->reset) {
690 Chip->state = STATE_START;
691
692 if (SlaveMode) UPD7759SlaveModeUpdate();
693 }
694 }
695
UPD7759PortWrite(INT32 chip,UINT8 Data)696 void UPD7759PortWrite(INT32 chip, UINT8 Data)
697 {
698 #if defined FBNEO_DEBUG
699 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759PortWrite called without init\n"));
700 if (chip > nNumChips) bprintf(PRINT_ERROR, _T("UPD7759PortWrite called with invalid chip %x\n"), chip);
701 #endif
702
703 Chip = Chips[chip];
704
705 Chip->fifo_in = Data;
706 }
707
UPD7759Scan(INT32 nAction,INT32 * pnMin)708 void UPD7759Scan(INT32 nAction, INT32 *pnMin)
709 {
710 #if defined FBNEO_DEBUG
711 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Scan called without init\n"));
712 #endif
713
714 if ((nAction & ACB_DRIVER_DATA) == 0) {
715 return;
716 }
717
718 if (pnMin != NULL) {
719 *pnMin = 0x029680;
720 }
721
722 if (SlaveMode) {
723 BurnTimerScan(nAction, pnMin);
724 }
725
726 for (INT32 i = 0; i <= nNumChips; i++) // first chip 0, second chip 1...
727 {
728 upd7759_chip *sChip = Chips[i];
729
730 SCAN_VAR(sChip->pos);
731 SCAN_VAR(sChip->step);
732 SCAN_VAR(sChip->fifo_in);
733 SCAN_VAR(sChip->reset);
734 SCAN_VAR(sChip->start);
735 SCAN_VAR(sChip->drq);
736 SCAN_VAR(sChip->state);
737 SCAN_VAR(sChip->clocks_left);
738 SCAN_VAR(sChip->nibbles_left);
739 SCAN_VAR(sChip->repeat_count);
740 SCAN_VAR(sChip->post_drq_state);
741 SCAN_VAR(sChip->post_drq_clocks);
742 SCAN_VAR(sChip->req_sample);
743 SCAN_VAR(sChip->last_sample);
744 SCAN_VAR(sChip->block_header);
745 SCAN_VAR(sChip->sample_rate);
746 SCAN_VAR(sChip->first_valid_header);
747 SCAN_VAR(sChip->offset);
748 SCAN_VAR(sChip->repeat_offset);
749 SCAN_VAR(sChip->adpcm_state);
750 SCAN_VAR(sChip->adpcm_data);
751 SCAN_VAR(sChip->sample);
752 SCAN_VAR(sChip->romoffset);
753 SCAN_VAR(sChip->volume);
754 SCAN_VAR(sChip->output_dir);
755 }
756 }
757
UPD7759Exit()758 void UPD7759Exit()
759 {
760 #if defined FBNEO_DEBUG
761 if (!DebugSnd_UPD7759Initted) bprintf(PRINT_ERROR, _T("UPD7759Exit called without init\n"));
762 #endif
763
764 for (INT32 i = 0; i <= nNumChips; i++) // first chip 0, second chip 1...
765 {
766 Chip = Chips[i];
767 if (Chip) {
768 Chip->biquadL.exit();
769 Chip->biquadR.exit();
770 BurnFree(Chip->out_buf);
771 BurnFree(Chip->out_buf_linear);
772 BurnFree(Chip->out_buf_linear_resampled);
773 BurnFree(Chips[i]);
774 }
775 }
776
777 if (SlaveMode) {
778 BurnTimerExit();
779 }
780
781 SlaveMode = 0;
782
783 DebugSnd_UPD7759Initted = 0;
784 nNumChips = 0;
785 }
786