OpenCores
URL https://opencores.org/ocsvn/rtf65002/rtf65002/trunk

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [TinyBasic65002.asm] - Blame information for rev 26

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 robfinch
;****************************************************************;
2
;                                                                ;
3
;               Tiny BASIC for the Raptor64                              ;
4
;                                                                ;
5
; Derived from a 68000 derivative of Palo Alto Tiny BASIC as     ;
6
; published in the May 1976 issue of Dr. Dobb's Journal.         ;
7
; Adapted to the 68000 by:                                       ;
8
;       Gordon brndly                                                                    ;
9
;       12147 - 51 Street                                                                ;
10
;       Edmonton AB  T5W 3G8                                                         ;
11
;       Canada                                                                               ;
12
;       (updated mailing address for 1996)                                       ;
13
;                                                                ;
14
; Adapted to the RTF65002 by:                                    ;
15
;    Robert Finch                                                ;
16
;    Ontario, Canada                                             ;
17
;        robfinch@opencores.org                              ;
18
;****************************************************************;
19
;    Copyright (C) 2012 by Robert Finch. This program may be     ;
20
;    freely distributed for personal use only. All commercial    ;
21
;                      rights are reserved.                                          ;
22
;****************************************************************;
23
;
24
; Register Usage
25
; r8 = text pointer (global usage)
26
; r3,r4 = inputs parameters to subroutines
27
; r2 = return value
28
;
29
;* Vers. 1.0  1984/7/17 - Original version by Gordon brndly
30
;*      1.1  1984/12/9  - Addition of '0x' print term by Marvin Lipford
31
;*      1.2  1985/4/9   - Bug fix in multiply routine by Rick Murray
32
 
33
;
34
; Standard jump table. You can change these addresses if you are
35
; customizing this interpreter for a different environment.
36
;
37
CR      EQU     0x0D            ;ASCII equates
38
LF      EQU     0x0A
39
TAB     EQU     0x09
40
CTRLC   EQU     0x03
41
CTRLH   EQU     0x08
42
CTRLI   EQU     0x09
43
CTRLJ   EQU     0x0A
44
CTRLK   EQU     0x0B
45
CTRLM   EQU 0x0D
46
CTRLS   EQU     0x13
47
CTRLX   EQU     0x18
48
XON             EQU     0x11
49
XOFF    EQU     0x13
50
 
51 18 robfinch
CursorRow       EQU             0x7C2
52
CursorCol       EQU             0x7C3
53
CursorFlash     EQU             0x7C4
54
IRQFlag         EQU             0x7C6
55 16 robfinch
 
56 18 robfinch
OSSP            EQU             0x700
57
TXTUNF          EQU             0x701
58
VARBGN          EQU             0x702
59
LOPVAR          EQU             0x703
60
STKGOS          EQU             0x704
61
CURRNT          EQU             0x705
62 26 robfinch
BUFFER          EQU             0x706
63 16 robfinch
BUFLEN          EQU             84
64 18 robfinch
LOPPT           EQU             0x760
65
LOPLN           EQU             0x761
66
LOPINC          EQU             0x762
67
LOPLMT          EQU             0x763
68
NUMWKA          EQU             0x764
69
STKINP          EQU             0x774
70
STKBOT          EQU             0x775
71
usrJmp          EQU             0x776
72
IRQROUT         EQU             0x777
73 16 robfinch
 
74
 
75
 
76
                cpu     rtf65002
77
                code
78
                org             $FFFFE800
79
GOSTART:
80
                jmp     CSTART  ;       Cold Start entry point
81
GOWARM:
82
                jmp     WSTART  ;       Warm Start entry point
83
GOOUT:
84
                jmp     OUTC    ;       Jump to character-out routine
85
GOIN:
86
                jmp     INCH    ;Jump to character-in routine
87
GOAUXO:
88
                jmp     AUXOUT  ;       Jump to auxiliary-out routine
89
GOAUXI:
90
                jmp     AUXIN   ;       Jump to auxiliary-in routine
91
GOBYE:
92
                jmp     BYEBYE  ;       Jump to monitor, DOS, etc.
93
;
94
; Modifiable system constants:
95
;
96
                align   4
97 26 robfinch
;THRD_AREA      dw      0x04000000      ; threading switch area 0x04000000-0x40FFFFF
98
;bitmap dw      0x04100000      ; bitmap graphics memory 0x04100000-0x417FFFF
99
TXTBGN  dw      0x04180000      ;TXT            ;beginning of program memory
100
ENDMEM  dw      0x057FFFFF      ;       end of available memory
101
STACKOFFS       dw      0x058FFFFF      ; stack offset - leave a little room for the BIOS stacks
102 16 robfinch
;
103
; The main interpreter starts here:
104
;
105
; Usage
106
; r1 = temp
107
; r8 = text buffer pointer
108
; r12 = end of text in text buffer
109
;
110
        align   4
111 26 robfinch
message "CSTART"
112 16 robfinch
public CSTART:
113
        ; First save off the link register and OS sp value
114
        tsx
115
        stx             OSSP
116
        ldx             STACKOFFS>>2    ; initialize stack pointer
117
        txs
118 26 robfinch
        jsr             RequestIOFocus
119
        jsr             HomeCursor
120
        lda             #0                              ; turn off keyboard echoing
121
        jsr             SetKeyboardEcho
122 16 robfinch
        stz             CursorFlash
123
        ldx             #0x10000020     ; black chars, yellow background
124
;       stx             charToPrint
125
        jsr             ClearScreen
126
        lda             #msgInit        ;       tell who we are
127
        jsr             PRMESG
128
        lda             TXTBGN>>2       ;       init. end-of-program pointer
129
        sta             TXTUNF
130
        lda             ENDMEM>>2       ;       get address of end of memory
131
        sub             #4096   ;       reserve 4K for the stack
132
        sta             STKBOT
133
        sub             #16384 ;   1000 vars
134
        sta     VARBGN
135
        jsr     clearVars   ; clear the variable area
136 18 robfinch
        stz             IRQROUT
137 16 robfinch
        lda     VARBGN   ; calculate number of bytes free
138
        ldy             TXTUNF
139
        sub     r1,r1,r3
140
        ldx             #12             ; max 12 digits
141
        jsr     PRTNUM
142
        lda             #msgBytesFree
143
        jsr             PRMESG
144
WSTART:
145
        stz             LOPVAR   ; initialize internal variables
146
        stz             STKGOS
147
        stz             CURRNT  ;       current line number pointer = 0
148
        ldx             ENDMEM>>2       ;       init S.P. again, just in case
149
        txs
150
        lda             #msgReady       ;       display "Ready"
151
        jsr             PRMESG
152
ST3:
153
        lda             #'>'            ; Prompt with a '>' and
154
        jsr             GETLN           ; read a line.
155
        jsr             TOUPBUF         ; convert to upper case
156
        ld              r12,r8          ; save pointer to end of line
157
        ld              r8,#BUFFER      ; point to the beginning of line
158
        jsr             TSTNUM          ; is there a number there?
159
        jsr             IGNBLK          ; skip trailing blanks
160
; does line no. exist? (or nonzero?)
161
        cpx             #0
162
        beq             DIRECT          ; if not, it's a direct statement
163
        cmp             #$FFFF          ; see if line no. is <= 16 bits
164
        bcc             ST2
165
        beq             ST2
166
        lda             #msgLineRange   ; if not, we've overflowed
167
        jmp             ERROR
168
ST2:
169
    ; ugliness - store a character at potentially an
170
    ; odd address (unaligned).
171
    tax                                 ; r2 = line number
172
        dec             r8
173
    stx         (r8)            ;
174
        jsr             FNDLN           ; find this line in save area
175
        ld              r13,r9          ; save possible line pointer
176
        cmp             #0
177
        beq             ST4                     ; if not found, insert
178
        ; here we found the line, so we're replacing the line
179
        ; in the text area
180
        ; first step - delete the line
181
        lda             #0
182
        jsr             FNDNXT          ; find the next line (into r9)
183
        cmp             #0
184
        bne             ST7
185
        cmp             r9,TXTUNF
186
        beq             ST6                     ; no more lines
187
        bcs             ST6
188
        cmp             r9,r0
189
        beq             ST6
190
ST7:
191
        ld              r1,r9           ; r1 = pointer to next line
192
        ld              r2,r13          ; pointer to line to be deleted
193
        ldy             TXTUNF          ; points to top of save area
194 26 robfinch
        sub             r1,r3,r9        ; r1 = length to move TXTUNF-pointer to next line
195
;       dea                                     ; count is one less
196
        ld              r2,r9           ; r2 = pointer to next line
197
        ld              r3,r13          ; r3 = pointer to line to delete
198
        push    r4
199
ST8:
200
        ld              r4,(x)
201
        st              r4,(y)
202
        inx
203
        iny
204
        dea
205
        bne             ST8
206
        pop             r4
207
;       mvn
208
;       jsr             MVUP            ; move up to delete
209
        sty             TXTUNF          ; update the end pointer
210 16 robfinch
        ; we moved the lines of text after the line being
211
        ; deleted down, so the pointer to the next line
212
        ; needs to be reset
213
        ld              r9,r13
214
        bra             ST4
215
        ; here there were no more lines, so just move the
216
        ; end of text pointer down
217
ST6:
218
        st              r13,TXTUNF
219
        ld              r9,r13
220
ST4:
221
        ; here we're inserting because the line wasn't found
222
        ; or it was deleted     from the text area
223 18 robfinch
        sub             r1,r12,r8               ; calculate the length of new line
224 16 robfinch
        cmp             #2                              ; is it just a line no. & CR? if so, it was just a delete
225
        beq             ST3
226
        bcc             ST3
227
 
228 18 robfinch
        ; compute new end of text
229
        ld              r10,TXTUNF              ; r10 = old TXTUNF
230
        add             r11,r10,r1              ; r11 = new top of TXTUNF (r1=line length)
231 16 robfinch
 
232
        cmp             r11,VARBGN      ; see if there's enough room
233
        bcc             ST5
234
        lda             #msgTooBig      ; if not, say so
235
        jmp             ERROR
236
 
237
        ; open a space in the text area
238
ST5:
239
        st              r11,TXTUNF      ; if so, store new end position
240
        ld              r1,r10          ; points to old end of text
241
        ld              r2,r11          ; points to new end of text
242
        ld              r3,r9       ; points to start of line after insert line
243
        jsr             MVDOWN          ; move things out of the way
244
 
245
        ; copy line into text space
246
        ld              r1,r8           ; set up to do the insertion; move from buffer
247
        ld              r2,r13          ; to vacated space
248
        ld              r3,r12          ; until end of buffer
249
        jsr             MVUP            ; do it
250
        jmp             ST3                     ; go back and get another line
251
 
252
;******************************************************************
253
;
254
; *** Tables *** DIRECT *** EXEC ***
255
;
256
; This section of the code tests a string against a table. When
257
; a match is found, control is transferred to the section of
258
; code according to the table.
259
;
260
; At 'EXEC', r8 should point to the string, r9 should point to
261
; the character table, and r10 should point to the execution
262
; table. At 'DIRECT', r8 should point to the string, r9 and
263
; r10 will be set up to point to TAB1 and TAB1_1, which are
264
; the tables of all direct and statement commands.
265
;
266
; A '.' in the string will terminate the test and the partial
267
; match will be considered as a match, e.g. 'P.', 'PR.','PRI.',
268
; 'PRIN.', or 'PRINT' will all match 'PRINT'.
269
;
270
; There are two tables: the character table and the execution
271
; table. The character table consists of any number of text items.
272
; Each item is a string of characters with the last character's
273
; high bit set to one. The execution table holds a 32-bit
274
; execution addresses that correspond to each entry in the
275
; character table.
276
;
277
; The end of the character table is a 0 byte which corresponds
278
; to the default routine in the execution table, which is
279
; executed if none of the other table items are matched.
280
;
281
; Character-matching tables:
282 26 robfinch
message "TAB1"
283 16 robfinch
TAB1:
284
        db      "LIS",'T'+0x80        ; Direct commands
285
        db      "LOA",'D'+0x80
286
        db      "NE",'W'+0x80
287
        db      "RU",'N'+0x80
288
        db      "SAV",'E'+0x80
289
TAB2:
290
        db      "NEX",'T'+0x80         ; Direct / statement
291
        db      "LE",'T'+0x80
292
        db      "I",'F'+0x80
293
        db      "GOT",'O'+0x80
294
        db      "GOSU",'B'+0x80
295
        db      "RETUR",'N'+0x80
296
        db      "RE",'M'+0x80
297
        db      "FO",'R'+0x80
298
        db      "INPU",'T'+0x80
299
        db      "PRIN",'T'+0x80
300
        db      "POK",'E'+0x80
301
        db      "STO",'P'+0x80
302
        db      "BY",'E'+0x80
