1 /*
2 * t6721.c - Toshiba 6721a Emulation
3 *
4 * Written by
5 * groepaz <groepaz@gmx.net>
6 *
7 * This file is part of VICE, the Versatile Commodore Emulator.
8 * See README for copyright notice.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * 02111-1307 USA.
24 *
25 */
26
27 #include "vice.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33
34 #include "lib.h"
35 #include "maincpu.h"
36 #include "monitor.h"
37 #include "snapshot.h"
38 #include "t6721.h"
39
40 /*
41
42 toshiba 6721a (voice output)
43
44 based on code from alankila (parcor.py) and nojoopa (mvtool)
45
46 - 8 kHz 9bit output (output is rendered in 16 bit)
47 - generates output for 20ms (or 10ms) out of 6 byte voice data!
48 - uses PARCOR voice synthesizing and analyzing method (Nippon Telegraph and Telephon Public Corporation)
49
50 */
51
52 #ifndef M_PI
53 #define M_PI 3.14159265358979323846
54 #endif
55
56 /* #define T6721DEBUG */
57
58 #define WRITEWAVFILE 0 /* write "test.wav" containing all generated output */
59
60 #ifdef T6721DEBUG
61 #define DBG(x) DBG_STATUS(); printf x;
62 #define DBGADD(x) printf x
63 #define DBG_STATUS() \
64 printf("t6721: @:%04x apd: %d busy: %d eos: %d playing: %d ", reg_pc, t6721->apd, t6721->busy, t6721->eos, t6721->playing);
65 #else
66 #define DBG(x)
67 #define DBGADD(x)
68 #define DBG_STATUS()
69 #endif
70
71 #define PARCOR_OUTPUT_HZ (8000)
72
73 #define PARCOR_BUFFER_LEN (0x400)
74 int16_t ringbuffer[PARCOR_BUFFER_LEN]; /* FIXME */
75 int ringbuffer_rptr = 0;
76 int ringbuffer_wptr = 0;
77 int phrase_sample_len = 0;
78
79 #define RBSTATE_STOP 0
80 #define RBSTATE_PLAY 1
81 #define RBSTATE_DELAY_SAMPLES (PARCOR_OUTPUT_HZ / 200) /* 5 ms */
82 static int ringbuffer_state = 0;
83
84 float upsmpcnt = 0;
85 float upsmp = 0;
86
87 struct param_s {
88 uint8_t energy;
89 uint8_t pitch;
90 int16_t k[10];
91 };
92 typedef struct param_s param_t;
93
94 static param_t p_from = { 0, 0x21, { 0 } };
95 static param_t p_to = { 0, 0x21, { 0 } };
96 static double p_z[11] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
97
98 /* FIXME: MOVE parcor parameters: energy + pitch + k1..10 */
99 static uint16_t parcor_param[1 + 1 + 10];
100
101 /*
102 words that use 48bits/frame:
103
104 magicvoice rom:
105
106 68 "ing"
107 78 "what"
108 80 "who"
109 105 "is"
110 129 "as"
111 130 "but"
112 148 "thuh"
113 151 "with"
114 158 "bad"
115 164 "because"
116 193 "orange"
117 209 "may"
118 225 "program"
119
120 v364 and WoW do NOT use 48bit frames !
121 */
122
123 /* parameter lengths (bits) */
124 /* [1] k0..k9 from speak and spell
125 * (48bit frames) 5, 5, 4, 4, 4, 4, 4, 3, 3, 3 (18bits + 21bits = 39bits, 9 free)
126 * [2] k0..k9 from "Handbook of Data Compression By David Salomon, Giovanni Motta, David (CON) Bryant
127 * (48bit frames) 3, 4, 4, 4, 4, 3, 3, 3, 3, 3 (15bits + 19bits = 34bits, 14 free)
128 */
129 static const int parcor_param_len[2][1 + 1 + 10] = {
130 /* FIXME: 48 bits/frame (this is vaguely guessed and totally wrong)
131 12 ? bits for energy+pitch
132 21 ? bits for k1..4
133 15 ? bits for k5..10
134 */
135 {6, 6, 6, 5, 5, 5, 3, 3, 3, 2, 2, 2},
136 #if 0
137 { 4, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3 }, /* [1] vaguely recognizeable */
138 { 7, 7, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3 }, /* [2] not working */
139 #endif
140 /* 96 bits/frame (these seem correct)
141 14 bits for energy+pitch
142 38 bits for k1..4
143 44 bits for k5..10
144 */
145 { 7, 7, 10, 10, 10, 8, 8, 8, 7, 7, 7, 7 }
146 };
147 static uint16_t chip_buf = 0;
148 static int chip_bit_i = 0;
149 static int param_i = 0;
150
151 #define PARMVALUE(ctx, x) (parcor_param[x] >> (16 - parcor_param_len[(ctx)->cond2_framebits][x]))
152
153 /* ------------------------------------------------------------------------- */
154
155 static void set_dtrd(t6721_state *t6721, int dtrd);
156 static void set_apd(t6721_state *t6721, int apd);
157 static void set_eos(t6721_state *t6721, int eos);
158 static void set_playing(t6721_state *t6721, int playing);
159
160 /*****************************************************************************
161 WAV Writer (for debugging)
162 *****************************************************************************/
163
164 #if WRITEWAVFILE
165 static FILE *wav_fp = NULL;
166 static size_t wavsize = 0;
167
168 static const uint8_t wav_header[] = {
169 'R', 'I', 'F', 'F',
170 0, 0, 0, 0, /* filesize - 8 */
171 'W', 'A', 'V', 'E',
172 'f', 'm', 't', ' ',
173 16, 0, 0, 0,
174 1, 0,
175 1, 0,
176 0x40, 0x1f, 0, 0, /* 8000 Hz */
177 0x80, 0x3e, 0, 0, /* 8000 Hz * 2B/sample */
178 2, 0,
179 16, 0,
180 'd', 'a', 't', 'a',
181 0, 0, 0, 0 /* bytes to follow (== wavsize)*/
182 };
183
write_header(void)184 static int write_header(void)
185 {
186 if (fwrite(wav_header, 1, sizeof(wav_header), wav_fp) < sizeof(wav_header)) {
187 fclose(wav_fp);
188 wav_fp = NULL;
189 return 1;
190 }
191 return 0;
192 }
193
fix_header(void)194 static int fix_header(void)
195 {
196 size_t temp;
197 uint8_t b[4] = { 0, 0, 0, 0 };
198
199 fseek(wav_fp, 4, SEEK_SET);
200
201 temp = wavsize + sizeof(wav_header) - 8;
202
203 b[0] = (temp >> 0) & 0xff;
204 b[1] = (temp >> 8) & 0xff;
205 b[2] = (temp >> 16) & 0xff;
206 b[3] = (temp >> 24) & 0xff;
207
208 if (fwrite(b, 1, 4, wav_fp) < 4) {
209 fclose(wav_fp);
210 wav_fp = NULL;
211 return 1;
212 }
213
214 fseek(wav_fp, 40, SEEK_SET);
215
216 temp = wavsize;
217
218 b[0] = (temp >> 0) & 0xff;
219 b[1] = (temp >> 8) & 0xff;
220 b[2] = (temp >> 16) & 0xff;
221 b[3] = (temp >> 24) & 0xff;
222
223 if (fwrite(b, 1, 4, wav_fp) < 4) {
224 fclose(wav_fp);
225 wav_fp = NULL;
226 return 1;
227 }
228
229 return 0;
230 }
231
wav_close_file(void)232 static void wav_close_file(void)
233 {
234 if (wav_fp) {
235 fix_header();
236 fclose(wav_fp);
237 wav_fp = NULL;
238 }
239 }
240
wav_create_file(const char * filename)241 static int wav_create_file(const char *filename)
242 {
243 if ((wav_fp = fopen(filename, "wb")) == NULL) {
244 perror(filename);
245 return 1;
246 }
247
248 archdep_vice_atexit(wav_close_file);
249 return write_header();
250 }
251
wav_write_sample(int16_t data)252 static int wav_write_sample(int16_t data)
253 {
254 uint8_t d;
255
256 if (wav_fp == NULL) {
257 wav_create_file("test.wav");
258 }
259
260 d = (uint8_t)(data & 0xff);
261
262 if (fwrite(&d, 1, 1, wav_fp) < 1) {
263 return 1;
264 }
265
266 wavsize++;
267
268 d = (uint8_t)((data >> 8) & 0xff);
269
270 if (fwrite(&d, 1, 1, wav_fp) < 1) {
271 return 1;
272 }
273
274 wavsize++;
275
276 return 0;
277 }
278 #endif
279
280 /*****************************************************************************
281 Output Ringbuffer
282 *****************************************************************************/
283
ringbuffer_reset(void)284 static void ringbuffer_reset(void)
285 {
286 ringbuffer_rptr = 0;
287 ringbuffer_wptr = 0;
288 ringbuffer_state = RBSTATE_STOP;
289 phrase_sample_len = 0;
290 }
291
292 /*
293 write one 8000khz sample to the output ringbuffer
294 returns 1 on error, 0 on success
295 */
parcor_output_sample(t6721_state * t6721,int16_t value)296 static int parcor_output_sample(t6721_state *t6721, int16_t value)
297 {
298 int next_wptr;
299
300 ringbuffer[ringbuffer_wptr] = value;
301 #if WRITEWAVFILE
302 wav_write_sample(value);
303 #endif
304 next_wptr = ringbuffer_wptr + 1;
305 if (next_wptr == PARCOR_BUFFER_LEN) {
306 next_wptr = 0;
307 }
308 if (next_wptr != ringbuffer_rptr) {
309 ringbuffer_wptr = next_wptr;
310 phrase_sample_len++;
311 return 0;
312 }
313 /* DBG(("ringbuffer overflow\n")); */
314 return 1;
315 }
316
317 /*
318 render one output sample
319 */
output_update_sample(t6721_state * t6721)320 static int16_t output_update_sample(t6721_state *t6721)
321 {
322 static float from, to;
323 int next_rptr;
324 int16_t this;
325
326 this = (int16_t)((from * (1.0f - upsmpcnt)) + (to * upsmpcnt));
327
328 upsmpcnt += (1.0f / upsmp);
329 if (upsmpcnt >= 1.0f) {
330 upsmpcnt -= 1.0f;
331 from = to;
332 if (ringbuffer_state == RBSTATE_STOP) {
333 if (phrase_sample_len > RBSTATE_DELAY_SAMPLES) {
334 ringbuffer_state = RBSTATE_PLAY;
335 }
336 } else {
337 if (phrase_sample_len > 0) {
338 next_rptr = ringbuffer_rptr + 1;
339 if (next_rptr == PARCOR_BUFFER_LEN) {
340 next_rptr = 0;
341 }
342 if (next_rptr != ringbuffer_wptr) {
343 ringbuffer_rptr = next_rptr;
344 phrase_sample_len--;
345 }
346 } else {
347 ringbuffer_state = RBSTATE_STOP;
348 }
349 }
350 to = (float) ringbuffer[ringbuffer_rptr];
351 }
352
353 return this;
354 }
355
356 static int framestretch[0x10] =
357 {
358 100, /* 0 : 1,0 */
359 70, /* 1 : 0,7 (1.4% faster) */
360 80, /* 2 : 0,8 */
361 90, /* 3 : 0,9 */
362 100, /* 4 : 1,0 (default) */
363 110, /* 5 : 1,1 */
364 120, /* 6 : 1,2 */
365 130, /* 7 : 1,3 */
366 140, /* 8 : 1,4 */
367 150, /* 9 : 1,5 */
368 155, /* a : 1,55 (0.65% slower) */
369 100, /* b : 1,0 */
370 100, /* c : 1,0 */
371 100, /* d : 1,0 */
372 100, /* e : 1,0 */
373 100 /* f : 1,0 */
374 };
375
get_frame_samples(t6721_state * t6721)376 static int get_frame_samples(t6721_state *t6721)
377 {
378 return ((t6721->cycles_per_sec * t6721->cond2_framelen * framestretch[t6721->speed]) / (100 * 100));
379 }
380
get_subframe_samples(t6721_state * t6721)381 static int get_subframe_samples(t6721_state *t6721)
382 {
383 return ((PARCOR_OUTPUT_HZ * t6721->cond2_framelen * framestretch[t6721->speed]) / (100 * 100 * 8));
384 }
385
386 /*****************************************************************************
387 PARCOR Synthesis
388 *****************************************************************************/
389
filter(int i,double ef,double k)390 static double filter(int i, double ef, double k)
391 {
392 double ef_prev = ef + k * p_z[1 + i - 1];
393 p_z[1 + i] = p_z[1 + i - 1] - k * ef_prev;
394 return ef_prev;
395 }
396
397 /* -------------------------------------------------------------------------
398 render one PARCOR subframe
399 returns 1 on error, 0 on success
400 ------------------------------------------------------------------------- */
render_subframe(t6721_state * t6721,int sub_i,int voiced)401 static int render_subframe(t6721_state *t6721, int sub_i, int voiced)
402 {
403 int i, j;
404 static double phase = 0.0;
405
406 double energy = ((p_from.energy * (8 - sub_i)) + (p_to.energy * sub_i)) / (8.0 * 127.0);
407 uint8_t pitch;
408 double phase_inc;
409
410 double k[10];
411
412 double sample, data;
413
414 int16_t output;
415
416 if (voiced) {
417 pitch = ((p_from.pitch * (8 - sub_i)) + (p_to.pitch * sub_i)) / 8;
418 phase_inc = 1.0 / (double)(pitch);
419 } else {
420 pitch = 0;
421 phase_inc = 0.0;
422 }
423
424 /* DBG(("voiced %i, energy %f, pitch %02x, phase_inc %f, k: ", voiced, energy, pitch, phase_inc)); */
425
426 for (i = 0; i < 10; ++i) {
427 k[i] = ((p_from.k[i] * (8 - sub_i)) + (p_to.k[i] * sub_i)) / (8.0 * 32768.0);
428 /* DBGADD(("%f, ", k[i])); */
429 }
430 /* DBGADD(("\n")); */
431
432 for (i = 0; i < get_subframe_samples(t6721); ++i) {
433 /* sample */
434 if (voiced) {
435 phase += phase_inc;
436 if (phase >= 1.0) {
437 phase -= 1.0;
438 }
439 sample = cos(M_PI * phase * phase);
440 } else {
441 /* FIXME: implement the actual pseudo random number generator used
442 on the chip */
443 sample = lib_float_rand(-1.0, 1.0);
444 }
445 sample *= energy;
446
447 /* filter */
448 data = sample;
449 for (j = t6721->cond2_stages - 1; j >= 0; --j) {
450 data = filter(j, data, k[j]);
451 }
452
453 /* scale to 16bit */
454 output = (int16_t)(data * (8192.0f + 2048.0f));
455
456 if (parcor_output_sample(t6721, output)) {
457 return 1;
458 }
459 }
460
461 return 0;
462 }
463
render_silence(t6721_state * t6721)464 static int render_silence(t6721_state *t6721)
465 {
466 int i;
467
468 for (i = 0; i < (get_subframe_samples(t6721) * 8); ++i) {
469 if (parcor_output_sample(t6721, 0)) {
470 return 1;
471 }
472 }
473
474 return 0;
475 }
476
477 /* -------------------------------------------------------------------------
478 render one PARCOR frame
479 returns 1 on error, 0 on success
480 ------------------------------------------------------------------------- */
parcor_render_frame(t6721_state * t6721,uint16_t * new_param)481 static int parcor_render_frame(t6721_state *t6721, uint16_t *new_param)
482 {
483 int i, voiced, silent;
484 uint8_t new_pitch;
485
486 new_pitch = (uint8_t)PARMVALUE(t6721, 1);
487 voiced = (new_pitch > 0);
488
489 memcpy(&p_from, &p_to, sizeof(p_from));
490
491 p_to.energy = (uint8_t)PARMVALUE(t6721, 0);
492 silent = ((new_pitch == 0x7e) && (p_to.energy == 1));
493
494 if (!voiced && !silent) {
495 new_pitch = p_from.pitch;
496 }
497
498 p_to.pitch = new_pitch;
499
500 if (!silent) {
501 for (i = 0; i < (voiced ? (12 - 2) : (6 - 2)); ++i) {
502 p_to.k[i] = (int16_t)(new_param[i + 2]);
503 }
504
505 for (i = 0; i < 8; ++i) {
506 if (render_subframe(t6721, i, voiced)) {
507 return 1;
508 }
509 }
510 } else {
511 if (render_silence(t6721)) {
512 return 1;
513 }
514 }
515
516 return 0;
517 }
518
519 /*****************************************************************************
520 handle data input from the DI line
521 *****************************************************************************/
522
523 static int parcor_framelen = 12;
524 static int parcor_frametype;
525 static int phrase_samples = 0;
526
527 static int zero_frames = 0;
528
529 /* read nibbles from FIFO and re-arrange into a parcor frame */
reset_di_fifo(void)530 static void reset_di_fifo(void)
531 {
532 chip_buf = 0;
533 chip_bit_i = 0;
534 param_i = 0;
535 }
536
537 /*
538 read data (one bit) from the DI line
539
540 returns:
541 -1 no data available
542 0 normal exit
543 1 got PARCOR frame
544 */
read_di_fifo(t6721_state * t6721)545 static int read_di_fifo(t6721_state *t6721)
546 {
547 unsigned int bit;
548 /*
549 if (t6721->dtrd) {
550 set_dtrd(t6721, 0);
551 return -1;
552 }
553
554 set_dtrd(t6721, 1);
555 */
556 if (t6721->read_data(t6721, &bit) < 1) {
557 /* DBGADD(("<*>")); */
558 return -1;
559 }
560
561 if ((param_i == 1) && (chip_bit_i == 0)) {
562 if (PARMVALUE(t6721, 0) == 0) {
563 if (bit) {
564 reset_di_fifo();
565 set_eos(t6721, 1);
566 t6721->busy = 0;
567 set_playing(t6721, 0);
568 parcor_framelen = 1;
569 parcor_frametype = T6721_FRAMETYPE_EOS;
570 zero_frames = 0;
571 return 1;
572 } else {
573 reset_di_fifo();
574 zero_frames++;
575 parcor_framelen = 1;
576 parcor_frametype = T6721_FRAMETYPE_ZERO;
577
578 if (zero_frames > 1) {
579 set_eos(t6721, 1);
580 t6721->busy = 0;
581 set_playing(t6721, 0);
582 zero_frames = 0;
583 }
584 return 1;
585 }
586 }
587 zero_frames = 0;
588 }
589
590 chip_buf >>= 1;
591 chip_buf |= bit ? 0x8000 : 0;
592 chip_bit_i++;
593
594 /* DBGADD(("(%x)", bit)); */
595
596 if (chip_bit_i < parcor_param_len[t6721->cond2_framebits][param_i]) {
597 return 0;
598 }
599
600 /* DBGADD(("<%03x>", chip_buf)); */
601
602 /* next parm is ready */
603 parcor_param[param_i] = chip_buf;
604 chip_bit_i = 0;
605 chip_buf = 0;
606
607 switch (param_i) {
608 case 0:
609 parcor_framelen = 12;
610 break;
611 case 1:
612 if (PARMVALUE(t6721, 1) == 0) {
613 parcor_framelen = 6;
614 parcor_frametype = T6721_FRAMETYPE_UNVOICED;
615 } else {
616 if ((PARMVALUE(t6721, 0) == 1) && (PARMVALUE(t6721, 1) == 0x7e)) {
617 parcor_frametype = T6721_FRAMETYPE_SILENT;
618 } else {
619 parcor_frametype = T6721_FRAMETYPE_VOICED;
620 }
621 }
622 break;
623 }
624
625 param_i++;
626
627 if (param_i == parcor_framelen) {
628 /* complete frame was read */
629 reset_di_fifo();
630 return 1;
631 }
632
633 return 0;
634 }
635
636 /*****************************************************************************
637 *****************************************************************************/
638
set_playing(t6721_state * t6721,int playing)639 static void set_playing(t6721_state *t6721, int playing)
640 {
641 if (t6721->playing != playing) {
642 if (playing) {
643 DBG(("start playing\n"));
644 t6721->playing_delay = 0x10000; /* FIXME: find out real value */
645 } else {
646 DBG(("stop playing\n"));
647 ringbuffer_reset();
648 reset_di_fifo(); /* ? */
649 }
650 }
651 t6721->playing = playing;
652 }
653
set_dtrd(t6721_state * t6721,int dtrd)654 static void set_dtrd(t6721_state *t6721, int dtrd)
655 {
656 t6721->dtrd = dtrd;
657 if (t6721->set_dtrd) {
658 t6721->set_dtrd(t6721);
659 }
660 }
661
set_apd(t6721_state * t6721,int apd)662 static void set_apd(t6721_state *t6721, int apd)
663 {
664 t6721->apd = apd;
665 if (t6721->set_apd) {
666 t6721->set_apd(t6721);
667 }
668 }
669
set_eos(t6721_state * t6721,int eos)670 static void set_eos(t6721_state *t6721, int eos)
671 {
672 if (t6721->eos != eos) {
673 t6721->eos = eos;
674 if (eos) {
675 t6721->status |= T6721_STATUS_END_OF_SPEECH;
676 } else {
677 t6721->status &= ~T6721_STATUS_END_OF_SPEECH;
678 }
679 if (t6721->set_eos) {
680 t6721->set_eos(t6721);
681 }
682 }
683 if (eos) {
684 /* FIXME: confirm: is this correct ? */
685 /* 10ms or 20ms depending on current framelen */
686 t6721->eos_samples = get_frame_samples(t6721);
687 }
688 }
689
690 /*****************************************************************************
691 "run" chip and update output_samples
692
693 FIXME: this perhaps needs some other (per cycle) hook (?)
694 *****************************************************************************/
695
696 /* run chip for exactly one CPU/System Cycle */
t6721_update_tick(t6721_state * t6721)697 void t6721_update_tick(t6721_state *t6721)
698 {
699 int res;
700 #ifdef T6721DEBUG
701 int i;
702 #endif
703
704 /* once asserted, the EOS signal is generated for 20ms */
705 if (t6721->eos_samples == 0) {
706 set_eos(t6721, 0);
707 } else {
708 t6721->eos_samples--;
709 }
710
711 if (t6721->playing_delay) {
712 t6721->playing_delay--;
713 return;
714 }
715
716 if (phrase_samples) {
717 phrase_samples--;
718 return;
719 }
720
721 if ((t6721->playing == 1) && (t6721->apd == 0) && (t6721->eos == 0)) {
722 set_dtrd(t6721, 1);
723 res = read_di_fifo(t6721);
724 if (res == -1) {
725 /* not enough data in FIFO */
726 } else if (res == 1) {
727 /* got PARCOR frame */
728 if ((parcor_frametype == T6721_FRAMETYPE_SILENT) ||
729 (parcor_frametype == T6721_FRAMETYPE_VOICED) ||
730 (parcor_frametype == T6721_FRAMETYPE_UNVOICED)) {
731 parcor_render_frame(t6721, parcor_param);
732 }
733 /* FIXME: confirm: is this correct ? */
734 /* 10ms or 20ms depending on current framelen */
735 phrase_samples = get_frame_samples(t6721) - (((t6721->cond2_framebits ? 96 : 48) * 10 * framestretch[t6721->speed]) / 100);
736 set_dtrd(t6721, 0);
737 #ifdef T6721DEBUG
738 DBG(("got Frame: "));
739 switch (parcor_frametype) {
740 case T6721_FRAMETYPE_VOICED:
741 DBGADD(("[voiced] "));
742 break;
743 case T6721_FRAMETYPE_UNVOICED:
744 DBGADD(("[unvoiced] "));
745 break;
746 case T6721_FRAMETYPE_EOS:
747 DBGADD(("[eos] "));
748 break;
749 case T6721_FRAMETYPE_ZERO:
750 DBGADD(("[zero] "));
751 break;
752 case T6721_FRAMETYPE_SILENT:
753 DBGADD(("[silent] "));
754 break;
755 }
756 for (i = 0; i < parcor_framelen; i++) {
757 DBGADD(("%03x ", parcor_param[i] >> (16 - parcor_param_len[t6721->cond2_framebits][i])));
758 }
759 DBGADD(("\n"));
760 #endif
761 }
762 }
763 }
764
765 /* run chip for N CPU/System Cycles */
t6721_update_ticks(t6721_state * t6721,int ticks)766 void t6721_update_ticks(t6721_state *t6721, int ticks)
767 {
768 while (ticks) {
769 t6721_update_tick(t6721);
770 t6721->cycles_done++;
771 ticks--;
772 }
773 }
774
775 float up2smp = 0;
776
777 /* render num samples into output buffer, run remaining cycles (if any) */
t6721_update_output(t6721_state * t6721,int16_t * buf,int num)778 void t6721_update_output(t6721_state *t6721, int16_t *buf, int num)
779 {
780 int i;
781 int cycles;
782
783 cycles = (int)((num * up2smp) - t6721->cycles_done);
784 if (cycles > 0) {
785 /* run chip for remaining cycles */
786 t6721_update_ticks(t6721, cycles);
787 t6721->cycles_done = 0;
788 } else {
789 /* carry over remaining cycles to next sound frame */
790 t6721->cycles_done = 0 - cycles;
791 }
792
793 /* render output samples */
794 for (i = 0; i < num; i++) {
795 *buf++ = output_update_sample(t6721);
796 }
797 }
798
799 /*****************************************************************************
800 Chip Command Handling
801 *****************************************************************************/
802
803 /*
804 when the WR pin goes high, d0..d3 from data are read by ("written to") the chip
805 */
t6721_store(t6721_state * t6721,uint8_t data)806 void t6721_store(t6721_state *t6721, uint8_t data)
807 {
808 /* DBG(("write %2x\n", data)); */
809 /* an actual store is performed on Lo->HI transition of WR */
810 if ((t6721->wr == 1) && (t6721->wr_last == 0)) {
811 if (t6721->cmd_nibbles) {
812 switch (t6721->cmd_current) {
813 case 0x03: /* ADDRESS LOAD 1/6 */
814 DBG(("arg %2x (ADDRESS LOAD %d/6)\n", data, 6 - t6721->cmd_nibbles));
815 break;
816 case 0x05: /* SPEED LOAD 1/2 */
817 DBG(("arg %2x (SPEED LOAD %d/2)\n", data, 3 - t6721->cmd_nibbles));
818 t6721->speed = data;
819 break;
820 case 0x06: /* CONDITION 1 1/2 */
821 DBG(("arg %2x (CONDITION 1 %d/2) ", data, 3 - t6721->cmd_nibbles));
822 t6721->condition1 = data;
823 if (t6721->condition1 & T6721_COND1_LOSS) {
824 t6721->cond1_loss = T6721_LOSS_ENABLED;
825 } else {
826 t6721->cond1_loss = T6721_LOSS_DISABLED;
827 }
828 if (t6721->condition1 & T6721_COND1_SHAPE) {
829 t6721->cond1_shape = T6721_SHAPE_TRIANGLE;
830 } else {
831 t6721->cond1_shape = T6721_SHAPE_PITCH;
832 }
833 DBGADD(("loss effect calculation: %d Sound Source Shape: %s\n", t6721->cond1_loss, t6721->cond1_shape ? "Triangle" : "Pitch" ));
834 break;
835 case 0x07: /* CONDITION 2 1/2 */
836 DBG(("arg %2x (CONDITION 2 %d/2) ", data, 3 - t6721->cmd_nibbles));
837 t6721->condition2 = data;
838 if (t6721->condition2 & T6721_COND2_STAGES) {
839 t6721->cond2_stages = T6721_STAGES_8;
840 } else {
841 t6721->cond2_stages = T6721_STAGES_10;
842 }
843 if (t6721->condition2 & T6721_COND2_REPEAT) {
844 t6721->cond2_repeat = T6721_REPEAT_DISABLED;
845 } else {
846 t6721->cond2_repeat = T6721_REPEAT_ENABLED;
847 }
848 if (t6721->condition2 & T6721_COND2_LENGTH) {
849 t6721->cond2_framelen = T6721_FRAME_10MS;
850 } else {
851 t6721->cond2_framelen = T6721_FRAME_20MS;
852 }
853 if (t6721->condition2 & T6721_COND2_BPFRAME) {
854 t6721->cond2_framebits = T6721_FRAME_96BIT;
855 } else {
856 t6721->cond2_framebits = T6721_FRAME_48BIT;
857 }
858 DBGADD(("stages: %d repeat: %d len: %d0ms bits: %d\n", t6721->cond2_stages, t6721->cond2_repeat, t6721->cond2_framelen, t6721->cond2_framebits ? 96 : 48 ));
859 break;
860 }
861
862 t6721->cmd_nibbles--;
863 } else {
864 t6721->cmd_current = data;
865
866 switch (data) {
867 case 0x00: /* NOP nop */
868 DBG(("cmd %2x (nop)\n", data));
869 t6721->readmode = T6721_READMODE_STATUS;
870 break;
871 case 0x01: /* STRT start */
872 DBG(("cmd %2x (start)\n", data));
873 set_playing(t6721, 1);
874 set_eos(t6721, 0);
875 t6721->status &= ~T6721_STATUS_ROM_DATA_ERROR; /* release rom data error status */
876 t6721->readmode = T6721_READMODE_STATUS;
877 break;
878 case 0x02: /* STOP stop */
879 DBG(("cmd %2x (stop)\n", data));
880 set_playing(t6721, 0);
881 t6721->readmode = T6721_READMODE_STATUS;
882 break;
883 case 0x03: /* ADDRESS LOAD 1/6 */
884 DBG(("cmd %2x (ADDRESS LOAD 1/6)\n", data));
885 t6721->cmd_nibbles = 5;
886 t6721->readmode = T6721_READMODE_STATUS;
887 break;
888 case 0x04: /* AAGN AUDIO ASGIN */
889 DBG(("cmd %2x (AUDIO ASGIN)\n", data));
890 set_apd(t6721, 0); /* release audio power down signal */
891 t6721->readmode = T6721_READMODE_STATUS;
892 break;
893 case 0x05: /* SPLD SPEED LOAD 1/2 */
894 DBG(("cmd %2x (SPEED LOAD 1/2)\n", data));
895 t6721->cmd_nibbles = 1;
896 t6721->readmode = T6721_READMODE_STATUS;
897 break;
898 case 0x06: /* CNDT1 CONDITION 1 1/2 */
899 DBG(("cmd %2x (CONDITION 1 1/2)\n", data));
900 t6721->cmd_nibbles = 1;
901 t6721->readmode = T6721_READMODE_STATUS;
902 break;
903 case 0x07: /* CNDT2 CONDITION 2 1/2 */
904 DBG(("cmd %2x (CONDITION 2 1/2)\n", data));
905 t6721->cmd_nibbles = 1;
906 t6721->readmode = T6721_READMODE_STATUS;
907 break;
908 case 0x08: /* RRDM ROM READ MODE */
909 DBG(("cmd %2x (ROM READ MODE)\n", data));
910 t6721->readmode = T6721_READMODE_ROM;
911 break;
912 case 0x09: /* SPDN system power down */
913 DBG(("cmd %2x (system power down)\n", data));
914 set_playing(t6721, 0);
915 t6721->readmode = T6721_READMODE_STATUS;
916 break;
917 case 0x0a: /* APDN AUDIO POWER DOWN */
918 DBG(("cmd %2x (AUDIO POWER DOWN)\n", data));
919 set_apd(t6721, 1); /* raise audio power down signal */
920 t6721->readmode = T6721_READMODE_STATUS;
921 break;
922 case 0x0b: /* SAGN system assign */
923 DBG(("cmd %2x (system assign)\n", data));
924 set_playing(t6721, 0);
925 t6721->status &= ~T6721_STATUS_SYSTEM_POWER_DOWN; /* release system power down status */
926 t6721->readmode = T6721_READMODE_STATUS;
927 break;
928 /* c-f is "redundant" ? */
929 case 0x0c:
930 case 0x0d:
931 case 0x0e:
932 case 0x0f:
933 DBG(("cmd %2x (redundant ?)\n", data));
934 t6721->status |= T6721_STATUS_COMMAND_ERROR; /* raise command error status */
935 break;
936 }
937 }
938 }
939
940 t6721->wr_last = t6721->wr;
941 }
942
t6721_read(t6721_state * t6721)943 uint8_t t6721_read(t6721_state *t6721)
944 {
945 int data;
946
947 if (t6721->readmode == T6721_READMODE_STATUS) {
948 data = (t6721->status & 0x0f);
949 } else {
950 /* FIXME: read-through from speech ROM is missing */
951 data = 0;
952 DBG(("FIXME read-through from speech ROM\n"));
953 }
954
955 return data;
956 }
957
958 /*****************************************************************************/
959
t6721_reset(t6721_state * t6721)960 void t6721_reset(t6721_state *t6721)
961 {
962 t6721->cmd_nibbles = 0;
963 t6721->cmd_current = 0;
964
965 t6721->speed = 0; /* param for speed load cmd */
966 t6721->condition1 = 0;
967 t6721->condition2 = 0;
968
969 t6721->busy = 0; /* BSY signal */
970 set_apd(t6721, 1); /* APD signal */
971 set_eos(t6721, 0); /* EOS signal */
972 set_dtrd(t6721, 0); /* DTRD signal */
973 set_playing(t6721, 0); /* stop playing */
974
975 t6721->status = 0;
976 t6721->readmode = T6721_READMODE_STATUS;
977 }
978
t6721_sound_machine_init(t6721_state * t6721,int speed,int cycles_per_sec)979 void t6721_sound_machine_init(t6721_state *t6721, int speed, int cycles_per_sec)
980 {
981 DBG(("sound machine init: speed %d cycles/sec: %d\n", speed, cycles_per_sec));
982 t6721->samples_per_sec = speed;
983 t6721->cycles_per_sec = cycles_per_sec;
984 /* ratio for converting ringbuffer -> output */
985 upsmp = (((float)speed) / ((float)PARCOR_OUTPUT_HZ));
986 /* ratio for converting samples in output buffer -> cpu/system cycles */
987 up2smp = (((float)cycles_per_sec) / ((float)speed));
988 }
989
t6721_sound_machine_init_vbr(t6721_state * t6721,int speed,int cycles_per_sec,int factor)990 void t6721_sound_machine_init_vbr(t6721_state *t6721, int speed, int cycles_per_sec, int factor)
991 {
992 DBG(("sound machine init: speed %d cycles/sec: %d\n", speed, cycles_per_sec));
993 t6721->samples_per_sec = speed;
994 t6721->cycles_per_sec = (cycles_per_sec * 1000 / factor);
995 /* ratio for converting ringbuffer -> output */
996 upsmp = (((float)speed) / ((float)PARCOR_OUTPUT_HZ));
997 /* ratio for converting samples in output buffer -> cpu/system cycles */
998 up2smp = (((float)cycles_per_sec) / ((float)speed));
999 }
1000
t6721_dump(t6721_state * t6721)1001 int t6721_dump(t6721_state *t6721)
1002 {
1003 mon_out("reference cycles per second: %d\n", t6721->cycles_per_sec);
1004 mon_out("output sample per second: %d\n", t6721->samples_per_sec);
1005 mon_out("apd: %d busy: %d eos: %d playing: %d\n", t6721->apd, t6721->busy, t6721->eos, t6721->playing);
1006 return 0;
1007 }
1008
1009 /* ---------------------------------------------------------------------*/
1010 /* snapshot support functions */
1011
1012 #define CART_DUMP_VER_MAJOR 0
1013 #define CART_DUMP_VER_MINOR 0
1014 #define SNAP_MODULE_NAME "T6721"
1015
1016 /* FIXME: implement snapshot support */
t6721_snapshot_write_module(snapshot_t * s,t6721_state * t6721)1017 int t6721_snapshot_write_module(snapshot_t *s, t6721_state *t6721)
1018 {
1019 return -1;
1020 #if 0
1021 snapshot_module_t *m;
1022
1023 m = snapshot_module_create(s, SNAP_MODULE_NAME,
1024 CART_DUMP_VER_MAJOR, CART_DUMP_VER_MINOR);
1025 if (m == NULL) {
1026 return -1;
1027 }
1028
1029 if (0) {
1030 snapshot_module_close(m);
1031 return -1;
1032 }
1033
1034 snapshot_module_close(m);
1035 return 0;
1036 #endif
1037 }
1038
t6721_snapshot_read_module(snapshot_t * s,t6721_state * t6721)1039 int t6721_snapshot_read_module(snapshot_t *s, t6721_state *t6721)
1040 {
1041 return -1;
1042 #if 0
1043 uint8_t vmajor, vminor;
1044 snapshot_module_t *m;
1045
1046 m = snapshot_module_open(s, SNAP_MODULE_NAME, &vmajor, &vminor);
1047 if (m == NULL) {
1048 return -1;
1049 }
1050
1051 if ((vmajor != CART_DUMP_VER_MAJOR) || (vminor != CART_DUMP_VER_MINOR)) {
1052 snapshot_module_close(m);
1053 return -1;
1054 }
1055
1056 if (0) {
1057 snapshot_module_close(m);
1058 return -1;
1059 }
1060
1061 snapshot_module_close(m);
1062 return 0;
1063 #endif
1064 }
1065