-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patht102rom.asm
20069 lines (18435 loc) · 658 KB
/
t102rom.asm
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
#ifndef MEMVARS
#include "memvar.inc"
#endif
org 0000H
; ======================================================
; Reset Vector
; ======================================================
JMP L1BA7H ; Different from M100: Jump to boot routine
org 0003H
DB "MENU",00H
org 0008H
; ======================================================
; Compare next byte with M
; ======================================================
MOV A,M ; Get byte from (HL)
XTHL ; Get address of next inst. from stack
CMP M ; Compare with expected code byte
JNZ ERRSYN ; Generate Syntax error if no match
INX H ; Increment past the compare byte
XTHL ; Put new return address on stack
; Fall through to get next BASIC instruction. The code above is
; used to parse the validity of BASIC statements.
org 0010H
; ======================================================
; Get next non-white char from M
; ======================================================
JMP L0858H ; RST 10H routine with pre-increment of HL
; ======================================================
; Load pointer to Storage of TEXT Line Starts in DE
; ======================================================
XCHG
LHLD VTXTLS ; Storage of TEXT Line Starts
XCHG
org 0018H
; ======================================================
; Compare DE and HL
; ======================================================
MOV A,H ; Compare MSB first to test <>
SUB D ; Compare with D
RNZ ; Return if not equal
MOV A,L ; Prepare to test LSB
SUB E ; Compare with E
RET
org 001EH
; ======================================================
; VRVIDFSend a space to screen/printer
; ======================================================
MVI A,20H ; Load SPACE into A
org 0020H
; ======================================================
; Send character in A to screen/printer
; ======================================================
JMP LCD ; Send A to screen or printer
NOP
org 0024H
; ======================================================
; Power down TRAP
; ======================================================
JMP VLPSIH ; RAM vector for TRAP interrupt
NOP
org 0028H
; ======================================================
; Determine type of last var used
; ======================================================
JMP L1069H ; RST 28H routine
NOP
org 002CH
; ======================================================
; RST 5.5 -- Bar Code Reader
; ======================================================
DI
JMP VBCRIH ; RST 5.5 RAM Vector
org 0030H
; ======================================================
; Get sign of FAC1
; ======================================================
JMP L33DCH ; RST 30H routine
NOP
org 0034H
; ======================================================
; RST 6.5 -- RS232 character pending
; ======================================================
DI
JMP L6DACH ; RST 6.5 routine (RS232 receive interrupt)
org 0038H
; ======================================================
; RAM vector table driver
; ======================================================
JMP L7FD6H ; RST 38H RAM vector driver routine
NOP
org 003CH
; ======================================================
; RST 7.5 -- Timer background task
; ======================================================
DI
JMP L1B32H ; RST 7.5 interrupt routine
org 0040H
; ======================================================
; Function vector table for SGN to MID$
; ======================================================
DW 3407H,3654H,33F2H,2B4CH
DW 1100H,10C8H,10CEH,305AH
DW 313EH,2FCFH,30A4H,2EEFH
DW 2F09H,2F58H,2F71H,1284H
DW 1889H,506DH,506BH,3501H
DW 352AH,35BAH,3645H,2943H
DW 273AH,2A07H,294FH,295FH
DW 298EH,29ABH,29DCH,29E6H
org 0080H
; ======================================================
; BASIC statement keyword table END to NEW
; ======================================================
DB 80H or 'E',"ND" ; 0
DB 80H or 'F',"OR"
DB 80H or 'N',"EXT"
DB 80H or 'D',"ATA"
DB 80H or 'I',"NPUT"
DB 80H or 'D',"IM" ; 5
DB 80H or 'R',"EAD"
DB 80H or 'L',"ET"
DB 80H or 'G',"OTO"
DB 80H or 'R',"UN"
DB 80H or 'I',"F" ; 10
DB 80H or 'R',"ESTORE"
DB 80H or 'G',"OSUB"
DB 80H or 'R',"ETURN"
DB 80H or 'R',"EM"
DB 80H or 'S',"TOP" ; 15
DB 80H or 'W',"IDTH"
DB 80H or 'E',"LSE"
DB 80H or 'L',"INE"
DB 80H or 'E',"DIT"
DB 80H or 'E',"RROR" ; 20
DB 80H or 'R',"ESUME"
DB 80H or 'O',"UT"
DB 80H or 'O',"N"
DB 80H or 'D',"SKO$"
DB 80H or 'O',"PEN" ; 25
DB 80H or 'C',"LOSE"
DB 80H or 'L',"OAD"
DB 80H or 'M',"ERGE"
DB 80H or 'F',"ILES"
DB 80H or 'S',"AVE" ; 30
DB 80H or 'L',"FILES"
DB 80H or 'L',"PRINT"
DB 80H or 'D',"EF"
DB 80H or 'P',"OKE"
DB 80H or 'P',"RINT" ; 35
DB 80H or 'C',"ONT"
DB 80H or 'L',"IST"
DB 80H or 'L',"LIST"
DB 80H or 'C',"LEAR"
DB 80H or 'C',"LOAD" ; 40
DB 80H or 'C',"SAVE"
DB 80H or 'T',"IME$"
DB 80H or 'D',"ATE$"
DB 80H or 'D',"AY$"
DB 80H or 'C',"OM" ; 45
DB 80H or 'M',"DM"
DB 80H or 'K',"EY"
DB 80H or 'C',"LS"
DB 80H or 'B',"EEP"
DB 80H or 'S',"OUND" ; 50
DB 80H or 'L',"COPY"
DB 80H or 'P',"SET"
DB 80H or 'P',"RESET"
DB 80H or 'M',"OTOR"
DB 80H or 'M',"AX" ; 55
DB 80H or 'P',"OWER"
DB 80H or 'C',"ALL"
DB 80H or 'M',"ENU"
DB 80H or 'I',"PL"
DB 80H or 'N',"AME" ; 60
DB 80H or 'K',"ILL"
DB 80H or 'S',"CREEN"
DB 80H or 'N',"EW"
org 018FH
; ======================================================
; Function keyword table TAB to <
; ======================================================
DB 80H or 'T',"AB("
DB 80H or 'T',"O" ; 65
DB 80H or 'U',"SING"
DB 80H or 'V',"ARPTR"
DB 80H or 'E',"RL"
DB 80H or 'E',"RR"
DB 80H or 'S',"TRING$" ; 70
DB 80H or 'I',"NSTR"
DB 80H or 'D',"SKI$"
DB 80H or 'I',"NKEY$"
DB 80H or 'C',"SRLIN"
DB 80H or 'O',"FF" ; 75
DB 80H or 'H',"IMEM"
DB 80H or 'T',"HEN"
DB 80H or 'N',"OT"
DB 80H or 'S',"TEP"
DB 80H or '+' ; 80
DB 80H or '-'
DB 80H or '*'
DB 80H or '/'
DB 80H or '^'
DB 80H or 'A',"ND" ; 85
DB 80H or 'O',"R"
DB 80H or 'X',"OR"
DB 80H or 'E',"QV"
DB 80H or 'I',"MP"
DB 80H or 'M',"OD" ; 90
DB 80H or '\'
DB 80H or '>'
DB 80H or '='
DB 80H or '<'
org 01F0H
; ======================================================
; Function keyword table SGN to MID$
; ======================================================
DB 80H or 'S',"GN" ; 95
DB 80H or 'I',"NT"
DB 80H or 'A',"BS"
DB 80H or 'F',"RE"
DB 80H or 'I',"NP"
DB 80H or 'L',"POS" ; 100
DB 80H or 'P',"OS"
DB 80H or 'S',"QR"
DB 80H or 'R',"ND"
DB 80H or 'L',"OG"
DB 80H or 'E',"XP" ; 105
DB 80H or 'C',"OS"
DB 80H or 'S',"IN"
DB 80H or 'T',"AN"
DB 80H or 'A',"TN"
DB 80H or 'P',"EEK" ; 110
DB 80H or 'E',"OF"
DB 80H or 'L',"OC"
DB 80H or 'L',"OF"
DB 80H or 'C',"INT"
DB 80H or 'C',"SNG" ; 115
DB 80H or 'C',"DBL"
DB 80H or 'F',"IX"
DB 80H or 'L',"EN"
DB 80H or 'S',"TR$"
DB 80H or 'V',"AL" ; 120
DB 80H or 'A',"SC"
DB 80H or 'C',"HR$"
DB 80H or 'S',"PACE$"
DB 80H or 'L',"EFT$"
DB 80H or 'R',"IGHT$" ; 125
DB 80H or 'M',"ID$"
DB 80H or "'" ; 127
DB 80H
org 0262H
; ======================================================
; BASIC statement vector table for END to NEW
; ======================================================
DW 409FH,0726H,4174H,099EH
DW 0CA3H,478BH,0CD9H,09C3H
DW 0936H,090FH,0B1AH,407FH
DW 091EH,0966H,09A0H,409AH
DW 1DC3H,09A0H,0C45H,5E51H
DW 0B0FH,0AB0H,110CH,0A2FH
DW 5071H,4CCBH,4E28H,4D70H
DW 4D71H,1F3AH,4DCFH,506FH
DW 0B4EH,0872H,128BH,0B56H
DW 40DAH,1140H,113BH,40F9H
DW 2377H,2280H,19ABH,19BDH
DW 19F1H,1A9EH,1A9EH,1BB8H
DW 4231H,4229H,1DC5H,1E5EH
DW 1C57H,1C66H,1DECH,7F0BH
DW 1419H,1DFAH,5797H,1A78H
DW 2037H,1F91H,1E22H,20FEH
org 02E2H
; ======================================================
; Operator order of precedence table
; ======================================================
DB 79H, 79H, 7CH, 7CH
DB 7FH, 50H, 46H, 3CH
DB 32H, 28H, 7AH, 7BH
DB BAH, 35H, 00H, 00H
org 02F2H
; ======================================================
; Vector table for math operations
; ======================================================
DW 3501H,35D9H
DW 352AH,2B78H,2B69H,2CFFH
DW 2DC7H,3D8EH,34FAH,37F4H
DW 37FDH,3803H,380EH,3D7FH
DW 3498H,3704H,36F8H,3725H
DW 0F0DH,3DF7H,34C2H
org 031CH
; ======================================================
; BASIC error message text
; ======================================================
DB "NF"
DB "SN"
DB "RG"
DB "OD"
DB "FC"
DB "OV"
DB "OM"
DB "UL"
DB "BS"
DB "DD"
DB "/0"
DB "ID"
DB "TM"
DB "OS"
DB "LS"
DB "ST"
DB "CN"
DB "IO"
DB "NR"
DB "RW"
DB "UE"
DB "MO"
DB "IE"
DB "BN"
DB "FF"
DB "AO"
DB "EF"
DB "NM"
DB "DS"
DB "FL"
DB "CF"
; ======================================================
; L035AH: Initialization image loaded to F5F0H
; ======================================================
DB 4DH ; LSB of COLD vs WARM boot marker (at address VSSYS)
DB 8AH ; MSB of COLD vs WARM boot marker
DB 00H ; Auto PowerDown signature LSB (at address VSPOPD)
DB 00H ; Auto PowerDown signature MSB
DB F0H ; LSB of HIMEM (VHIMEM)
DB F5H ; MSB of HIMEM
RET ; This RET can be changed to JMP to hook Boot-up (VPWONH)
NOP ; Space for address for JMP
NOP
EI ; This is the hook for WAND (VBCRIH) (RST 5.5)
RET ; Replace EI, RET, NOP with a JMP instruction
NOP
RET ; This is the RST 6.5 routine (RS232 receive interrupt) hook (VUARTH)
NOP ; Replace RET, NOP, NOP with a JMP instruction
NOP
RET ; This is the RST 7.5 hook (Background tick) (VTLINH)
NOP
NOP
JMP L1431H ; Normal TRAP (low power) interrupt routine - Hook at VLPSIH
org 036FH
; ======================================================
; External ROM detect image loaded at F605H
; ======================================================
DB 3EH,01H,D3H,E8H,21H,40H,00H,11H ; F605H - MVI A,01H; OUT E8H; LXI H,L0040H; LXI D,VARETH
DB A4H,FAH,7EH,12H,23H,13H,7DH,D6H ; F60DH - MVI A,M; STAX D; INX H; INX D; MOV A,L; SUI 48H
DB 48H,C2H,0FH,F6H,D3H,E8H,2AH,A4H ; F515H - JNZ F60FH; OUT E8H; LHLD VARETH;
DB FAH,11H,41H,42H,C3H,18H,00H,F3H ; F61DH - LXI D,L4142H; JMP 0018H; DI; ; Different from M100
DB 3EH,01H,D3H,E8H,C7H,00H,01H,00H ; F625H - MVI A,01H; OUT E8H; RST 0
DB 00H,FFH,FFH,00H,00H,00H,00H,00H ; F62DH \
DB 00H,00H,00H,00H,01H,01H,08H,28H ; F635H \
DB 00H,00H,00H,01H,01H,01H,01H,19H ; F63DH \
DB 28H,00H,00H,00H,50H,38H,30H,00H ; F645H \
DB 00H,00H,00H,00H,00H,00H,00H,00H ; F64DH \ Initialized Data space at F6XXH
DB 00H,00H,64H,FFH,00H,00H,4DH,37H ; F655H /
DB 49H,31H,44H,C3H,00H,00H,00H,C9H ; F65DH / ; Different from M100
DB 00H,C9H,D3H,00H,C9H,DBH,00H,C9H ; F665H /
DB 3AH,00H,00H,00H,00H,00H,00H,00H ; F66DH /
DB 00H,0EH,00H,15H,FDH,FEH,FFH,B2H ; F675H
DB FCH,00H,00H
org 03EAH
; ======================================================
; BASIC message strings
; ======================================================
DB " Error",00H
DB " in ",00H
DB "Ok",0DH,0AH,00H
DB "Break",00H
; ======================================================
; L0401H: Pop return address for NEXT or RETURN
; ======================================================
POPRET: LXI H,L0004H ; Prepare to point to BASIC token in stack
DAD SP ; Offset into stack
NXTLVL: MOV A,M ; Load BASIC token that caused the push (FOR or GOSUB)
INX H ; Increment back in stack past token
CPI 81H ; Test for FOR token
RNZ ; Return if not FOR token
MOV C,M
INX H
MOV B,M
INX H
PUSH H
MOV H,B
MOV L,C
MOV A,D
ORA E
XCHG
JZ L0419
XCHG
RST 3 ; Compare DE and HL
L0419: LXI B,L0016H ; TODO: find better name
POP H
RZ
DAD B
JMP NXTLVL ; Jump to test next level of FOR/GOSUB
; ======================================================
; L0422H: Initialize system and go to BASIC ready
; ======================================================
LXI B,L0501H ; Pop stack and vector to BASIC ready
JMP L048DH ; Restore stack & runtime and jump to BC
; ======================================================
; L0428H: Normal end of program reached
; ======================================================
ENDPRG: LHLD VBSCLN ; Current executing line number
MOV A,H ; Get MSB of executing line number
ANA L ; AND LSB of executing line number
INR A ; Test if executing line number is FFFFh
JZ LNFFFF ; Jump if executing line number is FFFFh
LDA VBASRF ; BASIC Program Running Flag
ORA A ; Test if program running
MVI E,13H ; Load code for NR Error (No RESUME)
JNZ L045DH ; Generate error in E if program running
LNFFFF: JMP L40B6H ; Branch into middle of "END" statement
; ======================================================
; L043DH: Never CALLed. Maybe used by OptROMS?
; ======================================================
JMP L045DH ; Generate error in E TODO: find out if this is ever reached
; ======================================================
; L0440H: Generate SN error on DATA statement line
; ======================================================
GERRSN: LHLD FB94H ; Line number of current data statement
SHLD VBSCLN ; Current executing line number
; ======================================================
; L0446H: Generate Syntax error
; ======================================================
ERRSYN: MVI E,02H ; Load value for SN Error TODO: examine this, it doesn't make sense
DB 01H
MVI E,0BH ; Load value for /0 Error
DB 01H
MVI E,01H ; Load value for NF Error
DB 01H
MVI E,0AH ; Load value for DD Error
DB 01H
MVI E,14H ; Load value for RW Error
DB 01H
MVI E,06H ; Load value for OV Error
DB 01H
MVI E,16H ; Load value for MO Error
DB 01H
MVI E,0DH ; Load value for TM Error
; ======================================================
; Generate error in E
; ======================================================
L045DH: XRA A
STA FCA7H
LHLD F67EH
MOV A,H
ORA L
JZ L0473H
LDA FBE6H
MOV M,A
LXI H,0000H
SHLD F67EH
L0473H: EI
LHLD VLJERR ; Load ON ERROR handler address (may be zero)
PUSH H ; Push ON ERROR handler address to stack
MOV A,H ; Get MSB of handler address
ORA L ; OR with LSB of handler address
RNZ ; RETurn to handler if not zero
LHLD VBSCLN ; Current executing line number
SHLD FB9FH ; Line number of last error
MOV A,H ; Move LSB of address of line number to A
ANA L ; AND with MSB of address
INR A ; Increment it test for FFFFH
JZ L048AH ; Skip saving as most recent line # if FFFFH
SHLD FBA1H ; Most recent used or entered line number
L048AH: LXI B,L0493H ; Load address of ERROR print routine in BC
; ======================================================
; Restore stack & runtime and jump to BC
; ======================================================
L048DH: LHLD FB9DH ; SP used by BASIC to reinitialize the stack
JMP L3F78H ; Jump into BASIC initialize routine
; ======================================================
; Generate Error in E Print routine
; ======================================================
L0493H: POP B
MOV A,E
MOV C,E
STA F672H ; Last Error code
LHLD VPCURL ; Most recent or currently running line pointer
SHLD FBA3H ; Pointer to occurrence of error
XCHG
LHLD FB9FH ; Line number of last error
MOV A,H
ANA L
INR A
JZ L04B6H
SHLD FBAAH ; Line where break, END, or STOP occurred
XCHG
SHLD FBACH ; Address where program stopped on last break, END, or STOP
LHLD FBA5H ; Address of ON ERROR routine
MOV A,H
ORA L
XCHG
L04B6H: LXI H,VBASRF ; BASIC Program Running Flag
JZ L04C5H ; Print BASIC error message - XX error in XXX
ANA M
JNZ L04C5H ; Print BASIC error message - XX error in XXX
DCR M
XCHG
JMP L082BH
; ======================================================
; Print BASIC error message - XX error in XXX
; ======================================================
L04C5H: XRA A
MOV M,A
MOV E,C
CALL L4BB8H ; Move LCD to blank line (send CRLF if needed)
MOV A,E
CPI 3BH
JNC L04DBH
CPI 32H
JNC L04DDH
CPI 17H
JC L04E0H
L04DBH: MVI A,30H
L04DDH: SUI 1BH
MOV E,A
L04E0H: MVI D,00H
LXI H,L031AH ; BASIC error message text
DAD D
DAD D
MVI A,3FH
RST 4 ; Send character in A to screen/printer
MOV A,M
RST 4 ; Send character in A to screen/printer
RST 2 ; Get next non-white char from M
RST 4 ; Send character in A to screen/printer
LXI H,L03EAH ; BASIC message strings
PUSH H
LHLD FB9FH ; Line number of last error
XTHL
L04F6H: CALL L27B1H ; Print buffer at M until NULL or '"'
POP H
MOV A,H
ANA L
INR A
CNZ L39CCH ; Finish printing BASIC ERROR message " in " line #
L0500H:
DB 3EH ; Makes "POP B" below look like "MVI A,C1H"
; ======================================================
; Pop stack and vector to BASIC ready
; ======================================================
L0501H: POP B ; Cleanup stack
; ======================================================
; Vector to BASIC ready - print Ok
; ======================================================
L0502H: CALL ROTLCD ; Reinitialize output back to LCD
CALL L4F45H
CALL L4BB8H ; Move LCD to blank line (send CRLF if needed)
LXI H,L03F6H ; Load pointer to "Ok" text
CALL L27B1H ; Print buffer at M until NULL or '"'
; ======================================================
; Silent vector to BASIC ready
; ======================================================
L0511H: LXI H,FFFFH ; Prepare to clear the BASIC executing line number
SHLD VBSCLN ; Current executing line number
LXI H,F66DH
SHLD VPCURL ; Most recent or currently running line pointer
CALL INLIN ; Input and display (no "?") line and store
JC L0511H ; Silent vector to BASIC ready
; ======================================================
; Perform operation at M and return to ready
; ======================================================
RST 2 ; Get next non-white char from M
INR A ; Increment A to test if NULL
DCR A ; Decrement A to test if NULL (why not just "ANA A"?)
JZ L0511H ; If at end of string, Silent vector to BASIC ready
PUSH PSW ; Save A & flags
CALL L08EBH ; Check for line number - Convert ASCII number at M to binary
JNC L0536H ; If last character received wasn't ASCII Digit, skip ahead
CALL L421AH ; Test if address FC8CH is Zero. WHY???
JZ ERRSYN ; Generate Syntax error - Line Integer too big
L0536H: DCX H ; Rewind BASIC command pointer 1 byte
MOV A,M ; Get next byte from BASIC command
CPI 20H ; Test for SPACE
JZ L0536H ; Jump back to test previous byte
CPI 09H ; Test for TAB
JZ L0536H ; Jump back to test previous byte
INX H ; Point to next byte from BASIC command line
MOV A,M ; Get next byte from BASIC command line
CPI 20H ; Test for SPACE
CZ L3457H ; If SPACE, increment HL and return. Never keep 1st SPACE
PUSH D
CALL L0646H ; Perform Token compression
POP D
POP PSW
SHLD VPCURL ; Most recent or currently running line pointer
JNC L4F1CH
PUSH D
PUSH B
XRA A
STA FB97H
RST 2 ; Get next non-white char from M
ORA A
PUSH PSW
XCHG
SHLD FBA1H ; Most recent used or entered line number
XCHG
CALL L0628H ; Find line number in DE
JC L056FH
POP PSW
PUSH PSW
JZ L094DH ; Generate UL error
ORA A
L056FH: PUSH B
JNC L0591H
CALL L126CH
MOV A,C
SUB E
MOV C,A
MOV A,B
SBB D
MOV B,A
LHLD VPSDOF ; Start of DO files pointer
DAD B
SHLD VPSDOF ; Start of DO files pointer
LHLD VPSCOF ; Start of CO files pointer
DAD B
SHLD VPSCOF ; Start of CO files pointer
LHLD VPRINP
DAD B
SHLD VPRINP
L0591H: POP D
POP PSW
PUSH D
JZ L05DAH
POP D
LXI H,0000H
SHLD FBA5H ; Address of ON ERROR routine
LHLD VPSVAR ; Start of variable data pointer
XTHL
POP B
PUSH H
DAD B
PUSH H
CALL L3EF0H ; Copy bytes from BC to HL with decriment until BC=DE
POP H
SHLD VPSVAR ; Start of variable data pointer
XCHG
MOV M,H
POP B
POP D
PUSH H
INX H
INX H
MOV M,E
INX H
MOV M,D
INX H
LXI D,F681H ; Address of temp storage for tokenized line
PUSH H
LHLD VPSDOF ; Start of DO files pointer
DAD B
SHLD VPSDOF ; Start of DO files pointer
LHLD VPSCOF ; Start of CO files pointer
DAD B
SHLD VPSCOF ; Start of CO files pointer
LHLD VPRINP
DAD B
SHLD VPRINP
POP H
L05D2H: LDAX D
MOV M,A
INX H
INX D
ORA A
JNZ L05D2H
L05DAH: POP D
CALL L05F4H ; Update line addresses for BASIC program at (DE)
LHLD FC8CH
SHLD FBA8H
CALL L3F28H ; Initialize BASIC Variables for new execution
LHLD FBA8H
SHLD FC8CH
JMP L0511H ; Silent vector to BASIC ready
; ======================================================
; Update line addresses for current BASIC program
; ======================================================
L05F0H: LHLD VBASPP ; Get Start of BASIC program pointer
XCHG ; Put start of program in DE
; ======================================================
; Update line addresses for BASIC program at (DE)
; ======================================================
L05F4H: MOV H,D ; Put address of current line in HL
MOV L,E
MOV A,M ; Get pointer to next line LSB
INX H ; Increment to MSB
ORA M ; OR MSB of pointer to test for NULL
RZ ; Return if at end of program
INX H ; Increment to Line Number LSB
INX H ; Increment to Line Number MSB
INX H ; Increment to first byte of BASIC line
XRA A ; Clear A to test for end of line
L05FEH: CMP M ; Test for end of BASIC line
INX H ; Increment to next byte of BASIC line
JNZ L05FEH ; Jump to test next byte of BASIC if not NULL
L0603H: XCHG ; DE=Address of next line, HL=start of current line
MOV M,E ; Save LSB of next line in current line pointer
INX H ; Increment to MSB
MOV M,D ; Save MSB of next line in current line pointer
JMP L05F4H ; Jump to update address of next line
; ======================================================
; Evaluate LIST statement arguments
; ======================================================
L060AH: LXI D,0000H
PUSH D
JZ L061BH
POP D
CALL L08E0H ; Evaluate line number text at M
PUSH D
JZ L0624H
RST 1 ; Compare next byte with M
DB D1H ; Test for '-'
L061BH: LXI D,FFFAH
CNZ L08E0H ; Evaluate line number text at M
JNZ ERRSYN ; Generate Syntax error
L0624H: XCHG
POP D
L0626H: XTHL ; Preserve HL on stack
PUSH H ; PUSH return address back to stack
; ======================================================
; Find line number in DE
; ======================================================
L0628H: LHLD VBASPP ; Start of BASIC program pointer
; ======================================================
; Find line number in DE starting at HL
; ======================================================
L062BH: MOV B,H ; Save HL in BC
MOV C,L ; Save LSB too
MOV A,M ; Get LSB of pointer to next BASIC line
INX H ; Increment to MSB
ORA M ; OR in MSB with LSB to test for 0000H
DCX H ; Decrement back to LSB
RZ ; Return if at end of BASIC program
INX H ; Increment to MSB of pointer to next BASIC program
INX H ; Increment to LSB of line number
MOV A,M ; Get LSB of line number
INX H ; Increment to MSB of line number
MOV H,M ; Get MSB of line number
MOV L,A ; Move LSB of line number to HL for comparison
RST 3 ; Compare DE and HL
MOV H,B ; Restore pointer to beginning of this BASIC line
MOV L,C ; Restore LSB of pointer too
MOV A,M ; Get LSB of next BASIC line number
INX H ; Increment to MSB
MOV H,M ; Get MSB of next BASIC line number
MOV L,A ; Move LSB to HL
CMC ; Compliment C to indicate line found
RZ ; Return if HL = DE. BC will have pointer to line
CMC ; Indicate line not found
RNC ; Return if beyond line number being sought
JMP L062BH ; Find line number in DE starting at HL
; ======================================================
; Perform Token compression
; ======================================================
L0646H: XRA A ; Prepare to zero out control vars
STA FB66H ; Zero out DATA statement found marker
MOV C,A ; Zero out line length
LXI D,F681H ; Pointer to temp storage space for tokenized line
L064EH: MOV A,M ; Get next byte from input string
CPI 20H ; Compare with SPACE
JZ L06EAH ; Save token in A to (DE)
MOV B,A ; Save character to B
CPI 22H ; Compare with QUOTE
JZ L070FH ; Jump if QUOTE to copy bytes until QUOTE or EOL
ORA A ; Test for end of input string
JZ L0716H ; Exit tokenize loop if end of string
INX H ; Increment to next byte in input string
ORA A ; Test for non-ASCII characters
JM L064EH ; Skip byte if non-ASCII (CODE or GRAPH character)
DCX H ; Decrement back to original byte in input string
LDA FB66H ; Load marker if DATA statement active
ORA A ; Test if DATA statement active
MOV A,M ; Get next byte from input string
JNZ L06EAH ; Copy byte to output if DATA statement active
CPI 3FH ; Compare with '?'
MVI A,A3H ; Load token for PRINT (convert '?' to PRINT)
JZ L06EAH ; Save token in A to (DE)
MOV A,M ; Get next byte from input string
CPI 30H ; Compare with '0'
JC L067EH ; Skip ahead if not '0-9'
CPI 3CH ; Compare with '<'
JC L06EAH ; Jump to add digit to output if '0-9'
L067EH: PUSH D ; Save output pointer on stack
LXI D,L007FH ; Point to TOKEN table (-1)
PUSH B ; Save line length count on stack
LXI B,L06CDH ; Load address of routine to ???
PUSH B ; Push address to stack
MVI B,7FH ; Initialize token number counter
MOV A,M ; Get next byte from input string
CPI 61H ; Compare with 'a'
JC L0697H ; Skip uppercase if not 'a-z'
CPI 7BH ; Compare with '{' ('z' + 1)
JNC L0697H ; Skip uppercase if not 'a-z'
ANI 5FH ; Make uppercase
MOV M,A ; Save as uppercase
L0697H: MOV C,M ; Get next byte (uppercase) from input string in C
XCHG ; HL now has pointer to Token table
L0699H: INX H ; Increment to next byte in token table
ORA M ; Test if this is the 1st byte of a token
JP L0699H ; Jump back to increment to next byte if not the 1st byte of token
INR B ; Increment the token # counter
MOV A,M ; Get the next byte from the token table
ANI 7FH ; Mask off the 1st byte marker
RZ ; Return to our tokenizer return hook if token not found
CMP C ; Test if input string byte matches next byte from token table
JNZ L0699H ; Skip to next token in table if it doesn't match
XCHG ; 1st Char of token found. Move token table ptr to DE and CMP the rest
PUSH H ; Save pointer to input string in case no match with this token
L06A9H: INX D ; Increment to next byte in token table
LDAX D ; Load the next byte from token table
ORA A ; Test for token 1st byte marker
JM L06C9H ; Jump if 1st byte of next token found = match!
MOV C,A ; Save next byte from token table in C
MOV A,B ; Load the token counter
CPI 88H ; Test for GOTO token??
JNZ L06B8H ; Skip ahead if GOTO?
RST 2 ; Get next non-white char from M
DCX H ; Pre-decrement pointer to next byte from input string
L06B8H: INX H ; Increment to next byte from input string
MOV A,M ; Get next byte from input string
CPI 61H ; Test if byte >= 'a'
JC L06C1H ; Skip uppercase if not >= 'a'
ANI 5FH ; Make uppercase
L06C1H: CMP C ; Compare byte from input string with next byte from token table
JZ L06A9H ; If it matches, jump back to test next byte for this token
POP H ; Restore pointer to input string to test next token
JMP L0697H ; Jump to test input against next token in table
L06C9H: MOV C,B ; Save token number in C
POP PSW ; POP saved pointer to input line
XCHG ; Pre-XCHG DE and HL
RET ; This returns to our Tokenizer return hook
L06CDH: XCHG ; Exchange DE & HL so HL = input string, DE = token table pointer
MOV A,C ; Move TOKEN or next byte from input to A
POP B ; Restore line length from stack
POP D ; Restore output pointer from stack
XCHG ; HL=output pointer, DE = input string
CPI 91H ; Test for ELSE token
MVI M,3AH ; Insert a ":" before ELSE token
JNZ L06DBH ; Skip insertion if not ELSE token
INR C ; It was ELSE token. Increment line length
INX H ; And increment output pointer to keep the ':'
L06DBH: CPI FFH ; Test for "'" token (Alternate REM)
JNZ L06E9H ; Skip ahead to add token to output if not "'" token
MVI M,3AH ; Insert a ':REM' before the "'"
INX H ; Increment to next output byte
MVI B,8EH ; Load value for REM token
MOV M,B ; Save REM token to output
INX H ; Increment to next output byte
INR C ; Increment line length to account for added ':'
INR C ; Increment line length to account for added REM token
L06E9H: XCHG ; HL=input line, DE = output pointer
L06EAH: INX H ; Increment to next input byte
STAX D ; Store this token to output (DE)
INX D ; Increment output pointer
INR C ; Increment line length counter
SUI 3AH ; Test for ':' token
JZ L06F8H ; Jump ahead if ':'
CPI 49H ; Test for DATA statement (I think?)
JNZ L06FBH ; Skip if not DATA statement
L06F8H: STA FB66H ; Indicate DATA statement found
L06FBH: SUI 54H ; Test for REM statement
JZ L0705H ; Jump ahead to save termination marker as NULL if REM
SUI 71H ; Test for FFh token
JNZ L064EH ; Jump if not FFh token
L0705H: MOV B,A ; Save termination marker as NULL (end of string)
L0706H: MOV A,M ; Get next byte from input string
ORA A ; Test for NULL termination
JZ L0716H ; Jump out of loop if end of string
CMP B ; Compare with termination character (QUOTE or NULL)
JZ L06EAH ; Jump to Save token if termination char found (QUOTE or NULL)
L070FH: INX H ; Increment to next input byte
STAX D ; Save this character to (DE) output
INR C ; Increment line length count
INX D ; Increment output pointer
JMP L0706H ; Jump to test next byte for termination marker (QUOTE or NULL)
L0716H: LXI H,L0005H ; Prepare to add 5 to line length for Address, Line # & termination
MOV B,H ; Zero MSB of BC
DAD B ; Add 5 to line length
MOV B,H ; Save MSB of line length in B
MOV C,L ; Save LSB of line length in C
LXI H,F680H ; End of statement marker
STAX D ; Store Zero to output - End of line marker
INX D ; Increment output pointer
STAX D ; Store 2nd zero to output - NULL next BASIC line address LSB
INX D ; Increment output pointer
STAX D ; Store 3rd zero to output - NULL next BASIC line address MSB
RET
; ======================================================
; FOR statement
; ======================================================
BSFOR: MVI A,64H
STA FB96H ; FOR/NEXT loop active flag
CALL BSLET ; LET statement
POP B ; Pop BASIC Loop "RET"urn address from stack
PUSH H ; Save pointer to FOR arguments on stack
CALL BSDATA ; DATA statement
SHLD FB92H ; Save address of first statement in FOR loop
LXI H,L0002H
DAD SP ; Get SP prior to our PUSH H above
L073AH: CALL L0405H
JNZ L0758H
DAD B
PUSH D
DCX H
MOV D,M
DCX H
MOV E,M
INX H
INX H
PUSH H
LHLD FB92H ; Get address of 1st statement in FOR loop
RST 3 ; Compare DE and HL
POP H
POP D
JNZ L073AH
POP D
SPHL
SHLD FB9DH ; SP used by BASIC to reinitialize the stack
MVI C,D1H ; Make POP D (D1H) below look like MVI C,D1H
XCHG
MVI C,0CH
CALL L3EFFH ; Test for 24 byte free in stack space
PUSH H
LHLD FB92H ; Get address of 1st statement in FOR loop
XTHL
PUSH H