-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspeak.mac
More file actions
2567 lines (2511 loc) · 30.8 KB
/
speak.mac
File metadata and controls
2567 lines (2511 loc) · 30.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.comment\
**************************************************************
* *
* Votrax Text To Speech Program *
* *
* Originally from February 1984 80'Micro, Page 126-154 *
* *
* Allows inflection change by imbedded code: *
* #1, #2, #3, #4 ... produce Bass to Soprano changes *
* #A to #Z produce finer inflection changes (19khz inc.) *
* *
**************************************************************\
.Z80
; *** NOTE: Currently the output buffer just uses un-allocated ram
; at 0F100h, which may conflict later with CP/M PLUS.
outbuf equ 0f100h ; 400 byte output buffer (smaller would do)
; Externals from SBCMON.MAC
extrn sc01_base
extrn port25$image
extrn inflec
extrn lrflag
extrn saveix
extrn ixptr
extrn linbuf
extrn getlin
extrn cr
extrn lf
extrn eot
extrn crlf
extrn print$string
extrn pmsg
extrn crtout
public votrax ; entry point to text input routine
public speak ; entry point to routine to speak a line at (SP)
public sc01$init ; initialize the votrax chip
public send$sc01 ; send A to Votrax chip
; ************************************************************
; Send byte to votrax chip
; ************************************************************
send$sc01:
push de
push hl
push bc
cp 090h ; #A - #Z inflection command?
jr c,no$az
sub 090h
and 00011111b ; mask off high 3 bits
or 80h ; keep strobe high for now
out (sc01_base+1),a ; send to frequency controller (keep strobe high)
ld (port25$image),a ; and updates its memory image
jr arcexit
no$az: cp 080h
jr c,no$14
sub 080h
ld e,a
ld d,0
ld hl,xlate
add hl,de
ld a,(hl)
ld (inflec),a ; save inflection for next time
jr arcexit
; After data is sent out, bring strobe low for 100usec, then bring it high.
; The data will be latched on the rising edge.
no$14: ld hl,inflec
or (hl) ; mask on the inflection
out (sc01_base),a ; send the command
ld a,(port25$image)
and 07fh ; bring strobe line low
out (sc01_base+1),a
; wait about 100 micro sec
ld b,20
delay2: ld hl,(0000) ; 16
djnz delay2 ; 13
ld a,(port25$image)
out (sc01_base+1),a ; set strobe high again
waiter2:in a,(sc01_base)
and 40h
jr z,waiter2 ; wait till chip done
arcexit:pop bc
pop hl
pop de
ret
xlate: db 00,040h,080h,0c0h ; B,T,A,S inflection
; translation table
; ------------------------ Initialization Routine -----------------------
; set default frequency divider value, de-assert strobe, and turn off
; votrax synth. chip.
sc01$init:
ld a, 80h or 018h ; 18h = frequency divider
out (sc01_base + 1),a ; set SC01 strobe high,
; and set freq of chip
ld (port25$image),a ; and preserve its image
ld a,03fh ; no sound command
call send$sc01 ; send to sc01 chip
ret
; ------------------------ Start of Votrax Driver --------------------------
votrax: call print$string
defb 0dh,0ah,'Votrax Text Voicer (^C exits). #1 to #4 & #A to #Z produce inflection changes.',eot
call sc01$init ; initialize the hardware
; Input the english text here into buffer.
TEST: call print$string
defb cr,lf,'>',eot
ld hl,linbuf+1 ; input line to normal input buffer
ld c,78 ; allow 78 characters input
call getlin ; input a bufered console line
ret c ; return to monitor if control character found
ld a,(linbuf+1) ; see if null line
cp cr
ret z ; return to monitor if ^C
ld ix,linbuf+1 ; point to input line
call begin ; and go convert and speak line
jp test ; and continue
; --------------------- External Line Input Entry Point -----------------
; External modules can call this routine to speak a line of text, using
; the calling convention:
;
; call speak
; defm 'Speak this line of text',eot
speak: push iy
push ix
push hl
push de
push bc
push af
ld hl,0
add hl,sp
ld de,12
add hl,de
push hl ; save return addr stack location
ld e,(hl)
inc hl
ld d,(hl)
push de
pop ix
speak2: ld a,(de) ; find last byte of string
inc de
cp eot
jr nz,speak2
pop hl
ld (hl),e ; put back new return address
inc hl
ld (hl),d
call begin ; go speak sentence
pop af
pop bc
pop de
pop hl
pop ix
pop iy
ret
; --------------------- End of init routines ---------------------------
begin: LD DE,OUTBUF ;GET START OF OUTPUT BUFFER
LD B,255 ;BYTE COUNTER
LD A,3FH ;BYTE TO CONDITION BUFFER
CLRBF1:
LD (DE),A ;CONDITION OUTPUT BUFFER
INC DE
DJNZ CLRBF1 ;DO ALL 256
LD B,145 ;LOAD COUNTER
CLRBF2:
LD (DE),A ;CONTINUE TO CONDITION
INC DE
DJNZ CLRBF2
; capitalize the input buffer, shift it to left one position as it goes along.
ld hl,linbuf ; point to cleaned up buffer
push ix
pop de ; point to input buffer
LD (HL),' ' ; FILL FIRST LOCATION WITH BLANK
INC HL ;START TO PUT DATA
EX DE,HL ;SWAP POINTERS
ML1: LD A,(HL) ; GET CHARACTER FROM STRING BUFFER
cp 'a' ; test for lower case
jr c,ml2
sub 20h
ML2: ld (de),a
inc de
inc hl
cp cr
jr z,ml3
cp eot
jr nz,ml1
ml3: ex de,hl
dec hl
LD (hl),' ' ; LOAD BLANKS TO END
inc hl
ld (hl),0
ld ix,linbuf ; point to text to convert
ld iy,outbuf
;***************************************************************
; CHARACTER LOOKUP ROUTINE
;***************************************************************
CHTYPE:
LD HL,CHTBLE ; POINT TO START OF TABLE
LD A,(ENDTBL) ; GET LENGTH OF TABLE
ADD A,-3 ; OBTAIN PROPER LENGTH
LD B,0
LD C,A
LD A,(IX) ; GET STRING CHARACTER
INC HL
LOOP:
INC HL
INC HL ; LOCATION OF RULE
CPI ; HL=HL+1 BC=BC+1
JR Z,MATCH
DEC C
DEC C
JR NZ,LOOP ; GET SET TO SCAN AGAIN
JP INFLT ; CHECK FOR INFLECTION
;
MATCH:
LD E,(HL) ; GET LSB OF CHAR RULES
INC HL ;
LD D,(HL) ; GET MSB OF CHAR RULES
LD (SAVEIX),IX
EX DE,HL ; PUT START OF STRING IN HL
JP RULSCN ; COMPARE TO RULES
;
;*************************************************************
; Inflection change routine = #
;*************************************************************
;
INFLT:
CP '#'
JP NZ,G1
INC IX
LD A,(IX)
cp '1' ; less than 1?
JP C,G1 ; ignore character then
CP '5' ; greater than 4?
JP NC,a$to$z ; see if freq change character
sub '1' ; make 0-3
add a,080h ; add offset
jr code
a$to$z: cp 'A' ; less than A?
jp c,G1 ; yes, ignore character
cp 'Z'+1 ; greater than Z?
jp nc,G1
sub 'A'
add a,096H ; add offset and freq offset
; since hardware is 0-31 and
; alphabet is only 0-25 so
; bias to faster frequencies
CODE: ld (iy),a ; load code to output buffer
inc iy
JP G1 ; get next character
;************************************************************
; RULE SCANNING
;************************************************************
;
RULSCN:
PUSH IX
POP DE ; MAKE DE POINTER TO START OF RULES
RULSN1:
CP (HL)
JR Z,OK
JP NEXTRL
OK:
INC HL
LD A,(HL) ; GET NEXT RULE CHARACTER
CP '<'
JP Z,LEFT
CP '>'
JP Z,RIGHT
CP '='
JP Z,TXFR ; SET THE PHONEMES TO THE TALK BUFFER
INC IX
LD A,(IX) ; GET NEW STRING CHARACTER
JR RULSN1
;
; LEFT SCAN ROUTINE
;
LEFT:
INC HL
PUSH HL
LD HL,LRFLAG
SET 0,(HL)
POP HL
LD A,(HL)
CP '!' ; NOT ALPHA
JP Z,NOALPH
CP '#'
JP Z,VOWEL ;CHECK VOWELS
CP ':'
JP Z,CONSTS ; 0 OR MORE CONSONANTS
CP '+'
JP Z,FRNTVL ; FRONT VOWEL
CP '^'
JP Z,CONSNT ; 1 OR MORE CONSONANTS
CP '.'
JP Z,VCNSNT ; VOICED CONSONANT
CP '&'
JP Z,SIBLNT ; SIBILANT
CP '$'
JP Z,INFCON
CP '>'
JP Z,RIGHT
CP '='
JP Z,TXFR
JP ASCCHK
;*****************************************************
;
;*****************************************************
;
RIGHT:
INC HL ; INC TO NEXT CHAR RULE
PUSH HL
LD HL,LRFLAG ; GET L/R FLAG
BIT 4,(HL) ; SET AT <>IX PTR TIME
JR NZ,RPASS ; SAVE ONLY ONCE
LD (IXPTR),IX ; SAVE POINTER
SET 4,(HL)
RPASS:
RES 0,(HL) ; RESET FOR RIGHT SCAN
POP HL
LD A,(HL)
CP '!'
JP Z,NOALPH ; GOTO BLANK ROUTINE
CP '#'
JP Z,VOWEL ; CHECK FOR VOWELS
CP ':'
JP Z,CONSTS ; 0 OR MORE CONSONANTS
CP '^'
JP Z,CONSNT ; CHECK FOR 1 CONSONANT
CP '+'
JP Z,FRNTVL ; CHECK FOR FRONT VOWEL
CP '.'
JP Z,VCNSNT ; VOICED CONSONANT
CP '%'
JP Z,SUFFIX
CP '='
JP Z,TXFR
JP ASCCHK
; *********************************************************
; NON-ALPHA TEST = !
; **********************************************************
NOALPH:
CALL SIDER
RNO:
SUB 40H ; TEST FOR NON-ALPHA
JP P,NEXTRL ; GET NEXT RULE IF ANY
JP QUITS
;
;***********************************************************
; TEST FOR ONE OR MORE VOWELS = #
;***********************************************************
;
VOWEL:
PUSH HL ; SAVE TABLE RULE POINTER
PUSH BC
LD C,0FFH
VREPT: LD HL,VMESS ; GET PARMS
LD A,(VMLEN) ; LENGTH
LD B,A ; LOAD B WITH LENGTH
INC C
CALL SIDER
RVOW:
CP (HL) ; COMPARE TO VMESS VALUE
JP Z,VREPT ; MATCH?
INC HL ; INC TO NEXT VMESS VALUE
DJNZ RVOW ; GO BACK AND CHECK
LD A,C
OR A ; IS IT POSITIVE
POP BC
POP HL ; RESTORE RULE POINTER
JP Z,NEXTRL ; MUST MATCH AT LEAST ONE VOWEL
call unsider
JP QUITS
;
VMESS: DB 'AEIOUY'
VMLEN: DB $-VMESS
;
;*************************************************************
; 0 OR MORE CONSONANTS = :
;*************************************************************
;
CONSTS: PUSH HL
CREPT: LD HL,CONMES
LD A,(CONLEN)
LD B,A
CALL SIDER
RCON:
CP (HL)
JR Z,CREPT
INC HL
DJNZ RCON
POP HL ;FAILED TO MATCH
call unsider
JP QUITS
;*************************************************************
; MATCH ONE CONSONANT = *
;*************************************************************
;
CONSNT:
LD A,(CONLEN) ;TABLE LENGTH
LD B,A ;B IS THE LOOP LENGTH
CALL SIDER
RCONS:
PUSH HL ; SAVE RULE PTR
LD HL,CONMES ; START OF CONSONANTS
CLOOP:
CP (HL) ; COMPARE
JR Z,CMATCH ; SKIP IF FOUND MATCH
INC HL ; INC TO NEXT CONSONANT
DJNZ CLOOP ; CHECK NEXT VALUE
POP HL ; RESORE RULE POINTER
JP NEXTRL ; CHECK NEXT RULE
CMATCH:
POP HL ; RESTORE RULE POINTER
JP QUITS
;
CONMES:
DB 'BCDFGHJKLMNPQRSTVWXZ'
CONLEN: DB $-CONMES
;
;*****************************************************
; MATCH A VOICED CONSONANT = .
;*****************************************************
;
VCNSNT:
LD A,(VCONLE) ; TABLE LENGTH
LD B,A
CALL SIDER
VCRT:
PUSH HL
LD HL,VMESSL
VLOOP:
CP (HL)
JR Z,VMATCH
INC HL
DJNZ VLOOP
POP HL
JP NEXTRL
VMATCH:
POP HL
JP QUITS
;
VMESSL: DB 'BDGJLMNRVWZ'
VCONLE: DB $-VMESSL
;
;******************************************************
; MATCH FRONT VOWEL = +
;******************************************************
;
FRNTVL:
CALL SIDER
FVR:
CP 'E'
JR Z,FVMTCH
CP 'I'
JR Z,FVMTCH
CP 'Y'
JR Z,FVMTCH
JP NEXTRL
FVMTCH:
JP QUITS
;
;***********************************************
; TEST FOR SUFFIXES
;***********************************************
;
SUFFIX:
PUSH HL ; RIGHT SCAN ONLY
INC IX ; INC STRING POINTER
PUSH IX ; AND SAVE IT
LD A,(SMESSL) ; GET LENGTH
LD B,A
LD HL,SMESS
SLOOP1:
LD A,(IX) ; GET CHAR
CP (HL) ; COMPARE VALUE
JR Z,SECCHK ; CHECK SECOND VALUE IF THERE
SLOOP2:
DEC B ; DEC LOOP COUNTER
JR Z,ROUTER ; NO MATCH
INC HL ; INC MESS POINTER
LD A,(HL) ; GET NEXT VALUE
CP ','
JR NZ,SLOOP2 ; GO TEST AGAIN
POP IX
PUSH IX
INC HL
JR SLOOP1
SECCHK:
INC HL
LD A,(HL)
CP ','
JR Z,FNDMTH
INC IX
DJNZ SLOOP1
;
ROUTER:
POP IX
POP HL
JP NEXTRL
FNDMTH:
POP BC
POP HL
JP RIGHT
;
SMESS: DB 'E,ER,ES,ED,ING,ELY,'
SMESSL: DB $-SMESS
;
;*********************************************************
; CHECK SIBILANTS = &
;*********************************************************
;
SIBLNT:
PUSH HL ; SAVE RULE PTR
LD HL,SIBMES ; GET START OF TABLE
LD A,(SIBLEN)
LD B,A ; SAVE IT
CALL SIBCON ; GO AND COMPARE
POP HL
JP NZ,NEXTRL
JP LEFT
;
;*********************************************************
; INFLUENCING CONSONANT = $
;*********************************************************
;
INFCON:
PUSH HL ; SAVE RULE PTR
LD HL,CONSM
LD A,(CONSLN)
LD B,A
CALL SIBCON ; GO CHECK FOR MATCH
POP HL
JP NZ,NEXTRL
JP LEFT
;
;********************************************************
; COMMON ROUTINE FOR SIBILANT AND INFLUENCING CONSONANT CHECK
;********************************************************
;
SIBCON:
DEC DE ; DEC LEFT POINTER
PUSH DE
SIBLOP:
LD A,(DE)
CP (HL)
JR Z,CHKAGN ; SKIP IF NO AND CHECK AGAIN
SIB2:
DEC B ; DEC LOOP COUNTER
JR Z,SIBERR ; ZERO = NO MATCH
INC HL ; INC TABLE POINTER
LD A,(HL) ; GET VALUE
CP ','
JR NZ,SIB2 ; SKIP IF NOT
POP DE
PUSH DE
INC HL
JR SIBLOP ; CHECK AGAIN
CHKAGN:
INC HL
LD A,(HL)
CP ','
JR Z,FNDIT
DEC DE
DJNZ SIBLOP ; GO BACK AND CHECK
;
SIBERR:
POP DE
set 7,A ; SET ERROR BIT
BIT 7,A ; Z=(b7=0)=FALSE = 0
RET
FNDIT:
POP DE
res 7,A ; bit 7=0
BIT 7,A ; z=(b7=0)=true=1
RET
;
SIBMES: DB 'S,C,G,Z,X,J,HC,HS,' ; BACKWARDS
SIBLEN: DB $-SIBMES
;
CONSM:
DB 'T,S,R,D,L,Z,N,J,HT,HC,HS,'
CONSLN: DB $-CONSM
;
;******************************************************
; CHECK FOR RIGHT OR LEFT ASCII CHARACTER
;******************************************************
;
ASCCHK:
CALL SIDER
CHECK:
CP (HL)
JP NZ,NEXTRL
JP QUITS
;
; RIGHT OR LEFT TEST TO CHECK SCAN INDICATOR
;
SIDER:
LD A,(LRFLAG) ; left or right side call?
BIT 0,A
JR NZ,GETDE ; jp if left rule
INC IX ; right rule, get next char
LD A,(IX) ; get character
JR EXIT ; and return
GETDE:
DEC DE ; back up and get character
LD A,(DE)
EXIT: RET
unsider:
ld a,(lrflag)
bit 0,a
jr nz,putde
dec ix
ld a,(ix)
jr unexit
putde:
inc de
ld a,(de)
unexit:
ret
QUITS:
LD A,(LRFLAG)
BIT 0,A
JP Z,RIGHT
JP LEFT
SIDE:
LD A,(LRFLAG)
BIT 0,A
RET
;
;***************************************
; SET POINTERS FOR NEXT RULE SCAN
;*****************************************
;
NEXTRL:
NOP
NLOOP:
LD A,(HL)
CP '@' ; GET RULE SEPARATOR
JR Z,FNDNXT
CP '['
JP Z,ERROR
INC HL
JR NLOOP
;
FNDNXT:
XOR A ; CLEAR ACCUMULATOR
LD (LRFLAG),A ; CLEAR FLAG WORD
LD IX,(SAVEIX) ; RESTORE IX FOR NEXT RULE
LD A,(IX) ; GET CHAR
INC HL ; SET POINTER PAST @ MARKER
JP RULSCN ; CHECK NEXT RULE
;
;********************************************************
; TRANSFER DATA TO TALK BUFFER
;********************************************************
;
TXFR:
INC HL ; SET POINTER PAST = SIGN
TLOOP: LD A,(HL) ; GET VALUE
CP '@' ; DONE TXFR?
JR Z,GNXTCH ; Z=TEST FOR DONE
LD (IY),A ; PUT DATA TO TALK BUFFER
INC IY
INC HL
JR TLOOP
;
GNXTCH:
LD A,(LRFLAG)
BIT 4,A ; IS BIT 4 SET?
JR Z,G1
LD IX,(IXPTR)
G1:
INC IX
XOR A
CP (IX)
JR Z,OUTPUT ; 0 = DONE DECODING
LD (LRFLAG),A ; CLEAR FLAG FOR NEXT RULE
JP CHTYPE
ERROR:
LD A,0DH
CALL WCHAR
LD A,'$'
INC IX
LD (IX),A
LD HL,linbuf
CALL WSTRING
LD HL,ERRMES
JP RETURN
WCHAR:
PUSH AF
PUSH BC
PUSH DE
PUSH HL
call crtout
POP HL
POP DE
POP BC
POP AF
RET
WSTRING:jp pmsg
ERRMES: DB 00,00,2BH,00H,3EH,3AH,3FH,3EH
; Output coded string to Votrax Chip
OUTPUT: LD HL,OUTBUF
OUT1:
OLOOP:
LD A,(HL)
CALL send$sc01
LD A,(HL)
CP 3FH
JR Z,RETURN
OL1:
INC HL
JR OLOOP
RETURN:
XOR A
LD (LRFLAG),A
ret
; JP BEGIN ; return from program here
OLDSTK: DS 2
;
EH3 EQU 00H
EH2 EQU 01H
EH1 EQU 02H
PA0 EQU 03H
DT EQU 04H
A2 EQU 05H
A1 EQU 06H
ZH EQU 07H
AH2 EQU 08H
I3 EQU 09H
I2 EQU 0AH
I1 EQU 0BH
MM EQU 0CH
N EQU 0DH
BB EQU 0EH
V EQU 0FH
CH EQU 10H
SH EQU 11H
ZZ EQU 12H
AW1 EQU 13H
NG EQU 14H
AH1 EQU 15H
OO1 EQU 16H
OO EQU 17H
LL EQU 18H
K EQU 19H
J EQU 1AH
HH EQU 1BH
G EQU 1CH
F EQU 1DH
DD EQU 1EH
S EQU 1FH
AA EQU 20H
AY EQU 21H
Y1 EQU 22H
UH3 EQU 23H
AH EQU 24H
PP EQU 25H
O EQU 26H
II EQU 27H
U EQU 28H
Y EQU 29H
T EQU 2AH
RR EQU 2BH
EE EQU 2CH
W EQU 2DH
AE EQU 2EH
AE1 EQU 2FH
AW2 EQU 30H
UH2 EQU 31H
UH1 EQU 32H
UH EQU 33H
O2 EQU 34H
O1 EQU 35H
IU EQU 36H
U1 EQU 37H
THV EQU 38H
TH EQU 39H
ER EQU 3AH
EH EQU 3BH
E1 EQU 3CH
AW EQU 3DH
PA1 EQU 3EH
STOP EQU 3FH
CHTBLE:
DS 3
DB 'A'
DW ARULES
DB 'B'
DW BRULES
DB 'C'
DW CRULES
DB 'D'
DW DRULES
DB 'E'
DW ERULES
DB 'F'
DW FRULES
DB 'G'
DW GRULES
DB 'H'
DW HRULES
DB 'I'
DW IRULES
DB 'J'
DW JRULES
DB 'K'
DW KRULES
DB 'L'
DW LRULES
DB 'M'
DW MRULES
DB 'N'
DW NRULES
DB 'O'
DW ORULES
DB 'P'
DW PRULES
DB 'Q'
DW QRULES
DB 'R'
DW RRULES
DB 'S'
DW SRULES
DB 'T'
DW TRULES
DB 'U'
DW URULES
DB 'V'
DW VRULES
DB 'W'
DW WRULES
DB 'X'
DW XRULES
DB 'Y'
DW YRULES
DB 'Z'
DW ZRULES
DB ' '
DW BLANK
DB '.'
DW PERIOD
DB 39
DW APOST
DB ','
DW COMMA
DB '?'
DW QUEST
DB '1'
DW RULE1
DB '2'
DW RULE2
DB '3'
DW RULE3
DB '4'
DW RULE4
DB '5'
DW RULE5
DB '6'
DW RULE6
DB '7'
DW RULE7
DB '8'
DW RULE8
DB '9'
DW RULE9
DB '0'
DW RULE0
db '-'
dw minus
db '+'
dw plus
db '='
dw equals
DB '*'
DW MULT
DB '/'
DW DIVIDE
DB '<'
DW LTHAN
DB '>'
DW GTHAN
DB '^'
DW TOTHE
DB ':'
DW COLON
DB ';'
DW SEMICO
DB '!'
DW EXCLA
DB '"'
DW QUOTE
DB '$'
DW DOLLAR
DB '%'
DW PERCNT
DB '('
DW RBRACK
DB ')'
DW LBRACK
DB '@'
DW ATSYM
ENDTBL: DB $-CHTBLE
SPECIAL: DB '#?*.$%&@^+:','@'
; ********************************
; Rule tables
; ********************************
PUNCTRULES:
ARULES:
DB 'A<!>!='
DB A1
DB AY
DB Y
DB '@'
DB 'A<!>H='
DB UH2
DB '@'
DB 'A>!='
DB UH2
DB '@'
DB 'ARE>!='
DB AH,ER,RR,'@'
DB 'AR<!>O='
DB UH2,RR,'@'
DB 'AR>#='
DB EH2,RR,'@'
DB 'AS<^!>#='
DB AE1,EH3,S,'@'
DB 'A>WA='
DB UH2
DB '@'
DB 'AW='
DB AW
DB '@'
DB 'ANY<:!='
DB EH2,EH2,N,Y,'@'
DB 'A>^+#='
DB AA
DB AY
DB '@'
DB 'ALLY<:#='
DB UH2
DB LL
DB EE
DB '@'
DB 'AL<!>#='
DB UH1
DB LL
DB '@'
DB 'AGAIN='