303
        db      "SY",'S'+0x80
304
        db      "CL",'S'+0x80
305
    db  "CL",'R'+0x80
306
    db  "RDC",'F'+0x80
307 18 robfinch
    db  "ONIR",'Q'+0x80
308
    db  "WAI",'T'+0x80
309 16 robfinch
        db      0
310
TAB4:
311
        db      "PEE",'K'+0x80         ;Functions
312
        db      "RN",'D'+0x80
313
        db      "AB",'S'+0x80
314 18 robfinch
        db  "SG",'N'+0x80
315 16 robfinch
        db      "TIC",'K'+0x80
316
        db      "SIZ",'E'+0x80
317
        db  "US",'R'+0x80
318
        db      0
319
TAB5:
320
        db      "T",'O'+0x80           ;"TO" in "FOR"
321
        db      0
322
TAB6:
323
        db      "STE",'P'+0x80         ;"STEP" in "FOR"
324
        db      0
325
TAB8:
326
        db      '>','='+0x80           ;Relational operators
327
        db      '<','>'+0x80
328
        db      '>'+0x80
329
        db      '='+0x80
330
        db      '<','='+0x80
331
        db      '<'+0x80
332
        db      0
333
TAB9:
334
    db  "AN",'D'+0x80
335
    db  0
336
TAB10:
337
    db  "O",'R'+0x80
338
    db  0
339
 
340
;* Execution address tables:
341
; We save some bytes by specifiying only the low order 16 bits of the address
342
;
343
TAB1_1:
344
        dh      LISTX                   ;Direct commands
345
        dh      LOAD
346
        dh      NEW
347
        dh      RUN
348
        dh      SAVE
349
TAB2_1:
350
        dh      NEXT            ;       Direct / statement
351
        dh      LET
352
        dh      IF
353
        dh      GOTO
354
        dh      GOSUB
355
        dh      RETURN
356
        dh      IF2                     ; REM
357
        dh      FOR
358
        dh      INPUT
359
        dh      PRINT
360
        dh      POKE
361
        dh      STOP
362
        dh      GOBYE
363
        dh      SYSX
364
        dh      _cls
365
        dh  _clr
366
        dh      _rdcf
367 18 robfinch
        dh  ONIRQ
368
        dh      WAITIRQ
369 16 robfinch
        dh      DEFLT
370
TAB4_1:
371
        dh      PEEK                    ;Functions
372
        dh      RND
373
        dh      ABS
374 18 robfinch
        dh  SGN
375 16 robfinch
        dh      TICKX
376
        dh      SIZEX
377
        dh  USRX
378
        dh      XP40
379
TAB5_1
380
        dh      FR1                     ;"TO" in "FOR"
381
        dh      QWHAT
382
TAB6_1
383
        dh      FR2                     ;"STEP" in "FOR"
384
        dh      FR3
385
TAB8_1
386
        dh      XP11    ;>=             Relational operators
387
        dh      XP12    ;<>
388
        dh      XP13    ;>
389
        dh      XP15    ;=
390
        dh      XP14    ;<=
391
        dh      XP16    ;<
392
        dh      XP17
393
TAB9_1
394
    dh  XP_AND
395
    dh  XP_ANDX
396
TAB10_1
397
    dh  XP_OR
398
    dh  XP_ORX
399
 
400
;*
401
; r3 = match flag (trashed)
402
; r9 = text table
403
; r10 = exec table
404
; r11 = trashed
405 26 robfinch
message "DIRECT"
406 16 robfinch
DIRECT:
407
        ld              r9,#TAB1
408
        ld              r10,#TAB1_1
409
EXEC:
410
        jsr             IGNBLK          ; ignore leading blanks
411 18 robfinch
        ld              r11,r8          ; save the pointer
412 16 robfinch
        eor             r3,r3,r3        ; clear match flag
413
EXLP:
414
        lda             (r8)            ; get the program character
415
        inc             r8
416
        lb              r2,$0,r9        ; get the table character
417
        bne             EXNGO           ; If end of table,
418 18 robfinch
        ld              r8,r11          ;       restore the text pointer and...
419 16 robfinch
        bra             EXGO            ;   execute the default.
420
EXNGO:
421
        cmp             r1,r3           ; Else check for period... if so, execute
422
        beq             EXGO
423
        and             r2,r2,#0x7f     ; ignore the table's high bit
424
        cmp             r2,r1           ;               is there a match?
425
        beq             EXMAT
426
        inc             r10                     ;if not, try the next entry
427
        inc             r10
428 18 robfinch
        ld              r8,r11          ; reset the program pointer
429 16 robfinch
        eor             r3,r3,r3        ; sorry, no match
430
EX1:
431
        lb              r1,0,r9         ; get to the end of the entry
432
        inc             r9
433
        bit             #$80            ; test for bit 7 set
434
        beq             EX1
435
        bra             EXLP            ; back for more matching
436
EXMAT:
437
        ldy             #'.'            ; we've got a match so far
438
        lb              r1,0,r9         ; end of table entry?
439
        inc             r9
440
        bit             #$80            ; test for bit 7 set
441
        beq             EXLP            ; if not, go back for more
442
EXGO:
443
        ; execute the appropriate routine
444 18 robfinch
        lb              r1,1,r10        ; get the low mid order byte
445 26 robfinch
        asl             r1,r1,#8
446 18 robfinch
        orb             r1,r1,0,r10     ; get the low order byte
447
        or              r1,r1,#$FFFF0000        ; add in ROM base
448
        jmp             (r1)
449 16 robfinch
 
450
 
451
;******************************************************************
452
;
453
; What follows is the code to execute direct and statement
454
; commands. Control is transferred to these points via the command
455
; table lookup code of 'DIRECT' and 'EXEC' in the last section.
456
; After the command is executed, control is transferred to other
457
; sections as follows:
458
;
459
; For 'LISTX', 'NEW', and 'STOP': go back to the warm start point.
460
; For 'RUN': go execute the first stored line if any; else go
461
; back to the warm start point.
462
; For 'GOTO' and 'GOSUB': go execute the target line.
463
; For 'RETURN' and 'NEXT'; go back to saved return line.
464
; For all others: if 'CURRNT' is 0, go to warm start; else go
465
; execute next command. (This is done in 'FINISH'.)
466
;
467
;******************************************************************
468
;
469
; *** NEW *** STOP *** RUN (& friends) *** GOTO ***
470
;
471
; 'NEW' sets TXTUNF to point to TXTBGN
472
;
473
 
474
NEW:
475
        jsr             ENDCHK
476
        lda             TXTBGN>>2
477
        sta             TXTUNF  ;       set the end pointer
478
        jsr     clearVars
479
 
480
; 'STOP' goes back to WSTART
481
;
482
STOP:
483
        jsr             ENDCHK
484
        jmp             WSTART          ; WSTART will reset the stack
485
 
486
; 'RUN' finds the first stored line, stores its address
487
; in CURRNT, and starts executing it. Note that only those
488
; commands in TAB2 are legal for a stored program.
489
;
490
; There are 3 more entries in 'RUN':
491
; 'RUNNXL' finds next line, stores it's address and executes it.
492
; 'RUNTSL' stores the address of this line and executes it.
493
; 'RUNSML' continues the execution on same line.
494
;
495
RUN:
496
        jsr             ENDCHK
497
        ld              r8,TXTBGN>>2    ;       set pointer to beginning
498
        st              r8,CURRNT
499
        jsr     clearVars
500
 
501
RUNNXL                                  ; RUN 
502
        lda             CURRNT  ; executing a program?
503
        beq             WSTART  ; if not, we've finished a direct stat.
504 18 robfinch
        lda             IRQROUT         ; are we handling IRQ's ?
505
        beq             RUN1
506
        ld              r0,IRQFlag              ; was there an IRQ ?
507
        beq             RUN1
508
        stz             IRQFlag
509
        jsr             PUSHA           ; the same code as a GOSUB
510
        push    r8
511
        lda             CURRNT
512
        pha                                     ; found it, save old 'CURRNT'...
513
        lda             STKGOS
514
        pha                                     ; and 'STKGOS'
515
        stz             LOPVAR          ; load new values
516
        tsx
517
        stx             STKGOS
518
        ld              r9,IRQROUT
519
        bra             RUNTSL
520
RUN1
521 16 robfinch
        lda             #0          ; else find the next line number
522
        ld              r9,r8
523
        jsr             FNDLNP          ; search for the next line
524 18 robfinch
;       cmp             #0
525
;       bne             RUNTSL
526 16 robfinch
        cmp             r9,TXTUNF; if we've fallen off the end, stop
527
        beq             WSTART
528
        bcs             WSTART
529
 
530
RUNTSL                                  ; RUN 
531
        st              r9,CURRNT       ; set CURRNT to point to the line no.
532
        add             r8,r9,#1        ; set the text pointer to
533
 
534
RUNSML                 ; RUN 
535
        jsr             CHKIO           ; see if a control-C was pressed
536
        ld              r9,#TAB2                ; find command in TAB2
537
        ld              r10,#TAB2_1
538
        jmp             EXEC            ; and execute it
539
 
540
 
541
; 'GOTO expr' evaluates the expression, finds the target
542
; line, and jumps to 'RUNTSL' to do it.
543
;
544
GOTO
545 18 robfinch
        lda             #'G'
546
        jsr             DisplayChar
547 16 robfinch
        jsr             OREXPR          ;evaluate the following expression
548 18 robfinch
        jsr             DisplayWord
549 16 robfinch
        ld      r5,r1
550
        jsr     ENDCHK          ;must find end of line
551
        ld      r1,r5
552
        jsr     FNDLN           ; find the target line
553
        cmp             #0
554
        bne             RUNTSL          ; go do it
555
        lda             #msgBadGotoGosub
556
        jmp             ERROR           ; no such line no.
557
 
558
_clr:
559
    jsr     clearVars
560
    jmp     FINISH
561
 
562
; Clear the variable area of memory
563
clearVars:
564
        push    r6
565
    ld      r6,#2048    ; number of words to clear
566
    lda     VARBGN
567
cv1:
568
    stz     (r1)
569
    ina
570
    dec         r6
571
    bne         cv1
572
    pop         r6
573
    rts
574
 
575 18 robfinch
;******************************************************************
576
; ONIRQ 
577
; ONIRQ sets up an interrupt handler which acts like a specialized
578
; subroutine call. ONIRQ is coded like a GOTO that never executes.
579
;******************************************************************
580
;
581
ONIRQ:
582
        jsr             OREXPR          ;evaluate the following expression
583
        ld      r5,r1
584
        jsr     ENDCHK          ;must find end of line
585
        ld      r1,r5
586
        jsr     FNDLN           ; find the target line
587
        cmp             #0
588
        bne             ONIRQ1
589
        stz             IRQROUT
590
        jmp             FINISH
591
ONIRQ1:
592
        st              r9,IRQROUT
593
        jmp             FINISH
594 16 robfinch
 
595 18 robfinch
 
596
WAITIRQ:
597
        jsr             CHKIO           ; see if a control-C was pressed
598
        ld              r0,IRQFlag
599
        beq             WAITIRQ
600
        jmp             FINISH
601
 
602
 
603 16 robfinch
;******************************************************************
604
; LIST
605
;
606
; LISTX has two forms:
607
; 'LIST' lists all saved lines
608
; 'LIST #' starts listing at the line #
609
; Control-S pauses the listing, control-C stops it.
610
;******************************************************************
611
;
612
LISTX:
613
        jsr             TSTNUM          ; see if there's a line no.
614
        ld      r5,r1
615
        jsr             ENDCHK          ; if not, we get a zero
616
        ld      r1,r5
617
        jsr             FNDLN           ; find this or next line
618
LS1:
619
        cmp             #0
620
        bne             LS4
621
        cmp             r9,TXTUNF
622
        beq             WSTART
623
        bcs             WSTART          ; warm start if we passed the end
624
LS4:
625
        ld              r1,r9
626
        jsr             PRTLN           ; print the line
627
        ld              r9,r1           ; set pointer for next
628
        jsr             CHKIO           ; check for listing halt request
629
        cmp             #0
630
        beq             LS3
631
        cmp             #CTRLS          ; pause the listing?
632
        bne             LS3
633
LS2:
634
        jsr     CHKIO           ; if so, wait for another keypress
635
        cmp             #0
636
        beq             LS2
637
LS3:
638
        lda             #0
639
        jsr             FNDLNP          ; find the next line
640
        bra             LS1
641
 
642
 
