1 /*
2 GI SP0256 Narrator Speech Processor
3 GI SPB640 Speech Buffer
4
5 By Joe Zbiciak. Ported to MESS by tim lindner.
6
7 Unimplemented:
8 - Microsequencer repeat count of zero
9 - Support for non bit-flipped ROMs
10 - SPB-640 perpherial/RAM bus
11
12 Copyright Joseph Zbiciak, all rights reserved.
13 Copyright tim lindner, all rights reserved.
14
15 - This source code is released as freeware for non-commercial purposes.
16 - You are free to use and redistribute this code in modified or
17 unmodified form, provided you list us in the credits.
18 - If you modify this source code, you must add a notice to each
19 modified source file that it has been changed. If you're a nice
20 person, you will clearly mark each change too. :)
21 - If you wish to use this for commercial purposes, please contact us at
22 intvnut@gmail.com (Joseph Zbiciak), tlindner@macmess.org (tim lindner)
23 - This entire notice must remain in the source code.
24 */
25
26 #include "burnint.h"
27 #include "sp0256.h"
28
29 #define READY_TIMER (0x0010)
30 #define CLOCK_DIVIDER (7*6*8)
31 #define HIGH_QUALITY
32
33 #define SCBUF_SIZE (4096) /* Must be power of 2 */
34 #define SCBUF_MASK (SCBUF_SIZE - 1)
35 #define PER_PAUSE (64) /* Equiv timing period for pauses. */
36 #define PER_NOISE (64) /* Equiv timing period for noise. */
37
38 #define FIFO_ADDR (0x1800 << 3) /* address of SPB260 speech FIFO. */
39
40 #define VERBOSE 0
41 #define DEBUG_FIFO 0
42
43 #define LOG(x) do { if (VERBOSE) bprintf x; } while (0)
44 #define LOG_FIFO(x) do { if (DEBUG_FIFO) bprintf x; } while (0)
45
46 #define SET_SBY(line_state) { \
47 if (m_sby_line != line_state) \
48 { \
49 m_sby_line = line_state; \
50 m_sby_cb(m_sby_line); \
51 } \
52 }
53
54 struct lpc12_t
55 {
56 INT32 rpt, cnt; /* Repeat counter, Period down-counter. */
57 UINT32 per, rng; /* Period, Amplitude, Random Number Generator */
58 INT32 amp;
59 INT16 f_coef[6]; /* F0 through F5. */
60 INT16 b_coef[6]; /* B0 through B5. */
61 INT16 z_data[6][2]; /* Time-delay data for the filter stages. */
62 UINT8 r[16]; /* The encoded register set. */
63 INT32 interp;
64 };
65
66 static void (*m_drq_cb)(UINT8) = NULL;
67 static void (*m_sby_cb)(UINT8) = NULL;
68
null_callback_drq(UINT8 data)69 static void null_callback_drq(UINT8 data)
70 {
71 //bprintf(0, _T("null callback drq: %X\n"), data);
72 }
73
null_callback_sby(UINT8 data)74 static void null_callback_sby(UINT8 data)
75 {
76 //bprintf(0, _T("null callback sby: %X\n"), data);
77 }
78
sp0256_set_drq_cb(void (* cb)(UINT8))79 void sp0256_set_drq_cb(void (*cb)(UINT8))
80 {
81 m_drq_cb = cb;
82 }
83
sp0256_set_sby_cb(void (* cb)(UINT8))84 void sp0256_set_sby_cb(void (*cb)(UINT8))
85 {
86 m_sby_cb = cb;
87 }
88
89 // "re"sampler stuff
90 static INT32 samples_from;
91 static INT16 *mixer_buffer;
92
93 static UINT8 *m_rom; /* 64K ROM. */
94
95 static INT32 m_sby_line; /* Standby line state */
96 static INT32 m_silent; /* Flag: SP0256 is silent. */
97
98 static INT16 *m_scratch; /* Scratch buffer for audio. */
99 static UINT32 m_sc_head; /* Head pointer into scratch circular buf */
100 static UINT32 m_sc_tail; /* Tail pointer into scratch circular buf */
101
102 static struct lpc12_t m_filt; /* 12-pole filter */
103 static INT32 m_lrq; /* Load ReQuest. == 0 if we can accept a load */
104 static INT32 m_ald; /* Address LoaD. < 0 if no command pending. */
105 static INT32 m_pc; /* Microcontroller's PC value. */
106 static INT32 m_stack; /* Microcontroller's PC stack. */
107 static INT32 m_fifo_sel; /* True when executing from FIFO. */
108 static INT32 m_halted; /* True when CPU is halted. */
109 static UINT32 m_mode; /* Mode register. */
110 static UINT32 m_page; /* Page set by SETPAGE */
111
112 static UINT32 m_fifo_head; /* FIFO head pointer (where new data goes). */
113 static UINT32 m_fifo_tail; /* FIFO tail pointer (where data comes from). */
114 static UINT32 m_fifo_bitp; /* FIFO bit-pointer (for partial decles). */
115 static UINT16 m_fifo[64]; /* The 64-decle FIFO. */
116
117
118 //-------------------------------------------------
119 // device_start - device-specific startup
120 //-------------------------------------------------
sp0256_set_clock(INT32 clock)121 void sp0256_set_clock(INT32 clock)
122 {
123 samples_from = (INT32)((double)(((clock / CLOCK_DIVIDER) * 100) / nBurnFPS) + 0.5);
124 }
125
sp0256_scan(INT32 nAction,INT32 * pnMin)126 void sp0256_scan(INT32 nAction, INT32* pnMin)
127 {
128 if (pnMin && *pnMin < 0x029521) {
129 *pnMin = 0x029521;
130 }
131
132 if (nAction & ACB_DRIVER_DATA) {
133 ScanVar(m_scratch, SCBUF_SIZE * sizeof(INT16), "sp0256 ScratchRam");
134
135 SCAN_VAR(m_sby_line);
136 SCAN_VAR(m_silent);
137
138 SCAN_VAR(m_sc_head);
139 SCAN_VAR(m_sc_tail);
140
141 SCAN_VAR(m_filt);
142 SCAN_VAR(m_lrq);
143 SCAN_VAR(m_ald);
144 SCAN_VAR(m_pc);
145 SCAN_VAR(m_stack);
146 SCAN_VAR(m_fifo_sel);
147 SCAN_VAR(m_halted);
148 SCAN_VAR(m_mode);
149 SCAN_VAR(m_page);
150
151 SCAN_VAR(m_fifo_head);
152 SCAN_VAR(m_fifo_tail);
153 SCAN_VAR(m_fifo_bitp);
154 SCAN_VAR(m_fifo);
155 }
156 }
157
sp0256_init(UINT8 * rom,INT32 clock)158 void sp0256_init(UINT8 *rom, INT32 clock)
159 {
160 m_rom = rom;
161
162 sp0256_set_drq_cb(null_callback_drq);
163 sp0256_set_sby_cb(null_callback_sby);
164
165 /* -------------------------------------------------------------------- */
166 /* Allocate a scratch buffer for generating ~10kHz samples. */
167 /* -------------------------------------------------------------------- */
168 m_scratch = (INT16 *)BurnMalloc(SCBUF_SIZE * sizeof(INT16));
169
170 // Init Re-sampler buffer
171 mixer_buffer = (INT16 *)BurnMalloc(nBurnSoundRate * sizeof(INT16));
172 sp0256_set_clock(clock);
173 }
174
sp0256_exit()175 void sp0256_exit()
176 {
177 BurnFree(m_scratch);
178 BurnFree(mixer_buffer);
179 }
180
181 //-------------------------------------------------
182 // device_reset - device-specific reset
183 //-------------------------------------------------
184
sp0256_reset()185 void sp0256_reset()
186 {
187 // reset FIFO and SP0256
188 m_fifo_head = m_fifo_tail = m_fifo_bitp = 0;
189 m_sc_head = m_sc_tail = 0;
190
191 memset(m_scratch, 0, SCBUF_SIZE * sizeof(INT16));
192 memset(&m_filt, 0, sizeof(m_filt));
193 memset(&m_fifo, 0, sizeof(m_fifo));
194 m_halted = 1;
195 m_filt.rpt = -1;
196 m_filt.rng = 1;
197 m_lrq = 0x0000;
198 m_ald = 0x0000;
199 m_pc = 0x0000;
200 m_stack = 0x0000;
201 m_fifo_sel = 0;
202 m_mode = 0;
203 m_page = 0x1000 << 3;
204 m_silent = 1;
205 m_sby_line = 1;
206 //m_drq_cb(1);
207 //SET_SBY(1)
208 }
209
210
211 /* ======================================================================== */
212 /* LIMIT -- Limiter function for digital sample output. */
213 /* ======================================================================== */
limit(INT16 s)214 static INT16 limit(INT16 s)
215 {
216 #ifdef HIGH_QUALITY /* Higher quality than the original, but who cares? */
217 if (s > 8191) return 8191;
218 if (s < -8192) return -8192;
219 #else
220 if (s > 127) return 127;
221 if (s < -128) return -128;
222 #endif
223 return s;
224 }
225
226 /* ======================================================================== */
227 /* LPC12_UPDATE -- Update the 12-pole filter, outputting samples. */
228 /* ======================================================================== */
lpc12_update(struct lpc12_t * f,INT32 num_samp,INT16 * out,UINT32 * optr)229 static INT32 lpc12_update(struct lpc12_t *f, INT32 num_samp, INT16 *out, UINT32 *optr)
230 {
231 INT32 i, j;
232 INT16 samp;
233 INT32 do_int;
234 INT32 oidx = *optr;
235
236 /* -------------------------------------------------------------------- */
237 /* Iterate up to the desired number of samples. We actually may */
238 /* break out early if our repeat count expires. */
239 /* -------------------------------------------------------------------- */
240 for (i = 0; i < num_samp; i++)
241 {
242 /* ---------------------------------------------------------------- */
243 /* Generate a series of periodic impulses, or random noise. */
244 /* ---------------------------------------------------------------- */
245 do_int = 0;
246 samp = 0;
247 if (f->per)
248 {
249 if (f->cnt <= 0)
250 {
251 f->cnt += f->per;
252 samp = f->amp;
253 f->rpt--;
254 do_int = f->interp;
255
256 for (j = 0; j < 6; j++)
257 f->z_data[j][1] = f->z_data[j][0] = 0;
258
259 } else
260 {
261 samp = 0;
262 f->cnt--;
263 }
264
265 } else
266 {
267 INT32 bit;
268
269 if (--f->cnt <= 0)
270 {
271 do_int = f->interp;
272 f->cnt = PER_NOISE;
273 f->rpt--;
274 for (j = 0; j < 6; j++)
275 f->z_data[j][0] = f->z_data[j][1] = 0;
276 }
277
278 bit = f->rng & 1;
279 f->rng = (f->rng >> 1) ^ (bit ? 0x4001 : 0);
280
281 if (bit) { samp = f->amp; }
282 else { samp = -f->amp; }
283 }
284
285 /* ---------------------------------------------------------------- */
286 /* If we need to, process the interpolation registers. */
287 /* ---------------------------------------------------------------- */
288 if (do_int)
289 {
290 f->r[0] += f->r[14];
291 f->r[1] += f->r[15];
292
293 f->amp = (f->r[0] & 0x1F) << (((f->r[0] & 0xE0) >> 5) + 0);
294 f->per = f->r[1];
295 }
296
297 /* ---------------------------------------------------------------- */
298 /* Stop if we expire our repeat counter and return the actual */
299 /* number of samples we did. */
300 /* ---------------------------------------------------------------- */
301 if (f->rpt <= 0) break;
302
303 /* ---------------------------------------------------------------- */
304 /* Each 2nd order stage looks like one of these. The App. Manual */
305 /* gives the first form, the patent gives the second form. */
306 /* They're equivalent except for time delay. I implement the */
307 /* first form. (Note: 1/Z == 1 unit of time delay.) */
308 /* */
309 /* ---->(+)-------->(+)----------+-------> */
310 /* ^ ^ | */
311 /* | | | */
312 /* | | | */
313 /* [B] [2*F] | */
314 /* ^ ^ | */
315 /* | | | */
316 /* | | | */
317 /* +---[1/Z]<--+---[1/Z]<--+ */
318 /* */
319 /* */
320 /* +---[2*F]<---+ */
321 /* | | */
322 /* | | */
323 /* v | */
324 /* ---->(+)-->[1/Z]-->+-->[1/Z]---+------> */
325 /* ^ | */
326 /* | | */
327 /* | | */
328 /* +-----------[B]<---------+ */
329 /* */
330 /* ---------------------------------------------------------------- */
331 for (j = 0; j < 6; j++)
332 {
333 samp += (((int)f->b_coef[j] * (int)f->z_data[j][1]) >> 9);
334 samp += (((int)f->f_coef[j] * (int)f->z_data[j][0]) >> 8);
335
336 f->z_data[j][1] = f->z_data[j][0];
337 f->z_data[j][0] = samp;
338 }
339
340 #ifdef HIGH_QUALITY /* Higher quality than the original, but who cares? */
341 out[oidx++ & SCBUF_MASK] = limit(samp) << 2;
342 #else
343 out[oidx++ & SCBUF_MASK] = (limit(samp >> 4) << 8);
344 #endif
345 }
346
347 *optr = oidx;
348
349 return i;
350 }
351
352 /* ======================================================================== */
353 /* LPC12_REGDEC -- Decode the register set in the filter bank. */
354 /* ======================================================================== */
lpc12_regdec(struct lpc12_t * f)355 static void lpc12_regdec(struct lpc12_t *f)
356 {
357 /* ======================================================================== */
358 /* qtbl -- Coefficient Quantization Table. This comes from a */
359 /* SP0250 data sheet, and should be correct for SP0256. */
360 /* ======================================================================== */
361 static const INT16 qtbl[128] =
362 {
363 0, 9, 17, 25, 33, 41, 49, 57,
364 65, 73, 81, 89, 97, 105, 113, 121,
365 129, 137, 145, 153, 161, 169, 177, 185,
366 193, 201, 209, 217, 225, 233, 241, 249,
367 257, 265, 273, 281, 289, 297, 301, 305,
368 309, 313, 317, 321, 325, 329, 333, 337,
369 341, 345, 349, 353, 357, 361, 365, 369,
370 373, 377, 381, 385, 389, 393, 397, 401,
371 405, 409, 413, 417, 421, 425, 427, 429,
372 431, 433, 435, 437, 439, 441, 443, 445,
373 447, 449, 451, 453, 455, 457, 459, 461,
374 463, 465, 467, 469, 471, 473, 475, 477,
375 479, 481, 482, 483, 484, 485, 486, 487,
376 488, 489, 490, 491, 492, 493, 494, 495,
377 496, 497, 498, 499, 500, 501, 502, 503,
378 504, 505, 506, 507, 508, 509, 510, 511
379 };
380
381 /* -------------------------------------------------------------------- */
382 /* Decode the Amplitude and Period registers. Force the 'cnt' to 0 */
383 /* to get an initial impulse. We compensate elsewhere by setting */
384 /* the repeat count to "repeat + 1". */
385 /* -------------------------------------------------------------------- */
386 f->amp = (f->r[0] & 0x1F) << (((f->r[0] & 0xE0) >> 5) + 0);
387 f->cnt = 0;
388 f->per = f->r[1];
389
390 /* -------------------------------------------------------------------- */
391 /* Decode the filter coefficients from the quant table. */
392 /* -------------------------------------------------------------------- */
393 for (INT32 i = 0; i < 6; i++)
394 {
395 #define IQ(x) (((x) & 0x80) ? qtbl[0x7F & -(x)] : -qtbl[(x)])
396
397 f->b_coef[i] = IQ(f->r[2 + 2*i]);
398 f->f_coef[i] = IQ(f->r[3 + 2*i]);
399 }
400
401 /* -------------------------------------------------------------------- */
402 /* Set the Interp flag based on whether we have interpolation parms */
403 /* -------------------------------------------------------------------- */
404 f->interp = f->r[14] || f->r[15];
405
406 return;
407 }
408
409 /* ======================================================================== */
410 /* SP0256_DATAFMT -- Data format table for the SP0256's microsequencer */
411 /* */
412 /* len 4 bits Length of field to extract */
413 /* lshift 4 bits Left-shift amount on field */
414 /* param 4 bits Parameter number being updated */
415 /* delta 1 bit This is a delta-update. (Implies sign-extend) */
416 /* field 1 bit This is a field replace. */
417 /* clr5 1 bit Clear F5, B5. */
418 /* clrall 1 bit Clear all before doing this update */
419 /* ======================================================================== */
420
421 #define CR(l,s,p,d,f,c5,ca) \
422 ( \
423 (((l) & 15) << 0) | \
424 (((s) & 15) << 4) | \
425 (((p) & 15) << 8) | \
426 (((d) & 1) << 12) | \
427 (((f) & 1) << 13) | \
428 (((c5) & 1) << 14) | \
429 (((ca) & 1) << 15) \
430 )
431
432 #define CR_DELTA CR(0,0,0,1,0,0,0)
433 #define CR_FIELD CR(0,0,0,0,1,0,0)
434 #define CR_CLR5 CR(0,0,0,0,0,1,0)
435 #define CR_CLRA CR(0,0,0,0,0,0,1)
436 #define CR_LEN(x) ((x) & 15)
437 #define CR_SHF(x) (((x) >> 4) & 15)
438 #define CR_PRM(x) (((x) >> 8) & 15)
439
440 enum { AM = 0, PR, B0, F0, B1, F1, B2, F2, B3, F3, B4, F4, B5, F5, IA, IP };
441
442 static const UINT16 sp0256_datafmt[] =
443 {
444 /* -------------------------------------------------------------------- */
445 /* OPCODE 1111: PAUSE */
446 /* -------------------------------------------------------------------- */
447 /* 0 */ CR( 0, 0, 0, 0, 0, 0, 1), /* Clear all */
448
449 /* -------------------------------------------------------------------- */
450 /* Opcode 0001: LOADALL */
451 /* -------------------------------------------------------------------- */
452 /* All modes */
453 /* 1 */ CR( 8, 0, AM, 0, 0, 0, 1), /* Amplitude */
454 /* 2 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
455 /* 3 */ CR( 8, 0, B0, 0, 0, 0, 0), /* B0 */
456 /* 4 */ CR( 8, 0, F0, 0, 0, 0, 0), /* F0 */
457 /* 5 */ CR( 8, 0, B1, 0, 0, 0, 0), /* B1 */
458 /* 6 */ CR( 8, 0, F1, 0, 0, 0, 0), /* F1 */
459 /* 7 */ CR( 8, 0, B2, 0, 0, 0, 0), /* B2 */
460 /* 8 */ CR( 8, 0, F2, 0, 0, 0, 0), /* F2 */
461 /* 9 */ CR( 8, 0, B3, 0, 0, 0, 0), /* B3 */
462 /* 10 */ CR( 8, 0, F3, 0, 0, 0, 0), /* F3 */
463 /* 11 */ CR( 8, 0, B4, 0, 0, 0, 0), /* B4 */
464 /* 12 */ CR( 8, 0, F4, 0, 0, 0, 0), /* F4 */
465 /* 13 */ CR( 8, 0, B5, 0, 0, 0, 0), /* B5 */
466 /* 14 */ CR( 8, 0, F5, 0, 0, 0, 0), /* F5 */
467 /* Mode 01 and 11 only */
468 /* 15 */ CR( 8, 0, IA, 0, 0, 0, 0), /* Amp Interp */
469 /* 16 */ CR( 8, 0, IP, 0, 0, 0, 0), /* Pit Interp */
470
471 /* -------------------------------------------------------------------- */
472 /* Opcode 0100: LOAD_4 */
473 /* -------------------------------------------------------------------- */
474 /* Mode 00 and 01 */
475 /* 17 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
476 /* 18 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
477 /* 19 */ CR( 4, 3, B3, 0, 0, 0, 0), /* B3 (S=0) */
478 /* 20 */ CR( 6, 2, F3, 0, 0, 0, 0), /* F3 */
479 /* 21 */ CR( 7, 1, B4, 0, 0, 0, 0), /* B4 */
480 /* 22 */ CR( 6, 2, F4, 0, 0, 0, 0), /* F4 */
481 /* Mode 01 only */
482 /* 23 */ CR( 8, 0, B5, 0, 0, 0, 0), /* B5 */
483 /* 24 */ CR( 8, 0, F5, 0, 0, 0, 0), /* F5 */
484
485 /* Mode 10 and 11 */
486 /* 25 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
487 /* 26 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
488 /* 27 */ CR( 6, 1, B3, 0, 0, 0, 0), /* B3 (S=0) */
489 /* 28 */ CR( 7, 1, F3, 0, 0, 0, 0), /* F3 */
490 /* 29 */ CR( 8, 0, B4, 0, 0, 0, 0), /* B4 */
491 /* 30 */ CR( 8, 0, F4, 0, 0, 0, 0), /* F4 */
492 /* Mode 11 only */
493 /* 31 */ CR( 8, 0, B5, 0, 0, 0, 0), /* B5 */
494 /* 32 */ CR( 8, 0, F5, 0, 0, 0, 0), /* F5 */
495
496 /* -------------------------------------------------------------------- */
497 /* Opcode 0110: SETMSB_6 */
498 /* -------------------------------------------------------------------- */
499 /* Mode 00 only */
500 /* 33 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
501 /* Mode 00 and 01 */
502 /* 34 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
503 /* 35 */ CR( 6, 2, F3, 0, 1, 0, 0), /* F3 (5 MSBs) */
504 /* 36 */ CR( 6, 2, F4, 0, 1, 0, 0), /* F4 (5 MSBs) */
505 /* Mode 01 only */
506 /* 37 */ CR( 8, 0, F5, 0, 1, 0, 0), /* F5 (5 MSBs) */
507
508 /* Mode 10 only */
509 /* 38 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
510 /* Mode 10 and 11 */
511 /* 39 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
512 /* 40 */ CR( 7, 1, F3, 0, 1, 0, 0), /* F3 (6 MSBs) */
513 /* 41 */ CR( 8, 0, F4, 0, 1, 0, 0), /* F4 (6 MSBs) */
514 /* Mode 11 only */
515 /* 42 */ CR( 8, 0, F5, 0, 1, 0, 0), /* F5 (6 MSBs) */
516
517 /* 43 */ 0, /* unused */
518 /* 44 */ 0, /* unused */
519
520 /* -------------------------------------------------------------------- */
521 /* Opcode 1001: DELTA_9 */
522 /* -------------------------------------------------------------------- */
523 /* Mode 00 and 01 */
524 /* 45 */ CR( 4, 2, AM, 1, 0, 0, 0), /* Amplitude */
525 /* 46 */ CR( 5, 0, PR, 1, 0, 0, 0), /* Period */
526 /* 47 */ CR( 3, 4, B0, 1, 0, 0, 0), /* B0 4 MSBs */
527 /* 48 */ CR( 3, 3, F0, 1, 0, 0, 0), /* F0 5 MSBs */
528 /* 49 */ CR( 3, 4, B1, 1, 0, 0, 0), /* B1 4 MSBs */
529 /* 50 */ CR( 3, 3, F1, 1, 0, 0, 0), /* F1 5 MSBs */
530 /* 51 */ CR( 3, 4, B2, 1, 0, 0, 0), /* B2 4 MSBs */
531 /* 52 */ CR( 3, 3, F2, 1, 0, 0, 0), /* F2 5 MSBs */
532 /* 53 */ CR( 3, 3, B3, 1, 0, 0, 0), /* B3 5 MSBs */
533 /* 54 */ CR( 4, 2, F3, 1, 0, 0, 0), /* F3 6 MSBs */
534 /* 55 */ CR( 4, 1, B4, 1, 0, 0, 0), /* B4 7 MSBs */
535 /* 56 */ CR( 4, 2, F4, 1, 0, 0, 0), /* F4 6 MSBs */
536 /* Mode 01 only */
537 /* 57 */ CR( 5, 0, B5, 1, 0, 0, 0), /* B5 8 MSBs */
538 /* 58 */ CR( 5, 0, F5, 1, 0, 0, 0), /* F5 8 MSBs */
539
540 /* Mode 10 and 11 */
541 /* 59 */ CR( 4, 2, AM, 1, 0, 0, 0), /* Amplitude */
542 /* 60 */ CR( 5, 0, PR, 1, 0, 0, 0), /* Period */
543 /* 61 */ CR( 4, 1, B0, 1, 0, 0, 0), /* B0 7 MSBs */
544 /* 62 */ CR( 4, 2, F0, 1, 0, 0, 0), /* F0 6 MSBs */
545 /* 63 */ CR( 4, 1, B1, 1, 0, 0, 0), /* B1 7 MSBs */
546 /* 64 */ CR( 4, 2, F1, 1, 0, 0, 0), /* F1 6 MSBs */
547 /* 65 */ CR( 4, 1, B2, 1, 0, 0, 0), /* B2 7 MSBs */
548 /* 66 */ CR( 4, 2, F2, 1, 0, 0, 0), /* F2 6 MSBs */
549 /* 67 */ CR( 4, 1, B3, 1, 0, 0, 0), /* B3 7 MSBs */
550 /* 68 */ CR( 5, 1, F3, 1, 0, 0, 0), /* F3 7 MSBs */
551 /* 69 */ CR( 5, 0, B4, 1, 0, 0, 0), /* B4 8 MSBs */
552 /* 70 */ CR( 5, 0, F4, 1, 0, 0, 0), /* F4 8 MSBs */
553 /* Mode 11 only */
554 /* 71 */ CR( 5, 0, B5, 1, 0, 0, 0), /* B5 8 MSBs */
555 /* 72 */ CR( 5, 0, F5, 1, 0, 0, 0), /* F5 8 MSBs */
556
557 /* -------------------------------------------------------------------- */
558 /* Opcode 1010: SETMSB_A */
559 /* -------------------------------------------------------------------- */
560 /* Mode 00 only */
561 /* 73 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
562 /* Mode 00 and 01 */
563 /* 74 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
564 /* 75 */ CR( 5, 3, F0, 0, 1, 0, 0), /* F0 (5 MSBs) */
565 /* 76 */ CR( 5, 3, F1, 0, 1, 0, 0), /* F1 (5 MSBs) */
566 /* 77 */ CR( 5, 3, F2, 0, 1, 0, 0), /* F2 (5 MSBs) */
567
568 /* Mode 10 only */
569 /* 78 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
570 /* Mode 10 and 11 */
571 /* 79 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
572 /* 80 */ CR( 6, 2, F0, 0, 1, 0, 0), /* F0 (6 MSBs) */
573 /* 81 */ CR( 6, 2, F1, 0, 1, 0, 0), /* F1 (6 MSBs) */
574 /* 82 */ CR( 6, 2, F2, 0, 1, 0, 0), /* F2 (6 MSBs) */
575
576 /* -------------------------------------------------------------------- */
577 /* Opcode 0010: LOAD_2 Mode 00 and 10 */
578 /* Opcode 1100: LOAD_C Mode 00 and 10 */
579 /* -------------------------------------------------------------------- */
580 /* LOAD_2, LOAD_C Mode 00 */
581 /* 83 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
582 /* 84 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
583 /* 85 */ CR( 3, 4, B0, 0, 0, 0, 0), /* B0 (S=0) */
584 /* 86 */ CR( 5, 3, F0, 0, 0, 0, 0), /* F0 */
585 /* 87 */ CR( 3, 4, B1, 0, 0, 0, 0), /* B1 (S=0) */
586 /* 88 */ CR( 5, 3, F1, 0, 0, 0, 0), /* F1 */
587 /* 89 */ CR( 3, 4, B2, 0, 0, 0, 0), /* B2 (S=0) */
588 /* 90 */ CR( 5, 3, F2, 0, 0, 0, 0), /* F2 */
589 /* 91 */ CR( 4, 3, B3, 0, 0, 0, 0), /* B3 (S=0) */
590 /* 92 */ CR( 6, 2, F3, 0, 0, 0, 0), /* F3 */
591 /* 93 */ CR( 7, 1, B4, 0, 0, 0, 0), /* B4 */
592 /* 94 */ CR( 6, 2, F4, 0, 0, 0, 0), /* F4 */
593 /* LOAD_2 only */
594 /* 95 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
595 /* 96 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
596
597 /* LOAD_2, LOAD_C Mode 10 */
598 /* 97 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
599 /* 98 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
600 /* 99 */ CR( 6, 1, B0, 0, 0, 0, 0), /* B0 (S=0) */
601 /* 100 */ CR( 6, 2, F0, 0, 0, 0, 0), /* F0 */
602 /* 101 */ CR( 6, 1, B1, 0, 0, 0, 0), /* B1 (S=0) */
603 /* 102 */ CR( 6, 2, F1, 0, 0, 0, 0), /* F1 */
604 /* 103 */ CR( 6, 1, B2, 0, 0, 0, 0), /* B2 (S=0) */
605 /* 104 */ CR( 6, 2, F2, 0, 0, 0, 0), /* F2 */
606 /* 105 */ CR( 6, 1, B3, 0, 0, 0, 0), /* B3 (S=0) */
607 /* 106 */ CR( 7, 1, F3, 0, 0, 0, 0), /* F3 */
608 /* 107 */ CR( 8, 0, B4, 0, 0, 0, 0), /* B4 */
609 /* 108 */ CR( 8, 0, F4, 0, 0, 0, 0), /* F4 */
610 /* LOAD_2 only */
611 /* 109 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
612 /* 110 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
613
614 /* -------------------------------------------------------------------- */
615 /* OPCODE 1101: DELTA_D */
616 /* -------------------------------------------------------------------- */
617 /* Mode 00 and 01 */
618 /* 111 */ CR( 4, 2, AM, 1, 0, 0, 0), /* Amplitude */
619 /* 112 */ CR( 5, 0, PR, 1, 0, 0, 0), /* Period */
620 /* 113 */ CR( 3, 3, B3, 1, 0, 0, 0), /* B3 5 MSBs */
621 /* 114 */ CR( 4, 2, F3, 1, 0, 0, 0), /* F3 6 MSBs */
622 /* 115 */ CR( 4, 1, B4, 1, 0, 0, 0), /* B4 7 MSBs */
623 /* 116 */ CR( 4, 2, F4, 1, 0, 0, 0), /* F4 6 MSBs */
624 /* Mode 01 only */
625 /* 117 */ CR( 5, 0, B5, 1, 0, 0, 0), /* B5 8 MSBs */
626 /* 118 */ CR( 5, 0, F5, 1, 0, 0, 0), /* F5 8 MSBs */
627
628 /* Mode 10 and 11 */
629 /* 119 */ CR( 4, 2, AM, 1, 0, 0, 0), /* Amplitude */
630 /* 120 */ CR( 5, 0, PR, 1, 0, 0, 0), /* Period */
631 /* 121 */ CR( 4, 1, B3, 1, 0, 0, 0), /* B3 7 MSBs */
632 /* 122 */ CR( 5, 1, F3, 1, 0, 0, 0), /* F3 7 MSBs */
633 /* 123 */ CR( 5, 0, B4, 1, 0, 0, 0), /* B4 8 MSBs */
634 /* 124 */ CR( 5, 0, F4, 1, 0, 0, 0), /* F4 8 MSBs */
635 /* Mode 11 only */
636 /* 125 */ CR( 5, 0, B5, 1, 0, 0, 0), /* B5 8 MSBs */
637 /* 126 */ CR( 5, 0, F5, 1, 0, 0, 0), /* F5 8 MSBs */
638
639 /* -------------------------------------------------------------------- */
640 /* OPCODE 1110: LOAD_E */
641 /* -------------------------------------------------------------------- */
642 /* 127 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
643 /* 128 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
644
645 /* -------------------------------------------------------------------- */
646 /* Opcode 0010: LOAD_2 Mode 01 and 11 */
647 /* Opcode 1100: LOAD_C Mode 01 and 11 */
648 /* -------------------------------------------------------------------- */
649 /* LOAD_2, LOAD_C Mode 01 */
650 /* 129 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
651 /* 130 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
652 /* 131 */ CR( 3, 4, B0, 0, 0, 0, 0), /* B0 (S=0) */
653 /* 132 */ CR( 5, 3, F0, 0, 0, 0, 0), /* F0 */
654 /* 133 */ CR( 3, 4, B1, 0, 0, 0, 0), /* B1 (S=0) */
655 /* 134 */ CR( 5, 3, F1, 0, 0, 0, 0), /* F1 */
656 /* 135 */ CR( 3, 4, B2, 0, 0, 0, 0), /* B2 (S=0) */
657 /* 136 */ CR( 5, 3, F2, 0, 0, 0, 0), /* F2 */
658 /* 137 */ CR( 4, 3, B3, 0, 0, 0, 0), /* B3 (S=0) */
659 /* 138 */ CR( 6, 2, F3, 0, 0, 0, 0), /* F3 */
660 /* 139 */ CR( 7, 1, B4, 0, 0, 0, 0), /* B4 */
661 /* 140 */ CR( 6, 2, F4, 0, 0, 0, 0), /* F4 */
662 /* 141 */ CR( 8, 0, B5, 0, 0, 0, 0), /* B5 */
663 /* 142 */ CR( 8, 0, F5, 0, 0, 0, 0), /* F5 */
664 /* LOAD_2 only */
665 /* 143 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
666 /* 144 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
667
668 /* LOAD_2, LOAD_C Mode 11 */
669 /* 145 */ CR( 6, 2, AM, 0, 0, 0, 1), /* Amplitude */
670 /* 146 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
671 /* 147 */ CR( 6, 1, B0, 0, 0, 0, 0), /* B0 (S=0) */
672 /* 148 */ CR( 6, 2, F0, 0, 0, 0, 0), /* F0 */
673 /* 149 */ CR( 6, 1, B1, 0, 0, 0, 0), /* B1 (S=0) */
674 /* 150 */ CR( 6, 2, F1, 0, 0, 0, 0), /* F1 */
675 /* 151 */ CR( 6, 1, B2, 0, 0, 0, 0), /* B2 (S=0) */
676 /* 152 */ CR( 6, 2, F2, 0, 0, 0, 0), /* F2 */
677 /* 153 */ CR( 6, 1, B3, 0, 0, 0, 0), /* B3 (S=0) */
678 /* 154 */ CR( 7, 1, F3, 0, 0, 0, 0), /* F3 */
679 /* 155 */ CR( 8, 0, B4, 0, 0, 0, 0), /* B4 */
680 /* 156 */ CR( 8, 0, F4, 0, 0, 0, 0), /* F4 */
681 /* 157 */ CR( 8, 0, B5, 0, 0, 0, 0), /* B5 */
682 /* 158 */ CR( 8, 0, F5, 0, 0, 0, 0), /* F5 */
683 /* LOAD_2 only */
684 /* 159 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
685 /* 160 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
686
687 /* -------------------------------------------------------------------- */
688 /* Opcode 0011: SETMSB_3 */
689 /* Opcode 0101: SETMSB_5 */
690 /* -------------------------------------------------------------------- */
691 /* Mode 00 only */
692 /* 161 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
693 /* Mode 00 and 01 */
694 /* 162 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
695 /* 163 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
696 /* 164 */ CR( 5, 3, F0, 0, 1, 0, 0), /* F0 (5 MSBs) */
697 /* 165 */ CR( 5, 3, F1, 0, 1, 0, 0), /* F1 (5 MSBs) */
698 /* 166 */ CR( 5, 3, F2, 0, 1, 0, 0), /* F2 (5 MSBs) */
699 /* SETMSB_3 only */
700 /* 167 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
701 /* 168 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
702
703 /* Mode 10 only */
704 /* 169 */ CR( 0, 0, 0, 0, 0, 1, 0), /* Clear 5 */
705 /* Mode 10 and 11 */
706 /* 170 */ CR( 6, 2, AM, 0, 0, 0, 0), /* Amplitude */
707 /* 171 */ CR( 8, 0, PR, 0, 0, 0, 0), /* Period */
708 /* 172 */ CR( 6, 2, F0, 0, 1, 0, 0), /* F0 (6 MSBs) */
709 /* 173 */ CR( 6, 2, F1, 0, 1, 0, 0), /* F1 (6 MSBs) */
710 /* 174 */ CR( 6, 2, F2, 0, 1, 0, 0), /* F2 (6 MSBs) */
711 /* SETMSB_3 only */
712 /* 175 */ CR( 5, 0, IA, 0, 0, 0, 0), /* Ampl. Intr. */
713 /* 176 */ CR( 5, 0, IP, 0, 0, 0, 0), /* Per. Intr. */
714 };
715
716 static const INT16 sp0256_df_idx[16 * 8] =
717 {
718 /* OPCODE 0000 */ -1, -1, -1, -1, -1, -1, -1, -1,
719 /* OPCODE 1000 */ -1, -1, -1, -1, -1, -1, -1, -1,
720 /* OPCODE 0100 */ 17, 22, 17, 24, 25, 30, 25, 32,
721 /* OPCODE 1100 */ 83, 94, 129,142, 97, 108, 145,158,
722 /* OPCODE 0010 */ 83, 96, 129,144, 97, 110, 145,160,
723 /* OPCODE 1010 */ 73, 77, 74, 77, 78, 82, 79, 82,
724 /* OPCODE 0110 */ 33, 36, 34, 37, 38, 41, 39, 42,
725 /* OPCODE 1110 */ 127,128, 127,128, 127,128, 127,128,
726 /* OPCODE 0001 */ 1, 14, 1, 16, 1, 14, 1, 16,
727 /* OPCODE 1001 */ 45, 56, 45, 58, 59, 70, 59, 72,
728 /* OPCODE 0101 */ 161,166, 162,166, 169,174, 170,174,
729 /* OPCODE 1101 */ 111,116, 111,118, 119,124, 119,126,
730 /* OPCODE 0011 */ 161,168, 162,168, 169,176, 170,176,
731 /* OPCODE 1011 */ -1, -1, -1, -1, -1, -1, -1, -1,
732 /* OPCODE 0111 */ -1, -1, -1, -1, -1, -1, -1, -1,
733 /* OPCODE 1111 */ 0, 0, 0, 0, 0, 0, 0, 0
734 };
735
736 /* ======================================================================== */
737 /* BITREV32 -- Bit-reverse a 32-bit number. */
738 /* ======================================================================== */
bitrev32(UINT32 val)739 static UINT32 bitrev32(UINT32 val)
740 {
741 val = ((val & 0xFFFF0000) >> 16) | ((val & 0x0000FFFF) << 16);
742 val = ((val & 0xFF00FF00) >> 8) | ((val & 0x00FF00FF) << 8);
743 val = ((val & 0xF0F0F0F0) >> 4) | ((val & 0x0F0F0F0F) << 4);
744 val = ((val & 0xCCCCCCCC) >> 2) | ((val & 0x33333333) << 2);
745 val = ((val & 0xAAAAAAAA) >> 1) | ((val & 0x55555555) << 1);
746
747 return val;
748 }
749
750 #if 0
751 /* ======================================================================== */
752 /* BITREV8 -- Bit-reverse a 8-bit number. */
753 /* ======================================================================== */
754 static UINT8 bitrev8(UINT8 val)
755 {
756 val = ((val & 0xF0) >> 4) | ((val & 0x0F) << 4);
757 val = ((val & 0xCC) >> 2) | ((val & 0x33) << 2);
758 val = ((val & 0xAA) >> 1) | ((val & 0x55) << 1);
759
760 return val;
761 }
762
763 /* ======================================================================== */
764 /* BITREVBUFF -- Bit-reverse a buffer. */
765 /* ======================================================================== */
766 void bitrevbuff(UINT8 *buffer, UINT32 start, UINT32 length)
767 {
768 for (UINT32 i = start; i < length; i++ )
769 buffer[i] = bitrev8(buffer[i]);
770 }
771 #endif
772
773 /* ======================================================================== */
774 /* SP0256_GETB -- Get up to 8 bits at the current PC. */
775 /* ======================================================================== */
getb(INT32 len)776 static UINT32 getb( INT32 len )
777 {
778 UINT32 data = 0;
779
780 /* -------------------------------------------------------------------- */
781 /* Fetch data from the FIFO or from the MASK */
782 /* -------------------------------------------------------------------- */
783 if (m_fifo_sel)
784 {
785 UINT32 d0, d1;
786 d0 = m_fifo[(m_fifo_tail ) & 63];
787 d1 = m_fifo[(m_fifo_tail + 1) & 63];
788
789 data = ((d1 << 10) | d0) >> m_fifo_bitp;
790
791 LOG_FIFO((0, _T("sp0256: RD_FIFO %.3X %d.%d %d\n"), data & ((1 << len) - 1),
792 m_fifo_tail, m_fifo_bitp, m_fifo_head));
793
794 /* ---------------------------------------------------------------- */
795 /* Note the PC doesn't advance when we execute from FIFO. */
796 /* Just the FIFO's bit-pointer advances. (That's not REALLY */
797 /* what happens, but that's roughly how it behaves.) */
798 /* ---------------------------------------------------------------- */
799 m_fifo_bitp += len;
800 if (m_fifo_bitp >= 10)
801 {
802 m_fifo_tail++;
803 m_fifo_bitp -= 10;
804 }
805 } else
806 {
807 /* ---------------------------------------------------------------- */
808 /* Figure out which ROMs are being fetched into, and grab two */
809 /* adjacent bytes. The byte we're interested in is extracted */
810 /* from the appropriate bit-boundary between them. */
811 /* ---------------------------------------------------------------- */
812 INT32 idx0 = (m_pc ) >> 3, d0;
813 INT32 idx1 = (m_pc + 8) >> 3, d1;
814
815 d0 = m_rom[idx0 & 0xffff];
816 d1 = m_rom[idx1 & 0xffff];
817
818 data = ((d1 << 8) | d0) >> (m_pc & 7);
819
820 m_pc += len;
821 }
822
823 /* -------------------------------------------------------------------- */
824 /* Mask data to the requested length. */
825 /* -------------------------------------------------------------------- */
826 data &= ((1 << len) - 1);
827
828 return data;
829 }
830
831 /* ======================================================================== */
832 /* SP0256_MICRO -- Emulate the microsequencer in the SP0256. Executes */
833 /* instructions either until the repeat count != 0 or */
834 /* the sequencer gets halted by a RTS to 0. */
835 /* ======================================================================== */
micro()836 static void micro()
837 {
838 UINT8 immed4;
839 UINT8 opcode;
840 UINT16 cr;
841 INT32 ctrl_xfer = 0;
842 INT32 repeat = 0;
843 INT32 i, idx0, idx1;
844
845 /* -------------------------------------------------------------------- */
846 /* Only execute instructions while the filter is not busy. */
847 /* -------------------------------------------------------------------- */
848 while (m_filt.rpt <= 0)
849 {
850 /* ---------------------------------------------------------------- */
851 /* If the CPU is halted, see if we have a new command pending */
852 /* in the Address LoaD buffer. */
853 /* ---------------------------------------------------------------- */
854 if (m_halted && !m_lrq)
855 {
856 m_pc = m_ald | (0x1000 << 3);
857 m_fifo_sel = 0;
858 m_halted = 0;
859 m_lrq = 0x8000;
860 m_ald = 0;
861 for (i = 0; i < 16; i++)
862 m_filt.r[i] = 0;
863 m_drq_cb(1);
864 }
865
866 /* ---------------------------------------------------------------- */
867 /* If we're still halted, do nothing. */
868 /* ---------------------------------------------------------------- */
869 if (m_halted)
870 {
871 m_filt.rpt = 1;
872 m_lrq = 0x8000;
873 m_ald = 0;
874 for (i = 0; i < 16; i++)
875 m_filt.r[i] = 0;
876
877 SET_SBY(1)
878
879 return;
880 }
881
882 /* ---------------------------------------------------------------- */
883 /* Fetch the first 8 bits of the opcode, which are always in the */
884 /* same approximate format -- immed4 followed by opcode. */
885 /* ---------------------------------------------------------------- */
886 immed4 = getb(4);
887 opcode = getb(4);
888 repeat = 0;
889 ctrl_xfer = 0;
890
891 LOG((0, _T("$%.4X.%.1X: OPCODE %d%d%d%d.%d%d\n"),
892 (m_pc >> 3) - 1, m_pc & 7,
893 !!(opcode & 1), !!(opcode & 2),
894 !!(opcode & 4), !!(opcode & 8),
895 !!(m_mode&4), !!(m_mode&2)));
896
897 /* ---------------------------------------------------------------- */
898 /* Handle the special cases for specific opcodes. */
899 /* ---------------------------------------------------------------- */
900 switch (opcode)
901 {
902 /* ------------------------------------------------------------ */
903 /* OPCODE 0000: RTS / SETPAGE */
904 /* ------------------------------------------------------------ */
905 case 0x0:
906 {
907 /* -------------------------------------------------------- */
908 /* If immed4 != 0, then this is a SETPAGE instruction. */
909 /* -------------------------------------------------------- */
910 if (immed4) /* SETPAGE */
911 {
912 m_page = bitrev32(immed4) >> 13;
913 } else
914 /* -------------------------------------------------------- */
915 /* Otherwise, this is an RTS / HLT. */
916 /* -------------------------------------------------------- */
917 {
918 UINT32 btrg;
919
920 /* ---------------------------------------------------- */
921 /* Figure out our branch target. */
922 /* ---------------------------------------------------- */
923 btrg = m_stack;
924
925 m_stack = 0;
926
927 /* ---------------------------------------------------- */
928 /* If the branch target is zero, this is a HLT. */
929 /* Otherwise, it's an RTS, so set the PC. */
930 /* ---------------------------------------------------- */
931 if (!btrg)
932 {
933 m_halted = 1;
934 m_pc = 0;
935 ctrl_xfer = 1;
936 } else
937 {
938 m_pc = btrg;
939 ctrl_xfer = 1;
940 }
941 }
942
943 break;
944 }
945
946 /* ------------------------------------------------------------ */
947 /* OPCODE 0111: JMP Jump to 12-bit/16-bit Abs Addr */
948 /* OPCODE 1011: JSR Jump to Subroutine */
949 /* ------------------------------------------------------------ */
950 case 0xE:
951 case 0xD:
952 {
953 INT32 btrg;
954
955 /* -------------------------------------------------------- */
956 /* Figure out our branch target. */
957 /* -------------------------------------------------------- */
958 btrg = m_page |
959 (bitrev32(immed4) >> 17) |
960 (bitrev32(getb(8)) >> 21);
961 ctrl_xfer = 1;
962
963 /* -------------------------------------------------------- */
964 /* If this is a JSR, push our return address on the */
965 /* stack. Make sure it's byte aligned. */
966 /* -------------------------------------------------------- */
967 if (opcode == 0xD)
968 m_stack = (m_pc + 7) & ~7;
969
970 /* -------------------------------------------------------- */
971 /* Jump to the new location! */
972 /* -------------------------------------------------------- */
973 m_pc = btrg;
974 break;
975 }
976
977 /* ------------------------------------------------------------ */
978 /* OPCODE 1000: SETMODE Set the Mode and Repeat MSBs */
979 /* ------------------------------------------------------------ */
980 case 0x1:
981 {
982 m_mode = ((immed4 & 8) >> 2) | (immed4 & 4) | ((immed4 & 3) << 4);
983 break;
984 }
985
986 /* ------------------------------------------------------------ */
987 /* OPCODE 0001: LOADALL Load All Parameters */
988 /* OPCODE 0010: LOAD_2 Load Per, Ampl, Coefs, Interp. */
989 /* OPCODE 0011: SETMSB_3 Load Pitch, Ampl, MSBs, & Intrp */
990 /* OPCODE 0100: LOAD_4 Load Pitch, Ampl, Coeffs */
991 /* OPCODE 0101: SETMSB_5 Load Pitch, Ampl, and Coeff MSBs */
992 /* OPCODE 0110: SETMSB_6 Load Ampl, and Coeff MSBs. */
993 /* OPCODE 1001: DELTA_9 Delta update Ampl, Pitch, Coeffs */
994 /* OPCODE 1010: SETMSB_A Load Ampl and MSBs of 3 Coeffs */
995 /* OPCODE 1100: LOAD_C Load Pitch, Ampl, Coeffs */
996 /* OPCODE 1101: DELTA_D Delta update Ampl, Pitch, Coeffs */
997 /* OPCODE 1110: LOAD_E Load Pitch, Amplitude */
998 /* OPCODE 1111: PAUSE Silent pause */
999 /* ------------------------------------------------------------ */
1000 default:
1001 {
1002 repeat = immed4 | (m_mode & 0x30);
1003 break;
1004 }
1005 }
1006 if (opcode != 1) m_mode &= 0xF;
1007
1008 /* ---------------------------------------------------------------- */
1009 /* If this was a control transfer, handle setting "fifo_sel" */
1010 /* and all that ugliness. */
1011 /* ---------------------------------------------------------------- */
1012 if (ctrl_xfer)
1013 {
1014 LOG((0, _T("jumping to $%.4X.%.1X: "), m_pc >> 3, m_pc & 7));
1015
1016 /* ------------------------------------------------------------ */
1017 /* Set our "FIFO Selected" flag based on whether we're going */
1018 /* to the FIFO's address. */
1019 /* ------------------------------------------------------------ */
1020 m_fifo_sel = m_pc == FIFO_ADDR;
1021
1022 LOG((0, _T("%s "), m_fifo_sel ? "FIFO" : "ROM"));
1023
1024 /* ------------------------------------------------------------ */
1025 /* Control transfers to the FIFO cause it to discard the */
1026 /* partial decle that's at the front of the FIFO. */
1027 /* ------------------------------------------------------------ */
1028 if (m_fifo_sel && m_fifo_bitp)
1029 {
1030 LOG((0, _T("bitp = %d -> Flush"), m_fifo_bitp));
1031
1032 /* Discard partially-read decle. */
1033 if (m_fifo_tail < m_fifo_head) m_fifo_tail++;
1034 m_fifo_bitp = 0;
1035 }
1036
1037 LOG((0, _T("\n")));
1038
1039 continue;
1040 }
1041
1042 /* ---------------------------------------------------------------- */
1043 /* Otherwise, if we have a repeat count, then go grab the data */
1044 /* block and feed it to the filter. */
1045 /* ---------------------------------------------------------------- */
1046 if (!repeat) continue;
1047
1048 m_filt.rpt = repeat + 1;
1049 LOG((0, _T("repeat = %d\n"), repeat));
1050
1051 i = (opcode << 3) | (m_mode & 6);
1052 idx0 = sp0256_df_idx[i++];
1053 idx1 = sp0256_df_idx[i ];
1054
1055 //assert(idx0 >= 0 && idx1 >= 0 && idx1 >= idx0);
1056
1057 /* ---------------------------------------------------------------- */
1058 /* Step through control words in the description for data block. */
1059 /* ---------------------------------------------------------------- */
1060 for (i = idx0; i <= idx1; i++)
1061 {
1062 INT32 len, shf, delta, field, prm, clra, clr5;
1063 INT8 value;
1064
1065 /* ------------------------------------------------------------ */
1066 /* Get the control word and pull out some important fields. */
1067 /* ------------------------------------------------------------ */
1068 cr = sp0256_datafmt[i];
1069
1070 len = CR_LEN(cr);
1071 shf = CR_SHF(cr);
1072 prm = CR_PRM(cr);
1073 clra = cr & CR_CLRA;
1074 clr5 = cr & CR_CLR5;
1075 delta = cr & CR_DELTA;
1076 field = cr & CR_FIELD;
1077 value = 0;
1078
1079 LOG((0, _T("$%.4X.%.1X: len=%2d shf=%2d prm=%2d d=%d f=%d "),
1080 m_pc >> 3, m_pc & 7, len, shf, prm, !!delta, !!field));
1081 /* ------------------------------------------------------------ */
1082 /* Clear any registers that were requested to be cleared. */
1083 /* ------------------------------------------------------------ */
1084 if (clra)
1085 {
1086 for (INT32 j = 0; j < 16; j++)
1087 m_filt.r[j] = 0;
1088
1089 m_silent = 1;
1090 }
1091
1092 if (clr5)
1093 m_filt.r[B5] = m_filt.r[F5] = 0;
1094
1095 /* ------------------------------------------------------------ */
1096 /* If this entry has a bitfield with it, grab the bitfield. */
1097 /* ------------------------------------------------------------ */
1098 if (len)
1099 {
1100 value = getb(len);
1101 }
1102 else
1103 {
1104 LOG((0, _T(" (no update)\n")));
1105 continue;
1106 }
1107
1108 /* ------------------------------------------------------------ */
1109 /* Sign extend if this is a delta update. */
1110 /* ------------------------------------------------------------ */
1111 if (delta) /* Sign extend */
1112 {
1113 if (value & (1 << (len - 1))) value |= -1 << len;
1114 }
1115
1116 /* ------------------------------------------------------------ */
1117 /* Shift the value to the appropriate precision. */
1118 /* ------------------------------------------------------------ */
1119 if (shf)
1120 value <<= shf;
1121
1122 LOG((0, _T("v=%.2X (%c%.2X) "), value & 0xFF,
1123 value & 0x80 ? '-' : '+',
1124 0xFF & (value & 0x80 ? -value : value)));
1125
1126 m_silent = 0;
1127
1128 /* ------------------------------------------------------------ */
1129 /* If this is a field-replace, insert the field. */
1130 /* ------------------------------------------------------------ */
1131 if (field)
1132 {
1133 LOG((0, _T("--field-> r[%2d] = %.2X -> "), prm, m_filt.r[prm]));
1134
1135 m_filt.r[prm] &= ~(~0 << shf); /* Clear the old bits. */
1136 m_filt.r[prm] |= value; /* Merge in the new bits. */
1137
1138 LOG((0, _T("%.2X\n"), m_filt.r[prm]));
1139
1140 continue;
1141 }
1142
1143 /* ------------------------------------------------------------ */
1144 /* If this is a delta update, add to the appropriate field. */
1145 /* ------------------------------------------------------------ */
1146 if (delta)
1147 {
1148 LOG((0, _T("--delta-> r[%2d] = %.2X -> "), prm, m_filt.r[prm]));
1149
1150 m_filt.r[prm] += value;
1151
1152 LOG((0, _T("%.2X\n"), m_filt.r[prm]));
1153
1154 continue;
1155 }
1156
1157 /* ------------------------------------------------------------ */
1158 /* Otherwise, just write the new value. */
1159 /* ------------------------------------------------------------ */
1160 m_filt.r[prm] = value;
1161 LOG((0, _T("--value-> r[%2d] = %.2X\n"), prm, m_filt.r[prm]));
1162 }
1163
1164 /* ---------------------------------------------------------------- */
1165 /* Special case: Set PAUSE's equivalent period. */
1166 /* ---------------------------------------------------------------- */
1167 if (opcode == 0xF)
1168 {
1169 m_silent = 1;
1170 m_filt.r[1] = PER_PAUSE;
1171 }
1172
1173 /* ---------------------------------------------------------------- */
1174 /* Now that we've updated the registers, go decode them. */
1175 /* ---------------------------------------------------------------- */
1176 lpc12_regdec(&m_filt);
1177
1178 /* ---------------------------------------------------------------- */
1179 /* Break out since we now have a repeat count. */
1180 /* ---------------------------------------------------------------- */
1181 break;
1182 }
1183 }
1184
sp0256_ald_write(UINT8 data)1185 void sp0256_ald_write(UINT8 data)
1186 {
1187 /* ---------------------------------------------------------------- */
1188 /* Drop writes to the ALD register if we're busy. */
1189 /* ---------------------------------------------------------------- */
1190
1191 if (!m_lrq)
1192 {
1193 LOG((0, _T("sp0256: Droped ALD write\n")));
1194 return;
1195 }
1196
1197 /* ---------------------------------------------------------------- */
1198 /* Set LRQ to "busy" and load the 8 LSBs of the data into the ALD */
1199 /* reg. We take the command address, and multiply by 2 bytes to */
1200 /* get the new PC address. */
1201 /* ---------------------------------------------------------------- */
1202 m_lrq = 0;
1203 m_ald = (0xff & data) << 4;
1204 m_drq_cb(0);
1205 SET_SBY(0)
1206
1207 return;
1208 }
1209
sp0256_lrq_read()1210 UINT8 sp0256_lrq_read()
1211 {
1212 // force stream update
1213 //m_stream->update();
1214
1215 return m_lrq == 0x8000;
1216 }
1217
sp0256_sby_read()1218 UINT8 sp0256_sby_read()
1219 {
1220 // TODO: force stream update??
1221
1222 return m_sby_line;
1223 }
1224
sp0256_spb640_read(INT32 offset)1225 UINT16 sp0256_spb640_read(INT32 offset)
1226 {
1227 /* -------------------------------------------------------------------- */
1228 /* Offset 0 returns the SP0256 LRQ status on bit 15. */
1229 /* -------------------------------------------------------------------- */
1230 if (offset == 0)
1231 {
1232 return m_lrq;
1233 }
1234
1235 /* -------------------------------------------------------------------- */
1236 /* Offset 1 returns the SPB640 FIFO full status on bit 15. */
1237 /* -------------------------------------------------------------------- */
1238 if (offset == 1)
1239 {
1240 return (m_fifo_head - m_fifo_tail) >= 64 ? 0x8000 : 0;
1241 }
1242
1243 /* -------------------------------------------------------------------- */
1244 /* Just return 255 for all other addresses in our range. */
1245 /* -------------------------------------------------------------------- */
1246 return 0x00ff;
1247 }
1248
sp0256_spb640_write(UINT16 offset,UINT16 data)1249 void sp0256_spb640_write(UINT16 offset, UINT16 data)
1250 {
1251 if (offset == 0)
1252 {
1253 sp0256_ald_write(data & 0xff);
1254 return;
1255 }
1256
1257 if (offset == 1)
1258 {
1259 /* ---------------------------------------------------------------- */
1260 /* If Bit 10 is set, reset the FIFO, and SP0256. */
1261 /* ---------------------------------------------------------------- */
1262
1263 if (data & 0x400)
1264 {
1265 m_fifo_head = m_fifo_tail = m_fifo_bitp = 0;
1266 sp0256_reset();
1267 return;
1268 }
1269
1270 /* ---------------------------------------------------------------- */
1271 /* If the FIFO is full, drop the data. */
1272 /* ---------------------------------------------------------------- */
1273 if ((m_fifo_head - m_fifo_tail) >= 64)
1274 {
1275 LOG((0, _T("spb640: Dropped FIFO write\n")));
1276 return;
1277 }
1278
1279 /* ---------------------------------------------------------------- */
1280 /* FIFO up the lower 10 bits of the data. */
1281 /* ---------------------------------------------------------------- */
1282
1283 LOG((0, _T("spb640: WR_FIFO %.3X %d.%d %d\n"), data & 0x3ff,
1284 m_fifo_tail, m_fifo_bitp, m_fifo_head));
1285
1286 m_fifo[m_fifo_head++ & 63] = data & 0x3ff;
1287
1288 return;
1289 }
1290 }
1291
set_lrq_timer_proc()1292 static void set_lrq_timer_proc()
1293 {
1294 m_lrq = 0x8000;
1295 }
1296
1297 //-------------------------------------------------
1298 // sound_stream_update - handle a stream update
1299 //-------------------------------------------------
sp0256_update(INT16 * sndbuff,INT32 samples_len)1300 void sp0256_update(INT16 *sndbuff, INT32 samples_len)
1301 {
1302 INT32 output_index = 0;
1303 INT32 length, did_samp;
1304
1305 INT32 samples = (samples_from * samples_len) / nBurnSoundLen;
1306
1307 memset(mixer_buffer, 0, samples * sizeof(INT16));
1308
1309 while (output_index < samples)
1310 {
1311 /* ---------------------------------------------------------------- */
1312 /* First, drain as much of our scratch buffer as we can into the */
1313 /* sound buffer. */
1314 /* ---------------------------------------------------------------- */
1315
1316 while (m_sc_tail != m_sc_head)
1317 {
1318 mixer_buffer[output_index++] = m_scratch[m_sc_tail++ & SCBUF_MASK];
1319 m_sc_tail &= SCBUF_MASK;
1320
1321 if (output_index > samples)
1322 break;
1323 }
1324
1325 /* ---------------------------------------------------------------- */
1326 /* If output outputs is full, then we're done. */
1327 /* ---------------------------------------------------------------- */
1328 if (output_index > samples)
1329 break;
1330
1331 length = samples - output_index;
1332
1333 /* ---------------------------------------------------------------- */
1334 /* Process the current set of filter coefficients as long as the */
1335 /* repeat count holds up and we have room in our scratch buffer. */
1336 /* ---------------------------------------------------------------- */
1337 did_samp = 0;
1338
1339 if (length > 0) do
1340 {
1341 INT32 do_samp;
1342
1343 /* ------------------------------------------------------------ */
1344 /* If our repeat count expired, emulate the microsequencer. */
1345 /* ------------------------------------------------------------ */
1346 if (m_filt.rpt <= 0)
1347 micro();
1348
1349 /* ------------------------------------------------------------ */
1350 /* Do as many samples as we can. */
1351 /* ------------------------------------------------------------ */
1352 do_samp = length - did_samp;
1353 if (m_sc_head + do_samp - m_sc_tail > SCBUF_SIZE)
1354 do_samp = m_sc_tail + SCBUF_SIZE - m_sc_head;
1355
1356 if (do_samp == 0) break;
1357
1358 if (m_silent && m_filt.rpt <= 0)
1359 {
1360 INT32 y = m_sc_head;
1361
1362 for (INT32 x = 0; x < do_samp; x++)
1363 m_scratch[y++ & SCBUF_MASK] = 0;
1364 m_sc_head += do_samp;
1365 did_samp += do_samp;
1366 }
1367 else
1368 {
1369 did_samp += lpc12_update(&m_filt, do_samp,
1370 m_scratch, &m_sc_head);
1371 }
1372 if ((length%READY_TIMER)==(READY_TIMER-1)) set_lrq_timer_proc();
1373 m_sc_head &= SCBUF_MASK;
1374
1375 } while (m_filt.rpt >= 0 && length > did_samp);
1376 }
1377
1378 for (INT32 j = 0; j < samples_len; j++)
1379 {
1380 INT32 k = (samples_from * j) / nBurnSoundLen;
1381
1382 INT32 lr = mixer_buffer[k];
1383 sndbuff[0] = BURN_SND_CLIP(sndbuff[0] + lr);
1384 sndbuff[1] = BURN_SND_CLIP(sndbuff[1] + lr);
1385 sndbuff += 2;
1386 }
1387 }
1388