forked from source-solutions/sebasic4
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path09_command.asm
More file actions
2183 lines (1942 loc) · 64.4 KB
/
Copy path09_command.asm
File metadata and controls
2183 lines (1942 loc) · 64.4 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
; // SE Basic IV 4.2 Cordelia
; // Copyright (c) 1999-2024 Source Solutions, Inc.
; // SE Basic IV is free software: you can redistribute it and/or modify
; // it under the terms of the GNU General Public License as published by
; // the Free Software Foundation, either version 3 of the License, or
; // (at your option) any later version.
; //
; // SE Basic IV is distributed in the hope that it will be useful,
; // but WITHOUT ANY WARRANTY; without even the implied warranty o;
; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; // GNU General Public License for more details.
; //
; // You should have received a copy of the GNU General Public License
; // along with SE Basic IV. If not, see <http://www.gnu.org/licenses/>.
;;
; // --- BASIC LINE AND COMMAND INTERPRETATINO -------------------------------
;;
:
org $1a7d
;;
; BASIC main parser
;;
line_scan:
res 7, (iy + _flags); // signal checking syntax
call e_line_no; // point to first code after a line number
xor a; // LD A, 0
ld (subppc), a; // zero subppc
dec a; // LD A, 0xFF
ld (err_nr), a; // set err_nr to OK
jr stmt_l_1; // immediate jump
;;
; statement loop
;;
stmt_loop:
rst next_char; // next character
stmt_l_1:
call test_trace; // handle trace and clear workspace
inc (iy + _subppc); // increase subppc each time around
jp m, report_syntax_err; // error if more than 127 statements
stmt_l_1a:
rst get_char; // get current character
ld b, 0; // clear B
cp ctrl_cr; // carriage return?
jp z, line_end; // jump if so
cp ':'; // colon?
jr z, stmt_loop; // loop if so
ld hl, stmt_ret; // stack new
push hl; // return address
ld c, a; // store command in C
rst next_char; // advance character address
ld a, c; // restore command to A
sub first_cmd; // reduce range
jr nc, stmt_l_2; // jump with valid commands
ld hl, (ch_add); // get character address
dec hl; // previous character
ld (ch_add), hl; // set character address
ld a, (hl); // get first character again
cp "'"; // is it a single quote?
ld a, tk_rem - first_cmd; // make the token REM
jr z, stmt_l_2; // and jump if so
ld a, tk_let - first_cmd; // else make the token LET
stmt_l_2:
rlca; // double the command
ld l, a; // store in L
ld bc, offst_tbl; // start of table
ld h, 0; // ready to index
add hl, bc; // hl points to table entry
ld c, (hl); // low byte to C
inc hl; // next byte
ld h, (hl); // high byte to H;
ld l, c; // low byte to L
jr get_param; // immediate jump
;;
; scan loop
;;
scan_loop:
ld hl, (t_addr); // temporary pointer to parameter table
get_param:
ld a, (hl); // get each entry
inc hl; // increase pointer
ld (t_addr), hl; // store it in sysvar
ld hl, scan_loop; // stack new
push hl; // return address
ld c, a; // entry to C
cp ' '; // separator?
jr nc, separator; // jump if so
ld hl, class_tbl; // address table
ld b, 0; // clear B
add hl, bc; // index into table
ld c, (hl); // offset to C
add hl, bc; // base address to HL
push hl; // use as new return address
rst get_char; // get current character
dec b; // LD B, 255
ret; // indirect jump
;;
; separator
;;
separator:
rst get_char; // get current character
cp c; // compare with entry
jp nz, report_syntax_err; // error if no match
rst next_char; // next character
ret; // end of subroutine
;;
; statement return
;;
stmt_ret:
call esc_key; // break?
jr c, stmt_r_1; // jump if not
call msg_loop;
jp report_break; // clear keyboard buffer and report break
stmt_r_1:
bit 7, (iy + _nsppc); // statement jump required?
jp nz, stmt_next; // jump if not
ld hl, (newppc); // get new line number
bit 7, h; // statement in editing area?
jr z, line_new; // jump if not
;;
; run line entry point
;;
line_run:
ld hl, -2; // line in editing area
ld (ppc), hl; // store in sysvar
ld hl, (worksp); // sysvar to HL
dec hl; // HL points to end of editing area
ld de, (e_line); // sysvar to DE
dec de; // DE points to location before editing area
ld a, (nsppc); // number of next statement to A
jr next_line; // immediate jump
;;
; new line
;;
line_new:
call line_addr; // get starting address
ld a, (nsppc); // statement number to A
jr z, line_use; // jump if line found
and a; // valid statement number?
jr nz, report_stmt_msng; // error if not
ld a, %11000000; // is first line after
and (hl); // end of program?
jr z, line_use; // jump if not
;;
; <code>END</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#END" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_end:
call close_all; // close all files
ld bc, -2; // line zero
ld (ppc), bc; // set line number
ld l, ok; // error to A
jp error_3; // generate error message
;;
; <code>ELSE</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#ELSE" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_else:
pop bc; // discard statement return address
call syntax_z; // checking syntax?
jp z, stmt_l_1a; // check the statement after ELSE
push bc; // put it temporarily back
;;
; <code>REM</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#REM" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_rem:
pop af; // discard statement return address
;;
; line end
;;
line_end:
call unstack_z; // return if checking syntax
ld hl, (nxtlin); // get address
ld a, %11000000; // address after
and (hl); // end of program?
ret nz; // return if so
xor a; // signal statement zero
;;
; line use
;;
line_use:
cp 1; // signal
adc a, 0; // statement one
ld d, (hl); // line
inc hl; // number
ld e, (hl); // to DE
inc hl; // point to length
ld (ppc), de; // store line number
ld e, (hl); // length
inc hl; // to
ld d, (hl); // DE
ex de, hl; // location before next line's
add hl, de; // first character to DE
inc hl; // start of line after to HL
;;
; next line
;;
next_line:
ld (nxtlin), hl; // set next line
ex de, hl; // swap pointers
ld (ch_add), hl; // CH-ADD to location before first character
ld e, 0; // clear in case of each_stmt
ld d, a; // statement number to D
ld (iy + _nsppc), 255; // signal no jump
dec d; // reduce statement number
ld (iy + _subppc), d; // store in subppc
jp z, stmt_loop; // consider first statement
inc d; // increment D
call each_stmt; // find start address
jr z, stmt_next; // jump if statement exists
report_stmt_msng:
rst error; // else
defb statement_missing; // error
;;
; check end
;;
check_end:
call syntax_z; // checking syntax?
ret nz; // return if not
pop bc; // discard scan_loop and
pop bc; // stmt_ret return addresses
;;
; statement next
;;
stmt_next:
rst get_char; // get current character
cp ctrl_cr; // carriage return
jr z, line_end; // jump if so
cp ':'; // colon?
jp z, stmt_loop; // jump if so
rst error; // else
defb syntax_error; // error
; // command class table
class_tbl:
defb class_00 - $; // no operands
defb class_01 - $; // a variable must follow
defb class_02 - $; // LET
defb class_03 - $; // a number may follow
defb class_04 - $; // FOR or NEXT
defb class_05 - $; // a set of items may follow
defb class_06 - $; // a number must follow
defb class_07 - $; // class_06 with no furhter operands
defb class_08 - $; // two comma-separated numbers must follow
defb class_09 - $; // class_08 with no furhter operands
defb class_0a - $; // an expression must follow
defb class_0b - $; // class_0a with no furhter operands
; // command classes 0, 1, 3, 5, 7, 9, B
;;
; command class 07
;;
class_07:
call class_06; // a number must follow
jr class_00; // no futher operands
;;
; command class 09
;;
class_09:
call class_08; // two comma-separated numbers must follow
jr class_00; // no futher operands
;;
; command class 0B
;;
class_0b:
call class_0a; // an expression must follow
jr class_00; // no futher operands
;;
; command class 03
;;
class_03:
call fetch_num; // get number, default to zero
;;
; command class 00
;;
class_00:
cp a; // set zero flag
;;
; command class 05
;;
class_05:
pop bc; // discard scan-loop return address
call z, check_end; // next statement if checking syntax
ex de, hl; // swap pointers
ld hl, (t_addr); // pointer to parameter table entry
ld c, (hl); // get
inc hl; // entry
ld b, (hl); // in BC
ex de, hl; // swap pointers
push bc; // stack entry
ret; // end of subroutine
;;
; command class 01
;;
class_01:
call look_vars1; // variable exists?
;;
; variable in assignment
;;
var_a_1:
ld (iy + _flagx), 0; // clear flagx
jr nc, var_a_2; // jump if variable exists
set 1, (iy + _flagx); // signal new variable
jr nz, var_a_3; // jump unless undimensioned array
report_undef_var:
rst error; // else
defb undefined_variable; // error
var_a_2:
call z, stk_var; // parameters and variables to calculator
bit 6, (iy + _flags); // numeric or string variable?
jr nz, var_a_3; // jump if numeric
xor a; // LD A, 0
call syntax_z; // checking syntax?
call nz, stk_fetch; // get paramaters of string if not
ld hl, flagx; // address system variable
or (hl); // set bit 0 for simple strings
ld (hl), a; // update flagx
ex de, hl; // HL points to string or element
var_a_3:
ld (strlen), bc; // HL points to string or element
ld (dest), hl; // and destination
ret; // end of subroutine
;;
; command class 02
;;
class_02:
pop bc; // discard scan_loop return address
call val_fet_1; // make assignment
call check_end; // next statement if checking syntax
ret; // indirect jump to stmt-ret in runtime
;;
; fetch a value
;;
val_fet_1:
ld a, (flags); // address system variable
val_fet_2:
push af; // stack system variable
call scanning; // evaluate expression
pop af; // unstack system variable
ld d, (iy + _flags); // get new flags
xor d; // test for
and %01000000; // numeric or string
jr nz, report_syntax_err; // error if no match
bit 7, d; // checking syntax?
jp nz, c_let; // jump if not
ret; // else return
;;
; command class 04
;;
class_04:
call look_vars; // find variable
push af; // stack AF
ld a, %10011111; // test
or c; // discriminator byte
inc a; // for FOR-NEXT
jr nz, report_syntax_err; // error if not
pop af; // unstack AF
jr var_a_1; // immediate jump
;;
; expect numeric / string expression
;;
next_2num:
rst next_char; // advance ch_add
;;
; command class 08
;;
class_08:
;;
; expect two numbers
;;
expt_2num:
call expt_1num; // get expression
expt_comma_1num:
cp ','; // comma?
jr nz, report_syntax_err; // error if not
expt_num:
rst next_char; // advance ch_add
;;
; command class 06
;;
class_06:
;;
; expect one number
;;
expt_1num:
call scanning; // evaluate expression
bit 6, (iy + _flags); // numeric or string variable?
ret nz; // return if numeric
report_syntax_err:
rst error; // else
defb syntax_error; // error
; org $1c8c
;;
; command class 0A
;;
class_0a:
;;
; expect string expression
; @see: UnoDOS 3 entry points
;;
expt_exp:
call scanning; // evaluate expression
bit 6, (iy + _flags); // numeric or string variable?
ret z; // return if string
jr report_syntax_err; // else error
;;
; fetch a number
;;
fetch_num:
cp ctrl_cr; // carriage return?
jr z, use_zero; // jump if so
cp ':'; // colon?
jr nz, expt_1num; // jump if not
;;
; use zero
;;
use_zero:
call unstack_z; // return if checking syntax
fwait; // enter calculator
fstk0; // stack zero
fce; // exit calculator
ret; // end of subroutine
;;
; <code>IF</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#IF" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_if:
pop bc; // discard stmt-ret return address
call syntax_z; // checking syntax
jr z, if_1; // jump if so
fwait; // enter calculator
fdel; // remove last item
fce; // exit calculator
ex de, hl; // swap pointers
call test_zero; // zero?
jr nc, if_1; // jump if not
rst get_char; // get character
ld b, 1; //
if_2:
call get_next; //
cp ctrl_cr; // carraige return? (end of line)
jp z, line_end; // jump if so
cp tk_else; // ELSE token
jr z, if_3; // jump if so
cp tk_if; // IF token
jr nz, if_2; // jump if not
inc b; //
jr if_2; // immedaite jump
if_3:
djnz if_2; // loop until done
ld (ch_add), hl; // set character address
if_1:
jp stmt_l_1; // next statement
;;
; <code>FOR</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#FOR" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_for:
cp tk_step; // STEP token?
jr nz, f_use_1; // jump if not
rst next_char; // advance CH-ADD
call expt_1num; // get step
call check_end; // next statement if checking syntax
jr f_reorder; // immediate jump
f_use_1:
call check_end; // next statement if checking syntax
fwait; // enter calculator
fstk1; // stack one
fce; // exit calculator
f_reorder:
fwait; // enter calculator
fst 0; // store step in mem-0
fdel; // remove last item
fxch; // l, v
fgt 0; // l, v, s
fxch; // l, s, v
fce; // exit calculator
call c_let; // find or create variable
ld (mem), hl; // contents of mem to HL
dec hl; // point to single character name
ld a, (hl); // store it in A
set 7, (hl); // set bit 7
ld bc, 6; // make six locations
add hl, bc; // point to following location
rlca; // for variable
jr c, f_l_s; // jump if so
ld c, 13; // else 13 more bytes required
call make_room; // make space
inc hl; // point to limit position
f_l_s:
push hl; // stack pointer
fwait; // l, x
fdel; // l
fdel; // empty calculator stack
fce; // exit calculator
pop hl; // unstack pointer
ex de, hl; // swap pointers
ld c, 10; // ten bytes of limit
ldir; // copy bytes
ld hl, (ppc); // current line number to HL
ex de, hl; // swap pointers
ld (hl), e; // line number
inc hl; // to for control
ld (hl), d; // variables
ld d, (iy + _subppc); // next statement to D
inc hl; // increase variable pointer
inc d; // increase statement
ld (hl), d; // store control variable
call next_loop; // pass possible?
ret nc; // return if so
ld a, (subppc); // statement to A
neg; // negate statement
ld b, (iy + _strlen); // character name to B
ld hl, (ppc); // current line number
ld (newppc), hl; // to newppc using HL
ld hl, (ch_add); // current value of sysvar
ld e, tk_next; // next token
ld d, a; // statement to D
f_loop:
push bc; // stack variable name
ld bc, (nxtlin); // current value of nxtlin
call look_prog; // search program area
ld (nxtlin), bc; // store new value of nxtlin
pop bc; // unstack variable name
jr c, report_for_wo_next; // error with missing next
rst next_char; // skip next token
or %00100000; // ignore letter case
cp b; // variable found?
jr z, f_found; // jump if so
rst next_char; // advance ch_add
jr f_loop; // loop until done
f_found:
rst next_char; // advance ch_add
xor a; // subtract statement
inc a; // LD A, 1
sub d; // counter from one
ld (nsppc), a; // store result
ret; // indirect jump to stmt_ret
report_for_wo_next:
rst error; // throw
defb for_without_next; // error
;;
; look program
;;
look_prog:
ld a, (hl); // current character
cp ':'; // colon?
jr z, look_p_2; // jump if so
look_p_1:
inc hl; // most significant byte of line number
ld a, %11000000; // end of
and (hl); // program?
scf; // set carry flag
ret nz; // return if no more lines
ld b, (hl); // line
inc hl; // number
ld c, (hl); // to BC
ld (newppc), bc; // store in newppc
inc hl; // get
ld c, (hl); // length
inc hl; // in
ld b, (hl); // BC
push hl; // stack pointer
add hl, bc; // calculate end of line address
ld c, l; // result
ld b, h; // to BC
pop hl; // unstack pointer
ld d, 0; // zero statement counter
look_p_2:
push bc; // stack end of line pointer
call each_stmt; // examine statements
pop bc; // unstack end of line pointer
ret nc; // return with occurence
jr look_p_1; // immediate jump
;;
; <code>NEXT</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#NEXT" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_next:
bit 1, (iy + _flagx); // variable found
jp nz, report_undef_var; // jump if not
ld hl, (dest); // address to HL
bit 7, (hl); // valid name?
jr z, report_next_wo_for; // jump if not
inc hl; // skip name
ld (mem), hl; // variable address to temporary memory area
fwait; // enter calculator
fgt 0; // v
fgt 2; // v, s
fadd; // v + s
fst 0; // v + s to mem_0
fdel; // remove last item
fce; // exit calculator
call next_loop; // test value against limit
ret c; // return if for-next loop done
ld hl, (mem); // address least significant byte
ld de, 15; // of looping
add hl, de; // line number
ld e, (hl); // line
inc hl; // number
ld d, (hl); // to DE
inc hl; // statement
ld h, (hl); // number to H
ex de, hl; // swap pointers
jp goto_2; // immediate jump
report_next_wo_for:
rst error; // throw
defb next_without_for; // error
;;
; next loop
;;
next_loop:
fwait; // enter calculator
fgt 1; // l
fgt 0; // l, v
fgt 2; // l, v, s
fcp lz; // less than zero?
fjpt next_1; // jump if so
fxch; // v, l
next_1:
fsub; // v - l or l - v
fcp gz; // greater than zero?
fjpt next_2; // jump if so
fce; // exit calculator
and a; // clear carry flag
ret; // end of subroutine
next_2:
fce; // exit calculator
scf; // set carry flag
ret; // end of subroutine
; // READ command
read_3:
rst next_char; // next character
;;
; <code>READ</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#READ" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_read:
call class_01; // get entry for existing variable
call syntax_z; // checking syntax?
jr z, read_2; // jump if so
rst get_char; // get current character
ld (x_ptr), hl; // ch_add to x_ptr
ld hl, (datadd); // data address pointer to HL
ld a, (hl); // first value to A
cp $2c; // comma?
jr z, read_1; // jump if not
ld e, tk_data; // data token?
call look_prog; // search for token
jr nc, read_1; // jump if found
rst error; // else
defb out_of_data; // error
read_1:
call temp_ptr1; // advance DATA pointer and set ch_add
call val_fet_1; // get value and assign to variable
rst get_char; // get ch_add
ld (datadd), hl; // store it in sysvar
ld hl, (x_ptr); // pointer to read statement to HL
ld (iy + _x_ptr_h), 0; // clear x_ptr
call temp_ptr2; // point ch_add to read statement
read_2:
rst get_char; // get current character
cp $2c; // comma?
jr z, read_3; // jump if so
call check_end; // ext statement if checking syntax
ret; // end of routine
;;
; <code>DATA</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#DATA" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_data:
call syntax_z; // checking syntax?
jr nz, data_2; // jump if so
data_1:
call scanning; // next expression
cp ','; // comma?
call nz, check_end; // next statement if checking syntax
rst next_char; // advance ch_add
jr data_1; // loop until done
data_2:
ld a, tk_data; // data
;;
; pass by
;;
pass_by:
ld b, a; // token to B
cpdr; // back to find token
ld de, $0200; // find following statement (D - 1)
jp each_stmt; // immediate jump
;;
; <code>RESTORE</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#RESTORE" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_restore:
call find_line; // valid line number to HL and BC
rest_run:
ld l, c; // result
ld h, b; // to HL
call line_addr; // get address of line or next line
dec hl; // point to location before
ld (datadd), hl; // and store in dat_add
ret; // end of routine
;;
; <code>RANDOMIZE</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#RANDOMIZE" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_randomize:
call find_int2; // get operand
ld a, c; // is it
or b; // zero?
jr nz, rand_1; // jump if not
ld bc, (time_t); // get low 16-bits of time_t
rand_1:
ld (seed), bc; // result to seed
ret; // end of routine
;;
; <code>CONT</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#CONT" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_cont:
ld hl, (oldppc); // line number to HL
ld d, (iy + _osppc); // statement number to D
jr goto_2; // immediate jump
;;
; find line
;;
find_line:
call find_int2; // line number to BC
ld l, c; // resault
ld h, b; // to HL
ld a, b; // high byte to A
cp $40; // less than 16384?
ret c; // return if so
report_undef_ln_no:
rst error; // else
defb undefined_line_number; // error
;;
; <code>GOTO</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#GOTO" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_goto:
call find_line; // valid line number to HL and BC
ld d, 0; // zero statement
goto_2:
ld (newppc), hl; // store line number
ld (iy + _nsppc), d; // store statement number
ret; // end of routine
;;
; <code>OUT</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#OUT" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_out:
call two_param; // get operands
out (c), a; // perform out
ret; // end of routine
;;
; <code>POKE</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#POKE" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_poke:
call two_param; // get operands
ld (bc), a; // store A in address BC
ret; // end of routine
;;
; <code>DOKE</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#DOKE" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_doke:
call find_int2; // get first parameter in BC
push bc; // stack it
call find_int2; // get second parameter
ld l, c; // copy
ld h, b; // to HL
pop bc; // unstack first parameter
ld (hl), c; // write first parameter
inc hl; // to address in
ld (hl), b; // second parameter
ret; // done
;;
; two parameters
;;
two_param:
call fp_to_a; // first parameter
jr c, report_overflow; // error if out of range
jr z, two_p_1; // jump with positive number
neg; // else negate
two_p_1:
push af; // stack first parameter
call find_int2; // get second parameter in BC
pop af; // unstack first parameter
ret; // end of subroutine
;;
; find integer
;;
find_int1:
call fp_to_a; // value on calculator stack to A
jr find_i_1; // immediate jump
find_int2:
call fp_to_bc; // value on calculator stack to BC
find_i_1:
jr c, report_overflow; // error if overflow
ret z; // return with positive numbers
report_overflow:
rst error; // else
defb overflow; // error
;;
; <code>RUN</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#RUN" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_run:
rst get_char; // get character
cp ctrl_cr; // carriage return?
jr z, run_zero; // jump if so
cp ':'; // test for next statement
jr z, run_zero; // jump if so
call scanning; // evaluate expression
bit 6, (iy + _flags); // numeric or string variable?
call nz, unstack_z; // return now if checking syntax
jp z, run_app; // jump if string
; // RUN <line> command
l_run:
call c_goto; // set newppc
ld bc, 0; // restore value
call rest_run; // perform restore
jr clear_run; // immediate jump
run_zero:
call check_end; // return if checking syntax
call use_zero; // use line zero
jr l_run; // run
;;
; <code>CLEAR</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#CLEAR" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_clear:
call find_int2; // get operand
clear_run:
ld a, c; // test
or b; // for zero
jr nz, clear_1; // jump if not
ld bc, (ramtop); // else use existing ramtop
clear_1:
push bc; // stack value
; call mute_psg; // mute PSG [FIXME: For some reason this kills the Help app if enabled]
call close_all; // close all streams
xor a; // LD A, $ff
dec a; // sets
ld (onerr_h), a; // ON ERROR STOP
ld de, (vars); // start of variables to DE
call var_end_hl; // location before varaibles end marker location to HL
call reclaim_1; // reclaim all bytes of current variables area
call rest_run; // data restore
call c_cls; // clear display
ld de, 50; // add
ld hl, (stkend); // fifty
add hl, de; // to stasck end
pop de; // unstack value in DE
sbc hl, de; // subtract it from ramptop
jr nc, report_out_of_memory; // jump if ramtop too low
and a; // prepare for subtraction
ld hl, (p_ramt); // upper value to HL
sbc hl, de; // subtract from upper value
jr nc, clear_2; // jump if valid
report_out_of_memory:
rst error; // else
defb out_of_memory; // error
clear_2:
ex de, hl; // value to HL
ld (ramtop), hl; // store it
pop de; // stmt_ret address to DE
pop bc; // error address to BC
ld (hl), $3e; // gosub stack marker
dec hl; // skip one location
ld sp, hl; // SP to empty gosub stack
push bc; // stack error address
ld (err_sp), sp; // store in sysvar
ex de, hl; // stmt_ret address to HL
jp (hl); // immediate jump
;;
; <code>GOSUB</code> command
; @see <a href="https://github.com/source-solutions/sebasic4/wiki/Language-reference#GOSUB" target="_blank" rel="noopener noreferrer">Language reference</a>
;;
c_gosub:
pop de; // stmt_ret address to DE
ld h, (iy + _subppc); // get statement number
inc h; // increment it
ex (sp), hl; // swap with error address
inc sp; // reclaim one location
ld bc, (ppc); // get current line number
push bc; // stack it
push hl; // stack error address
ld (err_sp), sp; // point sysvar to it
push de; // stack stmt_ret address