643
;******************************************************************
644
; PRINT command is 'PRINT ....:' or 'PRINT ....'
645
; where '....' is a list of expressions, formats, back-arrows,
646
; and strings.  These items a separated by commas.
647
;
648
; A format is a pound sign followed by a number.  It controls
649
; the number of spaces the value of an expression is going to
650
; be printed in.  It stays effective for the rest of the print
651
; command unless changed by another format.  If no format is
652
; specified, 11 positions will be used.
653
;
654
; A string is quoted in a pair of single- or double-quotes.
655
;
656
; An underline (back-arrow) means generate a  without a 
657
;
658
; A  is generated after the entire list has been printed
659
; or if the list is empty.  If the list ends with a semicolon,
660
; however, no  is generated.
661
;******************************************************************
662
;
663
PRINT:
664
        ld              r5,#11          ; D4 = number of print spaces
665
        ldy             #':'
666
        ld              r4,#PR2
667
        jsr             TSTC            ; if null list and ":"
668
        jsr             CRLF            ; give CR-LF and continue
669
        jmp             RUNSML          ;               execution on the same line
670
PR2:
671
        ldy             #CR
672
        ld              r4,#PR0
673
        jsr             TSTC            ;if null list and 
674
        jsr             CRLF            ;also give CR-LF and
675
        jmp             RUNNXL          ;execute the next line
676
PR0:
677
        ldy             #'#'
678
        ld              r4,#PR1
679
        jsr             TSTC            ;else is it a format?
680
        jsr             OREXPR          ; yes, evaluate expression
681 18 robfinch
        ld              r5,r1   ; and save it as print width
682 16 robfinch
        bra             PR3             ; look for more to print
683
PR1:
684
        ldy             #'$'
685
        ld              r4,#PR4
686
        jsr             TSTC    ;       is character expression? (MRL)
687
        jsr             OREXPR  ;       yep. Evaluate expression (MRL)
688
        jsr             GOOUT   ;       print low byte (MRL)
689
        bra             PR3             ;look for more. (MRL)
690
PR4:
691
        jsr             QTSTG   ;       is it a string?
692
        ; the following branch must occupy only two bytes!
693
        bra             PR8             ;       if not, must be an expression
694
PR3:
695
        ldy             #','
696
        ld              r4,#PR6
697
        jsr             TSTC    ;       if ",", go find next
698
        jsr             FIN             ;in the list.
699
        bra             PR0
700
PR6:
701
        jsr             CRLF            ;list ends here
702
        jmp             FINISH
703
PR8:
704
        jsr             OREXPR          ; evaluate the expression
705
        ld              r2,r5           ; set the width
706
        jsr             PRTNUM          ; print its value
707
        bra             PR3                     ; more to print?
708
 
709
FINISH:
710
        jsr             FIN             ; Check end of command
711
        jmp             QWHAT   ; print "What?" if wrong
712
 
713
 
714
;*******************************************************************
715
;
716
; *** GOSUB *** & RETURN ***
717
;
718
; 'GOSUB expr:' or 'GOSUB expr' is like the 'GOTO' command,
719
; except that the current text pointer, stack pointer, etc. are
720
; saved so that execution can be continued after the subroutine
721
; 'RETURN's.  In order that 'GOSUB' can be nested (and even
722
; recursive), the save area must be stacked.  The stack pointer
723
; is saved in 'STKGOS'.  The old 'STKGOS' is saved on the stack.
724
; If we are in the main routine, 'STKGOS' is zero (this was done
725
; in the initialization section of the interpreter), but we still
726
; save it as a flag for no further 'RETURN's.
727
;******************************************************************
728
;
729
GOSUB:
730
        jsr             PUSHA           ; save the current 'FOR' parameters
731
        jsr             OREXPR          ; get line number
732
        jsr             FNDLN           ; find the target line
733
        cmp             #0
734
        bne             gosub1
735
        lda             #msgBadGotoGosub
736
        jmp             ERROR           ; if not there, say "How?"
737
gosub1:
738
        push    r8
739
        lda             CURRNT
740
        pha                                     ; found it, save old 'CURRNT'...
741
        lda             STKGOS
742
        pha                                     ; and 'STKGOS'
743
        stz             LOPVAR          ; load new values
744
        tsx
745
        stx             STKGOS
746
        jmp             RUNTSL
747
 
748
 
749
;******************************************************************
750
; 'RETURN' undoes everything that 'GOSUB' did, and thus
751
; returns the execution to the command after the most recent
752
; 'GOSUB'.  If 'STKGOS' is zero, it indicates that we never had
753
; a 'GOSUB' and is thus an error.
754
;******************************************************************
755
;
756
RETURN:
757
        jsr             ENDCHK          ; there should be just a 
758
        ldx             STKGOS          ; get old stack pointer
759
        bne             return1
760
        lda             #msgRetWoGosub
761
        jmp             ERROR           ; if zero, it doesn't exist
762
return1:
763
        txs                                     ; else restore it
764
        pla
765
        sta             STKGOS          ; and the old 'STKGOS'
766
        pla
767
        sta             CURRNT          ; and the old 'CURRNT'
768
        pop             r8                      ; and the old text pointer
769
        jsr             POPA            ;and the old 'FOR' parameters
770
        jmp             FINISH          ;and we are back home
771
 
772
;******************************************************************
773
; *** FOR *** & NEXT ***
774
;
775
; 'FOR' has two forms:
776
; 'FOR var=exp1 TO exp2 STEP exp1' and 'FOR var=exp1 TO exp2'
777
; The second form means the same thing as the first form with a
778
; STEP of positive 1.  The interpreter will find the variable 'var'
779
; and set its value to the current value of 'exp1'.  It also
780
; evaluates 'exp2' and 'exp1' and saves all these together with
781
; the text pointer, etc. in the 'FOR' save area, which consists of
782
; 'LOPVAR', 'LOPINC', 'LOPLMT', 'LOPLN', and 'LOPPT'.  If there is
783
; already something in the save area (indicated by a non-zero
784
; 'LOPVAR'), then the old save area is saved on the stack before
785
; the new values are stored.  The interpreter will then dig in the
786
; stack and find out if this same variable was used in another
787
; currently active 'FOR' loop.  If that is the case, then the old
788
; 'FOR' loop is deactivated. (i.e. purged from the stack)
789
;******************************************************************
790
;
791
FOR:
792
        jsr             PUSHA           ; save the old 'FOR' save area
793
        jsr             SETVAL          ; set the control variable
794
        sta             LOPVAR          ; save its address
795
        ld              r9,#TAB5
796
        ld              r10,#TAB5_1     ; use 'EXEC' to test for 'TO'
797
        jmp             EXEC
798
FR1:
799
        jsr             OREXPR          ; evaluate the limit
800
        sta             LOPLMT  ; save that
801
        ld              r9,#TAB6
802
        ld              r10,#TAB6_1     ; use 'EXEC' to test for the word 'STEP
803
        jmp             EXEC
804
FR2:
805
        jsr             OREXPR          ; found it, get the step value
806
        bra             FR4
807
FR3:
808
        lda             #1              ; not found, step defaults to 1
809
FR4:
810
        sta             LOPINC  ; save that too
811
FR5:
812
        ldx             CURRNT
813
        stx             LOPLN   ; save address of current line number
814
        st              r8,LOPPT        ; and text pointer
815
        tsx
816
        txy                                     ; dig into the stack to find 'LOPVAR'
817
        ld              r6,LOPVAR
818
        bra             FR7
819
FR6:
820
        add             r3,r3,#5        ; look at next stack frame
821
FR7:
822
        ldx             (y)                     ; is it zero?
823
        beq             FR8                     ; if so, we're done
824
        cmp             r2,r6
825
        bne             FR6                     ; same as current LOPVAR? nope, look some more
826
 
827
    tya                       ; Else remove 5 long words from...
828
        add             r2,r3,#5   ; inside the stack.
829
        tsx
830
        txy
831
        jsr             MVDOWN
832
        pla                                     ; set the SP 5 long words up
833
        pla
834
        pla
835
        pla
836
        pla
837
FR8:
838
    jmp     FINISH              ; and continue execution
839
 
840
 
841
;******************************************************************
842
; 'NEXT var' serves as the logical (not necessarily physical) end
843
; of the 'FOR' loop.  The control variable 'var' is checked with
844
; the 'LOPVAR'.  If they are not the same, the interpreter digs in
845
; the stack to find the right one and purges all those that didn't
846
; match.  Either way, it then adds the 'STEP' to that variable and
847
; checks the result with against the limit value.  If it is within
848
; the limit, control loops back to the command following the
849
; 'FOR'.  If it's outside the limit, the save area is purged and
850
; execution continues.
851
;******************************************************************
852
;
853
NEXT:
854
        lda             #0              ; don't allocate it
855
        jsr             TSTV            ; get address of variable
856
        cmp             #0
857
        bne             NX4
858
        lda             #msgNextVar
859
        bra             ERROR           ; if no variable, say "What?"
860
NX4:
861
        ld              r9,r1   ; save variable's address
862
NX0:
863
        lda             LOPVAR  ; If 'LOPVAR' is zero, we never...
864
        bne             NX5             ; had a FOR loop
865
        lda             #msgNextFor
866
        bra             ERROR
867
NX5:
868
        cmp             r1,r9
869
        beq             NX2             ; else we check them OK, they agree
870
        jsr             POPA            ; nope, let's see the next frame
871
        bra             NX0
872
NX2:
873
        lda             (r9)            ; get control variable's value
874
        ldx             LOPINC
875
        add             r1,r1,r2        ; add in loop increment
876
;       BVS.L   QHOW            say "How?" for 32-bit overflow
877
        sta             (r9)            ; save control variable's new value
878
        ldy             LOPLMT          ; get loop's limit value
879
        cmp             r2,#1
880
        beq             NX1
881
        bpl             NX1                     ; check loop increment, branch if loop increment is positive
882
        cmp             r1,r3
883
        beq             NX3
884
        bmi             NXPurge         ; test against limit
885
        bra     NX3
886
NX1:
887
        cmp             r1,r3
888
        beq             NX3
889
        bpl             NXPurge
890
NX3:
891
        ld              r8,LOPLN        ; Within limit, go back to the...
892
        st              r8,CURRNT
893
        ld              r8,LOPPT        ; saved 'CURRNT' and text pointer.
894
        jmp             FINISH
895
NXPurge:
896
    jsr    POPA        ; purge this loop
897
    jmp     FINISH
898
 
899
 
900
;******************************************************************
901
; *** REM *** IF *** INPUT *** LET (& DEFLT) ***
902
;
903
; 'REM' can be followed by anything and is ignored by the
904
; interpreter.
905
;
906
;REM
907
;    br     IF2             ; skip the rest of the line
908
; 'IF' is followed by an expression, as a condition and one or
909
; more commands (including other 'IF's) separated by colons.
910
; Note that the word 'THEN' is not used.  The interpreter evaluates
911
; the expression.  If it is non-zero, execution continues.  If it
912
; is zero, the commands that follow are ignored and execution
913
; continues on the next line.
914
;******************************************************************
915
;
916
IF:
917
    jsr         OREXPR          ; evaluate the expression
918
IF1:
919
        cmp             #0
920
    bne     RUNSML              ; is it zero? if not, continue
921
IF2:
922 18 robfinch
    ld          r9,r8   ; set lookup pointer
923 16 robfinch
        lda             #0              ; find line #0 (impossible)
924
        jsr             FNDSKP          ; if so, skip the rest of the line
925
        cmp             #0
926
        bcs             WSTART  ; if no next line, do a warm start
927
IF3:
928
        jmp             RUNTSL          ; run the next line
929
 
930
 
931
;******************************************************************
932
; INPUT is called first and establishes a stack frame
933
INPERR:
934
        ldx             STKINP          ; restore the old stack pointer
935
        txs
936
        pla
937
        sta             CURRNT          ; and old 'CURRNT'
938
        pop             r8                      ; and old text pointer
939
        tsx
940
        add             r2,r2,#5        ; fall through will subtract 5
941
        txs
942
 
943
; 'INPUT' is like the 'PRINT' command, and is followed by a list
944
; of items.  If the item is a string in single or double quotes,
945
; or is an underline (back arrow), it has the same effect as in
946
; 'PRINT'.  If an item is a variable, this variable name is
947
; printed out followed by a colon, then the interpreter waits for
948
; an expression to be typed in.  The variable is then set to the
949
; value of this expression.  If the variable is preceeded by a
950
; string (again in single or double quotes), the string will be
951
; displayed followed by a colon.  The interpreter the waits for an
952
; expression to be entered and sets the variable equal to the
953
; expression's value.  If the input expression is invalid, the
954
; interpreter will print "What?", "How?", or "Sorry" and reprint
955
; the prompt and redo the input.  The execution will not terminate
956
; unless you press control-C.  This is handled in 'INPERR'.
957
;
958
INPUT:
959
        push    r7
960
        tsr             sp,r7
961
        sub             r7,r7,#5        ; allocate five words on stack
962
        trs             r7,sp
963
        st              r5,4,r7         ; save off r5 into stack var
964
IP6:
965
        st              r8,(r7)         ; save in case of error
966
        jsr             QTSTG           ; is next item a string?
967
        bra             IP2                     ; nope - this branch must take only two bytes
968
        lda             #1              ; allocate var
969
        jsr             TSTV            ; yes, but is it followed by a variable?
970
        cmp             #0
971
        beq     IP4   ; if not, brnch
972
        or              r10,r1,r0               ; put away the variable's address
973
        bra             IP3                     ; if so, input to variable
974
IP2:
975
        st              r8,1,r7         ; save off in stack var for 'PRTSTG'
976
        lda             #1
977
        jsr             TSTV            ; must be a variable now
978
        cmp             #0
979
        bne             IP7
980
        lda             #msgInputVar
981
        add             r7,r7,#5        ; cleanup stack
982
        trs             r7,sp
983
        pop             r7                      ; so we can get back r7
984
        bra             ERROR           ; "What?" it isn't?
985
IP7:
986
        or              r10,r1,r0       ; put away the variable's address
987
        ld              r5,(r8)         ; get ready for 'PRTSTG' by null terminating
988
        stz             (r8)
989
        lda             1,r7                    ; get back text pointer
990
        jsr             PRTSTG          ; print string as prompt
991
        st              r5,(r8)         ; un-null terminate
992
IP3
993
        st              r8,1,r7         ; save in case of error
994
        lda             CURRNT
995
        sta             2,r7                    ; also save 'CURRNT'
996
        lda             #-1
997
        sta             CURRNT          ; flag that we are in INPUT
998
        stx             STKINP          ; save the stack pointer too
999
        st              r10,3,r7        ; save the variable address
1000
        lda             #':'            ; print a colon first
1001
        jsr             GETLN           ; then get an input line
1002
        ld              r8,#BUFFER      ; point to the buffer
1003
        jsr             OREXPR          ; evaluate the input
1004
        ld              r10,3,r7        ; restore the variable address
1005
        sta             (r10)           ; save value in variable
1006
        lda             2,r7            ; restore old 'CURRNT'
1007
        sta             CURRNT
1008
        ld              r8,1,r7         ; and the old text pointer
1009
IP4:
1010
        ldy             #','
1011
        ld              r4,#IP5         ; is the next thing a comma?
1012
        jsr             TSTC
1013
        bra             IP6                     ; yes, more items
1014
IP5:
1015
        ld              r5,4,r7
1016
        add             r7,r7,#5        ; cleanup stack
1017
        trs             r7,sp
1018
        pop             r7
1019
        jmp             FINISH
1020
 
1021
 
1022
DEFLT:
1023
    lda     (r8)
1024
    cmp         #CR
1025
        beq         FINISH          ; empty line is OK else it is 'LET'
1026
 
1027
 
1028
;******************************************************************
1029
; 'LET' is followed by a list of items separated by commas.
1030
; Each item consists of a variable, an equals sign, and an
1031
; expression.  The interpreter evaluates the expression and sets
1032
; the variable to that value.  The interpreter will also handle
1033
; 'LET' commands without the word 'LET'.  This is done by 'DEFLT'.
1034
;******************************************************************
1035
;
1036
LET:
1037
    jsr         SETVAL          ; do the assignment
1038
    ldy         #','
1039
    ld          r4,#FINISH
1040
        jsr             TSTC            ; check for more 'LET' items
1041
        bra         LET
1042
LT1:
1043
    jmp     FINISH              ; until we are finished.
1044
 
1045
 
1046
;******************************************************************
1047
; *** LOAD *** & SAVE ***
1048
;
1049
; These two commands transfer a program to/from an auxiliary
1050
; device such as a cassette, another computer, etc.  The program
1051
; is converted to an easily-stored format: each line starts with
1052
; a colon, the line no. as 4 hex digits, and the rest of the line.
1053
; At the end, a line starting with an '@' sign is sent.  This
1054
; format can be read back with a minimum of processing time by
1055
; the RTF65002
1056
;******************************************************************
1057
;
1058
LOAD
1059
        ld              r8,TXTBGN>>2    ; set pointer to start of prog. area
1060
        lda             #CR                     ; For a CP/M host, tell it we're ready...
1061
        jsr             GOAUXO          ; by sending a CR to finish PIP command.
1062
LOD1:
1063
        jsr             GOAUXI          ; look for start of line
1064
        cmp             #0
1065
        beq             LOD1
1066
        bcc             LOD1
1067
        cmp             #'@'            ; end of program?
1068
        beq             LODEND
1069
        cmp             #$1A
1070
        beq     LODEND  ; or EOF marker
1071
        cmp             #':'
1072
        bne             LOD1    ; if not, is it start of line? if not, wait for it
1073
        jsr             GCHAR           ; get line number
1074
        sta             (r8)            ; store it
1075 18 robfinch
        inc             r8
1076 16 robfinch
LOD2:
1077
        jsr             GOAUXI          ; get another text char.
1078
        cmp             #0
1079
        beq             LOD2
1080
        bcc             LOD2
1081
        sta             (r8)
1082 18 robfinch
        inc             r8                      ; store it
1083 16 robfinch
        cmp             #CR
1084
        bne             LOD2            ; is it the end of the line? if not, go back for more
1085
        bra             LOD1            ; if so, start a new line
1086
LODEND:
1087
        st              r8,TXTUNF       ; set end-of program pointer
1088
        jmp             WSTART          ; back to direct mode
1089
 
1090
 
1091
; get character from input (16 bit value)
1092
GCHAR:
1093
        push    r5
1094
        push    r6
1095
        ld              r6,#3       ; repeat four times
1096
        ld              r5,#0
1097
GCHAR1:
1098
        jsr             GOAUXI          ; get a char
1099
        cmp             #0
1100
        beq             GCHAR1
1101
        bcc             GCHAR1
1102
        jsr             asciiToHex
1103
        asl             r5,r5
1104
        asl             r5,r5
1105
        asl             r5,r5
1106
        asl             r5,r5
1107
        or              r5,r5,r1
1108 18 robfinch
        dec             r6
1109 16 robfinch
        bne             GCHAR1
1110 18 robfinch
        ld              r1,r5
1111 16 robfinch
        pop             r6
1112
        pop             r5
1113
        rts
1114
 
1115
 
1116
; convert an ascii char to hex code
1117
; input
1118
;       r1 = char to convert
1119
 
1120
asciiToHex:
1121
        cmp             #'9'            ; less than '9'
1122
        beq             a2h1
1123
        bcc             a2h1
1124
        sub             #7                      ; shift 'A' to '9'+1
1125
a2h1:
1126
        sub             #'0'
1127
        and             #15                     ; make sure a nybble
1128
        rts
1129
 
1130
 
1131
 
1132
SAVE:
1133
        ld              r8,TXTBGN>>2    ;set pointer to start of prog. area
1134
        ld              r9,TXTUNF       ;set pointer to end of prog. area
1135
SAVE1:
1136
        jsr             AUXOCRLF    ; send out a CR & LF (CP/M likes this)
1137
        cmp             r8,r9
1138
        bcs             SAVEND          ; are we finished?
1139
        lda             #':'            ; if not, start a line
1140
        jsr             GOAUXO
1141
        lda             (r8)            ; get line number
1142 18 robfinch
        inc             r8
1143 16 robfinch
        jsr             PWORD       ; output line number as 4-digit hex
1144
SAVE2:
1145
        lda             (r8)            ; get a text char.
1146 18 robfinch
        inc             r8
1147 16 robfinch
        cmp             #CR
1148
        beq             SAVE1           ; is it the end of the line? if so, send CR & LF and start new line
1149
        jsr             GOAUXO          ; send it out
1150
        bra             SAVE2           ; go back for more text
1151
SAVEND:
1152
        lda             #'@'            ; send end-of-program indicator
1153
        jsr             GOAUXO
1154
        jsr             AUXOCRLF    ; followed by a CR & LF
1155
        lda             #$1A            ; and a control-Z to end the CP/M file
1156
        jsr             GOAUXO
1157
        bra             WSTART          ; then go do a warm start
1158
 
1159
 
1160
; output a CR LF sequence to auxillary output
1161
; Registers Affected
1162
;   r3 = LF
1163
AUXOCRLF:
1164
    lda         #CR
1165
    jsr         GOAUXO
1166
    lda         #LF
1167
    jsr         GOAUXO
1168
    rts
1169
 
1170
 
1171
; output a word in hex format
1172
; tricky because of the need to reverse the order of the chars
1173
PWORD:
1174
        push    r5
1175
        ld              r5,#NUMWKA+15
1176
        or              r4,r1,r0        ; r4 = value
1177
pword1:
1178
    or      r1,r4,r0    ; r1 = value
1179
    lsr         r4,r4           ; shift over to next nybble
1180
    lsr         r4,r4
1181
    lsr         r4,r4
1182
    lsr         r4,r4
1183
    jsr         toAsciiHex  ; convert LS nybble to ascii hex
1184
    sta     (r5)                ; save in work area
1185
    sub         r5,r5,#1
1186
    cmp         r5,#NUMWKA
1187
    beq         pword1
1188
    bcs         pword1
1189
pword2:
1190
    add         r5,r5,#1
1191
    lda    (r5)     ; get char to output
1192
        jsr             GOAUXO          ; send it
1193
        cmp             r5,#NUMWKA+15
1194
        bcc             pword2
1195
        pop             r5
1196
        rts
1197
 
1198
 
1199
; convert nybble in r2 to ascii hex char2
1200
; r2 = character to convert
1201
 
1202
toAsciiHex:
1203
        and             #15     ; make sure it's a nybble
1204
        cmp             #10     ; > 10 ?
1205
        bcc             tah1
1206
        add             #7      ; bump it up to the letter 'A'
1207
tah1:
1208
        add             #'0'    ; bump up to ascii '0'
1209
        rts
1210
 
1211
 
1212
 
1213
;******************************************************************
1214 18 robfinch
; *** POKE ***
1215 16 robfinch
;
1216 18 robfinch
; 'POKE expr1,expr2' stores the word from 'expr2' into the memory
1217 16 robfinch
; address specified by 'expr1'.
1218
;******************************************************************
1219
;
1220
POKE:
1221
        jsr             OREXPR          ; get the memory address
1222
        ldy             #','
1223
        ld              r4,#PKER        ; it must be followed by a comma
1224
        jsr             TSTC            ; it must be followed by a comma
1225
        pha                                     ; save the address
1226
        jsr             OREXPR          ; get the byte to be POKE'd
1227
        plx                                 ; get the address back
1228
        sta             (x)                     ; store the byte in memory
1229
        jmp             FINISH
1230
PKER:
1231
        lda             #msgComma
1232
        jmp             ERROR           ; if no comma, say "What?"
1233
 
1234
 
1235 18 robfinch
;******************************************************************
1236
; 'SYSX expr' jumps to the machine language subroutine whose
1237
; starting address is specified by 'expr'.  The subroutine can use
1238
; all registers but must leave the stack the way it found it.
1239
; The subroutine returns to the interpreter by executing an RTS.
1240
;******************************************************************
1241 16 robfinch
 
1242
SYSX:
1243
        jsr             OREXPR          ; get the subroutine's address
1244
        cmp             #0
1245
        bne             sysx1           ; make sure we got a valid address
1246
        lda             #msgSYSBad
1247
        jmp             ERROR
1248
sysx1:
1249
        push    r8                      ; save the text pointer
1250
        jsr             (r1)            ; jump to the subroutine
1251
        pop             r8                  ; restore the text pointer
1252
        jmp             FINISH
1253
 
1254
;******************************************************************
1255
; *** EXPR ***
1256
;
1257
; 'EXPR' evaluates arithmetical or logical expressions.
1258
; ::=  OR  ...
1259
; ::= AND  ...
1260
; ::=
1261
;          
1262
; where  is one of the operators in TAB8 and the result
1263
; of these operations is 1 if true and 0 if false.
1264
; ::=(+ or -)(+ or -)(...
1265
; where () are optional and (... are optional repeats.
1266
; ::=( <* or /> )(...
1267
; ::=
1268
;           
1269
;           ()
1270
;  is recursive so that the variable '@' can have an 
1271
; as an index, functions can have an  as arguments, and
1272
;  can be an  in parenthesis.
1273
;
1274
 
1275
; ::= OR  ...
1276
;
1277
OREXPR:
1278
        jsr             ANDEXPR         ; get first 
1279
XP_OR1:
1280
        pha                                     ; save  value
1281
        ld              r9,#TAB10       ; look up a logical operator
1282
        ld              r10,#TAB10_1
1283
        jmp             EXEC            ; go do it
1284
XP_OR:
1285
    jsr         ANDEXPR
1286
    plx
1287
    or      r1,r1,r2
1288
    bra     XP_OR1
1289
XP_ORX:
1290
        pla
1291
    rts
1292
 
1293
 
1294
; ::= AND  ...
1295
;
1296
ANDEXPR:
1297
        jsr             EXPR            ; get first 
1298
XP_AND1:
1299
        pha                                     ; save  value
1300
        ld              r9,#TAB9                ; look up a logical operator
1301
        ld              r10,#TAB9_1
1302
        jmp             EXEC            ; go do it
1303
XP_AND:
1304
    jsr         EXPR
1305
    plx
1306
    and     r1,r1,r2
1307
    bra     XP_AND1
1308
XP_ANDX:
1309
        pla
1310
    rts
1311
 
1312
 
1313
; Determine if the character is a digit
1314
;   Parameters
1315
;       r1 = char to test
1316
;   Returns
1317
;       r1 = 1 if digit, otherwise 0
1318
;
1319
isDigit:
1320
        cmp             #'0'
1321
        bcc             isDigitFalse
1322
        cmp             #'9'+1
1323
        bcs             isDigitFalse
1324
        lda             #1
1325
    rts
1326
isDigitFalse:
1327
    lda         #0
1328
    rts
1329
 
1330
 
1331
; Determine if the character is a alphabetic
1332
;   Parameters
1333
;       r1 = char to test
1334
;   Returns
1335
;       r1 = 1 if alpha, otherwise 0
1336
;
1337
isAlpha:
1338
        cmp             #'A'
1339
        bcc             isAlphaFalse
1340
        cmp             #'Z'
1341
        beq             isAlphaTrue
1342
        bcc             isAlphaTrue
1343
        cmp             #'a'
1344
        bcc             isAlphaFalse
1345
        cmp             #'z'+1
1346
        bcs             isAlphaFalse
1347
isAlphaTrue:
1348
    lda         #1
1349
    rts
1350
isAlphaFalse:
1351
    lda         #0
1352
    rts
1353
 
1354
 
1355
; Determine if the character is a alphanumeric
1356
;   Parameters
1357
;       r1 = char to test
1358
;   Returns
1359
;       r1 = 1 if alpha, otherwise 0
1360
;
1361
isAlnum:
1362
    tax                                         ; save test char
1363
    jsr         isDigit
1364
    cmp         #0
1365
    bne         isDigitx                ; if it is a digit
1366
    txa                                         ; get back test char
1367
    jsr    isAlpha
1368
isDigitx:
1369
    rts
1370
 
1371
 
1372
EXPR:
1373
        jsr             EXPR2
1374
        pha                                     ; save  value
1375
        ld              r9,#TAB8                ; look up a relational operator
1376
        ld              r10,#TAB8_1
1377
        jmp             EXEC            ; go do it
1378
XP11:
1379
        pla
1380
        jsr             XP18    ; is it ">="?
1381
        cmp             r2,r1
1382
        bpl             XPRT1   ; no, return r2=1
1383
        bra             XPRT0   ; else return r2=0
1384
XP12:
1385
        pla
1386
        jsr             XP18    ; is it "<>"?
1387
        cmp             r2,r1
1388
        bne             XPRT1   ; no, return r2=1
1389
        bra             XPRT0   ; else return r2=0
1390
XP13:
1391
        pla
1392
        jsr             XP18    ; is it ">"?
1393
        cmp             r2,r1
1394
        beq             XPRT0
1395
        bpl             XPRT1   ; no, return r2=1
1396
        bra             XPRT0   ; else return r2=0
1397
XP14:
1398
        pla
1399
        jsr             XP18    ; is it "<="?
1400
        cmp             r2,r1
1401
        beq             XPRT1   ; no, return r2=1
1402
        bmi             XPRT1
1403
        bra             XPRT0   ; else return r2=0
1404
XP15:
1405
        pla
1406
        jsr             XP18    ; is it "="?
1407
        cmp             r2,r1
1408
        beq             XPRT1   ; if not, return r2=1
1409
        bra             XPRT0   ; else return r2=0
1410
XP16:
1411
        pla
1412
        jsr             XP18    ; is it "<"?
1413
        cmp             r2,r1
1414
        bmi             XPRT1   ; if not, return r2=1
1415
        bra             XPRT0   ; else return r2=0
1416
XPRT0:
1417
        lda             #0   ; return r1=0 (false)
1418
        rts
1419
XPRT1:
1420
        lda             #1      ; return r1=1 (true)
1421
        rts
1422
 
1423
XP17:                           ; it's not a rel. operator
1424
        pla                             ; return r2=
1425
        rts
1426
 
1427
XP18:
1428
        pha
1429
        jsr             EXPR2           ; do a second 
1430
        plx
1431
        rts
1432
 
1433
; ::=(+ or -)(+ or -)(...
1434 26 robfinch
message "EXPR2"
1435 16 robfinch
EXPR2:
1436
        ldy             #'-'
1437
        ld              r4,#XP21
1438
        jsr             TSTC            ; negative sign?
1439
        lda             #0              ; yes, fake '0-'
1440
        pha
1441
        bra             XP26
1442
XP21:
1443
        ldy             #'+'
1444
        ld              r4,#XP22
1445
        jsr             TSTC            ; positive sign? ignore it
1446
XP22:
1447
        jsr             EXPR3           ; first 
1448
XP23:
1449
        pha                                     ; yes, save the value
1450
        ldy             #'+'
1451
        ld              r4,#XP25
1452
        jsr             TSTC            ; add?
1453
        jsr             EXPR3           ; get the second 
1454
XP24:
1455
        plx
1456
        add             r1,r1,r2        ; add it to the first 
1457
;       BVS.L   QHOW            brnch if there's an overflow
1458
        bra             XP23            ; else go back for more operations
1459
XP25:
1460
        ldy             #'-'
1461
        ld              r4,#XP45
1462
        jsr             TSTC            ; subtract?
1463
XP26:
1464
        jsr             EXPR3           ; get second 
1465
        sub             r1,r0,r1        ; change its sign
1466
        bra             XP24            ; and do an addition
1467
XP45:
1468
        pla
1469
        rts
1470
 
1471
 
1472
; ::=( <* or /> )(...
1473
 
1474
EXPR3:
1475
        jsr     EXPR4           ; get first 
1476
XP31:
1477
        pha                             ; yes, save that first result
1478
        ldy             #'*'
1479
        ld              r4,#XP34
1480
        jsr             TSTC            ; multiply?
1481
        jsr             EXPR4           ; get second 
1482
        plx
1483
        muls    r1,r1,r2        ; multiply the two
1484
        bra             XP31        ; then look for more terms
1485
XP34:
1486
        ldy             #'/'
1487
        ld              r4,#XP47
1488
        jsr             TSTC            ; divide?
1489
        jsr             EXPR4           ; get second 
1490
        tax
1491
        pla
1492
        divs    r1,r1,r2        ; do the division
1493
        bra             XP31            ; go back for any more terms
1494
XP47:
1495
        pla
1496
        rts
1497
 
1498
 
1499
; Functions are jsred through EXPR4
1500
; ::=
1501
;           
1502
;           ()
1503
 
1504
EXPR4:
1505
    ld          r9,#TAB4                ; find possible function
1506
    ld          r10,#TAB4_1
1507
        jmp             EXEC        ; branch to function which does subsequent rts for EXPR4
1508
XP40:                   ; we get here if it wasn't a function
1509
        lda             #0
1510
        jsr             TSTV
1511
        cmp             #0
1512
        beq     XP41            ; nor a variable
1513
        lda             (r1)            ; if a variable, return its value in r1
1514
        rts
1515
XP41:
1516
        jsr             TSTNUM          ; or is it a number?
1517
        cmp             r2,#0
1518
        bne             XP46            ; (if not, # of digits will be zero) if so, return it in r1
1519
        jsr             PARN        ; check for (EXPR)
1520
XP46:
1521
        rts
1522
 
1523
 
1524
; Check for a parenthesized expression
1525
PARN:
1526
        ldy             #'('
1527
        ld              r4,#XP43
1528
        jsr             TSTC            ; else look for ( OREXPR )
1529
        jsr             OREXPR
1530
        ldy             #')'
1531
        ld              r4,#XP43
1532
        jsr             TSTC
1533
XP42:
1534
        rts
1535
XP43:
1536
        pla                             ; get rid of return address
1537
        lda             #msgWhat
1538
        jmp             ERROR
1539
 
1540
 
1541
; ===== Test for a valid variable name.  Returns Z=1 if not
1542
;       found, else returns Z=0 and the address of the
1543
;       variable in r1.
1544
; Parameters
1545
;       r1 = 1 = allocate if not found
1546
; Returns
1547
;       r1 = address of variable, zero if not found
1548
 
1549
TSTV:
1550
        push    r5
1551
        ld              r5,r1           ; r5=allocate flag
1552
        jsr             IGNBLK
1553
        lda             (r8)            ; look at the program text
1554
        cmp             #'@'
1555
        bcc             tstv_notfound   ; C=1: not a variable
1556
        bne             TV1                             ; brnch if not "@" array
1557
        inc             r8                      ; If it is, it should be
1558
        jsr             PARN            ; followed by (EXPR) as its index.
1559
;       BCS.L   QHOW            say "How?" if index is too big
1560
    pha                             ; save the index
1561
        jsr             SIZEX           ; get amount of free memory
1562
        plx                                 ; get back the index
1563
        cmp             r2,r1
1564
        bcc             TV2                     ; see if there's enough memory
1565
        jmp     QSORRY          ; if not, say "Sorry"
1566
TV2:
1567
        lda             VARBGN          ; put address of array element...
1568
        sub     r1,r1,r2       ; into r1 (neg. offset is used)
1569
        bra     TSTVRT
1570
TV1:
1571
    jsr         getVarName      ; get variable name
1572
    cmp         #0
1573
    beq     TSTVRT    ; if not, return r1=0
1574
    ld          r2,r5
1575
    jsr         findVar     ; find or allocate
1576
TSTVRT:
1577
        pop             r5
1578
        rts                                     ; r1<>0 (found)
1579
tstv_notfound:
1580
        pop             r5
1581
        lda             #0                      ; r1=0 if not found
1582
    rts
1583
 
1584
 
1585
; Returns
1586
;   r1 = 2 character variable name + type
1587
;
1588
getVarName:
1589
    push        r5
1590
 
1591
    lda     (r8)                ; get first character
1592
    pha                                 ; save off current name
1593
    jsr         isAlpha
1594
    cmp         #0
1595
    beq     gvn1
1596
    ld      r5,#2       ; loop two more times
1597
 
1598
        ; check for second/third character
1599
gvn4:
1600
        inc             r8
1601
        lda     (r8)            ; do we have another char ?
1602
        jsr             isAlnum
1603
        cmp             #0
1604
        beq     gvn2            ; nope
1605
        pla                                     ; get varname
1606
        asl
1607
        asl
1608
        asl
1609
        asl
1610
        asl
1611
        asl
1612
        asl
1613
        asl
1614
        ldx     (r8)
1615
        or      r1,r1,r2   ; add in new char
1616
    pha                            ; save off name again
1617
    dec         r5
1618
    bne         gvn4
1619
 
1620
    ; now ignore extra variable name characters
1621
gvn6:
1622
    inc         r8
1623
    lda    (r8)
1624
    jsr    isAlnum
1625
    cmp         #0
1626
    bne     gvn6        ; keep looping as long as we have identifier chars
1627
 
1628
    ; check for a variable type
1629
gvn2:
1630
        lda             (r8)
1631
        cmp             #'%'
1632
        beq             gvn3
1633
        cmp             #'$'
1634
        beq             gvn3
1635
        lda             #0
1636
    dec         r8
1637
 
1638
    ; insert variable type indicator and return
1639
gvn3:
1640
    inc         r8
1641
    plx
1642
    asl         r2,r2
1643
    asl         r2,r2
1644
    asl         r2,r2
1645
    asl         r2,r2
1646
    asl         r2,r2
1647
    asl         r2,r2
1648
    asl         r2,r2
1649
    asl         r2,r2
1650
    or      r1,r1,r2    ; add in variable type
1651
    pop         r5
1652
    rts                                 ; return Z = 0, r1 = varname
1653
 
1654
    ; not a variable name
1655
gvn1:
1656
        pla
1657
        pop             r5
1658
    lda         #0       ; return Z = 1 if not a varname
1659
    rts
1660
 
1661
 
1662
; Find variable
1663
;   r1 = varname
1664
;       r2 = allocate flag
1665
; Returns
1666
;   r1 = variable address, Z =0 if found / allocated, Z=1 if not found
1667
 
1668
findVar:
1669
        push    r7
1670
    ldy     VARBGN
1671
fv4:
1672
    ld      r7,(y)      ; get varname / type
1673
    beq     fv3                 ; no more vars ?
1674
    cmp         r1,r7
1675
    beq     fv1                 ; match ?
1676
    iny                                 ; move to next var
1677
    iny
1678
    ld      r7,STKBOT
1679
    cmp         r3,r7
1680
    bcc     fv4                 ; loop back to look at next var
1681
 
1682
    ; variable not found
1683
    ; no more memory
1684
    lda         #msgVarSpace
1685
    jmp     ERROR
1686
;    lw      lr,[sp]
1687
;    lw      r7,4[sp]
1688
;    add     sp,sp,#8
1689
;    lw      r1,#0
1690
;    rts
1691
 
1692
    ; variable not found
1693
    ; allocate new ?
1694
fv3:
1695
        cpx             #0
1696
        beq             fv2
1697
    sta     (r3)     ; save varname / type
1698
    ; found variable
1699
    ; return address
1700
fv1:
1701
    add         r1,r3,#1
1702
        pop             r7
1703
    rts                     ; Z = 0, r1 = address
1704
 
1705
    ; didn't find var and not allocating
1706
fv2:
1707
    pop         r7
1708
        lda             #0              ; Z = 1, r1 = 0
1709
    rts
1710
 
1711
 
1712
; ===== The PEEK function returns the byte stored at the address
1713
;       contained in the following expression.
1714
;
1715
PEEK:
1716
        jsr             PARN            ; get the memory address
1717
        lda             (r1)            ; get the addressed byte
1718
        rts
1719
 
1720
 
1721
; user function jsr
1722
; call the user function with argument in r1
1723
USRX:
1724
        jsr             PARN            ; get expression value
1725
        push    r8                      ; save the text pointer
1726 18 robfinch
        ldx             #0
1727
        jsr             (usrJmp,x)      ; get usr vector, jump to the subroutine
1728 16 robfinch
        pop             r8                      ; restore the text pointer
1729
        rts
1730
 
1731
 
1732
; ===== The RND function returns a random number from 1 to
1733
;       the value of the following expression in D0.
1734
;
1735
RND:
1736
        jsr             PARN            ; get the upper limit
1737
        cmp             #0
1738
        beq             rnd2            ; it must be positive and non-zero
1739
        bcc             rnd1
1740
        tax
1741
        ;gran                           ; generate a random number
1742
        ;mfspr  r1,rand         ; get the number
1743
        tsr             LFSR,r1
1744
;       jsr             modu4           ; RND(n)=MOD(number,n)+1
1745
        mod             r1,r1,r2
1746
        ina
1747
        rts
1748
rnd1:
1749
        lda             #msgRNDBad
1750
        jmp             ERROR
1751
rnd2:
1752
        tsr             LFSR,r1
1753
;       gran
1754
;       mfspr   r1,rand
1755
        rts
1756
 
1757
 
1758
; r = a mod b
1759
; a = r1
1760
; b = r2
1761
; r = r6
1762
;modu4:
1763
;       push    r3
1764
;       push    r5
1765
;       push    r6
1766
;       push    r7
1767
;       ld      r7,#31          ; n = 32
1768
;       eor             r5,r5,r5        ; w = 0
1769
;;      eor             r6,r6,r6        ; r = 0
1770
;mod2:
1771
;       rol                                     ; a <<= 1
1772
;       and             r3,r1,#1
1773
;       asl             r6                      ; r <<= 1
1774
;       or              r6,r6,r3
1775
;       and             #-2
1776
;       cmp             r2,r6
1777
;       bmi             mod1            ; b < r ?
1778
;       sub             r6,r6,r2        ; r -= b
1779
;mod1:
1780
;       dec             r7                      ; n--
1781
;       bne             mod2
1782
;       ld              r1,r6
1783
;       pop             r7
1784
;       pop             r6
1785
;       pop             r5
1786
;       pop             r3
1787
;       rts
1788
;
1789
 
1790
; ===== The ABS function returns an absolute value in r2.
1791
;
1792
ABS:
1793
        jsr             PARN            ; get the following expr.'s value
1794
        cmp             #0
1795
        bmi             ABS1
1796
        rts
1797
ABS1:
1798
        sub             r1,r0,r1
1799
        rts
1800
 
1801
;==== The TICK function returns the cpu tick value in r1.
1802
;
1803
TICKX:
1804
        tsr             TICK,r1
1805
        rts
1806
 
1807
; ===== The SGN function returns the sign in r1. +1,0, or -1
1808
;
1809
SGN:
1810
        jsr             PARN            ; get the following expr.'s value
1811
        cmp             #0
1812
        beq             SGN1
1813
        bmi             SGN2
1814
        lda             #1
1815
        rts
1816
SGN2:
1817
        lda             #-1
1818
        rts
1819
SGN1:
1820
        rts
1821
 
1822
; ===== The SIZE function returns the size of free memory in r1.
1823
;
1824
SIZEX:
1825
        lda             VARBGN          ; get the number of free bytes...
1826
        ldx             TXTUNF          ; between 'TXTUNF' and 'VARBGN'
1827
        sub             r1,r1,r2
1828
        rts                                     ; return the number in r1
1829
 
1830
 
1831
;******************************************************************
1832
;
1833
; *** SETVAL *** FIN *** ENDCHK *** ERROR (& friends) ***
1834
;
1835
; 'SETVAL' expects a variable, followed by an equal sign and then
1836
; an expression.  It evaluates the expression and sets the variable
1837
; to that value.
1838
;
1839
; returns
1840
; r2 = variable's address
1841
;
1842
SETVAL:
1843
    lda         #1              ; allocate var
1844
    jsr         TSTV            ; variable name?
1845
    cmp         #0
1846
    bne         sv2
1847
        lda             #msgVar
1848
        jmp             ERROR
1849
sv2:
1850
        pha                         ; save the variable's address
1851
        ldy             #'='
1852
        ld              r4,#SV1
1853
        jsr             TSTC            ; get past the "=" sign
1854
        jsr             OREXPR          ; evaluate the expression
1855
        plx                                 ; get back the variable's address
1856
        sta     (x)                 ; and save value in the variable
1857
        txa                                     ; return r1 = variable address
1858
        rts
1859
SV1:
1860
    jmp     QWHAT               ; if no "=" sign
1861
 
1862
 
1863 18 robfinch
; 'FIN' checks the end of a command.  If it ended with ":",
1864
; execution continues.  If it ended with a CR, it finds the
1865
; the next line and continues from there.
1866
;
1867 16 robfinch
FIN:
1868
        ldy             #':'
1869
        ld              r4,#FI1
1870
        jsr             TSTC            ; *** FIN ***
1871
        pla                                     ; if ":", discard return address
1872
        jmp             RUNSML          ; continue on the same line
1873
FI1:
1874
        ldy             #CR
1875
        ld              r4,#FI2
1876
        jsr             TSTC            ; not ":", is it a CR?
1877
                                                ; else return to the caller
1878
        pla                                     ; yes, purge return address
1879
        jmp             RUNNXL          ; execute the next line
1880
FI2:
1881
        rts                                     ; else return to the caller
1882
 
1883
 
1884 18 robfinch
; 'ENDCHK' checks if a command is ended with a CR. This is
1885
; required in certain commands, such as GOTO, RETURN, STOP, etc.
1886
;
1887 16 robfinch
; Check that there is nothing else on the line
1888
; Registers Affected
1889
;   r1
1890
;
1891
ENDCHK:
1892 18 robfinch
        lda             #'E'
1893
        jsr             DisplayChar
1894 16 robfinch
        jsr             IGNBLK
1895
        lda             (r8)
1896
        cmp             #CR
1897
        beq             ec1     ; does it end with a CR?
1898
        lda             #msgExtraChars
1899
        jmp             ERROR
1900
ec1:
1901
        rts
1902
 
1903 18 robfinch
; 'ERROR' prints the string pointed to by r1. It then prints the
1904
; line pointed to by CURRNT with a "?" inserted at where the
1905
; old text pointer (should be on top of the stack) points to.
1906
; Execution of Tiny BASIC is stopped and a warm start is done.
1907
; If CURRNT is zero (indicating a direct command), the direct
1908
; command is not printed. If CURRNT is -1 (indicating
1909
; 'INPUT' command in progress), the input line is not printed
1910
; and execution is not terminated but continues at 'INPERR'.
1911
;
1912
; Related to 'ERROR' are the following:
1913
; 'QWHAT' saves text pointer on stack and gets "What?" message.
1914
; 'AWHAT' just gets the "What?" message and jumps to 'ERROR'.
1915
; 'QSORRY' and 'ASORRY' do the same kind of thing.
1916
; 'QHOW' and 'AHOW' also do this for "How?".
1917
;
1918 16 robfinch
TOOBIG:
1919
        lda             #msgTooBig
1920
        bra             ERROR
1921
QSORRY:
1922
    lda         #SRYMSG
1923
        bra         ERROR
1924
QWHAT:
1925
        lda             #msgWhat
1926
ERROR:
1927
        jsr             PRMESG          ; display the error message
1928 18 robfinch
        lda             CURRNT          ; get the current line pointer
1929 16 robfinch
        beq             ERROR1          ; if zero, do a warm start
1930
        cmp             #-1
1931
        beq             INPERR          ; is the line no. pointer = -1? if so, redo input
1932
        ld              r5,(r8)         ; save the char. pointed to
1933
        stz             (r8)            ; put a zero where the error is
1934
        lda             CURRNT          ; point to start of current line
1935
        jsr             PRTLN           ; display the line in error up to the 0
1936 18 robfinch
        ld      r6,r1       ; save off end pointer
1937 16 robfinch
        st              r5,(r8)         ; restore the character
1938
        lda             #'?'            ; display a "?"
1939
        jsr             GOOUT
1940
        ldx             #0                      ; stop char = 0
1941
        sub             r1,r6,#1        ; point back to the error char.
1942
        jsr             PRTSTG          ; display the rest of the line
1943
ERROR1:
1944
        jmp         WSTART              ; and do a warm start
1945
 
1946
;******************************************************************
1947
;
1948
; *** GETLN *** FNDLN (& friends) ***
1949
;
1950
; 'GETLN' reads in input line into 'BUFFER'. It first prompts with
1951
; the character in r3 (given by the caller), then it fills the
1952
; buffer and echos. It ignores LF's but still echos
1953
; them back. Control-H is used to delete the last character
1954
; entered (if there is one), and control-X is used to delete the
1955
; whole line and start over again. CR signals the end of a line,
1956
; and causes 'GETLN' to return.
1957
;
1958
;
1959
GETLN:
1960
        push    r5
1961
        jsr             GOOUT           ; display the prompt
1962
        lda             #1
1963
        sta             CursorFlash     ; turn on cursor flash
1964
        lda             #' '            ; and a space
1965
        jsr             GOOUT
1966
        ld              r8,#BUFFER      ; r8 is the buffer pointer
1967
GL1:
1968
        jsr             CHKIO           ; check keyboard
1969
        cmp             #0
1970
        beq             GL1                     ; wait for a char. to come in
1971
        cmp             #CTRLH
1972
        beq             GL3                     ; delete last character? if so
1973
        cmp             #CTRLX
1974
        beq             GL4                     ; delete the whole line?
1975
        cmp             #CR
1976
        beq             GL2                     ; accept a CR
1977
        cmp             #' '
1978
        bcc             GL1                     ; if other control char., discard it
1979
GL2:
1980
        sta             (r8)            ; save the char.
1981
        inc             r8
1982
        pha
1983
        jsr             GOOUT           ; echo the char back out
1984
        pla                                     ; get char back (GOOUT destroys r1)
1985
        cmp             #CR
1986
        beq             GL7                     ; if it's a CR, end the line
1987
        cmp             r8,#BUFFER+BUFLEN-1     ; any more room?
1988
        bcc             GL1                     ; yes: get some more, else delete last char.
1989
GL3:
1990
        lda             #CTRLH  ; delete a char. if possible
1991
        jsr             GOOUT
1992
        lda             #' '
1993
        jsr             GOOUT
1994
        cmp             r8,#BUFFER      ; any char.'s left?
1995
        bcc             GL1                     ; if not
1996
        beq             GL1
1997
        lda             #CTRLH          ; if so, finish the BS-space-BS sequence
1998
        jsr             GOOUT
1999
        dec             r8                      ; decrement the text pointer
2000
        bra             GL1                     ; back for more
2001
GL4:
2002 18 robfinch
        ld              r1,r8           ; delete the whole line
2003 16 robfinch
        sub             r5,r1,#BUFFER   ; figure out how many backspaces we need
2004
        beq             GL6                             ; if none needed, brnch
2005
        dec             r5                      ; loop count is one less
2006
GL5:
2007
        lda             #CTRLH          ; and display BS-space-BS sequences
2008
        jsr             GOOUT
2009
        lda             #' '
2010
        jsr             GOOUT
2011
        lda             #CTRLH
2012
        jsr             GOOUT
2013
        dec             r5
2014
        bne             GL5
2015
GL6:
2016
        ld              r8,#BUFFER      ; reinitialize the text pointer
2017
        bra             GL1                     ; and go back for more
2018
GL7:
2019
        lda             #0              ; turn off cursor flash
2020
        stz             (r8)            ; null terminate line
2021
        stz             CursorFlash
2022
        lda             #LF             ; echo a LF for the CR
2023
        jsr             GOOUT
2024
        pop             r5
2025
        rts
2026
 
2027
 
2028
; 'FNDLN' finds a line with a given line no. (in r1) in the
2029
; text save area.  r9 is used as the text pointer. If the line
2030
; is found, r9 will point to the beginning of that line
2031
; (i.e. the high byte of the line no.), and r1 = 1.
2032
; If that line is not there and a line with a higher line no.
2033
; is found, r9 points there and r1 = 0. If we reached
2034
; the end of the text save area and cannot find the line, flags
2035
; r9 = 0, r1 = 0.
2036
; r1=1 if line found
2037
; r0 = 1        <= line is found
2038
;       r9 = pointer to line
2039
; r0 = 0    <= line is not found
2040
;       r9 = zero, if end of text area
2041
;       r9 = otherwise higher line number
2042
;
2043
; 'FNDLN' will initialize r9 to the beginning of the text save
2044
; area to start the search. Some other entries of this routine
2045
; will not initialize r9 and do the search.
2046
; 'FNDLNP' will start with r9 and search for the line no.
2047
; 'FNDNXT' will bump r9 by 2, find a CR and then start search.
2048
; 'FNDSKP' uses r9 to find a CR, and then starts the search.
2049
; return Z=1 if line is found, r9 = pointer to line
2050
;
2051
; Parameters
2052
;       r1 = line number to find
2053
;
2054
FNDLN:
2055
        cmp             #$FFFF
2056
        bcc             fl1     ; line no. must be < 65535
2057
        lda             #msgLineRange
2058
        jmp             ERROR
2059
fl1:
2060
        ld              r9,TXTBGN>>2    ; init. the text save pointer
2061
 
2062
FNDLNP:
2063
        cmp             r9,TXTUNF       ; check if we passed the end
2064
        beq             FNDRET1
2065
        bcs             FNDRET1         ; if so, return with r9=0,r1=0
2066
        ldx             (r9)            ; get line number
2067
        cmp             r1,r2
2068
        beq             FNDRET2
2069
        bcs             FNDNXT  ; is this the line we want? no, not there yet
2070
FNDRET:
2071
        lda             #0      ; line not found, but r9=next line pointer
2072
        rts                     ; return the cond. codes
2073
FNDRET1:
2074
;       eor             r9,r9,r9        ; no higher line
2075
        lda             #0      ; line not found
2076
        rts
2077
FNDRET2:
2078
        lda             #1              ; line found
2079
        rts
2080
 
2081
FNDNXT:
2082
        inc             r9      ; find the next line
2083
 
2084
FNDSKP:
2085
        ldx             (r9)
2086
        inc             r9
2087
        cpx             #CR
2088
        bne             FNDSKP          ; try to find a CR, keep looking
2089
        bra             FNDLNP          ; check if end of text
2090
 
2091
 
2092
;******************************************************************
2093
; 'MVUP' moves a block up from where r1 points to where r2 points
2094
; until r1=r3
2095
;
2096
MVUP1:
2097
        ld              r4,(r1)
2098
        st              r4,(r2)
2099
        ina
2100
        inx
2101
MVUP:
2102
        cmp             r1,r3
2103
        bne             MVUP1
2104
MVRET:
2105
        rts
2106
 
2107
 
2108
; 'MVDOWN' moves a block down from where r1 points to where r2
2109
; points until r1=r3
2110
;
2111
MVDOWN1:
2112
        dea
2113
        dex
2114
        ld              r4,(r1)
2115
        st              r4,(r2)
2116
MVDOWN:
2117
        cmp             r1,r3
2118
        bne             MVDOWN1
2119
        rts
2120
 
2121
 
2122
; 'POPA' restores the 'FOR' loop variable save area from the stack
2123
;
2124
; 'PUSHA' stacks for 'FOR' loop variable save area onto the stack
2125
;
2126
; Note: a single zero word is stored on the stack in the
2127
; case that no FOR loops need to be saved. This needs to be
2128
; done because PUSHA / POPA is called all the time.
2129 26 robfinch
message "POPA"
2130 16 robfinch
POPA:
2131
        ply
2132
        pla
2133
        sta             LOPVAR  ; restore LOPVAR, but zero means no more
2134
        beq             PP1
2135
        pla
2136
        sta             LOPINC
2137
        pla
2138
        sta             LOPLMT
2139
        pla
2140
        sta             LOPLN
2141
        pla
2142
        sta             LOPPT
2143
PP1:
2144
        jmp             (y)
2145
 
2146
 
2147
PUSHA:
2148
        ply
2149
        lda             STKBOT          ; Are we running out of stack room?
2150
        add             r1,r1,#5        ; we might need this many words
2151
        tsx
2152
        cmp             r2,r1
2153
        bcc             QSORRY          ; out of stack space
2154
        ldx             LOPVAR          ; save loop variables
2155
        beq             PU1                     ; if LOPVAR is zero, that's all
2156
        lda             LOPPT
2157
        pha
2158
        lda             LOPLN
2159
        pha
2160
        lda             LOPLMT
2161
        pha
2162
        lda             LOPINC
2163
        pha
2164
PU1:
2165
        phx
2166
        jmp             (y)
2167
 
2168
 
2169
 
2170
;******************************************************************
2171
;
2172
; 'PRTSTG' prints a string pointed to by r1. It stops printing
2173
; and returns to the caller when either a CR is printed or when
2174
; the next byte is the same as what was passed in r2 by the
2175
; caller.
2176
;
2177
; 'PRTLN' prints the saved text line pointed to by r3
2178
; with line no. and all.
2179
;
2180
 
2181
; r1 = pointer to string
2182
; r2 = stop character
2183
; return r1 = pointer to end of line + 1
2184
 
2185
PRTSTG:
2186
        push    r5
2187
        push    r6
2188
        push    r7
2189
    ld      r5,r1           ; r5 = pointer
2190
    ld      r6,r2           ; r6 = stop char
2191
PS1:
2192
    ld      r7,(r5)     ; get a text character
2193
    inc         r5
2194
    cmp         r7,r6
2195
        beq         PRTRET              ; same as stop character? if so, return
2196
        ld      r1,r7
2197
        jsr             GOOUT           ; display the char.
2198
        cmp             r7,#CR
2199
        bne     PS1                     ; is it a C.R.? no, go back for more
2200
        lda             #LF      ; yes, add a L.F.
2201
        jsr             GOOUT
2202
PRTRET:
2203
    ld      r2,r7           ; return r2 = stop char
2204
        ld              r1,r5           ; return r1 = line pointer
2205
        pop             r7
2206
        pop             r6
2207
        pop             r5
2208
    rts                                 ; then return
2209
 
2210
 
2211
; 'QTSTG' looks for an underline (back-arrow on some systems),
2212
; single-quote, or double-quote.  If none of these are found, returns
2213
; to the caller.  If underline, outputs a CR without a LF.  If single
2214
; or double quote, prints the quoted string and demands a matching
2215
; end quote.  After the printing, the next i-word of the caller is
2216
; skipped over (usually a branch instruction).
2217
;
2218
QTSTG:
2219
        ldy             #'"'
2220
        ld              r4,#QT3
2221
        jsr             TSTC            ; *** QTSTG ***
2222
        ldx             #'"'            ; it is a "
2223
QT1:
2224
        ld              r1,r8
2225
        jsr             PRTSTG          ; print until another
2226
        ld              r8,r1
2227
        cpx             #CR
2228
        bne             QT2                     ; was last one a CR?
2229
        jmp             RUNNXL          ; if so run next line
2230
QT3:
2231
        ldy             #''''
2232
        ld              r4,#QT4
2233
        jsr             TSTC            ; is it a single quote?
2234
        ldx             #''''   ; if so, do same as above
2235
        bra             QT1
2236
QT4:
2237
        ldy             #'_'
2238
        ld              r4,#QT5
2239
        jsr             TSTC            ; is it an underline?
2240
        lda             #CR             ; if so, output a CR without LF
2241
        jsr             GOOUT
2242
QT2:
2243
        pla                                     ; get return address
2244
        ina                                     ; add 2 to it in order to skip following branch
2245
        ina
2246
        jmp             (r1)            ; skip over next i-word when returning
2247
QT5:                                            ; not " ' or _
2248
        rts
2249
 
2250
; Output a CR LF sequence
2251
;
2252
prCRLF:
2253
        lda             #CR
2254
        jsr             GOOUT
2255
        lda             #LF
2256
        jsr             GOOUT
2257
        rts
2258
 
2259 26 robfinch
; 'PRTNUM' prints the 32 bit number in r1, leading blanks are added if
2260
; needed to pad the number of spaces to the number in r2.
2261 16 robfinch
; However, if the number of digits is larger than the no. in
2262 26 robfinch
; r2, all digits are printed anyway. Negative sign is also
2263 16 robfinch
; printed and counted in, positive sign is not.
2264
;
2265
; r1 = number to print
2266
; r2 = number of digits
2267
; Register Usage
2268
;       r5 = number of padding spaces
2269
public PRTNUM:
2270
        push    r3
2271
        push    r5
2272
        push    r6
2273
        push    r7
2274
        ld              r7,#NUMWKA      ; r7 = pointer to numeric work area
2275
        ld              r6,r1           ; save number for later
2276
        ld              r5,r2           ; r5 = min number of chars
2277
        cmp             #0
2278
        bpl             PN2                     ; is it negative? if not
2279
        sub             r1,r0,r1        ; else make it positive
2280
        dec             r5                      ; one less for width count
2281
PN2:
2282
        ld              r3,#10
2283
PN1:
2284
        mod             r2,r1,r3        ; r2 = r1 mod 10
2285
        div             r1,r1,r3        ; r1 /= 10 divide by 10
2286
        add             r2,r2,#'0'      ; convert remainder to ascii
2287
        stx             (r7)            ; and store in buffer
2288
        inc             r7
2289
        dec             r5                      ; decrement width
2290
        cmp             #0
2291
        bne             PN1
2292
PN6:
2293
        cmp             r5,r0
2294 26 robfinch
        bmi             PN4             ; test pad count, skip padding if not needed
2295 16 robfinch
        beq             PN4
2296
PN3:
2297
        lda             #' '            ; display the required leading spaces
2298
        jsr             GOOUT
2299
        dec             r5
2300
        bne             PN3
2301
PN4:
2302
        cmp             r6,r0
2303
        bpl             PN5                     ; is number negative?
2304
        lda             #'-'            ; if so, display the sign
2305
        jsr             GOOUT
2306
PN5:
2307
        dec             r7
2308
        lda             (r7)            ; now unstack the digits and display
2309
        jsr             GOOUT
2310
        cmp             r7,#NUMWKA
2311
        beq             PNRET
2312
        bcs             PN5
2313
PNRET:
2314
        pop             r7
2315
        pop             r6
2316
        pop             r5
2317
        pop             r3
2318
        rts
2319
 
2320
; r1 = number to print
2321
; r2 = number of digits
2322
public PRTHEXNUM:
2323
        push    r4
2324
        push    r5
2325
        push    r6
2326
        push    r7
2327
        push    r8
2328
        ld              r7,#NUMWKA      ; r7 = pointer to numeric work area
2329
        ld              r6,r1           ; save number for later
2330
;       setlo   r5,#20          ; r5 = min number of chars
2331
        ld              r5,r2
2332
        ld              r4,r1
2333
        cmp             r4,r0
2334
        bpl             PHN2            ; is it negative? if not
2335
        sub             r4,r0,r4        ; else make it positive
2336
        dec             r5                      ; one less for width count
2337
PHN2
2338
        ld              r8,#10          ; maximum of 10 digits
2339
PHN1:
2340
        ld              r1,r4
2341
        and             #15
2342
        cmp             #10
2343
        bcc             PHN7
2344
        add             #'A'-10
2345
        bra             PHN8
2346
PHN7:
2347
        add             #'0'            ; convert remainder to ascii
2348
PHN8:
2349
        sta             (r7)            ; and store in buffer
2350
        inc             r7
2351
        dec             r5                      ; decrement width
2352
        lsr             r4,r4
2353
        lsr             r4,r4
2354
        lsr             r4,r4
2355
        lsr             r4,r4
2356
        beq             PHN6                    ; is it zero yet ?
2357
        dec             r8
2358
        bne             PHN1
2359
PHN6:   ; test pad count
2360
        cmp             r5,r0
2361
        beq             PHN4
2362
        bcc             PHN4    ; skip padding if not needed
2363
PHN3:
2364
        lda             #' '            ; display the required leading spaces
2365
        jsr             GOOUT
2366
        dec             r5
2367
        bne             PHN3
2368
PHN4:
2369
        cmp             r6,r0
2370
        bcs             PHN5    ; is number negative?
2371
        lda             #'-'            ; if so, display the sign
2372
        jsr             GOOUT
2373
PHN5:
2374
        dec             r7
2375
        lda             (r7)            ; now unstack the digits and display
2376
        jsr             GOOUT
2377
        cmp             r7,#NUMWKA
2378
        beq             PHNRET
2379
        bcs             PHN5
2380
PHNRET:
2381
        pop             r8
2382
        pop             r7
2383
        pop             r6
2384
        pop             r5
2385
        pop             r4
2386
        rts
2387
 
2388
 
2389
; r1 = pointer to line
2390
; returns r1 = pointer to end of line + 1
2391
PRTLN:
2392
        push    r5
2393
    ld          r5,r1           ; r5 = pointer
2394
    lda         (r5)            ; get the binary line number
2395
    inc         r5
2396
    ldx         #12       ; display a 0 or more digit line no.
2397
        jsr             PRTNUM
2398
        lda             #' '     ; followed by a blank
2399
        jsr             GOOUT
2400
        ldx             #0       ; stop char. is a zero
2401
        ld              r1,r5
2402
        jsr     PRTSTG          ; display the rest of the line
2403
        pop             r5
2404
        rts
2405
 
2406
 
2407
; ===== Test text byte following the call to this subroutine. If it
2408
;       equals the byte pointed to by r8, return to the code following
2409
;       the call. If they are not equal, brnch to the point
2410
;       indicated in r4.
2411
;
2412
; Registers Affected
2413
;   r3,r8
2414
; Returns
2415
;       r8 = updated text pointer
2416
;
2417
TSTC
2418
        pha
2419
        jsr             IGNBLK          ; ignore leading blanks
2420
        lda             (r8)
2421
        cmp             r3,r1
2422
        beq             TC1                     ; is it = to what r8 points to? if so
2423
        pla
2424
        ply                                     ; increment stack pointer (get rid of return address)
2425
        jmp             (r4)            ; jump to the routine
2426
TC1:
2427
        inc             r8                      ; if equal, bump text pointer
2428
        pla
2429
        rts
2430
 
2431
; ===== See if the text pointed to by r8 is a number. If so,
2432
;       return the number in r2 and the number of digits in r3,
2433
;       else return zero in r2 and r3.
2434
; Registers Affected
2435
;   r1,r2,r3,r4
2436
; Returns
2437
;       r1 = number
2438
;       r2 = number of digits in number
2439
;       r8 = updated text pointer
2440
;
2441
TSTNUM:
2442
        phy
2443
        jsr             IGNBLK          ; skip over blanks
2444
        lda             #0              ; initialize return parameters
2445
        ldx             #0
2446
        ld              r15,#10
2447
TN1:
2448
        ldy             (r8)
2449
        cpy             #'0'            ; is it less than zero?
2450
        bcc             TSNMRET
2451
        cpy             #'9'+1          ; is it greater than nine?
2452
        bcs             TSNMRET
2453
        cmp             r1,#$7FFFFFF    ; see if there's room for new digit
2454
        bcc             TN2
2455
        beq             TN2
2456
        lda             #msgNumTooBig
2457
        jmp             ERROR           ; if not, we've overflowd
2458
TN2:
2459
        inc             r8                      ; adjust text pointer
2460
        mul             r1,r1,r15       ; quickly multiply result by 10
2461
        and             r3,r3,#$0F      ; add in the new digit
2462
        add             r1,r1,r3
2463
        inx                                     ; increment the no. of digits
2464
        bra             TN1
2465
TSNMRET:
2466
        ply
2467
        rts
2468
 
2469
 
2470
;===== Skip over blanks in the text pointed to by r8.
2471
;
2472
; Registers Affected:
2473
;       r8
2474
; Returns
2475
;       r8 = pointer updateded past any spaces or tabs
2476
;
2477
IGNBLK:
2478
        pha
2479
IGB2:
2480
        lda             (r8)                    ; get char
2481
        cmp             #' '
2482
        beq             IGB1    ; see if it's a space
2483
        cmp             #'\t'
2484
        bne             IGBRET  ; or a tab
2485
IGB1:
2486
        inc             r8              ; increment the text pointer
2487
        bra             IGB2
2488
IGBRET:
2489
        pla
2490
        rts
2491
 
2492
; ===== Convert the line of text in the input buffer to upper
2493
;       case (except for stuff between quotes).
2494
;
2495
; Registers Affected
2496
;   r1,r3
2497
; Returns
2498
;       r8 = pointing to end of text in buffer
2499
;
2500
TOUPBUF:
2501
        ld              r8,#BUFFER      ; set up text pointer
2502
        eor             r3,r3,r3        ; clear quote flag
2503
TOUPB1:
2504
        lda             (r8)            ; get the next text char.
2505
        inc             r8
2506
        cmp             #CR
2507
        beq             TOUPBRT         ; is it end of line?
2508
        cmp             #'"'
2509
        beq             DOQUO   ; a double quote?
2510
        cmp             #''''
2511
        beq             DOQUO   ; or a single quote?
2512
        cpy             #0
2513
        bne             TOUPB1  ; inside quotes?
2514
        jsr             toUpper         ; convert to upper case
2515
        sta             -1,r8   ; store it
2516
        bra             TOUPB1          ; and go back for more
2517
DOQUO:
2518
        cpy             #0
2519
        bne             DOQUO1; are we inside quotes?
2520
        tay                             ; if not, toggle inside-quotes flag
2521
        bra             TOUPB1
2522
DOQUO1:
2523
        cmp             r3,r1
2524
        bne             TOUPB1          ; make sure we're ending proper quote
2525
        eor             r3,r3,r3        ; else clear quote flag
2526
        bra             TOUPB1
2527
TOUPBRT:
2528
        rts
2529
 
2530
 
2531
; ===== Convert the character in r1 to upper case
2532
;
2533
toUpper
2534
        cmp             #'a'            ; is it < 'a'?
2535
        bcc             TOUPRET
2536
        cmp             #'z'+1          ; or > 'z'?
2537
        bcs             TOUPRET
2538
        sub             #32     ; if not, make it upper case
2539
TOUPRET
2540
        rts
2541
 
2542
 
2543
; 'CHKIO' checks the input. If there's no input, it will return
2544
; to the caller with the r1=0. If there is input, the input byte is in r1.
2545
; However, if a control-C is read, 'CHKIO' will warm-start BASIC and will
2546
; not return to the caller.
2547
;
2548 26 robfinch
message "CHKIO"
2549 16 robfinch
CHKIO:
2550
        jsr             GOIN            ; get input if possible
2551
        cmp             #0
2552
        beq             CHKRET2         ; if Zero, no input
2553
        cmp             #CTRLC
2554
        bne             CHKRET  ; is it control-C?
2555
        pla                                     ; dump return address
2556
        jmp             WSTART          ; if so, do a warm start
2557
CHKRET2:
2558
        lda             #0
2559
CHKRET:
2560
        rts
2561
 
2562
; ===== Display a CR-LF sequence
2563
;
2564
CRLF:
2565
        lda             #CLMSG
2566
 
2567
 
2568
; ===== Display a zero-ended string pointed to by register r1
2569
; Registers Affected
2570
;   r1,r2,r4
2571
;
2572
PRMESG:
2573
        push    r5
2574
        or      r5,r1,r0    ; r5 = pointer to message
2575
PRMESG1:
2576
        inc             r5
2577
        lb              r1,-1,r5                ;       get the char.
2578
        beq             PRMRET
2579
        jsr             GOOUT           ;else display it trashes r4
2580
        bra             PRMESG1
2581
PRMRET:
2582
        or              r1,r5,r0
2583
        pop             r5
2584
        rts
2585
 
2586
 
2587
; ===== Display a zero-ended string pointed to by register r1
2588
; Registers Affected
2589
;   r1,r2,r3
2590
;
2591
PRMESGAUX:
2592
        phy
2593
        tay                                     ; y = pointer
2594
PRMESGA1:
2595
        iny
2596
        lb              r1,-1,y         ;       get the char.
2597
        beq             PRMRETA
2598
        jsr             GOAUXO          ;else display it
2599
        bra             PRMESGA1
2600
PRMRETA:
2601
        tya
2602
        ply
2603
        rts
2604
 
2605
;*****************************************************
2606
; The following routines are the only ones that need *
2607
; to be changed for a different I/O environment.     *
2608
;*****************************************************
2609
 
2610
 
2611
; ===== Output character to the console (Port 1) from register r1
2612
;       (Preserves all registers.)
2613
;
2614
OUTC:
2615
        jmp             DisplayChar
2616
 
2617
 
2618
; ===== Input a character from the console into register R1 (or
2619
;       return Zero status if there's no character available).
2620
;
2621
INCH:
2622 26 robfinch
;       jsr             KeybdCheckForKeyDirect
2623
;       cmp             #0
2624
;       beq             INCH1
2625
        jsr             KeybdGetChar
2626
        cmp             #-1
2627 16 robfinch
        beq             INCH1
2628 26 robfinch
        rts
2629 16 robfinch
INCH1:
2630 26 robfinch
        ina             ; return a zero for no-char
2631 16 robfinch
        rts
2632
 
2633
;*
2634
;* ===== Input a character from the host into register r1 (or
2635
;*      return Zero status if there's no character available).
2636
;*
2637
AUXIN:
2638
        jsr             SerialGetChar
2639
        cmp             #-1
2640
        beq             AXIRET_ZERO
2641
        and             #$7F                            ;zero out the high bit
2642
AXIRET:
2643
        rts
2644
AXIRET_ZERO:
2645
        lda             #0
2646
        rts
2647
 
2648
; ===== Output character to the host (Port 2) from register r1
2649
;       (Preserves all registers.)
2650
;
2651
AUXOUT
2652
        jmp             SerialPutChar   ; call boot rom routine
2653
 
2654
 
2655
_cls
2656
        jsr             ClearScreen
2657 26 robfinch
        jsr             HomeCursor
2658 16 robfinch
        jmp             FINISH
2659
 
2660
_wait10
2661
        rts
2662
_getATAStatus
2663
        rts
2664
_waitCFNotBusy
2665
        rts
2666
_rdcf
2667
        jmp             FINISH
2668
rdcf6
2669
        bra             ERROR
2670
 
2671
 
2672
; ===== Return to the resident monitor, operating system, etc.
2673
;
2674
BYEBYE:
2675 26 robfinch
        jsr             ReleaseIOFocus
2676 16 robfinch
        ldx             OSSP
2677
        txs
2678
        rts
2679
 
2680
;       MOVE.B  #228,D7         return to Tutor
2681
;       TRAP    #14
2682
 
2683
msgInit db      CR,LF,"RTF65002 Tiny BASIC v1.0",CR,LF,"(C) 2013  Robert Finch",CR,LF,LF,0
2684
OKMSG   db      CR,LF,"OK",CR,LF,0
2685
msgWhat db      "What?",CR,LF,0
2686
SRYMSG  db      "Sorry."
2687
CLMSG   db      CR,LF,0
2688
msgReadError    db      "Compact FLASH read error",CR,LF,0
2689
msgNumTooBig    db      "Number is too big",CR,LF,0
2690
msgDivZero              db      "Division by zero",CR,LF,0
2691
msgVarSpace     db  "Out of variable space",CR,LF,0
2692
msgBytesFree    db      " words free",CR,LF,0
2693
msgReady                db      CR,LF,"Ready",CR,LF,0
2694
msgComma                db      "Expecting a comma",CR,LF,0
2695
msgLineRange    db      "Line number too big",CR,LF,0
2696
msgVar                  db      "Expecting a variable",CR,LF,0
2697
msgRNDBad               db      "RND bad parameter",CR,LF,0
2698
msgSYSBad               db      "SYS bad address",CR,LF,0
2699
msgInputVar             db      "INPUT expecting a variable",CR,LF,0
2700
msgNextFor              db      "NEXT without FOR",CR,LF,0
2701
msgNextVar              db      "NEXT expecting a defined variable",CR,LF,0
2702
msgBadGotoGosub db      "GOTO/GOSUB bad line number",CR,LF,0
2703
msgRetWoGosub   db      "RETURN without GOSUB",CR,LF,0
2704
msgTooBig               db      "Program is too big",CR,LF,0
2705
msgExtraChars   db      "Extra characters on line ignored",CR,LF,0
2706
 
2707
        align   4
2708
LSTROM  equ     *               ; end of possible ROM area
2709
;       END
2710
 
2711
;*
2712
;* ===== Return to the resident monitor, operating system, etc.
2713
;*
2714
;BYEBYE:
2715
;       jmp             Monitor
2716
;    MOVE.B     #228,D7         ;return to Tutor
2717
;       TRAP    #14
2718
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.